~canonical-dx-team/ubuntu/maverick/gtk+2.0/menuproxy

« back to all changes in this revision

Viewing changes to demos/gtk-demo/drawingarea.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastien Bacher
  • Date: 2007-05-04 12:24:25 UTC
  • mfrom: (1.1.21 upstream)
  • Revision ID: james.westby@ubuntu.com-20070504122425-0m8midgzrp40y8w2
Tags: 2.10.12-1ubuntu1
* Sync with Debian
* New upstream version:
  Fixed bugs:
  - 379414 file chooser warnings when changing path in the entry
  - 418585 GtkFileChooserDefault sizing code is not DPI independent
  - 419568 Crash in search if start with special letter
  - 435062 build dies with icon cache validation
  - 379399 Segfault to call gtk_print_operation_run twice.
  - 387889 cups backend has problems when there are too many printers
  - 418531 invalid read to gtkicontheme.c gtk_icon_theme_lookup_icon...
  - 423916 crash in color scheme code
  - 424042 Segmentation fault while quickly pressing Alt+arrows
  - 415260 Protect against negative indices when setting values in G...
  - 419171 XGetVisualInfo() may not set nxvisuals
  - 128852 Gdk cursors don't look good on win32
  - 344657 Ctrl-H doesn't toggle "Show Hidden Files" setting
  - 345345 PrintOperation::paginate is not emitted for class handler
  - 347567 GtkPrintOperation::end-print is not emitted if it's cance...
  - 369112 gtk_ui_manager_add_ui should accept unnamed separator
  - 392015 Selected menu item invisible on Windows Vista
  - 399253 MS-Windows Theme Bottom Tab placement rendering glitches
  - 399425 gtk_input_dialog_fill_axes() adds child to gtkscrolledwin...
  - 403251 [patch] little memory leak in GtkPrintJob
  - 403267 [patch] memory leak in GtkPageSetupUnixDialog
  - 403470 MS-Windows Theme tab placement other than on top leaks a ...
  - 404506 Windows system fonts that have multi-byte font names cann...
  - 405089 Incorrect window placement for GtkEventBox private window
  - 405515 Minor leak in gtkfilesystemmodel.c
  - 405539 gdk_pixbuf_save() for PNG saver can return FALSE without ...
  - 415681 gdk_window_clear_area includes an extra line and column o...
  - 418219 GtkRecentChooser should apply filter before sorting and c...
  - 418403 Scroll to printer after selecting it from settings
  - 421985 _gtk_print_operation_platform_backend_launch_preview
  - 421990 gtk_print_job_get_surface
  - 421993 gtk_print_operation_init
  - 423064 Conditional jump or move depends on uninitialised value(s...
  - 423722 Fix printing header in gtk-demo
  - 424168 gtk_print_operation_run on async preview
  - 425655 Don't install gtk+-unix-print-2.0.pc on non-UNIX platforms
  - 425786 GDK segfaults if XineramaQueryScreens fails
  - 428665 Lpr Backend gets stuck in infinite loop during gtk_enumer...
  - 429902 GtkPrintOperation leaks cairo contextes
  - 431997 First delay of GdkPixbufAnimationIter is wrong
  - 433242 Inconsistent scroll arrow position calculations
  - 433972 Placing gtk.Expander inside a gtk.TextView() changes gtk....
  - 434261 _gtk_toolbar_elide_underscores incorrectly handles some s...
  - 383354 ctrl-L should make 'Location' entry disappear
  - 418673 gtk_recent_manager_add_item
  - 429732 gtk_accel_group_finalize accesses invalid memory
  - 435028 WM_CLIENT_LEADER is wrong on the leader_window
  - 431067 Background of the header window is not updated
  - 338843 add recent files support inside the ui manager
  - 148535 add drop shadow to menus, tooltips, etc. under Windows XP
* debian/control.in:
  - Conflicts on ubuntulooks (<= 0.9.11-1)
* debian/patches/15_default-fallback-icon-theme.patch:
  - patch from Debian, fallback on gnome icon theme

Show diffs side-by-side

added added

removed removed

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