1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: 8; c-basic-offset: 8 -*- */
3 * Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation
6 * This file is part of the Gnome Library.
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU Lesser General Public License as published by
10 * published by the Free Software Foundation; either the
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 * You should have received a copy of the GNU Lesser General Public License
18 * License along with the Gnome Library; see the file COPYING.LIB. If not,
24 * GnomeCanvas widget - Tk-like canvas widget for Gnome
26 * GnomeCanvas is basically a port of the Tk toolkit's most excellent canvas
27 * widget. Tk is copyrighted by the Regents of the University of California,
28 * Sun Microsystems, and other parties.
31 * Authors: Federico Mena <federico@nuclecu.unam.mx>
32 * Raph Levien <raph@gimp.org>
36 * TO-DO list for the canvas:
38 * - Allow to specify whether GnomeCanvasImage sizes are in units or pixels
39 * (scale or don't scale).
41 * - Implement a flag for gnome_canvas_item_reparent() that tells the function
42 * to keep the item visually in the same place, that is, to keep it in the
43 * same place with respect to the canvas origin.
45 * - GC put functions for items.
47 * - Widget item (finish it).
50 * gnome_canvas_gimme_all_items_contained_in_this_area (GnomeCanvas *canvas,
53 * - Retrofit all the primitive items with microtile support.
55 * - Curve support for line item.
57 * - Arc item (Havoc has it; to be integrated in GnomeCanvasEllipse).
59 * - Sane font handling API.
61 * - Get_arg methods for items:
62 * - How to fetch the outline width and know whether it is in pixels or units?
66 * Raph's TODO list for the antialiased canvas integration:
68 * - ::point() method for text item not accurate when affine transformed.
70 * - Clip rectangle not implemented in aa renderer for text item.
72 * - Clip paths only partially implemented.
74 * - Add more image loading techniques to work around imlib deficiencies.
77 #include "evolution-config.h"
82 #include <gdk/gdkprivate.h>
84 #include <cairo-gobject.h>
85 #include "gailcanvas.h"
86 #include "gnome-canvas.h"
87 #include "gnome-canvas-i18n.h"
88 #include "gnome-canvas-util.h"
90 /* We must run our idle update handler *before* GDK wants to redraw. */
91 #define CANVAS_IDLE_PRIORITY (GDK_PRIORITY_REDRAW - 5)
93 static void gnome_canvas_request_update (GnomeCanvas
*canvas
);
94 static void group_add (GnomeCanvasGroup
*group
,
95 GnomeCanvasItem
*item
);
96 static void group_remove (GnomeCanvasGroup
*group
,
97 GnomeCanvasItem
*item
);
98 static void add_idle (GnomeCanvas
*canvas
);
100 /*** GnomeCanvasItem ***/
102 /* Some convenience stuff */
103 #define GCI_UPDATE_MASK \
104 (GNOME_CANVAS_UPDATE_REQUESTED | \
105 GNOME_CANVAS_UPDATE_AFFINE | \
106 GNOME_CANVAS_UPDATE_CLIP | \
107 GNOME_CANVAS_UPDATE_VISIBILITY)
108 #define GCI_EPSILON 1e-18
109 #define GCI_PRINT_MATRIX(s,a) \
110 g_print ("%s %g %g %g %g %g %g\n", \
111 s, (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5])
123 static gint
emit_event (GnomeCanvas
*canvas
, GdkEvent
*event
);
125 static guint item_signals
[ITEM_LAST_SIGNAL
];
130 G_TYPE_INITIALLY_UNOWNED
)
132 /* Object initialization function for GnomeCanvasItem */
134 gnome_canvas_item_init (GnomeCanvasItem
*item
)
136 item
->flags
|= GNOME_CANVAS_ITEM_VISIBLE
;
138 cairo_matrix_init_identity (&item
->matrix
);
142 * gnome_canvas_item_new:
143 * @parent: The parent group for the new item.
144 * @type: The object type of the item.
145 * @first_arg_name: A list of object argument name/value pairs, NULL-terminated,
146 * used to configure the item. For example, "fill_color", "black",
147 * "width_units", 5.0, NULL.
150 * Creates a new canvas item with @parent as its parent group. The item is
151 * created at the top of its parent's stack, and starts up as visible. The item
152 * is of the specified @type, for example, it can be
153 * gnome_canvas_rect_get_type(). The list of object arguments/value pairs is
154 * used to configure the item. If you need to pass construct time parameters, you
155 * should use g_object_new() to pass the parameters and
156 * gnome_canvas_item_construct() to set up the canvas item.
158 * Return value: The newly-created item.
161 gnome_canvas_item_new (GnomeCanvasGroup
*parent
,
163 const gchar
*first_arg_name
, ...)
165 GnomeCanvasItem
*item
;
168 g_return_val_if_fail (GNOME_IS_CANVAS_GROUP (parent
), NULL
);
169 g_return_val_if_fail (g_type_is_a (type
, gnome_canvas_item_get_type ()), NULL
);
171 item
= GNOME_CANVAS_ITEM (g_object_new (type
, NULL
));
173 va_start (args
, first_arg_name
);
174 gnome_canvas_item_construct (item
, parent
, first_arg_name
, args
);
180 /* Performs post-creation operations on a canvas item (adding it to its parent
184 item_post_create_setup (GnomeCanvasItem
*item
)
186 group_add (GNOME_CANVAS_GROUP (item
->parent
), item
);
188 gnome_canvas_request_redraw (
189 item
->canvas
, item
->x1
, item
->y1
, item
->x2
+ 1, item
->y2
+ 1);
190 item
->canvas
->need_repick
= TRUE
;
193 /* Set_property handler for canvas items */
195 gnome_canvas_item_set_property (GObject
*gobject
,
200 GnomeCanvasItem
*item
;
202 g_return_if_fail (GNOME_IS_CANVAS_ITEM (gobject
));
204 item
= GNOME_CANVAS_ITEM (gobject
);
206 switch (property_id
) {
207 case ITEM_PROP_PARENT
:
208 if (item
->parent
!= NULL
) {
209 g_warning ("Cannot set `parent' argument after item has "
210 "already been constructed.");
211 } else if (g_value_get_object (value
)) {
212 item
->parent
= GNOME_CANVAS_ITEM (g_value_get_object (value
));
213 item
->canvas
= item
->parent
->canvas
;
214 item_post_create_setup (item
);
218 G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject
, property_id
, pspec
);
223 /* Get_property handler for canvas items */
225 gnome_canvas_item_get_property (GObject
*gobject
,
230 GnomeCanvasItem
*item
;
232 g_return_if_fail (GNOME_IS_CANVAS_ITEM (gobject
));
234 item
= GNOME_CANVAS_ITEM (gobject
);
236 switch (property_id
) {
237 case ITEM_PROP_PARENT
:
238 g_value_set_object (value
, item
->parent
);
242 G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject
, property_id
, pspec
);
248 * gnome_canvas_item_construct:
249 * @item: An unconstructed canvas item.
250 * @parent: The parent group for the item.
251 * @first_arg_name: The name of the first argument for configuring the item.
252 * @args: The list of arguments used to configure the item.
254 * Constructs a canvas item; meant for use only by item implementations.
257 gnome_canvas_item_construct (GnomeCanvasItem
*item
,
258 GnomeCanvasGroup
*parent
,
259 const gchar
*first_arg_name
,
262 g_return_if_fail (GNOME_IS_CANVAS_GROUP (parent
));
263 g_return_if_fail (GNOME_IS_CANVAS_ITEM (item
));
265 item
->parent
= GNOME_CANVAS_ITEM (parent
);
266 item
->canvas
= item
->parent
->canvas
;
268 g_object_set_valist (G_OBJECT (item
), first_arg_name
, args
);
270 item_post_create_setup (item
);
273 /* If the item is visible, requests a redraw of it. */
275 redraw_if_visible (GnomeCanvasItem
*item
)
277 if (item
->flags
& GNOME_CANVAS_ITEM_VISIBLE
)
278 gnome_canvas_request_redraw (
279 item
->canvas
, item
->x1
, item
->y1
,
280 item
->x2
+ 1, item
->y2
+ 1);
283 /* Standard object dispose function for canvas items */
285 gnome_canvas_item_dispose (GObject
*object
)
287 GnomeCanvasItem
*item
;
289 g_return_if_fail (GNOME_IS_CANVAS_ITEM (object
));
291 item
= GNOME_CANVAS_ITEM (object
);
294 redraw_if_visible (item
);
296 /* Make the canvas forget about us */
298 if (item
->canvas
&& item
== item
->canvas
->current_item
) {
299 item
->canvas
->current_item
= NULL
;
300 item
->canvas
->need_repick
= TRUE
;
303 if (item
->canvas
&& item
== item
->canvas
->new_current_item
) {
304 item
->canvas
->new_current_item
= NULL
;
305 item
->canvas
->need_repick
= TRUE
;
308 if (item
->canvas
&& item
== item
->canvas
->grabbed_item
) {
309 item
->canvas
->grabbed_item
= NULL
;
312 item
->canvas
->grabbed_device
, GDK_CURRENT_TIME
);
313 g_object_unref (item
->canvas
->grabbed_device
);
314 item
->canvas
->grabbed_device
= NULL
;
317 if (item
->canvas
&& item
== item
->canvas
->focused_item
)
318 item
->canvas
->focused_item
= NULL
;
320 /* Normal dispose stuff */
322 if (item
->flags
& GNOME_CANVAS_ITEM_MAPPED
)
323 (* GNOME_CANVAS_ITEM_GET_CLASS (item
)->unmap
) (item
);
325 if (item
->flags
& GNOME_CANVAS_ITEM_REALIZED
)
326 (* GNOME_CANVAS_ITEM_GET_CLASS (item
)->unrealize
) (item
);
329 group_remove (GNOME_CANVAS_GROUP (item
->parent
), item
);
331 if (GNOME_CANVAS_ITEM_GET_CLASS (item
)->dispose
)
332 GNOME_CANVAS_ITEM_GET_CLASS (item
)->dispose (item
);
334 G_OBJECT_CLASS (gnome_canvas_item_parent_class
)->dispose (object
);
335 /* items should remove any reference to item->canvas after the
340 /* Update handler for canvas items */
342 gnome_canvas_item_update (GnomeCanvasItem
*item
,
343 const cairo_matrix_t
*matrix
,
346 item
->flags
&= ~GNOME_CANVAS_ITEM_NEED_UPDATE
;
347 item
->flags
&= ~GNOME_CANVAS_ITEM_NEED_AFFINE
;
348 item
->flags
&= ~GNOME_CANVAS_ITEM_NEED_CLIP
;
349 item
->flags
&= ~GNOME_CANVAS_ITEM_NEED_VIS
;
352 /* Realize handler for canvas items */
354 gnome_canvas_item_realize (GnomeCanvasItem
*item
)
356 item
->flags
|= GNOME_CANVAS_ITEM_REALIZED
;
358 gnome_canvas_item_request_update (item
);
361 /* Unrealize handler for canvas items */
363 gnome_canvas_item_unrealize (GnomeCanvasItem
*item
)
365 item
->flags
&= ~GNOME_CANVAS_ITEM_REALIZED
;
368 /* Map handler for canvas items */
370 gnome_canvas_item_map (GnomeCanvasItem
*item
)
372 item
->flags
|= GNOME_CANVAS_ITEM_MAPPED
;
375 /* Unmap handler for canvas items */
377 gnome_canvas_item_unmap (GnomeCanvasItem
*item
)
379 item
->flags
&= ~GNOME_CANVAS_ITEM_MAPPED
;
382 /* Dispose handler for canvas items */
384 gnome_canvas_item_dispose_item (GnomeCanvasItem
*item
)
386 /* Placeholder so subclasses can safely chain up. */
390 gnome_canvas_item_draw (GnomeCanvasItem
*item
,
397 /* Placeholder so subclasses can safely chain up. */
400 static GnomeCanvasItem
*
401 gnome_canvas_item_point (GnomeCanvasItem
*item
,
407 /* Placeholder so subclasses can safely chain up. */
413 gnome_canvas_item_bounds (GnomeCanvasItem
*item
,
419 /* Placeholder so subclasses can safely chain up. */
423 gnome_canvas_item_event (GnomeCanvasItem
*item
,
426 /* Placeholder so subclasses can safely chain up. */
428 return FALSE
; /* event was not handled */
432 * This routine invokes the update method of the item
433 * Please notice, that we take parent to canvas pixel matrix as argument
434 * unlike virtual method ::update, whose argument is item 2 canvas pixel
437 * I will try to force somewhat meaningful naming for affines (Lauris)
438 * General naming rule is FROM2TO, where FROM and TO are abbreviations
439 * So p2cpx is Parent2CanvasPixel and i2cpx is Item2CanvasPixel
440 * I hope that this helps to keep track of what really happens
445 gnome_canvas_item_invoke_update (GnomeCanvasItem
*item
,
446 const cairo_matrix_t
*p2c
,
453 if (!(item
->flags
& GNOME_CANVAS_ITEM_VISIBLE
))
454 child_flags
&= ~GNOME_CANVAS_UPDATE_IS_VISIBLE
;
456 /* Calculate actual item transformation matrix */
458 cairo_matrix_multiply (&i2c
, &item
->matrix
, p2c
);
460 /* apply object flags to child flags */
462 child_flags
&= ~GNOME_CANVAS_UPDATE_REQUESTED
;
464 if (item
->flags
& GNOME_CANVAS_ITEM_NEED_UPDATE
)
465 child_flags
|= GNOME_CANVAS_UPDATE_REQUESTED
;
467 if (item
->flags
& GNOME_CANVAS_ITEM_NEED_AFFINE
)
468 child_flags
|= GNOME_CANVAS_UPDATE_AFFINE
;
470 if (item
->flags
& GNOME_CANVAS_ITEM_NEED_CLIP
)
471 child_flags
|= GNOME_CANVAS_UPDATE_CLIP
;
473 if (item
->flags
& GNOME_CANVAS_ITEM_NEED_VIS
)
474 child_flags
|= GNOME_CANVAS_UPDATE_VISIBILITY
;
476 if (child_flags
& GCI_UPDATE_MASK
) {
477 if (GNOME_CANVAS_ITEM_GET_CLASS (item
)->update
)
478 GNOME_CANVAS_ITEM_GET_CLASS (item
)->update (item
, &i2c
, child_flags
);
483 * This routine invokes the point method of the item.
484 * The arguments x, y should be in the parent item local coordinates.
486 * This is potentially evil, as we are relying on matrix inversion (Lauris)
489 static GnomeCanvasItem
*
490 gnome_canvas_item_invoke_point (GnomeCanvasItem
*item
,
496 cairo_matrix_t inverse
;
498 /* Calculate x & y in item local coordinates */
499 inverse
= item
->matrix
;
500 if (cairo_matrix_invert (&inverse
) != CAIRO_STATUS_SUCCESS
)
503 cairo_matrix_transform_point (&inverse
, &x
, &y
);
505 if (GNOME_CANVAS_ITEM_GET_CLASS (item
)->point
)
506 return GNOME_CANVAS_ITEM_GET_CLASS (item
)->point (item
, x
, y
, cx
, cy
);
512 * gnome_canvas_item_set:
513 * @item: A canvas item.
514 * @first_arg_name: The list of object argument name/value pairs used to
515 * configure the item.
518 * Configures a canvas item. The arguments in the item are set to the
519 * specified values, and the item is repainted as appropriate.
522 gnome_canvas_item_set (GnomeCanvasItem
*item
,
523 const gchar
*first_arg_name
,
528 va_start (args
, first_arg_name
);
529 gnome_canvas_item_set_valist (item
, first_arg_name
, args
);
534 * gnome_canvas_item_set_valist:
535 * @item: A canvas item.
536 * @first_arg_name: The name of the first argument used to configure the item.
537 * @args: The list of object argument name/value pairs used to configure the item.
539 * Configures a canvas item. The arguments in the item are set to the specified
540 * values, and the item is repainted as appropriate.
543 gnome_canvas_item_set_valist (GnomeCanvasItem
*item
,
544 const gchar
*first_arg_name
,
547 g_return_if_fail (GNOME_IS_CANVAS_ITEM (item
));
549 g_object_set_valist (G_OBJECT (item
), first_arg_name
, args
);
551 item
->canvas
->need_repick
= TRUE
;
555 * gnome_canvas_item_transform:
556 * @item: A canvas item.
557 * @matrix: An affine transformation matrix.
559 * Combines the specified affine transformation matrix with the item's current
563 gnome_canvas_item_transform (GnomeCanvasItem
*item
,
564 const cairo_matrix_t
*matrix
)
568 g_return_if_fail (GNOME_IS_CANVAS_ITEM (item
));
569 g_return_if_fail (matrix
!= NULL
);
571 /* Calculate actual item transformation matrix */
572 cairo_matrix_multiply (&i2p
, matrix
, &item
->matrix
);
574 gnome_canvas_item_set_matrix (item
, &i2p
);
578 * gnome_canvas_item_set_matrix:
579 * @item: A canvas item.
580 * @matrix: An affine transformation matrix or %NULL for the identity matrix.
582 * Makes the item's affine transformation matrix be equal to the specified
583 * matrix. NULL is treated as identity.
586 gnome_canvas_item_set_matrix (GnomeCanvasItem
*item
,
587 const cairo_matrix_t
*matrix
)
589 g_return_if_fail (GNOME_IS_CANVAS_ITEM (item
));
592 item
->matrix
= *matrix
;
594 cairo_matrix_init_identity (&item
->matrix
);
597 if (!(item
->flags
& GNOME_CANVAS_ITEM_NEED_AFFINE
)) {
599 item
->flags
|= GNOME_CANVAS_ITEM_NEED_AFFINE
;
600 gnome_canvas_item_request_update (item
);
603 item
->canvas
->need_repick
= TRUE
;
607 * gnome_canvas_item_move:
608 * @item: A canvas item.
609 * @dx: Horizontal offset.
610 * @dy: Vertical offset.
612 * Moves a canvas item by creating an affine transformation matrix for
613 * translation by using the specified values. This happens in item
614 * local coordinate system, so if you have nontrivial transform, it
615 * most probably does not do, what you want.
618 gnome_canvas_item_move (GnomeCanvasItem
*item
,
622 cairo_matrix_t translate
;
624 g_return_if_fail (GNOME_IS_CANVAS_ITEM (item
));
626 cairo_matrix_init_translate (&translate
, dx
, dy
);
628 gnome_canvas_item_transform (item
, &translate
);
631 /* Convenience function to reorder items in a group's child list. This puts the
632 * specified link after the "before" link. Returns TRUE if the list was changed.
635 put_item_after (GList
*link
,
638 GnomeCanvasGroup
*parent
;
639 GList
*old_before
, *old_after
;
642 parent
= GNOME_CANVAS_GROUP (GNOME_CANVAS_ITEM (link
->data
)->parent
);
645 after
= before
->next
;
647 after
= parent
->item_list
;
649 if (before
== link
|| after
== link
)
654 old_before
= link
->prev
;
655 old_after
= link
->next
;
658 old_before
->next
= old_after
;
660 parent
->item_list
= old_after
;
663 old_after
->prev
= old_before
;
665 parent
->item_list_end
= old_before
;
673 parent
->item_list
= link
;
679 parent
->item_list_end
= link
;
685 * gnome_canvas_item_raise:
686 * @item: A canvas item.
687 * @positions: Number of steps to raise the item.
689 * Raises the item in its parent's stack by the specified number of positions.
690 * If the number of positions is greater than the distance to the top of the
691 * stack, then the item is put at the top.
694 gnome_canvas_item_raise (GnomeCanvasItem
*item
,
697 GList
*link
, *before
;
698 GnomeCanvasGroup
*parent
;
700 g_return_if_fail (GNOME_IS_CANVAS_ITEM (item
));
701 g_return_if_fail (positions
>= 0);
703 if (!item
->parent
|| positions
== 0)
706 parent
= GNOME_CANVAS_GROUP (item
->parent
);
707 link
= g_list_find (parent
->item_list
, item
);
708 g_return_if_fail (link
!= NULL
);
710 for (before
= link
; positions
&& before
; positions
--)
711 before
= before
->next
;
714 before
= parent
->item_list_end
;
716 if (put_item_after (link
, before
)) {
717 redraw_if_visible (item
);
718 item
->canvas
->need_repick
= TRUE
;
723 * gnome_canvas_item_lower:
724 * @item: A canvas item.
725 * @positions: Number of steps to lower the item.
727 * Lowers the item in its parent's stack by the specified number of positions.
728 * If the number of positions is greater than the distance to the bottom of the
729 * stack, then the item is put at the bottom.
732 gnome_canvas_item_lower (GnomeCanvasItem
*item
,
735 GList
*link
, *before
;
736 GnomeCanvasGroup
*parent
;
738 g_return_if_fail (GNOME_IS_CANVAS_ITEM (item
));
739 g_return_if_fail (positions
>= 1);
741 if (!item
->parent
|| positions
== 0)
744 parent
= GNOME_CANVAS_GROUP (item
->parent
);
745 link
= g_list_find (parent
->item_list
, item
);
746 g_return_if_fail (link
!= NULL
);
749 for (before
= link
->prev
; positions
&& before
; positions
--)
750 before
= before
->prev
;
754 if (put_item_after (link
, before
)) {
755 redraw_if_visible (item
);
756 item
->canvas
->need_repick
= TRUE
;
761 * gnome_canvas_item_raise_to_top:
762 * @item: A canvas item.
764 * Raises an item to the top of its parent's stack.
767 gnome_canvas_item_raise_to_top (GnomeCanvasItem
*item
)
770 GnomeCanvasGroup
*parent
;
772 g_return_if_fail (GNOME_IS_CANVAS_ITEM (item
));
777 parent
= GNOME_CANVAS_GROUP (item
->parent
);
778 link
= g_list_find (parent
->item_list
, item
);
779 g_return_if_fail (link
!= NULL
);
781 if (put_item_after (link
, parent
->item_list_end
)) {
782 redraw_if_visible (item
);
783 item
->canvas
->need_repick
= TRUE
;
788 * gnome_canvas_item_lower_to_bottom:
789 * @item: A canvas item.
791 * Lowers an item to the bottom of its parent's stack.
794 gnome_canvas_item_lower_to_bottom (GnomeCanvasItem
*item
)
797 GnomeCanvasGroup
*parent
;
799 g_return_if_fail (GNOME_IS_CANVAS_ITEM (item
));
804 parent
= GNOME_CANVAS_GROUP (item
->parent
);
805 link
= g_list_find (parent
->item_list
, item
);
806 g_return_if_fail (link
!= NULL
);
808 if (put_item_after (link
, NULL
)) {
809 redraw_if_visible (item
);
810 item
->canvas
->need_repick
= TRUE
;
815 * gnome_canvas_item_show:
816 * @item: A canvas item.
818 * Shows a canvas item. If the item was already shown, then no action is taken.
821 gnome_canvas_item_show (GnomeCanvasItem
*item
)
823 g_return_if_fail (GNOME_IS_CANVAS_ITEM (item
));
825 if (!(item
->flags
& GNOME_CANVAS_ITEM_VISIBLE
)) {
826 item
->flags
|= GNOME_CANVAS_ITEM_VISIBLE
;
827 gnome_canvas_request_redraw (
828 item
->canvas
, item
->x1
, item
->y1
,
829 item
->x2
+ 1, item
->y2
+ 1);
830 item
->canvas
->need_repick
= TRUE
;
835 * gnome_canvas_item_hide:
836 * @item: A canvas item.
838 * Hides a canvas item. If the item was already hidden, then no action is
842 gnome_canvas_item_hide (GnomeCanvasItem
*item
)
844 g_return_if_fail (GNOME_IS_CANVAS_ITEM (item
));
846 if (item
->flags
& GNOME_CANVAS_ITEM_VISIBLE
) {
847 item
->flags
&= ~GNOME_CANVAS_ITEM_VISIBLE
;
848 gnome_canvas_request_redraw (
849 item
->canvas
, item
->x1
, item
->y1
,
850 item
->x2
+ 1, item
->y2
+ 1);
851 item
->canvas
->need_repick
= TRUE
;
856 * gnome_canvas_item_grab:
857 * @item: A canvas item.
858 * @event_mask: Mask of events that will be sent to this item.
859 * @cursor: If non-NULL, the cursor that will be used while the grab is active.
860 * @device: The pointer device to grab.
861 * @etime: The timestamp required for grabbing @device, or GDK_CURRENT_TIME.
863 * Specifies that all events that match the specified event mask should be sent
864 * to the specified item, and also grabs @device by calling gdk_device_grab().
865 * The event mask is also used when grabbing the @device. If @cursor is not
866 * NULL, then that cursor is used while the grab is active. The @etime
867 * parameter is the timestamp required for grabbing the @device.
869 * Return value: If an item was already grabbed, it returns
870 * %GDK_GRAB_ALREADY_GRABBED. If the specified item was hidden by calling
871 * gnome_canvas_item_hide(), then it returns %GDK_GRAB_NOT_VIEWABLE. Else,
872 * it returns the result of calling gdk_device_grab().
875 gnome_canvas_item_grab (GnomeCanvasItem
*item
,
882 GdkWindow
*bin_window
;
885 g_return_val_if_fail (
886 GNOME_IS_CANVAS_ITEM (item
), GDK_GRAB_NOT_VIEWABLE
);
887 g_return_val_if_fail (
888 gtk_widget_get_mapped (GTK_WIDGET (item
->canvas
)),
889 GDK_GRAB_NOT_VIEWABLE
);
890 g_return_val_if_fail (
891 GDK_IS_DEVICE (device
), GDK_GRAB_NOT_VIEWABLE
);
893 if (item
->canvas
->grabbed_item
)
894 return GDK_GRAB_ALREADY_GRABBED
;
896 if (!(item
->flags
& GNOME_CANVAS_ITEM_VISIBLE
))
897 return GDK_GRAB_NOT_VIEWABLE
;
899 layout
= GTK_LAYOUT (item
->canvas
);
900 bin_window
= gtk_layout_get_bin_window (layout
);
902 retval
= gdk_device_grab (
903 device
, bin_window
, GDK_OWNERSHIP_NONE
,
904 FALSE
, event_mask
, cursor
, etime
);
906 if (retval
!= GDK_GRAB_SUCCESS
)
909 item
->canvas
->grabbed_item
= item
;
910 item
->canvas
->grabbed_device
= g_object_ref (device
);
911 item
->canvas
->grabbed_event_mask
= event_mask
;
912 item
->canvas
->current_item
= item
; /* So that events go to the grabbed item */
918 * gnome_canvas_item_ungrab:
919 * @item: A canvas item that holds a grab.
920 * @etime: The timestamp for ungrabbing the mouse.
922 * Ungrabs the item, which must have been grabbed in the canvas, and ungrabs the
926 gnome_canvas_item_ungrab (GnomeCanvasItem
*item
,
929 g_return_if_fail (GNOME_IS_CANVAS_ITEM (item
));
931 if (item
->canvas
->grabbed_item
!= item
)
934 item
->canvas
->grabbed_item
= NULL
;
936 g_return_if_fail (item
->canvas
->grabbed_device
!= NULL
);
937 gdk_device_ungrab (item
->canvas
->grabbed_device
, etime
);
939 g_object_unref (item
->canvas
->grabbed_device
);
940 item
->canvas
->grabbed_device
= NULL
;
944 gnome_canvas_item_i2w_matrix (GnomeCanvasItem
*item
,
945 cairo_matrix_t
*matrix
)
947 g_return_if_fail (GNOME_IS_CANVAS_ITEM (item
));
948 g_return_if_fail (matrix
!= NULL
);
950 cairo_matrix_init_identity (matrix
);
953 cairo_matrix_multiply (matrix
, matrix
, &item
->matrix
);
960 gnome_canvas_item_w2i_matrix (GnomeCanvasItem
*item
,
961 cairo_matrix_t
*matrix
)
963 cairo_status_t status
;
965 g_return_if_fail (GNOME_IS_CANVAS_ITEM (item
));
966 g_return_if_fail (matrix
!= NULL
);
968 gnome_canvas_item_i2w_matrix (item
, matrix
);
969 status
= cairo_matrix_invert (matrix
);
970 g_return_if_fail (status
== CAIRO_STATUS_SUCCESS
);
974 * gnome_canvas_item_w2i:
975 * @item: A canvas item.
976 * @x: X coordinate to convert (input/output value).
977 * @y: Y coordinate to convert (input/output value).
979 * Converts a coordinate pair from world coordinates to item-relative
983 gnome_canvas_item_w2i (GnomeCanvasItem
*item
,
987 cairo_matrix_t matrix
;
989 g_return_if_fail (GNOME_IS_CANVAS_ITEM (item
));
990 g_return_if_fail (x
!= NULL
);
991 g_return_if_fail (y
!= NULL
);
993 gnome_canvas_item_w2i_matrix (item
, &matrix
);
994 cairo_matrix_transform_point (&matrix
, x
, y
);
998 * gnome_canvas_item_i2w:
999 * @item: A canvas item.
1000 * @x: X coordinate to convert (input/output value).
1001 * @y: Y coordinate to convert (input/output value).
1003 * Converts a coordinate pair from item-relative coordinates to world
1007 gnome_canvas_item_i2w (GnomeCanvasItem
*item
,
1011 cairo_matrix_t matrix
;
1013 g_return_if_fail (GNOME_IS_CANVAS_ITEM (item
));
1014 g_return_if_fail (x
!= NULL
);
1015 g_return_if_fail (y
!= NULL
);
1017 gnome_canvas_item_i2w_matrix (item
, &matrix
);
1018 cairo_matrix_transform_point (&matrix
, x
, y
);
1022 * gnome_canvas_item_i2c_matrix:
1023 * @item: A canvas item.
1024 * @matrix: Matrix to take the resulting transformation matrix (return value).
1026 * Gets the affine transform that converts from item-relative coordinates to
1027 * canvas pixel coordinates.
1030 gnome_canvas_item_i2c_matrix (GnomeCanvasItem
*item
,
1031 cairo_matrix_t
*matrix
)
1033 cairo_matrix_t i2w
, w2c
;
1035 gnome_canvas_item_i2w_matrix (item
, &i2w
);
1036 gnome_canvas_w2c_matrix (item
->canvas
, &w2c
);
1037 cairo_matrix_multiply (matrix
, &i2w
, &w2c
);
1040 /* Returns whether the item is an inferior of or is equal to the parent. */
1042 is_descendant (GnomeCanvasItem
*item
,
1043 GnomeCanvasItem
*parent
)
1045 for (; item
; item
= item
->parent
)
1053 * gnome_canvas_item_reparent:
1054 * @item: A canvas item.
1055 * @new_group: A canvas group.
1057 * Changes the parent of the specified item to be the new group. The item keeps
1058 * its group-relative coordinates as for its old parent, so the item may change
1059 * its absolute position within the canvas.
1062 gnome_canvas_item_reparent (GnomeCanvasItem
*item
,
1063 GnomeCanvasGroup
*new_group
)
1065 g_return_if_fail (GNOME_IS_CANVAS_ITEM (item
));
1066 g_return_if_fail (GNOME_IS_CANVAS_GROUP (new_group
));
1068 /* Both items need to be in the same canvas */
1069 g_return_if_fail (item
->canvas
== GNOME_CANVAS_ITEM (new_group
)->canvas
);
1071 /* The group cannot be an inferior of the item or be the item itself --
1072 * this also takes care of the case where the item is the root item of
1074 g_return_if_fail (!is_descendant (GNOME_CANVAS_ITEM (new_group
), item
));
1076 /* Everything is ok, now actually reparent the item */
1078 g_object_ref (item
); /* protect it from the unref in group_remove */
1080 redraw_if_visible (item
);
1082 group_remove (GNOME_CANVAS_GROUP (item
->parent
), item
);
1083 item
->parent
= GNOME_CANVAS_ITEM (new_group
);
1084 group_add (new_group
, item
);
1086 /* Redraw and repick */
1088 redraw_if_visible (item
);
1089 item
->canvas
->need_repick
= TRUE
;
1091 g_object_unref (item
);
1095 * gnome_canvas_item_grab_focus:
1096 * @item: A canvas item.
1098 * Makes the specified item take the keyboard focus, so all keyboard events will
1099 * be sent to it. If the canvas widget itself did not have the focus, it grabs
1103 gnome_canvas_item_grab_focus (GnomeCanvasItem
*item
)
1105 GnomeCanvasItem
*focused_item
;
1108 g_return_if_fail (GNOME_IS_CANVAS_ITEM (item
));
1109 g_return_if_fail (gtk_widget_get_can_focus (GTK_WIDGET (item
->canvas
)));
1111 focused_item
= item
->canvas
->focused_item
;
1115 GdkWindow
*bin_window
;
1117 layout
= GTK_LAYOUT (item
->canvas
);
1118 bin_window
= gtk_layout_get_bin_window (layout
);
1120 ev
.focus_change
.type
= GDK_FOCUS_CHANGE
;
1121 ev
.focus_change
.window
= bin_window
;
1122 ev
.focus_change
.send_event
= FALSE
;
1123 ev
.focus_change
.in
= FALSE
;
1125 emit_event (item
->canvas
, &ev
);
1128 item
->canvas
->focused_item
= item
;
1129 gtk_widget_grab_focus (GTK_WIDGET (item
->canvas
));
1133 GdkWindow
*bin_window
;
1135 layout
= GTK_LAYOUT (item
->canvas
);
1136 bin_window
= gtk_layout_get_bin_window (layout
);
1138 ev
.focus_change
.type
= GDK_FOCUS_CHANGE
;
1139 ev
.focus_change
.window
= bin_window
;
1140 ev
.focus_change
.send_event
= FALSE
;
1141 ev
.focus_change
.in
= TRUE
;
1143 emit_event (item
->canvas
, &ev
);
1148 * gnome_canvas_item_get_bounds:
1149 * @item: A canvas item.
1150 * @x1: Leftmost edge of the bounding box (return value).
1151 * @y1: Upper edge of the bounding box (return value).
1152 * @x2: Rightmost edge of the bounding box (return value).
1153 * @y2: Lower edge of the bounding box (return value).
1155 * Queries the bounding box of a canvas item. The bounds are returned in the
1156 * coordinate system of the item's parent.
1159 gnome_canvas_item_get_bounds (GnomeCanvasItem
*item
,
1165 gdouble tx1
, ty1
, tx2
, ty2
;
1167 g_return_if_fail (GNOME_IS_CANVAS_ITEM (item
));
1169 tx1
= ty1
= tx2
= ty2
= 0.0;
1171 /* Get the item's bounds in its coordinate system */
1173 if (GNOME_CANVAS_ITEM_GET_CLASS (item
)->bounds
)
1174 GNOME_CANVAS_ITEM_GET_CLASS (item
)->bounds (
1175 item
, &tx1
, &ty1
, &tx2
, &ty2
);
1177 /* Make the bounds relative to the item's parent coordinate system */
1178 gnome_canvas_matrix_transform_rect (&item
->matrix
, &tx1
, &ty1
, &tx2
, &ty2
);
1180 /* Return the values */
1196 * gnome_canvas_item_request_update
1197 * @item: A canvas item.
1199 * To be used only by item implementations. Requests that the canvas queue an
1200 * update for the specified item.
1203 gnome_canvas_item_request_update (GnomeCanvasItem
*item
)
1205 if (item
->flags
& GNOME_CANVAS_ITEM_NEED_UPDATE
)
1208 item
->flags
|= GNOME_CANVAS_ITEM_NEED_UPDATE
;
1210 if (item
->parent
!= NULL
) {
1211 /* Recurse up the tree */
1212 gnome_canvas_item_request_update (item
->parent
);
1214 /* Have reached the top of the tree, make
1215 * sure the update call gets scheduled. */
1216 gnome_canvas_request_update (item
->canvas
);
1220 /*** GnomeCanvasGroup ***/
1228 static void gnome_canvas_group_set_property (GObject
*object
,
1230 const GValue
*value
,
1232 static void gnome_canvas_group_get_property (GObject
*object
,
1237 static void gnome_canvas_group_dispose (GnomeCanvasItem
*object
);
1239 static void gnome_canvas_group_update (GnomeCanvasItem
*item
,
1240 const cairo_matrix_t
*matrix
,
1242 static void gnome_canvas_group_realize (GnomeCanvasItem
*item
);
1243 static void gnome_canvas_group_unrealize (GnomeCanvasItem
*item
);
1244 static void gnome_canvas_group_map (GnomeCanvasItem
*item
);
1245 static void gnome_canvas_group_unmap (GnomeCanvasItem
*item
);
1246 static void gnome_canvas_group_draw (GnomeCanvasItem
*item
,
1249 gint width
, gint height
);
1250 static GnomeCanvasItem
*gnome_canvas_group_point (GnomeCanvasItem
*item
,
1251 gdouble x
, gdouble y
,
1253 static void gnome_canvas_group_bounds (GnomeCanvasItem
*item
,
1254 gdouble
*x1
, gdouble
*y1
,
1255 gdouble
*x2
, gdouble
*y2
);
1260 GNOME_TYPE_CANVAS_ITEM
)
1262 /* Class initialization function for GnomeCanvasGroupClass */
1264 gnome_canvas_group_class_init (GnomeCanvasGroupClass
*class)
1266 GObjectClass
*object_class
;
1267 GnomeCanvasItemClass
*item_class
;
1269 object_class
= (GObjectClass
*) class;
1270 item_class
= (GnomeCanvasItemClass
*) class;
1272 object_class
->set_property
= gnome_canvas_group_set_property
;
1273 object_class
->get_property
= gnome_canvas_group_get_property
;
1275 g_object_class_install_property (
1278 g_param_spec_double (
1288 g_object_class_install_property (
1291 g_param_spec_double (
1301 item_class
->dispose
= gnome_canvas_group_dispose
;
1302 item_class
->update
= gnome_canvas_group_update
;
1303 item_class
->realize
= gnome_canvas_group_realize
;
1304 item_class
->unrealize
= gnome_canvas_group_unrealize
;
1305 item_class
->map
= gnome_canvas_group_map
;
1306 item_class
->unmap
= gnome_canvas_group_unmap
;
1307 item_class
->draw
= gnome_canvas_group_draw
;
1308 item_class
->point
= gnome_canvas_group_point
;
1309 item_class
->bounds
= gnome_canvas_group_bounds
;
1312 /* Object initialization function for GnomeCanvasGroup */
1314 gnome_canvas_group_init (GnomeCanvasGroup
*group
)
1318 /* Set_property handler for canvas groups */
1320 gnome_canvas_group_set_property (GObject
*gobject
,
1322 const GValue
*value
,
1325 GnomeCanvasItem
*item
;
1327 g_return_if_fail (GNOME_IS_CANVAS_GROUP (gobject
));
1329 item
= GNOME_CANVAS_ITEM (gobject
);
1331 switch (property_id
) {
1333 item
->matrix
.x0
= g_value_get_double (value
);
1337 item
->matrix
.y0
= g_value_get_double (value
);
1341 G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject
, property_id
, pspec
);
1346 /* Get_property handler for canvas groups */
1348 gnome_canvas_group_get_property (GObject
*gobject
,
1353 GnomeCanvasItem
*item
;
1355 g_return_if_fail (GNOME_IS_CANVAS_GROUP (gobject
));
1357 item
= GNOME_CANVAS_ITEM (gobject
);
1359 switch (property_id
) {
1361 g_value_set_double (value
, item
->matrix
.x0
);
1365 g_value_set_double (value
, item
->matrix
.y0
);
1369 G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject
, property_id
, pspec
);
1374 /* Dispose handler for canvas groups */
1376 gnome_canvas_group_dispose (GnomeCanvasItem
*object
)
1378 GnomeCanvasGroup
*group
;
1380 g_return_if_fail (GNOME_IS_CANVAS_GROUP (object
));
1382 group
= GNOME_CANVAS_GROUP (object
);
1384 while (group
->item_list
) {
1385 /* child is unref'ed by the child's group_remove (). */
1386 g_object_run_dispose (G_OBJECT (group
->item_list
->data
));
1389 GNOME_CANVAS_ITEM_CLASS (gnome_canvas_group_parent_class
)->
1393 /* Update handler for canvas groups */
1395 gnome_canvas_group_update (GnomeCanvasItem
*item
,
1396 const cairo_matrix_t
*i2c
,
1399 GnomeCanvasGroup
*group
;
1402 gdouble x1
, y1
, x2
, y2
;
1404 group
= GNOME_CANVAS_GROUP (item
);
1406 GNOME_CANVAS_ITEM_CLASS (gnome_canvas_group_parent_class
)->
1407 update (item
, i2c
, flags
);
1414 for (list
= group
->item_list
; list
; list
= list
->next
) {
1417 gnome_canvas_item_invoke_update (i
, i2c
, flags
);
1419 x1
= MIN (x1
, i
->x1
);
1420 x2
= MAX (x2
, i
->x2
);
1421 y1
= MIN (y1
, i
->y1
);
1422 y2
= MAX (y2
, i
->y2
);
1424 if (x1
>= x2
|| y1
>= y2
) {
1425 item
->x1
= item
->x2
= item
->y1
= item
->y2
= 0;
1434 /* Realize handler for canvas groups */
1436 gnome_canvas_group_realize (GnomeCanvasItem
*item
)
1438 GnomeCanvasGroup
*group
;
1442 group
= GNOME_CANVAS_GROUP (item
);
1444 for (list
= group
->item_list
; list
; list
= list
->next
) {
1447 if (!(i
->flags
& GNOME_CANVAS_ITEM_REALIZED
))
1448 (* GNOME_CANVAS_ITEM_GET_CLASS (i
)->realize
) (i
);
1451 GNOME_CANVAS_ITEM_CLASS (gnome_canvas_group_parent_class
)->
1455 /* Unrealize handler for canvas groups */
1457 gnome_canvas_group_unrealize (GnomeCanvasItem
*item
)
1459 GnomeCanvasGroup
*group
;
1463 group
= GNOME_CANVAS_GROUP (item
);
1465 for (list
= group
->item_list
; list
; list
= list
->next
) {
1468 if (i
->flags
& GNOME_CANVAS_ITEM_REALIZED
)
1469 (* GNOME_CANVAS_ITEM_GET_CLASS (i
)->unrealize
) (i
);
1472 GNOME_CANVAS_ITEM_CLASS (gnome_canvas_group_parent_class
)->
1476 /* Map handler for canvas groups */
1478 gnome_canvas_group_map (GnomeCanvasItem
*item
)
1480 GnomeCanvasGroup
*group
;
1484 group
= GNOME_CANVAS_GROUP (item
);
1486 for (list
= group
->item_list
; list
; list
= list
->next
) {
1489 if (!(i
->flags
& GNOME_CANVAS_ITEM_MAPPED
))
1490 (* GNOME_CANVAS_ITEM_GET_CLASS (i
)->map
) (i
);
1493 GNOME_CANVAS_ITEM_CLASS (gnome_canvas_group_parent_class
)->map (item
);
1496 /* Unmap handler for canvas groups */
1498 gnome_canvas_group_unmap (GnomeCanvasItem
*item
)
1500 GnomeCanvasGroup
*group
;
1504 group
= GNOME_CANVAS_GROUP (item
);
1506 for (list
= group
->item_list
; list
; list
= list
->next
) {
1509 if (i
->flags
& GNOME_CANVAS_ITEM_MAPPED
)
1510 (* GNOME_CANVAS_ITEM_GET_CLASS (i
)->unmap
) (i
);
1513 GNOME_CANVAS_ITEM_CLASS (gnome_canvas_group_parent_class
)->unmap (item
);
1516 /* Draw handler for canvas groups */
1518 gnome_canvas_group_draw (GnomeCanvasItem
*item
,
1525 GnomeCanvasGroup
*group
;
1527 GnomeCanvasItem
*child
= NULL
;
1529 group
= GNOME_CANVAS_GROUP (item
);
1531 for (list
= group
->item_list
; list
; list
= list
->next
) {
1534 if ((child
->flags
& GNOME_CANVAS_ITEM_VISIBLE
)
1535 && ((child
->x1
< (x
+ width
))
1536 && (child
->y1
< (y
+ height
))
1538 && (child
->y2
> y
))) {
1541 GNOME_CANVAS_ITEM_GET_CLASS (child
)->draw (
1542 child
, cr
, x
, y
, width
, height
);
1549 /* Point handler for canvas groups */
1550 static GnomeCanvasItem
*
1551 gnome_canvas_group_point (GnomeCanvasItem
*item
,
1557 GnomeCanvasGroup
*group
;
1559 GnomeCanvasItem
*child
, *point_item
;
1561 group
= GNOME_CANVAS_GROUP (item
);
1563 for (list
= g_list_last (group
->item_list
); list
; list
= list
->prev
) {
1566 if ((child
->x1
> cx
) || (child
->y1
> cy
))
1569 if ((child
->x2
< cx
) || (child
->y2
< cy
))
1572 if (!(child
->flags
& GNOME_CANVAS_ITEM_VISIBLE
))
1575 point_item
= gnome_canvas_item_invoke_point (child
, x
, y
, cx
, cy
);
1583 /* Bounds handler for canvas groups */
1585 gnome_canvas_group_bounds (GnomeCanvasItem
*item
,
1591 GnomeCanvasGroup
*group
;
1592 GnomeCanvasItem
*child
;
1594 gdouble tx1
, ty1
, tx2
, ty2
;
1595 gdouble minx
, miny
, maxx
, maxy
;
1598 group
= GNOME_CANVAS_GROUP (item
);
1600 /* Get the bounds of the first visible item */
1602 child
= NULL
; /* Unnecessary but eliminates a warning. */
1606 for (list
= group
->item_list
; list
; list
= list
->next
) {
1609 if (child
->flags
& GNOME_CANVAS_ITEM_VISIBLE
) {
1611 gnome_canvas_item_get_bounds (child
, &minx
, &miny
, &maxx
, &maxy
);
1616 /* If there were no visible items, return an empty bounding box */
1619 *x1
= *y1
= *x2
= *y2
= 0.0;
1623 /* Now we can grow the bounds using the rest of the items */
1627 for (; list
; list
= list
->next
) {
1630 if (!(child
->flags
& GNOME_CANVAS_ITEM_VISIBLE
))
1633 gnome_canvas_item_get_bounds (child
, &tx1
, &ty1
, &tx2
, &ty2
);
1654 /* Adds an item to a group */
1656 group_add (GnomeCanvasGroup
*group
,
1657 GnomeCanvasItem
*item
)
1659 g_object_ref_sink (item
);
1661 if (!group
->item_list
) {
1662 group
->item_list
= g_list_append (group
->item_list
, item
);
1663 group
->item_list_end
= group
->item_list
;
1665 group
->item_list_end
= g_list_append (group
->item_list_end
, item
)->next
;
1667 if (group
->item
.flags
& GNOME_CANVAS_ITEM_REALIZED
)
1668 (* GNOME_CANVAS_ITEM_GET_CLASS (item
)->realize
) (item
);
1670 if (group
->item
.flags
& GNOME_CANVAS_ITEM_MAPPED
)
1671 (* GNOME_CANVAS_ITEM_GET_CLASS (item
)->map
) (item
);
1673 g_object_notify (G_OBJECT (item
), "parent");
1676 /* Removes an item from a group */
1678 group_remove (GnomeCanvasGroup
*group
,
1679 GnomeCanvasItem
*item
)
1683 g_return_if_fail (GNOME_IS_CANVAS_GROUP (group
));
1684 g_return_if_fail (GNOME_IS_CANVAS_ITEM (item
));
1686 for (children
= group
->item_list
; children
; children
= children
->next
)
1687 if (children
->data
== item
) {
1688 if (item
->flags
& GNOME_CANVAS_ITEM_MAPPED
)
1689 (* GNOME_CANVAS_ITEM_GET_CLASS (item
)->unmap
) (item
);
1691 if (item
->flags
& GNOME_CANVAS_ITEM_REALIZED
)
1692 (* GNOME_CANVAS_ITEM_GET_CLASS (item
)->unrealize
) (item
);
1694 /* Unparent the child */
1696 item
->parent
= NULL
;
1697 g_object_unref (item
);
1699 /* Remove it from the list */
1701 if (children
== group
->item_list_end
)
1702 group
->item_list_end
= children
->prev
;
1704 group
->item_list
= g_list_remove_link (group
->item_list
, children
);
1705 g_list_free (children
);
1710 /*** GnomeCanvas ***/
1717 static void gnome_canvas_dispose (GObject
*object
);
1718 static void gnome_canvas_map (GtkWidget
*widget
);
1719 static void gnome_canvas_unmap (GtkWidget
*widget
);
1720 static void gnome_canvas_realize (GtkWidget
*widget
);
1721 static void gnome_canvas_unrealize (GtkWidget
*widget
);
1722 static void gnome_canvas_size_allocate (GtkWidget
*widget
,
1723 GtkAllocation
*allocation
);
1724 static gint
gnome_canvas_draw (GtkWidget
*widget
,
1726 static void gnome_canvas_drag_end (GtkWidget
*widget
,
1727 GdkDragContext
*context
);
1728 static gint
gnome_canvas_button (GtkWidget
*widget
,
1729 GdkEventButton
*event
);
1730 static gint
gnome_canvas_motion (GtkWidget
*widget
,
1731 GdkEventMotion
*event
);
1732 static gboolean
gnome_canvas_key (GtkWidget
*widget
,
1733 GdkEventKey
*event
);
1734 static gint
gnome_canvas_crossing (GtkWidget
*widget
,
1735 GdkEventCrossing
*event
);
1736 static gint
gnome_canvas_focus_in (GtkWidget
*widget
,
1737 GdkEventFocus
*event
);
1738 static gint
gnome_canvas_focus_out (GtkWidget
*widget
,
1739 GdkEventFocus
*event
);
1740 static void gnome_canvas_request_update_real (GnomeCanvas
*canvas
);
1741 static void gnome_canvas_draw_background (GnomeCanvas
*canvas
,
1748 static guint canvas_signals
[LAST_SIGNAL
];
1761 gnome_canvas_paint_rect (GnomeCanvas
*canvas
,
1769 GtkAllocation allocation
;
1770 GtkScrollable
*scrollable
;
1771 GtkAdjustment
*hadjustment
;
1772 GtkAdjustment
*vadjustment
;
1773 gint draw_x1
, draw_y1
;
1774 gint draw_x2
, draw_y2
;
1775 gint draw_width
, draw_height
;
1776 gdouble hadjustment_value
;
1777 gdouble vadjustment_value
;
1779 g_return_if_fail (!canvas
->need_update
);
1781 widget
= GTK_WIDGET (canvas
);
1782 gtk_widget_get_allocation (widget
, &allocation
);
1784 scrollable
= GTK_SCROLLABLE (canvas
);
1785 hadjustment
= gtk_scrollable_get_hadjustment (scrollable
);
1786 vadjustment
= gtk_scrollable_get_vadjustment (scrollable
);
1788 hadjustment_value
= gtk_adjustment_get_value (hadjustment
);
1789 vadjustment_value
= gtk_adjustment_get_value (vadjustment
);
1791 draw_x1
= MAX (x0
, hadjustment_value
- canvas
->zoom_xofs
);
1792 draw_y1
= MAX (y0
, vadjustment_value
- canvas
->zoom_yofs
);
1793 draw_x2
= MIN (draw_x1
+ allocation
.width
, x1
);
1794 draw_y2
= MIN (draw_y1
+ allocation
.height
, y1
);
1796 draw_width
= draw_x2
- draw_x1
;
1797 draw_height
= draw_y2
- draw_y1
;
1799 if (draw_width
< 1 || draw_height
< 1)
1802 canvas
->draw_xofs
= draw_x1
;
1803 canvas
->draw_yofs
= draw_y1
;
1808 canvas
, canvas_signals
[DRAW_BACKGROUND
], 0, cr
,
1809 draw_x1
, draw_y1
, draw_width
, draw_height
);
1813 if (canvas
->root
->flags
& GNOME_CANVAS_ITEM_VISIBLE
) {
1816 (* GNOME_CANVAS_ITEM_GET_CLASS (canvas
->root
)->draw
) (
1819 draw_width
, draw_height
);
1826 gnome_canvas_get_property (GObject
*object
,
1831 switch (property_id
) {
1832 case PROP_FOCUSED_ITEM
:
1833 g_value_set_object (value
, GNOME_CANVAS (object
)->focused_item
);
1836 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, property_id
, pspec
);
1842 gnome_canvas_set_property (GObject
*object
,
1844 const GValue
*value
,
1847 switch (property_id
) {
1848 case PROP_FOCUSED_ITEM
:
1849 GNOME_CANVAS (object
)->focused_item
= g_value_get_object (value
);
1852 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, property_id
, pspec
);
1857 /* Class initialization function for GnomeCanvasClass */
1859 gnome_canvas_class_init (GnomeCanvasClass
*class)
1861 GObjectClass
*object_class
;
1862 GtkWidgetClass
*widget_class
;
1864 object_class
= (GObjectClass
*) class;
1865 widget_class
= (GtkWidgetClass
*) class;
1867 object_class
->set_property
= gnome_canvas_set_property
;
1868 object_class
->get_property
= gnome_canvas_get_property
;
1869 object_class
->dispose
= gnome_canvas_dispose
;
1871 widget_class
->map
= gnome_canvas_map
;
1872 widget_class
->unmap
= gnome_canvas_unmap
;
1873 widget_class
->realize
= gnome_canvas_realize
;
1874 widget_class
->unrealize
= gnome_canvas_unrealize
;
1875 widget_class
->size_allocate
= gnome_canvas_size_allocate
;
1876 widget_class
->draw
= gnome_canvas_draw
;
1877 widget_class
->drag_end
= gnome_canvas_drag_end
;
1878 widget_class
->button_press_event
= gnome_canvas_button
;
1879 widget_class
->button_release_event
= gnome_canvas_button
;
1880 widget_class
->motion_notify_event
= gnome_canvas_motion
;
1881 widget_class
->key_press_event
= gnome_canvas_key
;
1882 widget_class
->key_release_event
= gnome_canvas_key
;
1883 widget_class
->enter_notify_event
= gnome_canvas_crossing
;
1884 widget_class
->leave_notify_event
= gnome_canvas_crossing
;
1885 widget_class
->focus_in_event
= gnome_canvas_focus_in
;
1886 widget_class
->focus_out_event
= gnome_canvas_focus_out
;
1888 class->draw_background
= gnome_canvas_draw_background
;
1889 class->request_update
= gnome_canvas_request_update_real
;
1891 g_object_class_install_property (
1894 g_param_spec_object (
1898 GNOME_TYPE_CANVAS_ITEM
,
1902 canvas_signals
[DRAW_BACKGROUND
] = g_signal_new (
1904 G_TYPE_FROM_CLASS (object_class
),
1906 G_STRUCT_OFFSET (GnomeCanvasClass
, draw_background
),
1909 CAIRO_GOBJECT_TYPE_CONTEXT
,
1915 gtk_widget_class_set_accessible_type (widget_class
, GAIL_TYPE_CANVAS
);
1916 gail_canvas_a11y_init ();
1919 /* Callback used when the root item of a canvas is destroyed. The user should
1920 * never ever do this, so we panic if this happens.
1922 G_GNUC_NORETURN
static void
1923 panic_root_finalized (gpointer data
,
1924 GObject
*gone_object
)
1926 g_error ("Eeeek, root item %p of canvas %p was destroyed!", gone_object
, data
);
1929 /* Object initialization function for GnomeCanvas */
1931 gnome_canvas_init (GnomeCanvas
*canvas
)
1934 guint layout_width
, layout_height
;
1936 layout
= GTK_LAYOUT (canvas
);
1937 gtk_layout_get_size (layout
, &layout_width
, &layout_height
);
1939 gtk_widget_set_can_focus (GTK_WIDGET (canvas
), TRUE
);
1941 canvas
->need_update
= FALSE
;
1942 canvas
->idle_id
= 0;
1944 canvas
->scroll_x1
= 0.0;
1945 canvas
->scroll_y1
= 0.0;
1946 canvas
->scroll_x2
= layout_width
;
1947 canvas
->scroll_y2
= layout_height
;
1949 canvas
->pick_event
.type
= GDK_LEAVE_NOTIFY
;
1950 canvas
->pick_event
.crossing
.x
= 0;
1951 canvas
->pick_event
.crossing
.y
= 0;
1953 gtk_scrollable_set_hadjustment (GTK_SCROLLABLE (canvas
), NULL
);
1954 gtk_scrollable_set_vadjustment (GTK_SCROLLABLE (canvas
), NULL
);
1956 /* Create the root item as a special case */
1958 canvas
->root
= GNOME_CANVAS_ITEM (
1959 g_object_new (gnome_canvas_group_get_type (), NULL
));
1960 canvas
->root
->canvas
= canvas
;
1962 g_object_ref_sink (canvas
->root
);
1964 g_object_weak_ref (G_OBJECT (canvas
->root
), panic_root_finalized
, canvas
);
1966 canvas
->need_repick
= TRUE
;
1969 /* Convenience function to remove the idle handler of a canvas */
1971 remove_idle (GnomeCanvas
*canvas
)
1973 if (canvas
->idle_id
== 0)
1976 g_source_remove (canvas
->idle_id
);
1977 canvas
->idle_id
= 0;
1980 /* Removes the transient state of the canvas (idle handler, grabs). */
1982 shutdown_transients (GnomeCanvas
*canvas
)
1984 if (canvas
->grabbed_device
!= NULL
) {
1985 gdk_device_ungrab (canvas
->grabbed_device
, GDK_CURRENT_TIME
);
1986 g_object_unref (canvas
->grabbed_device
);
1987 canvas
->grabbed_device
= NULL
;
1990 canvas
->grabbed_item
= NULL
;
1992 remove_idle (canvas
);
1995 /* Dispose handler for GnomeCanvas */
1997 gnome_canvas_dispose (GObject
*object
)
1999 GnomeCanvas
*canvas
;
2001 g_return_if_fail (GNOME_IS_CANVAS (object
));
2003 /* remember, dispose can be run multiple times! */
2005 canvas
= GNOME_CANVAS (object
);
2008 g_object_weak_unref (G_OBJECT (canvas
->root
), panic_root_finalized
, canvas
);
2009 g_object_unref (canvas
->root
);
2010 canvas
->root
= NULL
;
2013 shutdown_transients (canvas
);
2015 /* Chain up to parent's dispose() method. */
2016 G_OBJECT_CLASS (gnome_canvas_parent_class
)->dispose (object
);
2022 * Creates a new empty canvas in non-antialiased mode.
2024 * Return value: A newly-created canvas.
2027 gnome_canvas_new (void)
2029 return GTK_WIDGET (g_object_new (gnome_canvas_get_type (), NULL
));
2032 /* Map handler for the canvas */
2034 gnome_canvas_map (GtkWidget
*widget
)
2036 GnomeCanvas
*canvas
;
2038 g_return_if_fail (GNOME_IS_CANVAS (widget
));
2040 /* Normal widget mapping stuff */
2042 GTK_WIDGET_CLASS (gnome_canvas_parent_class
)->map (widget
);
2044 canvas
= GNOME_CANVAS (widget
);
2046 if (canvas
->need_update
)
2051 if (GNOME_CANVAS_ITEM_GET_CLASS (canvas
->root
)->map
)
2052 (* GNOME_CANVAS_ITEM_GET_CLASS (canvas
->root
)->map
) (canvas
->root
);
2055 /* Unmap handler for the canvas */
2057 gnome_canvas_unmap (GtkWidget
*widget
)
2059 GnomeCanvas
*canvas
;
2061 g_return_if_fail (GNOME_IS_CANVAS (widget
));
2063 canvas
= GNOME_CANVAS (widget
);
2065 shutdown_transients (canvas
);
2069 if (GNOME_CANVAS_ITEM_GET_CLASS (canvas
->root
)->unmap
)
2070 (* GNOME_CANVAS_ITEM_GET_CLASS (canvas
->root
)->unmap
) (canvas
->root
);
2072 /* Normal widget unmapping stuff */
2074 GTK_WIDGET_CLASS (gnome_canvas_parent_class
)->unmap (widget
);
2077 /* Realize handler for the canvas */
2079 gnome_canvas_realize (GtkWidget
*widget
)
2081 GnomeCanvas
*canvas
;
2083 GdkWindow
*bin_window
;
2085 g_return_if_fail (GNOME_IS_CANVAS (widget
));
2087 /* Normal widget realization stuff */
2089 GTK_WIDGET_CLASS (gnome_canvas_parent_class
)->realize (widget
);
2091 canvas
= GNOME_CANVAS (widget
);
2093 layout
= GTK_LAYOUT (canvas
);
2094 bin_window
= gtk_layout_get_bin_window (layout
);
2096 gdk_window_set_events (
2098 (gdk_window_get_events (bin_window
)
2101 | GDK_BUTTON_PRESS_MASK
2102 | GDK_BUTTON_RELEASE_MASK
2103 | GDK_POINTER_MOTION_MASK
2104 | GDK_KEY_PRESS_MASK
2105 | GDK_KEY_RELEASE_MASK
2106 | GDK_ENTER_NOTIFY_MASK
2107 | GDK_LEAVE_NOTIFY_MASK
2108 | GDK_FOCUS_CHANGE_MASK
));
2110 /* Create our own temporary pixmap gc and realize all the items */
2112 (* GNOME_CANVAS_ITEM_GET_CLASS (canvas
->root
)->realize
) (canvas
->root
);
2115 /* Unrealize handler for the canvas */
2117 gnome_canvas_unrealize (GtkWidget
*widget
)
2119 GnomeCanvas
*canvas
;
2121 g_return_if_fail (GNOME_IS_CANVAS (widget
));
2123 canvas
= GNOME_CANVAS (widget
);
2125 shutdown_transients (canvas
);
2127 /* Unrealize items and parent widget */
2129 (* GNOME_CANVAS_ITEM_GET_CLASS (canvas
->root
)->unrealize
) (canvas
->root
);
2131 GTK_WIDGET_CLASS (gnome_canvas_parent_class
)->unrealize (widget
);
2134 /* Handles scrolling of the canvas. Adjusts the scrolling and zooming offset to
2135 * keep as much as possible of the canvas scrolling region in view.
2138 scroll_to (GnomeCanvas
*canvas
,
2143 GtkAllocation allocation
;
2144 GtkScrollable
*scrollable
;
2145 GtkAdjustment
*hadjustment
;
2146 GtkAdjustment
*vadjustment
;
2147 guint layout_width
, layout_height
;
2148 gint scroll_width
, scroll_height
;
2149 gint right_limit
, bottom_limit
;
2150 gint old_zoom_xofs
, old_zoom_yofs
;
2151 gint canvas_width
, canvas_height
;
2153 widget
= GTK_WIDGET (canvas
);
2154 gtk_widget_get_allocation (widget
, &allocation
);
2156 scrollable
= GTK_SCROLLABLE (canvas
);
2157 hadjustment
= gtk_scrollable_get_hadjustment (scrollable
);
2158 vadjustment
= gtk_scrollable_get_vadjustment (scrollable
);
2160 gtk_layout_get_size (GTK_LAYOUT (canvas
), &layout_width
, &layout_height
);
2162 canvas_width
= allocation
.width
;
2163 canvas_height
= allocation
.height
;
2166 floor ((canvas
->scroll_x2
- canvas
->scroll_x1
) + 0.5);
2168 floor ((canvas
->scroll_y2
- canvas
->scroll_y1
) + 0.5);
2170 right_limit
= scroll_width
- canvas_width
;
2171 bottom_limit
= scroll_height
- canvas_height
;
2173 old_zoom_xofs
= canvas
->zoom_xofs
;
2174 old_zoom_yofs
= canvas
->zoom_yofs
;
2176 if (right_limit
< 0) {
2178 canvas
->zoom_xofs
= (canvas_width
- scroll_width
) / 2;
2179 scroll_width
= canvas_width
;
2180 } else if (cx
< 0) {
2182 canvas
->zoom_xofs
= 0;
2183 } else if (cx
> right_limit
) {
2185 canvas
->zoom_xofs
= 0;
2187 canvas
->zoom_xofs
= 0;
2189 if (bottom_limit
< 0) {
2191 canvas
->zoom_yofs
= (canvas_height
- scroll_height
) / 2;
2192 scroll_height
= canvas_height
;
2193 } else if (cy
< 0) {
2195 canvas
->zoom_yofs
= 0;
2196 } else if (cy
> bottom_limit
) {
2198 canvas
->zoom_yofs
= 0;
2200 canvas
->zoom_yofs
= 0;
2202 if ((canvas
->zoom_xofs
!= old_zoom_xofs
) ||
2203 (canvas
->zoom_yofs
!= old_zoom_yofs
)) {
2204 /* This can only occur, if either canvas size or widget
2205 * size changes. So I think we can request full redraw
2206 * here. The reason is, that coverage UTA will be
2207 * invalidated by offset change. */
2208 /* FIXME Strictly this is not correct - we have to remove
2209 * our own idle (Lauris) */
2210 /* More stuff - we have to mark root as needing fresh affine
2212 if (!(canvas
->root
->flags
& GNOME_CANVAS_ITEM_NEED_AFFINE
)) {
2213 canvas
->root
->flags
|= GNOME_CANVAS_ITEM_NEED_AFFINE
;
2214 gnome_canvas_request_update (canvas
);
2216 gtk_widget_queue_draw (GTK_WIDGET (canvas
));
2220 gtk_adjustment_set_value (hadjustment
, cx
);
2223 gtk_adjustment_set_value (vadjustment
, cy
);
2225 if ((scroll_width
!= (gint
) layout_width
)
2226 || (scroll_height
!= (gint
) layout_height
))
2227 gtk_layout_set_size (GTK_LAYOUT (canvas
), scroll_width
, scroll_height
);
2230 /* Size allocation handler for the canvas */
2232 gnome_canvas_size_allocate (GtkWidget
*widget
,
2233 GtkAllocation
*allocation
)
2235 GtkScrollable
*scrollable
;
2236 GtkAdjustment
*hadjustment
;
2237 GtkAdjustment
*vadjustment
;
2239 g_return_if_fail (GNOME_IS_CANVAS (widget
));
2240 g_return_if_fail (allocation
!= NULL
);
2242 GTK_WIDGET_CLASS (gnome_canvas_parent_class
)->
2243 size_allocate (widget
, allocation
);
2245 scrollable
= GTK_SCROLLABLE (widget
);
2246 hadjustment
= gtk_scrollable_get_hadjustment (scrollable
);
2247 vadjustment
= gtk_scrollable_get_vadjustment (scrollable
);
2249 /* Recenter the view, if appropriate */
2251 g_object_freeze_notify (G_OBJECT (hadjustment
));
2252 g_object_freeze_notify (G_OBJECT (vadjustment
));
2254 gtk_adjustment_set_page_size (hadjustment
, allocation
->width
);
2255 gtk_adjustment_set_page_increment (hadjustment
, allocation
->width
/ 2);
2257 gtk_adjustment_set_page_size (vadjustment
, allocation
->height
);
2258 gtk_adjustment_set_page_increment (vadjustment
, allocation
->height
/ 2);
2261 GNOME_CANVAS (widget
),
2262 gtk_adjustment_get_value (hadjustment
),
2263 gtk_adjustment_get_value (vadjustment
));
2265 g_object_thaw_notify (G_OBJECT (hadjustment
));
2266 g_object_thaw_notify (G_OBJECT (vadjustment
));
2270 gnome_canvas_draw (GtkWidget
*widget
,
2273 GnomeCanvas
*canvas
= GNOME_CANVAS (widget
);
2274 cairo_rectangle_int_t rect
;
2276 GtkAdjustment
*hadjustment
;
2277 GtkAdjustment
*vadjustment
;
2278 gdouble hadjustment_value
;
2279 gdouble vadjustment_value
;
2281 layout
= GTK_LAYOUT (canvas
);
2282 hadjustment
= gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (layout
));
2283 vadjustment
= gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (layout
));
2285 hadjustment_value
= gtk_adjustment_get_value (hadjustment
);
2286 vadjustment_value
= gtk_adjustment_get_value (vadjustment
);
2288 gdk_cairo_get_clip_rectangle (cr
, &rect
);
2290 if (canvas
->need_update
) {
2293 /* We start updating root with w2c matrix */
2294 gnome_canvas_w2c_matrix (canvas
, &w2c
);
2296 gnome_canvas_item_invoke_update (canvas
->root
, &w2c
, 0);
2298 canvas
->need_update
= FALSE
;
2304 -canvas
->zoom_xofs
+ rect
.x
,
2305 -canvas
->zoom_yofs
+ rect
.y
);
2307 rect
.x
+= hadjustment_value
;
2308 rect
.y
+= vadjustment_value
;
2310 /* No pending updates, draw exposed area immediately */
2311 gnome_canvas_paint_rect (
2314 rect
.x
+ rect
.width
,
2315 rect
.y
+ rect
.height
);
2318 /* And call expose on parent container class */
2319 GTK_WIDGET_CLASS (gnome_canvas_parent_class
)->draw (widget
, cr
);
2325 gnome_canvas_drag_end (GtkWidget
*widget
,
2326 GdkDragContext
*context
)
2328 GnomeCanvas
*canvas
= GNOME_CANVAS (widget
);
2330 if (canvas
->grabbed_item
) {
2331 gnome_canvas_item_ungrab (canvas
->grabbed_item
, GDK_CURRENT_TIME
);
2334 if (GTK_WIDGET_CLASS (gnome_canvas_parent_class
)->drag_end
)
2335 GTK_WIDGET_CLASS (gnome_canvas_parent_class
)->drag_end (widget
, context
);
2338 /* Emits an event for an item in the canvas, be it the current item, grabbed
2339 * item, or focused item, as appropriate.
2343 emit_event (GnomeCanvas
*canvas
,
2348 GnomeCanvasItem
*item
;
2349 GnomeCanvasItem
*parent
;
2352 /* Perform checks for grabbed items */
2354 if (canvas
->grabbed_item
&&
2355 !is_descendant (canvas
->current_item
, canvas
->grabbed_item
)) {
2356 /* I think this warning is annoying and I don't know what it's for
2357 * so I'll disable it for now.
2359 /* g_warning ("emit_event() returning FALSE!\n");*/
2363 if (canvas
->grabbed_item
) {
2364 switch (event
->type
) {
2365 case GDK_ENTER_NOTIFY
:
2366 mask
= GDK_ENTER_NOTIFY_MASK
;
2369 case GDK_LEAVE_NOTIFY
:
2370 mask
= GDK_LEAVE_NOTIFY_MASK
;
2373 case GDK_MOTION_NOTIFY
:
2374 mask
= GDK_POINTER_MOTION_MASK
;
2377 case GDK_BUTTON_PRESS
:
2378 case GDK_2BUTTON_PRESS
:
2379 case GDK_3BUTTON_PRESS
:
2380 mask
= GDK_BUTTON_PRESS_MASK
;
2383 case GDK_BUTTON_RELEASE
:
2384 mask
= GDK_BUTTON_RELEASE_MASK
;
2388 mask
= GDK_KEY_PRESS_MASK
;
2391 case GDK_KEY_RELEASE
:
2392 mask
= GDK_KEY_RELEASE_MASK
;
2396 mask
= GDK_SCROLL_MASK
;
2404 if (!(mask
& canvas
->grabbed_event_mask
))
2408 /* Convert to world coordinates -- we have two cases because of diferent
2409 * offsets of the fields in the event structures.
2412 ev
= gdk_event_copy (event
);
2416 case GDK_ENTER_NOTIFY
:
2417 case GDK_LEAVE_NOTIFY
:
2418 gnome_canvas_window_to_world (
2420 ev
->crossing
.x
, ev
->crossing
.y
,
2421 &ev
->crossing
.x
, &ev
->crossing
.y
);
2424 case GDK_MOTION_NOTIFY
:
2425 case GDK_BUTTON_PRESS
:
2426 case GDK_2BUTTON_PRESS
:
2427 case GDK_3BUTTON_PRESS
:
2428 case GDK_BUTTON_RELEASE
:
2429 gnome_canvas_window_to_world (
2431 ev
->motion
.x
, ev
->motion
.y
,
2432 &ev
->motion
.x
, &ev
->motion
.y
);
2439 /* Choose where we send the event */
2441 item
= canvas
->current_item
;
2443 if (canvas
->focused_item
2444 && ((event
->type
== GDK_KEY_PRESS
) ||
2445 (event
->type
== GDK_KEY_RELEASE
) ||
2446 (event
->type
== GDK_FOCUS_CHANGE
)))
2447 item
= canvas
->focused_item
;
2449 /* The event is propagated up the hierarchy (for if someone connected to
2450 * a group instead of a leaf event), and emission is stopped if a
2451 * handler returns TRUE, just like for GtkWidget events.
2456 while (item
&& !finished
) {
2457 g_object_ref (item
);
2460 item
, item_signals
[ITEM_EVENT
], 0,
2463 parent
= item
->parent
;
2464 g_object_unref (item
);
2469 gdk_event_free (ev
);
2474 /* Re-picks the current item in the canvas, based on the event's coordinates.
2475 * Also emits enter/leave events for items as appropriate.
2478 pick_current_item (GnomeCanvas
*canvas
,
2488 /* If a button is down, we'll perform enter and leave events on the
2489 * current item, but not enter on any other item. This is more or less
2490 * like X pointer grabbing for canvas items.
2492 button_down
= canvas
->state
& (GDK_BUTTON1_MASK
2496 | GDK_BUTTON5_MASK
);
2498 canvas
->left_grabbed_item
= FALSE
;
2500 /* Save the event in the canvas. This is used to synthesize enter and
2501 * leave events in case the current item changes. It is also used to
2502 * re-pick the current item if the current one gets deleted. Also,
2503 * synthesize an enter event.
2505 if (event
!= &canvas
->pick_event
) {
2506 if ((event
->type
== GDK_MOTION_NOTIFY
) ||
2507 (event
->type
== GDK_BUTTON_RELEASE
)) {
2508 /* these fields have the same offsets in both types of events */
2510 canvas
->pick_event
.crossing
.type
= GDK_ENTER_NOTIFY
;
2511 canvas
->pick_event
.crossing
.window
= event
->motion
.window
;
2512 canvas
->pick_event
.crossing
.send_event
= event
->motion
.send_event
;
2513 canvas
->pick_event
.crossing
.subwindow
= NULL
;
2514 canvas
->pick_event
.crossing
.x
= event
->motion
.x
;
2515 canvas
->pick_event
.crossing
.y
= event
->motion
.y
;
2516 canvas
->pick_event
.crossing
.mode
= GDK_CROSSING_NORMAL
;
2517 canvas
->pick_event
.crossing
.detail
= GDK_NOTIFY_NONLINEAR
;
2518 canvas
->pick_event
.crossing
.focus
= FALSE
;
2519 canvas
->pick_event
.crossing
.state
= event
->motion
.state
;
2521 /* these fields don't have the same offsets in both types of events */
2523 if (event
->type
== GDK_MOTION_NOTIFY
) {
2524 canvas
->pick_event
.crossing
.x_root
= event
->motion
.x_root
;
2525 canvas
->pick_event
.crossing
.y_root
= event
->motion
.y_root
;
2527 canvas
->pick_event
.crossing
.x_root
= event
->button
.x_root
;
2528 canvas
->pick_event
.crossing
.y_root
= event
->button
.y_root
;
2531 canvas
->pick_event
= *event
;
2534 /* Don't do anything else if this is a recursive call */
2536 if (canvas
->in_repick
)
2539 /* LeaveNotify means that there is no current item, so we don't look for one */
2541 if (canvas
->pick_event
.type
!= GDK_LEAVE_NOTIFY
) {
2542 /* these fields don't have the same offsets in both types of events */
2544 if (canvas
->pick_event
.type
== GDK_ENTER_NOTIFY
) {
2545 x
= canvas
->pick_event
.crossing
.x
- canvas
->zoom_xofs
;
2546 y
= canvas
->pick_event
.crossing
.y
- canvas
->zoom_yofs
;
2548 x
= canvas
->pick_event
.motion
.x
- canvas
->zoom_xofs
;
2549 y
= canvas
->pick_event
.motion
.y
- canvas
->zoom_yofs
;
2552 /* canvas pixel coords */
2554 cx
= (gint
) (x
+ 0.5);
2555 cy
= (gint
) (y
+ 0.5);
2559 x
= canvas
->scroll_x1
+ x
;
2560 y
= canvas
->scroll_y1
+ y
;
2562 /* find the closest item */
2564 if (canvas
->root
->flags
& GNOME_CANVAS_ITEM_VISIBLE
)
2565 canvas
->new_current_item
=
2566 gnome_canvas_item_invoke_point (
2567 canvas
->root
, x
, y
, cx
, cy
);
2569 canvas
->new_current_item
= NULL
;
2571 canvas
->new_current_item
= NULL
;
2573 if ((canvas
->new_current_item
== canvas
->current_item
)
2574 && !canvas
->left_grabbed_item
)
2575 return retval
; /* current item did not change */
2577 /* Synthesize events for old and new current items */
2579 if ((canvas
->new_current_item
!= canvas
->current_item
)
2580 && (canvas
->current_item
!= NULL
)
2581 && !canvas
->left_grabbed_item
) {
2584 new_event
= canvas
->pick_event
;
2585 new_event
.type
= GDK_LEAVE_NOTIFY
;
2587 new_event
.crossing
.detail
= GDK_NOTIFY_ANCESTOR
;
2588 new_event
.crossing
.subwindow
= NULL
;
2589 canvas
->in_repick
= TRUE
;
2590 retval
= emit_event (canvas
, &new_event
);
2591 canvas
->in_repick
= FALSE
;
2594 /* new_current_item may have been set to NULL during the
2595 * call to emit_event() above */
2597 if ((canvas
->new_current_item
!= canvas
->current_item
) && button_down
) {
2598 canvas
->left_grabbed_item
= TRUE
;
2602 /* Handle the rest of cases */
2604 canvas
->left_grabbed_item
= FALSE
;
2605 canvas
->current_item
= canvas
->new_current_item
;
2607 if (canvas
->current_item
!= NULL
) {
2610 new_event
= canvas
->pick_event
;
2611 new_event
.type
= GDK_ENTER_NOTIFY
;
2612 new_event
.crossing
.detail
= GDK_NOTIFY_ANCESTOR
;
2613 new_event
.crossing
.subwindow
= NULL
;
2614 retval
= emit_event (canvas
, &new_event
);
2620 /* Button event handler for the canvas */
2622 gnome_canvas_button (GtkWidget
*widget
,
2623 GdkEventButton
*event
)
2625 GnomeCanvas
*canvas
;
2627 GdkWindow
*bin_window
;
2631 g_return_val_if_fail (GNOME_IS_CANVAS (widget
), FALSE
);
2632 g_return_val_if_fail (event
!= NULL
, FALSE
);
2636 canvas
= GNOME_CANVAS (widget
);
2638 layout
= GTK_LAYOUT (canvas
);
2639 bin_window
= gtk_layout_get_bin_window (layout
);
2642 * dispatch normally regardless of the event's window if an item has
2643 * has a pointer grab in effect
2645 if (!canvas
->grabbed_item
&& event
->window
!= bin_window
)
2648 switch (event
->button
) {
2650 mask
= GDK_BUTTON1_MASK
;
2653 mask
= GDK_BUTTON2_MASK
;
2656 mask
= GDK_BUTTON3_MASK
;
2659 mask
= GDK_BUTTON4_MASK
;
2662 mask
= GDK_BUTTON5_MASK
;
2668 switch (event
->type
) {
2669 case GDK_BUTTON_PRESS
:
2670 case GDK_2BUTTON_PRESS
:
2671 case GDK_3BUTTON_PRESS
:
2672 /* Pick the current item as if the button were
2673 * not pressed, and then process the event. */
2674 canvas
->state
= event
->state
;
2675 pick_current_item (canvas
, (GdkEvent
*) event
);
2676 canvas
->state
^= mask
;
2677 retval
= emit_event (canvas
, (GdkEvent
*) event
);
2680 case GDK_BUTTON_RELEASE
:
2681 /* Process the event as if the button were pressed,
2682 * then repick after the button has been released. */
2683 canvas
->state
= event
->state
;
2684 retval
= emit_event (canvas
, (GdkEvent
*) event
);
2685 event
->state
^= mask
;
2686 canvas
->state
= event
->state
;
2687 pick_current_item (canvas
, (GdkEvent
*) event
);
2688 event
->state
^= mask
;
2692 g_warn_if_reached ();
2698 /* Motion event handler for the canvas */
2700 gnome_canvas_motion (GtkWidget
*widget
,
2701 GdkEventMotion
*event
)
2703 GnomeCanvas
*canvas
;
2705 GdkWindow
*bin_window
;
2707 g_return_val_if_fail (GNOME_IS_CANVAS (widget
), FALSE
);
2708 g_return_val_if_fail (event
!= NULL
, FALSE
);
2710 canvas
= GNOME_CANVAS (widget
);
2712 layout
= GTK_LAYOUT (widget
);
2713 bin_window
= gtk_layout_get_bin_window (layout
);
2715 if (event
->window
!= bin_window
)
2718 canvas
->state
= event
->state
;
2719 pick_current_item (canvas
, (GdkEvent
*) event
);
2720 return emit_event (canvas
, (GdkEvent
*) event
);
2723 /* Key event handler for the canvas */
2725 gnome_canvas_key (GtkWidget
*widget
,
2728 GnomeCanvas
*canvas
;
2730 g_return_val_if_fail (GNOME_IS_CANVAS (widget
), FALSE
);
2731 g_return_val_if_fail (event
!= NULL
, FALSE
);
2733 canvas
= GNOME_CANVAS (widget
);
2735 if (!emit_event (canvas
, (GdkEvent
*) event
)) {
2736 GtkWidgetClass
*widget_class
;
2738 widget_class
= GTK_WIDGET_CLASS (gnome_canvas_parent_class
);
2740 if (event
->type
== GDK_KEY_PRESS
) {
2741 if (widget_class
->key_press_event
)
2742 return (* widget_class
->key_press_event
) (widget
, event
);
2743 } else if (event
->type
== GDK_KEY_RELEASE
) {
2744 if (widget_class
->key_release_event
)
2745 return (* widget_class
->key_release_event
) (widget
, event
);
2747 g_warn_if_reached ();
2754 /* Crossing event handler for the canvas */
2756 gnome_canvas_crossing (GtkWidget
*widget
,
2757 GdkEventCrossing
*event
)
2759 GnomeCanvas
*canvas
;
2761 GdkWindow
*bin_window
;
2763 g_return_val_if_fail (GNOME_IS_CANVAS (widget
), FALSE
);
2764 g_return_val_if_fail (event
!= NULL
, FALSE
);
2766 canvas
= GNOME_CANVAS (widget
);
2768 layout
= GTK_LAYOUT (canvas
);
2769 bin_window
= gtk_layout_get_bin_window (layout
);
2771 if (event
->window
!= bin_window
)
2774 /* XXX Detect and disregard synthesized crossing events generated
2775 * by synth_crossing() in gtkwidget.c. The pointer coordinates
2776 * are invalid and pick_current_item() relies on them. */
2777 if (event
->x
== 0 && event
->y
== 0 &&
2778 event
->x_root
== 0 && event
->y_root
== 0)
2781 canvas
->state
= event
->state
;
2782 return pick_current_item (canvas
, (GdkEvent
*) event
);
2785 /* Focus in handler for the canvas */
2787 gnome_canvas_focus_in (GtkWidget
*widget
,
2788 GdkEventFocus
*event
)
2790 GnomeCanvas
*canvas
;
2792 /* XXX Can't access flags directly anymore, but is it really needed?
2793 * If so, could we call gtk_widget_send_focus_change() instead? */
2795 GTK_WIDGET_SET_FLAGS (widget
, GTK_HAS_FOCUS
);
2798 canvas
= GNOME_CANVAS (widget
);
2800 if (canvas
->focused_item
)
2801 return emit_event (canvas
, (GdkEvent
*) event
);
2806 /* Focus out handler for the canvas */
2808 gnome_canvas_focus_out (GtkWidget
*widget
,
2809 GdkEventFocus
*event
)
2811 GnomeCanvas
*canvas
;
2813 /* XXX Can't access flags directly anymore, but is it really needed?
2814 * If so, could we call gtk_widget_send_focus_change() instead? */
2816 GTK_WIDGET_UNSET_FLAGS (widget
, GTK_HAS_FOCUS
);
2819 canvas
= GNOME_CANVAS (widget
);
2821 if (canvas
->focused_item
)
2822 return emit_event (canvas
, (GdkEvent
*) event
);
2828 gnome_canvas_draw_background (GnomeCanvas
*canvas
,
2835 GtkStyleContext
*style_context
;
2838 style_context
= gtk_widget_get_style_context (GTK_WIDGET (canvas
));
2839 if (!gtk_style_context_lookup_color (style_context
, "theme_bg_color", &rgba
))
2840 gdk_rgba_parse (&rgba
, "#aaaaaa");
2843 gdk_cairo_set_source_rgba (cr
, &rgba
);
2849 do_update (GnomeCanvas
*canvas
)
2851 /* Cause the update if necessary */
2854 if (canvas
->need_update
) {
2857 /* We start updating root with w2c matrix */
2858 gnome_canvas_w2c_matrix (canvas
, &w2c
);
2860 gnome_canvas_item_invoke_update (canvas
->root
, &w2c
, 0);
2862 canvas
->need_update
= FALSE
;
2865 /* Pick new current item */
2867 while (canvas
->need_repick
) {
2868 canvas
->need_repick
= FALSE
;
2869 pick_current_item (canvas
, &canvas
->pick_event
);
2872 /* it is possible that during picking we emitted an event in which
2873 * the user then called some function which then requested update
2874 * of something. Without this we'd be left in a state where
2875 * need_update would have been left TRUE and the canvas would have
2876 * been left unpainted. */
2877 if (canvas
->need_update
) {
2882 /* Idle handler for the canvas. It deals with pending updates and redraws. */
2884 idle_handler (gpointer data
)
2886 GnomeCanvas
*canvas
;
2888 canvas
= GNOME_CANVAS (data
);
2893 canvas
->idle_id
= 0;
2898 /* Convenience function to add an idle handler to a canvas */
2900 add_idle (GnomeCanvas
*canvas
)
2902 g_return_if_fail (canvas
->need_update
);
2904 if (!canvas
->idle_id
)
2905 canvas
->idle_id
= g_idle_add_full (
2906 CANVAS_IDLE_PRIORITY
,
2911 /* canvas->idle_id = gtk_idle_add (idle_handler, canvas); */
2915 * gnome_canvas_root:
2916 * @canvas: A canvas.
2918 * Queries the root group of a canvas.
2920 * Return value: The root group of the specified canvas.
2923 gnome_canvas_root (GnomeCanvas
*canvas
)
2925 g_return_val_if_fail (GNOME_IS_CANVAS (canvas
), NULL
);
2927 return GNOME_CANVAS_GROUP (canvas
->root
);
2931 * gnome_canvas_set_scroll_region:
2932 * @canvas: A canvas.
2933 * @x1: Leftmost limit of the scrolling region.
2934 * @y1: Upper limit of the scrolling region.
2935 * @x2: Rightmost limit of the scrolling region.
2936 * @y2: Lower limit of the scrolling region.
2938 * Sets the scrolling region of a canvas to the specified rectangle. The canvas
2939 * will then be able to scroll only within this region. The view of the canvas
2940 * is adjusted as appropriate to display as much of the new region as possible.
2943 gnome_canvas_set_scroll_region (GnomeCanvas
*canvas
,
2949 GtkScrollable
*scrollable
;
2950 GtkAdjustment
*hadjustment
;
2951 GtkAdjustment
*vadjustment
;
2952 gdouble hadjustment_value
;
2953 gdouble vadjustment_value
;
2954 gdouble wxofs
, wyofs
;
2957 g_return_if_fail (GNOME_IS_CANVAS (canvas
));
2959 scrollable
= GTK_SCROLLABLE (canvas
);
2960 hadjustment
= gtk_scrollable_get_hadjustment (scrollable
);
2961 vadjustment
= gtk_scrollable_get_vadjustment (scrollable
);
2963 hadjustment_value
= gtk_adjustment_get_value (hadjustment
);
2964 vadjustment_value
= gtk_adjustment_get_value (vadjustment
);
2967 * Set the new scrolling region. If possible, do not move the
2968 * visible contents of the canvas.
2973 hadjustment_value
+ canvas
->zoom_xofs
,
2974 vadjustment_value
+ canvas
->zoom_yofs
,
2977 canvas
->scroll_x1
= x1
;
2978 canvas
->scroll_y1
= y1
;
2979 canvas
->scroll_x2
= x2
;
2980 canvas
->scroll_y2
= y2
;
2982 gnome_canvas_w2c (canvas
, wxofs
, wyofs
, &xofs
, &yofs
);
2984 scroll_to (canvas
, xofs
, yofs
);
2986 canvas
->need_repick
= TRUE
;
2988 /* todo: should be requesting update */
2989 (* GNOME_CANVAS_ITEM_CLASS (canvas
->root
->object
.class)->update
) (
2990 canvas
->root
, NULL
, NULL
, 0);
2995 * gnome_canvas_get_scroll_region:
2996 * @canvas: A canvas.
2997 * @x1: Leftmost limit of the scrolling region (return value).
2998 * @y1: Upper limit of the scrolling region (return value).
2999 * @x2: Rightmost limit of the scrolling region (return value).
3000 * @y2: Lower limit of the scrolling region (return value).
3002 * Queries the scrolling region of a canvas.
3005 gnome_canvas_get_scroll_region (GnomeCanvas
*canvas
,
3011 g_return_if_fail (GNOME_IS_CANVAS (canvas
));
3014 *x1
= canvas
->scroll_x1
;
3017 *y1
= canvas
->scroll_y1
;
3020 *x2
= canvas
->scroll_x2
;
3023 *y2
= canvas
->scroll_y2
;
3027 * gnome_canvas_scroll_to:
3028 * @canvas: A canvas.
3029 * @cx: Horizontal scrolling offset in canvas pixel units.
3030 * @cy: Vertical scrolling offset in canvas pixel units.
3032 * Makes a canvas scroll to the specified offsets, given in canvas pixel units.
3033 * The canvas will adjust the view so that it is not outside the scrolling
3034 * region. This function is typically not used, as it is better to hook
3035 * scrollbars to the canvas layout's scrolling adjusments.
3038 gnome_canvas_scroll_to (GnomeCanvas
*canvas
,
3042 g_return_if_fail (GNOME_IS_CANVAS (canvas
));
3044 scroll_to (canvas
, cx
, cy
);
3048 * gnome_canvas_get_scroll_offsets:
3049 * @canvas: A canvas.
3050 * @cx: Horizontal scrolling offset (return value).
3051 * @cy: Vertical scrolling offset (return value).
3053 * Queries the scrolling offsets of a canvas. The values are returned in canvas
3057 gnome_canvas_get_scroll_offsets (GnomeCanvas
*canvas
,
3061 GtkAdjustment
*adjustment
;
3062 GtkScrollable
*scrollable
;
3064 g_return_if_fail (GNOME_IS_CANVAS (canvas
));
3066 scrollable
= GTK_SCROLLABLE (canvas
);
3069 adjustment
= gtk_scrollable_get_hadjustment (scrollable
);
3070 *cx
= (gint
) gtk_adjustment_get_value (adjustment
);
3074 adjustment
= gtk_scrollable_get_vadjustment (scrollable
);
3075 *cy
= (gint
) gtk_adjustment_get_value (adjustment
);
3080 * gnome_canvas_get_item_at:
3081 * @canvas: A canvas.
3082 * @x: X position in world coordinates.
3083 * @y: Y position in world coordinates.
3085 * Looks for the item that is under the specified position, which must be
3086 * specified in world coordinates.
3088 * Return value: The sought item, or NULL if no item is at the specified
3092 gnome_canvas_get_item_at (GnomeCanvas
*canvas
,
3098 g_return_val_if_fail (GNOME_IS_CANVAS (canvas
), NULL
);
3100 gnome_canvas_w2c (canvas
, x
, y
, &cx
, &cy
);
3102 return gnome_canvas_item_invoke_point (canvas
->root
, x
, y
, cx
, cy
);
3105 /* Queues an update of the canvas */
3107 gnome_canvas_request_update (GnomeCanvas
*canvas
)
3109 GNOME_CANVAS_GET_CLASS (canvas
)->request_update (canvas
);
3113 gnome_canvas_request_update_real (GnomeCanvas
*canvas
)
3115 if (canvas
->need_update
)
3118 canvas
->need_update
= TRUE
;
3119 if (gtk_widget_get_mapped ((GtkWidget
*) canvas
))
3124 get_visible_rect (GnomeCanvas
*canvas
,
3125 GdkRectangle
*visible
)
3127 GtkAllocation allocation
;
3128 GtkScrollable
*scrollable
;
3129 GtkAdjustment
*hadjustment
;
3130 GtkAdjustment
*vadjustment
;
3131 gdouble hadjustment_value
;
3132 gdouble vadjustment_value
;
3134 gtk_widget_get_allocation (GTK_WIDGET (canvas
), &allocation
);
3136 scrollable
= GTK_SCROLLABLE (canvas
);
3137 hadjustment
= gtk_scrollable_get_hadjustment (scrollable
);
3138 vadjustment
= gtk_scrollable_get_vadjustment (scrollable
);
3140 hadjustment_value
= gtk_adjustment_get_value (hadjustment
);
3141 vadjustment_value
= gtk_adjustment_get_value (vadjustment
);
3143 visible
->x
= hadjustment_value
- canvas
->zoom_xofs
;
3144 visible
->y
= vadjustment_value
- canvas
->zoom_yofs
;
3145 visible
->width
= allocation
.width
;
3146 visible
->height
= allocation
.height
;
3150 * gnome_canvas_request_redraw:
3151 * @canvas: A canvas.
3152 * @x1: Leftmost coordinate of the rectangle to be redrawn.
3153 * @y1: Upper coordinate of the rectangle to be redrawn.
3154 * @x2: Rightmost coordinate of the rectangle to be redrawn, plus 1.
3155 * @y2: Lower coordinate of the rectangle to be redrawn, plus 1.
3157 * Convenience function that informs a canvas that the specified rectangle needs
3158 * to be repainted. The rectangle includes @x1 and @y1, but not @x2 and @y2. To
3159 * be used only by item implementations.
3162 gnome_canvas_request_redraw (GnomeCanvas
*canvas
,
3168 GdkRectangle area
, clip
;
3170 g_return_if_fail (GNOME_IS_CANVAS (canvas
));
3172 if (!gtk_widget_is_drawable (GTK_WIDGET (canvas
)) || (x1
>= x2
) || (y1
>= y2
))
3177 area
.width
= x2
- x1
+ 1;
3178 area
.height
= y2
- y1
+ 1;
3180 get_visible_rect (canvas
, &clip
);
3181 if (!gdk_rectangle_intersect (&area
, &clip
, &area
))
3184 gdk_window_invalidate_rect (
3185 gtk_layout_get_bin_window (GTK_LAYOUT (canvas
)),
3190 * gnome_canvas_w2c_matrix:
3191 * @canvas: A canvas.
3192 * @matrix: (out): matrix to initialize
3194 * Gets the transformtion matrix that converts from world coordinates to canvas
3195 * pixel coordinates.
3198 gnome_canvas_w2c_matrix (GnomeCanvas
*canvas
,
3199 cairo_matrix_t
*matrix
)
3201 g_return_if_fail (GNOME_IS_CANVAS (canvas
));
3202 g_return_if_fail (matrix
!= NULL
);
3204 cairo_matrix_init_translate (
3205 matrix
, -canvas
->scroll_x1
, -canvas
->scroll_y1
);
3209 * gnome_canvas_c2w_matrix:
3210 * @canvas: A canvas.
3211 * @matrix: (out): matrix to initialize
3213 * Gets the transformtion matrix that converts from canvas pixel coordinates to
3214 * world coordinates.
3217 gnome_canvas_c2w_matrix (GnomeCanvas
*canvas
,
3218 cairo_matrix_t
*matrix
)
3220 g_return_if_fail (GNOME_IS_CANVAS (canvas
));
3221 g_return_if_fail (matrix
!= NULL
);
3223 cairo_matrix_init_translate (
3224 matrix
, canvas
->scroll_x1
, canvas
->scroll_y1
);
3229 * @canvas: A canvas.
3230 * @wx: World X coordinate.
3231 * @wy: World Y coordinate.
3232 * @cx: X pixel coordinate (return value).
3233 * @cy: Y pixel coordinate (return value).
3235 * Converts world coordinates into canvas pixel coordinates.
3238 gnome_canvas_w2c (GnomeCanvas
*canvas
,
3246 g_return_if_fail (GNOME_IS_CANVAS (canvas
));
3248 gnome_canvas_w2c_matrix (canvas
, &w2c
);
3249 cairo_matrix_transform_point (&w2c
, &wx
, &wy
);
3252 *cx
= floor (wx
+ 0.5);
3254 *cy
= floor (wy
+ 0.5);
3258 * gnome_canvas_w2c_d:
3259 * @canvas: A canvas.
3260 * @wx: World X coordinate.
3261 * @wy: World Y coordinate.
3262 * @cx: X pixel coordinate (return value).
3263 * @cy: Y pixel coordinate (return value).
3265 * Converts world coordinates into canvas pixel coordinates. This
3266 * version returns coordinates in floating point coordinates, for
3267 * greater precision.
3270 gnome_canvas_w2c_d (GnomeCanvas
*canvas
,
3278 g_return_if_fail (GNOME_IS_CANVAS (canvas
));
3280 gnome_canvas_w2c_matrix (canvas
, &w2c
);
3281 cairo_matrix_transform_point (&w2c
, &wx
, &wy
);
3291 * @canvas: A canvas.
3292 * @cx: Canvas pixel X coordinate.
3293 * @cy: Canvas pixel Y coordinate.
3294 * @wx: X world coordinate (return value).
3295 * @wy: Y world coordinate (return value).
3297 * Converts canvas pixel coordinates to world coordinates.
3300 gnome_canvas_c2w (GnomeCanvas
*canvas
,
3309 g_return_if_fail (GNOME_IS_CANVAS (canvas
));
3313 gnome_canvas_c2w_matrix (canvas
, &c2w
);
3314 cairo_matrix_transform_point (&c2w
, &x
, &y
);
3323 * gnome_canvas_window_to_world:
3324 * @canvas: A canvas.
3325 * @winx: Window-relative X coordinate.
3326 * @winy: Window-relative Y coordinate.
3327 * @worldx: X world coordinate (return value).
3328 * @worldy: Y world coordinate (return value).
3330 * Converts window-relative coordinates into world coordinates. You can use
3331 * this when you need to convert mouse coordinates into world coordinates, for
3335 gnome_canvas_window_to_world (GnomeCanvas
*canvas
,
3341 g_return_if_fail (GNOME_IS_CANVAS (canvas
));
3344 *worldx
= canvas
->scroll_x1
+ (winx
- canvas
->zoom_xofs
);
3347 *worldy
= canvas
->scroll_y1
+ (winy
- canvas
->zoom_yofs
);
3351 * gnome_canvas_world_to_window:
3352 * @canvas: A canvas.
3353 * @worldx: World X coordinate.
3354 * @worldy: World Y coordinate.
3355 * @winx: X window-relative coordinate.
3356 * @winy: Y window-relative coordinate.
3358 * Converts world coordinates into window-relative coordinates.
3361 gnome_canvas_world_to_window (GnomeCanvas
*canvas
,
3367 g_return_if_fail (GNOME_IS_CANVAS (canvas
));
3370 *winx
= (worldx
- canvas
->scroll_x1
) + canvas
->zoom_xofs
;
3373 *winy
= (worldy
- canvas
->scroll_y1
) + canvas
->zoom_yofs
;
3377 boolean_handled_accumulator (GSignalInvocationHint
*ihint
,
3378 GValue
*return_accu
,
3379 const GValue
*handler_return
,
3382 gboolean continue_emission
;
3383 gboolean signal_handled
;
3385 signal_handled
= g_value_get_boolean (handler_return
);
3386 g_value_set_boolean (return_accu
, signal_handled
);
3387 continue_emission
= !signal_handled
;
3389 return continue_emission
;
3392 /* Class initialization function for GnomeCanvasItemClass */
3394 gnome_canvas_item_class_init (GnomeCanvasItemClass
*class)
3396 GObjectClass
*gobject_class
;
3398 gobject_class
= (GObjectClass
*) class;
3400 gobject_class
->set_property
= gnome_canvas_item_set_property
;
3401 gobject_class
->get_property
= gnome_canvas_item_get_property
;
3403 g_object_class_install_property (
3406 g_param_spec_object (
3410 GNOME_TYPE_CANVAS_ITEM
,
3414 item_signals
[ITEM_EVENT
] = g_signal_new (
3416 G_TYPE_FROM_CLASS (class),
3418 G_STRUCT_OFFSET (GnomeCanvasItemClass
, event
),
3419 boolean_handled_accumulator
, NULL
, NULL
,
3421 GDK_TYPE_EVENT
| G_SIGNAL_TYPE_STATIC_SCOPE
);
3423 gobject_class
->dispose
= gnome_canvas_item_dispose
;
3425 class->update
= gnome_canvas_item_update
;
3426 class->realize
= gnome_canvas_item_realize
;
3427 class->unrealize
= gnome_canvas_item_unrealize
;
3428 class->map
= gnome_canvas_item_map
;
3429 class->unmap
= gnome_canvas_item_unmap
;
3430 class->dispose
= gnome_canvas_item_dispose_item
;
3431 class->draw
= gnome_canvas_item_draw
;
3432 class->point
= gnome_canvas_item_point
;
3433 class->bounds
= gnome_canvas_item_bounds
;
3434 class->event
= gnome_canvas_item_event
;