[ADG] Renamed '*-util.*' files to '*-utils.*'
[adg.git] / src / adg / adg-dim-style.c
blob2aa63686bc9022b37a066f7318fda7c108b3bd63
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"
46 enum {
47 PROP_0,
48 PROP_MARKER1,
49 PROP_MARKER2,
50 PROP_COLOR_DRESS,
51 PROP_VALUE_DRESS,
52 PROP_MIN_DRESS,
53 PROP_MAX_DRESS,
54 PROP_LINE_DRESS,
55 PROP_FROM_OFFSET,
56 PROP_TO_OFFSET,
57 PROP_BEYOND,
58 PROP_BASELINE_SPACING,
59 PROP_LIMITS_SPACING,
60 PROP_QUOTE_SHIFT,
61 PROP_LIMITS_SHIFT,
62 PROP_NUMBER_FORMAT,
63 PROP_NUMBER_TAG
67 static void finalize (GObject *object);
68 static void get_property (GObject *object,
69 guint prop_id,
70 GValue *value,
71 GParamSpec *pspec);
72 static void set_property (GObject *object,
73 guint prop_id,
74 const GValue *value,
75 GParamSpec *pspec);
76 static void apply (AdgStyle *style,
77 AdgEntity *entity,
78 cairo_t *cr);
79 static gboolean set_from_offset (AdgDimStyle *dim_style,
80 gdouble offset);
81 static gboolean set_to_offset (AdgDimStyle *dim_style,
82 gdouble offset);
83 static gboolean set_baseline_spacing (AdgDimStyle *dim_style,
84 gdouble spacing);
85 static gboolean set_limits_spacing (AdgDimStyle *dim_style,
86 gdouble spacing);
87 static gboolean set_beyond (AdgDimStyle *dim_style,
88 gdouble beyond);
89 static gboolean set_quote_shift (AdgDimStyle *dim_style,
90 const AdgPair *shift);
91 static gboolean set_limits_shift (AdgDimStyle *dim_style,
92 const AdgPair *shift);
93 static void set_number_format (AdgDimStyle *dim_style,
94 const gchar *format);
95 static void set_number_tag (AdgDimStyle *dim_style,
96 const gchar *tag);
97 static AdgMarker * marker_new (const AdgMarkerData
98 *marker_data);
99 static gboolean set_marker (AdgMarkerData *marker_data,
100 AdgMarker *marker);
101 static void free_marker (AdgMarkerData *marker_data);
104 G_DEFINE_TYPE(AdgDimStyle, adg_dim_style, ADG_TYPE_STYLE);
107 static void
108 adg_dim_style_class_init(AdgDimStyleClass *klass)
110 GObjectClass *gobject_class;
111 AdgStyleClass *style_class;
112 GParamSpec *param;
114 gobject_class = (GObjectClass *) klass;
115 style_class = (AdgStyleClass *) klass;
117 g_type_class_add_private(klass, sizeof(AdgDimStylePrivate));
119 gobject_class->finalize = finalize;
120 gobject_class->get_property = get_property;
121 gobject_class->set_property = set_property;
123 style_class->apply = apply;
125 param = g_param_spec_object("marker1",
126 P_("First Marker"),
127 P_("The template entity to use as first marker"),
128 ADG_TYPE_MARKER,
129 G_PARAM_WRITABLE);
130 g_object_class_install_property(gobject_class, PROP_MARKER1, param);
132 param = g_param_spec_object("marker2",
133 P_("Second Marker"),
134 P_("The template entity to use as second marker"),
135 ADG_TYPE_MARKER,
136 G_PARAM_WRITABLE);
137 g_object_class_install_property(gobject_class, PROP_MARKER2, param);
139 param = adg_param_spec_dress("color-dress",
140 P_("Color Dress"),
141 P_("Color dress for the whole dimension"),
142 ADG_DRESS_COLOR_DIMENSION,
143 G_PARAM_READWRITE);
144 g_object_class_install_property(gobject_class, PROP_COLOR_DRESS, param);
146 param = adg_param_spec_dress("value-dress",
147 P_("Value Dress"),
148 P_("Font dress for the nominal value of the dimension"),
149 ADG_DRESS_TEXT_VALUE,
150 G_PARAM_READWRITE);
151 g_object_class_install_property(gobject_class, PROP_VALUE_DRESS, param);
153 param = adg_param_spec_dress("min-dress",
154 P_("Minimum Limit Dress"),
155 P_("Font dress for the lower limit value"),
156 ADG_DRESS_TEXT_LIMIT,
157 G_PARAM_READWRITE);
158 g_object_class_install_property(gobject_class, PROP_MIN_DRESS, param);
160 param = adg_param_spec_dress("max-dress",
161 P_("Maximum Limit Dress"),
162 P_("Font dress for the upper limit value"),
163 ADG_DRESS_TEXT_LIMIT,
164 G_PARAM_READWRITE);
165 g_object_class_install_property(gobject_class, PROP_MAX_DRESS, param);
167 param = adg_param_spec_dress("line-dress",
168 P_("Line Dress"),
169 P_("Line dress for the baseline and the extension lines"),
170 ADG_DRESS_LINE_DIMENSION,
171 G_PARAM_READWRITE);
172 g_object_class_install_property(gobject_class, PROP_LINE_DRESS, param);
174 param = g_param_spec_double("from-offset",
175 P_("From Offset"),
176 P_("Offset (in global space) of the extension lines from the path to the quote"),
177 0, G_MAXDOUBLE, 5,
178 G_PARAM_READWRITE);
179 g_object_class_install_property(gobject_class, PROP_FROM_OFFSET, param);
181 param = g_param_spec_double("to-offset",
182 P_("To Offset"),
183 P_("How many extend (in global space) the extension lines after hitting the baseline"),
184 0, G_MAXDOUBLE, 5,
185 G_PARAM_READWRITE);
186 g_object_class_install_property(gobject_class, PROP_TO_OFFSET, param);
188 param = g_param_spec_double("beyond",
189 P_("Beyond Length"),
190 P_("How much the baseline should be extended (in global space) beyond the extension lines on dimensions with outside markers"),
191 0, G_MAXDOUBLE, 20,
192 G_PARAM_READWRITE);
193 g_object_class_install_property(gobject_class, PROP_BEYOND, param);
195 param = g_param_spec_double("baseline-spacing",
196 P_("Baseline Spacing"),
197 P_("Distance between two consecutive baselines while stacking dimensions"),
198 0, G_MAXDOUBLE, 30,
199 G_PARAM_READWRITE);
200 g_object_class_install_property(gobject_class, PROP_BASELINE_SPACING, param);
202 param = g_param_spec_double("limits-spacing",
203 P_("Limits Spacing"),
204 P_("Distance between limits/tolerances"),
205 0, G_MAXDOUBLE, 2,
206 G_PARAM_READWRITE);
207 g_object_class_install_property(gobject_class, PROP_LIMITS_SPACING, param);
209 param = g_param_spec_boxed("quote-shift",
210 P_("Quote Shift"),
211 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)"),
212 ADG_TYPE_PAIR,
213 G_PARAM_READWRITE);
214 g_object_class_install_property(gobject_class, PROP_QUOTE_SHIFT, param);
216 param = g_param_spec_boxed("limits-shift",
217 P_("Limits Shift"),
218 P_("Used to specify a smooth displacement (in global space) for the limits/tolerances by taking as reference the perfect compact position"),
219 ADG_TYPE_PAIR,
220 G_PARAM_READWRITE);
221 g_object_class_install_property(gobject_class, PROP_LIMITS_SHIFT, param);
223 param = g_param_spec_string("number-format",
224 P_("Number Format"),
225 P_("The format (in printf style) of the numeric component of the basic value"),
226 "%-.7g",
227 G_PARAM_READWRITE);
228 g_object_class_install_property(gobject_class, PROP_NUMBER_FORMAT, param);
230 param = g_param_spec_string("number-tag",
231 P_("Number Tag"),
232 P_("The tag to substitute inside the basic value pattern"),
233 "<>",
234 G_PARAM_READWRITE);
235 g_object_class_install_property(gobject_class, PROP_NUMBER_TAG, param);
238 static void
239 adg_dim_style_init(AdgDimStyle *dim_style)
241 AdgDimStylePrivate *data = G_TYPE_INSTANCE_GET_PRIVATE(dim_style,
242 ADG_TYPE_DIM_STYLE,
243 AdgDimStylePrivate);
245 data->marker1.type = 0;
246 data->marker1.n_parameters = 0;
247 data->marker1.parameters = NULL;
248 data->marker2.type = 0;
249 data->marker2.n_parameters = 0;
250 data->marker2.parameters = NULL;
251 data->color_dress = ADG_DRESS_COLOR_DIMENSION;
252 data->value_dress = ADG_DRESS_TEXT_VALUE;
253 data->min_dress = ADG_DRESS_TEXT_LIMIT;
254 data->max_dress = ADG_DRESS_TEXT_LIMIT;
255 data->line_dress = ADG_DRESS_LINE_DIMENSION;
256 data->marker_dress = ADG_DRESS_UNDEFINED;
257 data->from_offset = 6;
258 data->to_offset = 6;
259 data->beyond = 20;
260 data->baseline_spacing = 30;
261 data->limits_spacing = 1;
262 data->quote_shift.x = 0;
263 data->quote_shift.y = -4;
264 data->limits_shift.x = +2;
265 data->limits_shift.y = -2;
266 data->number_format = g_strdup("%-.7g");
267 data->number_tag = g_strdup("<>");
269 dim_style->data = data;
272 static void
273 finalize(GObject *object)
275 AdgDimStylePrivate *data = ((AdgDimStyle *) object)->data;
277 free_marker(&data->marker1);
278 free_marker(&data->marker2);
280 g_free(data->number_format);
281 data->number_format = NULL;
283 g_free(data->number_tag);
284 data->number_tag = NULL;
287 static void
288 get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
290 AdgDimStylePrivate *data = ((AdgDimStyle *) object)->data;
292 switch (prop_id) {
293 case PROP_COLOR_DRESS:
294 g_value_set_int(value, data->color_dress);
295 break;
296 case PROP_VALUE_DRESS:
297 g_value_set_int(value, data->value_dress);
298 break;
299 case PROP_MIN_DRESS:
300 g_value_set_int(value, data->min_dress);
301 break;
302 case PROP_MAX_DRESS:
303 g_value_set_int(value, data->max_dress);
304 break;
305 case PROP_LINE_DRESS:
306 g_value_set_int(value, data->line_dress);
307 break;
308 case PROP_FROM_OFFSET:
309 g_value_set_double(value, data->from_offset);
310 break;
311 case PROP_TO_OFFSET:
312 g_value_set_double(value, data->to_offset);
313 break;
314 case PROP_BEYOND:
315 g_value_set_double(value, data->beyond);
316 break;
317 case PROP_BASELINE_SPACING:
318 g_value_set_double(value, data->baseline_spacing);
319 break;
320 case PROP_LIMITS_SPACING:
321 g_value_set_double(value, data->limits_spacing);
322 break;
323 case PROP_QUOTE_SHIFT:
324 g_value_set_boxed(value, &data->quote_shift);
325 break;
326 case PROP_LIMITS_SHIFT:
327 g_value_set_boxed(value, &data->limits_shift);
328 break;
329 case PROP_NUMBER_FORMAT:
330 g_value_set_string(value, data->number_format);
331 break;
332 case PROP_NUMBER_TAG:
333 g_value_set_string(value, data->number_tag);
334 break;
335 default:
336 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
337 break;
341 static void
342 set_property(GObject *object,
343 guint prop_id, const GValue *value, GParamSpec *pspec)
345 AdgDimStyle *dim_style;
346 AdgDimStylePrivate *data;
348 dim_style = (AdgDimStyle *) object;
349 data = dim_style->data;
351 switch (prop_id) {
352 case PROP_MARKER1:
353 set_marker(&data->marker1, g_value_get_object(value));
354 break;
355 case PROP_MARKER2:
356 set_marker(&data->marker2, g_value_get_object(value));
357 break;
358 case PROP_COLOR_DRESS:
359 adg_dress_set(&data->color_dress, g_value_get_int(value));
360 break;
361 case PROP_VALUE_DRESS:
362 adg_dress_set(&data->value_dress, g_value_get_int(value));
363 break;
364 case PROP_MIN_DRESS:
365 adg_dress_set(&data->min_dress, g_value_get_int(value));
366 break;
367 case PROP_MAX_DRESS:
368 adg_dress_set(&data->max_dress, g_value_get_int(value));
369 break;
370 case PROP_LINE_DRESS:
371 adg_dress_set(&data->line_dress, g_value_get_int(value));
372 break;
373 case PROP_FROM_OFFSET:
374 set_from_offset(dim_style, g_value_get_double(value));
375 break;
376 case PROP_TO_OFFSET:
377 set_to_offset(dim_style, g_value_get_double(value));
378 break;
379 case PROP_BEYOND:
380 set_beyond(dim_style, g_value_get_double(value));
381 break;
382 case PROP_BASELINE_SPACING:
383 set_baseline_spacing(dim_style, g_value_get_double(value));
384 break;
385 case PROP_LIMITS_SPACING:
386 set_limits_spacing(dim_style, g_value_get_double(value));
387 break;
388 case PROP_QUOTE_SHIFT:
389 set_quote_shift(dim_style, g_value_get_boxed(value));
390 break;
391 case PROP_LIMITS_SHIFT:
392 set_limits_shift(dim_style, g_value_get_boxed(value));
393 break;
394 case PROP_NUMBER_FORMAT:
395 set_number_format(dim_style, g_value_get_string(value));
396 break;
397 case PROP_NUMBER_TAG:
398 set_number_tag(dim_style, g_value_get_string(value));
399 break;
400 default:
401 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
402 break;
408 * adg_dim_style_new:
410 * Constructs a new empty dimension style initialized with default params.
412 * Returns: a newly created dimension style
414 AdgDimStyle *
415 adg_dim_style_new(void)
417 return g_object_new(ADG_TYPE_DIM_STYLE, NULL);
421 * adg_dim_style_set_marker1:
422 * @dim_style: an #AdgStyle
423 * @marker: an #AdgMarker derived entity
425 * Uses @marker as entity template to generate a new marker entity
426 * when a call to adg_dim_style_marker1_new() is made. It is allowed
427 * to pass %NULL as @marker, in which case the template data of the
428 * first marker are unset.
430 * This method duplicates internally the property values of @marker,
431 * so any further change to @marker does not affect @dim_style anymore.
432 * This also means @marker could be destroyed without problems after
433 * this call because @dim_style uses only its property values and does
434 * not add any references to @marker.
436 void
437 adg_dim_style_set_marker1(AdgDimStyle *dim_style, AdgMarker *marker)
439 AdgDimStylePrivate *data;
441 g_return_if_fail(ADG_IS_DIM_STYLE(dim_style));
443 data = dim_style->data;
445 if (set_marker(&data->marker1, marker))
446 g_object_notify((GObject *) dim_style, "marker1");
450 * adg_dim_style_marker1_new:
451 * @dim_style: an #AdgDimStyle
453 * Creates a new marker entity by cloning the #AdgMarker:marker1
454 * object. The returned entity should be unreferenced with
455 * g_object_unref() when no longer needed.
457 * Returns: a newly created marker or %NULL if the #AdgDimStyle:marker1
458 * property is not set or on errors
460 AdgMarker *
461 adg_dim_style_marker1_new(AdgDimStyle *dim_style)
463 AdgDimStylePrivate *data;
465 g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style), NULL);
467 data = dim_style->data;
469 return marker_new(&data->marker1);
473 * adg_dim_style_set_marker2:
474 * @dim_style: an #AdgStyle
475 * @marker: an #AdgMarker derived entity
477 * Uses @marker as entity template to generate a new marker entity
478 * when a call to adg_dim_style_marker2_new() is made. It is allowed
479 * to pass %NULL as @marker, in which case the template data of the
480 * second marker are unset.
482 * This method duplicates internally the property values of @marker,
483 * so any further change to @marker does not affect @dim_style anymore.
484 * This also means @marker could be destroyed without problems after
485 * this call because @dim_style uses only its property values and does
486 * not add any references to @marker.
488 void
489 adg_dim_style_set_marker2(AdgDimStyle *dim_style, AdgMarker *marker)
491 AdgDimStylePrivate *data;
493 g_return_if_fail(ADG_IS_DIM_STYLE(dim_style));
494 g_return_if_fail(marker == NULL || ADG_IS_MARKER(marker));
496 data = dim_style->data;
498 if (set_marker(&data->marker2, marker))
499 g_object_notify((GObject *) dim_style, "marker2");
503 * adg_dim_style_marker2_new:
504 * @dim_style: an #AdgDimStyle
506 * Creates a new marker entity by cloning the #AdgMarker:marker2
507 * object. The returned entity should be unreferenced with
508 * g_object_unref() when no longer needed.
510 * Returns: a newly created marker or %NULL if the #AdgDimStyle:marker2
511 * property is not set or on errors
513 AdgMarker *
514 adg_dim_style_marker2_new(AdgDimStyle *dim_style)
516 AdgDimStylePrivate *data;
518 g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style), NULL);
520 data = dim_style->data;
522 return marker_new(&data->marker2);
526 * adg_dim_style_set_color_dress:
527 * @dim_style: an #AdgDimStyle object
528 * @dress: the new color dress
530 * Sets a new color dress on @dim_style.
532 void
533 adg_dim_style_set_color_dress(AdgDimStyle *dim_style, AdgDress dress)
535 AdgDimStylePrivate *data;
537 g_return_if_fail(ADG_IS_DIM_STYLE(dim_style));
539 data = dim_style->data;
541 if (adg_dress_set(&data->color_dress, dress))
542 g_object_notify((GObject *) dim_style, "color-dress");
546 * adg_dim_style_get_color_dress:
547 * @dim_style: an #AdgDimStyle object
549 * Gets the @dim_style color dress to be used. This dress should be
550 * intended as a fallback color as it could be overriden by more
551 * specific dresses, such as a color explicitely specified on the
552 * #AdgDimStyle:value-dress.
554 * Returns: the color dress
556 AdgDress
557 adg_dim_style_get_color_dress(AdgDimStyle *dim_style)
559 AdgDimStylePrivate *data;
561 g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style), ADG_DRESS_UNDEFINED);
563 data = dim_style->data;
565 return data->color_dress;
569 * adg_dim_style_set_value_dress:
570 * @dim_style: an #AdgDimStyle object
571 * @dress: the new basic value font style
573 * Sets a new dress on @dim_style for the basic value.
575 void
576 adg_dim_style_set_value_dress(AdgDimStyle *dim_style, AdgDress dress)
578 AdgDimStylePrivate *data;
580 g_return_if_fail(ADG_IS_DIM_STYLE(dim_style));
582 data = dim_style->data;
584 if (adg_dress_set(&data->value_dress, dress))
585 g_object_notify((GObject *) dim_style, "value-dress");
589 * adg_dim_style_get_value_dress:
590 * @dim_style: an #AdgDimStyle object
592 * Gets the font dress to be used for the basic value of dimensions
593 * with @dim_style.
595 * Returns: the font dress
597 AdgDress
598 adg_dim_style_get_value_dress(AdgDimStyle *dim_style)
600 AdgDimStylePrivate *data;
602 g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style), ADG_DRESS_UNDEFINED);
604 data = dim_style->data;
606 return data->value_dress;
610 * adg_dim_style_set_min_dress:
611 * @dim_style: an #AdgDimStyle object
612 * @dress: the new lower limit dress
614 * Sets a new dress on @dim_style for the lower limit value.
616 void
617 adg_dim_style_set_min_dress(AdgDimStyle *dim_style, AdgDress dress)
619 AdgDimStylePrivate *data;
621 g_return_if_fail(ADG_IS_DIM_STYLE(dim_style));
623 data = dim_style->data;
625 if (adg_dress_set(&data->min_dress, dress))
626 g_object_notify((GObject *) dim_style, "min-dress");
630 * adg_dim_style_get_min_dress:
631 * @dim_style: an #AdgDimStyle object
633 * Gets the @dim_style dress to be used for the lower limit.
635 * Returns: the lower limit dress
637 AdgDress
638 adg_dim_style_get_min_dress(AdgDimStyle *dim_style)
640 AdgDimStylePrivate *data;
642 g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style), ADG_DRESS_UNDEFINED);
644 data = dim_style->data;
646 return data->min_dress;
650 * adg_dim_style_set_max_dress:
651 * @dim_style: an #AdgDimStyle object
652 * @dress: the new upper limit dress
654 * Sets a new dress on @dim_style for the upper limit value.
656 void
657 adg_dim_style_set_max_dress(AdgDimStyle *dim_style, AdgDress dress)
659 AdgDimStylePrivate *data;
661 g_return_if_fail(ADG_IS_DIM_STYLE(dim_style));
663 data = dim_style->data;
665 if (adg_dress_set(&data->max_dress, dress))
666 g_object_notify((GObject *) dim_style, "max-dress");
670 * adg_dim_style_get_max_dress:
671 * @dim_style: an #AdgDimStyle object
673 * Gets the @dim_style dress to be used for the upper limit.
675 * Returns: the upper limit dress
677 AdgDress
678 adg_dim_style_get_max_dress(AdgDimStyle *dim_style)
680 AdgDimStylePrivate *data;
682 g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style), ADG_DRESS_UNDEFINED);
684 data = dim_style->data;
686 return data->max_dress;
690 * adg_dim_style_set_line_dress:
691 * @dim_style: an #AdgDimStyle object
692 * @dress: the new line dress
694 * Sets a new line dress on @dim_style.
696 void
697 adg_dim_style_set_line_dress(AdgDimStyle *dim_style, AdgDress dress)
699 AdgDimStylePrivate *data;
701 g_return_if_fail(ADG_IS_DIM_STYLE(dim_style));
703 data = dim_style->data;
705 if (adg_dress_set(&data->line_dress, dress))
706 g_object_notify((GObject *) dim_style, "line-dress");
710 * adg_dim_style_get_line_dress:
711 * @dim_style: an #AdgDimStyle object
713 * Gets the line dress to be used for rendering the base and
714 * the extension lines with @dim_style.
716 * Returns: the line dress
718 AdgDress
719 adg_dim_style_get_line_dress(AdgDimStyle *dim_style)
721 AdgDimStylePrivate *data;
723 g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style), ADG_DRESS_UNDEFINED);
725 data = dim_style->data;
727 return data->line_dress;
731 * adg_dim_style_set_from_offset:
732 * @dim_style: an #AdgDimStyle object
733 * @offset: the new offset
735 * Sets a new value in the #AdgDimStyle:from-offset property.
737 void
738 adg_dim_style_set_from_offset(AdgDimStyle *dim_style, gdouble offset)
740 g_return_if_fail(ADG_IS_DIM_STYLE(dim_style));
742 if (set_from_offset(dim_style, offset))
743 g_object_notify((GObject *) dim_style, "from-offset");
747 * adg_dim_style_get_from_offset:
748 * @dim_style: an #AdgDimStyle object
750 * Gets the distance (in global space) the extension lines must keep from the
751 * sensed points.
753 * Returns: the requested distance
755 gdouble
756 adg_dim_style_get_from_offset(AdgDimStyle *dim_style)
758 AdgDimStylePrivate *data;
760 g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style), 0);
762 data = dim_style->data;
764 return data->from_offset;
768 * adg_dim_style_set_to_offset:
769 * @dim_style: an #AdgDimStyle object
770 * @offset: the new offset
772 * Sets a new value in the #AdgDimStyle:to-offset property.
774 void
775 adg_dim_style_set_to_offset(AdgDimStyle *dim_style, gdouble offset)
777 g_return_if_fail(ADG_IS_DIM_STYLE(dim_style));
779 if (set_to_offset(dim_style, offset))
780 g_object_notify((GObject *) dim_style, "to-offset");
784 * adg_dim_style_get_to_offset:
785 * @dim_style: an #AdgDimStyle object
787 * Gets how much (in global space) the extension lines must extend after
788 * crossing the baseline.
790 * Returns: the requested distance
792 gdouble
793 adg_dim_style_get_to_offset(AdgDimStyle *dim_style)
795 AdgDimStylePrivate *data;
797 g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style), 0);
799 data = dim_style->data;
801 return data->to_offset;
805 * adg_dim_style_set_beyond:
806 * @dim_style: an #AdgDimStyle object
807 * @beyond: the new length
809 * Sets a new value in the #AdgDimStyle:beyond property.
811 void
812 adg_dim_style_set_beyond(AdgDimStyle *dim_style, gdouble beyond)
814 g_return_if_fail(ADG_IS_DIM_STYLE(dim_style));
816 if (set_beyond(dim_style, beyond))
817 g_object_notify((GObject *) dim_style, "beyond");
821 * adg_dim_style_get_beyond:
822 * @dim_style: an #AdgDimStyle object
824 * Gets how much (in global space) the baseline should extend beyond
825 * the extension lines on dimension with outside markers.
827 * Returns: the requested beyond length
829 gdouble
830 adg_dim_style_get_beyond(AdgDimStyle *dim_style)
832 AdgDimStylePrivate *data;
834 g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style), 0);
836 data = dim_style->data;
838 return data->beyond;
842 * adg_dim_style_set_baseline_spacing:
843 * @dim_style: an #AdgDimStyle object
844 * @spacing: the new spacing
846 * Sets a new value in the #AdgDimStyle:baseline-spacing value.
848 void
849 adg_dim_style_set_baseline_spacing(AdgDimStyle *dim_style, gdouble spacing)
851 g_return_if_fail(ADG_IS_DIM_STYLE(dim_style));
853 if (set_baseline_spacing(dim_style, spacing))
854 g_object_notify((GObject *) dim_style, "baseline-spacing");
858 * adg_dim_style_get_baseline_spacing:
859 * @dim_style: an #AdgDimStyle object
861 * Gets the distance between two consecutive baselines
862 * while stacking dimensions.
864 * Returns: the requested spacing
866 gdouble
867 adg_dim_style_get_baseline_spacing(AdgDimStyle *dim_style)
869 AdgDimStylePrivate *data;
871 g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style), 0);
873 data = dim_style->data;
875 return data->baseline_spacing;
879 * adg_dim_style_set_limits_spacing:
880 * @dim_style: an #AdgDimStyle object
881 * @spacing: the new spacing
883 * Sets a new #AdgDimStyle:limits-spacing value.
885 void
886 adg_dim_style_set_limits_spacing(AdgDimStyle *dim_style, gdouble spacing)
888 g_return_if_fail(ADG_IS_DIM_STYLE(dim_style));
890 if (set_limits_spacing(dim_style, spacing))
891 g_object_notify((GObject *) dim_style, "limits-spacing");
895 * adg_dim_style_get_limits_spacing:
896 * @dim_style: an #AdgDimStyle object
898 * Gets the distance (in global space) between the limits/tolerances.
900 * Returns: the requested spacing
902 gdouble
903 adg_dim_style_get_limits_spacing(AdgDimStyle *dim_style)
905 AdgDimStylePrivate *data;
907 g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style), 0);
909 data = dim_style->data;
911 return data->limits_spacing;
915 * adg_dim_style_set_quote_shift:
916 * @dim_style: an #AdgDimStyle object
917 * @shift: the new displacement
919 * Sets a new #AdgDimStyle:quote-shift value.
921 void
922 adg_dim_style_set_quote_shift(AdgDimStyle *dim_style, const AdgPair *shift)
924 g_return_if_fail(ADG_IS_DIM_STYLE(dim_style));
926 if (set_quote_shift(dim_style, shift))
927 g_object_notify((GObject *) dim_style, "quote-shift");
931 * adg_dim_style_get_quote_shift:
932 * @dim_style: an #AdgDimStyle object
934 * Gets the smooth displacement of the quote. The returned pointer refers
935 * to an internal allocated struct and must not be modified or freed.
937 * Returns: the requested shift
939 const AdgPair *
940 adg_dim_style_get_quote_shift(AdgDimStyle *dim_style)
942 AdgDimStylePrivate *data;
944 g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style), NULL);
946 data = dim_style->data;
948 return &data->quote_shift;
952 * adg_dim_style_set_limits_shift:
953 * @dim_style: an #AdgDimStyle object
954 * @shift: the new displacement
956 * Sets a new #AdgDimStyle:limits-shift value.
958 void
959 adg_dim_style_set_limits_shift(AdgDimStyle *dim_style, const AdgPair *shift)
961 g_return_if_fail(ADG_IS_DIM_STYLE(dim_style));
963 if (set_limits_shift(dim_style, shift))
964 g_object_notify((GObject *) dim_style, "limits-shift");
968 * adg_dim_style_get_limits_shift:
969 * @dim_style: an #AdgDimStyle object
971 * Gets the smooth displacement for the limits. The returned pointer
972 * refers to an internal allocated struct and must not be modified or freed.
974 * Returns: the requested shift
976 const AdgPair *
977 adg_dim_style_get_limits_shift(AdgDimStyle *dim_style)
979 AdgDimStylePrivate *data;
981 g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style), NULL);
983 data = dim_style->data;
985 return &data->limits_shift;
989 * adg_dim_style_set_number_format:
990 * @dim_style: an #AdgDimStyle object
991 * @format: the new format to adopt
993 * Sets a new value in the #AdgDimStyle:number-format property.
995 void
996 adg_dim_style_set_number_format(AdgDimStyle *dim_style, const gchar *format)
998 g_return_if_fail(ADG_IS_DIM_STYLE(dim_style));
1000 set_number_format(dim_style, format);
1001 g_object_notify((GObject *) dim_style, "number-format");
1005 * adg_dim_style_get_number_format:
1006 * @dim_style: an #AdgDimStyle object
1008 * Gets the number format (in printf style) of this quoting style. The
1009 * returned pointer refers to internally managed text that must not be
1010 * modified or freed.
1012 * Returns: the requested format
1014 const gchar *
1015 adg_dim_style_get_number_format(AdgDimStyle *dim_style)
1017 AdgDimStylePrivate *data;
1019 g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style), NULL);
1021 data = dim_style->data;
1023 return data->number_format;
1027 * adg_dim_style_set_number_tag:
1028 * @dim_style: an #AdgDimStyle object
1029 * @tag: the new tag
1031 * Sets a new value in the #AdgDimStyle:number-tag property.
1033 void
1034 adg_dim_style_set_number_tag(AdgDimStyle *dim_style, const gchar *tag)
1036 g_return_if_fail(ADG_IS_DIM_STYLE(dim_style));
1038 set_number_tag(dim_style, tag);
1039 g_object_notify((GObject *) dim_style, "number-tag");
1043 * adg_dim_style_get_number_tag:
1044 * @dim_style: an #AdgDimStyle object
1046 * Gets the number tag to substitute while building the basic value. The
1047 * returned pointer refers to internally managed text that must not be
1048 * modified or freed.
1050 * Returns: the requested tag
1052 const gchar *
1053 adg_dim_style_get_number_tag(AdgDimStyle *dim_style)
1055 AdgDimStylePrivate *data;
1057 g_return_val_if_fail(ADG_IS_DIM_STYLE(dim_style), NULL);
1059 data = dim_style->data;
1061 return data->number_tag;
1065 static void
1066 apply(AdgStyle *style, AdgEntity *entity, cairo_t *cr)
1068 AdgDimStylePrivate *data = ((AdgDimStyle *) style)->data;
1070 adg_entity_apply_dress(entity, data->color_dress, cr);
1073 static gboolean
1074 set_from_offset(AdgDimStyle *dim_style, gdouble offset)
1076 AdgDimStylePrivate *data = dim_style->data;
1078 /* A better approach would be to use the GParamSpec of this property */
1079 g_return_val_if_fail(offset >= 0, FALSE);
1081 if (data->from_offset == offset)
1082 return FALSE;
1084 data->from_offset = offset;
1085 return TRUE;
1088 static gboolean
1089 set_to_offset(AdgDimStyle *dim_style, gdouble offset)
1091 AdgDimStylePrivate *data = dim_style->data;
1093 /* A better approach would be to use the GParamSpec of this property */
1094 g_return_val_if_fail(offset >= 0, FALSE);
1096 if (data->to_offset == offset)
1097 return FALSE;
1099 data->to_offset = offset;
1100 return TRUE;
1103 static gboolean
1104 set_baseline_spacing(AdgDimStyle *dim_style, gdouble spacing)
1106 AdgDimStylePrivate *data = dim_style->data;
1108 /* A better approach would be to use the GParamSpec of this property */
1109 g_return_val_if_fail(spacing >= 0, FALSE);
1111 if (data->baseline_spacing == spacing)
1112 return FALSE;
1114 data->baseline_spacing = spacing;
1115 return TRUE;
1118 static gboolean
1119 set_limits_spacing(AdgDimStyle *dim_style, gdouble spacing)
1121 AdgDimStylePrivate *data = dim_style->data;
1123 /* A better approach would be to use the GParamSpec of this property */
1124 g_return_val_if_fail(spacing >= 0, FALSE);
1126 if (data->limits_spacing == spacing)
1127 return FALSE;
1129 data->limits_spacing = spacing;
1130 return TRUE;
1133 static gboolean
1134 set_beyond(AdgDimStyle *dim_style, gdouble beyond)
1136 AdgDimStylePrivate *data = dim_style->data;
1138 /* A better approach would be to use the GParamSpec of this property */
1139 g_return_val_if_fail(beyond >= 0, FALSE);
1141 if (data->beyond == beyond)
1142 return FALSE;
1144 data->beyond = beyond;
1145 return TRUE;
1148 static gboolean
1149 set_quote_shift(AdgDimStyle *dim_style, const AdgPair *shift)
1151 AdgDimStylePrivate *data;
1153 g_return_val_if_fail(shift != NULL, FALSE);
1155 data = dim_style->data;
1157 if (adg_pair_equal(&data->quote_shift, shift))
1158 return FALSE;
1160 data->quote_shift = *shift;
1162 return TRUE;
1165 static gboolean
1166 set_limits_shift(AdgDimStyle *dim_style, const AdgPair *shift)
1168 AdgDimStylePrivate *data;
1170 g_return_val_if_fail(shift != NULL, FALSE);
1172 data = dim_style->data;
1174 if (adg_pair_equal(&data->limits_shift, shift))
1175 return FALSE;
1177 data->limits_shift = *shift;
1179 return TRUE;
1182 static void
1183 set_number_format(AdgDimStyle *dim_style, const gchar *format)
1185 AdgDimStylePrivate *data = dim_style->data;
1187 g_free(data->number_format);
1188 data->number_format = g_strdup(format);
1191 static void
1192 set_number_tag(AdgDimStyle *dim_style, const gchar *tag)
1194 AdgDimStylePrivate *data = dim_style->data;
1196 g_free(data->number_tag);
1197 data->number_tag = g_strdup(tag);
1200 static AdgMarker *
1201 marker_new(const AdgMarkerData *marker_data)
1203 if (marker_data->type == 0)
1204 return NULL;
1206 return g_object_newv(marker_data->type,
1207 marker_data->n_parameters,
1208 marker_data->parameters);
1211 static gboolean
1212 set_marker(AdgMarkerData *marker_data, AdgMarker *marker)
1214 g_return_val_if_fail(marker == NULL || ADG_IS_MARKER(marker), FALSE);
1216 /* Free the previous marker data, if any */
1217 free_marker(marker_data);
1219 if (marker) {
1220 GObject *object;
1221 GParamSpec **specs;
1222 GParamSpec *spec;
1223 GParameter *parameter;
1224 guint n;
1226 object = (GObject *) marker;
1227 specs = g_object_class_list_properties(G_OBJECT_GET_CLASS(marker),
1228 &marker_data->n_parameters);
1230 marker_data->type = G_TYPE_FROM_INSTANCE(marker);
1231 marker_data->parameters = g_new0(GParameter, marker_data->n_parameters);
1233 for (n = 0; n < marker_data->n_parameters; ++n) {
1234 spec = specs[n];
1235 parameter = &marker_data->parameters[n];
1237 /* Using intern strings because GParameter:name is const.
1238 * GObject properties are internally managed using non-static
1239 * GQuark, so g_intern_string() is the way to go */
1240 parameter->name = g_intern_string(spec->name);
1242 g_value_init(&parameter->value, spec->value_type);
1243 g_object_get_property(object, spec->name, &parameter->value);
1246 g_free(specs);
1249 return TRUE;
1252 static void
1253 free_marker(AdgMarkerData *marker_data)
1255 guint n;
1257 for (n = 0; n < marker_data->n_parameters; ++n)
1258 g_value_unset(&marker_data->parameters[n].value);
1260 marker_data->type = 0;
1261 marker_data->n_parameters = 0;
1262 marker_data->parameters = NULL;