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-toy-text.h"
40 #include "adg-type-builtins.h"
43 #define PARENT_OBJECT_CLASS ((GObjectClass *) 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 gboolean
invalidate (AdgEntity
*entity
);
74 static gchar
* default_value (AdgDim
*dim
);
75 static void quote_layout (AdgDim
*dim
,
77 static gboolean
set_angle (AdgDim
*dim
,
79 static gboolean
set_value (AdgDim
*dim
,
81 static gboolean
set_value_min (AdgDim
*dim
,
82 const gchar
*value_min
);
83 static gboolean
set_value_max (AdgDim
*dim
,
84 const gchar
*value_max
);
85 static gboolean
set_note (AdgDim
*dim
,
87 static void detach_entity (AdgEntity
**p_entity
);
90 G_DEFINE_ABSTRACT_TYPE(AdgDim
, adg_dim
, ADG_TYPE_ENTITY
);
94 adg_dim_class_init(AdgDimClass
*klass
)
96 GObjectClass
*gobject_class
;
97 AdgEntityClass
*entity_class
;
100 gobject_class
= (GObjectClass
*) klass
;
101 entity_class
= (AdgEntityClass
*) klass
;
103 g_type_class_add_private(klass
, sizeof(AdgDimPrivate
));
105 gobject_class
->dispose
= dispose
;
106 gobject_class
->finalize
= finalize
;
107 gobject_class
->get_property
= get_property
;
108 gobject_class
->set_property
= set_property
;
110 entity_class
->invalidate
= invalidate
;
112 klass
->default_value
= default_value
;
113 klass
->quote_layout
= quote_layout
;
115 param
= adg_param_spec_dress("dress",
117 P_("The dress to use for rendering this dimension"),
118 ADG_DRESS_DIMENSION_REGULAR
,
120 g_object_class_install_property(gobject_class
, PROP_DRESS
, param
);
122 param
= g_param_spec_boxed("ref1",
124 P_("First reference point of the dimension"),
126 G_PARAM_READWRITE
| G_PARAM_CONSTRUCT
);
127 g_object_class_install_property(gobject_class
, PROP_REF1
, param
);
129 param
= g_param_spec_boxed("ref2",
131 P_("Second reference point of the dimension"),
133 G_PARAM_READWRITE
| G_PARAM_CONSTRUCT
);
134 g_object_class_install_property(gobject_class
, PROP_REF2
, param
);
136 param
= g_param_spec_boxed("pos1",
138 P_("First position point: it will be computed with the level property to get the real dimension position"),
139 ADG_TYPE_PAIR
, G_PARAM_READWRITE
);
140 g_object_class_install_property(gobject_class
, PROP_POS1
, param
);
142 param
= g_param_spec_boxed("pos2",
144 P_("Second position point: it will be computed with the level property to get the real dimension position"),
145 ADG_TYPE_PAIR
, G_PARAM_READWRITE
);
146 g_object_class_install_property(gobject_class
, PROP_POS2
, param
);
148 param
= g_param_spec_double("angle",
150 P_("The dimension direction, if relevant"),
151 -G_MAXDOUBLE
, G_MAXDOUBLE
, 0,
153 g_object_class_install_property(gobject_class
, PROP_ANGLE
, param
);
155 param
= g_param_spec_double("level",
157 P_("The dimension level, that is the factor to multiply dim_style->baseline_spacing to get the offset (in device units) from pos1..pos2 where render the dimension baseline"),
158 -G_MAXDOUBLE
, G_MAXDOUBLE
, 1.0,
160 g_object_class_install_property(gobject_class
, PROP_LEVEL
, param
);
162 param
= g_param_spec_enum("outside",
164 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"),
165 ADG_TYPE_THREE_STATE
, ADG_THREE_STATE_UNKNOWN
,
167 g_object_class_install_property(gobject_class
, PROP_OUTSIDE
, param
);
169 param
= g_param_spec_string("value",
171 P_("The theoretically exact value for this quote: set to NULL to automatically get the default value"),
172 NULL
, G_PARAM_READWRITE
);
173 g_object_class_install_property(gobject_class
, PROP_VALUE
, param
);
175 param
= g_param_spec_string("value-min",
176 P_("Minimum Value or Low Tolerance"),
177 P_("The minimum value allowed or the lowest tolerance from value (depending of the dimension style): set to NULL to suppress"),
178 NULL
, G_PARAM_READWRITE
);
179 g_object_class_install_property(gobject_class
, PROP_VALUE_MIN
, param
);
181 param
= g_param_spec_string("value-max",
182 P_("Maximum Value or High Tolerance"),
183 P_("The maximum value allowed or the highest tolerance from value (depending of the dimension style): set to NULL to suppress"),
184 NULL
, G_PARAM_READWRITE
);
185 g_object_class_install_property(gobject_class
, PROP_VALUE_MAX
, param
);
187 param
= g_param_spec_string("note",
189 P_("A custom note appended to the end of the quote"),
190 NULL
, G_PARAM_READWRITE
);
191 g_object_class_install_property(gobject_class
, PROP_NOTE
, param
);
195 adg_dim_init(AdgDim
*dim
)
197 AdgDimPrivate
*data
= G_TYPE_INSTANCE_GET_PRIVATE(dim
, ADG_TYPE_DIM
,
200 data
->dress
= ADG_DRESS_DIMENSION_REGULAR
;
201 data
->ref1
.x
= data
->ref1
.y
= 0;
202 data
->ref2
.x
= data
->ref2
.y
= 0;
203 data
->pos1
.x
= data
->pos1
.y
= 0;
204 data
->pos2
.x
= data
->pos2
.y
= 0;
208 data
->value_min
= NULL
;
209 data
->value_max
= NULL
;
212 data
->value_entity
= g_object_new(ADG_TYPE_TOY_TEXT
,
213 "parent", dim
, NULL
);
214 data
->value_min_entity
= g_object_new(ADG_TYPE_TOY_TEXT
,
215 "parent", dim
, NULL
);
216 data
->value_max_entity
= g_object_new(ADG_TYPE_TOY_TEXT
,
217 "parent", dim
, NULL
);
218 data
->note_entity
= g_object_new(ADG_TYPE_TOY_TEXT
,
219 "parent", dim
, NULL
);
225 dispose(GObject
*object
)
227 AdgDimPrivate
*data
= ((AdgDim
*) object
)->data
;
229 detach_entity(&data
->value_entity
);
230 detach_entity(&data
->value_min_entity
);
231 detach_entity(&data
->value_max_entity
);
232 detach_entity(&data
->note_entity
);
234 if (PARENT_OBJECT_CLASS
->dispose
!= NULL
)
235 PARENT_OBJECT_CLASS
->dispose(object
);
239 finalize(GObject
*object
)
241 AdgDimPrivate
*data
= ((AdgDim
*) object
)->data
;
244 g_free(data
->value_min
);
245 g_free(data
->value_max
);
248 if (PARENT_OBJECT_CLASS
->finalize
!= NULL
)
249 PARENT_OBJECT_CLASS
->finalize(object
);
253 get_property(GObject
*object
, guint prop_id
, GValue
*value
, GParamSpec
*pspec
)
255 AdgDimPrivate
*data
= ((AdgDim
*) object
)->data
;
259 g_value_set_int(value
, data
->dress
);
262 g_value_set_boxed(value
, &data
->ref1
);
265 g_value_set_boxed(value
, &data
->ref2
);
268 g_value_set_boxed(value
, &data
->pos1
);
271 g_value_set_boxed(value
, &data
->pos1
);
274 g_value_set_double(value
, data
->angle
);
277 g_value_set_double(value
, data
->level
);
280 g_value_set_enum(value
, data
->outside
);
283 g_value_set_string(value
, data
->value
);
286 g_value_set_string(value
, data
->value_min
);
289 g_value_set_string(value
, data
->value_max
);
292 g_value_set_string(value
, data
->note
);
295 G_OBJECT_WARN_INVALID_PROPERTY_ID(object
, prop_id
, pspec
);
301 set_property(GObject
*object
, guint prop_id
,
302 const GValue
*value
, GParamSpec
*pspec
)
307 dim
= (AdgDim
*) object
;
312 adg_dress_set(&data
->dress
, g_value_get_int(value
));
315 cpml_pair_copy(&data
->ref1
, (AdgPair
*) g_value_get_boxed(value
));
318 cpml_pair_copy(&data
->ref2
, (AdgPair
*) g_value_get_boxed(value
));
321 cpml_pair_copy(&data
->pos1
, (AdgPair
*) g_value_get_boxed(value
));
324 cpml_pair_copy(&data
->pos2
, (AdgPair
*) g_value_get_boxed(value
));
327 set_angle(dim
, g_value_get_double(value
));
330 data
->level
= g_value_get_double(value
);
333 data
->outside
= g_value_get_enum(value
);
336 set_value(dim
, g_value_get_string(value
));
339 set_value_min(dim
, g_value_get_string(value
));
342 set_value_max(dim
, g_value_get_string(value
));
345 set_note(dim
, g_value_get_string(value
));
348 G_OBJECT_WARN_INVALID_PROPERTY_ID(object
, prop_id
, pspec
);
358 * Gets the dimension dress to be used in rendering @dim.
360 * Returns: the current dimension dress
363 adg_dim_get_dress(AdgDim
*dim
)
367 g_return_val_if_fail(ADG_IS_DIM(dim
), ADG_DRESS_UNDEFINED
);
377 * @dress: the new #AdgDress to use
379 * Sets a new dimension dress to @dim. The new dress must be
380 * related to the original dress for this property: you cannot
381 * set a dress used for line styles to a dress managing fonts.
383 * The check is done by calling adg_dress_are_related() with
384 * @dress and the previous dress as arguments. Check out its
385 * documentation for details on what is a related dress.
388 adg_dim_set_dress(AdgDim
*dim
, AdgDress dress
)
392 g_return_if_fail(ADG_IS_DIM(dim
));
396 if (adg_dress_set(&data
->dress
, dress
))
397 g_object_notify((GObject
*) dim
, "dress");
404 * Gets the origin (org) coordinates. The returned pair is internally
405 * owned and must not be freed or modified. This function is only
406 * useful in new dimension implementations.
408 * Returns: the org coordinates
411 adg_dim_get_org(AdgDim
*dim
)
415 g_return_val_if_fail(ADG_IS_DIM(dim
), NULL
);
425 * @org: the org coordinates
428 * This function is only useful in new dimension implementations.
431 * Sets new org coordinates.
434 adg_dim_set_org(AdgDim
*dim
, const AdgPair
*org
)
438 g_return_if_fail(ADG_IS_DIM(dim
));
439 g_return_if_fail(org
!= NULL
);
446 * adg_dim_set_org_explicit:
448 * @org_x: x component of org
449 * @org_y: y component of org
452 * This function is only useful in new dimension implementations.
455 * Explicitely sets new org coordinates.
458 adg_dim_set_org_explicit(AdgDim
*dim
, gdouble org_x
, gdouble org_y
)
462 g_return_if_fail(ADG_IS_DIM(dim
));
473 * Gets the ref1 coordinates. The returned pair is internally owned
474 * and must not be freed or modified.
476 * Returns: the ref1 coordinates
479 adg_dim_get_ref1(AdgDim
*dim
)
483 g_return_val_if_fail(ADG_IS_DIM(dim
), NULL
);
494 * Gets the ref2 coordinates. The returned pair is internally owned
495 * and must not be freed or modified.
497 * Returns: the ref2 coordinates
500 adg_dim_get_ref2(AdgDim
*dim
)
504 g_return_val_if_fail(ADG_IS_DIM(dim
), NULL
);
514 * @ref1: the ref1 coordinates
515 * @ref2: the ref2 coordinates
517 * Shortcut to set ref1 and ref2 points at once.
520 adg_dim_set_ref(AdgDim
*dim
, const AdgPair
*ref1
, const AdgPair
*ref2
)
522 g_return_if_fail(ADG_IS_DIM(dim
));
524 if (ref1
!= NULL
|| ref2
!= NULL
) {
529 object
= (GObject
*) dim
;
531 g_object_freeze_notify(object
);
535 g_object_notify(object
, "ref1");
540 g_object_notify(object
, "ref2");
543 g_object_thaw_notify(object
);
548 * adg_dim_set_ref_explicit:
550 * @ref1_x: x component of pos1
551 * @ref1_y: y component of pos1
552 * @ref2_x: x component of pos2
553 * @ref2_y: y component of pos2
555 * Shortcut to set ref1 and ref2 points at once,
556 * using explicit coordinates.
559 adg_dim_set_ref_explicit(AdgDim
*dim
, gdouble ref1_x
, gdouble ref1_y
,
560 gdouble ref2_x
, gdouble ref2_y
)
570 adg_dim_set_ref(dim
, &ref1
, &ref2
);
577 * Gets the pos1 coordinates. The returned pair is internally owned
578 * and must not be freed or modified.
580 * Returns: the pos1 coordinates
583 adg_dim_get_pos1(AdgDim
*dim
)
587 g_return_val_if_fail(ADG_IS_DIM(dim
), NULL
);
598 * Gets the pos2 coordinates. The returned pair is internally owned
599 * and must not be freed or modified.
601 * Returns: the pos2 coordinates
604 adg_dim_get_pos2(AdgDim
*dim
)
608 g_return_val_if_fail(ADG_IS_DIM(dim
), NULL
);
618 * @pos1: the pos1 coordinates
619 * @pos2: the pos2 coordinates
621 * Shortcut to set pos1 and pos2 points at once.
624 adg_dim_set_pos(AdgDim
*dim
, AdgPair
*pos1
, AdgPair
*pos2
)
626 g_return_if_fail(ADG_IS_DIM(dim
));
628 if (pos1
!= NULL
|| pos2
!= NULL
) {
633 object
= (GObject
*) dim
;
635 g_object_freeze_notify(object
);
639 g_object_notify(object
, "pos1");
643 g_object_notify(object
, "pos2");
646 g_object_thaw_notify(object
);
651 * adg_dim_set_pos_explicit:
653 * @pos1_x: x component of pos1
654 * @pos1_y: y component of pos1
655 * @pos2_x: x component of pos2
656 * @pos2_y: y component of pos2
658 * Shortcut to set pos1 and pos2 points at once,
659 * using explicit coordinates.
662 adg_dim_set_pos_explicit(AdgDim
*dim
, gdouble pos1_x
, gdouble pos1_y
,
663 gdouble pos2_x
, gdouble pos2_y
)
673 adg_dim_set_pos(dim
, &pos1
, &pos2
);
681 * This function is only useful in new dimension implementations.
684 * Gets the dimension angle.
686 * Returns: the angle (in radians)
689 adg_dim_get_angle(AdgDim
*dim
)
693 g_return_val_if_fail(ADG_IS_DIM(dim
), 0);
703 * @angle: the new angle (in radians)
706 * This function is only useful in new dimension implementations.
709 * Sets a new dimension angle. The @angle could be modified by this
710 * function to fit in the current dimension style mode, so do not
711 * expect to get the same value with adg_dim_get_angle().
714 adg_dim_set_angle(AdgDim
*dim
, gdouble angle
)
716 g_return_if_fail(ADG_IS_DIM(dim
));
718 if (set_angle(dim
, angle
))
719 g_object_notify((GObject
*) dim
, "angle");
726 * Gets the level of this dimension.
728 * Returns: the level value
731 adg_dim_get_level(AdgDim
*dim
)
735 g_return_val_if_fail(ADG_IS_DIM(dim
), 0);
745 * @level: the new level
747 * Sets a new level for this dimension. The level is used to
748 * stack the quotes using a spacing value from dim_style
749 * (specified in global space).
752 adg_dim_set_level(AdgDim
*dim
, gdouble level
)
756 g_return_if_fail(ADG_IS_DIM(dim
));
761 g_object_notify((GObject
*) dim
, "level");
765 * adg_dim_get_outside:
768 * Gets the state of the #AdgDim:outside property: check the property
769 * documentation for further details.
771 * Returns: the current flag state
774 adg_dim_get_outside(AdgDim
*dim
)
778 g_return_val_if_fail(ADG_IS_DIM(dim
), ADG_THREE_STATE_UNKNOWN
);
782 return data
->outside
;
786 * adg_dim_set_outside:
788 * @outside: the new outside state
790 * Sets a new state for the #AdgDim:outside flag: check the property
791 * documentation for further details.
794 adg_dim_set_outside(AdgDim
*dim
, AdgThreeState outside
)
798 g_return_if_fail(ADG_IS_DIM(dim
));
801 data
->outside
= outside
;
803 g_object_notify((GObject
*) dim
, "outside");
810 * Gets the value text. The string is internally owned and
811 * must not be freed or modified.
813 * Returns: the value text
816 adg_dim_get_value(AdgDim
*dim
)
820 g_return_val_if_fail(ADG_IS_DIM(dim
), NULL
);
830 * @value: the value text
832 * Explicitely sets the text to use as value. If @value is %NULL or
833 * was never set, an automatic text is calculated using the format
834 * specified in the current #AdgDimStyle and getting its value by
835 * calling the default_value() virtual method.
838 adg_dim_set_value(AdgDim
*dim
, const gchar
*value
)
840 g_return_if_fail(ADG_IS_DIM(dim
));
842 if (set_value(dim
, value
))
843 g_object_notify((GObject
*) dim
, "value");
847 * adg_dim_get_value_min:
850 * Gets the minimum value text or %NULL on minimum value disabled.
851 * The string is internally owned and must not be freed or modified.
853 * Returns: the mimimum value text
856 adg_dim_get_value_min(AdgDim
*dim
)
860 g_return_val_if_fail(ADG_IS_DIM(dim
), NULL
);
864 return data
->value_min
;
868 * adg_dim_set_value_min:
870 * @value_min: the new minimum value
872 * Sets the minimum value. Use %NULL as @value_min to disable it.
875 adg_dim_set_value_min(AdgDim
*dim
, const gchar
*value_min
)
877 g_return_if_fail(ADG_IS_DIM(dim
));
879 if (set_value_min(dim
, value_min
))
880 g_object_notify((GObject
*) dim
, "value-min");
884 * adg_dim_get_value_max:
887 * Gets the maximum value text or %NULL on maximum value disabled.
888 * The string is internally owned and must not be freed or modified.
890 * Returns: the maximum value text
893 adg_dim_get_value_max(AdgDim
*dim
)
897 g_return_val_if_fail(ADG_IS_DIM(dim
), NULL
);
901 return data
->value_max
;
905 * adg_dim_set_value_max:
907 * @value_max: the new maximum value
909 * Sets the maximum value. Use %NULL as @value_max to disable it.
912 adg_dim_set_value_max(AdgDim
*dim
, const gchar
*value_max
)
914 g_return_if_fail(ADG_IS_DIM(dim
));
916 if (set_value_max(dim
, value_max
))
917 g_object_notify((GObject
*) dim
, "value-max");
921 * adg_dim_set_tolerances:
923 * @value_min: the new minumum value
924 * @value_max: the new maximum value
926 * Shortcut to set both the tolerances at once.
929 adg_dim_set_tolerances(AdgDim
*dim
,
930 const gchar
*value_min
, const gchar
*value_max
)
932 g_return_if_fail(ADG_IS_DIM(dim
));
934 g_object_freeze_notify((GObject
*) dim
);
935 adg_dim_set_value_min(dim
, value_min
);
936 adg_dim_set_value_max(dim
, value_max
);
937 g_object_thaw_notify((GObject
*) dim
);
944 * Gets the note text or %NULL if the note is not used. The string is
945 * internally owned and must not be freed or modified.
947 * Returns: the note text
950 adg_dim_get_note(AdgDim
*dim
)
954 g_return_val_if_fail(ADG_IS_DIM(dim
), NULL
);
964 * @note: the new note
966 * Sets a new note text, usually appended at the end of the dimension text.
969 adg_dim_set_note(AdgDim
*dim
, const gchar
*note
)
971 g_return_if_fail(ADG_IS_DIM(dim
));
973 if (set_note(dim
, note
))
974 g_object_notify((GObject
*) dim
, "note");
978 * adg_dim_render_quote:
979 * @dim: an #AdgDim object
980 * @cr: a #cairo_t drawing context
983 * This function is only useful in new dimension implementations.
986 * Renders the quote of @dim at the @org position.
989 adg_dim_render_quote(AdgDim
*dim
, cairo_t
*cr
)
992 AdgDimStyle
*dim_style
;
994 g_return_if_fail(ADG_IS_DIM(dim
));
997 dim_style
= (AdgDimStyle
*)
998 adg_entity_style((AdgEntity
*) dim
, data
->dress
);
1000 /* Check if the basic value text needs to be automatically generated */
1001 if (data
->value
== NULL
) {
1002 gchar
*text
= ADG_DIM_GET_CLASS(dim
)->default_value(dim
);
1003 adg_toy_text_set_label((AdgToyText
*) data
->value_entity
, text
);
1007 /* Set the internal toy_text dresses */
1008 adg_toy_text_set_dress((AdgToyText
*) data
->value_entity
,
1009 adg_dim_style_get_value_dress(dim_style
));
1010 adg_toy_text_set_dress((AdgToyText
*) data
->value_min_entity
,
1011 adg_dim_style_get_down_dress(dim_style
));
1012 adg_toy_text_set_dress((AdgToyText
*) data
->value_max_entity
,
1013 adg_dim_style_get_up_dress(dim_style
));
1014 adg_toy_text_set_dress((AdgToyText
*) data
->note_entity
,
1015 adg_dim_style_get_note_dress(dim_style
));
1017 ADG_DIM_GET_CLASS(dim
)->quote_layout(dim
, cr
);
1019 adg_entity_render(data
->value_entity
, cr
);
1020 adg_entity_render(data
->value_min_entity
, cr
);
1021 adg_entity_render(data
->value_max_entity
, cr
);
1022 adg_entity_render(data
->note_entity
, cr
);
1026 invalidate(AdgEntity
*entity
)
1028 AdgDimPrivate
*data
= ((AdgDim
*) entity
)->data
;
1030 adg_entity_invalidate(data
->value_entity
);
1031 adg_entity_invalidate(data
->value_min_entity
);
1032 adg_entity_invalidate(data
->value_max_entity
);
1033 adg_entity_invalidate(data
->note_entity
);
1039 default_value(AdgDim
*dim
)
1041 g_warning("AdgDim::default_value not implemented for `%s'",
1042 g_type_name(G_TYPE_FROM_INSTANCE(dim
)));
1043 return g_strdup("undef");
1047 quote_layout(AdgDim
*dim
, cairo_t
*cr
)
1050 AdgDimPrivate
*data
;
1051 AdgDimStyle
*dim_style
;
1052 cairo_text_extents_t extents
;
1054 const AdgPair
*shift
;
1056 entity
= (AdgEntity
*) dim
;
1058 dim_style
= (AdgDimStyle
*) adg_entity_style(entity
, data
->dress
);
1060 /* Initialize local maps to the origin */
1061 cairo_matrix_init_translate(&map
, data
->org
.x
, data
->org
.y
);
1063 adg_entity_set_local_map(data
->value_entity
, &map
);
1064 adg_entity_set_local_map(data
->value_min_entity
, &map
);
1065 adg_entity_set_local_map(data
->value_max_entity
, &map
);
1066 adg_entity_set_local_map(data
->note_entity
, &map
);
1068 /* Initialize global maps to the quote rotation angle */
1069 cairo_matrix_init_rotate(&map
, data
->angle
);
1071 adg_entity_set_global_map(data
->value_entity
, &map
);
1072 adg_entity_set_global_map(data
->value_min_entity
, &map
);
1073 adg_entity_set_global_map(data
->value_max_entity
, &map
);
1074 adg_entity_set_global_map(data
->note_entity
, &map
);
1077 adg_toy_text_get_extents((AdgToyText
*) data
->value_entity
, cr
, &extents
);
1079 /* Limit values (value_min and value_max) */
1080 if (data
->value_min
!= NULL
|| data
->value_max
!= NULL
) {
1081 cairo_text_extents_t min_extents
= { 0 };
1082 cairo_text_extents_t max_extents
= { 0 };
1083 gdouble spacing
= 0;
1086 if (data
->value_min
!= NULL
)
1087 adg_toy_text_get_extents((AdgToyText
*) data
->value_min_entity
,
1090 /* High tolerance */
1091 if (data
->value_max
!= NULL
)
1092 adg_toy_text_get_extents((AdgToyText
*) data
->value_max_entity
,
1095 shift
= adg_dim_style_get_tolerance_shift(dim_style
);
1096 if (data
->value_min
!= NULL
&& data
->value_max
!= NULL
)
1097 spacing
= adg_dim_style_get_tolerance_spacing(dim_style
);
1099 cairo_matrix_init_translate(&map
, extents
.width
+ shift
->x
,
1100 (spacing
+ min_extents
.height
+
1101 max_extents
.height
) / 2 +
1102 shift
->y
- extents
.height
/ 2);
1103 adg_entity_transform_global_map(data
->value_min_entity
, &map
);
1104 cairo_matrix_translate(&map
, 0, -min_extents
.height
- spacing
);
1105 adg_entity_transform_global_map(data
->value_max_entity
, &map
);
1107 extents
.width
+= shift
->x
+ MAX(min_extents
.width
, max_extents
.width
);
1111 if (data
->note
!= NULL
) {
1112 cairo_text_extents_t note_extents
;
1114 adg_toy_text_get_extents((AdgToyText
*) data
->note_entity
,
1116 shift
= adg_dim_style_get_note_shift(dim_style
);
1118 cairo_matrix_init_translate(&map
, extents
.width
+ shift
->x
, shift
->y
);
1119 adg_entity_transform_global_map(data
->note_entity
, &map
);
1121 extents
.width
+= shift
->x
+ note_extents
.width
;
1124 /* Center and apply the style displacements */
1125 shift
= adg_dim_style_get_quote_shift(dim_style
);
1126 cairo_matrix_init_translate(&map
, shift
->x
- extents
.width
/ 2, shift
->y
);
1128 adg_entity_transform_global_map(data
->value_entity
, &map
);
1129 adg_entity_transform_global_map(data
->value_min_entity
, &map
);
1130 adg_entity_transform_global_map(data
->value_max_entity
, &map
);
1131 adg_entity_transform_global_map(data
->note_entity
, &map
);
1135 set_angle(AdgDim
*dim
, gdouble angle
)
1137 AdgDimPrivate
*data
= dim
->data
;
1139 angle
= cpml_angle(angle
);
1140 if (angle
> G_PI_4
|| angle
<= -G_PI_4
* 3)
1141 angle
= cpml_angle(angle
+ G_PI
);
1143 if (angle
== data
->angle
)
1146 data
->angle
= angle
;
1152 set_value(AdgDim
*dim
, const gchar
*value
)
1154 AdgDimPrivate
*data
;
1158 if (adg_strcmp(value
, data
->value
) == 0)
1161 g_free(data
->value
);
1162 data
->value
= g_strdup(value
);
1163 adg_toy_text_set_label((AdgToyText
*) data
->value_entity
, value
);
1169 set_value_min(AdgDim
*dim
, const gchar
*value_min
)
1171 AdgDimPrivate
*data
= dim
->data
;
1173 if (adg_strcmp(value_min
, data
->value_min
) == 0)
1176 g_free(data
->value_min
);
1177 data
->value_min
= g_strdup(value_min
);
1178 adg_toy_text_set_label((AdgToyText
*) data
->value_min_entity
, value_min
);
1184 set_value_max(AdgDim
*dim
, const gchar
*value_max
)
1186 AdgDimPrivate
*data
= dim
->data
;
1188 if (adg_strcmp(value_max
, data
->value_max
) == 0)
1191 g_free(data
->value_max
);
1192 data
->value_max
= g_strdup(value_max
);
1193 adg_toy_text_set_label((AdgToyText
*) data
->value_max_entity
, value_max
);
1199 set_note(AdgDim
*dim
, const gchar
*note
)
1201 AdgDimPrivate
*data
= dim
->data
;
1203 if (adg_strcmp(note
, data
->note
) == 0)
1207 data
->note
= g_strdup(note
);
1208 adg_toy_text_set_label((AdgToyText
*) data
->note_entity
, note
);
1214 detach_entity(AdgEntity
**p_entity
)
1216 if (*p_entity
!= NULL
) {
1217 adg_entity_set_parent(*p_entity
, NULL
);
1218 g_object_unref(*p_entity
);