/src/wrappers/gtk/examples/gtk-demo/drawingarea.e
Specman e | 349 lines | 21 code | 66 blank | 262 comment | 2 complexity | 62b6a3354ab17b9e42e220e05847a08f MD5 | raw file
1indexing 2 description: "." 3 copyright: "[ 4 Copyright (C) 2006 Paolo Redaelli, GTK+ team 5 6 This library is free software; you can redistribute it and/or 7 modify it under the terms of the GNU Lesser General Public License 8 as published by the Free Software Foundation; either version 2.1 of 9 the License, or (at your option) any later version. 10 11 This library is distributed in the hope that it will be useful, but 12 WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 Lesser General Public License for more details. 15 16 You should have received a copy of the GNU Lesser General Public 17 License along with this library; if not, write to the Free Software 18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19 02110-1301 USA 20 ]" 21 22class DRAWINGAREA 23 24creation make 25 26feature 27-- /* Drawing Area 28-- * 29-- * GtkDrawingArea is a blank area where you can draw custom displays 30-- * of various kinds. 31-- * 32-- * This demo has two drawing areas. The checkerboard area shows 33-- * how you can just draw something; all you have to do is write 34-- * a signal handler for expose_event, as shown here. 35-- * 36-- * The "scribble" area is a bit more advanced, and shows how to handle 37-- * events such as button presses and mouse motion. Click the mouse 38-- * and drag in the scribble area to draw squiggles. Resize the window 39-- * to clear the area. 40-- */ 41 42-- #include <gtk/gtk.h> 43 44-- static GtkWidget *window = NULL; 45-- /* Pixmap for scribble area, to store current scribbles */ 46-- static GdkPixmap *pixmap = NULL; 47 48-- /* Create a new pixmap of the appropriate size to store our scribbles */ 49-- static gboolean 50-- scribble_configure_event (GtkWidget *widget, 51-- GdkEventConfigure *event, 52-- gpointer data) 53-- { 54-- if (pixmap) 55-- g_object_unref (pixmap); 56 57-- pixmap = gdk_pixmap_new (widget->window, 58-- widget->allocation.width, 59-- widget->allocation.height, 60-- -1); 61 62-- /* Initialize the pixmap to white */ 63-- gdk_draw_rectangle (pixmap, 64-- widget->style->white_gc, 65-- TRUE, 66-- 0, 0, 67-- widget->allocation.width, 68-- widget->allocation.height); 69 70-- /* We've handled the configure event, no need for further processing. */ 71-- return TRUE; 72-- } 73 74-- /* Redraw the screen from the pixmap */ 75-- static gboolean 76-- scribble_expose_event (GtkWidget *widget, 77-- GdkEventExpose *event, 78-- gpointer data) 79-- { 80-- /* We use the "foreground GC" for the widget since it already exists, 81-- * but honestly any GC would work. The only thing to worry about 82-- * is whether the GC has an inappropriate clip region set. 83-- */ 84 85-- gdk_draw_drawable (widget->window, 86-- widget->style->fg_gc[GTK_WIDGET_STATE (widget)], 87-- pixmap, 88-- /* Only copy the area that was exposed. */ 89-- event->area.x, event->area.y, 90-- event->area.x, event->area.y, 91-- event->area.width, event->area.height); 92 93-- return FALSE; 94-- } 95 96-- /* Draw a rectangle on the screen */ 97-- static void 98-- draw_brush (GtkWidget *widget, 99-- gdouble x, 100-- gdouble y) 101-- { 102-- GdkRectangle update_rect; 103 104-- update_rect.x = x - 3; 105-- update_rect.y = y - 3; 106-- update_rect.width = 6; 107-- update_rect.height = 6; 108 109-- /* Paint to the pixmap, where we store our state */ 110-- gdk_draw_rectangle (pixmap, 111-- widget->style->black_gc, 112-- TRUE, 113-- update_rect.x, update_rect.y, 114-- update_rect.width, update_rect.height); 115 116-- /* Now invalidate the affected region of the drawing area. */ 117-- gdk_window_invalidate_rect (widget->window, 118-- &update_rect, 119-- FALSE); 120-- } 121 122-- static gboolean 123-- scribble_button_press_event (GtkWidget *widget, 124-- GdkEventButton *event, 125-- gpointer data) 126-- { 127-- if (pixmap == NULL) 128-- return FALSE; /* paranoia check, in case we haven't gotten a configure event */ 129 130-- if (event->button == 1) 131-- draw_brush (widget, event->x, event->y); 132 133-- /* We've handled the event, stop processing */ 134-- return TRUE; 135-- } 136 137-- static gboolean 138-- scribble_motion_notify_event (GtkWidget *widget, 139-- GdkEventMotion *event, 140-- gpointer data) 141-- { 142-- int x, y; 143-- GdkModifierType state; 144 145-- if (pixmap == NULL) 146-- return FALSE; /* paranoia check, in case we haven't gotten a configure event */ 147 148-- /* This call is very important; it requests the next motion event. 149-- * If you don't call gdk_window_get_pointer() you'll only get 150-- * a single motion event. The reason is that we specified 151-- * GDK_POINTER_MOTION_HINT_MASK to gtk_widget_set_events(). 152-- * If we hadn't specified that, we could just use event->x, event->y 153-- * as the pointer location. But we'd also get deluged in events. 154-- * By requesting the next event as we handle the current one, 155-- * we avoid getting a huge number of events faster than we 156-- * can cope. 157-- */ 158 159-- gdk_window_get_pointer (event->window, &x, &y, &state); 160 161-- if (state & GDK_BUTTON1_MASK) 162-- draw_brush (widget, x, y); 163 164-- /* We've handled it, stop processing */ 165-- return TRUE; 166-- } 167 168 169-- static gboolean 170-- checkerboard_expose (GtkWidget *da, 171-- GdkEventExpose *event, 172-- gpointer data) 173-- { 174-- gint i, j, xcount, ycount; 175-- GdkGC *gc1, *gc2; 176-- GdkColor color; 177 178-- #define CHECK_SIZE 10 179-- #define SPACING 2 180 181-- /* At the start of an expose handler, a clip region of event->area 182-- * is set on the window, and event->area has been cleared to the 183-- * widget's background color. The docs for 184-- * gdk_window_begin_paint_region() give more details on how this 185-- * works. 186-- */ 187 188-- /* It would be a bit more efficient to keep these 189-- * GC's around instead of recreating on each expose, but 190-- * this is the lazy/slow way. 191-- */ 192-- gc1 = gdk_gc_new (da->window); 193-- color.red = 30000; 194-- color.green = 0; 195-- color.blue = 30000; 196-- gdk_gc_set_rgb_fg_color (gc1, &color); 197 198-- gc2 = gdk_gc_new (da->window); 199-- color.red = 65535; 200-- color.green = 65535; 201-- color.blue = 65535; 202-- gdk_gc_set_rgb_fg_color (gc2, &color); 203 204-- xcount = 0; 205-- i = SPACING; 206-- while (i < da->allocation.width) 207-- { 208-- j = SPACING; 209-- ycount = xcount % 2; /* start with even/odd depending on row */ 210-- while (j < da->allocation.height) 211-- { 212-- GdkGC *gc; 213 214-- if (ycount % 2) 215-- gc = gc1; 216-- else 217-- gc = gc2; 218 219-- /* If we're outside event->area, this will do nothing. 220-- * It might be mildly more efficient if we handled 221-- * the clipping ourselves, but again we're feeling lazy. 222-- */ 223-- gdk_draw_rectangle (da->window, 224-- gc, 225-- TRUE, 226-- i, j, 227-- CHECK_SIZE, 228-- CHECK_SIZE); 229 230-- j += CHECK_SIZE + SPACING; 231-- ++ycount; 232-- } 233 234-- i += CHECK_SIZE + SPACING; 235-- ++xcount; 236-- } 237 238-- g_object_unref (gc1); 239-- g_object_unref (gc2); 240 241-- /* return TRUE because we've handled this event, so no 242-- * further processing is required. 243-- */ 244-- return TRUE; 245-- } 246 247-- GtkWidget * 248-- do_drawingarea (GtkWidget *do_widget) 249-- { 250-- GtkWidget *frame; 251-- GtkWidget *vbox; 252-- GtkWidget *da; 253-- GtkWidget *label; 254 255-- if (!window) 256-- { 257-- window = gtk_window_new (GTK_WINDOW_TOPLEVEL); 258-- gtk_window_set_screen (GTK_WINDOW (window), 259-- gtk_widget_get_screen (do_widget)); 260-- gtk_window_set_title (GTK_WINDOW (window), "Drawing Area"); 261 262-- g_signal_connect (window, "destroy", G_CALLBACK (gtk_widget_destroyed), &window); 263 264-- gtk_container_set_border_width (GTK_CONTAINER (window), 8); 265 266-- vbox = gtk_vbox_new (FALSE, 8); 267-- gtk_container_set_border_width (GTK_CONTAINER (vbox), 8); 268-- gtk_container_add (GTK_CONTAINER (window), vbox); 269 270-- /* 271-- * Create the checkerboard area 272-- */ 273 274-- label = gtk_label_new (NULL); 275-- gtk_label_set_markup (GTK_LABEL (label), 276-- "<u>Checkerboard pattern</u>"); 277-- gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0); 278 279-- frame = gtk_frame_new (NULL); 280-- gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN); 281-- gtk_box_pack_start (GTK_BOX (vbox), frame, TRUE, TRUE, 0); 282 283-- da = gtk_drawing_area_new (); 284-- /* set a minimum size */ 285-- gtk_widget_set_size_request (da, 100, 100); 286 287-- gtk_container_add (GTK_CONTAINER (frame), da); 288 289-- g_signal_connect (da, "expose_event", 290-- G_CALLBACK (checkerboard_expose), NULL); 291 292-- /* 293-- * Create the scribble area 294-- */ 295 296-- label = gtk_label_new (NULL); 297-- gtk_label_set_markup (GTK_LABEL (label), 298-- "<u>Scribble area</u>"); 299-- gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0); 300 301-- frame = gtk_frame_new (NULL); 302-- gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN); 303-- gtk_box_pack_start (GTK_BOX (vbox), frame, TRUE, TRUE, 0); 304 305-- da = gtk_drawing_area_new (); 306-- /* set a minimum size */ 307-- gtk_widget_set_size_request (da, 100, 100); 308 309-- gtk_container_add (GTK_CONTAINER (frame), da); 310 311-- /* Signals used to handle backing pixmap */ 312 313-- g_signal_connect (da, "expose_event", 314-- G_CALLBACK (scribble_expose_event), NULL); 315-- g_signal_connect (da,"configure_event", 316-- G_CALLBACK (scribble_configure_event), NULL); 317 318-- /* Event signals */ 319 320-- g_signal_connect (da, "motion_notify_event", 321-- G_CALLBACK (scribble_motion_notify_event), NULL); 322-- g_signal_connect (da, "button_press_event", 323-- G_CALLBACK (scribble_button_press_event), NULL); 324 325 326-- /* Ask to receive events the drawing area doesn't normally 327-- * subscribe to 328-- */ 329-- gtk_widget_set_events (da, gtk_widget_get_events (da) 330-- | GDK_LEAVE_NOTIFY_MASK 331-- | GDK_BUTTON_PRESS_MASK 332-- | GDK_POINTER_MOTION_MASK 333-- | GDK_POINTER_MOTION_HINT_MASK); 334 335-- } 336 337-- if (!GTK_WIDGET_VISIBLE (window)) 338-- { 339-- gtk_widget_show_all (window); 340-- } 341-- else 342-- { 343-- gtk_widget_destroy (window); 344-- window = NULL; 345-- } 346 347-- return window; 348-- } 349end