1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: 8; c-basic-offset: 8 -*- */
2 /*
3  * Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation
4  * All rights reserved.
5  *
6  * This file is part of the Mate Library.
7  *
8  * The Mate Library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public License as
10  * published by the Free Software Foundation; either version 2 of the
11  * License, or (at your option) any later version.
12  *
13  * The Mate Library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with the Mate Library; see the file COPYING.LIB.  If not,
20  * write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
21  * Boston, MA 02110-1301, USA.
22  */
23 /*
24   @NOTATION@
25  */
26 /* EelCanvas widget - Tk-like canvas widget for Mate
27  *
28  * EelCanvas is basically a port of the Tk toolkit's most excellent canvas
29  * widget.  Tk is copyrighted by the Regents of the University of California,
30  * Sun Microsystems, and other parties.
31  *
32  *
33  * Authors: Federico Mena <federico@nuclecu.unam.mx>
34  *          Raph Levien <raph@gimp.org>
35  */
36 
37 #ifndef EEL_CANVAS_H
38 #define EEL_CANVAS_H
39 
40 #include <gtk/gtk.h>
41 #include <gtk/gtk-a11y.h>
42 #include <gdk/gdk.h>
43 #include <stdarg.h>
44 
45 #ifdef __cplusplus
46 extern "C" {
47 #endif
48 
49 
50     /* "Small" value used by canvas stuff */
51 #define EEL_CANVAS_EPSILON 1e-10
52 
53 
54     /* Macros for building colors that fit in a 32-bit integer.  The values are in
55      * [0, 255].
56      */
57 
58 #define EEL_CANVAS_COLOR(r, g, b) ((((int) (r) & 0xff) << 24)	\
59 				     | (((int) (g) & 0xff) << 16)	\
60 				     | (((int) (b) & 0xff) << 8)	\
61 				     | 0xff)
62 
63 #define EEL_CANVAS_COLOR_A(r, g, b, a) ((((int) (r) & 0xff) << 24)	\
64 					  | (((int) (g) & 0xff) << 16)	\
65 					  | (((int) (b) & 0xff) << 8)	\
66 					  | ((int) (a) & 0xff))
67 
68 
69     typedef struct _EelCanvas           EelCanvas;
70     typedef struct _EelCanvasClass      EelCanvasClass;
71     typedef struct _EelCanvasItem       EelCanvasItem;
72     typedef struct _EelCanvasItemClass  EelCanvasItemClass;
73     typedef struct _EelCanvasGroup      EelCanvasGroup;
74     typedef struct _EelCanvasGroupClass EelCanvasGroupClass;
75 
76 
77     /* EelCanvasItem - base item class for canvas items
78      *
79      * All canvas items are derived from EelCanvasItem.  The only information a
80      * EelCanvasItem contains is its parent canvas, its parent canvas item group,
81      * and its bounding box in world coordinates.
82      *
83      * Items inside a canvas are organized in a tree of EelCanvasItemGroup nodes
84      * and EelCanvasItem leaves.  Each canvas has a single root group, which can
85      * be obtained with the eel_canvas_get_root() function.
86      *
87      * The abstract EelCanvasItem class does not have any configurable or
88      * queryable attributes.
89      */
90 
91     /* Object flags for items */
92     enum
93     {
94         EEL_CANVAS_ITEM_REALIZED         = 1 << 4,
95         EEL_CANVAS_ITEM_MAPPED           = 1 << 5,
96         EEL_CANVAS_ITEM_ALWAYS_REDRAW    = 1 << 6,
97         EEL_CANVAS_ITEM_VISIBLE          = 1 << 7,
98         EEL_CANVAS_ITEM_NEED_UPDATE      = 1 << 8,
99         EEL_CANVAS_ITEM_NEED_DEEP_UPDATE = 1 << 9
100     };
101 
102     /* Update flags for items */
103     enum
104     {
105         EEL_CANVAS_UPDATE_REQUESTED  = 1 << 0,
106         EEL_CANVAS_UPDATE_DEEP       = 1 << 1
107     };
108 
109 #define EEL_TYPE_CANVAS_ITEM            (eel_canvas_item_get_type ())
110 #define EEL_CANVAS_ITEM(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), EEL_TYPE_CANVAS_ITEM, EelCanvasItem))
111 #define EEL_CANVAS_ITEM_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), EEL_TYPE_CANVAS_ITEM, EelCanvasItemClass))
112 #define EEL_IS_CANVAS_ITEM(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EEL_TYPE_CANVAS_ITEM))
113 #define EEL_IS_CANVAS_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EEL_TYPE_CANVAS_ITEM))
114 #define EEL_CANVAS_ITEM_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), EEL_TYPE_CANVAS_ITEM, EelCanvasItemClass))
115 
116 
117     struct _EelCanvasItem
118     {
119         GInitiallyUnowned object;
120 
121         /* Parent canvas for this item */
122         EelCanvas *canvas;
123 
124         /* Parent canvas group for this item (a EelCanvasGroup) */
125         EelCanvasItem *parent;
126 
127         /* Bounding box for this item (in canvas coordinates) */
128         double x1, y1, x2, y2;
129 
130         /* Object flags */
131         guint flags;
132     };
133 
134     struct _EelCanvasItemClass
135     {
136         GInitiallyUnownedClass parent_class;
137 
138         void (* destroy) (EelCanvasItem *item);
139 
140         /* Tell the item to update itself.  The flags are from the update flags
141          * defined above.  The item should update its internal state from its
142          * queued state, and recompute and request its repaint area. The
143          * update method also recomputes the bounding box of the item.
144          */
145         void (* update) (EelCanvasItem *item, double i2w_dx, double i2w_dy, int flags);
146 
147         /* Realize an item -- create GCs, etc. */
148         void (* realize) (EelCanvasItem *item);
149 
150         /* Unrealize an item */
151         void (* unrealize) (EelCanvasItem *item);
152 
153         /* Map an item - normally only need by items with their own GdkWindows */
154         void (* map) (EelCanvasItem *item);
155 
156         /* Unmap an item */
157         void (* unmap) (EelCanvasItem *item);
158 
159         /* Draw an item of this type.  (x, y) are the upper-left canvas pixel
160          * coordinates of the drawable, a temporary pixmap, where things get
161          * drawn.  (width, height) are the dimensions of the drawable.
162          */
163 	void (* draw) (EelCanvasItem *item, cairo_t *cr, cairo_region_t *region);
164 
165         /* Calculate the distance from an item to the specified point.  It also
166              * returns a canvas item which is the item itself in the case of the
167              * object being an actual leaf item, or a child in case of the object
168              * being a canvas group.  (cx, cy) are the canvas pixel coordinates that
169              * correspond to the item-relative coordinates (x, y).
170          */
171         double (* point) (EelCanvasItem *item, double x, double y, int cx, int cy,
172                           EelCanvasItem **actual_item);
173 
174         void (* translate) (EelCanvasItem *item, double dx, double dy);
175 
176         /* Fetch the item's bounding box (need not be exactly tight).  This
177          * should be in item-relative coordinates.
178          */
179         void (* bounds) (EelCanvasItem *item, double *x1, double *y1, double *x2, double *y2);
180 
181         /* Signal: an event ocurred for an item of this type.  The (x, y)
182          * coordinates are in the canvas world coordinate system.
183          */
184         gboolean (* event)                (EelCanvasItem *item, GdkEvent *event);
185 
186         /* Reserved for future expansion */
187         gpointer spare_vmethods [4];
188     };
189 
190 
191     /* Standard Gtk function */
192     GType eel_canvas_item_get_type (void) G_GNUC_CONST;
193 
194     /* Create a canvas item using the standard Gtk argument mechanism.  The item is
195      * automatically inserted at the top of the specified canvas group.  The last
196      * argument must be a NULL pointer.
197      */
198     EelCanvasItem *eel_canvas_item_new (EelCanvasGroup *parent, GType type,
199                                         const gchar *first_arg_name, ...);
200 
201     void eel_canvas_item_destroy (EelCanvasItem *item);
202 
203     /* Constructors for use in derived classes and language wrappers */
204     void eel_canvas_item_construct (EelCanvasItem *item, EelCanvasGroup *parent,
205                                     const gchar *first_arg_name, va_list args);
206 
207     /* Configure an item using the standard Gtk argument mechanism.  The last
208      * argument must be a NULL pointer.
209      */
210     void eel_canvas_item_set (EelCanvasItem *item, const gchar *first_arg_name, ...);
211 
212     /* Used only for language wrappers and the like */
213     void eel_canvas_item_set_valist (EelCanvasItem *item,
214                                      const gchar *first_arg_name, va_list args);
215 
216     /* Move an item by the specified amount */
217     void eel_canvas_item_move (EelCanvasItem *item, double dx, double dy);
218 
219     /* Raise an item in the z-order of its parent group by the specified number of
220      * positions.
221      */
222     void eel_canvas_item_raise (EelCanvasItem *item, int positions);
223 
224     /* Lower an item in the z-order of its parent group by the specified number of
225      * positions.
226      */
227     void eel_canvas_item_lower (EelCanvasItem *item, int positions);
228 
229     /* Raise an item to the top of its parent group's z-order. */
230     void eel_canvas_item_raise_to_top (EelCanvasItem *item);
231 
232     /* Lower an item to the bottom of its parent group's z-order */
233     void eel_canvas_item_lower_to_bottom (EelCanvasItem *item);
234 
235     /* Send an item behind another item */
236     void eel_canvas_item_send_behind (EelCanvasItem *item,
237                                       EelCanvasItem *behind_item);
238 
239 
240     /* Show an item (make it visible).  If the item is already shown, it has no
241      * effect.
242      */
243     void eel_canvas_item_show (EelCanvasItem *item);
244 
245     /* Hide an item (make it invisible).  If the item is already invisible, it has
246      * no effect.
247      */
248     void eel_canvas_item_hide (EelCanvasItem *item);
249 
250     /* Grab the seat for the specified item.  Only the events in event_mask will be
251      * reported. If cursor is non-NULL, it will be used during the duration of the
252      * grab. event is the event, triggering the grab. Returns the same values as gdk_seat_grab().
253      */
254      GdkGrabStatus eel_canvas_item_grab (EelCanvasItem *item,
255                                          GdkEventMask event_mask,
256                                          GdkCursor *cursor,
257                                          const GdkEvent* event);
258 
259     /* Ungrabs the seat -- the specified item must be the same that was passed to
260      * eel_canvas_item_grab().
261      */
262     void eel_canvas_item_ungrab (EelCanvasItem *item);
263 
264     /* These functions convert from a coordinate system to another.  "w" is world
265      * coordinates and "i" is item coordinates.
266      */
267     void eel_canvas_item_w2i (EelCanvasItem *item, double *x, double *y);
268     void eel_canvas_item_i2w (EelCanvasItem *item, double *x, double *y);
269 
270     /* Remove the item from its parent group and make the new group its parent.  The
271      * item will be put on top of all the items in the new group.  The item's
272      * coordinates relative to its new parent to *not* change -- this means that the
273      * item could potentially move on the screen.
274      *
275      * The item and the group must be in the same canvas.  An item cannot be
276      * reparented to a group that is the item itself or that is an inferior of the
277      * item.
278      */
279     void eel_canvas_item_reparent (EelCanvasItem *item, EelCanvasGroup *new_group);
280 
281     /* Used to send all of the keystroke events to a specific item as well as
282      * GDK_FOCUS_CHANGE events.
283      */
284     void eel_canvas_item_grab_focus (EelCanvasItem *item);
285 
286     /* Fetch the bounding box of the item.  The bounding box may not be exactly
287      * tight, but the canvas items will do the best they can.  The returned bounding
288      * box is in the coordinate system of the item's parent.
289      */
290     void eel_canvas_item_get_bounds (EelCanvasItem *item,
291                                      double *x1, double *y1, double *x2, double *y2);
292 
293     /* Request that the update method eventually get called.  This should be used
294      * only by item implementations.
295      */
296     void eel_canvas_item_request_update (EelCanvasItem *item);
297 
298     /* Request a redraw of the bounding box of the canvas item */
299     void eel_canvas_item_request_redraw (EelCanvasItem *item);
300 
301     /* EelCanvasGroup - a group of canvas items
302      *
303      * A group is a node in the hierarchical tree of groups/items inside a canvas.
304      * Groups serve to give a logical structure to the items.
305      *
306      * Consider a circuit editor application that uses the canvas for its schematic
307      * display.  Hierarchically, there would be canvas groups that contain all the
308      * components needed for an "adder", for example -- this includes some logic
309      * gates as well as wires.  You can move stuff around in a convenient way by
310      * doing a eel_canvas_item_move() of the hierarchical groups -- to move an
311      * adder, simply move the group that represents the adder.
312      *
313      * The following arguments are available:
314      *
315      * name		type		read/write	description
316      * --------------------------------------------------------------------------------
317      * x		double		RW		X coordinate of group's origin
318      * y		double		RW		Y coordinate of group's origin
319      */
320 
321 
322 #define EEL_TYPE_CANVAS_GROUP            (eel_canvas_group_get_type ())
323 #define EEL_CANVAS_GROUP(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), EEL_TYPE_CANVAS_GROUP, EelCanvasGroup))
324 #define EEL_CANVAS_GROUP_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), EEL_TYPE_CANVAS_GROUP, EelCanvasGroupClass))
325 #define EEL_IS_CANVAS_GROUP(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EEL_TYPE_CANVAS_GROUP))
326 #define EEL_IS_CANVAS_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EEL_TYPE_CANVAS_GROUP))
327 #define EEL_CANVAS_GROUP_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), EEL_TYPE_CANVAS_GROUP, EelCanvasGroupClass))
328 
329 
330     struct _EelCanvasGroup
331     {
332         EelCanvasItem item;
333 
334         double xpos, ypos;
335 
336         /* Children of the group */
337         GList *item_list;
338         GList *item_list_end;
339     };
340 
341     struct _EelCanvasGroupClass
342     {
343         EelCanvasItemClass parent_class;
344     };
345 
346 
347     /* Standard Gtk function */
348     GType eel_canvas_group_get_type (void) G_GNUC_CONST;
349 
350 
351     /*** EelCanvas ***/
352 
353 
354 #define EEL_TYPE_CANVAS            (eel_canvas_get_type ())
355 #define EEL_CANVAS(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), EEL_TYPE_CANVAS, EelCanvas))
356 #define EEL_CANVAS_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), EEL_TYPE_CANVAS, EelCanvasClass))
357 #define EEL_IS_CANVAS(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EEL_TYPE_CANVAS))
358 #define EEL_IS_CANVAS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EEL_TYPE_CANVAS))
359 #define EEL_CANVAS_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), EEL_TYPE_CANVAS, EelCanvasClass))
360 
361 
362     struct _EelCanvas
363     {
364         GtkLayout layout;
365 
366         /* Root canvas group */
367         EelCanvasItem *root;
368 
369         /* The item containing the mouse pointer, or NULL if none */
370         EelCanvasItem *current_item;
371 
372         /* Item that is about to become current (used to track deletions and such) */
373         EelCanvasItem *new_current_item;
374 
375         /* Item that holds a pointer grab, or NULL if none */
376         EelCanvasItem *grabbed_item;
377 
378         /* If non-NULL, the currently focused item */
379         EelCanvasItem *focused_item;
380 
381         /* Event on which selection of current item is based */
382         GdkEvent pick_event;
383 
384         /* Scrolling region */
385         double scroll_x1, scroll_y1;
386         double scroll_x2, scroll_y2;
387 
388         /* Scaling factor to be used for display */
389         double pixels_per_unit;
390 
391         /* Idle handler ID */
392         guint idle_id;
393 
394         /* Signal handler ID for destruction of the root item */
395         guint root_destroy_id;
396 
397         /* Internal pixel offsets when zoomed out */
398         int zoom_xofs, zoom_yofs;
399 
400         /* Last known modifier state, for deferred repick when a button is down */
401         int state;
402 
403         /* Event mask specified when grabbing an item */
404         guint grabbed_event_mask;
405 
406         /* Tolerance distance for picking items */
407         int close_enough;
408 
409         /* Whether the canvas should center the canvas in the middle of
410          * the window if the scroll region is smaller than the window */
411         unsigned int center_scroll_region : 1;
412 
413         /* Whether items need update at next idle loop iteration */
414         unsigned int need_update : 1;
415 
416         /* Are we in the midst of an update */
417         unsigned int doing_update : 1;
418 
419         /* Whether the canvas needs redrawing at the next idle loop iteration */
420         unsigned int need_redraw : 1;
421 
422         /* Whether current item will be repicked at next idle loop iteration */
423         unsigned int need_repick : 1;
424 
425         /* For use by internal pick_current_item() function */
426         unsigned int left_grabbed_item : 1;
427 
428         /* For use by internal pick_current_item() function */
429         unsigned int in_repick : 1;
430     };
431 
432     struct _EelCanvasClass
433     {
434         GtkLayoutClass parent_class;
435 
436         /* Draw the background for the area given.
437          */
438         void (* draw_background) (EelCanvas *canvas,
439                                   cairo_t *cr);
440 
441         /* Private Virtual methods for groping the canvas inside matecomponent */
442         void (* request_update) (EelCanvas *canvas);
443 
444         /* Reserved for future expansion */
445         gpointer spare_vmethods [4];
446     };
447 
448 
449     /* Standard Gtk function */
450     GType eel_canvas_get_type (void) G_GNUC_CONST;
451 
452     /* Creates a new canvas.  You should check that the canvas is created with the
453      * proper visual and colormap.  Any visual will do unless you intend to insert
454      * gdk_imlib images into it, in which case you should use the gdk_imlib visual.
455      *
456      * You should call eel_canvas_set_scroll_region() soon after calling this
457      * function to set the desired scrolling limits for the canvas.
458      */
459     GtkWidget *eel_canvas_new (void);
460 
461     /* Returns the root canvas item group of the canvas */
462     EelCanvasGroup *eel_canvas_root (EelCanvas *canvas);
463 
464     /* Sets the limits of the scrolling region, in world coordinates */
465     void eel_canvas_set_scroll_region (EelCanvas *canvas,
466                                        double x1, double y1, double x2, double y2);
467 
468     /* Gets the limits of the scrolling region, in world coordinates */
469     void eel_canvas_get_scroll_region (EelCanvas *canvas,
470                                        double *x1, double *y1, double *x2, double *y2);
471 
472     /* Sets the number of pixels that correspond to one unit in world coordinates */
473     void eel_canvas_set_pixels_per_unit (EelCanvas *canvas, double n);
474 
475     /* Wether the canvas centers the scroll region if it is smaller than the window  */
476     void eel_canvas_set_center_scroll_region (EelCanvas *canvas, gboolean center_scroll_region);
477 
478     /* Scrolls the canvas to the specified offsets, given in canvas pixel coordinates */
479     void eel_canvas_scroll_to (EelCanvas *canvas, int cx, int cy);
480 
481     /* Returns the scroll offsets of the canvas in canvas pixel coordinates.  You
482      * can specify NULL for any of the values, in which case that value will not be
483      * queried.
484      */
485     void eel_canvas_get_scroll_offsets (EelCanvas *canvas, int *cx, int *cy);
486 
487     /* Requests that the canvas be repainted immediately instead of in the idle
488      * loop.
489      */
490     void eel_canvas_update_now (EelCanvas *canvas);
491 
492     /* Returns the item that is at the specified position in world coordinates, or
493      * NULL if no item is there.
494      */
495     EelCanvasItem *eel_canvas_get_item_at (EelCanvas *canvas, double x, double y);
496 
497     /* For use only by item type implementations.  Request that the canvas
498      * eventually redraw the specified region, specified in canvas pixel
499      * coordinates.  The region contains (x1, y1) but not (x2, y2).
500      */
501     void eel_canvas_request_redraw (EelCanvas *canvas, int x1, int y1, int x2, int y2);
502 
503     /* These functions convert from a coordinate system to another.  "w" is world
504      * coordinates, "c" is canvas pixel coordinates (pixel coordinates that are
505      * (0,0) for the upper-left scrolling limit and something else for the
506      * lower-left scrolling limit).
507      */
508     void eel_canvas_w2c_rect_d (EelCanvas *canvas,
509                                 double *x1, double *y1,
510                                 double *x2, double *y2);
511     void eel_canvas_w2c (EelCanvas *canvas, double wx, double wy, int *cx, int *cy);
512     void eel_canvas_w2c_d (EelCanvas *canvas, double wx, double wy, double *cx, double *cy);
513     void eel_canvas_c2w (EelCanvas *canvas, int cx, int cy, double *wx, double *wy);
514 
515     /* This function takes in coordinates relative to the GTK_LAYOUT
516      * (canvas)->bin_window and converts them to world coordinates.
517      * These days canvas coordinates and window coordinates are the same, but
518      * these are left for backwards compat reasons.
519      */
520     void eel_canvas_window_to_world (EelCanvas *canvas,
521                                      double winx, double winy, double *worldx, double *worldy);
522 
523     /* This is the inverse of eel_canvas_window_to_world() */
524     void eel_canvas_world_to_window (EelCanvas *canvas,
525                                      double worldx, double worldy, double *winx, double *winy);
526 
527     GType eel_canvas_accessible_get_type (void);
528 
529     typedef struct _EelCanvasAccessible EelCanvasAccessible;
530     typedef struct _EelCanvasAccessibleClass EelCanvasAccessibleClass;
531 
532     struct _EelCanvasAccessible
533     {
534         GtkContainerAccessible parent;
535     };
536 
537     struct _EelCanvasAccessibleClass
538     {
539         GtkContainerAccessibleClass parent_class;
540     };
541 
542     GType eel_canvas_item_accessible_get_type (void);
543 
544     typedef struct _EelCanvasItemAccessible EelCanvasItemAccessible;
545     typedef struct _EelCanvasItemAccessibleClass EelCanvasItemAccessibleClass;
546 
547     struct _EelCanvasItemAccessible
548     {
549         GtkAccessible parent;
550     };
551 
552     struct _EelCanvasItemAccessibleClass
553     {
554         GtkAccessibleClass parent_class;
555     };
556 
557 #ifdef __cplusplus
558 }
559 #endif
560 
561 #endif
562