1 /* ADG - Automatic Drawing Generation
2 * Copyright (C) 2007,2008,2009 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.
37 #include "adg-dim-private.h"
38 #include "adg-dim-style.h"
39 #include "adg-dress-builtins.h"
40 #include "adg-toy-text.h"
41 #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)
62 static void dispose (GObject
*object
);
63 static void finalize (GObject
*object
);
64 static void get_property (GObject
*object
,
68 static void set_property (GObject
*object
,
72 static void global_changed (AdgEntity
*entity
);
73 static void local_changed (AdgEntity
*entity
);
74 static void invalidate (AdgEntity
*entity
);
75 static void arrange (AdgEntity
*entity
);
76 static gchar
* default_value (AdgDim
*dim
);
77 static gdouble
quote_angle (gdouble angle
);
78 static gboolean
set_dim_dress (AdgDim
*dim
,
80 static gboolean
set_value (AdgDim
*dim
,
82 static gboolean
set_min (AdgDim
*dim
,
84 static gboolean
set_max (AdgDim
*dim
,
88 G_DEFINE_ABSTRACT_TYPE(AdgDim
, adg_dim
, ADG_TYPE_ENTITY
);
92 adg_dim_class_init(AdgDimClass
*klass
)
94 GObjectClass
*gobject_class
;
95 AdgEntityClass
*entity_class
;
98 gobject_class
= (GObjectClass
*) klass
;
99 entity_class
= (AdgEntityClass
*) klass
;
101 g_type_class_add_private(klass
, sizeof(AdgDimPrivate
));
103 gobject_class
->dispose
= dispose
;
104 gobject_class
->finalize
= finalize
;
105 gobject_class
->get_property
= get_property
;
106 gobject_class
->set_property
= set_property
;
108 entity_class
->global_changed
= global_changed
;
109 entity_class
->local_changed
= local_changed
;
110 entity_class
->invalidate
= invalidate
;
111 entity_class
->arrange
= arrange
;
113 klass
->quote_angle
= quote_angle
;
114 klass
->default_value
= default_value
;
116 param
= adg_param_spec_dress("dim-dress",
118 P_("The dress to use for rendering this dimension"),
121 g_object_class_install_property(gobject_class
, PROP_DIM_DRESS
, param
);
123 param
= g_param_spec_boxed("ref1",
125 P_("First reference point of the dimension"),
128 g_object_class_install_property(gobject_class
, PROP_REF1
, param
);
130 param
= g_param_spec_boxed("ref2",
132 P_("Second reference point of the dimension"),
135 g_object_class_install_property(gobject_class
, PROP_REF2
, param
);
137 param
= g_param_spec_boxed("pos",
139 P_("The reference position in local space of the quote: it will be combined with \"level\" to get the real quote position"),
142 g_object_class_install_property(gobject_class
, PROP_POS
, param
);
144 param
= g_param_spec_double("level",
146 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"),
147 -G_MAXDOUBLE
, G_MAXDOUBLE
, 1.0,
149 g_object_class_install_property(gobject_class
, PROP_LEVEL
, param
);
151 param
= g_param_spec_enum("outside",
153 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"),
154 ADG_TYPE_THREE_STATE
, ADG_THREE_STATE_UNKNOWN
,
156 g_object_class_install_property(gobject_class
, PROP_OUTSIDE
, param
);
158 param
= g_param_spec_string("value",
160 P_("The theoretically exact value for this quote: set to NULL to automatically get the default value"),
163 g_object_class_install_property(gobject_class
, PROP_VALUE
, param
);
165 param
= g_param_spec_string("value-min",
166 P_("Minimum Value or Low Tolerance"),
167 P_("The minimum value allowed or the lowest tolerance from value (depending of the dimension style): set to NULL to suppress"),
170 g_object_class_install_property(gobject_class
, PROP_MIN
, param
);
172 param
= g_param_spec_string("value-max",
173 P_("Maximum Value or High Tolerance"),
174 P_("The maximum value allowed or the highest tolerance from value (depending of the dimension style): set to NULL to suppress"),
177 g_object_class_install_property(gobject_class
, PROP_MAX
, param
);
181 adg_dim_init(AdgDim
*dim
)
183 AdgDimPrivate
*data
= G_TYPE_INSTANCE_GET_PRIVATE(dim
, ADG_TYPE_DIM
,
186 data
->dim_dress
= ADG_DRESS_DIMENSION
;
191 data
->outside
= ADG_THREE_STATE_UNKNOWN
;
200 dispose(GObject
*object
)
202 AdgDimPrivate
*data
= ((AdgDim
*) object
)->data
;
204 if (data
->quote
.container
!= NULL
) {
205 g_object_unref(data
->quote
.container
);
206 data
->quote
.container
= NULL
;
208 if (data
->ref1
!= NULL
) {
209 adg_point_destroy(data
->ref1
);
212 if (data
->ref2
!= NULL
) {
213 adg_point_destroy(data
->ref2
);
216 if (data
->pos
!= NULL
) {
217 adg_point_destroy(data
->pos
);
221 if (PARENT_OBJECT_CLASS
->dispose
!= NULL
)
222 PARENT_OBJECT_CLASS
->dispose(object
);
226 finalize(GObject
*object
)
228 AdgDimPrivate
*data
= ((AdgDim
*) object
)->data
;
234 if (PARENT_OBJECT_CLASS
->finalize
!= NULL
)
235 PARENT_OBJECT_CLASS
->finalize(object
);
239 get_property(GObject
*object
, guint prop_id
, GValue
*value
, GParamSpec
*pspec
)
241 AdgDimPrivate
*data
= ((AdgDim
*) object
)->data
;
245 g_value_set_int(value
, data
->dim_dress
);
248 g_value_set_boxed(value
, data
->ref1
);
251 g_value_set_boxed(value
, data
->ref2
);
254 g_value_set_boxed(value
, data
->pos
);
257 g_value_set_double(value
, data
->level
);
260 g_value_set_enum(value
, data
->outside
);
263 g_value_set_string(value
, data
->value
);
266 g_value_set_string(value
, data
->min
);
269 g_value_set_string(value
, data
->max
);
272 G_OBJECT_WARN_INVALID_PROPERTY_ID(object
, prop_id
, pspec
);
278 set_property(GObject
*object
, guint prop_id
,
279 const GValue
*value
, GParamSpec
*pspec
)
284 dim
= (AdgDim
*) object
;
289 set_dim_dress(dim
, g_value_get_int(value
));
292 if (data
->ref1
!= NULL
)
293 adg_point_destroy(data
->ref1
);
294 data
->ref1
= g_value_dup_boxed(value
);
297 if (data
->ref2
!= NULL
)
298 adg_point_destroy(data
->ref2
);
299 data
->ref2
= g_value_dup_boxed(value
);
302 if (data
->pos
!= NULL
)
303 adg_point_destroy(data
->pos
);
304 data
->pos
= g_value_dup_boxed(value
);
307 data
->level
= g_value_get_double(value
);
310 data
->outside
= g_value_get_enum(value
);
313 set_value(dim
, g_value_get_string(value
));
316 set_min(dim
, g_value_get_string(value
));
319 set_max(dim
, g_value_get_string(value
));
322 G_OBJECT_WARN_INVALID_PROPERTY_ID(object
, prop_id
, pspec
);
329 * adg_dim_get_dim_dress:
332 * Gets the dimension dress to be used in rendering @dim.
334 * Returns: the current dimension dress
337 adg_dim_get_dim_dress(AdgDim
*dim
)
341 g_return_val_if_fail(ADG_IS_DIM(dim
), ADG_DRESS_UNDEFINED
);
345 return data
->dim_dress
;
349 * adg_dim_set_dim_dress:
351 * @dress: the new #AdgDress to use
353 * Sets a new dimension dress to @dim. The new dress must be
354 * related to the original dress for this property: you cannot
355 * set a dress used for line styles to a dress managing fonts.
357 * The check is done by calling adg_dress_are_related() with
358 * @dress and the previous dress as arguments. Check out its
359 * documentation for details on what is a related dress.
362 adg_dim_set_dim_dress(AdgDim
*dim
, AdgDress dress
)
364 g_return_if_fail(ADG_IS_DIM(dim
));
366 if (set_dim_dress(dim
, dress
))
367 g_object_notify((GObject
*) dim
, "dim-dress");
374 * Gets the ref1 coordinates. The returned pair is internally owned
375 * and must not be freed or modified.
377 * Returns: the ref1 coordinates
380 adg_dim_get_ref1(AdgDim
*dim
)
384 g_return_val_if_fail(ADG_IS_DIM(dim
), NULL
);
388 return ADG_POINT_PAIR(data
->ref1
);
395 * Gets the ref2 coordinates. The returned pair is internally owned
396 * and must not be freed or modified.
398 * Returns: the ref2 coordinates
401 adg_dim_get_ref2(AdgDim
*dim
)
405 g_return_val_if_fail(ADG_IS_DIM(dim
), NULL
);
409 return ADG_POINT_PAIR(data
->ref2
);
415 * @ref1: the ref1 coordinates
416 * @ref2: the ref2 coordinates
418 * Sets the #AdgDim:ref1 and #AdgDim:ref2 reference points
419 * using @ref1 and @ref2 pairs. @ref1 or @ref2 could be
420 * %NULL (but not both), in which case only the non-null
421 * reference point is changed.
424 adg_dim_set_ref(AdgDim
*dim
, const AdgPair
*ref1
, const AdgPair
*ref2
)
429 g_return_if_fail(ADG_IS_DIM(dim
));
430 g_return_if_fail(ref1
!= NULL
|| ref2
!= NULL
);
433 object
= (GObject
*) dim
;
435 g_object_freeze_notify(object
);
438 if (data
->ref1
== NULL
)
439 data
->ref1
= adg_point_new();
441 adg_point_set(data
->ref1
, ref1
);
443 g_object_notify(object
, "ref1");
447 if (data
->ref2
== NULL
)
448 data
->ref2
= adg_point_new();
450 adg_point_set(data
->ref2
, ref2
);
452 g_object_notify(object
, "ref2");
455 g_object_thaw_notify(object
);
459 * adg_dim_set_ref_explicit:
461 * @ref1_x: x coordinate of ref1
462 * @ref1_y: y coordinate of ref1
463 * @ref2_x: x coordinate of ref2
464 * @ref2_y: y coordinate of ref2
466 * Works in the same way as adg_dim_set_ref() but using
467 * explicit coordinates instead of #AdgPair args. The
468 * notable difference is that, by using gdouble values,
469 * you can't set only one reference point.
472 adg_dim_set_ref_explicit(AdgDim
*dim
,
473 gdouble ref1_x
, gdouble ref1_y
,
474 gdouble ref2_x
, gdouble ref2_y
)
484 adg_dim_set_ref(dim
, &ref1
, &ref2
);
488 * adg_dim_set_ref_from_model:
490 * @model: the source #AdgModel
491 * @ref1: name of the pair in @model to use as ref1
492 * @ref2: name of the pair in @model to use as ref2
494 * Sets #AdgDim:ref1 and #AdgDim:ref2 properties by linking
495 * them to the @ref1 and @ref2 named pairs in @model. @ref1
496 * or @ref2 could be %NULL (but not both), in which case
497 * only the non-null reference point is changed.
499 * Using this function twice you can also link the reference
500 * points to named pairs taken from different models:
503 * adg_dim_set_ref_from_model(dim, model1, ref1, NULL);
504 * adg_dim_set_ref_from_model(dim, model2, NULL, ref2);
508 adg_dim_set_ref_from_model(AdgDim
*dim
, AdgModel
*model
,
509 const gchar
*ref1
, const gchar
*ref2
)
514 g_return_if_fail(ADG_IS_DIM(dim
));
515 g_return_if_fail(ADG_IS_MODEL(model
));
516 g_return_if_fail(ref1
!= NULL
|| ref2
!= NULL
);
518 object
= (GObject
*) dim
;
521 g_object_freeze_notify(object
);
524 if (data
->ref1
== NULL
)
525 data
->ref1
= adg_point_new();
527 adg_point_set_from_model(data
->ref1
, model
, ref1
);
529 g_object_notify(object
, "ref1");
533 if (data
->ref2
== NULL
)
534 data
->ref2
= adg_point_new();
536 adg_point_set_from_model(data
->ref2
, model
, ref2
);
538 g_object_notify(object
, "ref2");
541 g_object_thaw_notify(object
);
548 * Gets the position coordinates. The returned pair is internally owned
549 * and must not be freed or modified.
551 * Returns: the pos coordinates
554 adg_dim_get_pos(AdgDim
*dim
)
558 g_return_val_if_fail(ADG_IS_DIM(dim
), NULL
);
562 return ADG_POINT_PAIR(data
->pos
);
568 * @pos: the pos coordinates
570 * Sets a new #AdgDim:pos position.
573 adg_dim_set_pos(AdgDim
*dim
, const AdgPair
*pos
)
577 g_return_if_fail(ADG_IS_DIM(dim
));
578 g_return_if_fail(pos
!= NULL
);
582 if (data
->pos
== NULL
)
583 data
->pos
= adg_point_new();
585 adg_point_set(data
->pos
, pos
);
587 g_object_notify((GObject
*) dim
, "pos");
591 * adg_dim_set_pos_explicit:
593 * @pos_x: x coordinate of pos
594 * @pos_y: y coordinate of pos
596 * Shortcut to set #AdgDim:pos using explicit coordinates.
599 adg_dim_set_pos_explicit(AdgDim
*dim
, gdouble x
, gdouble y
)
606 adg_dim_set_pos(dim
, &pos
);
610 * adg_dim_set_pos_from_model:
612 * @model: the source #AdgModel
613 * @ref1: name of the pair in @model to use as pos
615 * Sets #AdgDim:pos by linking it to the @pos named pair
619 adg_dim_set_pos_from_model(AdgDim
*dim
, AdgModel
*model
, const gchar
*pos
)
623 g_return_if_fail(ADG_IS_DIM(dim
));
624 g_return_if_fail(ADG_IS_MODEL(model
));
625 g_return_if_fail(pos
!= NULL
);
629 if (data
->pos
== NULL
)
630 data
->pos
= adg_point_new();
632 adg_point_set_from_model(data
->pos
, model
, pos
);
634 g_object_notify((GObject
*) dim
, "pos");
641 * Gets the level of this dimension.
643 * Returns: the level value
646 adg_dim_get_level(AdgDim
*dim
)
650 g_return_val_if_fail(ADG_IS_DIM(dim
), 0);
660 * @level: the new level
662 * Sets a new level for this dimension. The level is used to
663 * stack the quotes using a spacing value from dim_style
664 * (specified in global space).
667 adg_dim_set_level(AdgDim
*dim
, gdouble level
)
671 g_return_if_fail(ADG_IS_DIM(dim
));
676 g_object_notify((GObject
*) dim
, "level");
680 * adg_dim_get_outside:
683 * Gets the state of the #AdgDim:outside property: check the property
684 * documentation for further details.
686 * Returns: the current flag state
689 adg_dim_get_outside(AdgDim
*dim
)
693 g_return_val_if_fail(ADG_IS_DIM(dim
), ADG_THREE_STATE_UNKNOWN
);
697 return data
->outside
;
701 * adg_dim_set_outside:
703 * @outside: the new outside state
705 * Sets a new state for the #AdgDim:outside flag: check the property
706 * documentation for further details.
709 adg_dim_set_outside(AdgDim
*dim
, AdgThreeState outside
)
713 g_return_if_fail(ADG_IS_DIM(dim
));
716 data
->outside
= outside
;
718 g_object_notify((GObject
*) dim
, "outside");
725 * Gets the value text. The string is internally owned and
726 * must not be freed or modified.
728 * Returns: the value text
731 adg_dim_get_value(AdgDim
*dim
)
735 g_return_val_if_fail(ADG_IS_DIM(dim
), NULL
);
745 * @value: the value text
747 * Explicitely sets the text to use as value. If @value is %NULL or
748 * was never set, an automatic text is calculated using the format
749 * specified in the current #AdgDimStyle and getting its value by
750 * calling the default_value() virtual method.
753 adg_dim_set_value(AdgDim
*dim
, const gchar
*value
)
755 g_return_if_fail(ADG_IS_DIM(dim
));
757 if (set_value(dim
, value
))
758 g_object_notify((GObject
*) dim
, "value");
765 * Gets the minimum value text or %NULL on minimum value disabled.
766 * The string is internally owned and must not be freed or modified.
768 * Returns: the mimimum value text
771 adg_dim_get_min(AdgDim
*dim
)
775 g_return_val_if_fail(ADG_IS_DIM(dim
), NULL
);
785 * @min: the new minimum limit
787 * Sets the minimum value. Use %NULL as @min to disable it.
790 adg_dim_set_min(AdgDim
*dim
, const gchar
*min
)
792 g_return_if_fail(ADG_IS_DIM(dim
));
794 if (set_min(dim
, min
))
795 g_object_notify((GObject
*) dim
, "value-min");
802 * Gets the maximum value text or %NULL on maximum value disabled.
803 * The string is internally owned and must not be freed or modified.
805 * Returns: the maximum value text
808 adg_dim_get_max(AdgDim
*dim
)
812 g_return_val_if_fail(ADG_IS_DIM(dim
), NULL
);
822 * @max: the new maximum value
824 * Sets the maximum value. Use %NULL as @max to disable it.
827 adg_dim_set_max(AdgDim
*dim
, const gchar
*max
)
829 g_return_if_fail(ADG_IS_DIM(dim
));
831 if (set_max(dim
, max
))
832 g_object_notify((GObject
*) dim
, "value-max");
836 * adg_dim_set_limits:
838 * @min: the new minumum value
839 * @max: the new maximum value
841 * Shortcut to set both the limits at once.
844 adg_dim_set_limits(AdgDim
*dim
, const gchar
*min
, const gchar
*max
)
846 g_return_if_fail(ADG_IS_DIM(dim
));
848 g_object_freeze_notify((GObject
*) dim
);
849 adg_dim_set_min(dim
, min
);
850 adg_dim_set_max(dim
, max
);
851 g_object_thaw_notify((GObject
*) dim
);
859 * This function is only useful in new dimension implementations.
862 * Gets the quote container, if any. This function is valid only
863 * after the #AdgDim implementation of the arrange() virtual method
866 * Returns: the quote container
869 adg_dim_get_quote(AdgDim
*dim
)
873 g_return_val_if_fail(ADG_IS_DIM(dim
), NULL
);
877 return data
->quote
.container
;
881 * adg_dim_quote_angle:
883 * @angle: an angle (in radians)
886 * This function is only useful in new dimension implementations.
889 * Converts @angle accordling to the style of @dim. Any quote angle
890 * should be validated by this method because every dimensioning
891 * style has its own convention regardling the text rotation.
893 * Returns: the angle to use (always in radians)
896 adg_dim_quote_angle(AdgDim
*dim
, gdouble angle
)
900 g_return_val_if_fail(ADG_IS_DIM(dim
), angle
);
902 klass
= ADG_DIM_GET_CLASS(dim
);
904 if (klass
->quote_angle
== NULL
)
907 return klass
->quote_angle(angle
);
911 * _adg_dim_get_dim_style:
912 * @dim: an #AdgDim entity
914 * Gets the #AdgDimStyle associated to @dim. The dress to style
915 * resolution is done in the arrange() method so this value is
916 * typically available in render() or in a derived arrange()
917 * method, after the #AdgDim arrange() function has been chained up.
919 * Returns: the dim style of @entity
922 _adg_dim_get_dim_style(AdgDim
*dim
)
926 g_return_val_if_fail(ADG_IS_DIM(dim
), NULL
);
930 return data
->dim_style
;
935 arrange(AdgEntity
*entity
)
939 AdgEntity
*container_entity
;
940 AdgEntity
*value_entity
;
941 AdgEntity
*min_entity
;
942 AdgEntity
*max_entity
;
945 const AdgPair
*shift
;
947 dim
= (AdgDim
*) entity
;
950 /* Resolve the dim style */
951 if (data
->dim_style
== NULL
)
952 data
->dim_style
= (AdgDimStyle
*) adg_entity_style(entity
,
955 if (data
->quote
.container
== NULL
)
956 data
->quote
.container
= g_object_new(ADG_TYPE_CONTAINER
,
957 "parent", dim
, NULL
);
959 if (data
->quote
.value
== NULL
) {
960 AdgDress dress
= adg_dim_style_get_value_dress(data
->dim_style
);
962 data
->quote
.value
= g_object_new(ADG_TYPE_TOY_TEXT
,
963 "font-dress", dress
, NULL
);
965 adg_container_add(data
->quote
.container
,
966 (AdgEntity
*) data
->quote
.value
);
968 if (data
->value
== NULL
) {
969 /* Automatically generate the value text */
970 gchar
*text
= ADG_DIM_GET_CLASS(dim
)->default_value(dim
);
971 adg_toy_text_set_label(data
->quote
.value
, text
);
974 adg_toy_text_set_label(data
->quote
.value
, data
->value
);
978 if (data
->quote
.min
== NULL
&& data
->min
!= NULL
) {
979 AdgDress dress
= adg_dim_style_get_min_dress(data
->dim_style
);
981 data
->quote
.min
= g_object_new(ADG_TYPE_TOY_TEXT
,
982 "font-dress", dress
, NULL
);
984 adg_container_add(data
->quote
.container
, (AdgEntity
*) data
->quote
.min
);
985 adg_toy_text_set_label(data
->quote
.min
, data
->min
);
988 if (data
->quote
.max
== NULL
&& data
->max
!= NULL
) {
989 AdgDress dress
= adg_dim_style_get_max_dress(data
->dim_style
);
991 data
->quote
.max
= g_object_new(ADG_TYPE_TOY_TEXT
,
992 "font-dress", dress
, NULL
);
994 adg_container_add(data
->quote
.container
, (AdgEntity
*) data
->quote
.max
);
995 adg_toy_text_set_label(data
->quote
.max
, data
->max
);
998 container_entity
= (AdgEntity
*) data
->quote
.container
;
999 value_entity
= (AdgEntity
*) data
->quote
.value
;
1000 min_entity
= (AdgEntity
*) data
->quote
.min
;
1001 max_entity
= (AdgEntity
*) data
->quote
.max
;
1003 /* Propagate the arrange signal to the quote container */
1004 adg_entity_arrange(container_entity
);
1007 adg_entity_get_extents(value_entity
, &extents
);
1009 /* Limit values (min and max) */
1010 if (min_entity
!= NULL
|| max_entity
!= NULL
) {
1011 CpmlExtents min_extents
= { 0 };
1012 CpmlExtents max_extents
= { 0 };
1013 gdouble spacing
= 0;
1016 if (min_entity
!= NULL
)
1017 adg_entity_get_extents(min_entity
, &min_extents
);
1020 if (max_entity
!= NULL
)
1021 adg_entity_get_extents(max_entity
, &max_extents
);
1023 shift
= adg_dim_style_get_limits_shift(data
->dim_style
);
1024 if (min_entity
!= NULL
&& max_entity
!= NULL
)
1025 spacing
= adg_dim_style_get_limits_spacing(data
->dim_style
);
1027 cairo_matrix_init_translate(&map
, extents
.size
.x
+ shift
->x
,
1028 (spacing
+ min_extents
.size
.y
+
1029 max_extents
.size
.y
) / 2 +
1030 shift
->y
- extents
.size
.y
/ 2);
1032 if (min_entity
!= NULL
)
1033 adg_entity_set_global_map(min_entity
, &map
);
1035 if (max_entity
!= NULL
) {
1036 cairo_matrix_translate(&map
, 0, -min_extents
.size
.y
- spacing
);
1037 adg_entity_set_global_map(max_entity
, &map
);
1040 extents
.size
.x
+= shift
->x
+ MAX(min_extents
.size
.x
, max_extents
.size
.x
);
1043 /* Center and apply the style displacements */
1044 shift
= adg_dim_style_get_quote_shift(data
->dim_style
);
1045 cairo_matrix_init_translate(&map
, shift
->x
- extents
.size
.x
/ 2, shift
->y
);
1046 adg_entity_set_global_map(container_entity
, &map
);
1048 adg_entity_arrange(container_entity
);
1052 global_changed(AdgEntity
*entity
)
1054 AdgDimPrivate
*data
= ((AdgDim
*) entity
)->data
;
1056 PARENT_ENTITY_CLASS
->global_changed(entity
);
1058 if (data
->quote
.container
!= NULL
)
1059 adg_entity_global_changed((AdgEntity
*) data
->quote
.container
);
1063 local_changed(AdgEntity
*entity
)
1065 AdgDimPrivate
*data
= ((AdgDim
*) entity
)->data
;
1067 PARENT_ENTITY_CLASS
->local_changed(entity
);
1069 if (data
->quote
.container
!= NULL
)
1070 adg_entity_local_changed((AdgEntity
*) data
->quote
.container
);
1074 invalidate(AdgEntity
*entity
)
1076 AdgDimPrivate
*data
= ((AdgDim
*) entity
)->data
;
1078 if (data
->quote
.container
!= NULL
)
1079 adg_entity_invalidate((AdgEntity
*) data
->quote
.container
);
1083 default_value(AdgDim
*dim
)
1085 g_warning("AdgDim::default_value not implemented for `%s'",
1086 g_type_name(G_TYPE_FROM_INSTANCE(dim
)));
1087 return g_strdup("undef");
1091 quote_angle(gdouble angle
)
1093 angle
= cpml_angle(angle
);
1095 if (angle
> G_PI_4
* 4 / 3 || angle
<= -G_PI_4
* 3)
1096 angle
= cpml_angle(angle
+ G_PI
);
1102 set_dim_dress(AdgDim
*dim
, AdgDress dress
)
1104 AdgDimPrivate
*data
= dim
->data
;
1106 if (adg_dress_set(&data
->dim_dress
, dress
)) {
1107 data
->dim_style
= NULL
;
1115 set_value(AdgDim
*dim
, const gchar
*value
)
1117 AdgDimPrivate
*data
;
1121 if (adg_strcmp(value
, data
->value
) == 0)
1124 g_free(data
->value
);
1125 data
->value
= g_strdup(value
);
1127 if (data
->quote
.value
!= NULL
) {
1128 g_object_unref(data
->quote
.value
);
1129 data
->quote
.value
= NULL
;
1136 set_min(AdgDim
*dim
, const gchar
*min
)
1138 AdgDimPrivate
*data
= dim
->data
;
1140 if (adg_strcmp(min
, data
->min
) == 0)
1144 data
->min
= g_strdup(min
);
1146 if (data
->quote
.min
!= NULL
) {
1147 g_object_unref(data
->quote
.min
);
1148 data
->quote
.min
= NULL
;
1155 set_max(AdgDim
*dim
, const gchar
*max
)
1157 AdgDimPrivate
*data
= dim
->data
;
1159 if (adg_strcmp(max
, data
->max
) == 0)
1163 data
->max
= g_strdup(max
);
1165 if (data
->quote
.max
!= NULL
) {
1166 g_object_unref(data
->quote
.max
);
1167 data
->quote
.max
= NULL
;