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