[AdgCanvas] Added "size" property
[adg.git] / src / adg / adg-canvas.c
blobe70624da5393c614eaf91685cd987592ad4018a5
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-canvas
23 * @short_description: The drawing container
25 * The canvas is the toplevel entity of an ADG drawing. It can be
26 * bound to a GTK+ widget, such as #AdgGtkArea, or manually rendered
27 * to a custom surface.
28 **/
30 /**
31 * AdgCanvas:
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-canvas.h"
40 #include "adg-canvas-private.h"
41 #include "adg-dress-builtins.h"
42 #include "adg-color-style.h"
44 #define _ADG_OLD_OBJECT_CLASS ((GObjectClass *) adg_canvas_parent_class)
45 #define _ADG_OLD_ENTITY_CLASS ((AdgEntityClass *) adg_canvas_parent_class)
48 G_DEFINE_TYPE(AdgCanvas, adg_canvas, ADG_TYPE_CONTAINER);
50 enum {
51 PROP_0,
52 PROP_SIZE,
53 PROP_BACKGROUND_DRESS,
54 PROP_FRAME_DRESS,
55 PROP_TITLE_BLOCK,
56 PROP_TOP_MARGIN,
57 PROP_RIGHT_MARGIN,
58 PROP_BOTTOM_MARGIN,
59 PROP_LEFT_MARGIN,
60 PROP_HAS_FRAME,
61 PROP_TOP_PADDING,
62 PROP_RIGHT_PADDING,
63 PROP_BOTTOM_PADDING,
64 PROP_LEFT_PADDING
68 static void _adg_dispose (GObject *object);
69 static void _adg_get_property (GObject *object,
70 guint param_id,
71 GValue *value,
72 GParamSpec *pspec);
73 static void _adg_set_property (GObject *object,
74 guint param_id,
75 const GValue *value,
76 GParamSpec *pspec);
77 static void _adg_global_changed (AdgEntity *entity);
78 static void _adg_local_changed (AdgEntity *entity);
79 static void _adg_invalidate (AdgEntity *entity);
80 static void _adg_arrange (AdgEntity *entity);
81 static void _adg_render (AdgEntity *entity,
82 cairo_t *cr);
85 static void
86 adg_canvas_class_init(AdgCanvasClass *klass)
88 GObjectClass *gobject_class;
89 AdgEntityClass *entity_class;
90 GParamSpec *param;
92 gobject_class = (GObjectClass *) klass;
93 entity_class = (AdgEntityClass *) klass;
95 g_type_class_add_private(klass, sizeof(AdgCanvasPrivate));
97 gobject_class->dispose = _adg_dispose;
98 gobject_class->get_property = _adg_get_property;
99 gobject_class->set_property = _adg_set_property;
101 entity_class->global_changed = _adg_global_changed;
102 entity_class->local_changed = _adg_local_changed;
103 entity_class->invalidate = _adg_invalidate;
104 entity_class->arrange = _adg_arrange;
105 entity_class->render = _adg_render;
107 param = g_param_spec_boxed("size",
108 P_("Canvas Size"),
109 P_("The size set on this canvas: use 0 to have an automatic dimension based on the canvas extents"),
110 ADG_TYPE_PAIR,
111 G_PARAM_READWRITE);
112 g_object_class_install_property(gobject_class, PROP_SIZE, param);
114 param = adg_param_spec_dress("background-dress",
115 P_("Background Dress"),
116 P_("The color dress to use for the canvas background"),
117 ADG_DRESS_COLOR_BACKGROUND,
118 G_PARAM_READWRITE);
119 g_object_class_install_property(gobject_class, PROP_BACKGROUND_DRESS, param);
121 param = adg_param_spec_dress("frame-dress",
122 P_("Frame Dress"),
123 P_("Line dress to use while drawing the frame around the canvas"),
124 ADG_DRESS_LINE_FRAME,
125 G_PARAM_READWRITE);
126 g_object_class_install_property(gobject_class, PROP_FRAME_DRESS, param);
128 param = g_param_spec_object("title-block",
129 P_("Title Block"),
130 P_("The title block to assign to this canvas"),
131 ADG_TYPE_TITLE_BLOCK,
132 G_PARAM_READWRITE);
133 g_object_class_install_property(gobject_class, PROP_TITLE_BLOCK, param);
135 param = g_param_spec_double("top-margin",
136 P_("Top Margin"),
137 P_("The margin (in identity space) to leave above the frame"),
138 G_MINDOUBLE, G_MAXDOUBLE, 15,
139 G_PARAM_READWRITE);
140 g_object_class_install_property(gobject_class, PROP_TOP_MARGIN, param);
142 param = g_param_spec_double("right-margin",
143 P_("Right Margin"),
144 P_("The margin (in identity space) to leave empty at the right of the frame"),
145 G_MINDOUBLE, G_MAXDOUBLE, 15,
146 G_PARAM_READWRITE);
147 g_object_class_install_property(gobject_class, PROP_RIGHT_MARGIN, param);
149 param = g_param_spec_double("bottom-margin",
150 P_("Bottom Margin"),
151 P_("The margin (in identity space) to leave empty below the frame"),
152 G_MINDOUBLE, G_MAXDOUBLE, 15,
153 G_PARAM_READWRITE);
154 g_object_class_install_property(gobject_class, PROP_BOTTOM_MARGIN, param);
156 param = g_param_spec_double("left-margin",
157 P_("Left Margin"),
158 P_("The margin (in identity space) to leave empty at the left of the frame"),
159 G_MINDOUBLE, G_MAXDOUBLE, 15,
160 G_PARAM_READWRITE);
161 g_object_class_install_property(gobject_class, PROP_LEFT_MARGIN, param);
163 param = g_param_spec_boolean("has-frame",
164 P_("Has Frame Flag"),
165 P_("If enabled, a frame using the frame dress will be drawn around the canvas extents, taking into account the margins"),
166 TRUE,
167 G_PARAM_READWRITE);
168 g_object_class_install_property(gobject_class, PROP_HAS_FRAME, param);
170 param = g_param_spec_double("top-padding",
171 P_("Top Padding"),
172 P_("The padding (in identity space) to leave empty above between the drawing and the frame"),
173 G_MINDOUBLE, G_MAXDOUBLE, 15,
174 G_PARAM_READWRITE);
175 g_object_class_install_property(gobject_class, PROP_TOP_PADDING, param);
177 param = g_param_spec_double("right-padding",
178 P_("Right Padding"),
179 P_("The padding (in identity space) to leave empty at the right between the drawing and the frame"),
180 G_MINDOUBLE, G_MAXDOUBLE, 15,
181 G_PARAM_READWRITE);
182 g_object_class_install_property(gobject_class, PROP_RIGHT_PADDING, param);
184 param = g_param_spec_double("bottom-padding",
185 P_("Bottom Padding"),
186 P_("The padding (in identity space) to leave empty below between the drawing and the frame"),
187 G_MINDOUBLE, G_MAXDOUBLE, 15,
188 G_PARAM_READWRITE);
189 g_object_class_install_property(gobject_class, PROP_BOTTOM_PADDING, param);
191 param = g_param_spec_double("left-padding",
192 P_("Left Padding"),
193 P_("The padding (in identity space) to leave empty at the left between the drawing and the frame"),
194 G_MINDOUBLE, G_MAXDOUBLE, 15,
195 G_PARAM_READWRITE);
196 g_object_class_install_property(gobject_class, PROP_LEFT_PADDING, param);
199 static void
200 adg_canvas_init(AdgCanvas *canvas)
202 AdgCanvasPrivate *data = G_TYPE_INSTANCE_GET_PRIVATE(canvas,
203 ADG_TYPE_CANVAS,
204 AdgCanvasPrivate);
206 data->size.x = 0;
207 data->size.y = 0;
208 data->background_dress = ADG_DRESS_COLOR_BACKGROUND;
209 data->frame_dress = ADG_DRESS_LINE_FRAME;
210 data->title_block = NULL;
211 data->top_margin = 15;
212 data->right_margin = 15;
213 data->bottom_margin = 15;
214 data->left_margin = 15;
215 data->has_frame = TRUE;
216 data->top_padding = 15;
217 data->right_padding = 15;
218 data->bottom_padding = 15;
219 data->left_padding = 15;
221 canvas->data = data;
224 static void
225 _adg_dispose(GObject *object)
227 AdgCanvasPrivate *data = ((AdgCanvas *) object)->data;
229 if (data->title_block) {
230 g_object_unref(data->title_block);
231 data->title_block = NULL;
234 if (_ADG_OLD_OBJECT_CLASS->dispose)
235 _ADG_OLD_OBJECT_CLASS->dispose(object);
239 static void
240 _adg_get_property(GObject *object, guint prop_id,
241 GValue *value, GParamSpec *pspec)
243 AdgCanvasPrivate *data = ((AdgCanvas *) object)->data;
245 switch (prop_id) {
246 case PROP_SIZE:
247 g_value_set_boxed(value, &data->size);
248 break;
249 case PROP_BACKGROUND_DRESS:
250 g_value_set_int(value, data->background_dress);
251 break;
252 case PROP_FRAME_DRESS:
253 g_value_set_int(value, data->frame_dress);
254 break;
255 case PROP_TITLE_BLOCK:
256 g_value_set_object(value, data->title_block);
257 break;
258 case PROP_TOP_MARGIN:
259 g_value_set_double(value, data->top_margin);
260 break;
261 case PROP_RIGHT_MARGIN:
262 g_value_set_double(value, data->right_margin);
263 break;
264 case PROP_BOTTOM_MARGIN:
265 g_value_set_double(value, data->bottom_margin);
266 break;
267 case PROP_LEFT_MARGIN:
268 g_value_set_double(value, data->left_margin);
269 break;
270 case PROP_HAS_FRAME:
271 g_value_set_boolean(value, data->has_frame);
272 break;
273 case PROP_TOP_PADDING:
274 g_value_set_double(value, data->top_padding);
275 break;
276 case PROP_RIGHT_PADDING:
277 g_value_set_double(value, data->right_padding);
278 break;
279 case PROP_BOTTOM_PADDING:
280 g_value_set_double(value, data->bottom_padding);
281 break;
282 case PROP_LEFT_PADDING:
283 g_value_set_double(value, data->left_padding);
284 break;
285 default:
286 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
287 break;
291 static void
292 _adg_set_property(GObject *object, guint prop_id,
293 const GValue *value, GParamSpec *pspec)
295 AdgCanvas *canvas;
296 AdgCanvasPrivate *data;
297 AdgTitleBlock *title_block;
299 canvas = (AdgCanvas *) object;
300 data = canvas->data;
302 switch (prop_id) {
303 case PROP_SIZE:
304 adg_pair_copy(&data->size, g_value_get_boxed(value));
305 break;
306 case PROP_BACKGROUND_DRESS:
307 data->background_dress = g_value_get_int(value);
308 break;
309 case PROP_FRAME_DRESS:
310 data->frame_dress = g_value_get_int(value);
311 break;
312 case PROP_TITLE_BLOCK:
313 title_block = g_value_get_object(value);
314 if (title_block) {
315 g_object_ref(title_block);
316 adg_entity_set_parent((AdgEntity *) title_block,
317 (AdgEntity *) canvas);
319 if (data->title_block)
320 g_object_unref(data->title_block);
321 data->title_block = title_block;
322 break;
323 case PROP_TOP_MARGIN:
324 data->top_margin = g_value_get_double(value);
325 break;
326 case PROP_RIGHT_MARGIN:
327 data->right_margin = g_value_get_double(value);
328 break;
329 case PROP_BOTTOM_MARGIN:
330 data->bottom_margin = g_value_get_double(value);
331 break;
332 case PROP_LEFT_MARGIN:
333 data->left_margin = g_value_get_double(value);
334 break;
335 case PROP_HAS_FRAME:
336 data->has_frame = g_value_get_boolean(value);
337 break;
338 case PROP_TOP_PADDING:
339 data->top_padding = g_value_get_double(value);
340 break;
341 case PROP_RIGHT_PADDING:
342 data->right_padding = g_value_get_double(value);
343 break;
344 case PROP_BOTTOM_PADDING:
345 data->bottom_padding = g_value_get_double(value);
346 break;
347 case PROP_LEFT_PADDING:
348 data->left_padding = g_value_get_double(value);
349 break;
350 default:
351 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
352 break;
358 * adg_canvas_new:
360 * Creates a new empty canvas object.
362 * Returns: the canvas
364 AdgCanvas *
365 adg_canvas_new(void)
367 return g_object_new(ADG_TYPE_CANVAS, NULL);
371 * adg_canvas_set_size:
372 * @canvas: an #AdgCanvas
373 * @size: the new size for the canvas
375 * Sets a specific size on @canvas. The x and/or y
376 * components of the returned #AdgPair could be %0, in which
377 * case the size returned by adg_entity_get_extents() on
378 * @canvas will be used instead.
380 void
381 adg_canvas_set_size(AdgCanvas *canvas, const AdgPair *size)
383 g_return_if_fail(ADG_IS_CANVAS(canvas));
384 g_return_if_fail(size != NULL);
386 g_object_set((GObject *) canvas, "size", size, NULL);
390 * adg_canvas_set_size_explicit:
391 * @canvas: an #AdgCanvas
392 * @x: the new width of the canvas or %0 to reset
393 * @y: the new height of the canvas or %0 to reset
395 * A convenient function to set the size of @canvas using
396 * explicit coordinates. Check adg_canvas_set_size() for
397 * further details.
399 void
400 adg_canvas_set_size_explicit(AdgCanvas *canvas, gdouble x, gdouble y)
402 AdgPair size;
404 size.x = x;
405 size.y = y;
407 adg_canvas_set_size(canvas, &size);
411 * adg_canvas_get_size:
412 * @canvas: an #AdgCanvas
414 * Gets the specific size set on @canvas. The x and/or y
415 * components of the returned #AdgPair could be %0, in which
416 * case the size returned by adg_entity_get_extents() on
417 * @canvas will be used instead.
419 * Returns: the explicit size set on this canvas or %NULL on errors
421 const AdgPair *
422 adg_canvas_get_size(AdgCanvas *canvas)
424 AdgCanvasPrivate *data;
426 g_return_val_if_fail(ADG_IS_CANVAS(canvas), NULL);
428 data = canvas->data;
429 return &data->size;
433 * adg_canvas_set_background_dress:
434 * @canvas: an #AdgCanvas
435 * @dress: the new #AdgDress to use
437 * Sets a new background dress for rendering @canvas: the new
438 * dress must be a color dress.
440 void
441 adg_canvas_set_background_dress(AdgCanvas *canvas, AdgDress dress)
443 g_return_if_fail(ADG_IS_CANVAS(canvas));
444 g_object_set((GObject *) canvas, "background-dress", dress, NULL);
448 * adg_canvas_get_background_dress:
449 * @canvas: an #AdgCanvas
451 * Gets the background dress to be used in rendering @canvas.
453 * Returns: the current background dress
455 AdgDress
456 adg_canvas_get_background_dress(AdgCanvas *canvas)
458 AdgCanvasPrivate *data;
460 g_return_val_if_fail(ADG_IS_CANVAS(canvas), ADG_DRESS_UNDEFINED);
462 data = canvas->data;
464 return data->background_dress;
468 * adg_canvas_set_frame_dress:
469 * @canvas: an #AdgCanvas
470 * @dress: the new #AdgDress to use
472 * Sets the #AdgCanvas:frame-dress property of @canvas to @dress:
473 * the new dress must be a line dress.
475 void
476 adg_canvas_set_frame_dress(AdgCanvas *canvas, AdgDress dress)
478 g_return_if_fail(ADG_IS_CANVAS(canvas));
479 g_object_set((GObject *) canvas, "frame-dress", dress, NULL);
483 * adg_canvas_get_frame_dress:
484 * @canvas: an #AdgCanvas
486 * Gets the frame dress to be used in rendering the border of @canvas.
488 * Returns: the current frame dress
490 AdgDress
491 adg_canvas_get_frame_dress(AdgCanvas *canvas)
493 AdgCanvasPrivate *data;
495 g_return_val_if_fail(ADG_IS_CANVAS(canvas), ADG_DRESS_UNDEFINED);
497 data = canvas->data;
498 return data->frame_dress;
502 * adg_canvas_set_title_block:
503 * @canvas: an #AdgCanvas
504 * @title_block: a title block
506 * Sets the #AdgCanvas:title-block property of @canvas to @title_block.
508 * Although a title block entity could be added to @canvas in the usual
509 * way, that is using the adg_container_add() method, assigning a title
510 * block with adg_canvas_set_title_block() is somewhat different:
512 * - @title_block will be automatically attached to the bottom right
513 * corner of to the @canvas frame (this could be accomplished in the
514 * usual way too, by resetting the right and bottom paddings);
515 * - the @title_block boundary box is not taken into account while
516 * computing the extents of @canvas.
518 void
519 adg_canvas_set_title_block(AdgCanvas *canvas, AdgTitleBlock *title_block)
521 g_return_if_fail(ADG_IS_CANVAS(canvas));
522 g_return_if_fail(title_block == NULL || ADG_IS_TITLE_BLOCK(title_block));
523 g_object_set((GObject *) canvas, "title-block", title_block, NULL);
527 * adg_canvas_get_title_block:
528 * @canvas: an #AdgCanvas
530 * Gets the #AdgTitleBlock object of @canvas: check
531 * adg_canvas_set_title_block() for details.
533 * Returns: the title block object or %NULL
535 AdgTitleBlock *
536 adg_canvas_get_title_block(AdgCanvas *canvas)
538 AdgCanvasPrivate *data;
540 g_return_val_if_fail(ADG_IS_CANVAS(canvas), NULL);
542 data = canvas->data;
543 return data->title_block;
547 * adg_canvas_set_top_margin:
548 * @canvas: an #AdgCanvas
549 * @value: the new margin, in identity space
551 * Changes the top margin of @canvas by setting #AdgCanvas:top-margin
552 * to @value. Negative values are allowed.
554 void
555 adg_canvas_set_top_margin(AdgCanvas *canvas, gdouble value)
557 g_return_if_fail(ADG_IS_CANVAS(canvas));
558 g_object_set((GObject *) canvas, "top-margin", value, NULL);
562 * adg_canvas_get_top_margin:
563 * @canvas: an #AdgCanvas
565 * Gets the top margin (in identity space) of @canvas.
567 * Returns: the requested margin or %0 on error
569 gdouble
570 adg_canvas_get_top_margin(AdgCanvas *canvas)
572 AdgCanvasPrivate *data;
574 g_return_val_if_fail(ADG_IS_CANVAS(canvas), 0.);
576 data = canvas->data;
577 return data->top_margin;
581 * adg_canvas_set_right_margin:
582 * @canvas: an #AdgCanvas
583 * @value: the new margin, in identity space
585 * Changes the right margin of @canvas by setting #AdgCanvas:right-margin
586 * to @value. Negative values are allowed.
588 void
589 adg_canvas_set_right_margin(AdgCanvas *canvas, gdouble value)
591 g_return_if_fail(ADG_IS_CANVAS(canvas));
592 g_object_set((GObject *) canvas, "right-margin", value, NULL);
596 * adg_canvas_get_right_margin:
597 * @canvas: an #AdgCanvas
599 * Gets the right margin (in identity space) of @canvas.
601 * Returns: the requested margin or %0 on error
603 gdouble
604 adg_canvas_get_right_margin(AdgCanvas *canvas)
606 AdgCanvasPrivate *data;
608 g_return_val_if_fail(ADG_IS_CANVAS(canvas), 0.);
610 data = canvas->data;
611 return data->right_margin;
616 * adg_canvas_set_bottom_margin:
617 * @canvas: an #AdgCanvas
618 * @value: the new margin, in identity space
620 * Changes the bottom margin of @canvas by setting #AdgCanvas:bottom-margin
621 * to @value. Negative values are allowed.
623 void
624 adg_canvas_set_bottom_margin(AdgCanvas *canvas, gdouble value)
626 g_return_if_fail(ADG_IS_CANVAS(canvas));
627 g_object_set((GObject *) canvas, "bottom-margin", value, NULL);
631 * adg_canvas_get_bottom_margin:
632 * @canvas: an #AdgCanvas
634 * Gets the bottom margin (in identity space) of @canvas.
636 * Returns: the requested margin or %0 on error
638 gdouble
639 adg_canvas_get_bottom_margin(AdgCanvas *canvas)
641 AdgCanvasPrivate *data;
643 g_return_val_if_fail(ADG_IS_CANVAS(canvas), 0.);
645 data = canvas->data;
646 return data->bottom_margin;
650 * adg_canvas_set_left_margin:
651 * @canvas: an #AdgCanvas
652 * @value: the new margin, in identity space
654 * Changes the left margin of @canvas by setting #AdgCanvas:left-margin
655 * to @value. Negative values are allowed.
657 void
658 adg_canvas_set_left_margin(AdgCanvas *canvas, gdouble value)
660 g_return_if_fail(ADG_IS_CANVAS(canvas));
661 g_object_set((GObject *) canvas, "left-margin", value, NULL);
665 * adg_canvas_get_left_margin:
666 * @canvas: an #AdgCanvas
668 * Gets the left margin (in identity space) of @canvas.
670 * Returns: the requested margin or %0 on error
672 gdouble
673 adg_canvas_get_left_margin(AdgCanvas *canvas)
675 AdgCanvasPrivate *data;
677 g_return_val_if_fail(ADG_IS_CANVAS(canvas), 0.);
679 data = canvas->data;
680 return data->left_margin;
684 * adg_canvas_set_margins:
685 * @canvas: an #AdgCanvas
686 * @top: top margin, in identity space
687 * @right: right margin, in identity space
688 * @bottom: bottom margin, in identity space
689 * @left: left margin, in identity space
691 * Convenient function to set all the margins at once.
693 void
694 adg_canvas_set_margins(AdgCanvas *canvas, gdouble top, gdouble right,
695 gdouble bottom, gdouble left)
697 g_return_if_fail(ADG_IS_CANVAS(canvas));
698 g_object_set((GObject *) canvas,
699 "top-margin", top,
700 "right-margin", right,
701 "bottom-margin", bottom,
702 "left-margin", left,
703 NULL);
707 * adg_canvas_switch_frame:
708 * @canvas: an #AdgCanvas
709 * @new_state: the new flag status
711 * Sets a new status on the #AdgCanvas:has-frame property: %TRUE
712 * means a border around the canvas extents (less the margins)
713 * should be rendered.
715 void
716 adg_canvas_switch_frame(AdgCanvas *canvas, gboolean new_state)
718 g_return_if_fail(ADG_IS_CANVAS(canvas));
719 g_object_set((GObject *) canvas, "has-frame", new_state, NULL);
723 * adg_canvas_has_frame:
724 * @canvas: an #AdgCanvas
726 * Gets the current status of the #AdgCanvas:has-frame property,
727 * that is whether a border around the canvas extents (less the
728 * margins) should be rendered (%TRUE) or not (%FALSE).
730 * Returns: the current status of the frame flag
732 gboolean
733 adg_canvas_has_frame(AdgCanvas *canvas)
735 AdgCanvasPrivate *data;
737 g_return_val_if_fail(ADG_IS_CANVAS(canvas), FALSE);
739 data = canvas->data;
740 return data->has_frame;
744 * adg_canvas_set_top_padding:
745 * @canvas: an #AdgCanvas
746 * @value: the new padding, in identity space
748 * Changes the top padding of @canvas by setting #AdgCanvas:top-padding
749 * to @value. Negative values are allowed.
751 void
752 adg_canvas_set_top_padding(AdgCanvas *canvas, gdouble value)
754 g_return_if_fail(ADG_IS_CANVAS(canvas));
755 g_object_set((GObject *) canvas, "top-padding", value, NULL);
759 * adg_canvas_get_top_padding:
760 * @canvas: an #AdgCanvas
762 * Gets the top padding (in identity space) of @canvas.
764 * Returns: the requested padding or %0 on error
766 gdouble
767 adg_canvas_get_top_padding(AdgCanvas *canvas)
769 AdgCanvasPrivate *data;
771 g_return_val_if_fail(ADG_IS_CANVAS(canvas), 0.);
773 data = canvas->data;
774 return data->top_padding;
778 * adg_canvas_set_right_padding:
779 * @canvas: an #AdgCanvas
780 * @value: the new padding, in identity space
782 * Changes the right padding of @canvas by setting #AdgCanvas:right-padding
783 * to @value. Negative values are allowed.
785 void
786 adg_canvas_set_right_padding(AdgCanvas *canvas, gdouble value)
788 g_return_if_fail(ADG_IS_CANVAS(canvas));
789 g_object_set((GObject *) canvas, "right-padding", value, NULL);
793 * adg_canvas_get_right_padding:
794 * @canvas: an #AdgCanvas
796 * Gets the right padding (in identity space) of @canvas.
798 * Returns: the requested padding or %0 on error
800 gdouble
801 adg_canvas_get_right_padding(AdgCanvas *canvas)
803 AdgCanvasPrivate *data;
805 g_return_val_if_fail(ADG_IS_CANVAS(canvas), 0.);
807 data = canvas->data;
808 return data->right_padding;
813 * adg_canvas_set_bottom_padding:
814 * @canvas: an #AdgCanvas
815 * @value: the new padding, in identity space
817 * Changes the bottom padding of @canvas by setting #AdgCanvas:bottom-padding
818 * to @value. Negative values are allowed.
820 void
821 adg_canvas_set_bottom_padding(AdgCanvas *canvas, gdouble value)
823 g_return_if_fail(ADG_IS_CANVAS(canvas));
824 g_object_set((GObject *) canvas, "bottom-padding", value, NULL);
828 * adg_canvas_get_bottom_padding:
829 * @canvas: an #AdgCanvas
831 * Gets the bottom padding (in identity space) of @canvas.
833 * Returns: the requested padding or %0 on error
835 gdouble
836 adg_canvas_get_bottom_padding(AdgCanvas *canvas)
838 AdgCanvasPrivate *data;
840 g_return_val_if_fail(ADG_IS_CANVAS(canvas), 0.);
842 data = canvas->data;
843 return data->bottom_padding;
847 * adg_canvas_set_left_padding:
848 * @canvas: an #AdgCanvas
849 * @value: the new padding, in identity space
851 * Changes the left padding of @canvas by setting #AdgCanvas:left-padding
852 * to @value. Negative values are allowed.
854 void
855 adg_canvas_set_left_padding(AdgCanvas *canvas, gdouble value)
857 g_return_if_fail(ADG_IS_CANVAS(canvas));
858 g_object_set((GObject *) canvas, "left-padding", value, NULL);
862 * adg_canvas_get_left_padding:
863 * @canvas: an #AdgCanvas
865 * Gets the left padding (in identity space) of @canvas.
867 * Returns: the requested padding or %0 on error
869 gdouble
870 adg_canvas_get_left_padding(AdgCanvas *canvas)
872 AdgCanvasPrivate *data;
874 g_return_val_if_fail(ADG_IS_CANVAS(canvas), 0.);
876 data = canvas->data;
877 return data->left_padding;
881 * adg_canvas_set_paddings:
882 * @canvas: an #AdgCanvas
883 * @top: top padding, in identity space
884 * @right: right padding, in identity space
885 * @bottom: bottom padding, in identity space
886 * @left: left padding, in identity space
888 * Convenient function to set all the paddings at once.
890 void
891 adg_canvas_set_paddings(AdgCanvas *canvas, gdouble top, gdouble right,
892 gdouble bottom, gdouble left)
894 g_return_if_fail(ADG_IS_CANVAS(canvas));
895 g_object_set((GObject *) canvas,
896 "top-padding", top,
897 "right-padding", right,
898 "bottom-padding", bottom,
899 "left-padding", left,
900 NULL);
904 static void
905 _adg_global_changed(AdgEntity *entity)
907 AdgCanvasPrivate *data = ((AdgCanvas *) entity)->data;
909 if (_ADG_OLD_ENTITY_CLASS->global_changed)
910 _ADG_OLD_ENTITY_CLASS->global_changed(entity);
912 if (data->title_block)
913 adg_entity_global_changed((AdgEntity *) data->title_block);
916 static void
917 _adg_local_changed(AdgEntity *entity)
919 AdgCanvasPrivate *data = ((AdgCanvas *) entity)->data;
921 if (_ADG_OLD_ENTITY_CLASS->local_changed)
922 _ADG_OLD_ENTITY_CLASS->local_changed(entity);
924 if (data->title_block)
925 adg_entity_local_changed((AdgEntity *) data->title_block);
928 static void
929 _adg_invalidate(AdgEntity *entity)
931 AdgCanvasPrivate *data = ((AdgCanvas *) entity)->data;
933 if (_ADG_OLD_ENTITY_CLASS->invalidate)
934 _ADG_OLD_ENTITY_CLASS->invalidate(entity);
936 if (data->title_block)
937 adg_entity_invalidate((AdgEntity *) data->title_block);
940 static void
941 _adg_arrange(AdgEntity *entity)
943 AdgCanvasPrivate *data = ((AdgCanvas *) entity)->data;
944 CpmlExtents extents;
946 if (_ADG_OLD_ENTITY_CLASS->arrange)
947 _ADG_OLD_ENTITY_CLASS->arrange(entity);
949 cpml_extents_copy(&extents, adg_entity_get_extents(entity));
951 /* The extents should be defined, otherwise there is no drawing */
952 g_return_if_fail(extents.is_defined);
954 extents.org.x -= data->left_margin + data->left_padding;
955 extents.org.y -= data->top_margin + data->top_padding;
956 extents.size.x += data->left_margin + data->left_padding;
957 extents.size.x += data->right_margin + data->right_padding;
958 extents.size.y += data->top_margin + data->top_padding;
959 extents.size.y += data->bottom_margin + data->bottom_padding;
960 adg_entity_set_extents(entity, &extents);
962 if (data->title_block) {
963 AdgEntity *title_block_entity;
964 const CpmlExtents *title_block_extents;
965 AdgPair shift;
967 title_block_entity = (AdgEntity *) data->title_block;
968 adg_entity_arrange(title_block_entity);
969 title_block_extents = adg_entity_get_extents(title_block_entity);
971 shift.x = extents.org.x + extents.size.x - title_block_extents->org.x
972 - title_block_extents->size.x - data->right_margin;
973 shift.y = extents.org.y + extents.size.y - title_block_extents->org.y
974 - title_block_extents->size.y - data->bottom_margin;
976 /* The following block could be optimized by skipping tiny shift,
977 * usually left by mathematical roundings */
978 if (shift.x != 0 || shift.y != 0) {
979 AdgMatrix unglobal, map;
980 adg_matrix_copy(&unglobal, adg_entity_get_global_matrix(entity));
981 cairo_matrix_invert(&unglobal);
983 cairo_matrix_transform_distance(&unglobal, &shift.x, &shift.y);
984 cairo_matrix_init_translate(&map, shift.x, shift.y);
985 adg_entity_transform_global_map(title_block_entity, &map,
986 ADG_TRANSFORM_AFTER);
988 adg_entity_global_changed(title_block_entity);
989 adg_entity_arrange(title_block_entity);
994 static void
995 _adg_render(AdgEntity *entity, cairo_t *cr)
997 AdgCanvasPrivate *data;
998 const CpmlExtents *extents;
1000 data = ((AdgCanvas *) entity)->data;
1001 extents = adg_entity_get_extents(entity);
1003 cairo_save(cr);
1005 /* Background fill */
1006 cairo_identity_matrix(cr);
1007 cairo_rectangle(cr, extents->org.x, extents->org.y,
1008 extents->size.x, extents->size.y);
1009 adg_entity_apply_dress(entity, data->background_dress, cr);
1010 cairo_fill(cr);
1012 /* Frame line */
1013 if (data->has_frame) {
1014 CpmlExtents frame;
1015 cpml_extents_copy(&frame, extents);
1017 frame.org.x += data->left_margin;
1018 frame.org.y += data->top_margin;
1019 frame.size.x -= data->left_margin + data->right_margin;
1020 frame.size.y -= data->top_margin + data->bottom_margin;
1022 cairo_rectangle(cr, frame.org.x, frame.org.y,
1023 frame.size.x, frame.size.y);
1024 cairo_set_matrix(cr, adg_entity_get_global_matrix(entity));
1025 adg_entity_apply_dress(entity, data->frame_dress, cr);
1026 cairo_stroke(cr);
1029 cairo_restore(cr);
1031 if (data->title_block)
1032 adg_entity_render((AdgEntity *) data->title_block, cr);
1034 if (_ADG_OLD_ENTITY_CLASS->render)
1035 _ADG_OLD_ENTITY_CLASS->render(entity, cr);