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 _adg_dispose (GObject
*object
);
64 static void _adg_finalize (GObject
*object
);
65 static void _adg_get_property (GObject
*object
,
69 static void _adg_set_property (GObject
*object
,
73 static void _adg_global_changed (AdgEntity
*entity
);
74 static void _adg_local_changed (AdgEntity
*entity
);
75 static void _adg_invalidate (AdgEntity
*entity
);
76 static void _adg_arrange (AdgEntity
*entity
);
77 static gchar
* _adg_default_value (AdgDim
*dim
);
78 static gdouble
_adg_quote_angle (gdouble angle
);
79 static gboolean
_adg_set_outside (AdgDim
*dim
,
80 AdgThreeState outside
);
81 static gboolean
_adg_set_detached (AdgDim
*dim
,
82 AdgThreeState detached
);
83 static gboolean
_adg_set_value (AdgDim
*dim
,
85 static gboolean
_adg_set_min (AdgDim
*dim
,
87 static gboolean
_adg_set_max (AdgDim
*dim
,
91 G_DEFINE_ABSTRACT_TYPE(AdgDim
, adg_dim
, ADG_TYPE_ENTITY
);
95 adg_dim_class_init(AdgDimClass
*klass
)
97 GObjectClass
*gobject_class
;
98 AdgEntityClass
*entity_class
;
101 gobject_class
= (GObjectClass
*) klass
;
102 entity_class
= (AdgEntityClass
*) klass
;
104 g_type_class_add_private(klass
, sizeof(AdgDimPrivate
));
106 gobject_class
->dispose
= _adg_dispose
;
107 gobject_class
->finalize
= _adg_finalize
;
108 gobject_class
->get_property
= _adg_get_property
;
109 gobject_class
->set_property
= _adg_set_property
;
111 entity_class
->global_changed
= _adg_global_changed
;
112 entity_class
->local_changed
= _adg_local_changed
;
113 entity_class
->invalidate
= _adg_invalidate
;
114 entity_class
->arrange
= _adg_arrange
;
116 klass
->quote_angle
= _adg_quote_angle
;
117 klass
->default_value
= _adg_default_value
;
119 param
= adg_param_spec_dress("dim-dress",
120 P_("Dimension Dress"),
121 P_("The dress to use for rendering this dimension"),
124 g_object_class_install_property(gobject_class
, PROP_DIM_DRESS
, param
);
126 param
= g_param_spec_boxed("ref1",
127 P_("First Reference"),
128 P_("First reference point of the dimension"),
131 g_object_class_install_property(gobject_class
, PROP_REF1
, param
);
133 param
= g_param_spec_boxed("ref2",
134 P_("Second Reference"),
135 P_("Second reference point of the dimension"),
138 g_object_class_install_property(gobject_class
, PROP_REF2
, param
);
140 param
= g_param_spec_boxed("pos",
142 P_("The reference position of the quote: it will be combined with \"level\" to get the real quote position"),
145 g_object_class_install_property(gobject_class
, PROP_POS
, param
);
147 param
= g_param_spec_double("level",
149 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"),
150 -G_MAXDOUBLE
, G_MAXDOUBLE
, 1.0,
152 g_object_class_install_property(gobject_class
, PROP_LEVEL
, param
);
154 param
= g_param_spec_enum("outside",
156 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"),
157 ADG_TYPE_THREE_STATE
, ADG_THREE_STATE_UNKNOWN
,
159 g_object_class_install_property(gobject_class
, PROP_OUTSIDE
, param
);
161 param
= g_param_spec_enum("detached",
162 P_("Detached Quote"),
163 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"),
164 ADG_TYPE_THREE_STATE
, ADG_THREE_STATE_UNKNOWN
,
166 g_object_class_install_property(gobject_class
, PROP_DETACHED
, param
);
168 param
= g_param_spec_string("value",
170 P_("The theoretically exact value for this quote: set to NULL to automatically get the default value"),
173 g_object_class_install_property(gobject_class
, PROP_VALUE
, param
);
175 param
= g_param_spec_string("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"),
180 g_object_class_install_property(gobject_class
, PROP_MIN
, param
);
182 param
= g_param_spec_string("max",
183 P_("Maximum Value or High Tolerance"),
184 P_("The maximum value allowed or the highest tolerance from value (depending of the dimension style): set to NULL to suppress"),
187 g_object_class_install_property(gobject_class
, PROP_MAX
, param
);
191 adg_dim_init(AdgDim
*dim
)
193 AdgDimPrivate
*data
= G_TYPE_INSTANCE_GET_PRIVATE(dim
, ADG_TYPE_DIM
,
196 data
->dim_dress
= ADG_DRESS_DIMENSION
;
201 data
->outside
= ADG_THREE_STATE_UNKNOWN
;
202 data
->detached
= ADG_THREE_STATE_UNKNOWN
;
211 _adg_dispose(GObject
*object
)
213 AdgDimPrivate
*data
= ((AdgDim
*) object
)->data
;
215 if (data
->quote
.entity
!= NULL
) {
216 g_object_unref(data
->quote
.entity
);
217 data
->quote
.entity
= NULL
;
219 if (data
->ref1
!= NULL
) {
220 adg_point_destroy(data
->ref1
);
223 if (data
->ref2
!= NULL
) {
224 adg_point_destroy(data
->ref2
);
227 if (data
->pos
!= NULL
) {
228 adg_point_destroy(data
->pos
);
232 if (PARENT_OBJECT_CLASS
->dispose
)
233 PARENT_OBJECT_CLASS
->dispose(object
);
237 _adg_finalize(GObject
*object
)
239 AdgDimPrivate
*data
= ((AdgDim
*) object
)->data
;
245 if (PARENT_OBJECT_CLASS
->finalize
)
246 PARENT_OBJECT_CLASS
->finalize(object
);
250 _adg_get_property(GObject
*object
, guint prop_id
,
251 GValue
*value
, GParamSpec
*pspec
)
253 AdgDimPrivate
*data
= ((AdgDim
*) object
)->data
;
257 g_value_set_int(value
, data
->dim_dress
);
260 g_value_set_boxed(value
, data
->ref1
);
263 g_value_set_boxed(value
, data
->ref2
);
266 g_value_set_boxed(value
, data
->pos
);
269 g_value_set_double(value
, data
->level
);
272 g_value_set_enum(value
, data
->outside
);
275 g_value_set_enum(value
, data
->detached
);
278 g_value_set_string(value
, data
->value
);
281 g_value_set_string(value
, data
->min
);
284 g_value_set_string(value
, data
->max
);
287 G_OBJECT_WARN_INVALID_PROPERTY_ID(object
, prop_id
, pspec
);
293 _adg_set_property(GObject
*object
, guint prop_id
,
294 const GValue
*value
, GParamSpec
*pspec
)
299 dim
= (AdgDim
*) object
;
304 data
->dim_dress
= g_value_get_int(value
);
307 adg_point_set(&data
->ref1
, g_value_get_boxed(value
));
310 adg_point_set(&data
->ref2
, g_value_get_boxed(value
));
313 adg_point_set(&data
->pos
, g_value_get_boxed(value
));
316 data
->level
= g_value_get_double(value
);
319 _adg_set_outside(dim
, g_value_get_enum(value
));
322 _adg_set_detached(dim
, g_value_get_enum(value
));
325 _adg_set_value(dim
, g_value_get_string(value
));
328 _adg_set_min(dim
, g_value_get_string(value
));
331 _adg_set_max(dim
, g_value_get_string(value
));
334 G_OBJECT_WARN_INVALID_PROPERTY_ID(object
, prop_id
, pspec
);
341 * adg_dim_set_dim_dress:
343 * @dress: the new #AdgDress to use
345 * Sets a new dimension dress to @dim. The new dress must be
346 * related to the original dress for this property: you cannot
347 * set a dress used for line styles to a dress managing fonts.
349 * The check is done by calling adg_dress_are_related() with
350 * @dress and the previous dress as arguments. Check out its
351 * documentation for details on what is a related dress.
354 adg_dim_set_dim_dress(AdgDim
*dim
, AdgDress dress
)
356 g_return_if_fail(ADG_IS_DIM(dim
));
357 g_object_set((GObject
*) dim
, "dim-dress", dress
, NULL
);
361 * adg_dim_get_dim_dress:
364 * Gets the dimension dress to be used in rendering @dim.
366 * Returns: the current dimension dress
369 adg_dim_get_dim_dress(AdgDim
*dim
)
373 g_return_val_if_fail(ADG_IS_DIM(dim
), ADG_DRESS_UNDEFINED
);
377 return data
->dim_dress
;
383 * @ref1: the new point to use as first reference
385 * Sets the #AdgDim:ref1 property to @ref1. The old point
386 * is silently discarded, unreferencing its model if that
387 * point was bound to a named pair (hence, possibly destroying
388 * the model if this was the last reference).
390 * @ref1 can be %NULL, in which case the point is unset.
393 adg_dim_set_ref1(AdgDim
*dim
, const AdgPoint
*ref1
)
397 g_return_if_fail(ADG_IS_DIM(dim
));
401 if (adg_point_set(&data
->ref1
, ref1
))
402 g_object_notify((GObject
*) dim
, "ref1");
406 * adg_dim_set_ref1_explicit:
408 * @x: x coordinate of the first reference point
409 * @y: y coordinate of the first reference point
411 * Sets the #AdgDim:ref1 property to the (@x, @y) explicit
412 * coordinates. The old point is silently discarded,
413 * unreferencing its model if that point was bound to a named
414 * pair (hence, possibly destroying the model if this was the
418 adg_dim_set_ref1_explicit(AdgDim
*dim
, gdouble x
, gdouble y
)
420 AdgPoint
*point
= adg_point_new();
422 adg_point_set_pair_explicit(point
, x
, y
);
423 adg_dim_set_ref1(dim
, point
);
425 adg_point_destroy(point
);
429 * adg_dim_set_ref1_from_pair:
431 * @ref1: the coordinates pair of the first reference point
433 * Convenient function to set the #AdgDim:ref1 property using a
434 * pair instead of explicit coordinates.
437 adg_dim_set_ref1_from_pair(AdgDim
*dim
, const AdgPair
*ref1
)
439 g_return_if_fail(ref1
!= NULL
);
441 adg_dim_set_ref1_explicit(dim
, ref1
->x
, ref1
->y
);
445 * adg_dim_set_ref1_from_model:
447 * @model: the source #AdgModel
448 * @ref1: a named pair in @model
450 * Binds #AdgDim:ref1 to the @ref1 named pair of @model. If @model
451 * is %NULL, the point will be unset. In any case, the old point
452 * is silently discarded, unreferencing its model if that point
453 * was bound to a named pair (hence, possibly destroying the model
454 * if this was the last reference).
456 * The assignment is lazy so @ref1 could be not be present in @model.
457 * Anyway, at the first access to this point an error will be raised
458 * if the named pair is still missing.
461 adg_dim_set_ref1_from_model(AdgDim
*dim
, AdgModel
*model
, const gchar
*ref1
)
463 AdgPoint
*point
= adg_point_new();
465 adg_point_set_pair_from_model(point
, model
, ref1
);
466 adg_dim_set_ref1(dim
, point
);
468 adg_point_destroy(point
);
475 * Gets the #AdgDim:ref1 point. The returned point is internally owned
476 * and must not be freed or modified. Anyway, it is not const because
477 * adg_point_get_pair() must be able to modify the internal cache of
478 * the returned point.
480 * Returns: the first reference point
483 adg_dim_get_ref1(AdgDim
*dim
)
487 g_return_val_if_fail(ADG_IS_DIM(dim
), NULL
);
497 * @ref2: the new point to use as second reference
499 * Sets the #AdgDim:ref2 property to @ref2. The old point
500 * is silently discarded, unreferencing its model if that
501 * point was bound to a named pair (hence, possibly destroying
502 * the model if it was the last reference).
504 * @ref2 can be %NULL, in which case the point is unset.
507 adg_dim_set_ref2(AdgDim
*dim
, const AdgPoint
*ref2
)
511 g_return_if_fail(ADG_IS_DIM(dim
));
515 if (adg_point_set(&data
->ref2
, ref2
))
516 g_object_notify((GObject
*) dim
, "ref2");
520 * adg_dim_set_ref2_explicit:
522 * @x: x coordinate of the second reference point
523 * @y: y coordinate of the second reference point
525 * Sets the #AdgDim:ref2 property to the (@x, @y) explicit
526 * coordinates. The old point is silently discarded,
527 * unreferencing its model if that point was bound to a named
528 * pair (hence, possibly destroying the model if this was the
532 adg_dim_set_ref2_explicit(AdgDim
*dim
, gdouble x
, gdouble y
)
534 AdgPoint
*point
= adg_point_new();
536 adg_point_set_pair_explicit(point
, x
, y
);
537 adg_dim_set_ref2(dim
, point
);
539 adg_point_destroy(point
);
543 * adg_dim_set_ref2_from_pair:
545 * @ref2: the coordinates pair of the second reference point
547 * Convenient function to set the #AdgDim:ref2 property using a
548 * pair instead of explicit coordinates.
551 adg_dim_set_ref2_from_pair(AdgDim
*dim
, const AdgPair
*ref2
)
553 g_return_if_fail(ref2
!= NULL
);
555 adg_dim_set_ref2_explicit(dim
, ref2
->x
, ref2
->y
);
559 * adg_dim_set_ref2_from_model:
561 * @model: the source #AdgModel
562 * @ref2: a named pair in @model
564 * Binds #AdgDim:ref2 to the @ref2 named pair of @model. If @model
565 * is %NULL, the point will be unset. In any case, the old point
566 * is silently discarded, unreferencing its model if that point
567 * was bound to a named pair (hence, possibly destroying the model
568 * if this was the last reference).
570 * The assignment is lazy so @ref2 could be not be present in @model.
571 * Anyway, at the first access to this point an error will be raised
572 * if the named pair is still missing.
575 adg_dim_set_ref2_from_model(AdgDim
*dim
, AdgModel
*model
, const gchar
*ref2
)
577 AdgPoint
*point
= adg_point_new();
579 adg_point_set_pair_from_model(point
, model
, ref2
);
580 adg_dim_set_ref2(dim
, point
);
582 adg_point_destroy(point
);
589 * Gets the #AdgDim:ref2 point. The returned point is internally owned
590 * and must not be freed or modified. Anyway, it is not const because
591 * adg_point_get_pair() must be able to modify the internal cache of
592 * the returned point.
594 * Returns: the second reference point
597 adg_dim_get_ref2(AdgDim
*dim
)
601 g_return_val_if_fail(ADG_IS_DIM(dim
), NULL
);
611 * @pos: the new point to use as position
613 * Sets the #AdgDim:pos property to @pos. The old point
614 * is silently discarded, unreferencing its model if that
615 * point was bound to a named pair (hence, possibly destroying
616 * the model if it was the last reference).
618 * @pos can be %NULL, in which case the point is unset.
621 adg_dim_set_pos(AdgDim
*dim
, const AdgPoint
*pos
)
625 g_return_if_fail(ADG_IS_DIM(dim
));
629 if (adg_point_set(&data
->pos
, pos
))
630 g_object_notify((GObject
*) dim
, "pos");
634 * adg_dim_set_pos_explicit:
636 * @x: x coordinate of the position
637 * @y: y coordinate of the position
639 * Sets the #AdgDim:pos property to the (@x, @y) explicit
640 * coordinates. The old point is silently discarded,
641 * unreferencing its model if that point was bound to a named
642 * pair (hence, possibly destroying the model if this was the
646 adg_dim_set_pos_explicit(AdgDim
*dim
, gdouble x
, gdouble y
)
648 AdgPoint
*point
= adg_point_new();
650 adg_point_set_pair_explicit(point
, x
, y
);
651 adg_dim_set_pos(dim
, point
);
653 adg_point_destroy(point
);
657 * adg_dim_set_pos_from_pair:
659 * @pos: the coordinates pair of the position point
661 * Convenient function to set the #AdgDim:pos property using a
662 * pair instead of explicit coordinates.
665 adg_dim_set_pos_from_pair(AdgDim
*dim
, const AdgPair
*pos
)
667 g_return_if_fail(pos
!= NULL
);
669 adg_dim_set_pos_explicit(dim
, pos
->x
, pos
->y
);
673 * adg_dim_set_pos_from_model:
675 * @model: the source #AdgModel
676 * @pos: a named pair in @model
678 * Binds #AdgDim:pos to the @pos named pair of @model. If @model
679 * is %NULL, the point will be unset. In any case, the old point
680 * is silently discarded, unreferencing its model if that point
681 * was bound to a named pair (hence, possibly destroying the model
682 * if this was the last reference).
684 * The assignment is lazy so @pos could be not be present in @model.
685 * Anyway, at the first access to this point an error will be raised
686 * if the named pair is still missing.
689 adg_dim_set_pos_from_model(AdgDim
*dim
, AdgModel
*model
, const gchar
*pos
)
691 AdgPoint
*point
= adg_point_new();
693 adg_point_set_pair_from_model(point
, model
, pos
);
694 adg_dim_set_pos(dim
, point
);
696 adg_point_destroy(point
);
703 * Gets the #AdgDim:pos point. The returned point is internally owned
704 * and must not be freed or modified. Anyway, it is not const because
705 * adg_point_get_pair() must be able to modify the internal cache of
706 * the returned point.
708 * Returns: the position point
711 adg_dim_get_pos(AdgDim
*dim
)
715 g_return_val_if_fail(ADG_IS_DIM(dim
), NULL
);
725 * @level: the new level
727 * Sets a new level for this dimension. The level is used to
728 * stack the quotes using a spacing value from dim_style
729 * (specified in global space).
732 adg_dim_set_level(AdgDim
*dim
, gdouble level
)
736 g_return_if_fail(ADG_IS_DIM(dim
));
741 g_object_notify((GObject
*) dim
, "level");
748 * Gets the level of this dimension.
750 * Returns: the level value
753 adg_dim_get_level(AdgDim
*dim
)
757 g_return_val_if_fail(ADG_IS_DIM(dim
), 0);
765 * adg_dim_set_outside:
767 * @outside: the new outside state
769 * Sets a new state for the #AdgDim:outside flag: check the property
770 * documentation for further details.
773 adg_dim_set_outside(AdgDim
*dim
, AdgThreeState outside
)
775 g_return_if_fail(ADG_IS_DIM(dim
));
777 if (_adg_set_outside(dim
, outside
))
778 g_object_notify((GObject
*) dim
, "outside");
782 * adg_dim_get_outside:
785 * Gets the state of the #AdgDim:outside property: check the property
786 * documentation for further details.
788 * Returns: the current flag state
791 adg_dim_get_outside(AdgDim
*dim
)
795 g_return_val_if_fail(ADG_IS_DIM(dim
), ADG_THREE_STATE_UNKNOWN
);
799 return data
->outside
;
803 * adg_dim_set_detached:
805 * @detached: the new detached state
807 * Sets a new state for the #AdgDim:detached flag: check the property
808 * documentation for further details.
810 * This is used only by dimensions where detaching has meaning.
811 * In some cases, such as with #AdgRDim dimensions, this property is
815 adg_dim_set_detached(AdgDim
*dim
, AdgThreeState detached
)
817 g_return_if_fail(ADG_IS_DIM(dim
));
819 if (_adg_set_detached(dim
, detached
))
820 g_object_notify((GObject
*) dim
, "detached");
824 * adg_dim_get_detached:
827 * Gets the state of the #AdgDim:detached property: check the property
828 * documentation for further details.
830 * Returns: the current flag state
833 adg_dim_get_detached(AdgDim
*dim
)
837 g_return_val_if_fail(ADG_IS_DIM(dim
), ADG_THREE_STATE_UNKNOWN
);
841 return data
->detached
;
847 * @value: the value text
849 * Explicitely sets the text to use as value. If @value is %NULL or
850 * was never set, an automatic text is calculated using the format
851 * specified in the current #AdgDimStyle and getting its value by
852 * calling the default_value() virtual method.
855 adg_dim_set_value(AdgDim
*dim
, const gchar
*value
)
857 g_return_if_fail(ADG_IS_DIM(dim
));
859 if (_adg_set_value(dim
, value
))
860 g_object_notify((GObject
*) dim
, "value");
867 * Gets the value text. The string is internally owned and
868 * must not be freed or modified.
870 * Returns: the value text
873 adg_dim_get_value(AdgDim
*dim
)
877 g_return_val_if_fail(ADG_IS_DIM(dim
), NULL
);
885 * adg_dim_set_limits:
887 * @min: the new minumum value
888 * @max: the new maximum value
890 * Shortcut to set both the limits at once.
893 adg_dim_set_limits(AdgDim
*dim
, const gchar
*min
, const gchar
*max
)
895 g_return_if_fail(ADG_IS_DIM(dim
));
897 g_object_freeze_notify((GObject
*) dim
);
898 adg_dim_set_min(dim
, min
);
899 adg_dim_set_max(dim
, max
);
900 g_object_thaw_notify((GObject
*) dim
);
906 * @min: the new minimum limit
908 * Sets the minimum value. Use %NULL as @min to disable it.
911 adg_dim_set_min(AdgDim
*dim
, const gchar
*min
)
913 g_return_if_fail(ADG_IS_DIM(dim
));
915 if (_adg_set_min(dim
, min
))
916 g_object_notify((GObject
*) dim
, "min");
923 * Gets the minimum value text or %NULL on minimum value disabled.
924 * The string is internally owned and must not be freed or modified.
926 * Returns: the mimimum value text
929 adg_dim_get_min(AdgDim
*dim
)
933 g_return_val_if_fail(ADG_IS_DIM(dim
), NULL
);
943 * @max: the new maximum value
945 * Sets the maximum value. Use %NULL as @max to disable it.
948 adg_dim_set_max(AdgDim
*dim
, const gchar
*max
)
950 g_return_if_fail(ADG_IS_DIM(dim
));
952 if (_adg_set_max(dim
, max
))
953 g_object_notify((GObject
*) dim
, "max");
960 * Gets the maximum value text or %NULL on maximum value disabled.
961 * The string is internally owned and must not be freed or modified.
963 * Returns: the maximum value text
966 adg_dim_get_max(AdgDim
*dim
)
970 g_return_val_if_fail(ADG_IS_DIM(dim
), NULL
);
982 * This function is only useful in new dimension implementations.
985 * Gets the quote entity, if any. This function is valid only after
986 * the #AdgDim implementation of the arrange() virtual method has
989 * Returns: the quote entity
992 adg_dim_get_quote(AdgDim
*dim
)
996 g_return_val_if_fail(ADG_IS_DIM(dim
), NULL
);
1000 return data
->quote
.entity
;
1004 * adg_dim_quote_angle:
1006 * @angle: an angle (in radians)
1009 * This function is only useful in new dimension implementations.
1012 * Converts @angle accordling to the style of @dim. Any quote angle
1013 * should be validated by this method because every dimensioning
1014 * style has its own convention regardling the text rotation.
1016 * Returns: the angle to use (always in radians)
1019 adg_dim_quote_angle(AdgDim
*dim
, gdouble angle
)
1023 g_return_val_if_fail(ADG_IS_DIM(dim
), angle
);
1025 klass
= ADG_DIM_GET_CLASS(dim
);
1027 if (klass
->quote_angle
== NULL
)
1030 return klass
->quote_angle(angle
);
1035 _adg_global_changed(AdgEntity
*entity
)
1037 AdgDimPrivate
*data
= ((AdgDim
*) entity
)->data
;
1039 if (PARENT_ENTITY_CLASS
->global_changed
)
1040 PARENT_ENTITY_CLASS
->global_changed(entity
);
1042 if (data
->quote
.entity
!= NULL
)
1043 adg_entity_global_changed((AdgEntity
*) data
->quote
.entity
);
1047 _adg_local_changed(AdgEntity
*entity
)
1049 AdgDimPrivate
*data
= ((AdgDim
*) entity
)->data
;
1051 if (PARENT_ENTITY_CLASS
->local_changed
)
1052 PARENT_ENTITY_CLASS
->local_changed(entity
);
1054 if (data
->quote
.entity
!= NULL
)
1055 adg_entity_local_changed((AdgEntity
*) data
->quote
.entity
);
1059 _adg_invalidate(AdgEntity
*entity
)
1061 AdgDimPrivate
*data
= ((AdgDim
*) entity
)->data
;
1063 if (PARENT_ENTITY_CLASS
->invalidate
)
1064 PARENT_ENTITY_CLASS
->invalidate(entity
);
1066 if (data
->quote
.entity
!= NULL
)
1067 adg_entity_invalidate((AdgEntity
*) data
->quote
.entity
);
1069 adg_point_invalidate(data
->ref1
);
1070 adg_point_invalidate(data
->ref2
);
1071 adg_point_invalidate(data
->pos
);
1075 _adg_arrange(AdgEntity
*entity
)
1078 AdgDimPrivate
*data
;
1079 AdgEntity
*quote_entity
;
1080 AdgContainer
*quote_container
;
1081 AdgEntity
*value_entity
;
1082 AdgEntity
*min_entity
;
1083 AdgEntity
*max_entity
;
1084 const AdgPair
*shift
;
1087 dim
= (AdgDim
*) entity
;
1090 /* Resolve the dim style */
1091 if (data
->dim_style
== NULL
)
1092 data
->dim_style
= (AdgDimStyle
*)
1093 adg_entity_style(entity
, data
->dim_dress
);
1095 if (data
->quote
.entity
== NULL
)
1096 data
->quote
.entity
= g_object_new(ADG_TYPE_ALIGNMENT
,
1097 "local-method", ADG_MIX_NONE
,
1098 "parent", dim
, NULL
);
1100 quote_entity
= (AdgEntity
*) data
->quote
.entity
;
1101 quote_container
= (AdgContainer
*) data
->quote
.entity
;
1103 if (data
->quote
.value
== NULL
) {
1104 AdgDress dress
= adg_dim_style_get_value_dress(data
->dim_style
);
1106 data
->quote
.value
= g_object_new(ADG_TYPE_TOY_TEXT
,
1107 "local-method", ADG_MIX_PARENT
,
1108 "font-dress", dress
, NULL
);
1110 adg_container_add(quote_container
, (AdgEntity
*) data
->quote
.value
);
1113 adg_toy_text_set_label(data
->quote
.value
, data
->value
);
1115 AdgDimClass
*klass
= ADG_DIM_GET_CLASS(dim
);
1117 if (klass
->default_value
) {
1118 /* Automatically generate the value text */
1119 gchar
*text
= klass
->default_value(dim
);
1120 adg_toy_text_set_label(data
->quote
.value
, text
);
1126 if (data
->quote
.min
== NULL
&& data
->min
!= NULL
) {
1127 AdgDress dress
= adg_dim_style_get_min_dress(data
->dim_style
);
1129 data
->quote
.min
= g_object_new(ADG_TYPE_TOY_TEXT
,
1130 "local-method", ADG_MIX_PARENT
,
1131 "font-dress", dress
, NULL
);
1133 adg_container_add(quote_container
, (AdgEntity
*) data
->quote
.min
);
1134 adg_toy_text_set_label(data
->quote
.min
, data
->min
);
1137 if (data
->quote
.max
== NULL
&& data
->max
!= NULL
) {
1138 AdgDress dress
= adg_dim_style_get_max_dress(data
->dim_style
);
1140 data
->quote
.max
= g_object_new(ADG_TYPE_TOY_TEXT
,
1141 "local-method", ADG_MIX_PARENT
,
1142 "font-dress", dress
, NULL
);
1144 adg_container_add(quote_container
, (AdgEntity
*) data
->quote
.max
);
1145 adg_toy_text_set_label(data
->quote
.max
, data
->max
);
1148 value_entity
= (AdgEntity
*) data
->quote
.value
;
1149 min_entity
= (AdgEntity
*) data
->quote
.min
;
1150 max_entity
= (AdgEntity
*) data
->quote
.max
;
1151 shift
= adg_dim_style_get_quote_shift(data
->dim_style
);
1153 adg_entity_set_global_map(quote_entity
, adg_matrix_identity());
1154 adg_entity_global_changed(quote_entity
);
1156 cairo_matrix_init_translate(&map
, shift
->x
, shift
->y
);
1157 adg_entity_set_global_map(value_entity
, &map
);
1158 adg_entity_arrange(value_entity
);
1160 /* Limit values (min and max) */
1161 if (min_entity
!= NULL
|| max_entity
!= NULL
) {
1162 const CpmlExtents
*extents
= adg_entity_get_extents(value_entity
);
1163 //CpmlExtents min_extents = { 0 };
1164 //CpmlExtents max_extents = { 0 };
1165 const AdgPair
*limits_shift
= adg_dim_style_get_limits_shift(data
->dim_style
);
1168 if (min_entity
!= NULL
)
1169 cpml_extents_copy(&min_extents
, adg_entity_get_extents(min_entity
));
1171 if (max_entity
!= NULL
)
1172 cpml_extents_copy(&max_extents
, adg_entity_get_extents(max_entity
));
1174 if (min_entity
!= NULL
&& max_entity
!= NULL
)
1175 spacing
= adg_dim_style_get_limits_spacing(data
->dim_style
);
1177 cairo_matrix_init_translate(&map
,
1179 shift
->x
+ limit_shift
->x
,
1180 (spacing
+ min_extents
.size
.y
+
1181 max_extents
.size
.y
- extents
->size
.y
) / 2 +
1182 shift
->y
+ limit_shift
->y
);
1184 cairo_matrix_init_translate(&map
, extents
->size
.x
+ limits_shift
->x
,
1185 -extents
->size
.y
/ 2 + limits_shift
->y
);
1187 if (min_entity
!= NULL
) {
1188 adg_entity_set_global_map(min_entity
, &map
);
1189 adg_entity_arrange(min_entity
);
1190 extents
= adg_entity_get_extents(min_entity
);
1191 map
.y0
-= extents
->size
.y
+
1192 adg_dim_style_get_limits_spacing(data
->dim_style
);
1195 if (max_entity
!= NULL
) {
1196 adg_entity_set_global_map(max_entity
, &map
);
1197 adg_entity_arrange(max_entity
);
1201 adg_entity_arrange(quote_entity
);
1205 _adg_default_value(AdgDim
*dim
)
1207 g_warning("AdgDim::default_value not implemented for `%s'",
1208 g_type_name(G_TYPE_FROM_INSTANCE(dim
)));
1209 return g_strdup("undef");
1213 _adg_quote_angle(gdouble angle
)
1215 angle
= cpml_angle(angle
);
1217 if (angle
> G_PI_4
* 4 / 3 || angle
<= -G_PI_4
* 3)
1218 angle
= cpml_angle(angle
+ G_PI
);
1224 _adg_set_outside(AdgDim
*dim
, AdgThreeState outside
)
1226 AdgDimPrivate
*data
;
1228 g_return_val_if_fail(adg_is_enum_value(outside
, ADG_TYPE_THREE_STATE
),
1233 if (data
->outside
== outside
)
1236 data
->outside
= outside
;
1242 _adg_set_detached(AdgDim
*dim
, AdgThreeState detached
)
1244 AdgDimPrivate
*data
;
1246 g_return_val_if_fail(adg_is_enum_value(detached
, ADG_TYPE_THREE_STATE
),
1251 if (data
->detached
== detached
)
1254 data
->detached
= detached
;
1260 _adg_set_value(AdgDim
*dim
, const gchar
*value
)
1262 AdgDimPrivate
*data
;
1266 if (g_strcmp0(value
, data
->value
) == 0)
1269 g_free(data
->value
);
1270 data
->value
= g_strdup(value
);
1272 if (data
->quote
.value
!= NULL
) {
1273 g_object_unref(data
->quote
.value
);
1274 data
->quote
.value
= NULL
;
1281 _adg_set_min(AdgDim
*dim
, const gchar
*min
)
1283 AdgDimPrivate
*data
= dim
->data
;
1285 if (g_strcmp0(min
, data
->min
) == 0)
1289 data
->min
= g_strdup(min
);
1291 if (data
->quote
.min
!= NULL
) {
1292 g_object_unref(data
->quote
.min
);
1293 data
->quote
.min
= NULL
;
1300 _adg_set_max(AdgDim
*dim
, const gchar
*max
)
1302 AdgDimPrivate
*data
= dim
->data
;
1304 if (g_strcmp0(max
, data
->max
) == 0)
1308 data
->max
= g_strdup(max
);
1310 if (data
->quote
.max
!= NULL
) {
1311 g_object_unref(data
->quote
.max
);
1312 data
->quote
.max
= NULL
;