[AdgTableStyle] Added guards against invalid properties
[adg.git] / adg / adg-dim-style.c
blob0560b3b94b65a532eb3c0c76b755b94bc0ae1f03
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.
21 /**
22 * SECTION:adg-dim-style
23 * @short_description: Dimension style related stuff
25 * Contains parameters on how to build dimensions such as the different font
26 * styles (for value and limits), line style, offsets of the various
27 * dimension components etc...
30 /**
31 * AdgDimStyle:
33 * All fields are private and should not be used directly.
34 * Use its public methods instead.
35 **/
38 #include "adg-internal.h"
39 #include "adg-dim-style.h"
40 #include "adg-dim-style-private.h"
41 #include "adg-dress-builtins.h"
42 #include "adg-font-style.h"
43 #include "adg-line-style.h"
44 #include "adg-util.h"
47 enum {
48 PROP_0,
49 PROP_MARKER1,
50 PROP_MARKER2,
51 PROP_COLOR_DRESS,
52 PROP_VALUE_DRESS,
53 PROP_MIN_DRESS,
54 PROP_MAX_DRESS,
55 PROP_LINE_DRESS,
56 PROP_FROM_OFFSET,
57 PROP_TO_OFFSET,
58 PROP_BEYOND,
59 PROP_BASELINE_SPACING,
60 PROP_LIMITS_SPACING,
61 PROP_QUOTE_SHIFT,
62 PROP_LIMITS_SHIFT,
63 PROP_NUMBER_FORMAT,
64 PROP_NUMBER_TAG
68 static void finalize (GObject *object);
69 static void get_property (GObject *object,
70 guint prop_id,
71 GValue *value,
72 GParamSpec *pspec);
73 static void set_property (GObject *object,
74 guint prop_id,
75 const GValue *value,
76 GParamSpec *pspec);
77 static void apply (AdgStyle *style,
78 AdgEntity *entity,
79 cairo_t *cr);
80 static gboolean set_from_offset (AdgDimStyle *dim_style,
81 gdouble offset);
82 static gboolean set_to_offset (AdgDimStyle *dim_style,
83 gdouble offset);
84 static gboolean set_baseline_spacing (AdgDimStyle *dim_style,
85 gdouble spacing);
86 static gboolean set_limits_spacing (AdgDimStyle *dim_style,
87 gdouble spacing);
88 static gboolean set_beyond (AdgDimStyle *dim_style,
89 gdouble beyond);
90 static gboolean set_quote_shift (AdgDimStyle *dim_style,
91 const AdgPair *shift);
92 static gboolean set_limits_shift (AdgDimStyle *dim_style,
93 const AdgPair *shift);
94 static void set_number_format (AdgDimStyle *dim_style,
95 const gchar *format);
96 static void set_number_tag (AdgDimStyle *dim_style,
97 const gchar *tag);
98 static AdgMarker * marker_new (const AdgMarkerData
99 *marker_data);
100 static gboolean set_marker (AdgMarkerData *marker_data,
101 AdgMarker *marker);
102 static void free_marker (AdgMarkerData *marker_data);
105 G_DEFINE_TYPE(AdgDimStyle, adg_dim_style, ADG_TYPE_STYLE);
108 static void
109 adg_dim_style_class_init(AdgDimStyleClass *klass)
111 GObjectClass *gobject_class;
112 AdgStyleClass *style_class;
113 GParamSpec *param;
115 gobject_class = (GObjectClass *) klass;
116 style_class = (AdgStyleClass *) klass;
118 g_type_class_add_private(klass, sizeof(AdgDimStylePrivate));
120 gobject_class->finalize = finalize;
121 gobject_class->get_property = get_property;
122 gobject_class->set_property = set_property;
124 style_class->apply = apply;
126 param = g_param_spec_object("marker1",
127 P_("First Marker"),
128 P_("The template entity to use as first marker"),
129 ADG_TYPE_MARKER,
130 G_PARAM_WRITABLE);
131 g_object_class_install_property(gobject_class, PROP_MARKER1, param);
133 param = g_param_spec_object("marker2",
134 P_("Second Marker"),
135 P_("The template entity to use as second marker"),
136 ADG_TYPE_MARKER,
137 G_PARAM_WRITABLE);
138 g_object_class_install_property(gobject_class, PROP_MARKER2, param);
140 param = adg_param_spec_dress("color-dress",
141 P_("Color Dress"),
142 P_("Color dress for the whole dimension"),
143 ADG_DRESS_COLOR_DIMENSION,
144 G_PARAM_READWRITE);
145 g_object_class_install_property(gobject_class, PROP_COLOR_DRESS, param);
147 param = adg_param_spec_dress("value-dress",
148 P_("Value Dress"),
149 P_("Font dress for the nominal value of the dimension"),
150 ADG_DRESS_TEXT_VALUE,
151 G_PARAM_READWRITE);
152 g_object_class_install_property(gobject_class, PROP_VALUE_DRESS, param);
154 param = adg_param_spec_dress("min-dress",
155 P_("Minimum Limit Dress"),
156 P_("Font dress for the lower limit value"),
157 ADG_DRESS_TEXT_LIMIT,
158 G_PARAM_READWRITE);
159 g_object_class_install_property(gobject_class, PROP_MIN_DRESS, param);
161 param = adg_param_spec_dress("max-dress",
162 P_("Maximum Limit Dress"),
163 P_("Font dress for the upper limit value"),
164 ADG_DRESS_TEXT_LIMIT,
165 G_PARAM_READWRITE);
166 g_object_class_install_property(gobject_class, PROP_MAX_DRESS, param);
168 param = adg_param_spec_dress("line-dress",
169 P_("Line Dress"),
170 P_("Line dress for the baseline and the extension lines"),
171 ADG_DRESS_LINE_THINNER,
172 G_PARAM_READWRITE);
173 g_object_class_install_property(gobject_class, PROP_LINE_DRESS, param);
175 param = g_param_spec_double("from-offset",
176 P_("From Offset"),
177 P_("Offset (in global space) of the extension lines from the path to the quote"),
178 0, G_MAXDOUBLE, 5,
179 G_PARAM_READWRITE);
180 g_object_class_install_property(gobject_class, PROP_FROM_OFFSET, param);
182 param = g_param_spec_double("to-offset",
183 P_("To Offset"),
184 P_("How many extend (in global space) the extension lines after hitting the baseline"),
185 0, G_MAXDOUBLE, 5,
186 G_PARAM_READWRITE);
187 g_object_class_install_property(gobject_class, PROP_TO_OFFSET, param);
189 param = g_param_spec_double("beyond",
190 P_("Beyond Length"),
191 P_("How much the baseline should be extended (in global space) beyond the extension lines on dimensions with outside markers"),
192 0, G_MAXDOUBLE, 20,
193 G_PARAM_READWRITE);
194 g_object_class_install_property(gobject_class, PROP_BEYOND, param);
196 param = g_param_spec_double("baseline-spacing",
197 P_("Baseline Spacing"),
198 P_("Distance between two consecutive baselines while stacking dimensions"),
199 0, G_MAXDOUBLE, 30,
200 G_PARAM_READWRITE);
201 g_object_class_install_property(gobject_class, PROP_BASELINE_SPACING, param);
203 param = g_param_spec_double("limits-spacing",
204 P_("Limits Spacing"),
205 P_("Distance between limits/tolerances"),
206 0, G_MAXDOUBLE, 2,
207 G_PARAM_READWRITE);
208 g_object_class_install_property(gobject_class, PROP_LIMITS_SPACING, param);
210 param = g_param_spec_boxed("quote-shift",
211 P_("Quote Shift"),
212 P_("Used to specify a smooth displacement (in global space) of the quote by taking as reference the perfect compact position (the middle of the baseline on common linear dimension, for instance)"),
213 ADG_TYPE_PAIR,
214 G_PARAM_READWRITE);
215 g_object_class_install_property(gobject_class, PROP_QUOTE_SHIFT, param);
217 param = g_param_spec_boxed("limits-shift",
218 P_("Limits Shift"),
219 P_("Used to specify a smooth displacement (in global space) for the limits/tolerances by taking as reference the perfect compact position"),
220 ADG_TYPE_PAIR,
221 G_PARAM_READWRITE);
222 g_object_class_install_property(gobject_class, PROP_LIMITS_SHIFT, param);
224 param = g_param_spec_string("number-format",
225 P_("Number Format"),
226 P_("The format (in printf style) of the numeric component of the basic value"),
227 "%-.7g",
228 G_PARAM_READWRITE);
229 g_object_class_install_property(gobject_class, PROP_NUMBER_FORMAT, param);
231 param = g_param_spec_string("number-tag",
232 P_("Number Tag"),
233 P_("The tag to substitute inside the basic value pattern"),
234 "<>",
235 G_PARAM_READWRITE);
236 g_object_class_install_property(gobject_class, PROP_NUMBER_TAG, param);
239 static void
240 adg_dim_style_init(AdgDimStyle *dim_style)
242 AdgDimStylePrivate *data = G_TYPE_INSTANCE_GET_PRIVATE(dim_style,
243 ADG_TYPE_DIM_STYLE,
244 AdgDimStylePrivate);
246 data->marker1.type = 0;
247 data->marker1.n_parameters = 0;
248 data->marker1.parameters = NULL;
249 data->marker2.type = 0;
250 data->marker2.n_parameters = 0;
251 data->marker2.parameters = NULL;
252 data->color_dress = ADG_DRESS_COLOR_DIMENSION;
253 data->value_dress = ADG_DRESS_TEXT_VALUE;
254 data->min_dress = ADG_DRESS_TEXT_LIMIT;
255 data->max_dress = ADG_DRESS_TEXT_LIMIT;
256 data->line_dress = ADG_DRESS_LINE_THINNER;
257 data->marker_dress = ADG_DRESS_UNDEFINED;
258 data->from_offset = 6;
259 data->to_offset = 6;
260 data->beyond = 20;
261 data->baseline_spacing = 30;
262 data->limits_spacing = 1;
263 data->quote_shift.x = 0;
264 data->quote_shift.y = -4;
265 data->limits_shift.x = +2;
266 data->limits_shift.y = -2;
267 data->number_format = g_strdup("%-.7g");
268 data->number_tag = g_strdup("<>");
270 dim_style->data = data;
273 static void
274 finalize(GObject *object)
276 AdgDimStylePrivate *data = ((AdgDimStyle *) object)->data;
278 free_marker(&data->marker1);
279 free_marker(&data->marker2);
281 g_free(data->number_format);
282 data->number_format = NULL;
284 g_free(data->number_tag);
285 data->number_tag = NULL;
288 static void
289 get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
291 AdgDimStylePrivate *data = ((AdgDimStyle *) object)->data;
293 switch (prop_id) {
294 case PROP_COLOR_DRESS:
295 g_value_set_int(value, data->color_dress);
296 break;
297 case PROP_VALUE_DRESS:
298 g_value_set_int(value, data->value_dress);
299 break;
300 case PROP_MIN_DRESS:
301 g_value_set_int(value, data->min_dress);
302 break;
303 case PROP_MAX_DRESS:
304 g_value_set_int(value, data->max_dress);
305 break;
306 case PROP_LINE_DRESS:
307 g_value_set_int(value, data->line_dress);
308 break;
309 case PROP_FROM_OFFSET:
310 g_value_set_double(value, data->from_offset);
311 break;
312 case PROP_TO_OFFSET:
313 g_value_set_double(value, data->to_offset);
314 break;
315 case PROP_BEYOND:
316 g_value_set_double(value, data->beyond);
317 break;
318 case PROP_BASELINE_SPACING:
319 g_value_set_double(value, data->baseline_spacing);
320 break;
321 case PROP_LIMITS_SPACING:
322 g_value_set_double(value, data->limits_spacing);
323 break;
324 case PROP_QUOTE_SHIFT:
325 g_value_set_boxed(value, &data->quote_shift);
326 break;
327 case PROP_LIMITS_SHIFT:
328 g_value_set_boxed(value, &data->limits_shift);
329 break;
330 case PROP_NUMBER_FORMAT:
331 g_value_set_string(value, data->number_format);
332 break;
333 case PROP_NUMBER_TAG:
334 g_value_set_string(value, data->number_tag);
335 break;
336 default:
337 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
338 break;
342 static void
343 set_property(GObject *object,
344 guint prop_id, const GValue *value, GParamSpec *pspec)
346 AdgDimStyle *dim_style;
347 AdgDimStylePrivate *data;
349 dim_style = (AdgDimStyle *) object;
350 data = dim_style->data;
352 switch (prop_id) {
353 case PROP_MARKER1:
354 set_marker(&data->marker1, g_value_get_object(value));
355 break;
356 case PROP_MARKER2:
357 set_marker(&data->marker2, g_value_get_object(value));
358 break;
359 case PROP_COLOR_DRESS:
360 adg_dress_set(&data->color_dress, g_value_get_int(value));
361 break;
362 case PROP_VALUE_DRESS:
363 adg_dress_set(&data->value_dress, g_value_get_int(value));
364 break;
365 case PROP_MIN_DRESS:
366 adg_dress_set(&data->min_dress, g_value_get_int(value));
367 break;
368 case PROP_MAX_DRESS:
369 adg_dress_set(&data->max_dress, g_value_get_int(value));
370 break;
371 case PROP_LINE_DRESS:
372 adg_dress_set(&data->line_dress, g_value_get_int(value));
373 break;
374 case PROP_FROM_OFFSET:
375 set_from_offset(dim_style, g_value_get_double(value));
376 break;
377 case PROP_TO_OFFSET:
378 set_to_offset(dim_style, g_value_get_double(value));
379 break;
380 case PROP_BEYOND:
381 set_beyond(dim_style, g_value_get_double(value));
382 break;
383 case PROP_BASELINE_SPACING:
384 set_baseline_spacing(dim_style, g_value_get_double(value));
385 break;
386 case PROP_LIMITS_SPACING:
387 set_limits_spacing(dim_style, g_value_get_double(value));
388 break;
389 case PROP_QUOTE_SHIFT:
390 set_quote_shift(dim_style, g_value_get_boxed(value));
391 break;
392 case PROP_LIMITS_SHIFT:
393 set_limits_shift(dim_style, g_value_get_boxed(value));
394 break;
395 case PROP_NUMBER_FORMAT:
396 set_number_format(dim_style, g_value_get_string(value));
397 break;
398 case PROP_NUMBER_TAG:
399 set_number_tag(dim_style, g_value_get_string(value));
400 break;
401 default:
402 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
403 break;
409 * adg_dim_style_new:
411 * Constructs a new empty dimension style initialized with default params.
413 * Returns: a newly created dimension style
415 AdgDimStyle *
416 adg_dim_style_new(void)
418 return g_object_new(ADG_TYPE_DIM_STYLE, NULL);
422 * adg_dim_style_set_marker1:
423 * @dim_style: an #AdgStyle
424 * @marker: an #AdgMarker derived entity
426 * Uses @marker as entity template to generate a new marker entity
427 * when a call to adg_dim_style_marker1_new() is made. It is allowed
428 * to pass %NULL as @marker, in which case the template data of the
429 * first marker are unset.
431 * This method duplicates internally the property values of @marker,
432 * so any further change to @marker does not affect @dim_style anymore.
433 * This also means @marker could be destroyed without problems after
434 * this call because @dim_style uses only its property values and does
435 * not add any references to @marker.
437 void
438 adg_dim_style_set_marker1(AdgDimStyle *dim_style, AdgMarker *marker)
440 AdgDimStylePrivate *data;
442 g_return_if_fail(ADG_IS_DIM_STYLE(dim_style));
444 data = dim_style->data;
446 if (set_marker(&data->marker1, marker))
447 g_object_notify((GObject *) dim_style, "marker1");
451 * adg_dim_style_marker1_new:
452 * @dim_style: an #AdgDimStyle
454 * Creates a new marker entity by cloning the #AdgMarker:marker1
455 * object. The returned entity should be unreferenced with
456 * g_object_unref() when no longer needed.
458 * Returns: a newly created marker or %NULL if the #AdgDimStyle:marker1
459 * property is not set or on errors
461 AdgMarker *
462 adg_dim_style_marker1_new(AdgDimStyle *dim_style)
464 AdgDimStylePrivate *data;
466 g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style), NULL);
468 data = dim_style->data;
470 return marker_new(&data->marker1);
474 * adg_dim_style_set_marker2:
475 * @dim_style: an #AdgStyle
476 * @marker: an #AdgMarker derived entity
478 * Uses @marker as entity template to generate a new marker entity
479 * when a call to adg_dim_style_marker2_new() is made. It is allowed
480 * to pass %NULL as @marker, in which case the template data of the
481 * second marker are unset.
483 * This method duplicates internally the property values of @marker,
484 * so any further change to @marker does not affect @dim_style anymore.
485 * This also means @marker could be destroyed without problems after
486 * this call because @dim_style uses only its property values and does
487 * not add any references to @marker.
489 void
490 adg_dim_style_set_marker2(AdgDimStyle *dim_style, AdgMarker *marker)
492 AdgDimStylePrivate *data;
494 g_return_if_fail(ADG_IS_DIM_STYLE(dim_style));
495 g_return_if_fail(marker == NULL || ADG_IS_MARKER(marker));
497 data = dim_style->data;
499 if (set_marker(&data->marker2, marker))
500 g_object_notify((GObject *) dim_style, "marker2");
504 * adg_dim_style_marker2_new:
505 * @dim_style: an #AdgDimStyle
507 * Creates a new marker entity by cloning the #AdgMarker:marker2
508 * object. The returned entity should be unreferenced with
509 * g_object_unref() when no longer needed.
511 * Returns: a newly created marker or %NULL if the #AdgDimStyle:marker2
512 * property is not set or on errors
514 AdgMarker *
515 adg_dim_style_marker2_new(AdgDimStyle *dim_style)
517 AdgDimStylePrivate *data;
519 g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style), NULL);
521 data = dim_style->data;
523 return marker_new(&data->marker2);
527 * adg_dim_style_set_color_dress:
528 * @dim_style: an #AdgDimStyle object
529 * @dress: the new color dress
531 * Sets a new color dress on @dim_style.
533 void
534 adg_dim_style_set_color_dress(AdgDimStyle *dim_style, AdgDress dress)
536 AdgDimStylePrivate *data;
538 g_return_if_fail(ADG_IS_DIM_STYLE(dim_style));
540 data = dim_style->data;
542 if (adg_dress_set(&data->color_dress, dress))
543 g_object_notify((GObject *) dim_style, "color-dress");
547 * adg_dim_style_get_color_dress:
548 * @dim_style: an #AdgDimStyle object
550 * Gets the @dim_style color dress to be used. This dress should be
551 * intended as a fallback color as it could be overriden by more
552 * specific dresses, such as a color explicitely specified on the
553 * #AdgDimStyle:value-dress.
555 * Returns: the color dress
557 AdgDress
558 adg_dim_style_get_color_dress(AdgDimStyle *dim_style)
560 AdgDimStylePrivate *data;
562 g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style), ADG_DRESS_UNDEFINED);
564 data = dim_style->data;
566 return data->color_dress;
570 * adg_dim_style_set_value_dress:
571 * @dim_style: an #AdgDimStyle object
572 * @dress: the new basic value font style
574 * Sets a new dress on @dim_style for the basic value.
576 void
577 adg_dim_style_set_value_dress(AdgDimStyle *dim_style, AdgDress dress)
579 AdgDimStylePrivate *data;
581 g_return_if_fail(ADG_IS_DIM_STYLE(dim_style));
583 data = dim_style->data;
585 if (adg_dress_set(&data->value_dress, dress))
586 g_object_notify((GObject *) dim_style, "value-dress");
590 * adg_dim_style_get_value_dress:
591 * @dim_style: an #AdgDimStyle object
593 * Gets the font dress to be used for the basic value of dimensions
594 * with @dim_style.
596 * Returns: the font dress
598 AdgDress
599 adg_dim_style_get_value_dress(AdgDimStyle *dim_style)
601 AdgDimStylePrivate *data;
603 g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style), ADG_DRESS_UNDEFINED);
605 data = dim_style->data;
607 return data->value_dress;
611 * adg_dim_style_set_min_dress:
612 * @dim_style: an #AdgDimStyle object
613 * @dress: the new lower limit dress
615 * Sets a new dress on @dim_style for the lower limit value.
617 void
618 adg_dim_style_set_min_dress(AdgDimStyle *dim_style, AdgDress dress)
620 AdgDimStylePrivate *data;
622 g_return_if_fail(ADG_IS_DIM_STYLE(dim_style));
624 data = dim_style->data;
626 if (adg_dress_set(&data->min_dress, dress))
627 g_object_notify((GObject *) dim_style, "min-dress");
631 * adg_dim_style_get_min_dress:
632 * @dim_style: an #AdgDimStyle object
634 * Gets the @dim_style dress to be used for the lower limit.
636 * Returns: the lower limit dress
638 AdgDress
639 adg_dim_style_get_min_dress(AdgDimStyle *dim_style)
641 AdgDimStylePrivate *data;
643 g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style), ADG_DRESS_UNDEFINED);
645 data = dim_style->data;
647 return data->min_dress;
651 * adg_dim_style_set_max_dress:
652 * @dim_style: an #AdgDimStyle object
653 * @dress: the new upper limit dress
655 * Sets a new dress on @dim_style for the upper limit value.
657 void
658 adg_dim_style_set_max_dress(AdgDimStyle *dim_style, AdgDress dress)
660 AdgDimStylePrivate *data;
662 g_return_if_fail(ADG_IS_DIM_STYLE(dim_style));
664 data = dim_style->data;
666 if (adg_dress_set(&data->max_dress, dress))
667 g_object_notify((GObject *) dim_style, "max-dress");
671 * adg_dim_style_get_max_dress:
672 * @dim_style: an #AdgDimStyle object
674 * Gets the @dim_style dress to be used for the upper limit.
676 * Returns: the upper limit dress
678 AdgDress
679 adg_dim_style_get_max_dress(AdgDimStyle *dim_style)
681 AdgDimStylePrivate *data;
683 g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style), ADG_DRESS_UNDEFINED);
685 data = dim_style->data;
687 return data->max_dress;
691 * adg_dim_style_set_line_dress:
692 * @dim_style: an #AdgDimStyle object
693 * @dress: the new line dress
695 * Sets a new line dress on @dim_style.
697 void
698 adg_dim_style_set_line_dress(AdgDimStyle *dim_style, AdgDress dress)
700 AdgDimStylePrivate *data;
702 g_return_if_fail(ADG_IS_DIM_STYLE(dim_style));
704 data = dim_style->data;
706 if (adg_dress_set(&data->line_dress, dress))
707 g_object_notify((GObject *) dim_style, "line-dress");
711 * adg_dim_style_get_line_dress:
712 * @dim_style: an #AdgDimStyle object
714 * Gets the line dress to be used for rendering the base and
715 * the extension lines with @dim_style.
717 * Returns: the line dress
719 AdgDress
720 adg_dim_style_get_line_dress(AdgDimStyle *dim_style)
722 AdgDimStylePrivate *data;
724 g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style), ADG_DRESS_UNDEFINED);
726 data = dim_style->data;
728 return data->line_dress;
732 * adg_dim_style_set_from_offset:
733 * @dim_style: an #AdgDimStyle object
734 * @offset: the new offset
736 * Sets a new value in the #AdgDimStyle:from-offset property.
738 void
739 adg_dim_style_set_from_offset(AdgDimStyle *dim_style, gdouble offset)
741 g_return_if_fail(ADG_IS_DIM_STYLE(dim_style));
743 if (set_from_offset(dim_style, offset))
744 g_object_notify((GObject *) dim_style, "from-offset");
748 * adg_dim_style_get_from_offset:
749 * @dim_style: an #AdgDimStyle object
751 * Gets the distance (in global space) the extension lines must keep from the
752 * sensed points.
754 * Returns: the requested distance
756 gdouble
757 adg_dim_style_get_from_offset(AdgDimStyle *dim_style)
759 AdgDimStylePrivate *data;
761 g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style), 0);
763 data = dim_style->data;
765 return data->from_offset;
769 * adg_dim_style_set_to_offset:
770 * @dim_style: an #AdgDimStyle object
771 * @offset: the new offset
773 * Sets a new value in the #AdgDimStyle:to-offset property.
775 void
776 adg_dim_style_set_to_offset(AdgDimStyle *dim_style, gdouble offset)
778 g_return_if_fail(ADG_IS_DIM_STYLE(dim_style));
780 if (set_to_offset(dim_style, offset))
781 g_object_notify((GObject *) dim_style, "to-offset");
785 * adg_dim_style_get_to_offset:
786 * @dim_style: an #AdgDimStyle object
788 * Gets how much (in global space) the extension lines must extend after
789 * crossing the baseline.
791 * Returns: the requested distance
793 gdouble
794 adg_dim_style_get_to_offset(AdgDimStyle *dim_style)
796 AdgDimStylePrivate *data;
798 g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style), 0);
800 data = dim_style->data;
802 return data->to_offset;
806 * adg_dim_style_set_beyond:
807 * @dim_style: an #AdgDimStyle object
808 * @beyond: the new length
810 * Sets a new value in the #AdgDimStyle:beyond property.
812 void
813 adg_dim_style_set_beyond(AdgDimStyle *dim_style, gdouble beyond)
815 g_return_if_fail(ADG_IS_DIM_STYLE(dim_style));
817 if (set_beyond(dim_style, beyond))
818 g_object_notify((GObject *) dim_style, "beyond");
822 * adg_dim_style_get_beyond:
823 * @dim_style: an #AdgDimStyle object
825 * Gets how much (in global space) the baseline should extend beyond
826 * the extension lines on dimension with outside markers.
828 * Returns: the requested beyond length
830 gdouble
831 adg_dim_style_get_beyond(AdgDimStyle *dim_style)
833 AdgDimStylePrivate *data;
835 g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style), 0);
837 data = dim_style->data;
839 return data->beyond;
843 * adg_dim_style_set_baseline_spacing:
844 * @dim_style: an #AdgDimStyle object
845 * @spacing: the new spacing
847 * Sets a new value in the #AdgDimStyle:baseline-spacing value.
849 void
850 adg_dim_style_set_baseline_spacing(AdgDimStyle *dim_style, gdouble spacing)
852 g_return_if_fail(ADG_IS_DIM_STYLE(dim_style));
854 if (set_baseline_spacing(dim_style, spacing))
855 g_object_notify((GObject *) dim_style, "baseline-spacing");
859 * adg_dim_style_get_baseline_spacing:
860 * @dim_style: an #AdgDimStyle object
862 * Gets the distance between two consecutive baselines
863 * while stacking dimensions.
865 * Returns: the requested spacing
867 gdouble
868 adg_dim_style_get_baseline_spacing(AdgDimStyle *dim_style)
870 AdgDimStylePrivate *data;
872 g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style), 0);
874 data = dim_style->data;
876 return data->baseline_spacing;
880 * adg_dim_style_set_limits_spacing:
881 * @dim_style: an #AdgDimStyle object
882 * @spacing: the new spacing
884 * Sets a new #AdgDimStyle:limits-spacing value.
886 void
887 adg_dim_style_set_limits_spacing(AdgDimStyle *dim_style, gdouble spacing)
889 g_return_if_fail(ADG_IS_DIM_STYLE(dim_style));
891 if (set_limits_spacing(dim_style, spacing))
892 g_object_notify((GObject *) dim_style, "limits-spacing");
896 * adg_dim_style_get_limits_spacing:
897 * @dim_style: an #AdgDimStyle object
899 * Gets the distance (in global space) between the limits/tolerances.
901 * Returns: the requested spacing
903 gdouble
904 adg_dim_style_get_limits_spacing(AdgDimStyle *dim_style)
906 AdgDimStylePrivate *data;
908 g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style), 0);
910 data = dim_style->data;
912 return data->limits_spacing;
916 * adg_dim_style_set_quote_shift:
917 * @dim_style: an #AdgDimStyle object
918 * @shift: the new displacement
920 * Sets a new #AdgDimStyle:quote-shift value.
922 void
923 adg_dim_style_set_quote_shift(AdgDimStyle *dim_style, const AdgPair *shift)
925 g_return_if_fail(ADG_IS_DIM_STYLE(dim_style));
927 if (set_quote_shift(dim_style, shift))
928 g_object_notify((GObject *) dim_style, "quote-shift");
932 * adg_dim_style_get_quote_shift:
933 * @dim_style: an #AdgDimStyle object
935 * Gets the smooth displacement of the quote. The returned pointer refers
936 * to an internal allocated struct and must not be modified or freed.
938 * Returns: the requested shift
940 const AdgPair *
941 adg_dim_style_get_quote_shift(AdgDimStyle *dim_style)
943 AdgDimStylePrivate *data;
945 g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style), NULL);
947 data = dim_style->data;
949 return &data->quote_shift;
953 * adg_dim_style_set_limits_shift:
954 * @dim_style: an #AdgDimStyle object
955 * @shift: the new displacement
957 * Sets a new #AdgDimStyle:limits-shift value.
959 void
960 adg_dim_style_set_limits_shift(AdgDimStyle *dim_style, const AdgPair *shift)
962 g_return_if_fail(ADG_IS_DIM_STYLE(dim_style));
964 if (set_limits_shift(dim_style, shift))
965 g_object_notify((GObject *) dim_style, "limits-shift");
969 * adg_dim_style_get_limits_shift:
970 * @dim_style: an #AdgDimStyle object
972 * Gets the smooth displacement for the limits. The returned pointer
973 * refers to an internal allocated struct and must not be modified or freed.
975 * Returns: the requested shift
977 const AdgPair *
978 adg_dim_style_get_limits_shift(AdgDimStyle *dim_style)
980 AdgDimStylePrivate *data;
982 g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style), NULL);
984 data = dim_style->data;
986 return &data->limits_shift;
990 * adg_dim_style_set_number_format:
991 * @dim_style: an #AdgDimStyle object
992 * @format: the new format to adopt
994 * Sets a new value in the #AdgDimStyle:number-format property.
996 void
997 adg_dim_style_set_number_format(AdgDimStyle *dim_style, const gchar *format)
999 g_return_if_fail(ADG_IS_DIM_STYLE(dim_style));
1001 set_number_format(dim_style, format);
1002 g_object_notify((GObject *) dim_style, "number-format");
1006 * adg_dim_style_get_number_format:
1007 * @dim_style: an #AdgDimStyle object
1009 * Gets the number format (in printf style) of this quoting style. The
1010 * returned pointer refers to internally managed text that must not be
1011 * modified or freed.
1013 * Returns: the requested format
1015 const gchar *
1016 adg_dim_style_get_number_format(AdgDimStyle *dim_style)
1018 AdgDimStylePrivate *data;
1020 g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style), NULL);
1022 data = dim_style->data;
1024 return data->number_format;
1028 * adg_dim_style_set_number_tag:
1029 * @dim_style: an #AdgDimStyle object
1030 * @tag: the new tag
1032 * Sets a new value in the #AdgDimStyle:number-tag property.
1034 void
1035 adg_dim_style_set_number_tag(AdgDimStyle *dim_style, const gchar *tag)
1037 g_return_if_fail(ADG_IS_DIM_STYLE(dim_style));
1039 set_number_tag(dim_style, tag);
1040 g_object_notify((GObject *) dim_style, "number-tag");
1044 * adg_dim_style_get_number_tag:
1045 * @dim_style: an #AdgDimStyle object
1047 * Gets the number tag to substitute while building the basic value. The
1048 * returned pointer refers to internally managed text that must not be
1049 * modified or freed.
1051 * Returns: the requested tag
1053 const gchar *
1054 adg_dim_style_get_number_tag(AdgDimStyle *dim_style)
1056 AdgDimStylePrivate *data;
1058 g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style), NULL);
1060 data = dim_style->data;
1062 return data->number_tag;
1066 static void
1067 apply(AdgStyle *style, AdgEntity *entity, cairo_t *cr)
1069 AdgDimStylePrivate *data = ((AdgDimStyle *) style)->data;
1071 adg_entity_apply_dress(entity, data->color_dress, cr);
1074 static gboolean
1075 set_from_offset(AdgDimStyle *dim_style, gdouble offset)
1077 AdgDimStylePrivate *data = dim_style->data;
1079 /* A better approach would be to use the GParamSpec of this property */
1080 g_return_val_if_fail(offset >= 0, FALSE);
1082 if (data->from_offset == offset)
1083 return FALSE;
1085 data->from_offset = offset;
1086 return TRUE;
1089 static gboolean
1090 set_to_offset(AdgDimStyle *dim_style, gdouble offset)
1092 AdgDimStylePrivate *data = dim_style->data;
1094 /* A better approach would be to use the GParamSpec of this property */
1095 g_return_val_if_fail(offset >= 0, FALSE);
1097 if (data->to_offset == offset)
1098 return FALSE;
1100 data->to_offset = offset;
1101 return TRUE;
1104 static gboolean
1105 set_baseline_spacing(AdgDimStyle *dim_style, gdouble spacing)
1107 AdgDimStylePrivate *data = dim_style->data;
1109 /* A better approach would be to use the GParamSpec of this property */
1110 g_return_val_if_fail(spacing >= 0, FALSE);
1112 if (data->baseline_spacing == spacing)
1113 return FALSE;
1115 data->baseline_spacing = spacing;
1116 return TRUE;
1119 static gboolean
1120 set_limits_spacing(AdgDimStyle *dim_style, gdouble spacing)
1122 AdgDimStylePrivate *data = dim_style->data;
1124 /* A better approach would be to use the GParamSpec of this property */
1125 g_return_val_if_fail(spacing >= 0, FALSE);
1127 if (data->limits_spacing == spacing)
1128 return FALSE;
1130 data->limits_spacing = spacing;
1131 return TRUE;
1134 static gboolean
1135 set_beyond(AdgDimStyle *dim_style, gdouble beyond)
1137 AdgDimStylePrivate *data = dim_style->data;
1139 /* A better approach would be to use the GParamSpec of this property */
1140 g_return_val_if_fail(beyond >= 0, FALSE);
1142 if (data->beyond == beyond)
1143 return FALSE;
1145 data->beyond = beyond;
1146 return TRUE;
1149 static gboolean
1150 set_quote_shift(AdgDimStyle *dim_style, const AdgPair *shift)
1152 AdgDimStylePrivate *data;
1154 g_return_val_if_fail(shift != NULL, FALSE);
1156 data = dim_style->data;
1158 if (adg_pair_equal(&data->quote_shift, shift))
1159 return FALSE;
1161 data->quote_shift = *shift;
1163 return TRUE;
1166 static gboolean
1167 set_limits_shift(AdgDimStyle *dim_style, const AdgPair *shift)
1169 AdgDimStylePrivate *data;
1171 g_return_val_if_fail(shift != NULL, FALSE);
1173 data = dim_style->data;
1175 if (adg_pair_equal(&data->limits_shift, shift))
1176 return FALSE;
1178 data->limits_shift = *shift;
1180 return TRUE;
1183 static void
1184 set_number_format(AdgDimStyle *dim_style, const gchar *format)
1186 AdgDimStylePrivate *data = dim_style->data;
1188 g_free(data->number_format);
1189 data->number_format = g_strdup(format);
1192 static void
1193 set_number_tag(AdgDimStyle *dim_style, const gchar *tag)
1195 AdgDimStylePrivate *data = dim_style->data;
1197 g_free(data->number_tag);
1198 data->number_tag = g_strdup(tag);
1201 static AdgMarker *
1202 marker_new(const AdgMarkerData *marker_data)
1204 if (marker_data->type == 0)
1205 return NULL;
1207 return g_object_newv(marker_data->type,
1208 marker_data->n_parameters,
1209 marker_data->parameters);
1212 static gboolean
1213 set_marker(AdgMarkerData *marker_data, AdgMarker *marker)
1215 g_return_val_if_fail(marker == NULL || ADG_IS_MARKER(marker), FALSE);
1217 /* Free the previous marker data, if any */
1218 free_marker(marker_data);
1220 if (marker) {
1221 GObject *object;
1222 GParamSpec **specs;
1223 GParamSpec *spec;
1224 GParameter *parameter;
1225 guint n;
1227 object = (GObject *) marker;
1228 specs = g_object_class_list_properties(G_OBJECT_GET_CLASS(marker),
1229 &marker_data->n_parameters);
1231 marker_data->type = G_TYPE_FROM_INSTANCE(marker);
1232 marker_data->parameters = g_new0(GParameter, marker_data->n_parameters);
1234 for (n = 0; n < marker_data->n_parameters; ++n) {
1235 spec = specs[n];
1236 parameter = &marker_data->parameters[n];
1238 /* Using intern strings because GParameter:name is const.
1239 * GObject properties are internally managed using non-static
1240 * GQuark, so g_intern_string() is the way to go */
1241 parameter->name = g_intern_string(spec->name);
1243 g_value_init(&parameter->value, spec->value_type);
1244 g_object_get_property(object, spec->name, &parameter->value);
1247 g_free(specs);
1250 return TRUE;
1253 static void
1254 free_marker(AdgMarkerData *marker_data)
1256 guint n;
1258 for (n = 0; n < marker_data->n_parameters; ++n)
1259 g_value_unset(&marker_data->parameters[n].value);
1261 marker_data->type = 0;
1262 marker_data->n_parameters = 0;
1263 marker_data->parameters = NULL;