1 /* ADG - Automatic Drawing Generation
2 * Copyright (C) 2007,2008,2009,2010 Nicola Fontana <ntd at entidi.it>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
23 * @short_description: Root abstract class for all dimension entities
25 * The #AdgDim class is the base stub of all the dimension entities.
31 * All fields are private and should not be used directly.
32 * Use its public methods instead.
36 #include "adg-internal.h"
38 #include "adg-dim-private.h"
39 #include "adg-dim-style.h"
40 #include "adg-dress-builtins.h"
41 #include "adg-toy-text.h"
42 #include "adg-type-builtins.h"
44 #define PARENT_OBJECT_CLASS ((GObjectClass *) adg_dim_parent_class)
45 #define PARENT_ENTITY_CLASS ((AdgEntityClass *) adg_dim_parent_class)
63 static void dispose (GObject
*object
);
64 static void finalize (GObject
*object
);
65 static void get_property (GObject
*object
,
69 static void set_property (GObject
*object
,
73 static void global_changed (AdgEntity
*entity
);
74 static void local_changed (AdgEntity
*entity
);
75 static void invalidate (AdgEntity
*entity
);
76 static void arrange (AdgEntity
*entity
);
77 static gchar
* default_value (AdgDim
*dim
);
78 static gdouble
quote_angle (gdouble angle
);
79 static gboolean
set_dim_dress (AdgDim
*dim
,
81 static gboolean
set_ref1 (AdgDim
*dim
,
82 const AdgPoint
*ref1
);
83 static gboolean
set_ref2 (AdgDim
*dim
,
84 const AdgPoint
*ref2
);
85 static gboolean
set_pos (AdgDim
*dim
,
87 static gboolean
set_outside (AdgDim
*dim
,
88 AdgThreeState outside
);
89 static gboolean
set_detached (AdgDim
*dim
,
90 AdgThreeState detached
);
91 static gboolean
set_value (AdgDim
*dim
,
93 static gboolean
set_min (AdgDim
*dim
,
95 static gboolean
set_max (AdgDim
*dim
,
97 static gboolean
set_point (AdgPoint
**point
,
98 const AdgPoint
*new_point
);
101 G_DEFINE_ABSTRACT_TYPE(AdgDim
, adg_dim
, ADG_TYPE_ENTITY
);
105 adg_dim_class_init(AdgDimClass
*klass
)
107 GObjectClass
*gobject_class
;
108 AdgEntityClass
*entity_class
;
111 gobject_class
= (GObjectClass
*) klass
;
112 entity_class
= (AdgEntityClass
*) klass
;
114 g_type_class_add_private(klass
, sizeof(AdgDimPrivate
));
116 gobject_class
->dispose
= dispose
;
117 gobject_class
->finalize
= finalize
;
118 gobject_class
->get_property
= get_property
;
119 gobject_class
->set_property
= set_property
;
121 entity_class
->global_changed
= global_changed
;
122 entity_class
->local_changed
= local_changed
;
123 entity_class
->invalidate
= invalidate
;
124 entity_class
->arrange
= arrange
;
126 klass
->quote_angle
= quote_angle
;
127 klass
->default_value
= default_value
;
129 param
= adg_param_spec_dress("dim-dress",
130 P_("Dimension Dress"),
131 P_("The dress to use for rendering this dimension"),
134 g_object_class_install_property(gobject_class
, PROP_DIM_DRESS
, param
);
136 param
= g_param_spec_boxed("ref1",
138 P_("First reference point of the dimension"),
141 g_object_class_install_property(gobject_class
, PROP_REF1
, param
);
143 param
= g_param_spec_boxed("ref2",
145 P_("Second reference point of the dimension"),
148 g_object_class_install_property(gobject_class
, PROP_REF2
, param
);
150 param
= g_param_spec_boxed("pos",
152 P_("The reference position of the quote: it will be combined with \"level\" to get the real quote position"),
155 g_object_class_install_property(gobject_class
, PROP_POS
, param
);
157 param
= g_param_spec_double("level",
159 P_("The dimension level, that is the factor to multiply the baseline spacing (defined in the dimension style) to get the offset from pos where the quote should be rendered"),
160 -G_MAXDOUBLE
, G_MAXDOUBLE
, 1.0,
162 g_object_class_install_property(gobject_class
, PROP_LEVEL
, param
);
164 param
= g_param_spec_enum("outside",
166 P_("Whether the arrows must be inside the extension lines (ADG_THREE_STATE_OFF), must be extended outside the extension lines (ADG_THREE_STATE_ON) or should be automatically handled depending on the available space"),
167 ADG_TYPE_THREE_STATE
, ADG_THREE_STATE_UNKNOWN
,
169 g_object_class_install_property(gobject_class
, PROP_OUTSIDE
, param
);
171 param
= g_param_spec_enum("detached",
172 P_("Detached Quote"),
173 P_("Where the quote must be positioned: in the middle of the base line (ADG_THREE_STATE_OFF), near the pos point (ADG_THREE_STATE_ON) or should be automatically deducted depending on the available space"),
174 ADG_TYPE_THREE_STATE
, ADG_THREE_STATE_UNKNOWN
,
176 g_object_class_install_property(gobject_class
, PROP_DETACHED
, param
);
178 param
= g_param_spec_string("value",
180 P_("The theoretically exact value for this quote: set to NULL to automatically get the default value"),
183 g_object_class_install_property(gobject_class
, PROP_VALUE
, param
);
185 param
= g_param_spec_string("min",
186 P_("Minimum Value or Low Tolerance"),
187 P_("The minimum value allowed or the lowest tolerance from value (depending of the dimension style): set to NULL to suppress"),
190 g_object_class_install_property(gobject_class
, PROP_MIN
, param
);
192 param
= g_param_spec_string("max",
193 P_("Maximum Value or High Tolerance"),
194 P_("The maximum value allowed or the highest tolerance from value (depending of the dimension style): set to NULL to suppress"),
197 g_object_class_install_property(gobject_class
, PROP_MAX
, param
);
201 adg_dim_init(AdgDim
*dim
)
203 AdgDimPrivate
*data
= G_TYPE_INSTANCE_GET_PRIVATE(dim
, ADG_TYPE_DIM
,
206 data
->dim_dress
= ADG_DRESS_DIMENSION
;
211 data
->outside
= ADG_THREE_STATE_UNKNOWN
;
212 data
->detached
= ADG_THREE_STATE_UNKNOWN
;
221 dispose(GObject
*object
)
223 AdgDimPrivate
*data
= ((AdgDim
*) object
)->data
;
225 if (data
->quote
.entity
!= NULL
) {
226 g_object_unref(data
->quote
.entity
);
227 data
->quote
.entity
= NULL
;
229 if (data
->ref1
!= NULL
) {
230 adg_point_destroy(data
->ref1
);
233 if (data
->ref2
!= NULL
) {
234 adg_point_destroy(data
->ref2
);
237 if (data
->pos
!= NULL
) {
238 adg_point_destroy(data
->pos
);
242 if (PARENT_OBJECT_CLASS
->dispose
)
243 PARENT_OBJECT_CLASS
->dispose(object
);
247 finalize(GObject
*object
)
249 AdgDimPrivate
*data
= ((AdgDim
*) object
)->data
;
255 if (PARENT_OBJECT_CLASS
->finalize
)
256 PARENT_OBJECT_CLASS
->finalize(object
);
260 get_property(GObject
*object
, guint prop_id
, GValue
*value
, GParamSpec
*pspec
)
262 AdgDimPrivate
*data
= ((AdgDim
*) object
)->data
;
266 g_value_set_int(value
, data
->dim_dress
);
269 g_value_set_boxed(value
, data
->ref1
);
272 g_value_set_boxed(value
, data
->ref2
);
275 g_value_set_boxed(value
, data
->pos
);
278 g_value_set_double(value
, data
->level
);
281 g_value_set_enum(value
, data
->outside
);
284 g_value_set_enum(value
, data
->detached
);
287 g_value_set_string(value
, data
->value
);
290 g_value_set_string(value
, data
->min
);
293 g_value_set_string(value
, data
->max
);
296 G_OBJECT_WARN_INVALID_PROPERTY_ID(object
, prop_id
, pspec
);
302 set_property(GObject
*object
, guint prop_id
,
303 const GValue
*value
, GParamSpec
*pspec
)
308 dim
= (AdgDim
*) object
;
313 set_dim_dress(dim
, g_value_get_int(value
));
316 set_ref1(dim
, g_value_get_boxed(value
));
319 set_ref2(dim
, g_value_get_boxed(value
));
322 set_pos(dim
, g_value_get_boxed(value
));
325 data
->level
= g_value_get_double(value
);
328 set_outside(dim
, g_value_get_enum(value
));
331 set_detached(dim
, g_value_get_enum(value
));
334 set_value(dim
, g_value_get_string(value
));
337 set_min(dim
, g_value_get_string(value
));
340 set_max(dim
, g_value_get_string(value
));
343 G_OBJECT_WARN_INVALID_PROPERTY_ID(object
, prop_id
, pspec
);
350 * adg_dim_set_dim_dress:
352 * @dress: the new #AdgDress to use
354 * Sets a new dimension dress to @dim. The new dress must be
355 * related to the original dress for this property: you cannot
356 * set a dress used for line styles to a dress managing fonts.
358 * The check is done by calling adg_dress_are_related() with
359 * @dress and the previous dress as arguments. Check out its
360 * documentation for details on what is a related dress.
363 adg_dim_set_dim_dress(AdgDim
*dim
, AdgDress dress
)
365 g_return_if_fail(ADG_IS_DIM(dim
));
367 if (set_dim_dress(dim
, dress
))
368 g_object_notify((GObject
*) dim
, "dim-dress");
372 * adg_dim_get_dim_dress:
375 * Gets the dimension dress to be used in rendering @dim.
377 * Returns: the current dimension dress
380 adg_dim_get_dim_dress(AdgDim
*dim
)
384 g_return_val_if_fail(ADG_IS_DIM(dim
), ADG_DRESS_UNDEFINED
);
388 return data
->dim_dress
;
394 * @ref1: the new point to use as first reference
396 * Sets the #AdgDim:ref1 property to @ref1. The old point
397 * is silently discarded, unreferencing its model if that
398 * point was bound to a named pair (hence, possibly destroying
399 * the model if this was the last reference).
401 * @ref1 can be %NULL, in which case the point is unset.
404 adg_dim_set_ref1(AdgDim
*dim
, const AdgPoint
*ref1
)
406 g_return_if_fail(ADG_IS_DIM(dim
));
408 if (set_ref1(dim
, ref1
))
409 g_object_notify((GObject
*) dim
, "ref1");
413 * adg_dim_set_ref1_explicit:
415 * @x: x coordinate of the first reference point
416 * @y: y coordinate of the first reference point
418 * Sets the #AdgDim:ref1 property to the (@x, @y) explicit
419 * coordinates. The old point is silently discarded,
420 * unreferencing its model if that point was bound to a named
421 * pair (hence, possibly destroying the model if this was the
425 adg_dim_set_ref1_explicit(AdgDim
*dim
, gdouble x
, gdouble y
)
427 AdgPoint
*point
= adg_point_new();
429 adg_point_set_pair_explicit(point
, x
, y
);
430 adg_dim_set_ref1(dim
, point
);
432 adg_point_destroy(point
);
436 * adg_dim_set_ref1_from_pair:
438 * @ref1: the coordinates pair of the first reference point
440 * Convenient function to set the #AdgDim:ref1 property using a
441 * pair instead of explicit coordinates.
444 adg_dim_set_ref1_from_pair(AdgDim
*dim
, const AdgPair
*ref1
)
446 g_return_if_fail(ref1
!= NULL
);
448 adg_dim_set_ref1_explicit(dim
, ref1
->x
, ref1
->y
);
452 * adg_dim_set_ref1_from_model:
454 * @model: the source #AdgModel
455 * @ref1: a named pair in @model
457 * Binds #AdgDim:ref1 to the @ref1 named pair of @model. If @model
458 * is %NULL, the point will be unset. In any case, the old point
459 * is silently discarded, unreferencing its model if that point
460 * was bound to a named pair (hence, possibly destroying the model
461 * if this was the last reference).
463 * The assignment is lazy so @ref1 could be not be present in @model.
464 * Anyway, at the first access to this point an error will be raised
465 * if the named pair is still missing.
468 adg_dim_set_ref1_from_model(AdgDim
*dim
, AdgModel
*model
, const gchar
*ref1
)
470 AdgPoint
*point
= adg_point_new();
472 adg_point_set_pair_from_model(point
, model
, ref1
);
473 adg_dim_set_ref1(dim
, point
);
475 adg_point_destroy(point
);
482 * Gets the #AdgDim:ref1 point. The returned point is internally owned
483 * and must not be freed or modified. Anyway, it is not const because
484 * adg_point_get_pair() must be able to modify the internal cache of
485 * the returned point.
487 * Returns: the first reference point
490 adg_dim_get_ref1(AdgDim
*dim
)
494 g_return_val_if_fail(ADG_IS_DIM(dim
), NULL
);
504 * @ref2: the new point to use as second reference
506 * Sets the #AdgDim:ref2 property to @ref2. The old point
507 * is silently discarded, unreferencing its model if that
508 * point was bound to a named pair (hence, possibly destroying
509 * the model if it was the last reference).
511 * @ref2 can be %NULL, in which case the point is unset.
514 adg_dim_set_ref2(AdgDim
*dim
, const AdgPoint
*ref2
)
516 g_return_if_fail(ADG_IS_DIM(dim
));
518 if (set_ref2(dim
, ref2
))
519 g_object_notify((GObject
*) dim
, "ref2");
523 * adg_dim_set_ref2_explicit:
525 * @x: x coordinate of the second reference point
526 * @y: y coordinate of the second reference point
528 * Sets the #AdgDim:ref2 property to the (@x, @y) explicit
529 * coordinates. The old point is silently discarded,
530 * unreferencing its model if that point was bound to a named
531 * pair (hence, possibly destroying the model if this was the
535 adg_dim_set_ref2_explicit(AdgDim
*dim
, gdouble x
, gdouble y
)
537 AdgPoint
*point
= adg_point_new();
539 adg_point_set_pair_explicit(point
, x
, y
);
540 adg_dim_set_ref2(dim
, point
);
542 adg_point_destroy(point
);
546 * adg_dim_set_ref2_from_pair:
548 * @ref2: the coordinates pair of the second reference point
550 * Convenient function to set the #AdgDim:ref2 property using a
551 * pair instead of explicit coordinates.
554 adg_dim_set_ref2_from_pair(AdgDim
*dim
, const AdgPair
*ref2
)
556 g_return_if_fail(ref2
!= NULL
);
558 adg_dim_set_ref2_explicit(dim
, ref2
->x
, ref2
->y
);
562 * adg_dim_set_ref2_from_model:
564 * @model: the source #AdgModel
565 * @ref2: a named pair in @model
567 * Binds #AdgDim:ref2 to the @ref2 named pair of @model. If @model
568 * is %NULL, the point will be unset. In any case, the old point
569 * is silently discarded, unreferencing its model if that point
570 * was bound to a named pair (hence, possibly destroying the model
571 * if this was the last reference).
573 * The assignment is lazy so @ref2 could be not be present in @model.
574 * Anyway, at the first access to this point an error will be raised
575 * if the named pair is still missing.
578 adg_dim_set_ref2_from_model(AdgDim
*dim
, AdgModel
*model
, const gchar
*ref2
)
580 AdgPoint
*point
= adg_point_new();
582 adg_point_set_pair_from_model(point
, model
, ref2
);
583 adg_dim_set_ref2(dim
, point
);
585 adg_point_destroy(point
);
592 * Gets the #AdgDim:ref2 point. The returned point is internally owned
593 * and must not be freed or modified. Anyway, it is not const because
594 * adg_point_get_pair() must be able to modify the internal cache of
595 * the returned point.
597 * Returns: the second reference point
600 adg_dim_get_ref2(AdgDim
*dim
)
604 g_return_val_if_fail(ADG_IS_DIM(dim
), NULL
);
614 * @pos: the new point to use as position
616 * Sets the #AdgDim:pos property to @pos. The old point
617 * is silently discarded, unreferencing its model if that
618 * point was bound to a named pair (hence, possibly destroying
619 * the model if it was the last reference).
621 * @pos can be %NULL, in which case the point is unset.
624 adg_dim_set_pos(AdgDim
*dim
, const AdgPoint
*pos
)
626 g_return_if_fail(ADG_IS_DIM(dim
));
628 if (set_pos(dim
, pos
))
629 g_object_notify((GObject
*) dim
, "pos");
633 * adg_dim_set_pos_explicit:
635 * @x: x coordinate of the position
636 * @y: y coordinate of the position
638 * Sets the #AdgDim:pos property to the (@x, @y) explicit
639 * coordinates. The old point is silently discarded,
640 * unreferencing its model if that point was bound to a named
641 * pair (hence, possibly destroying the model if this was the
645 adg_dim_set_pos_explicit(AdgDim
*dim
, gdouble x
, gdouble y
)
647 AdgPoint
*point
= adg_point_new();
649 adg_point_set_pair_explicit(point
, x
, y
);
650 adg_dim_set_pos(dim
, point
);
652 adg_point_destroy(point
);
656 * adg_dim_set_pos_from_pair:
658 * @pos: the coordinates pair of the position point
660 * Convenient function to set the #AdgDim:pos property using a
661 * pair instead of explicit coordinates.
664 adg_dim_set_pos_from_pair(AdgDim
*dim
, const AdgPair
*pos
)
666 g_return_if_fail(pos
!= NULL
);
668 adg_dim_set_pos_explicit(dim
, pos
->x
, pos
->y
);
672 * adg_dim_set_pos_from_model:
674 * @model: the source #AdgModel
675 * @pos: a named pair in @model
677 * Binds #AdgDim:pos to the @pos named pair of @model. If @model
678 * is %NULL, the point will be unset. In any case, the old point
679 * is silently discarded, unreferencing its model if that point
680 * was bound to a named pair (hence, possibly destroying the model
681 * if this was the last reference).
683 * The assignment is lazy so @pos could be not be present in @model.
684 * Anyway, at the first access to this point an error will be raised
685 * if the named pair is still missing.
688 adg_dim_set_pos_from_model(AdgDim
*dim
, AdgModel
*model
, const gchar
*pos
)
690 AdgPoint
*point
= adg_point_new();
692 adg_point_set_pair_from_model(point
, model
, pos
);
693 adg_dim_set_pos(dim
, point
);
695 adg_point_destroy(point
);
702 * Gets the #AdgDim:pos point. The returned point is internally owned
703 * and must not be freed or modified. Anyway, it is not const because
704 * adg_point_get_pair() must be able to modify the internal cache of
705 * the returned point.
707 * Returns: the position point
710 adg_dim_get_pos(AdgDim
*dim
)
714 g_return_val_if_fail(ADG_IS_DIM(dim
), NULL
);
724 * @level: the new level
726 * Sets a new level for this dimension. The level is used to
727 * stack the quotes using a spacing value from dim_style
728 * (specified in global space).
731 adg_dim_set_level(AdgDim
*dim
, gdouble level
)
735 g_return_if_fail(ADG_IS_DIM(dim
));
740 g_object_notify((GObject
*) dim
, "level");
747 * Gets the level of this dimension.
749 * Returns: the level value
752 adg_dim_get_level(AdgDim
*dim
)
756 g_return_val_if_fail(ADG_IS_DIM(dim
), 0);
764 * adg_dim_set_outside:
766 * @outside: the new outside state
768 * Sets a new state for the #AdgDim:outside flag: check the property
769 * documentation for further details.
772 adg_dim_set_outside(AdgDim
*dim
, AdgThreeState outside
)
774 g_return_if_fail(ADG_IS_DIM(dim
));
776 if (set_outside(dim
, outside
))
777 g_object_notify((GObject
*) dim
, "outside");
781 * adg_dim_get_outside:
784 * Gets the state of the #AdgDim:outside property: check the property
785 * documentation for further details.
787 * Returns: the current flag state
790 adg_dim_get_outside(AdgDim
*dim
)
794 g_return_val_if_fail(ADG_IS_DIM(dim
), ADG_THREE_STATE_UNKNOWN
);
798 return data
->outside
;
802 * adg_dim_set_detached:
804 * @detached: the new detached state
806 * Sets a new state for the #AdgDim:detached flag: check the property
807 * documentation for further details.
809 * This is used only by dimensions where detaching has meaning.
810 * In some cases, such as with #AdgRDim dimensions, this property is
814 adg_dim_set_detached(AdgDim
*dim
, AdgThreeState detached
)
816 g_return_if_fail(ADG_IS_DIM(dim
));
818 if (set_detached(dim
, detached
))
819 g_object_notify((GObject
*) dim
, "detached");
823 * adg_dim_get_detached:
826 * Gets the state of the #AdgDim:detached property: check the property
827 * documentation for further details.
829 * Returns: the current flag state
832 adg_dim_get_detached(AdgDim
*dim
)
836 g_return_val_if_fail(ADG_IS_DIM(dim
), ADG_THREE_STATE_UNKNOWN
);
840 return data
->detached
;
846 * @value: the value text
848 * Explicitely sets the text to use as value. If @value is %NULL or
849 * was never set, an automatic text is calculated using the format
850 * specified in the current #AdgDimStyle and getting its value by
851 * calling the default_value() virtual method.
854 adg_dim_set_value(AdgDim
*dim
, const gchar
*value
)
856 g_return_if_fail(ADG_IS_DIM(dim
));
858 if (set_value(dim
, value
))
859 g_object_notify((GObject
*) dim
, "value");
866 * Gets the value text. The string is internally owned and
867 * must not be freed or modified.
869 * Returns: the value text
872 adg_dim_get_value(AdgDim
*dim
)
876 g_return_val_if_fail(ADG_IS_DIM(dim
), NULL
);
884 * adg_dim_set_limits:
886 * @min: the new minumum value
887 * @max: the new maximum value
889 * Shortcut to set both the limits at once.
892 adg_dim_set_limits(AdgDim
*dim
, const gchar
*min
, const gchar
*max
)
894 g_return_if_fail(ADG_IS_DIM(dim
));
896 g_object_freeze_notify((GObject
*) dim
);
897 adg_dim_set_min(dim
, min
);
898 adg_dim_set_max(dim
, max
);
899 g_object_thaw_notify((GObject
*) dim
);
905 * @min: the new minimum limit
907 * Sets the minimum value. Use %NULL as @min to disable it.
910 adg_dim_set_min(AdgDim
*dim
, const gchar
*min
)
912 g_return_if_fail(ADG_IS_DIM(dim
));
914 if (set_min(dim
, min
))
915 g_object_notify((GObject
*) dim
, "min");
922 * Gets the minimum value text or %NULL on minimum value disabled.
923 * The string is internally owned and must not be freed or modified.
925 * Returns: the mimimum value text
928 adg_dim_get_min(AdgDim
*dim
)
932 g_return_val_if_fail(ADG_IS_DIM(dim
), NULL
);
942 * @max: the new maximum value
944 * Sets the maximum value. Use %NULL as @max to disable it.
947 adg_dim_set_max(AdgDim
*dim
, const gchar
*max
)
949 g_return_if_fail(ADG_IS_DIM(dim
));
951 if (set_max(dim
, max
))
952 g_object_notify((GObject
*) dim
, "max");
959 * Gets the maximum value text or %NULL on maximum value disabled.
960 * The string is internally owned and must not be freed or modified.
962 * Returns: the maximum value text
965 adg_dim_get_max(AdgDim
*dim
)
969 g_return_val_if_fail(ADG_IS_DIM(dim
), NULL
);
981 * This function is only useful in new dimension implementations.
984 * Gets the quote entity, if any. This function is valid only after
985 * the #AdgDim implementation of the arrange() virtual method has
988 * Returns: the quote entity
991 adg_dim_get_quote(AdgDim
*dim
)
995 g_return_val_if_fail(ADG_IS_DIM(dim
), NULL
);
999 return data
->quote
.entity
;
1003 * adg_dim_quote_angle:
1005 * @angle: an angle (in radians)
1008 * This function is only useful in new dimension implementations.
1011 * Converts @angle accordling to the style of @dim. Any quote angle
1012 * should be validated by this method because every dimensioning
1013 * style has its own convention regardling the text rotation.
1015 * Returns: the angle to use (always in radians)
1018 adg_dim_quote_angle(AdgDim
*dim
, gdouble angle
)
1022 g_return_val_if_fail(ADG_IS_DIM(dim
), angle
);
1024 klass
= ADG_DIM_GET_CLASS(dim
);
1026 if (klass
->quote_angle
== NULL
)
1029 return klass
->quote_angle(angle
);
1034 global_changed(AdgEntity
*entity
)
1036 AdgDimPrivate
*data
= ((AdgDim
*) entity
)->data
;
1038 if (PARENT_ENTITY_CLASS
->global_changed
)
1039 PARENT_ENTITY_CLASS
->global_changed(entity
);
1041 if (data
->quote
.entity
!= NULL
)
1042 adg_entity_global_changed((AdgEntity
*) data
->quote
.entity
);
1046 local_changed(AdgEntity
*entity
)
1048 AdgDimPrivate
*data
= ((AdgDim
*) entity
)->data
;
1050 if (PARENT_ENTITY_CLASS
->local_changed
)
1051 PARENT_ENTITY_CLASS
->local_changed(entity
);
1053 if (data
->quote
.entity
!= NULL
)
1054 adg_entity_local_changed((AdgEntity
*) data
->quote
.entity
);
1058 invalidate(AdgEntity
*entity
)
1060 AdgDimPrivate
*data
= ((AdgDim
*) entity
)->data
;
1062 if (PARENT_ENTITY_CLASS
->invalidate
)
1063 PARENT_ENTITY_CLASS
->invalidate(entity
);
1065 if (data
->quote
.entity
!= NULL
)
1066 adg_entity_invalidate((AdgEntity
*) data
->quote
.entity
);
1068 adg_point_invalidate(data
->ref1
);
1069 adg_point_invalidate(data
->ref2
);
1070 adg_point_invalidate(data
->pos
);
1074 arrange(AdgEntity
*entity
)
1077 AdgDimPrivate
*data
;
1078 AdgEntity
*quote_entity
;
1079 AdgContainer
*quote_container
;
1080 AdgEntity
*value_entity
;
1081 AdgEntity
*min_entity
;
1082 AdgEntity
*max_entity
;
1083 const AdgPair
*shift
;
1086 dim
= (AdgDim
*) entity
;
1089 /* Resolve the dim style */
1090 if (data
->dim_style
== NULL
)
1091 data
->dim_style
= (AdgDimStyle
*)
1092 adg_entity_style(entity
, data
->dim_dress
);
1094 if (data
->quote
.entity
== NULL
)
1095 data
->quote
.entity
= g_object_new(ADG_TYPE_ALIGNMENT
,
1096 "local-method", ADG_MIX_NONE
,
1097 "parent", dim
, NULL
);
1099 quote_entity
= (AdgEntity
*) data
->quote
.entity
;
1100 quote_container
= (AdgContainer
*) data
->quote
.entity
;
1102 if (data
->quote
.value
== NULL
) {
1103 AdgDress dress
= adg_dim_style_get_value_dress(data
->dim_style
);
1105 data
->quote
.value
= g_object_new(ADG_TYPE_TOY_TEXT
,
1106 "local-method", ADG_MIX_PARENT
,
1107 "font-dress", dress
, NULL
);
1109 adg_container_add(quote_container
, (AdgEntity
*) data
->quote
.value
);
1112 adg_toy_text_set_label(data
->quote
.value
, data
->value
);
1114 AdgDimClass
*klass
= ADG_DIM_GET_CLASS(dim
);
1116 if (klass
->default_value
) {
1117 /* Automatically generate the value text */
1118 gchar
*text
= klass
->default_value(dim
);
1119 adg_toy_text_set_label(data
->quote
.value
, text
);
1125 if (data
->quote
.min
== NULL
&& data
->min
!= NULL
) {
1126 AdgDress dress
= adg_dim_style_get_min_dress(data
->dim_style
);
1128 data
->quote
.min
= g_object_new(ADG_TYPE_TOY_TEXT
,
1129 "local-method", ADG_MIX_PARENT
,
1130 "font-dress", dress
, NULL
);
1132 adg_container_add(quote_container
, (AdgEntity
*) data
->quote
.min
);
1133 adg_toy_text_set_label(data
->quote
.min
, data
->min
);
1136 if (data
->quote
.max
== NULL
&& data
->max
!= NULL
) {
1137 AdgDress dress
= adg_dim_style_get_max_dress(data
->dim_style
);
1139 data
->quote
.max
= g_object_new(ADG_TYPE_TOY_TEXT
,
1140 "local-method", ADG_MIX_PARENT
,
1141 "font-dress", dress
, NULL
);
1143 adg_container_add(quote_container
, (AdgEntity
*) data
->quote
.max
);
1144 adg_toy_text_set_label(data
->quote
.max
, data
->max
);
1147 value_entity
= (AdgEntity
*) data
->quote
.value
;
1148 min_entity
= (AdgEntity
*) data
->quote
.min
;
1149 max_entity
= (AdgEntity
*) data
->quote
.max
;
1150 shift
= adg_dim_style_get_quote_shift(data
->dim_style
);
1152 adg_entity_set_global_map(quote_entity
, adg_matrix_identity());
1153 adg_entity_global_changed(quote_entity
);
1155 cairo_matrix_init_translate(&map
, shift
->x
, shift
->y
);
1156 adg_entity_set_global_map(value_entity
, &map
);
1157 adg_entity_arrange(value_entity
);
1159 /* Limit values (min and max) */
1160 if (min_entity
!= NULL
|| max_entity
!= NULL
) {
1161 const CpmlExtents
*extents
= adg_entity_get_extents(value_entity
);
1162 //CpmlExtents min_extents = { 0 };
1163 //CpmlExtents max_extents = { 0 };
1164 const AdgPair
*limits_shift
= adg_dim_style_get_limits_shift(data
->dim_style
);
1167 if (min_entity
!= NULL
)
1168 cpml_extents_copy(&min_extents
, adg_entity_get_extents(min_entity
));
1170 if (max_entity
!= NULL
)
1171 cpml_extents_copy(&max_extents
, adg_entity_get_extents(max_entity
));
1173 if (min_entity
!= NULL
&& max_entity
!= NULL
)
1174 spacing
= adg_dim_style_get_limits_spacing(data
->dim_style
);
1176 cairo_matrix_init_translate(&map
,
1178 shift
->x
+ limit_shift
->x
,
1179 (spacing
+ min_extents
.size
.y
+
1180 max_extents
.size
.y
- extents
->size
.y
) / 2 +
1181 shift
->y
+ limit_shift
->y
);
1183 cairo_matrix_init_translate(&map
, extents
->size
.x
+ limits_shift
->x
,
1184 -extents
->size
.y
/ 2 + limits_shift
->y
);
1186 if (min_entity
!= NULL
) {
1187 adg_entity_set_global_map(min_entity
, &map
);
1188 adg_entity_arrange(min_entity
);
1189 extents
= adg_entity_get_extents(min_entity
);
1190 map
.y0
-= extents
->size
.y
+
1191 adg_dim_style_get_limits_spacing(data
->dim_style
);
1194 if (max_entity
!= NULL
) {
1195 adg_entity_set_global_map(max_entity
, &map
);
1196 adg_entity_arrange(max_entity
);
1200 adg_entity_arrange(quote_entity
);
1204 default_value(AdgDim
*dim
)
1206 g_warning("AdgDim::default_value not implemented for `%s'",
1207 g_type_name(G_TYPE_FROM_INSTANCE(dim
)));
1208 return g_strdup("undef");
1212 quote_angle(gdouble angle
)
1214 angle
= cpml_angle(angle
);
1216 if (angle
> G_PI_4
* 4 / 3 || angle
<= -G_PI_4
* 3)
1217 angle
= cpml_angle(angle
+ G_PI
);
1223 set_dim_dress(AdgDim
*dim
, AdgDress dress
)
1225 AdgDimPrivate
*data
= dim
->data
;
1227 if (adg_dress_set(&data
->dim_dress
, dress
)) {
1228 data
->dim_style
= NULL
;
1236 set_ref1(AdgDim
*dim
, const AdgPoint
*ref1
)
1238 AdgDimPrivate
*data
= dim
->data
;
1240 return set_point(&data
->ref1
, ref1
);
1244 set_ref2(AdgDim
*dim
, const AdgPoint
*ref2
)
1246 AdgDimPrivate
*data
= dim
->data
;
1248 return set_point(&data
->ref2
, ref2
);
1252 set_pos(AdgDim
*dim
, const AdgPoint
*pos
)
1254 AdgDimPrivate
*data
= dim
->data
;
1256 return set_point(&data
->pos
, pos
);
1260 set_outside(AdgDim
*dim
, AdgThreeState outside
)
1262 AdgDimPrivate
*data
;
1264 g_return_val_if_fail(adg_is_enum_value(outside
, ADG_TYPE_THREE_STATE
),
1269 if (data
->outside
== outside
)
1272 data
->outside
= outside
;
1278 set_detached(AdgDim
*dim
, AdgThreeState detached
)
1280 AdgDimPrivate
*data
;
1282 g_return_val_if_fail(adg_is_enum_value(detached
, ADG_TYPE_THREE_STATE
),
1287 if (data
->detached
== detached
)
1290 data
->detached
= detached
;
1296 set_value(AdgDim
*dim
, const gchar
*value
)
1298 AdgDimPrivate
*data
;
1302 if (adg_strcmp(value
, data
->value
) == 0)
1305 g_free(data
->value
);
1306 data
->value
= g_strdup(value
);
1308 if (data
->quote
.value
!= NULL
) {
1309 g_object_unref(data
->quote
.value
);
1310 data
->quote
.value
= NULL
;
1317 set_min(AdgDim
*dim
, const gchar
*min
)
1319 AdgDimPrivate
*data
= dim
->data
;
1321 if (adg_strcmp(min
, data
->min
) == 0)
1325 data
->min
= g_strdup(min
);
1327 if (data
->quote
.min
!= NULL
) {
1328 g_object_unref(data
->quote
.min
);
1329 data
->quote
.min
= NULL
;
1336 set_max(AdgDim
*dim
, const gchar
*max
)
1338 AdgDimPrivate
*data
= dim
->data
;
1340 if (adg_strcmp(max
, data
->max
) == 0)
1344 data
->max
= g_strdup(max
);
1346 if (data
->quote
.max
!= NULL
) {
1347 g_object_unref(data
->quote
.max
);
1348 data
->quote
.max
= NULL
;
1355 set_point(AdgPoint
**point
, const AdgPoint
*new_point
)
1357 if ((*point
== new_point
) ||
1358 (*point
&& new_point
&& adg_point_equal(*point
, new_point
)))
1362 *point
= adg_point_new();
1365 adg_point_copy(*point
, new_point
);
1367 adg_point_destroy(*point
);