1 /* ADG - Automatic Drawing Generation
2 * Copyright (C) 2007,2008,2009,2010,2011 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"
37 #include "adg-container.h"
38 #include "adg-alignment.h"
39 #include "adg-textual.h"
40 #include "adg-toy-text.h"
42 #include "adg-model.h"
43 #include "adg-trail.h"
44 #include "adg-point.h"
45 #include "adg-marker.h"
46 #include "adg-style.h"
47 #include "adg-dim-style.h"
48 #include "adg-dress.h"
49 #include "adg-dress-builtins.h"
52 #include "adg-dim-private.h"
56 #define _ADG_OLD_OBJECT_CLASS ((GObjectClass *) adg_dim_parent_class)
57 #define _ADG_OLD_ENTITY_CLASS ((AdgEntityClass *) adg_dim_parent_class)
60 G_DEFINE_ABSTRACT_TYPE(AdgDim
, adg_dim
, ADG_TYPE_ENTITY
)
77 static void _adg_dispose (GObject
*object
);
78 static void _adg_finalize (GObject
*object
);
79 static void _adg_get_property (GObject
*object
,
83 static void _adg_set_property (GObject
*object
,
87 static void _adg_global_changed (AdgEntity
*entity
);
88 static void _adg_local_changed (AdgEntity
*entity
);
89 static void _adg_invalidate (AdgEntity
*entity
);
90 static void _adg_arrange (AdgEntity
*entity
);
91 static gchar
* _adg_default_value (AdgDim
*dim
);
92 static gdouble
_adg_quote_angle (gdouble angle
);
93 static gboolean
_adg_set_outside (AdgDim
*dim
,
94 AdgThreeState outside
);
95 static gboolean
_adg_set_detached (AdgDim
*dim
,
96 AdgThreeState detached
);
97 static gboolean
_adg_set_value (AdgDim
*dim
,
99 static gboolean
_adg_set_min (AdgDim
*dim
,
101 static gboolean
_adg_set_max (AdgDim
*dim
,
106 adg_dim_class_init(AdgDimClass
*klass
)
108 GObjectClass
*gobject_class
;
109 AdgEntityClass
*entity_class
;
112 gobject_class
= (GObjectClass
*) klass
;
113 entity_class
= (AdgEntityClass
*) klass
;
115 g_type_class_add_private(klass
, sizeof(AdgDimPrivate
));
117 gobject_class
->dispose
= _adg_dispose
;
118 gobject_class
->finalize
= _adg_finalize
;
119 gobject_class
->get_property
= _adg_get_property
;
120 gobject_class
->set_property
= _adg_set_property
;
122 entity_class
->global_changed
= _adg_global_changed
;
123 entity_class
->local_changed
= _adg_local_changed
;
124 entity_class
->invalidate
= _adg_invalidate
;
125 entity_class
->arrange
= _adg_arrange
;
127 klass
->quote_angle
= _adg_quote_angle
;
128 klass
->default_value
= _adg_default_value
;
130 param
= adg_param_spec_dress("dim-dress",
131 P_("Dimension Dress"),
132 P_("The dress to use for rendering this dimension"),
135 g_object_class_install_property(gobject_class
, PROP_DIM_DRESS
, param
);
137 param
= g_param_spec_boxed("ref1",
138 P_("First Reference"),
139 P_("First reference point of the dimension"),
142 g_object_class_install_property(gobject_class
, PROP_REF1
, param
);
144 param
= g_param_spec_boxed("ref2",
145 P_("Second Reference"),
146 P_("Second reference point of the dimension"),
149 g_object_class_install_property(gobject_class
, PROP_REF2
, param
);
151 param
= g_param_spec_boxed("pos",
153 P_("The reference position of the quote: it will be combined with \"level\" to get the real quote position"),
156 g_object_class_install_property(gobject_class
, PROP_POS
, param
);
158 param
= g_param_spec_double("level",
160 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"),
161 -G_MAXDOUBLE
, G_MAXDOUBLE
, 1.0,
163 g_object_class_install_property(gobject_class
, PROP_LEVEL
, param
);
165 param
= g_param_spec_enum("outside",
167 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"),
168 ADG_TYPE_THREE_STATE
, ADG_THREE_STATE_UNKNOWN
,
170 g_object_class_install_property(gobject_class
, PROP_OUTSIDE
, param
);
172 param
= g_param_spec_enum("detached",
173 P_("Detached Quote"),
174 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"),
175 ADG_TYPE_THREE_STATE
, ADG_THREE_STATE_UNKNOWN
,
177 g_object_class_install_property(gobject_class
, PROP_DETACHED
, param
);
179 param
= g_param_spec_string("value",
180 P_("Value Template"),
181 P_("The template string to be used for generating the set value of the quote"),
183 G_PARAM_READWRITE
| G_PARAM_CONSTRUCT
);
184 g_object_class_install_property(gobject_class
, PROP_VALUE
, param
);
186 param
= g_param_spec_string("min",
187 P_("Minimum Value or Low Tolerance"),
188 P_("The minimum value allowed or the lowest tolerance from value (depending of the dimension style): set to NULL to suppress"),
191 g_object_class_install_property(gobject_class
, PROP_MIN
, param
);
193 param
= g_param_spec_string("max",
194 P_("Maximum Value or High Tolerance"),
195 P_("The maximum value allowed or the highest tolerance from value (depending of the dimension style): set to NULL to suppress"),
198 g_object_class_install_property(gobject_class
, PROP_MAX
, param
);
202 adg_dim_init(AdgDim
*dim
)
204 AdgDimPrivate
*data
= G_TYPE_INSTANCE_GET_PRIVATE(dim
, ADG_TYPE_DIM
,
207 data
->dim_dress
= ADG_DRESS_DIMENSION
;
212 data
->outside
= ADG_THREE_STATE_UNKNOWN
;
213 data
->detached
= ADG_THREE_STATE_UNKNOWN
;
218 /* These ones are G_PARAM_CONSTRUCT, so initialized by GObject */
226 _adg_dispose(GObject
*object
)
231 entity
= (AdgEntity
*) object
;
232 data
= ((AdgDim
*) object
)->data
;
234 if (data
->quote
.entity
) {
235 g_object_unref(data
->quote
.entity
);
236 data
->quote
.entity
= NULL
;
240 data
->ref1
= adg_entity_point(entity
, data
->ref1
, NULL
);
243 data
->ref2
= adg_entity_point(entity
, data
->ref2
, NULL
);
246 data
->pos
= adg_entity_point(entity
, data
->pos
, NULL
);
248 if (_ADG_OLD_OBJECT_CLASS
->dispose
)
249 _ADG_OLD_OBJECT_CLASS
->dispose(object
);
253 _adg_finalize(GObject
*object
)
255 AdgDimPrivate
*data
= ((AdgDim
*) object
)->data
;
261 if (_ADG_OLD_OBJECT_CLASS
->finalize
)
262 _ADG_OLD_OBJECT_CLASS
->finalize(object
);
266 _adg_get_property(GObject
*object
, guint prop_id
,
267 GValue
*value
, GParamSpec
*pspec
)
269 AdgDimPrivate
*data
= ((AdgDim
*) object
)->data
;
273 g_value_set_int(value
, data
->dim_dress
);
276 g_value_set_boxed(value
, data
->ref1
);
279 g_value_set_boxed(value
, data
->ref2
);
282 g_value_set_boxed(value
, data
->pos
);
285 g_value_set_double(value
, data
->level
);
288 g_value_set_enum(value
, data
->outside
);
291 g_value_set_enum(value
, data
->detached
);
294 g_value_set_string(value
, data
->value
);
297 g_value_set_string(value
, data
->min
);
300 g_value_set_string(value
, data
->max
);
303 G_OBJECT_WARN_INVALID_PROPERTY_ID(object
, prop_id
, pspec
);
309 _adg_set_property(GObject
*object
, guint prop_id
,
310 const GValue
*value
, GParamSpec
*pspec
)
316 entity
= (AdgEntity
*) object
;
317 dim
= (AdgDim
*) object
;
322 data
->dim_dress
= g_value_get_int(value
);
325 data
->ref1
= adg_entity_point(entity
, data
->ref1
,
326 g_value_get_boxed(value
));
329 data
->ref2
= adg_entity_point(entity
, data
->ref2
,
330 g_value_get_boxed(value
));
333 data
->pos
= adg_entity_point(entity
, data
->pos
,
334 g_value_get_boxed(value
));
337 data
->level
= g_value_get_double(value
);
340 _adg_set_outside(dim
, g_value_get_enum(value
));
343 _adg_set_detached(dim
, g_value_get_enum(value
));
346 _adg_set_value(dim
, g_value_get_string(value
));
349 _adg_set_min(dim
, g_value_get_string(value
));
352 _adg_set_max(dim
, g_value_get_string(value
));
355 G_OBJECT_WARN_INVALID_PROPERTY_ID(object
, prop_id
, pspec
);
362 * adg_dim_set_dim_dress:
364 * @dress: the new #AdgDress to use
366 * Sets a new dimension dress to @dim. The new dress must be
367 * related to the original dress for this property: you cannot
368 * set a dress used for line styles to a dress managing fonts.
370 * The check is done by calling adg_dress_are_related() with
371 * @dress and the previous dress as arguments. Check out its
372 * documentation for details on what is a related dress.
375 adg_dim_set_dim_dress(AdgDim
*dim
, AdgDress dress
)
377 g_return_if_fail(ADG_IS_DIM(dim
));
378 g_object_set(dim
, "dim-dress", dress
, NULL
);
382 * adg_dim_get_dim_dress:
385 * Gets the dimension dress to be used in rendering @dim.
387 * Returns: the current dimension dress
390 adg_dim_get_dim_dress(AdgDim
*dim
)
394 g_return_val_if_fail(ADG_IS_DIM(dim
), ADG_DRESS_UNDEFINED
);
398 return data
->dim_dress
;
404 * @ref1: the new point to use as first reference
406 * Sets the #AdgDim:ref1 property to @ref1. The old point
407 * is silently discarded, unreferencing its model if that
408 * point was bound to a named pair (hence, possibly destroying
409 * the model if this was the last reference).
411 * @ref1 can be %NULL, in which case the point is destroyed.
414 adg_dim_set_ref1(AdgDim
*dim
, const AdgPoint
*ref1
)
416 g_return_if_fail(ADG_IS_DIM(dim
));
417 g_object_set(dim
, "ref1", ref1
, NULL
);
421 * adg_dim_set_ref1_explicit:
423 * @x: x coordinate of the first reference point
424 * @y: y coordinate of the first reference point
426 * Sets the #AdgDim:ref1 property to the (@x, @y) explicit
427 * coordinates. The old point is silently discarded,
428 * unreferencing its model if that point was bound to a named
429 * pair (hence, possibly destroying the model if this was the
433 adg_dim_set_ref1_explicit(AdgDim
*dim
, gdouble x
, gdouble y
)
435 AdgPoint
*point
= adg_point_new();
437 adg_point_set_pair_explicit(point
, x
, y
);
438 adg_dim_set_ref1(dim
, point
);
440 adg_point_destroy(point
);
444 * adg_dim_set_ref1_from_pair:
446 * @ref1: the coordinates pair of the first reference point
448 * Convenient function to set the #AdgDim:ref1 property using a
449 * pair instead of explicit coordinates.
452 adg_dim_set_ref1_from_pair(AdgDim
*dim
, const AdgPair
*ref1
)
454 g_return_if_fail(ref1
!= NULL
);
456 adg_dim_set_ref1_explicit(dim
, ref1
->x
, ref1
->y
);
460 * adg_dim_set_ref1_from_model:
462 * @model: the source #AdgModel
463 * @ref1: a named pair in @model
465 * Binds #AdgDim:ref1 to the @ref1 named pair of @model. If @model
466 * is %NULL, the point will be unset. In any case, the old point
467 * is silently discarded, unreferencing its model if that point
468 * was bound to a named pair (hence, possibly destroying the model
469 * if this was the last reference).
471 * The assignment is lazy so @ref1 could be not be present in @model.
472 * Anyway, at the first access to this point an error will be raised
473 * if the named pair is still missing.
476 adg_dim_set_ref1_from_model(AdgDim
*dim
, AdgModel
*model
, const gchar
*ref1
)
478 AdgPoint
*point
= adg_point_new();
480 adg_point_set_pair_from_model(point
, model
, ref1
);
481 adg_dim_set_ref1(dim
, point
);
483 adg_point_destroy(point
);
490 * Gets the #AdgDim:ref1 point. The returned point is internally owned
491 * and must not be freed or modified. Anyway, it is not const because
492 * adg_point_get_pair() must be able to modify the internal cache of
493 * the returned point.
495 * Returns: the first reference point
498 adg_dim_get_ref1(AdgDim
*dim
)
502 g_return_val_if_fail(ADG_IS_DIM(dim
), NULL
);
512 * @ref2: the new point to use as second reference
514 * Sets the #AdgDim:ref2 property to @ref2. The old point
515 * is silently discarded, unreferencing its model if that
516 * point was bound to a named pair (hence, possibly destroying
517 * the model if it was the last reference).
519 * @ref2 can be %NULL, in which case the point is destroyed.
522 adg_dim_set_ref2(AdgDim
*dim
, const AdgPoint
*ref2
)
524 g_return_if_fail(ADG_IS_DIM(dim
));
525 g_object_set(dim
, "ref2", ref2
, NULL
);
529 * adg_dim_set_ref2_explicit:
531 * @x: x coordinate of the second reference point
532 * @y: y coordinate of the second reference point
534 * Sets the #AdgDim:ref2 property to the (@x, @y) explicit
535 * coordinates. The old point is silently discarded,
536 * unreferencing its model if that point was bound to a named
537 * pair (hence, possibly destroying the model if this was the
541 adg_dim_set_ref2_explicit(AdgDim
*dim
, gdouble x
, gdouble y
)
543 AdgPoint
*point
= adg_point_new();
545 adg_point_set_pair_explicit(point
, x
, y
);
546 adg_dim_set_ref2(dim
, point
);
548 adg_point_destroy(point
);
552 * adg_dim_set_ref2_from_pair:
554 * @ref2: the coordinates pair of the second reference point
556 * Convenient function to set the #AdgDim:ref2 property using a
557 * pair instead of explicit coordinates.
560 adg_dim_set_ref2_from_pair(AdgDim
*dim
, const AdgPair
*ref2
)
562 g_return_if_fail(ref2
!= NULL
);
564 adg_dim_set_ref2_explicit(dim
, ref2
->x
, ref2
->y
);
568 * adg_dim_set_ref2_from_model:
570 * @model: the source #AdgModel
571 * @ref2: a named pair in @model
573 * Binds #AdgDim:ref2 to the @ref2 named pair of @model. If @model
574 * is %NULL, the point will be unset. In any case, the old point
575 * is silently discarded, unreferencing its model if that point
576 * was bound to a named pair (hence, possibly destroying the model
577 * if this was the last reference).
579 * The assignment is lazy so @ref2 could be not be present in @model.
580 * Anyway, at the first access to this point an error will be raised
581 * if the named pair is still missing.
584 adg_dim_set_ref2_from_model(AdgDim
*dim
, AdgModel
*model
, const gchar
*ref2
)
586 AdgPoint
*point
= adg_point_new();
588 adg_point_set_pair_from_model(point
, model
, ref2
);
589 adg_dim_set_ref2(dim
, point
);
591 adg_point_destroy(point
);
598 * Gets the #AdgDim:ref2 point. The returned point is internally owned
599 * and must not be freed or modified. Anyway, it is not const because
600 * adg_point_get_pair() must be able to modify the internal cache of
601 * the returned point.
603 * Returns: the second reference point
606 adg_dim_get_ref2(AdgDim
*dim
)
610 g_return_val_if_fail(ADG_IS_DIM(dim
), NULL
);
620 * @pos: the new point to use as position
622 * Sets the #AdgDim:pos property to @pos. The old point
623 * is silently discarded, unreferencing its model if that
624 * point was bound to a named pair (hence, possibly destroying
625 * the model if it was the last reference).
627 * @pos can be %NULL, in which case the point is destroyed.
630 adg_dim_set_pos(AdgDim
*dim
, const AdgPoint
*pos
)
632 g_return_if_fail(ADG_IS_DIM(dim
));
633 g_object_set(dim
, "pos", pos
, NULL
);
637 * adg_dim_set_pos_explicit:
639 * @x: x coordinate of the position
640 * @y: y coordinate of the position
642 * Sets the #AdgDim:pos property to the (@x, @y) explicit
643 * coordinates. The old point is silently discarded,
644 * unreferencing its model if that point was bound to a named
645 * pair (hence, possibly destroying the model if this was the
649 adg_dim_set_pos_explicit(AdgDim
*dim
, gdouble x
, gdouble y
)
651 AdgPoint
*point
= adg_point_new();
653 adg_point_set_pair_explicit(point
, x
, y
);
654 adg_dim_set_pos(dim
, point
);
656 adg_point_destroy(point
);
660 * adg_dim_set_pos_from_pair:
662 * @pos: the coordinates pair of the position point
664 * Convenient function to set the #AdgDim:pos property using a
665 * pair instead of explicit coordinates.
668 adg_dim_set_pos_from_pair(AdgDim
*dim
, const AdgPair
*pos
)
670 g_return_if_fail(pos
!= NULL
);
672 adg_dim_set_pos_explicit(dim
, pos
->x
, pos
->y
);
676 * adg_dim_set_pos_from_model:
678 * @model: the source #AdgModel
679 * @pos: a named pair in @model
681 * Binds #AdgDim:pos to the @pos named pair of @model. If @model
682 * is %NULL, the point will be unset. In any case, the old point
683 * is silently discarded, unreferencing its model if that point
684 * was bound to a named pair (hence, possibly destroying the model
685 * if this was the last reference).
687 * The assignment is lazy so @pos could be not be present in @model.
688 * Anyway, at the first access to this point an error will be raised
689 * if the named pair is still missing.
692 adg_dim_set_pos_from_model(AdgDim
*dim
, AdgModel
*model
, const gchar
*pos
)
694 AdgPoint
*point
= adg_point_new();
696 adg_point_set_pair_from_model(point
, model
, pos
);
697 adg_dim_set_pos(dim
, point
);
699 adg_point_destroy(point
);
706 * Gets the #AdgDim:pos point. The returned point is internally owned
707 * and must not be freed or modified. Anyway, it is not const because
708 * adg_point_get_pair() must be able to modify the internal cache of
709 * the returned point.
711 * Returns: the position point
714 adg_dim_get_pos(AdgDim
*dim
)
718 g_return_val_if_fail(ADG_IS_DIM(dim
), NULL
);
728 * @level: the new level
730 * Sets a new level for this dimension. The level is used to
731 * stack the quotes using a spacing value from dim_style
732 * (specified in global space).
735 adg_dim_set_level(AdgDim
*dim
, gdouble level
)
739 g_return_if_fail(ADG_IS_DIM(dim
));
744 g_object_notify((GObject
*) dim
, "level");
751 * Gets the level of this dimension.
753 * Returns: the level value
756 adg_dim_get_level(AdgDim
*dim
)
760 g_return_val_if_fail(ADG_IS_DIM(dim
), 0);
768 * adg_dim_set_outside:
770 * @outside: the new outside state
772 * Sets a new state for the #AdgDim:outside flag: check the property
773 * documentation for further details.
776 adg_dim_set_outside(AdgDim
*dim
, AdgThreeState outside
)
778 g_return_if_fail(ADG_IS_DIM(dim
));
780 if (_adg_set_outside(dim
, outside
))
781 g_object_notify((GObject
*) dim
, "outside");
785 * adg_dim_get_outside:
788 * Gets the state of the #AdgDim:outside property: check the property
789 * documentation for further details.
791 * Returns: the current flag state
794 adg_dim_get_outside(AdgDim
*dim
)
798 g_return_val_if_fail(ADG_IS_DIM(dim
), ADG_THREE_STATE_UNKNOWN
);
802 return data
->outside
;
806 * adg_dim_set_detached:
808 * @detached: the new detached state
810 * Sets a new state for the #AdgDim:detached flag: check the property
811 * documentation for further details.
813 * This is used only by dimensions where detaching has meaning.
814 * In some cases, such as with #AdgRDim dimensions, this property is
818 adg_dim_set_detached(AdgDim
*dim
, AdgThreeState detached
)
820 g_return_if_fail(ADG_IS_DIM(dim
));
822 if (_adg_set_detached(dim
, detached
))
823 g_object_notify((GObject
*) dim
, "detached");
827 * adg_dim_get_detached:
830 * Gets the state of the #AdgDim:detached property: check the property
831 * documentation for further details.
833 * Returns: the current flag state
836 adg_dim_get_detached(AdgDim
*dim
)
840 g_return_val_if_fail(ADG_IS_DIM(dim
), ADG_THREE_STATE_UNKNOWN
);
844 return data
->detached
;
850 * @value: the value text
852 * Explicitely sets the text to use as value. If @value is %NULL or
853 * was never set, an automatic text is calculated using the format
854 * specified in the current #AdgDimStyle and getting its value by
855 * calling the default_value() virtual method.
857 * Inside the template string, the "<>" tag (or whatever specified
858 * by the #AdgDimStyle:number-tag property) is substituted with the
859 * string returned by the default_value() virtual method.
862 adg_dim_set_value(AdgDim
*dim
, const gchar
*value
)
864 g_return_if_fail(ADG_IS_DIM(dim
));
866 if (_adg_set_value(dim
, value
))
867 g_object_notify((GObject
*) dim
, "value");
874 * Gets the value text. The string is internally owned and
875 * must not be freed or modified.
877 * Returns: the value text
880 adg_dim_get_value(AdgDim
*dim
)
884 g_return_val_if_fail(ADG_IS_DIM(dim
), NULL
);
892 * adg_dim_set_limits:
894 * @min: the new minumum value
895 * @max: the new maximum value
897 * Shortcut to set both the limits at once.
900 adg_dim_set_limits(AdgDim
*dim
, const gchar
*min
, const gchar
*max
)
902 g_return_if_fail(ADG_IS_DIM(dim
));
904 g_object_freeze_notify((GObject
*) dim
);
905 adg_dim_set_min(dim
, min
);
906 adg_dim_set_max(dim
, max
);
907 g_object_thaw_notify((GObject
*) dim
);
913 * @min: the new minimum limit
915 * Sets the minimum value. Use %NULL as @min to disable it.
918 adg_dim_set_min(AdgDim
*dim
, const gchar
*min
)
920 g_return_if_fail(ADG_IS_DIM(dim
));
922 if (_adg_set_min(dim
, min
))
923 g_object_notify((GObject
*) dim
, "min");
930 * Gets the minimum value text or %NULL on minimum value disabled.
931 * The string is internally owned and must not be freed or modified.
933 * Returns: the mimimum value text
936 adg_dim_get_min(AdgDim
*dim
)
940 g_return_val_if_fail(ADG_IS_DIM(dim
), NULL
);
950 * @max: the new maximum value
952 * Sets the maximum value. Use %NULL as @max to disable it.
955 adg_dim_set_max(AdgDim
*dim
, const gchar
*max
)
957 g_return_if_fail(ADG_IS_DIM(dim
));
959 if (_adg_set_max(dim
, max
))
960 g_object_notify((GObject
*) dim
, "max");
967 * Gets the maximum value text or %NULL on maximum value disabled.
968 * The string is internally owned and must not be freed or modified.
970 * Returns: the maximum value text
973 adg_dim_get_max(AdgDim
*dim
)
977 g_return_val_if_fail(ADG_IS_DIM(dim
), NULL
);
989 * This function is only useful in new dimension implementations.
992 * Gets the quote entity, if any. This function is valid only after
993 * the #AdgDim implementation of the arrange() virtual method has
996 * Returns: the quote entity
999 adg_dim_get_quote(AdgDim
*dim
)
1001 AdgDimPrivate
*data
;
1003 g_return_val_if_fail(ADG_IS_DIM(dim
), NULL
);
1007 return data
->quote
.entity
;
1011 * adg_dim_quote_angle:
1013 * @angle: an angle (in radians)
1016 * This function is only useful in new dimension implementations.
1019 * Converts @angle accordling to the style of @dim. Any quote angle
1020 * should be validated by this method because every dimensioning
1021 * style has its own convention regardling the text rotation.
1023 * Returns: the angle to use (always in radians)
1026 adg_dim_quote_angle(AdgDim
*dim
, gdouble angle
)
1030 g_return_val_if_fail(ADG_IS_DIM(dim
), angle
);
1032 klass
= ADG_DIM_GET_CLASS(dim
);
1034 if (klass
->quote_angle
== NULL
)
1037 return klass
->quote_angle(angle
);
1042 _adg_global_changed(AdgEntity
*entity
)
1044 AdgDimPrivate
*data
= ((AdgDim
*) entity
)->data
;
1046 if (_ADG_OLD_ENTITY_CLASS
->global_changed
)
1047 _ADG_OLD_ENTITY_CLASS
->global_changed(entity
);
1049 if (data
->quote
.entity
)
1050 adg_entity_global_changed((AdgEntity
*) data
->quote
.entity
);
1054 _adg_local_changed(AdgEntity
*entity
)
1056 AdgDimPrivate
*data
= ((AdgDim
*) entity
)->data
;
1058 if (_ADG_OLD_ENTITY_CLASS
->local_changed
)
1059 _ADG_OLD_ENTITY_CLASS
->local_changed(entity
);
1061 if (data
->quote
.entity
)
1062 adg_entity_local_changed((AdgEntity
*) data
->quote
.entity
);
1066 _adg_invalidate(AdgEntity
*entity
)
1068 AdgDimPrivate
*data
= ((AdgDim
*) entity
)->data
;
1070 if (data
->quote
.value
) {
1071 g_object_unref(data
->quote
.value
);
1072 data
->quote
.value
= NULL
;
1074 if (data
->quote
.entity
)
1075 adg_entity_invalidate((AdgEntity
*) data
->quote
.entity
);
1077 adg_point_invalidate(data
->ref1
);
1079 adg_point_invalidate(data
->ref2
);
1081 adg_point_invalidate(data
->pos
);
1083 if (_ADG_OLD_ENTITY_CLASS
->invalidate
)
1084 _ADG_OLD_ENTITY_CLASS
->invalidate(entity
);
1088 _adg_arrange(AdgEntity
*entity
)
1091 AdgDimPrivate
*data
;
1092 AdgEntity
*quote_entity
;
1093 AdgContainer
*quote_container
;
1094 AdgEntity
*value_entity
;
1095 AdgEntity
*min_entity
;
1096 AdgEntity
*max_entity
;
1097 const AdgPair
*shift
;
1100 dim
= (AdgDim
*) entity
;
1103 /* Resolve the dim style */
1104 if (data
->dim_style
== NULL
)
1105 data
->dim_style
= (AdgDimStyle
*)
1106 adg_entity_style(entity
, data
->dim_dress
);
1108 if (data
->quote
.entity
== NULL
)
1109 data
->quote
.entity
= g_object_new(ADG_TYPE_ALIGNMENT
,
1110 "local-method", ADG_MIX_NONE
,
1111 "parent", dim
, NULL
);
1113 quote_entity
= (AdgEntity
*) data
->quote
.entity
;
1114 quote_container
= (AdgContainer
*) data
->quote
.entity
;
1116 if (data
->quote
.value
== NULL
) {
1123 klass
= ADG_DIM_GET_CLASS(dim
);
1124 dress
= adg_dim_style_get_value_dress(data
->dim_style
);
1125 tag
= adg_dim_style_get_number_tag(data
->dim_style
);
1126 value
= klass
->default_value
? klass
->default_value(dim
) : NULL
;
1128 data
->quote
.value
= g_object_new(ADG_TYPE_BEST_TEXT
,
1129 "local-method", ADG_MIX_PARENT
,
1130 "font-dress", dress
, NULL
);
1131 adg_container_add(quote_container
, (AdgEntity
*) data
->quote
.value
);
1134 text
= adg_string_replace(data
->value
, tag
, value
);
1136 text
= g_strdup(value
);
1140 adg_textual_set_text(data
->quote
.value
, text
);
1144 if (data
->quote
.min
== NULL
&& data
->min
) {
1145 AdgDress dress
= adg_dim_style_get_min_dress(data
->dim_style
);
1147 data
->quote
.min
= g_object_new(ADG_TYPE_BEST_TEXT
,
1148 "local-method", ADG_MIX_PARENT
,
1149 "font-dress", dress
, NULL
);
1151 adg_container_add(quote_container
, (AdgEntity
*) data
->quote
.min
);
1152 adg_textual_set_text(data
->quote
.min
, data
->min
);
1155 if (data
->quote
.max
== NULL
&& data
->max
) {
1156 AdgDress dress
= adg_dim_style_get_max_dress(data
->dim_style
);
1158 data
->quote
.max
= g_object_new(ADG_TYPE_BEST_TEXT
,
1159 "local-method", ADG_MIX_PARENT
,
1160 "font-dress", dress
, NULL
);
1162 adg_container_add(quote_container
, (AdgEntity
*) data
->quote
.max
);
1163 adg_textual_set_text(data
->quote
.max
, data
->max
);
1166 value_entity
= (AdgEntity
*) data
->quote
.value
;
1167 min_entity
= (AdgEntity
*) data
->quote
.min
;
1168 max_entity
= (AdgEntity
*) data
->quote
.max
;
1169 shift
= adg_dim_style_get_quote_shift(data
->dim_style
);
1171 adg_entity_set_global_map(quote_entity
, adg_matrix_identity());
1172 adg_entity_global_changed(quote_entity
);
1174 cairo_matrix_init_translate(&map
, 0, shift
->y
);
1175 adg_entity_set_global_map(value_entity
, &map
);
1176 adg_entity_arrange(value_entity
);
1178 /* Limit values (min and max) */
1179 if (min_entity
|| max_entity
) {
1180 const AdgPair
*limits_shift
;
1184 AdgPair org_min
, org_max
;
1186 limits_shift
= adg_dim_style_get_limits_shift(data
->dim_style
);
1187 spacing
= adg_dim_style_get_limits_spacing(data
->dim_style
);
1188 size
= adg_entity_get_extents(value_entity
)->size
;
1189 adg_matrix_copy(&unglobal
, adg_entity_get_global_matrix(entity
));
1190 cairo_matrix_invert(&unglobal
);
1191 cpml_vector_transform(&size
, &unglobal
);
1192 org_min
.x
= size
.x
+ limits_shift
->x
;
1193 org_min
.y
= -size
.y
/ 2 + limits_shift
->y
;
1196 if (min_entity
&& max_entity
) {
1197 /* Prearrange the min entity to get its extents */
1198 adg_entity_arrange(min_entity
);
1199 size
= adg_entity_get_extents(min_entity
)->size
;
1200 cpml_vector_transform(&size
, &unglobal
);
1202 org_min
.y
+= spacing
/ 2;
1203 org_max
.y
= org_min
.y
- size
.y
- spacing
/ 2;
1207 cairo_matrix_init_translate(&map
, org_min
.x
, org_min
.y
);
1208 adg_entity_set_global_map(min_entity
, &map
);
1209 adg_entity_arrange(min_entity
);
1213 cairo_matrix_init_translate(&map
, org_max
.x
, org_max
.y
);
1214 adg_entity_set_global_map(max_entity
, &map
);
1215 adg_entity_arrange(max_entity
);
1219 adg_entity_arrange(quote_entity
);
1223 _adg_default_value(AdgDim
*dim
)
1225 g_warning(_("AdgDim::default_value not implemented for `%s'"),
1226 g_type_name(G_TYPE_FROM_INSTANCE(dim
)));
1227 return g_strdup("undef");
1231 _adg_quote_angle(gdouble angle
)
1233 angle
= cpml_angle(angle
);
1235 if (angle
> G_PI_4
* 4 / 3 || angle
<= -G_PI_4
* 3)
1236 angle
= cpml_angle(angle
+ G_PI
);
1242 _adg_set_outside(AdgDim
*dim
, AdgThreeState outside
)
1244 AdgDimPrivate
*data
;
1246 g_return_val_if_fail(adg_is_enum_value(outside
, ADG_TYPE_THREE_STATE
),
1251 if (data
->outside
== outside
)
1254 data
->outside
= outside
;
1260 _adg_set_detached(AdgDim
*dim
, AdgThreeState detached
)
1262 AdgDimPrivate
*data
;
1264 g_return_val_if_fail(adg_is_enum_value(detached
, ADG_TYPE_THREE_STATE
),
1269 if (data
->detached
== detached
)
1272 data
->detached
= detached
;
1278 _adg_set_value(AdgDim
*dim
, const gchar
*value
)
1280 AdgDimPrivate
*data
;
1284 if (g_strcmp0(value
, data
->value
) == 0)
1287 g_free(data
->value
);
1288 data
->value
= g_strdup(value
);
1290 if (data
->quote
.value
) {
1291 g_object_unref(data
->quote
.value
);
1292 data
->quote
.value
= NULL
;
1299 _adg_set_min(AdgDim
*dim
, const gchar
*min
)
1301 AdgDimPrivate
*data
= dim
->data
;
1303 if (g_strcmp0(min
, data
->min
) == 0)
1307 data
->min
= g_strdup(min
);
1309 if (data
->quote
.min
) {
1310 g_object_unref(data
->quote
.min
);
1311 data
->quote
.min
= NULL
;
1318 _adg_set_max(AdgDim
*dim
, const gchar
*max
)
1320 AdgDimPrivate
*data
= dim
->data
;
1322 if (g_strcmp0(max
, data
->max
) == 0)
1326 data
->max
= g_strdup(max
);
1328 if (data
->quote
.max
) {
1329 g_object_unref(data
->quote
.max
);
1330 data
->quote
.max
= NULL
;