2
* GooCanvas. Copyright (C) 2005-6 Damon Chaplin.
3
* Released under the GNU LGPL license. See COPYING for details.
5
* goocanvasitemsimple.c - abstract base class for canvas items.
9
* SECTION:goocanvasitemsimple
10
* @Title: GooCanvasItemSimple
11
* @Short_Description: the base class for the standard canvas items.
15
* #GooCanvasItemSimple is used as a base class for all of the standard canvas
16
* items. It can also be used as the base class for new custom canvas items.
18
* It provides default implementations for many of the #GooCanvasItem
21
* For very simple items, all that is needed is to implement the create_path()
22
* method. (#GooCanvasEllipse, #GooCanvasRect and #GooCanvasPath do this.)
24
* More complicated items need to implement the update(), paint() and
25
* is_item_at() methods instead. (#GooCanvasImage, #GooCanvasPolyline,
26
* #GooCanvasText and #GooCanvasWidget do this.) They may also need to
27
* override some of the other GooCanvasItem methods such as set_canvas(),
28
* set_parent() or allocate_area() if special code is needed. (#GooCanvasWidget
29
* does this to make sure the #GtkWidget is embedded in the #GooCanvas widget
33
#include <glib/gi18n-lib.h>
35
#include "goocanvasprivate.h"
36
#include "goocanvasitemsimple.h"
37
#include "goocanvas.h"
38
#include "goocanvasatk.h"
44
/* Basic drawing properties. */
51
/* Line style & width properties. */
55
PROP_LINE_JOIN_MITER_LIMIT,
58
/* Font properties. */
63
/* Convenience properties. */
65
PROP_STROKE_COLOR_RGBA,
71
/* Other properties. Note that the order here is important PROP_TRANSFORM
72
must be the first non-style property. see set_property(). */
76
PROP_VISIBILITY_THRESHOLD,
86
static gboolean accessibility_enabled = FALSE;
88
static void canvas_item_interface_init (GooCanvasItemIface *iface);
89
static void goo_canvas_item_simple_dispose (GObject *object);
90
static void goo_canvas_item_simple_finalize (GObject *object);
91
static void goo_canvas_item_simple_get_property (GObject *object,
95
static void goo_canvas_item_simple_set_property (GObject *object,
100
static void goo_canvas_item_simple_default_create_path (GooCanvasItemSimple *simple,
102
static void goo_canvas_item_simple_default_update (GooCanvasItemSimple *simple,
104
static void goo_canvas_item_simple_default_paint (GooCanvasItemSimple *simple,
106
const GooCanvasBounds *bounds);
107
static gboolean goo_canvas_item_simple_default_is_item_at (GooCanvasItemSimple *simple,
111
gboolean is_pointer_event);
114
G_DEFINE_TYPE_WITH_CODE (GooCanvasItemSimple, goo_canvas_item_simple,
116
G_IMPLEMENT_INTERFACE (GOO_TYPE_CANVAS_ITEM,
117
canvas_item_interface_init))
121
goo_canvas_item_simple_install_common_properties (GObjectClass *gobject_class)
123
/* Basic drawing properties. */
124
g_object_class_install_property (gobject_class, PROP_STROKE_PATTERN,
125
g_param_spec_boxed ("stroke-pattern",
127
_("The pattern to use to paint the perimeter of the item, or NULL disable painting"),
128
GOO_TYPE_CAIRO_PATTERN,
131
g_object_class_install_property (gobject_class, PROP_FILL_PATTERN,
132
g_param_spec_boxed ("fill-pattern",
134
_("The pattern to use to paint the interior of the item, or NULL to disable painting"),
135
GOO_TYPE_CAIRO_PATTERN,
138
g_object_class_install_property (gobject_class, PROP_FILL_RULE,
139
g_param_spec_enum ("fill-rule",
141
_("The fill rule used to determine which parts of the item are filled"),
142
GOO_TYPE_CAIRO_FILL_RULE,
143
CAIRO_FILL_RULE_WINDING,
146
g_object_class_install_property (gobject_class, PROP_OPERATOR,
147
g_param_spec_enum ("operator",
149
_("The compositing operator to use"),
150
GOO_TYPE_CAIRO_OPERATOR,
154
g_object_class_install_property (gobject_class, PROP_ANTIALIAS,
155
g_param_spec_enum ("antialias",
157
_("The antialiasing mode to use"),
158
GOO_TYPE_CAIRO_ANTIALIAS,
159
CAIRO_ANTIALIAS_GRAY,
162
/* Line style & width properties. */
163
g_object_class_install_property (gobject_class, PROP_LINE_WIDTH,
164
g_param_spec_double ("line-width",
166
_("The line width to use for the item's perimeter"),
167
0.0, G_MAXDOUBLE, 2.0,
170
g_object_class_install_property (gobject_class, PROP_LINE_CAP,
171
g_param_spec_enum ("line-cap",
173
_("The line cap style to use"),
174
GOO_TYPE_CAIRO_LINE_CAP,
178
g_object_class_install_property (gobject_class, PROP_LINE_JOIN,
179
g_param_spec_enum ("line-join",
181
_("The line join style to use"),
182
GOO_TYPE_CAIRO_LINE_JOIN,
183
CAIRO_LINE_JOIN_MITER,
186
g_object_class_install_property (gobject_class, PROP_LINE_JOIN_MITER_LIMIT,
187
g_param_spec_double ("line-join-miter-limit",
189
_("The smallest angle to use with miter joins, in degrees. Bevel joins will be used below this limit"),
190
0.0, G_MAXDOUBLE, 10.0,
193
g_object_class_install_property (gobject_class, PROP_LINE_DASH,
194
g_param_spec_boxed ("line-dash",
196
_("The dash pattern to use"),
197
GOO_TYPE_CANVAS_LINE_DASH,
200
/* Font properties. */
201
g_object_class_install_property (gobject_class, PROP_FONT,
202
g_param_spec_string ("font",
204
_("The base font to use for the text"),
208
g_object_class_install_property (gobject_class, PROP_FONT_DESC,
209
g_param_spec_boxed ("font-desc",
210
_("Font Description"),
211
_("The attributes specifying which font to use"),
212
PANGO_TYPE_FONT_DESCRIPTION,
215
g_object_class_install_property (gobject_class, PROP_HINT_METRICS,
216
g_param_spec_enum ("hint-metrics",
218
_("The hinting to be used for font metrics"),
219
GOO_TYPE_CAIRO_HINT_METRICS,
220
CAIRO_HINT_METRICS_OFF,
223
/* Convenience properties - writable only. */
224
g_object_class_install_property (gobject_class, PROP_STROKE_COLOR,
225
g_param_spec_string ("stroke-color",
227
_("The color to use for the item's perimeter. To disable painting set the 'stroke-pattern' property to NULL"),
231
g_object_class_install_property (gobject_class, PROP_STROKE_COLOR_RGBA,
232
g_param_spec_uint ("stroke-color-rgba",
233
_("Stroke Color RGBA"),
234
_("The color to use for the item's perimeter, specified as a 32-bit integer value. To disable painting set the 'stroke-pattern' property to NULL"),
238
g_object_class_install_property (gobject_class, PROP_STROKE_PIXBUF,
239
g_param_spec_object ("stroke-pixbuf",
241
_("The pixbuf to use to draw the item's perimeter. To disable painting set the 'stroke-pattern' property to NULL"),
245
g_object_class_install_property (gobject_class, PROP_FILL_COLOR,
246
g_param_spec_string ("fill-color",
248
_("The color to use to paint the interior of the item. To disable painting set the 'fill-pattern' property to NULL"),
252
g_object_class_install_property (gobject_class, PROP_FILL_COLOR_RGBA,
253
g_param_spec_uint ("fill-color-rgba",
254
_("Fill Color RGBA"),
255
_("The color to use to paint the interior of the item, specified as a 32-bit integer value. To disable painting set the 'fill-pattern' property to NULL"),
259
g_object_class_install_property (gobject_class, PROP_FILL_PIXBUF,
260
g_param_spec_object ("fill-pixbuf",
262
_("The pixbuf to use to paint the interior of the item. To disable painting set the 'fill-pattern' property to NULL"),
266
/* Other properties. */
267
g_object_class_override_property (gobject_class, PROP_PARENT,
270
g_object_class_override_property (gobject_class, PROP_VISIBILITY,
273
g_object_class_override_property (gobject_class, PROP_VISIBILITY_THRESHOLD,
274
"visibility-threshold");
276
g_object_class_override_property (gobject_class, PROP_TRANSFORM,
279
g_object_class_override_property (gobject_class, PROP_POINTER_EVENTS,
282
g_object_class_override_property (gobject_class, PROP_TITLE,
285
g_object_class_override_property (gobject_class, PROP_DESCRIPTION,
288
g_object_class_override_property (gobject_class, PROP_CAN_FOCUS,
291
g_object_class_override_property (gobject_class, PROP_TOOLTIP,
295
* GooCanvasItemSimple:clip-path
297
* The sequence of commands describing the clip path of the item, specified
298
* as a string using the same syntax
299
* as in the <ulink url="http://www.w3.org/Graphics/SVG/">Scalable Vector
300
* Graphics (SVG)</ulink> path element.
303
* GooCanvasItemModelSimple:clip-path
305
* The sequence of commands describing the clip path of the item, specified
306
* as a string using the same syntax
307
* as in the <ulink url="http://www.w3.org/Graphics/SVG/">Scalable Vector
308
* Graphics (SVG)</ulink> path element.
310
g_object_class_install_property (gobject_class, PROP_CLIP_PATH,
311
g_param_spec_string ("clip-path",
313
_("The sequence of path commands specifying the clip path"),
317
g_object_class_install_property (gobject_class, PROP_CLIP_FILL_RULE,
318
g_param_spec_enum ("clip-fill-rule",
320
_("The fill rule used to determine which parts of the item are clipped"),
321
GOO_TYPE_CAIRO_FILL_RULE,
322
CAIRO_FILL_RULE_WINDING,
329
goo_canvas_item_simple_class_init (GooCanvasItemSimpleClass *klass)
331
GObjectClass *gobject_class = (GObjectClass*) klass;
333
gobject_class->dispose = goo_canvas_item_simple_dispose;
334
gobject_class->finalize = goo_canvas_item_simple_finalize;
336
gobject_class->get_property = goo_canvas_item_simple_get_property;
337
gobject_class->set_property = goo_canvas_item_simple_set_property;
339
/* Register our accessible factory, but only if accessibility is enabled. */
340
if (!ATK_IS_NO_OP_OBJECT_FACTORY (atk_registry_get_factory (atk_get_default_registry (), GTK_TYPE_WIDGET)))
342
accessibility_enabled = TRUE;
343
atk_registry_set_factory_type (atk_get_default_registry (),
344
GOO_TYPE_CANVAS_ITEM_SIMPLE,
345
goo_canvas_item_accessible_factory_get_type ());
348
goo_canvas_item_simple_install_common_properties (gobject_class);
350
klass->simple_create_path = goo_canvas_item_simple_default_create_path;
351
klass->simple_update = goo_canvas_item_simple_default_update;
352
klass->simple_paint = goo_canvas_item_simple_default_paint;
353
klass->simple_is_item_at = goo_canvas_item_simple_default_is_item_at;
358
goo_canvas_item_simple_init (GooCanvasItemSimple *item)
360
GooCanvasBounds *bounds = &item->bounds;
362
bounds->x1 = bounds->y1 = bounds->x2 = bounds->y2 = 0.0;
363
item->simple_data = g_slice_new0 (GooCanvasItemSimpleData);
364
item->simple_data->visibility = GOO_CANVAS_ITEM_VISIBLE;
365
item->simple_data->pointer_events = GOO_CANVAS_EVENTS_VISIBLE_PAINTED;
366
item->simple_data->clip_fill_rule = CAIRO_FILL_RULE_WINDING;
367
item->need_update = TRUE;
368
item->need_entire_subtree_update = TRUE;
373
goo_canvas_item_simple_reset_model (GooCanvasItemSimple *simple)
377
g_signal_handlers_disconnect_matched (simple->model, G_SIGNAL_MATCH_DATA,
378
0, 0, NULL, NULL, simple);
379
g_object_unref (simple->model);
380
simple->model = NULL;
381
simple->simple_data = NULL;
386
/* Frees the contents of the GooCanvasItemSimpleData, but not the struct. */
388
goo_canvas_item_simple_free_data (GooCanvasItemSimpleData *simple_data)
392
if (simple_data->style)
394
g_object_unref (simple_data->style);
395
simple_data->style = NULL;
398
if (simple_data->clip_path_commands)
400
g_array_free (simple_data->clip_path_commands, TRUE);
401
simple_data->clip_path_commands = NULL;
404
g_slice_free (cairo_matrix_t, simple_data->transform);
405
simple_data->transform = NULL;
411
goo_canvas_item_simple_dispose (GObject *object)
413
GooCanvasItemSimple *simple = (GooCanvasItemSimple*) object;
415
/* Remove the view from the GooCanvas hash table. */
416
if (simple->canvas && simple->model)
417
goo_canvas_unregister_item (simple->canvas,
418
(GooCanvasItemModel*) simple->model);
420
goo_canvas_item_simple_reset_model (simple);
421
goo_canvas_item_simple_free_data (simple->simple_data);
423
G_OBJECT_CLASS (goo_canvas_item_simple_parent_class)->dispose (object);
428
goo_canvas_item_simple_finalize (GObject *object)
430
GooCanvasItemSimple *simple = (GooCanvasItemSimple*) object;
432
g_slice_free (GooCanvasItemSimpleData, simple->simple_data);
433
simple->simple_data = NULL;
435
G_OBJECT_CLASS (goo_canvas_item_simple_parent_class)->finalize (object);
440
goo_canvas_item_simple_get_common_property (GObject *object,
441
GooCanvasItemSimpleData *simple_data,
447
GooCanvasStyle *style = simple_data->style;
449
gdouble line_width = 2.0;
454
/* Basic drawing properties. */
455
case PROP_STROKE_PATTERN:
456
svalue = goo_canvas_style_get_property (style, goo_canvas_style_stroke_pattern_id);
457
g_value_set_boxed (value, svalue ? svalue->data[0].v_pointer : NULL);
459
case PROP_FILL_PATTERN:
460
svalue = goo_canvas_style_get_property (style, goo_canvas_style_fill_pattern_id);
461
g_value_set_boxed (value, svalue ? svalue->data[0].v_pointer : NULL);
464
svalue = goo_canvas_style_get_property (style, goo_canvas_style_fill_rule_id);
465
g_value_set_enum (value, svalue ? svalue->data[0].v_long : CAIRO_FILL_RULE_WINDING);
468
svalue = goo_canvas_style_get_property (style, goo_canvas_style_operator_id);
469
g_value_set_enum (value, svalue ? svalue->data[0].v_long : CAIRO_OPERATOR_OVER);
472
svalue = goo_canvas_style_get_property (style, goo_canvas_style_antialias_id);
473
g_value_set_enum (value, svalue ? svalue->data[0].v_long : CAIRO_ANTIALIAS_GRAY);
476
/* Line style & width properties. */
477
case PROP_LINE_WIDTH:
478
svalue = goo_canvas_style_get_property (style, goo_canvas_style_line_width_id);
480
line_width = svalue->data[0].v_double;
482
line_width = goo_canvas_get_default_line_width (canvas);
483
g_value_set_double (value, line_width);
486
svalue = goo_canvas_style_get_property (style, goo_canvas_style_line_cap_id);
487
g_value_set_enum (value, svalue ? svalue->data[0].v_long : CAIRO_LINE_CAP_BUTT);
490
svalue = goo_canvas_style_get_property (style, goo_canvas_style_line_join_id);
491
g_value_set_enum (value, svalue ? svalue->data[0].v_long : CAIRO_LINE_JOIN_MITER);
493
case PROP_LINE_JOIN_MITER_LIMIT:
494
svalue = goo_canvas_style_get_property (style, goo_canvas_style_line_join_miter_limit_id);
495
g_value_set_double (value, svalue ? svalue->data[0].v_double : 10.0);
498
svalue = goo_canvas_style_get_property (style, goo_canvas_style_line_dash_id);
499
g_value_set_boxed (value, svalue ? svalue->data[0].v_pointer : NULL);
502
/* Font properties. */
504
svalue = goo_canvas_style_get_property (style, goo_canvas_style_font_desc_id);
506
font = pango_font_description_to_string (svalue->data[0].v_pointer);
507
g_value_set_string (value, font);
511
svalue = goo_canvas_style_get_property (style, goo_canvas_style_font_desc_id);
512
g_value_set_boxed (value, svalue ? svalue->data[0].v_pointer : NULL);
514
case PROP_HINT_METRICS:
515
svalue = goo_canvas_style_get_property (style, goo_canvas_style_hint_metrics_id);
516
g_value_set_enum (value, svalue ? svalue->data[0].v_long : CAIRO_HINT_METRICS_OFF);
519
/* Convenience properties. */
520
case PROP_STROKE_COLOR_RGBA:
521
svalue = goo_canvas_style_get_property (style, goo_canvas_style_stroke_pattern_id);
523
goo_canvas_get_rgba_value_from_pattern (svalue->data[0].v_pointer,
526
case PROP_FILL_COLOR_RGBA:
527
svalue = goo_canvas_style_get_property (style, goo_canvas_style_fill_pattern_id);
529
goo_canvas_get_rgba_value_from_pattern (svalue->data[0].v_pointer,
533
/* Other properties. */
535
g_value_set_boxed (value, simple_data->transform);
537
case PROP_VISIBILITY:
538
g_value_set_enum (value, simple_data->visibility);
540
case PROP_VISIBILITY_THRESHOLD:
541
g_value_set_double (value, simple_data->visibility_threshold);
543
case PROP_POINTER_EVENTS:
544
g_value_set_flags (value, simple_data->pointer_events);
547
g_value_set_boolean (value, simple_data->can_focus);
549
case PROP_CLIP_FILL_RULE:
550
g_value_set_enum (value, simple_data->clip_fill_rule);
553
g_value_set_string (value, simple_data->tooltip);
556
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
563
goo_canvas_item_simple_get_property (GObject *object,
568
GooCanvasItemSimple *simple = (GooCanvasItemSimple*) object;
569
GooCanvasItemSimpleData *simple_data = simple->simple_data;
570
AtkObject *accessible;
575
g_value_set_object (value, simple->parent);
578
accessible = atk_gobject_accessible_for_object (object);
579
g_value_set_string (value, atk_object_get_name (accessible));
581
case PROP_DESCRIPTION:
582
accessible = atk_gobject_accessible_for_object (object);
583
g_value_set_string (value, atk_object_get_description (accessible));
586
goo_canvas_item_simple_get_common_property (object, simple_data,
587
simple->canvas, prop_id,
595
goo_canvas_item_simple_set_common_property (GObject *object,
596
GooCanvasItemSimpleData *simple_data,
601
GooCanvasStyle *style;
602
cairo_pattern_t *pattern;
603
gboolean recompute_bounds = FALSE;
604
cairo_matrix_t *transform;
605
GValue tmpval = { 0 };
606
const char *font_name;
607
PangoFontDescription *font_desc = NULL;
609
/* See if we need to create our own style. */
610
if (prop_id < PROP_TRANSFORM)
612
if (!simple_data->style)
614
simple_data->style = goo_canvas_style_new ();
616
else if (!simple_data->own_style)
618
g_object_unref (simple_data->style);
619
simple_data->style = goo_canvas_style_new ();
621
simple_data->own_style = TRUE;
624
style = simple_data->style;
628
/* Basic drawing properties. */
629
case PROP_STROKE_PATTERN:
630
goo_canvas_style_set_property (style, goo_canvas_style_stroke_pattern_id, value);
632
case PROP_FILL_PATTERN:
633
goo_canvas_style_set_property (style, goo_canvas_style_fill_pattern_id, value);
636
goo_canvas_style_set_property (style, goo_canvas_style_fill_rule_id, value);
639
goo_canvas_style_set_property (style, goo_canvas_style_operator_id, value);
642
goo_canvas_style_set_property (style, goo_canvas_style_antialias_id, value);
645
/* Line style & width properties. */
646
case PROP_LINE_WIDTH:
647
goo_canvas_style_set_property (style, goo_canvas_style_line_width_id, value);
648
recompute_bounds = TRUE;
651
goo_canvas_style_set_property (style, goo_canvas_style_line_cap_id, value);
652
recompute_bounds = TRUE;
655
goo_canvas_style_set_property (style, goo_canvas_style_line_join_id, value);
656
recompute_bounds = TRUE;
658
case PROP_LINE_JOIN_MITER_LIMIT:
659
goo_canvas_style_set_property (style, goo_canvas_style_line_join_miter_limit_id,
661
recompute_bounds = TRUE;
664
goo_canvas_style_set_property (style, goo_canvas_style_line_dash_id, value);
665
recompute_bounds = TRUE;
668
/* Font properties. */
670
font_name = g_value_get_string (value);
672
font_desc = pango_font_description_from_string (font_name);
673
g_value_init (&tmpval, PANGO_TYPE_FONT_DESCRIPTION);
674
g_value_take_boxed (&tmpval, font_desc);
675
goo_canvas_style_set_property (style, goo_canvas_style_font_desc_id, &tmpval);
676
g_value_unset (&tmpval);
677
recompute_bounds = TRUE;
680
goo_canvas_style_set_property (style, goo_canvas_style_font_desc_id, value);
681
recompute_bounds = TRUE;
683
case PROP_HINT_METRICS:
684
goo_canvas_style_set_property (style, goo_canvas_style_hint_metrics_id, value);
685
recompute_bounds = TRUE;
688
/* Convenience properties. */
689
case PROP_STROKE_COLOR:
690
pattern = goo_canvas_create_pattern_from_color_value (value);
691
goo_canvas_set_style_property_from_pattern (style, goo_canvas_style_stroke_pattern_id, pattern);
693
case PROP_STROKE_COLOR_RGBA:
694
pattern = goo_canvas_create_pattern_from_rgba_value (value);
695
goo_canvas_set_style_property_from_pattern (style, goo_canvas_style_stroke_pattern_id, pattern);
697
case PROP_STROKE_PIXBUF:
698
pattern = goo_canvas_create_pattern_from_pixbuf_value (value);
699
goo_canvas_set_style_property_from_pattern (style, goo_canvas_style_stroke_pattern_id, pattern);
702
case PROP_FILL_COLOR:
703
pattern = goo_canvas_create_pattern_from_color_value (value);
704
goo_canvas_set_style_property_from_pattern (style, goo_canvas_style_fill_pattern_id, pattern);
706
case PROP_FILL_COLOR_RGBA:
707
pattern = goo_canvas_create_pattern_from_rgba_value (value);
708
goo_canvas_set_style_property_from_pattern (style, goo_canvas_style_fill_pattern_id, pattern);
710
case PROP_FILL_PIXBUF:
711
pattern = goo_canvas_create_pattern_from_pixbuf_value (value);
712
goo_canvas_set_style_property_from_pattern (style, goo_canvas_style_fill_pattern_id, pattern);
715
/* Other properties. */
717
g_slice_free (cairo_matrix_t, simple_data->transform);
718
transform = g_value_get_boxed (value);
719
simple_data->transform = goo_cairo_matrix_copy (transform);
720
recompute_bounds = TRUE;
722
case PROP_VISIBILITY:
723
simple_data->visibility = g_value_get_enum (value);
725
case PROP_VISIBILITY_THRESHOLD:
726
simple_data->visibility_threshold = g_value_get_double (value);
728
case PROP_POINTER_EVENTS:
729
simple_data->pointer_events = g_value_get_flags (value);
732
simple_data->can_focus = g_value_get_boolean (value);
735
if (simple_data->clip_path_commands)
736
g_array_free (simple_data->clip_path_commands, TRUE);
737
simple_data->clip_path_commands = goo_canvas_parse_path_data (g_value_get_string (value));
738
recompute_bounds = TRUE;
740
case PROP_CLIP_FILL_RULE:
741
simple_data->clip_fill_rule = g_value_get_enum (value);
742
recompute_bounds = TRUE;
745
simple_data->tooltip = g_value_dup_string (value);
748
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
752
return recompute_bounds;
757
goo_canvas_item_simple_set_property (GObject *object,
762
GooCanvasItem *item = (GooCanvasItem*) object;
763
GooCanvasItemSimple *simple = (GooCanvasItemSimple*) object;
764
GooCanvasItemSimpleData *simple_data = simple->simple_data;
765
GooCanvasItem *parent;
766
AtkObject *accessible;
767
gboolean recompute_bounds;
771
g_warning ("Can't set property of a canvas item with a model - set the model property instead");
778
parent = g_value_get_object (value);
779
goo_canvas_item_remove (item);
780
goo_canvas_item_add_child (parent, item, -1);
783
accessible = atk_gobject_accessible_for_object (object);
784
atk_object_set_name (accessible, g_value_get_string (value));
786
case PROP_DESCRIPTION:
787
accessible = atk_gobject_accessible_for_object (object);
788
atk_object_set_description (accessible, g_value_get_string (value));
791
recompute_bounds = goo_canvas_item_simple_set_common_property (object,
796
goo_canvas_item_simple_changed (simple, recompute_bounds);
803
goo_canvas_item_simple_get_canvas (GooCanvasItem *item)
805
GooCanvasItemSimple *simple = (GooCanvasItemSimple*) item;
806
return simple->canvas;
811
goo_canvas_item_simple_set_canvas (GooCanvasItem *item,
814
GooCanvasItemSimple *simple = (GooCanvasItemSimple*) item;
815
simple->canvas = canvas;
819
static GooCanvasItem*
820
goo_canvas_item_simple_get_parent (GooCanvasItem *item)
822
GooCanvasItemSimple *simple = (GooCanvasItemSimple*) item;
823
return simple->parent;
828
goo_canvas_item_simple_set_parent (GooCanvasItem *item,
829
GooCanvasItem *parent)
831
GooCanvasItemSimple *simple = (GooCanvasItemSimple*) item;
834
simple->parent = parent;
835
canvas = parent ? goo_canvas_item_get_canvas (parent) : NULL;
836
goo_canvas_item_set_canvas (item, canvas);
837
simple->need_update = TRUE;
838
simple->need_entire_subtree_update = TRUE;
843
* goo_canvas_item_simple_changed:
844
* @item: a #GooCanvasItemSimple.
845
* @recompute_bounds: if the item's bounds need to be recomputed.
847
* This function is intended to be used by subclasses of #GooCanvasItemSimple.
849
* It is used as a callback for the "changed" signal of the item models.
850
* It requests an update or redraw of the item as appropriate.
853
goo_canvas_item_simple_changed (GooCanvasItemSimple *item,
854
gboolean recompute_bounds)
856
GooCanvasItemSimple *simple = (GooCanvasItemSimple*) item;
857
GooCanvasItemSimpleData *simple_data = simple->simple_data;
859
if (recompute_bounds)
861
item->need_entire_subtree_update = TRUE;
862
if (!item->need_update)
864
goo_canvas_item_request_update ((GooCanvasItem*) item);
866
/* Do this after requesting an update, since GooCanvasGroup will
867
ignore the update request if we do this first. */
868
item->need_update = TRUE;
874
goo_canvas_request_item_redraw (item->canvas, &item->bounds, simple_data->is_static);
880
goo_canvas_item_simple_get_transform (GooCanvasItem *item,
881
cairo_matrix_t *matrix)
883
GooCanvasItemSimple *simple = (GooCanvasItemSimple*) item;
884
GooCanvasItemSimpleData *simple_data = simple->simple_data;
886
if (!simple_data->transform)
889
*matrix = *simple_data->transform;
895
goo_canvas_item_simple_set_transform (GooCanvasItem *item,
896
const cairo_matrix_t *transform)
898
GooCanvasItemSimple *simple = (GooCanvasItemSimple*) item;
899
GooCanvasItemSimpleData *simple_data = simple->simple_data;
903
if (!simple_data->transform)
904
simple_data->transform = g_slice_new (cairo_matrix_t);
906
*simple_data->transform = *transform;
910
g_slice_free (cairo_matrix_t, simple_data->transform);
911
simple_data->transform = NULL;
914
goo_canvas_item_simple_changed (simple, TRUE);
918
static GooCanvasStyle*
919
goo_canvas_item_simple_get_style (GooCanvasItem *item)
921
GooCanvasItemSimple *simple = (GooCanvasItemSimple*) item;
923
return simple->simple_data->style;
928
goo_canvas_item_simple_set_style (GooCanvasItem *item,
929
GooCanvasStyle *style)
931
GooCanvasItemSimple *simple = (GooCanvasItemSimple*) item;
932
GooCanvasItemSimpleData *simple_data = simple->simple_data;
934
if (simple_data->style)
935
g_object_unref (simple_data->style);
939
simple_data->style = goo_canvas_style_copy (style);
940
simple_data->own_style = TRUE;
944
simple_data->style = NULL;
945
simple_data->own_style = FALSE;
948
goo_canvas_item_simple_changed (simple, TRUE);
953
goo_canvas_item_simple_get_bounds (GooCanvasItem *item,
954
GooCanvasBounds *bounds)
956
GooCanvasItemSimple *simple = (GooCanvasItemSimple*) item;
958
if (simple->need_update)
959
goo_canvas_item_ensure_updated (item);
961
*bounds = simple->bounds;
966
goo_canvas_item_simple_get_items_at (GooCanvasItem *item,
970
gboolean is_pointer_event,
971
gboolean parent_visible,
974
GooCanvasItemSimpleClass *class = GOO_CANVAS_ITEM_SIMPLE_GET_CLASS (item);
975
GooCanvasItemSimple *simple = (GooCanvasItemSimple*) item;
976
GooCanvasItemSimpleData *simple_data = simple->simple_data;
977
double user_x = x, user_y = y;
978
cairo_matrix_t matrix;
979
gboolean add_item = FALSE;
981
if (simple->need_update)
982
goo_canvas_item_ensure_updated (item);
984
/* Skip the item if the point isn't in the item's bounds. */
985
if (simple->bounds.x1 > x || simple->bounds.x2 < x
986
|| simple->bounds.y1 > y || simple->bounds.y2 < y)
989
/* Check if the item should receive events. */
990
if (is_pointer_event)
992
if (simple_data->pointer_events == GOO_CANVAS_EVENTS_NONE)
994
if (simple_data->pointer_events & GOO_CANVAS_EVENTS_VISIBLE_MASK
996
|| simple_data->visibility <= GOO_CANVAS_ITEM_INVISIBLE
997
|| (simple_data->visibility == GOO_CANVAS_ITEM_VISIBLE_ABOVE_THRESHOLD
998
&& simple->canvas->scale < simple_data->visibility_threshold)))
1003
if (simple_data->transform)
1004
cairo_transform (cr, simple_data->transform);
1006
cairo_device_to_user (cr, &user_x, &user_y);
1008
/* Remove any current translation, to avoid the 16-bit cairo limit. */
1009
cairo_get_matrix (cr, &matrix);
1010
matrix.x0 = matrix.y0 = 0.0;
1011
cairo_set_matrix (cr, &matrix);
1013
/* If the item has a clip path, check if the point is inside it. */
1014
if (simple_data->clip_path_commands)
1016
goo_canvas_create_path (simple_data->clip_path_commands, cr);
1017
cairo_set_fill_rule (cr, simple_data->clip_fill_rule);
1018
if (!cairo_in_fill (cr, user_x, user_y))
1025
add_item = class->simple_is_item_at (simple, user_x, user_y, cr,
1031
return g_list_prepend (found_items, item);
1038
goo_canvas_item_simple_default_is_item_at (GooCanvasItemSimple *simple,
1042
gboolean is_pointer_event)
1044
GooCanvasItemSimpleClass *class = GOO_CANVAS_ITEM_SIMPLE_GET_CLASS (simple);
1046
GooCanvasItemSimpleData *simple_data = simple->simple_data;
1047
GooCanvasPointerEvents pointer_events = GOO_CANVAS_EVENTS_ALL;
1049
if (is_pointer_event)
1050
pointer_events = simple_data->pointer_events;
1052
/* Use the virtual method subclasses define to create the path. */
1053
class->simple_create_path (simple, cr);
1055
if (goo_canvas_item_simple_check_in_path (simple, x, y, cr, pointer_events))
1063
goo_canvas_item_simple_is_visible (GooCanvasItem *item)
1065
GooCanvasItemSimple *simple = (GooCanvasItemSimple*) item;
1066
GooCanvasItemSimpleData *simple_data = simple->simple_data;
1068
if (simple_data->visibility <= GOO_CANVAS_ITEM_INVISIBLE
1069
|| (simple_data->visibility == GOO_CANVAS_ITEM_VISIBLE_ABOVE_THRESHOLD
1070
&& simple->canvas->scale < simple_data->visibility_threshold))
1074
return goo_canvas_item_is_visible (simple->parent);
1081
goo_canvas_item_simple_get_is_static (GooCanvasItem *item)
1083
GooCanvasItemSimple *simple = (GooCanvasItemSimple*) item;
1084
GooCanvasItemSimpleData *simple_data = simple->simple_data;
1086
return simple_data->is_static;
1091
goo_canvas_item_simple_set_is_static (GooCanvasItem *item,
1094
GooCanvasItemSimple *simple = (GooCanvasItemSimple*) item;
1095
GooCanvasItemSimpleData *simple_data = simple->simple_data;
1097
simple_data->is_static = is_static;
1102
* goo_canvas_item_simple_check_style:
1103
* @item: a #GooCanvasItemSimple.
1105
* This function is intended to be used by subclasses of #GooCanvasItemSimple,
1106
* typically in their update() or get_requested_area() methods.
1108
* It ensures that the item's style is setup correctly. If the item has its
1109
* own #GooCanvasStyle it makes sure the parent is set correctly. If it
1110
* doesn't have its own style it uses the parent item's style.
1113
goo_canvas_item_simple_check_style (GooCanvasItemSimple *item)
1115
GooCanvasItemSimpleData *simple_data = item->simple_data;
1116
GooCanvasStyle *parent_style = NULL;
1119
parent_style = goo_canvas_item_get_style (item->parent);
1121
if (simple_data->own_style)
1123
goo_canvas_style_set_parent (simple_data->style, parent_style);
1125
else if (simple_data->style != parent_style)
1127
/* The item doesn't have its own style so we use the parent's (though
1128
that may also be NULL). */
1129
if (simple_data->style)
1130
g_object_unref (simple_data->style);
1132
simple_data->style = parent_style;
1135
g_object_ref (parent_style);
1141
goo_canvas_item_simple_update_internal (GooCanvasItemSimple *simple,
1144
GooCanvasItemSimpleClass *class = GOO_CANVAS_ITEM_SIMPLE_GET_CLASS (simple);
1145
GooCanvasItemSimpleData *simple_data = simple->simple_data;
1146
GooCanvasBounds tmp_bounds;
1147
cairo_matrix_t transform;
1149
simple->need_update = FALSE;
1151
goo_canvas_item_simple_check_style (simple);
1153
cairo_get_matrix (cr, &transform);
1155
class->simple_update (simple, cr);
1157
/* Modify the extents by the item's clip path. */
1158
if (simple_data->clip_path_commands)
1160
cairo_identity_matrix (cr);
1161
goo_canvas_create_path (simple_data->clip_path_commands, cr);
1162
cairo_set_fill_rule (cr, simple_data->clip_fill_rule);
1163
cairo_fill_extents (cr, &tmp_bounds.x1, &tmp_bounds.y1,
1164
&tmp_bounds.x2, &tmp_bounds.y2);
1165
simple->bounds.x1 = MAX (simple->bounds.x1, tmp_bounds.x1);
1166
simple->bounds.y1 = MAX (simple->bounds.y1, tmp_bounds.y1);
1167
simple->bounds.x2 = MIN (simple->bounds.x2, tmp_bounds.x2);
1168
simple->bounds.y2 = MIN (simple->bounds.y2, tmp_bounds.y2);
1170
if (simple->bounds.x1 > simple->bounds.x2)
1171
simple->bounds.x2 = simple->bounds.x1;
1172
if (simple->bounds.y1 > simple->bounds.y2)
1173
simple->bounds.y2 = simple->bounds.y1;
1176
cairo_set_matrix (cr, &transform);
1181
goo_canvas_item_simple_default_update (GooCanvasItemSimple *simple,
1184
GooCanvasItemSimpleClass *class = GOO_CANVAS_ITEM_SIMPLE_GET_CLASS (simple);
1186
/* Use the identity matrix to get the bounds completely in user space. */
1187
cairo_identity_matrix (cr);
1189
class->simple_create_path (simple, cr);
1190
goo_canvas_item_simple_get_path_bounds (simple, cr, &simple->bounds);
1195
goo_canvas_item_simple_update (GooCanvasItem *item,
1196
gboolean entire_tree,
1198
GooCanvasBounds *bounds)
1200
GooCanvasItemSimple *simple = (GooCanvasItemSimple*) item;
1201
GooCanvasItemSimpleData *simple_data = simple->simple_data;
1202
cairo_matrix_t matrix;
1203
double x_offset, y_offset;
1205
if (entire_tree || simple->need_update)
1207
/* Request a redraw of the existing bounds. */
1208
goo_canvas_request_item_redraw (simple->canvas, &simple->bounds, simple_data->is_static);
1211
if (simple_data->transform)
1212
cairo_transform (cr, simple_data->transform);
1214
/* Remove any current translation, to avoid the 16-bit cairo limit. */
1215
cairo_get_matrix (cr, &matrix);
1216
x_offset = matrix.x0;
1217
y_offset = matrix.y0;
1218
matrix.x0 = matrix.y0 = 0.0;
1219
cairo_set_matrix (cr, &matrix);
1221
goo_canvas_item_simple_update_internal (simple, cr);
1223
goo_canvas_item_simple_user_bounds_to_device (simple, cr,
1226
/* Add the translation back to the bounds. */
1227
simple->bounds.x1 += x_offset;
1228
simple->bounds.y1 += y_offset;
1229
simple->bounds.x2 += x_offset;
1230
simple->bounds.y2 += y_offset;
1234
/* Request a redraw of the new bounds. */
1235
goo_canvas_request_item_redraw (simple->canvas, &simple->bounds, simple_data->is_static);
1238
*bounds = simple->bounds;
1243
goo_canvas_item_simple_get_requested_area (GooCanvasItem *item,
1245
GooCanvasBounds *requested_area)
1247
GooCanvasItemSimple *simple = (GooCanvasItemSimple*) item;
1248
GooCanvasItemSimpleData *simple_data = simple->simple_data;
1249
cairo_matrix_t matrix;
1250
double x_offset, y_offset;
1252
/* Request a redraw of the existing bounds. */
1253
goo_canvas_request_item_redraw (simple->canvas, &simple->bounds, simple_data->is_static);
1256
if (simple_data->transform)
1257
cairo_transform (cr, simple_data->transform);
1259
/* Remove any current translation, to avoid the 16-bit cairo limit. */
1260
cairo_get_matrix (cr, &matrix);
1261
x_offset = matrix.x0;
1262
y_offset = matrix.y0;
1263
matrix.x0 = matrix.y0 = 0.0;
1264
cairo_set_matrix (cr, &matrix);
1266
goo_canvas_item_simple_update_internal (simple, cr);
1268
if (simple->simple_data->visibility == GOO_CANVAS_ITEM_HIDDEN)
1270
simple->bounds.x1 = simple->bounds.x2 = 0.0;
1271
simple->bounds.y1 = simple->bounds.y2 = 0.0;
1276
/* FIXME: Maybe optimize by just converting the offsets to user space
1279
/* Convert to device space. */
1280
cairo_user_to_device (cr, &simple->bounds.x1, &simple->bounds.y1);
1281
cairo_user_to_device (cr, &simple->bounds.x2, &simple->bounds.y2);
1283
/* Add the translation back to the bounds. */
1284
simple->bounds.x1 += x_offset;
1285
simple->bounds.y1 += y_offset;
1286
simple->bounds.x2 += x_offset;
1287
simple->bounds.y2 += y_offset;
1289
/* Restore the item's proper transformation matrix. */
1290
matrix.x0 = x_offset;
1291
matrix.y0 = y_offset;
1292
cairo_set_matrix (cr, &matrix);
1294
/* Convert back to user space. */
1295
cairo_device_to_user (cr, &simple->bounds.x1, &simple->bounds.y1);
1296
cairo_device_to_user (cr, &simple->bounds.x2, &simple->bounds.y2);
1299
/* Copy the user bounds to the requested area. */
1300
*requested_area = simple->bounds;
1302
/* Convert to the parent's coordinate space. */
1303
goo_canvas_item_simple_user_bounds_to_parent (simple, cr, requested_area);
1305
/* Convert the item's bounds to device space. */
1306
goo_canvas_item_simple_user_bounds_to_device (simple, cr, &simple->bounds);
1315
goo_canvas_item_simple_allocate_area (GooCanvasItem *item,
1317
const GooCanvasBounds *requested_area,
1318
const GooCanvasBounds *allocated_area,
1322
GooCanvasItemSimple *simple = (GooCanvasItemSimple*) item;
1323
GooCanvasItemSimpleData *simple_data = simple->simple_data;
1325
/* Simple items can't resize at all, so we just adjust the bounds x & y
1326
positions here, and let the item be clipped if necessary. */
1327
simple->bounds.x1 += x_offset;
1328
simple->bounds.y1 += y_offset;
1329
simple->bounds.x2 += x_offset;
1330
simple->bounds.y2 += y_offset;
1332
/* Request a redraw of the new bounds. */
1333
goo_canvas_request_item_redraw (simple->canvas, &simple->bounds, simple_data->is_static);
1338
goo_canvas_item_simple_paint (GooCanvasItem *item,
1340
const GooCanvasBounds *bounds,
1343
GooCanvasItemSimpleClass *class = GOO_CANVAS_ITEM_SIMPLE_GET_CLASS (item);
1344
GooCanvasItemSimple *simple = (GooCanvasItemSimple*) item;
1345
GooCanvasItemSimpleData *simple_data = simple->simple_data;
1347
/* Skip the item if the bounds don't intersect the expose rectangle. */
1348
if (simple->bounds.x1 > bounds->x2 || simple->bounds.x2 < bounds->x1
1349
|| simple->bounds.y1 > bounds->y2 || simple->bounds.y2 < bounds->y1)
1352
/* Check if the item should be visible. */
1353
if (simple_data->visibility <= GOO_CANVAS_ITEM_INVISIBLE
1354
|| (simple_data->visibility == GOO_CANVAS_ITEM_VISIBLE_ABOVE_THRESHOLD
1355
&& scale < simple_data->visibility_threshold))
1359
if (simple_data->transform)
1360
cairo_transform (cr, simple_data->transform);
1362
/* Clip with the item's clip path, if it is set. */
1363
if (simple_data->clip_path_commands)
1365
goo_canvas_create_path (simple_data->clip_path_commands, cr);
1366
cairo_set_fill_rule (cr, simple_data->clip_fill_rule);
1370
class->simple_paint (simple, cr, bounds);
1377
goo_canvas_item_simple_default_paint (GooCanvasItemSimple *simple,
1379
const GooCanvasBounds *bounds)
1381
GooCanvasItemSimpleClass *class = GOO_CANVAS_ITEM_SIMPLE_GET_CLASS (simple);
1383
class->simple_create_path (simple, cr);
1384
goo_canvas_item_simple_paint_path (simple, cr);
1389
goo_canvas_item_simple_default_create_path (GooCanvasItemSimple *simple,
1397
goo_canvas_item_simple_title_changed (GooCanvasItemModelSimple *smodel,
1399
GooCanvasItemSimple *item)
1401
AtkObject *accessible;
1403
accessible = atk_gobject_accessible_for_object (G_OBJECT (item));
1404
atk_object_set_name (accessible, smodel->title);
1409
goo_canvas_item_simple_description_changed (GooCanvasItemModelSimple *smodel,
1411
GooCanvasItemSimple *item)
1413
AtkObject *accessible;
1415
accessible = atk_gobject_accessible_for_object (G_OBJECT (item));
1416
atk_object_set_description (accessible, smodel->description);
1421
goo_canvas_item_simple_setup_accessibility (GooCanvasItemSimple *item)
1423
GooCanvasItemModelSimple *smodel = item->model;
1424
AtkObject *accessible;
1426
accessible = atk_gobject_accessible_for_object (G_OBJECT (item));
1427
if (!ATK_IS_NO_OP_OBJECT (accessible))
1430
atk_object_set_name (accessible, smodel->title);
1431
if (smodel->description)
1432
atk_object_set_description (accessible, smodel->description);
1434
g_signal_connect (smodel, "notify::title",
1435
G_CALLBACK (goo_canvas_item_simple_title_changed),
1437
g_signal_connect (smodel, "notify::description",
1438
G_CALLBACK (goo_canvas_item_simple_description_changed),
1445
goo_canvas_item_model_simple_changed (GooCanvasItemModelSimple *smodel,
1446
gboolean recompute_bounds,
1447
GooCanvasItemSimple *simple)
1449
goo_canvas_item_simple_changed (simple, recompute_bounds);
1453
static GooCanvasItemModel*
1454
goo_canvas_item_simple_get_model (GooCanvasItem *item)
1456
GooCanvasItemSimple *simple = (GooCanvasItemSimple*) item;
1457
return (GooCanvasItemModel*) simple->model;
1462
* goo_canvas_item_simple_set_model:
1463
* @item: a #GooCanvasItemSimple.
1464
* @model: the model that @item will view.
1466
* This function should be called by subclasses of #GooCanvasItemSimple
1467
* in their set_model() method.
1470
goo_canvas_item_simple_set_model (GooCanvasItemSimple *item,
1471
GooCanvasItemModel *model)
1473
g_return_if_fail (model != NULL);
1475
goo_canvas_item_simple_reset_model (item);
1476
goo_canvas_item_simple_free_data (item->simple_data);
1477
g_slice_free (GooCanvasItemSimpleData, item->simple_data);
1479
item->model = g_object_ref (model);
1480
item->simple_data = &item->model->simple_data;
1482
if (accessibility_enabled)
1483
goo_canvas_item_simple_setup_accessibility (item);
1485
g_signal_connect (model, "changed",
1486
G_CALLBACK (goo_canvas_item_model_simple_changed),
1492
goo_canvas_item_simple_set_model_internal (GooCanvasItem *item,
1493
GooCanvasItemModel *model)
1495
goo_canvas_item_simple_set_model ((GooCanvasItemSimple*) item, model);
1500
goo_canvas_item_simple_query_tooltip (GooCanvasItem *item,
1503
gboolean keyboard_tip,
1504
GtkTooltip *tooltip)
1506
GooCanvasItemSimple *simple = (GooCanvasItemSimple*) item;
1507
GooCanvasItemSimpleData *simple_data = simple->simple_data;
1509
if (simple_data->tooltip)
1511
gtk_tooltip_set_markup (tooltip, simple_data->tooltip);
1520
canvas_item_interface_init (GooCanvasItemIface *iface)
1522
iface->get_canvas = goo_canvas_item_simple_get_canvas;
1523
iface->set_canvas = goo_canvas_item_simple_set_canvas;
1525
iface->get_parent = goo_canvas_item_simple_get_parent;
1526
iface->set_parent = goo_canvas_item_simple_set_parent;
1527
iface->get_bounds = goo_canvas_item_simple_get_bounds;
1528
iface->get_items_at = goo_canvas_item_simple_get_items_at;
1529
iface->update = goo_canvas_item_simple_update;
1530
iface->get_requested_area = goo_canvas_item_simple_get_requested_area;
1531
iface->allocate_area = goo_canvas_item_simple_allocate_area;
1532
iface->paint = goo_canvas_item_simple_paint;
1534
iface->get_transform = goo_canvas_item_simple_get_transform;
1535
iface->set_transform = goo_canvas_item_simple_set_transform;
1536
iface->get_style = goo_canvas_item_simple_get_style;
1537
iface->set_style = goo_canvas_item_simple_set_style;
1538
iface->is_visible = goo_canvas_item_simple_is_visible;
1539
iface->get_is_static = goo_canvas_item_simple_get_is_static;
1540
iface->set_is_static = goo_canvas_item_simple_set_is_static;
1542
iface->get_model = goo_canvas_item_simple_get_model;
1543
iface->set_model = goo_canvas_item_simple_set_model_internal;
1545
iface->query_tooltip = goo_canvas_item_simple_query_tooltip;
1550
* goo_canvas_item_simple_paint_path:
1551
* @item: a #GooCanvasItemSimple.
1552
* @cr: a cairo context.
1554
* This function is intended to be used by subclasses of #GooCanvasItemSimple.
1556
* It paints the current path, using the item's style settings.
1559
goo_canvas_item_simple_paint_path (GooCanvasItemSimple *item,
1562
GooCanvasStyle *style = item->simple_data->style;
1564
if (goo_canvas_style_set_fill_options (style, cr))
1565
cairo_fill_preserve (cr);
1567
if (goo_canvas_style_set_stroke_options (style, cr))
1570
cairo_new_path (cr);
1574
/* Returns the bounds of the path, using the item's stroke and fill options,
1575
in device coords. Note that the bounds include both the stroke and the
1576
fill extents, even if they will not be painted. (We need this to handle
1577
the "pointer-events" property.) */
1579
* goo_canvas_item_simple_get_path_bounds:
1580
* @item: a #GooCanvasItemSimple.
1581
* @cr: a cairo context.
1582
* @bounds: the #GooCanvasBounds struct to store the resulting bounding box.
1584
* This function is intended to be used by subclasses of #GooCanvasItemSimple,
1585
* typically in their update() or get_requested_area() methods.
1587
* It calculates the bounds of the current path, using the item's style
1588
* settings, and stores the results in the given #GooCanvasBounds struct.
1590
* The returned bounds contains the bounding box of the path in device space,
1591
* converted to user space coordinates. To calculate the bounds completely in
1592
* user space, use cairo_identity_matrix() to temporarily reset the current
1593
* transformation matrix to the identity matrix.
1596
goo_canvas_item_simple_get_path_bounds (GooCanvasItemSimple *item,
1598
GooCanvasBounds *bounds)
1600
GooCanvasStyle *style = item->simple_data->style;
1601
GooCanvasBounds fill_bounds, stroke_bounds;
1603
/* Calculate the filled extents. */
1604
goo_canvas_style_set_fill_options (style, cr);
1605
cairo_fill_extents (cr, &fill_bounds.x1, &fill_bounds.y1,
1606
&fill_bounds.x2, &fill_bounds.y2);
1608
/* Check the stroke. */
1609
goo_canvas_style_set_stroke_options (style, cr);
1610
cairo_stroke_extents (cr, &stroke_bounds.x1, &stroke_bounds.y1,
1611
&stroke_bounds.x2, &stroke_bounds.y2);
1613
/* Workaround for cairo < 1.4.0. It used to just return odd values
1614
if the path had empty bounds. This fix will work, but only if there is
1615
no transform currently set, since cairo will convert to user space. */
1616
if (cairo_version () < CAIRO_VERSION_ENCODE (1, 4, 0))
1618
if (fill_bounds.x1 == 32767.0 && fill_bounds.x2 == -32768.0)
1619
fill_bounds.x1 = fill_bounds.x2 = 0.0;
1620
if (stroke_bounds.x1 == 32767.0 && stroke_bounds.x2 == -32768.0)
1621
stroke_bounds.x1 = stroke_bounds.x2 = 0.0;
1624
if (fill_bounds.x1 == 0.0 && fill_bounds.x2 == 0.0)
1626
/* The fill bounds are empty so just use the stroke bounds.
1627
If the stroke bounds are also empty the bounds will be all 0.0. */
1628
bounds->x1 = MIN (stroke_bounds.x1, stroke_bounds.x2);
1629
bounds->x2 = MAX (stroke_bounds.x1, stroke_bounds.x2);
1630
bounds->y1 = MIN (stroke_bounds.y1, stroke_bounds.y2);
1631
bounds->y2 = MAX (stroke_bounds.y1, stroke_bounds.y2);
1633
else if (stroke_bounds.x1 == 0.0 && stroke_bounds.x2 == 0.0)
1635
/* The stroke bounds are empty so just use the fill bounds. */
1636
bounds->x1 = MIN (fill_bounds.x1, fill_bounds.x2);
1637
bounds->x2 = MAX (fill_bounds.x1, fill_bounds.x2);
1638
bounds->y1 = MIN (fill_bounds.y1, fill_bounds.y2);
1639
bounds->y2 = MAX (fill_bounds.y1, fill_bounds.y2);
1643
/* Both fill & stoke bounds are non-empty so combine them. */
1644
bounds->x1 = MIN (fill_bounds.x1, fill_bounds.x2);
1645
bounds->x2 = MAX (fill_bounds.x1, fill_bounds.x2);
1646
bounds->y1 = MIN (fill_bounds.y1, fill_bounds.y2);
1647
bounds->y2 = MAX (fill_bounds.y1, fill_bounds.y2);
1649
bounds->x1 = MIN (bounds->x1, stroke_bounds.x1);
1650
bounds->x1 = MIN (bounds->x1, stroke_bounds.x2);
1652
bounds->x2 = MAX (bounds->x2, stroke_bounds.x1);
1653
bounds->x2 = MAX (bounds->x2, stroke_bounds.x2);
1655
bounds->y1 = MIN (bounds->y1, stroke_bounds.y1);
1656
bounds->y1 = MIN (bounds->y1, stroke_bounds.y2);
1658
bounds->y2 = MAX (bounds->y2, stroke_bounds.y1);
1659
bounds->y2 = MAX (bounds->y2, stroke_bounds.y2);
1665
* goo_canvas_item_simple_user_bounds_to_device:
1666
* @item: a #GooCanvasItemSimple.
1667
* @cr: a cairo context.
1668
* @bounds: the bounds of the item, in the item's coordinate space.
1670
* This function is intended to be used by subclasses of #GooCanvasItemSimple,
1671
* typically in their update() or get_requested_area() methods.
1673
* It converts the item's bounds to a bounding box in the canvas (device)
1677
goo_canvas_item_simple_user_bounds_to_device (GooCanvasItemSimple *item,
1679
GooCanvasBounds *bounds)
1681
GooCanvasBounds tmp_bounds = *bounds, tmp_bounds2 = *bounds;
1683
/* Convert the top-left and bottom-right corners to device coords. */
1684
cairo_user_to_device (cr, &tmp_bounds.x1, &tmp_bounds.y1);
1685
cairo_user_to_device (cr, &tmp_bounds.x2, &tmp_bounds.y2);
1687
/* Now convert the top-right and bottom-left corners. */
1688
cairo_user_to_device (cr, &tmp_bounds2.x1, &tmp_bounds2.y2);
1689
cairo_user_to_device (cr, &tmp_bounds2.x2, &tmp_bounds2.y1);
1691
/* Calculate the minimum x coordinate seen and put in x1. */
1692
bounds->x1 = MIN (tmp_bounds.x1, tmp_bounds.x2);
1693
bounds->x1 = MIN (bounds->x1, tmp_bounds2.x1);
1694
bounds->x1 = MIN (bounds->x1, tmp_bounds2.x2);
1696
/* Calculate the maximum x coordinate seen and put in x2. */
1697
bounds->x2 = MAX (tmp_bounds.x1, tmp_bounds.x2);
1698
bounds->x2 = MAX (bounds->x2, tmp_bounds2.x1);
1699
bounds->x2 = MAX (bounds->x2, tmp_bounds2.x2);
1701
/* Calculate the minimum y coordinate seen and put in y1. */
1702
bounds->y1 = MIN (tmp_bounds.y1, tmp_bounds.y2);
1703
bounds->y1 = MIN (bounds->y1, tmp_bounds2.y1);
1704
bounds->y1 = MIN (bounds->y1, tmp_bounds2.y2);
1706
/* Calculate the maximum y coordinate seen and put in y2. */
1707
bounds->y2 = MAX (tmp_bounds.y1, tmp_bounds.y2);
1708
bounds->y2 = MAX (bounds->y2, tmp_bounds2.y1);
1709
bounds->y2 = MAX (bounds->y2, tmp_bounds2.y2);
1714
* goo_canvas_item_simple_user_bounds_to_parent:
1715
* @item: a #GooCanvasItemSimple.
1716
* @cr: a cairo context.
1717
* @bounds: the bounds of the item, in the item's coordinate space.
1719
* This function is intended to be used by subclasses of #GooCanvasItemSimple,
1720
* typically in their get_requested_area() method.
1722
* It converts the item's bounds to a bounding box in its parent's coordinate
1723
* space. If the item has no transformation matrix set then no conversion is
1727
goo_canvas_item_simple_user_bounds_to_parent (GooCanvasItemSimple *item,
1729
GooCanvasBounds *bounds)
1731
GooCanvasItemSimpleData *simple_data = item->simple_data;
1732
cairo_matrix_t *transform = simple_data->transform;
1733
GooCanvasBounds tmp_bounds, tmp_bounds2;
1738
tmp_bounds = tmp_bounds2 = *bounds;
1740
/* Convert the top-left and bottom-right corners to parent coords. */
1741
cairo_matrix_transform_point (transform, &tmp_bounds.x1, &tmp_bounds.y1);
1742
cairo_matrix_transform_point (transform, &tmp_bounds.x2, &tmp_bounds.y2);
1744
/* Now convert the top-right and bottom-left corners. */
1745
cairo_matrix_transform_point (transform, &tmp_bounds2.x1, &tmp_bounds2.y2);
1746
cairo_matrix_transform_point (transform, &tmp_bounds2.x2, &tmp_bounds2.y1);
1748
/* Calculate the minimum x coordinate seen and put in x1. */
1749
bounds->x1 = MIN (tmp_bounds.x1, tmp_bounds.x2);
1750
bounds->x1 = MIN (bounds->x1, tmp_bounds2.x1);
1751
bounds->x1 = MIN (bounds->x1, tmp_bounds2.x2);
1753
/* Calculate the maximum x coordinate seen and put in x2. */
1754
bounds->x2 = MAX (tmp_bounds.x1, tmp_bounds.x2);
1755
bounds->x2 = MAX (bounds->x2, tmp_bounds2.x1);
1756
bounds->x2 = MAX (bounds->x2, tmp_bounds2.x2);
1758
/* Calculate the minimum y coordinate seen and put in y1. */
1759
bounds->y1 = MIN (tmp_bounds.y1, tmp_bounds.y2);
1760
bounds->y1 = MIN (bounds->y1, tmp_bounds2.y1);
1761
bounds->y1 = MIN (bounds->y1, tmp_bounds2.y2);
1763
/* Calculate the maximum y coordinate seen and put in y2. */
1764
bounds->y2 = MAX (tmp_bounds.y1, tmp_bounds.y2);
1765
bounds->y2 = MAX (bounds->y2, tmp_bounds2.y1);
1766
bounds->y2 = MAX (bounds->y2, tmp_bounds2.y2);
1771
* goo_canvas_item_simple_check_in_path:
1772
* @item: a #GooCanvasItemSimple.
1773
* @x: the x coordinate of the point.
1774
* @y: the y coordinate of the point.
1775
* @cr: a cairo context.
1776
* @pointer_events: specifies which parts of the path to check.
1778
* This function is intended to be used by subclasses of #GooCanvasItemSimple.
1780
* It checks if the given point is in the current path, using the item's
1783
* Returns: %TRUE if the given point is in the current path.
1786
goo_canvas_item_simple_check_in_path (GooCanvasItemSimple *item,
1790
GooCanvasPointerEvents pointer_events)
1792
GooCanvasStyle *style = item->simple_data->style;
1793
gboolean do_fill, do_stroke;
1795
/* Check the filled path, if required. */
1796
if (pointer_events & GOO_CANVAS_EVENTS_FILL_MASK)
1798
do_fill = goo_canvas_style_set_fill_options (style, cr);
1799
if (!(pointer_events & GOO_CANVAS_EVENTS_PAINTED_MASK) || do_fill)
1801
if (cairo_in_fill (cr, x, y))
1806
/* Check the stroke, if required. */
1807
if (pointer_events & GOO_CANVAS_EVENTS_STROKE_MASK)
1809
do_stroke = goo_canvas_style_set_stroke_options (style, cr);
1810
if (!(pointer_events & GOO_CANVAS_EVENTS_PAINTED_MASK) || do_stroke)
1812
if (cairo_in_stroke (cr, x, y))
1822
* goo_canvas_item_simple_get_line_width:
1823
* @item: a #GooCanvasItemSimple.
1825
* Gets the item's line width.
1827
* Returns: the item's line width.
1830
goo_canvas_item_simple_get_line_width (GooCanvasItemSimple *item)
1834
value = goo_canvas_style_get_property (item->simple_data->style,
1835
goo_canvas_style_line_width_id);
1837
return value->data[0].v_double;
1838
else if (item->canvas)
1839
return goo_canvas_get_default_line_width (item->canvas);
1846
* SECTION:goocanvasitemmodelsimple
1847
* @Title: GooCanvasItemModelSimple
1848
* @Short_Description: the base class for the standard canvas item models.
1852
* #GooCanvasItemModelSimple is used as a base class for the standard canvas
1853
* item models. It can also be used as the base class for new custom canvas
1856
* It provides default implementations for many of the #GooCanvasItemModel
1859
* Subclasses of #GooCanvasItemModelSimple only need to implement the
1860
* create_item() method of the #GooCanvasItemModel interface, to create
1861
* the default canvas item to view the item model.
1865
static void item_model_interface_init (GooCanvasItemModelIface *iface);
1866
static void goo_canvas_item_model_simple_dispose (GObject *object);
1867
static void goo_canvas_item_model_simple_finalize (GObject *object);
1868
static void goo_canvas_item_model_simple_get_property (GObject *object,
1872
static void goo_canvas_item_model_simple_set_property (GObject *object,
1874
const GValue *value,
1877
G_DEFINE_TYPE_WITH_CODE (GooCanvasItemModelSimple,
1878
goo_canvas_item_model_simple, G_TYPE_OBJECT,
1879
G_IMPLEMENT_INTERFACE (GOO_TYPE_CANVAS_ITEM_MODEL,
1880
item_model_interface_init))
1884
goo_canvas_item_model_simple_class_init (GooCanvasItemModelSimpleClass *klass)
1886
GObjectClass *gobject_class = (GObjectClass*) klass;
1888
gobject_class->dispose = goo_canvas_item_model_simple_dispose;
1889
gobject_class->finalize = goo_canvas_item_model_simple_finalize;
1891
gobject_class->get_property = goo_canvas_item_model_simple_get_property;
1892
gobject_class->set_property = goo_canvas_item_model_simple_set_property;
1894
goo_canvas_item_simple_install_common_properties (gobject_class);
1899
goo_canvas_item_model_simple_init (GooCanvasItemModelSimple *smodel)
1901
smodel->simple_data.visibility = GOO_CANVAS_ITEM_VISIBLE;
1902
smodel->simple_data.pointer_events = GOO_CANVAS_EVENTS_VISIBLE_PAINTED;
1903
smodel->simple_data.clip_fill_rule = CAIRO_FILL_RULE_WINDING;
1908
goo_canvas_item_model_simple_dispose (GObject *object)
1910
GooCanvasItemModelSimple *smodel = (GooCanvasItemModelSimple*) object;
1912
goo_canvas_item_simple_free_data (&smodel->simple_data);
1914
G_OBJECT_CLASS (goo_canvas_item_model_simple_parent_class)->dispose (object);
1919
goo_canvas_item_model_simple_finalize (GObject *object)
1921
/*GooCanvasItemModelSimple *smodel = (GooCanvasItemModelSimple*) object;*/
1923
G_OBJECT_CLASS (goo_canvas_item_model_simple_parent_class)->finalize (object);
1928
goo_canvas_item_model_simple_get_property (GObject *object,
1933
GooCanvasItemModelSimple *smodel = (GooCanvasItemModelSimple*) object;
1934
GooCanvasItemSimpleData *simple_data = &smodel->simple_data;
1939
g_value_set_object (value, smodel->parent);
1942
g_value_set_string (value, smodel->title);
1944
case PROP_DESCRIPTION:
1945
g_value_set_string (value, smodel->description);
1948
goo_canvas_item_simple_get_common_property (object, simple_data, NULL,
1949
prop_id, value, pspec);
1955
extern void _goo_canvas_item_model_emit_changed (GooCanvasItemModel *model,
1956
gboolean recompute_bounds);
1959
goo_canvas_item_model_simple_set_property (GObject *object,
1961
const GValue *value,
1964
GooCanvasItemModel *model = (GooCanvasItemModel*) object;
1965
GooCanvasItemModelSimple *smodel = (GooCanvasItemModelSimple*) object;
1966
GooCanvasItemSimpleData *simple_data = &smodel->simple_data;
1967
GooCanvasItemModel *parent;
1968
gboolean recompute_bounds;
1973
parent = g_value_get_object (value);
1974
goo_canvas_item_model_remove (model);
1975
goo_canvas_item_model_add_child (parent, model, -1);
1978
g_free (smodel->title);
1979
smodel->title = g_value_dup_string (value);
1981
case PROP_DESCRIPTION:
1982
g_free (smodel->description);
1983
smodel->description = g_value_dup_string (value);
1986
recompute_bounds = goo_canvas_item_simple_set_common_property (object,
1991
_goo_canvas_item_model_emit_changed (model, recompute_bounds);
1997
static GooCanvasItemModel*
1998
goo_canvas_item_model_simple_get_parent (GooCanvasItemModel *model)
2000
GooCanvasItemModelSimple *smodel = (GooCanvasItemModelSimple*) model;
2001
return smodel->parent;
2006
goo_canvas_item_model_simple_set_parent (GooCanvasItemModel *model,
2007
GooCanvasItemModel *parent)
2009
GooCanvasItemModelSimple *smodel = (GooCanvasItemModelSimple*) model;
2010
smodel->parent = parent;
2015
goo_canvas_item_model_simple_get_transform (GooCanvasItemModel *model,
2016
cairo_matrix_t *matrix)
2018
GooCanvasItemModelSimple *smodel = (GooCanvasItemModelSimple*) model;
2019
GooCanvasItemSimpleData *simple_data = &smodel->simple_data;
2021
if (!simple_data->transform)
2024
*matrix = *simple_data->transform;
2030
goo_canvas_item_model_simple_set_transform (GooCanvasItemModel *model,
2031
const cairo_matrix_t *transform)
2033
GooCanvasItemModelSimple *smodel = (GooCanvasItemModelSimple*) model;
2034
GooCanvasItemSimpleData *simple_data = &smodel->simple_data;
2038
if (!simple_data->transform)
2039
simple_data->transform = g_slice_new (cairo_matrix_t);
2041
*simple_data->transform = *transform;
2045
g_slice_free (cairo_matrix_t, simple_data->transform);
2046
simple_data->transform = NULL;
2049
_goo_canvas_item_model_emit_changed (model, TRUE);
2053
static GooCanvasStyle*
2054
goo_canvas_item_model_simple_get_style (GooCanvasItemModel *model)
2056
GooCanvasItemModelSimple *smodel = (GooCanvasItemModelSimple*) model;
2058
return smodel->simple_data.style;
2063
goo_canvas_item_model_simple_set_style (GooCanvasItemModel *model,
2064
GooCanvasStyle *style)
2066
GooCanvasItemModelSimple *smodel = (GooCanvasItemModelSimple*) model;
2067
GooCanvasItemSimpleData *simple_data = &smodel->simple_data;
2069
if (simple_data->style)
2070
g_object_unref (simple_data->style);
2074
simple_data->style = goo_canvas_style_copy (style);
2075
simple_data->own_style = TRUE;
2079
simple_data->style = NULL;
2080
simple_data->own_style = FALSE;
2083
_goo_canvas_item_model_emit_changed (model, TRUE);
2088
item_model_interface_init (GooCanvasItemModelIface *iface)
2090
iface->get_parent = goo_canvas_item_model_simple_get_parent;
2091
iface->set_parent = goo_canvas_item_model_simple_set_parent;
2092
iface->get_transform = goo_canvas_item_model_simple_get_transform;
2093
iface->set_transform = goo_canvas_item_model_simple_set_transform;
2094
iface->get_style = goo_canvas_item_model_simple_get_style;
2095
iface->set_style = goo_canvas_item_model_simple_set_style;