]> Pileus Git - ~andy/gtk/blob - tests/testgtk.c
Merge branch 'gtk-2-90'
[~andy/gtk] / tests / testgtk.c
1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /*
21  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
22  * file for a list of people on the GTK+ Team.  See the ChangeLog
23  * files for a list of changes.  These files are distributed with
24  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
25  */
26
27
28 #include "config.h"
29
30 #undef  G_LOG_DOMAIN
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <sys/stat.h>
36 #include <math.h>
37 #include <time.h>
38 #ifdef HAVE_UNISTD_H
39 #include <unistd.h>
40 #endif
41
42 #define GTK_ENABLE_BROKEN
43 #include "gtk/gtk.h"
44 #include "gdk/gdk.h"
45 #include "gdk/gdkkeysyms.h"
46
47 #ifdef G_OS_WIN32
48 #define sleep(n) _sleep(n)
49 #endif
50
51 #include "prop-editor.h"
52
53 #include "circles.xbm"
54 #include "test.xpm"
55
56 gboolean
57 file_exists (const char *filename)
58 {
59   struct stat statbuf;
60
61   return stat (filename, &statbuf) == 0;
62 }
63
64 GtkWidget *
65 shape_create_icon (GdkScreen *screen,
66                    char      *xpm_file,
67                    gint       x,
68                    gint       y,
69                    gint       px,
70                    gint       py,
71                    gint       window_type);
72
73 static GtkWidget *
74 build_option_menu (gchar           *items[],
75                    gint             num_items,
76                    gint             history,
77                    void           (*func) (GtkWidget *widget, gpointer data),
78                    gpointer         data);
79
80 /* macro, structure and variables used by tree window demos */
81 #define DEFAULT_NUMBER_OF_ITEM  3
82 #define DEFAULT_RECURSION_LEVEL 3
83
84 struct {
85   GSList* selection_mode_group;
86   GtkWidget* single_button;
87   GtkWidget* browse_button;
88   GtkWidget* multiple_button;
89   GtkWidget* draw_line_button;
90   GtkWidget* view_line_button;
91   GtkWidget* no_root_item_button;
92   GtkWidget* nb_item_spinner;
93   GtkWidget* recursion_spinner;
94 } sTreeSampleSelection;
95
96 typedef struct sTreeButtons {
97   guint nb_item_add;
98   GtkWidget* add_button;
99   GtkWidget* remove_button;
100   GtkWidget* subtree_button;
101 } sTreeButtons;
102 /* end of tree section */
103
104 static GtkWidget *
105 build_option_menu (gchar           *items[],
106                    gint             num_items,
107                    gint             history,
108                    void           (*func)(GtkWidget *widget, gpointer data),
109                    gpointer         data)
110 {
111   GtkWidget *omenu;
112   gint i;
113
114   omenu = gtk_combo_box_new_text ();
115   g_signal_connect (omenu, "changed",
116                     G_CALLBACK (func), data);
117       
118   for (i = 0; i < num_items; i++)
119       gtk_combo_box_append_text (GTK_COMBO_BOX (omenu), items[i]);
120
121   gtk_combo_box_set_active (GTK_COMBO_BOX (omenu), history);
122   
123   return omenu;
124 }
125
126 /*
127  * Windows with an alpha channel
128  */
129
130
131 static gboolean
132 on_alpha_window_expose (GtkWidget      *widget,
133                         GdkEventExpose *expose)
134 {
135   cairo_t *cr;
136   cairo_pattern_t *pattern;
137   int radius;
138
139   cr = gdk_cairo_create (widget->window);
140
141   radius = MIN (widget->allocation.width, widget->allocation.height) / 2;
142   pattern = cairo_pattern_create_radial (widget->allocation.width / 2,
143                                          widget->allocation.height / 2,
144                                          0.0,
145                                          widget->allocation.width / 2,
146                                          widget->allocation.height / 2,
147                                          radius * 1.33);
148
149   if (gdk_screen_get_rgba_colormap (gtk_widget_get_screen (widget)) &&
150       gtk_widget_is_composited (widget))
151     cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 0.0); /* transparent */
152   else
153     cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); /* opaque white */
154     
155   cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
156   cairo_paint (cr);
157   
158   cairo_pattern_add_color_stop_rgba (pattern, 0.0,
159                                      1.0, 0.75, 0.0, 1.0); /* solid orange */
160   cairo_pattern_add_color_stop_rgba (pattern, 1.0,
161                                      1.0, 0.75, 0.0, 0.0); /* transparent orange */
162
163   cairo_set_source (cr, pattern);
164   cairo_pattern_destroy (pattern);
165   
166   cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
167   cairo_paint (cr);
168
169   cairo_destroy (cr);
170
171   return FALSE;
172 }
173
174 static GtkWidget *
175 build_alpha_widgets (void)
176 {
177   GtkWidget *table;
178   GtkWidget *radio_button;
179   GtkWidget *hbox;
180   GtkWidget *label;
181   GtkWidget *entry;
182
183   table = gtk_table_new (1, 1, FALSE);
184
185   radio_button = gtk_radio_button_new_with_label (NULL, "Red");
186   gtk_table_attach (GTK_TABLE (table),
187                     radio_button,
188                     0, 1,                  0, 1,
189                     GTK_EXPAND | GTK_FILL, 0,
190                     0,                     0);
191
192   radio_button = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (radio_button), "Green");
193   gtk_table_attach (GTK_TABLE (table),
194                     radio_button,
195                     0, 1,                  1, 2,
196                     GTK_EXPAND | GTK_FILL, 0,
197                     0,                     0);
198
199   radio_button = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (radio_button), "Blue"),
200   gtk_table_attach (GTK_TABLE (table),
201                     radio_button,
202                     0, 1,                  2, 3,
203                     GTK_EXPAND | GTK_FILL, 0,
204                     0,                     0);
205
206   gtk_table_attach (GTK_TABLE (table),
207                     gtk_check_button_new_with_label ("Sedentary"),
208                     1, 2,                  0, 1,
209                     GTK_EXPAND | GTK_FILL, 0,
210                     0,                     0);
211   gtk_table_attach (GTK_TABLE (table),
212                     gtk_check_button_new_with_label ("Nocturnal"),
213                     1, 2,                  1, 2,
214                     GTK_EXPAND | GTK_FILL, 0,
215                     0,                     0);
216   gtk_table_attach (GTK_TABLE (table),
217                     gtk_check_button_new_with_label ("Compulsive"),
218                     1, 2,                  2, 3,
219                     GTK_EXPAND | GTK_FILL, 0,
220                     0,                     0);
221
222   radio_button = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (radio_button), "Green");
223   gtk_table_attach (GTK_TABLE (table),
224                     radio_button,
225                     0, 1,                  1, 2,
226                     GTK_EXPAND | GTK_FILL, 0,
227                     0,                     0);
228
229   radio_button = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (radio_button), "Blue"),
230   gtk_table_attach (GTK_TABLE (table),
231                     radio_button,
232                     0, 1,                  2, 3,
233                     GTK_EXPAND | GTK_FILL, 0,
234                     0,                     0);
235   
236   hbox = gtk_hbox_new (FALSE, 0);
237   label = gtk_label_new (NULL);
238   gtk_label_set_markup (GTK_LABEL (label), "<i>Entry: </i>");
239   gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
240   entry = gtk_entry_new ();
241   gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0);
242   gtk_table_attach (GTK_TABLE (table),
243                     hbox,
244                     0, 1,                  3, 4,
245                     GTK_EXPAND | GTK_FILL, 0,
246                     0,                     0);
247   
248   return table;
249 }
250
251 static gboolean
252 on_alpha_drawing_expose (GtkWidget      *widget,
253                          GdkEventExpose *expose)
254 {
255   int x = widget->allocation.x;
256   int y = widget->allocation.y;
257   int width = widget->allocation.width;
258   int height = widget->allocation.height;
259   GdkPixbuf *pixbuf;
260   guchar *buffer;
261   guchar *p;
262   int i, j;
263
264   buffer = g_malloc (64 * 64 * 4);
265   
266   gdk_draw_rectangle (widget->window, widget->style->black_gc, FALSE,
267                       x,         y,
268                       width - 1, height - 1);
269
270   p = buffer;
271   for (i = 0; i < 64; i++) {
272     for (j = 0; j < 64; j++) {
273       *(p++) = i * 4 + 3;
274       *(p++) = 0;
275       *(p++) = j + 4 + 3;
276       *(p++) = MIN (255, ((32 - i) * (32 - i) + (32 - j) * (32 - j)) / 8);
277     }
278   }
279   p++;
280
281   gdk_draw_rgb_32_image (widget->window, widget->style->black_gc,
282                          x + 18, y + (height - 64) /2,
283                          64, 64, GDK_RGB_DITHER_NORMAL, buffer, 64 * 4);
284
285   pixbuf = gdk_pixbuf_new_from_data (buffer, GDK_COLORSPACE_RGB, TRUE,
286                                      8, 64, 64, 4 * 64, NULL, NULL);
287
288   gdk_draw_pixbuf (widget->window, widget->style->black_gc, pixbuf,
289                    0, 0, x + width - 18 - 64, y + (height - 64) /2,
290                    64, 64, GDK_RGB_DITHER_NORMAL, 0, 0);
291
292   g_object_unref (pixbuf);
293
294   g_free (buffer);
295   
296   return FALSE;
297 }
298
299 static GtkWidget *
300 build_alpha_drawing ()
301 {
302   GtkWidget *hbox;
303
304   hbox = gtk_hbox_new (FALSE, 0);
305   gtk_widget_set_size_request (hbox, 100, 100);
306
307   g_signal_connect (hbox, "expose-event",
308                     G_CALLBACK (on_alpha_drawing_expose), NULL);
309
310   return hbox;
311 }
312
313 static void
314 on_alpha_screen_changed (GtkWidget *widget,
315                          GdkScreen *old_screen,
316                          GtkWidget *label)
317 {
318   GdkScreen *screen = gtk_widget_get_screen (widget);
319   GdkColormap *colormap = gdk_screen_get_rgba_colormap (screen);
320
321   if (!colormap)
322     {
323       colormap = gdk_screen_get_rgb_colormap (screen);
324       gtk_label_set_markup (GTK_LABEL (label), "<b>Screen doesn't support alpha</b>");
325     }
326   else
327     {
328       gtk_label_set_markup (GTK_LABEL (label), "<b>Screen supports alpha</b>");
329     }
330
331   gtk_widget_set_colormap (widget, colormap);
332 }
333
334 static void
335 on_composited_changed (GtkWidget *window,
336                       GtkLabel *label)
337 {
338   gboolean is_composited = gtk_widget_is_composited (window);
339
340   if (is_composited)
341     gtk_label_set_text (label, "Composited");
342   else
343     gtk_label_set_text (label, "Not composited");
344 }
345
346 void
347 create_alpha_window (GtkWidget *widget)
348 {
349   static GtkWidget *window;
350
351   if (!window)
352     {
353       GtkWidget *vbox;
354       GtkWidget *label;
355       
356       window = gtk_dialog_new_with_buttons ("Alpha Window",
357                                             GTK_WINDOW (gtk_widget_get_toplevel (widget)), 0,
358                                             GTK_STOCK_CLOSE, 0,
359                                             NULL);
360
361       gtk_widget_set_app_paintable (window, TRUE);
362       g_signal_connect (window, "expose-event",
363                         G_CALLBACK (on_alpha_window_expose), NULL);
364       
365       vbox = gtk_vbox_new (FALSE, 8);
366       gtk_container_set_border_width (GTK_CONTAINER (vbox), 12);
367       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), vbox,
368                           TRUE, TRUE, 0);
369
370       label = gtk_label_new (NULL);
371       gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
372       on_alpha_screen_changed (window, NULL, label);
373       g_signal_connect (window, "screen-changed",
374                         G_CALLBACK (on_alpha_screen_changed), label);
375       
376       label = gtk_label_new (NULL);
377       gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
378       on_composited_changed (window, GTK_LABEL (label));
379       g_signal_connect (window, "composited_changed", G_CALLBACK (on_composited_changed), label);
380       
381       gtk_box_pack_start (GTK_BOX (vbox), build_alpha_widgets (), TRUE, TRUE, 0);
382       gtk_box_pack_start (GTK_BOX (vbox), build_alpha_drawing (), TRUE, TRUE, 0);
383
384       g_signal_connect (window, "destroy",
385                         G_CALLBACK (gtk_widget_destroyed),
386                         &window);
387       
388       g_signal_connect (window, "response",
389                         G_CALLBACK (gtk_widget_destroy),
390                         NULL); 
391     }
392
393   if (!gtk_widget_get_visible (window))
394     gtk_widget_show_all (window);
395   else
396     gtk_widget_destroy (window);
397 }
398
399 /*
400  * Composited non-toplevel window
401  */
402
403 /* The expose event handler for the event box.
404  *
405  * This function simply draws a transparency onto a widget on the area
406  * for which it receives expose events.  This is intended to give the
407  * event box a "transparent" background.
408  *
409  * In order for this to work properly, the widget must have an RGBA
410  * colourmap.  The widget should also be set as app-paintable since it
411  * doesn't make sense for GTK to draw a background if we are drawing it
412  * (and because GTK might actually replace our transparency with its
413  * default background colour).
414  */
415 static gboolean
416 transparent_expose (GtkWidget *widget,
417                     GdkEventExpose *event)
418 {
419   cairo_t *cr;
420
421   cr = gdk_cairo_create (widget->window);
422   cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
423   gdk_cairo_region (cr, event->region);
424   cairo_fill (cr);
425   cairo_destroy (cr);
426
427   return FALSE;
428 }
429
430 /* The expose event handler for the window.
431  *
432  * This function performs the actual compositing of the event box onto
433  * the already-existing background of the window at 50% normal opacity.
434  *
435  * In this case we do not want app-paintable to be set on the widget
436  * since we want it to draw its own (red) background.  Because of this,
437  * however, we must ensure that we use g_signal_register_after so that
438  * this handler is called after the red has been drawn.  If it was
439  * called before then GTK would just blindly paint over our work.
440  */
441 static gboolean
442 window_expose_event (GtkWidget *widget,
443                      GdkEventExpose *event)
444 {
445   GdkRegion *region;
446   GtkWidget *child;
447   cairo_t *cr;
448
449   /* get our child (in this case, the event box) */ 
450   child = gtk_bin_get_child (GTK_BIN (widget));
451
452   /* create a cairo context to draw to the window */
453   cr = gdk_cairo_create (widget->window);
454
455   /* the source data is the (composited) event box */
456   gdk_cairo_set_source_pixmap (cr, child->window,
457                                child->allocation.x,
458                                child->allocation.y);
459
460   /* draw no more than our expose event intersects our child */
461   region = gdk_region_rectangle (&child->allocation);
462   gdk_region_intersect (region, event->region);
463   gdk_cairo_region (cr, region);
464   cairo_clip (cr);
465
466   /* composite, with a 50% opacity */
467   cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
468   cairo_paint_with_alpha (cr, 0.5);
469
470   /* we're done */
471   cairo_destroy (cr);
472
473   return FALSE;
474 }
475
476 void
477 create_composited_window (GtkWidget *widget)
478 {
479   static GtkWidget *window;
480
481   if (!window)
482     {
483       GtkWidget *event, *button;
484       GdkScreen *screen;
485       GdkColormap *rgba;
486       GdkColor red;
487
488       /* make the widgets */
489       button = gtk_button_new_with_label ("A Button");
490       event = gtk_event_box_new ();
491       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
492
493       g_signal_connect (window, "destroy",
494                         G_CALLBACK (gtk_widget_destroyed),
495                         &window);
496
497       /* put a red background on the window */
498       gdk_color_parse ("red", &red);
499       gtk_widget_modify_bg (window, GTK_STATE_NORMAL, &red);
500
501       /* set the colourmap for the event box.
502        * must be done before the event box is realised.
503        */
504       screen = gtk_widget_get_screen (event);
505       rgba = gdk_screen_get_rgba_colormap (screen);
506       gtk_widget_set_colormap (event, rgba);
507
508       /* set our event box to have a fully-transparent background
509        * drawn on it.  currently there is no way to simply tell gtk
510        * that "transparency" is the background colour for a widget.
511        */
512       gtk_widget_set_app_paintable (GTK_WIDGET (event), TRUE);
513       g_signal_connect (event, "expose-event",
514                         G_CALLBACK (transparent_expose), NULL);
515
516       /* put them inside one another */
517       gtk_container_set_border_width (GTK_CONTAINER (window), 10);
518       gtk_container_add (GTK_CONTAINER (window), event);
519       gtk_container_add (GTK_CONTAINER (event), button);
520
521       /* realise and show everything */
522       gtk_widget_realize (button);
523
524       /* set the event box GdkWindow to be composited.
525        * obviously must be performed after event box is realised.
526        */
527       gdk_window_set_composited (event->window, TRUE);
528
529       /* set up the compositing handler.
530        * note that we do _after so that the normal (red) background is drawn
531        * by gtk before our compositing occurs.
532        */
533       g_signal_connect_after (window, "expose-event",
534                               G_CALLBACK (window_expose_event), NULL);
535     }
536
537   if (!gtk_widget_get_visible (window))
538     gtk_widget_show_all (window);
539   else
540     gtk_widget_destroy (window);
541 }
542
543 /*
544  * Big windows and guffaw scrolling
545  */
546
547 static gboolean
548 pattern_expose (GtkWidget      *widget,
549                 GdkEventExpose *event,
550                 gpointer        data)
551 {
552   GdkColor *color;
553   GdkWindow *window = event->window;
554
555   color = g_object_get_data (G_OBJECT (window), "pattern-color");
556   if (color)
557     {
558       GdkGC *tmp_gc = gdk_gc_new (window);
559       gdk_gc_set_rgb_fg_color (tmp_gc, color);
560
561       gdk_draw_rectangle (window, tmp_gc, TRUE,
562                           event->area.x, event->area.y,
563                           event->area.width, event->area.height);
564
565       g_object_unref (tmp_gc);
566     }
567
568   return FALSE;
569 }
570
571 static void
572 pattern_set_bg (GtkWidget   *widget,
573                 GdkWindow   *child,
574                 gint         level)
575 {
576   static const GdkColor colors[] = {
577     { 0, 0x4444, 0x4444, 0xffff },
578     { 0, 0x8888, 0x8888, 0xffff },
579     { 0, 0xaaaa, 0xaaaa, 0xffff }
580   };
581     
582   g_object_set_data (G_OBJECT (child), "pattern-color", (gpointer) &colors[level]);
583   gdk_window_set_user_data (child, widget);
584 }
585
586 static void
587 create_pattern (GtkWidget   *widget,
588                 GdkWindow   *parent,
589                 gint         level,
590                 gint         width,
591                 gint         height)
592 {
593   gint h = 1;
594   gint i = 0;
595     
596   GdkWindow *child;
597
598   while (2 * h <= height)
599     {
600       gint w = 1;
601       gint j = 0;
602       
603       while (2 * w <= width)
604         {
605           if ((i + j) % 2 == 0)
606             {
607               gint x = w  - 1;
608               gint y = h - 1;
609               
610               GdkWindowAttr attributes;
611
612               attributes.window_type = GDK_WINDOW_CHILD;
613               attributes.x = x;
614               attributes.y = y;
615               attributes.width = w;
616               attributes.height = h;
617               attributes.wclass = GDK_INPUT_OUTPUT;
618               attributes.event_mask = GDK_EXPOSURE_MASK;
619               attributes.visual = gtk_widget_get_visual (widget);
620               attributes.colormap = gtk_widget_get_colormap (widget);
621               
622               child = gdk_window_new (parent, &attributes,
623                                       GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP);
624
625               pattern_set_bg (widget, child, level);
626
627               if (level < 2)
628                 create_pattern (widget, child, level + 1, w, h);
629
630               gdk_window_show (child);
631             }
632           j++;
633           w *= 2;
634         }
635       i++;
636       h *= 2;
637     }
638 }
639
640 #define PATTERN_SIZE (1 << 18)
641
642 static void
643 pattern_hadj_changed (GtkAdjustment *adj,
644                       GtkWidget     *darea)
645 {
646   gint *old_value = g_object_get_data (G_OBJECT (adj), "old-value");
647   gint new_value = adj->value;
648
649   if (gtk_widget_get_realized (darea))
650     {
651       gdk_window_scroll (darea->window, *old_value - new_value, 0);
652       *old_value = new_value;
653     }
654 }
655
656 static void
657 pattern_vadj_changed (GtkAdjustment *adj,
658                       GtkWidget *darea)
659 {
660   gint *old_value = g_object_get_data (G_OBJECT (adj), "old-value");
661   gint new_value = adj->value;
662
663   if (gtk_widget_get_realized (darea))
664     {
665       gdk_window_scroll (darea->window, 0, *old_value - new_value);
666       *old_value = new_value;
667     }
668 }
669
670 static void
671 pattern_realize (GtkWidget *widget,
672                  gpointer   data)
673 {
674   pattern_set_bg (widget, widget->window, 0);
675   create_pattern (widget, widget->window, 1, PATTERN_SIZE, PATTERN_SIZE);
676 }
677
678 static void 
679 create_big_windows (GtkWidget *widget)
680 {
681   static GtkWidget *window = NULL;
682   GtkWidget *darea, *table, *scrollbar;
683   GtkWidget *eventbox;
684   GtkAdjustment *hadj;
685   GtkAdjustment *vadj;
686   static gint current_x;
687   static gint current_y;
688  
689   if (!window)
690     {
691       current_x = 0;
692       current_y = 0;
693       
694       window = gtk_dialog_new_with_buttons ("Big Windows",
695                                             NULL, 0,
696                                             GTK_STOCK_CLOSE,
697                                             GTK_RESPONSE_NONE,
698                                             NULL);
699  
700       gtk_window_set_screen (GTK_WINDOW (window),
701                              gtk_widget_get_screen (widget));
702
703       gtk_window_set_default_size (GTK_WINDOW (window), 200, 300);
704
705       g_signal_connect (window, "destroy",
706                         G_CALLBACK (gtk_widget_destroyed),
707                         &window);
708
709       g_signal_connect (window, "response",
710                         G_CALLBACK (gtk_widget_destroy),
711                         NULL);
712
713       table = gtk_table_new (2, 2, FALSE);
714       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox),
715                           table, TRUE, TRUE, 0);
716
717       darea = gtk_drawing_area_new ();
718
719       hadj = (GtkAdjustment *)gtk_adjustment_new (0, 0, PATTERN_SIZE, 10, 100, 100);
720       g_signal_connect (hadj, "value_changed",
721                         G_CALLBACK (pattern_hadj_changed), darea);
722       g_object_set_data (G_OBJECT (hadj), "old-value", &current_x);
723       
724       vadj = (GtkAdjustment *)gtk_adjustment_new (0, 0, PATTERN_SIZE, 10, 100, 100);
725       g_signal_connect (vadj, "value_changed",
726                         G_CALLBACK (pattern_vadj_changed), darea);
727       g_object_set_data (G_OBJECT (vadj), "old-value", &current_y);
728       
729       g_signal_connect (darea, "realize",
730                         G_CALLBACK (pattern_realize),
731                         NULL);
732       g_signal_connect (darea, "expose_event",
733                         G_CALLBACK (pattern_expose),
734                         NULL);
735
736       eventbox = gtk_event_box_new ();
737       gtk_table_attach (GTK_TABLE (table), eventbox,
738                         0, 1,                  0, 1,
739                         GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND,
740                         0,                     0);
741
742       gtk_container_add (GTK_CONTAINER (eventbox), darea);
743
744       scrollbar = gtk_hscrollbar_new (hadj);
745       gtk_table_attach (GTK_TABLE (table), scrollbar,
746                         0, 1,                  1, 2,
747                         GTK_FILL | GTK_EXPAND, GTK_FILL,
748                         0,                     0);
749
750       scrollbar = gtk_vscrollbar_new (vadj);
751       gtk_table_attach (GTK_TABLE (table), scrollbar,
752                         1, 2,                  0, 1,
753                         GTK_FILL,              GTK_EXPAND | GTK_FILL,
754                         0,                     0);
755
756     }
757
758   if (!gtk_widget_get_visible (window))
759     gtk_widget_show_all (window);
760   else
761     gtk_widget_hide (window);
762 }
763
764 /*
765  * GtkButton
766  */
767
768 static void
769 button_window (GtkWidget *widget,
770                GtkWidget *button)
771 {
772   if (!gtk_widget_get_visible (button))
773     gtk_widget_show (button);
774   else
775     gtk_widget_hide (button);
776 }
777
778 static void
779 create_buttons (GtkWidget *widget)
780 {
781   static GtkWidget *window = NULL;
782   GtkWidget *box1;
783   GtkWidget *box2;
784   GtkWidget *table;
785   GtkWidget *button[10];
786   GtkWidget *separator;
787
788   if (!window)
789     {
790       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
791       gtk_window_set_screen (GTK_WINDOW (window),
792                              gtk_widget_get_screen (widget));
793
794       g_signal_connect (window, "destroy",
795                         G_CALLBACK (gtk_widget_destroyed),
796                         &window);
797
798       gtk_window_set_title (GTK_WINDOW (window), "GtkButton");
799       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
800
801       box1 = gtk_vbox_new (FALSE, 0);
802       gtk_container_add (GTK_CONTAINER (window), box1);
803
804       table = gtk_table_new (3, 3, FALSE);
805       gtk_table_set_row_spacings (GTK_TABLE (table), 5);
806       gtk_table_set_col_spacings (GTK_TABLE (table), 5);
807       gtk_container_set_border_width (GTK_CONTAINER (table), 10);
808       gtk_box_pack_start (GTK_BOX (box1), table, TRUE, TRUE, 0);
809
810       button[0] = gtk_button_new_with_label ("button1");
811       button[1] = gtk_button_new_with_mnemonic ("_button2");
812       button[2] = gtk_button_new_with_mnemonic ("_button3");
813       button[3] = gtk_button_new_from_stock (GTK_STOCK_OK);
814       button[4] = gtk_button_new_with_label ("button5");
815       button[5] = gtk_button_new_with_label ("button6");
816       button[6] = gtk_button_new_with_label ("button7");
817       button[7] = gtk_button_new_from_stock (GTK_STOCK_CLOSE);
818       button[8] = gtk_button_new_with_label ("button9");
819       
820       g_signal_connect (button[0], "clicked",
821                         G_CALLBACK (button_window),
822                         button[1]);
823
824       gtk_table_attach (GTK_TABLE (table), button[0], 0, 1, 0, 1,
825                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
826
827       g_signal_connect (button[1], "clicked",
828                         G_CALLBACK (button_window),
829                         button[2]);
830
831       gtk_table_attach (GTK_TABLE (table), button[1], 1, 2, 1, 2,
832                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
833
834       g_signal_connect (button[2], "clicked",
835                         G_CALLBACK (button_window),
836                         button[3]);
837       gtk_table_attach (GTK_TABLE (table), button[2], 2, 3, 2, 3,
838                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
839
840       g_signal_connect (button[3], "clicked",
841                         G_CALLBACK (button_window),
842                         button[4]);
843       gtk_table_attach (GTK_TABLE (table), button[3], 0, 1, 2, 3,
844                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
845
846       g_signal_connect (button[4], "clicked",
847                         G_CALLBACK (button_window),
848                         button[5]);
849       gtk_table_attach (GTK_TABLE (table), button[4], 2, 3, 0, 1,
850                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
851
852       g_signal_connect (button[5], "clicked",
853                         G_CALLBACK (button_window),
854                         button[6]);
855       gtk_table_attach (GTK_TABLE (table), button[5], 1, 2, 2, 3,
856                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
857
858       g_signal_connect (button[6], "clicked",
859                         G_CALLBACK (button_window),
860                         button[7]);
861       gtk_table_attach (GTK_TABLE (table), button[6], 1, 2, 0, 1,
862                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
863
864       g_signal_connect (button[7], "clicked",
865                         G_CALLBACK (button_window),
866                         button[8]);
867       gtk_table_attach (GTK_TABLE (table), button[7], 2, 3, 1, 2,
868                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
869
870       g_signal_connect (button[8], "clicked",
871                         G_CALLBACK (button_window),
872                         button[0]);
873       gtk_table_attach (GTK_TABLE (table), button[8], 0, 1, 1, 2,
874                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
875
876       separator = gtk_hseparator_new ();
877       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
878
879       box2 = gtk_vbox_new (FALSE, 10);
880       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
881       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
882
883       button[9] = gtk_button_new_with_label ("close");
884       g_signal_connect_swapped (button[9], "clicked",
885                                 G_CALLBACK (gtk_widget_destroy),
886                                 window);
887       gtk_box_pack_start (GTK_BOX (box2), button[9], TRUE, TRUE, 0);
888       gtk_widget_set_can_default (button[9], TRUE);
889       gtk_widget_grab_default (button[9]);
890     }
891
892   if (!gtk_widget_get_visible (window))
893     gtk_widget_show_all (window);
894   else
895     gtk_widget_destroy (window);
896 }
897
898 /*
899  * GtkToggleButton
900  */
901
902 static void
903 create_toggle_buttons (GtkWidget *widget)
904 {
905   static GtkWidget *window = NULL;
906   GtkWidget *box1;
907   GtkWidget *box2;
908   GtkWidget *button;
909   GtkWidget *separator;
910
911   if (!window)
912     {
913       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
914       gtk_window_set_screen (GTK_WINDOW (window),
915                              gtk_widget_get_screen (widget));
916
917       g_signal_connect (window, "destroy",
918                         G_CALLBACK (gtk_widget_destroyed),
919                         &window);
920
921       gtk_window_set_title (GTK_WINDOW (window), "GtkToggleButton");
922       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
923
924       box1 = gtk_vbox_new (FALSE, 0);
925       gtk_container_add (GTK_CONTAINER (window), box1);
926
927       box2 = gtk_vbox_new (FALSE, 10);
928       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
929       gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
930
931       button = gtk_toggle_button_new_with_label ("button1");
932       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
933
934       button = gtk_toggle_button_new_with_label ("button2");
935       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
936
937       button = gtk_toggle_button_new_with_label ("button3");
938       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
939
940       button = gtk_toggle_button_new_with_label ("inconsistent");
941       gtk_toggle_button_set_inconsistent (GTK_TOGGLE_BUTTON (button), TRUE);
942       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
943       
944       separator = gtk_hseparator_new ();
945       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
946
947       box2 = gtk_vbox_new (FALSE, 10);
948       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
949       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
950
951       button = gtk_button_new_with_label ("close");
952       g_signal_connect_swapped (button, "clicked",
953                                 G_CALLBACK (gtk_widget_destroy),
954                                 window);
955       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
956       gtk_widget_set_can_default (button, TRUE);
957       gtk_widget_grab_default (button);
958     }
959
960   if (!gtk_widget_get_visible (window))
961     gtk_widget_show_all (window);
962   else
963     gtk_widget_destroy (window);
964 }
965
966 static GtkWidget *
967 create_widget_grid (GType widget_type)
968 {
969   GtkWidget *table;
970   GtkWidget *group_widget = NULL;
971   gint i, j;
972   
973   table = gtk_table_new (FALSE, 3, 3);
974   
975   for (i = 0; i < 5; i++)
976     {
977       for (j = 0; j < 5; j++)
978         {
979           GtkWidget *widget;
980           char *tmp;
981           
982           if (i == 0 && j == 0)
983             {
984               widget = NULL;
985             }
986           else if (i == 0)
987             {
988               tmp = g_strdup_printf ("%d", j);
989               widget = gtk_label_new (tmp);
990               g_free (tmp);
991             }
992           else if (j == 0)
993             {
994               tmp = g_strdup_printf ("%c", 'A' + i - 1);
995               widget = gtk_label_new (tmp);
996               g_free (tmp);
997             }
998           else
999             {
1000               widget = g_object_new (widget_type, NULL);
1001               
1002               if (g_type_is_a (widget_type, GTK_TYPE_RADIO_BUTTON))
1003                 {
1004                   if (!group_widget)
1005                     group_widget = widget;
1006                   else
1007                     g_object_set (widget, "group", group_widget, NULL);
1008                 }
1009             }
1010           
1011           if (widget)
1012             gtk_table_attach (GTK_TABLE (table), widget,
1013                               i, i + 1, j, j + 1,
1014                               0,        0,
1015                               0,        0);
1016         }
1017     }
1018
1019   return table;
1020 }
1021
1022 /*
1023  * GtkCheckButton
1024  */
1025
1026 static void
1027 create_check_buttons (GtkWidget *widget)
1028 {
1029   static GtkWidget *window = NULL;
1030   GtkWidget *box1;
1031   GtkWidget *box2;
1032   GtkWidget *button;
1033   GtkWidget *separator;
1034   GtkWidget *table;
1035   
1036   if (!window)
1037     {
1038       window = gtk_dialog_new_with_buttons ("Check Buttons",
1039                                             NULL, 0,
1040                                             GTK_STOCK_CLOSE,
1041                                             GTK_RESPONSE_NONE,
1042                                             NULL);
1043
1044       gtk_window_set_screen (GTK_WINDOW (window), 
1045                              gtk_widget_get_screen (widget));
1046
1047       g_signal_connect (window, "destroy",
1048                         G_CALLBACK (gtk_widget_destroyed),
1049                         &window);
1050       g_signal_connect (window, "response",
1051                         G_CALLBACK (gtk_widget_destroy),
1052                         NULL);
1053
1054       box1 = GTK_DIALOG (window)->vbox;
1055       
1056       box2 = gtk_vbox_new (FALSE, 10);
1057       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
1058       gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
1059
1060       button = gtk_check_button_new_with_mnemonic ("_button1");
1061       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
1062
1063       button = gtk_check_button_new_with_label ("button2");
1064       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
1065
1066       button = gtk_check_button_new_with_label ("button3");
1067       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
1068
1069       button = gtk_check_button_new_with_label ("inconsistent");
1070       gtk_toggle_button_set_inconsistent (GTK_TOGGLE_BUTTON (button), TRUE);
1071       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
1072
1073       separator = gtk_hseparator_new ();
1074       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
1075
1076       table = create_widget_grid (GTK_TYPE_CHECK_BUTTON);
1077       gtk_container_set_border_width (GTK_CONTAINER (table), 10);
1078       gtk_box_pack_start (GTK_BOX (box1), table, TRUE, TRUE, 0);
1079     }
1080
1081   if (!gtk_widget_get_visible (window))
1082     gtk_widget_show_all (window);
1083   else
1084     gtk_widget_destroy (window);
1085 }
1086
1087 /*
1088  * GtkRadioButton
1089  */
1090
1091 static void
1092 create_radio_buttons (GtkWidget *widget)
1093 {
1094   static GtkWidget *window = NULL;
1095   GtkWidget *box1;
1096   GtkWidget *box2;
1097   GtkWidget *button;
1098   GtkWidget *separator;
1099   GtkWidget *table;
1100
1101   if (!window)
1102     {
1103       window = gtk_dialog_new_with_buttons ("Radio Buttons",
1104                                             NULL, 0,
1105                                             GTK_STOCK_CLOSE,
1106                                             GTK_RESPONSE_NONE,
1107                                             NULL);
1108
1109       gtk_window_set_screen (GTK_WINDOW (window),
1110                              gtk_widget_get_screen (widget));
1111
1112       g_signal_connect (window, "destroy",
1113                         G_CALLBACK (gtk_widget_destroyed),
1114                         &window);
1115       g_signal_connect (window, "response",
1116                         G_CALLBACK (gtk_widget_destroy),
1117                         NULL);
1118
1119       box1 = GTK_DIALOG (window)->vbox;
1120
1121       box2 = gtk_vbox_new (FALSE, 10);
1122       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
1123       gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
1124
1125       button = gtk_radio_button_new_with_label (NULL, "button1");
1126       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
1127
1128       button = gtk_radio_button_new_with_label (
1129                  gtk_radio_button_get_group (GTK_RADIO_BUTTON (button)),
1130                  "button2");
1131       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
1132       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
1133
1134       button = gtk_radio_button_new_with_label (
1135                  gtk_radio_button_get_group (GTK_RADIO_BUTTON (button)),
1136                  "button3");
1137       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
1138
1139       button = gtk_radio_button_new_with_label (
1140                  gtk_radio_button_get_group (GTK_RADIO_BUTTON (button)),
1141                  "inconsistent");
1142       gtk_toggle_button_set_inconsistent (GTK_TOGGLE_BUTTON (button), TRUE);
1143       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
1144       
1145       separator = gtk_hseparator_new ();
1146       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
1147
1148       box2 = gtk_vbox_new (FALSE, 10);
1149       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
1150       gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
1151
1152       button = gtk_radio_button_new_with_label (NULL, "button4");
1153       gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (button), FALSE);
1154       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
1155
1156       button = gtk_radio_button_new_with_label (
1157                  gtk_radio_button_get_group (GTK_RADIO_BUTTON (button)),
1158                  "button5");
1159       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
1160       gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (button), FALSE);
1161       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
1162
1163       button = gtk_radio_button_new_with_label (
1164                  gtk_radio_button_get_group (GTK_RADIO_BUTTON (button)),
1165                  "button6");
1166       gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (button), FALSE);
1167       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
1168
1169       separator = gtk_hseparator_new ();
1170       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
1171
1172       table = create_widget_grid (GTK_TYPE_RADIO_BUTTON);
1173       gtk_container_set_border_width (GTK_CONTAINER (table), 10);
1174       gtk_box_pack_start (GTK_BOX (box1), table, TRUE, TRUE, 0);
1175     }
1176
1177   if (!gtk_widget_get_visible (window))
1178     gtk_widget_show_all (window);
1179   else
1180     gtk_widget_destroy (window);
1181 }
1182
1183 /*
1184  * GtkButtonBox
1185  */
1186
1187 static GtkWidget *
1188 create_bbox (gint  horizontal,
1189              char* title, 
1190              gint  spacing,
1191              gint  child_w,
1192              gint  child_h,
1193              gint  layout)
1194 {
1195   GtkWidget *frame;
1196   GtkWidget *bbox;
1197   GtkWidget *button;
1198         
1199   frame = gtk_frame_new (title);
1200
1201   if (horizontal)
1202     bbox = gtk_hbutton_box_new ();
1203   else
1204     bbox = gtk_vbutton_box_new ();
1205
1206   gtk_container_set_border_width (GTK_CONTAINER (bbox), 5);
1207   gtk_container_add (GTK_CONTAINER (frame), bbox);
1208
1209   gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), layout);
1210   gtk_box_set_spacing (GTK_BOX (bbox), spacing);
1211   
1212   button = gtk_button_new_with_label ("OK");
1213   gtk_container_add (GTK_CONTAINER (bbox), button);
1214   
1215   button = gtk_button_new_with_label ("Cancel");
1216   gtk_container_add (GTK_CONTAINER (bbox), button);
1217   
1218   button = gtk_button_new_with_label ("Help");
1219   gtk_container_add (GTK_CONTAINER (bbox), button);
1220
1221   return frame;
1222 }
1223
1224 static void
1225 create_button_box (GtkWidget *widget)
1226 {
1227   static GtkWidget* window = NULL;
1228   GtkWidget *main_vbox;
1229   GtkWidget *vbox;
1230   GtkWidget *hbox;
1231   GtkWidget *frame_horz;
1232   GtkWidget *frame_vert;
1233
1234   if (!window)
1235   {
1236     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1237     gtk_window_set_screen (GTK_WINDOW (window), gtk_widget_get_screen (widget));
1238     gtk_window_set_title (GTK_WINDOW (window), "Button Boxes");
1239     
1240     g_signal_connect (window, "destroy",
1241                       G_CALLBACK (gtk_widget_destroyed),
1242                       &window);
1243
1244     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
1245
1246     main_vbox = gtk_vbox_new (FALSE, 0);
1247     gtk_container_add (GTK_CONTAINER (window), main_vbox);
1248     
1249     frame_horz = gtk_frame_new ("Horizontal Button Boxes");
1250     gtk_box_pack_start (GTK_BOX (main_vbox), frame_horz, TRUE, TRUE, 10);
1251     
1252     vbox = gtk_vbox_new (FALSE, 0);
1253     gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
1254     gtk_container_add (GTK_CONTAINER (frame_horz), vbox);
1255     
1256     gtk_box_pack_start (GTK_BOX (vbox), 
1257                         create_bbox (TRUE, "Spread", 40, 85, 20, GTK_BUTTONBOX_SPREAD),
1258                         TRUE, TRUE, 0);
1259     
1260     gtk_box_pack_start (GTK_BOX (vbox), 
1261                         create_bbox (TRUE, "Edge", 40, 85, 20, GTK_BUTTONBOX_EDGE),
1262                         TRUE, TRUE, 5);
1263     
1264     gtk_box_pack_start (GTK_BOX (vbox), 
1265                         create_bbox (TRUE, "Start", 40, 85, 20, GTK_BUTTONBOX_START),
1266                         TRUE, TRUE, 5);
1267     
1268     gtk_box_pack_start (GTK_BOX (vbox), 
1269                         create_bbox (TRUE, "End", 40, 85, 20, GTK_BUTTONBOX_END),
1270                         TRUE, TRUE, 5);
1271     
1272     gtk_box_pack_start (GTK_BOX (vbox),
1273                         create_bbox (TRUE, "Center", 40, 85, 20, GTK_BUTTONBOX_CENTER),
1274                         TRUE, TRUE, 5);
1275     
1276     frame_vert = gtk_frame_new ("Vertical Button Boxes");
1277     gtk_box_pack_start (GTK_BOX (main_vbox), frame_vert, TRUE, TRUE, 10);
1278     
1279     hbox = gtk_hbox_new (FALSE, 0);
1280     gtk_container_set_border_width (GTK_CONTAINER (hbox), 10);
1281     gtk_container_add (GTK_CONTAINER (frame_vert), hbox);
1282
1283     gtk_box_pack_start (GTK_BOX (hbox), 
1284                         create_bbox (FALSE, "Spread", 30, 85, 20, GTK_BUTTONBOX_SPREAD),
1285                         TRUE, TRUE, 0);
1286     
1287     gtk_box_pack_start (GTK_BOX (hbox), 
1288                         create_bbox (FALSE, "Edge", 30, 85, 20, GTK_BUTTONBOX_EDGE),
1289                         TRUE, TRUE, 5);
1290     
1291     gtk_box_pack_start (GTK_BOX (hbox), 
1292                         create_bbox (FALSE, "Start", 30, 85, 20, GTK_BUTTONBOX_START),
1293                         TRUE, TRUE, 5);
1294     
1295     gtk_box_pack_start (GTK_BOX (hbox), 
1296                         create_bbox (FALSE, "End", 30, 85, 20, GTK_BUTTONBOX_END),
1297                         TRUE, TRUE, 5);
1298     
1299     gtk_box_pack_start (GTK_BOX (hbox),
1300                         create_bbox (FALSE, "Center", 30, 85, 20, GTK_BUTTONBOX_CENTER),
1301                         TRUE, TRUE, 5);
1302   }
1303
1304   if (!gtk_widget_get_visible (window))
1305     gtk_widget_show_all (window);
1306   else
1307     gtk_widget_destroy (window);
1308 }
1309
1310 /*
1311  * GtkToolBar
1312  */
1313
1314 static GtkWidget*
1315 new_pixmap (char      *filename,
1316             GdkWindow *window,
1317             GdkColor  *background)
1318 {
1319   GtkWidget *wpixmap;
1320   GdkPixmap *pixmap;
1321   GdkBitmap *mask;
1322
1323   if (strcmp (filename, "test.xpm") == 0 ||
1324       !file_exists (filename))
1325     {
1326       pixmap = gdk_pixmap_create_from_xpm_d (window, &mask,
1327                                              background,
1328                                              openfile);
1329     }
1330   else
1331     pixmap = gdk_pixmap_create_from_xpm (window, &mask,
1332                                          background,
1333                                          filename);
1334   
1335   wpixmap = gtk_image_new_from_pixmap (pixmap, mask);
1336
1337   return wpixmap;
1338 }
1339
1340
1341 static void
1342 set_toolbar_small_stock (GtkWidget *widget,
1343                          gpointer   data)
1344 {
1345   gtk_toolbar_set_icon_size (GTK_TOOLBAR (data), GTK_ICON_SIZE_SMALL_TOOLBAR);
1346 }
1347
1348 static void
1349 set_toolbar_large_stock (GtkWidget *widget,
1350                          gpointer   data)
1351 {
1352   gtk_toolbar_set_icon_size (GTK_TOOLBAR (data), GTK_ICON_SIZE_LARGE_TOOLBAR);
1353 }
1354
1355 static void
1356 set_toolbar_horizontal (GtkWidget *widget,
1357                         gpointer   data)
1358 {
1359   gtk_orientable_set_orientation (GTK_ORIENTABLE (data), GTK_ORIENTATION_HORIZONTAL);
1360 }
1361
1362 static void
1363 set_toolbar_vertical (GtkWidget *widget,
1364                       gpointer   data)
1365 {
1366   gtk_orientable_set_orientation (GTK_ORIENTABLE (data), GTK_ORIENTATION_VERTICAL);
1367 }
1368
1369 static void
1370 set_toolbar_icons (GtkWidget *widget,
1371                    gpointer   data)
1372 {
1373   gtk_toolbar_set_style (GTK_TOOLBAR (data), GTK_TOOLBAR_ICONS);
1374 }
1375
1376 static void
1377 set_toolbar_text (GtkWidget *widget,
1378                   gpointer   data)
1379 {
1380   gtk_toolbar_set_style (GTK_TOOLBAR (data), GTK_TOOLBAR_TEXT);
1381 }
1382
1383 static void
1384 set_toolbar_both (GtkWidget *widget,
1385                   gpointer   data)
1386 {
1387   gtk_toolbar_set_style (GTK_TOOLBAR (data), GTK_TOOLBAR_BOTH);
1388 }
1389
1390 static void
1391 set_toolbar_both_horiz (GtkWidget *widget,
1392                         gpointer   data)
1393 {
1394   gtk_toolbar_set_style (GTK_TOOLBAR (data), GTK_TOOLBAR_BOTH_HORIZ);
1395 }
1396
1397 static void
1398 set_toolbar_enable (GtkWidget *widget,
1399                     gpointer   data)
1400 {
1401   GtkSettings *settings = gtk_widget_get_settings (widget);
1402   g_object_set (settings, "gtk-enable-tooltips", TRUE, NULL);
1403 }
1404
1405 static void
1406 set_toolbar_disable (GtkWidget *widget,
1407                      gpointer   data)
1408 {
1409   GtkSettings *settings = gtk_widget_get_settings (widget);
1410   g_object_set (settings, "gtk-enable-tooltips", FALSE, NULL);
1411 }
1412
1413 static GtkActionEntry create_toolbar_items[] = {
1414     { NULL, GTK_STOCK_NEW, NULL, NULL, "Stock icon: New",
1415       G_CALLBACK (set_toolbar_small_stock) },
1416     { NULL, GTK_STOCK_OPEN, NULL, NULL, "Stock icon: Open",
1417       G_CALLBACK (set_toolbar_large_stock) },
1418     { NULL, NULL, "Horizontal", NULL, "Horizontal toolbar layout",
1419       G_CALLBACK (set_toolbar_horizontal) },
1420     { NULL, NULL, "Vertical", NULL, "Vertical toolbar layout",
1421       G_CALLBACK (set_toolbar_vertical) },
1422     { NULL },
1423     { NULL, NULL, "Icons", NULL, "Only show toolbar icons",
1424       G_CALLBACK (set_toolbar_icons) },
1425     { NULL, NULL, "Text", NULL, "Only show toolbar text",
1426       G_CALLBACK (set_toolbar_text) },
1427     { NULL, NULL, "Both", NULL, "Show toolbar icons and text",
1428       G_CALLBACK (set_toolbar_both) },
1429     { NULL, NULL, "Both (horizontal)", NULL, "Show toolbar icons and text in a horizontal fashion",
1430       G_CALLBACK (set_toolbar_both_horiz) },
1431     { NULL },
1432     { "entry", NULL, NULL, "This is an unusable GtkEntry ;)",
1433       NULL },
1434     { NULL },
1435     { NULL },
1436     { NULL, NULL, "Enable", NULL, "Enable tooltips",
1437       G_CALLBACK (set_toolbar_enable) },
1438     { NULL, NULL, "Disable", NULL, "Disable tooltips",
1439       G_CALLBACK (set_toolbar_disable) },
1440     { NULL },
1441     { NULL, NULL, "Frobate", NULL, "Frobate tooltip",
1442       NULL },
1443     { NULL, NULL, "Baz", NULL, "Baz tooltip",
1444       NULL },
1445     { NULL },
1446     { NULL, NULL, "Blah", NULL, "Blash tooltip",
1447       NULL },
1448     { NULL, NULL, "Bar", NULL, "Bar tooltip",
1449       NULL },
1450 };
1451
1452 static void
1453 create_toolbar (GtkWidget *widget)
1454 {
1455   static GtkWidget *window = NULL;
1456   GtkWidget *toolbar;
1457
1458   if (!window)
1459     {
1460       guint i;
1461
1462       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1463       gtk_window_set_screen (GTK_WINDOW (window),
1464                              gtk_widget_get_screen (widget));
1465       
1466       gtk_window_set_title (GTK_WINDOW (window), "Toolbar test");
1467
1468       g_signal_connect (window, "destroy",
1469                         G_CALLBACK (gtk_widget_destroyed),
1470                         &window);
1471
1472       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
1473       gtk_widget_realize (window);
1474
1475       toolbar = gtk_toolbar_new ();
1476       for (i = 0; i < G_N_ELEMENTS (create_toolbar_items); i++)
1477         {
1478           GtkToolItem *toolitem;
1479
1480           if (create_toolbar_items[i].tooltip == NULL)
1481             toolitem = gtk_separator_tool_item_new ();
1482           else if (g_strcmp0 (create_toolbar_items[i].name, "entry") == 0)
1483             {
1484               GtkWidget *entry;
1485
1486               toolitem = gtk_tool_item_new ();
1487               entry = gtk_entry_new ();
1488               gtk_container_add (GTK_CONTAINER (toolitem), entry);
1489             }
1490           else if (create_toolbar_items[i].stock_id)
1491             toolitem = gtk_tool_button_new_from_stock (create_toolbar_items[i].stock_id);
1492           else
1493             {
1494               GtkWidget *icon;
1495
1496               icon = new_pixmap ("test.xpm", window->window,
1497                                  &window->style->bg[GTK_STATE_NORMAL]);
1498               toolitem = gtk_tool_button_new (icon, create_toolbar_items[i].label);
1499             }
1500           if (create_toolbar_items[i].callback)
1501             g_signal_connect (toolitem, "clicked",
1502                               create_toolbar_items[i].callback, toolbar);
1503           gtk_tool_item_set_tooltip_text (toolitem, create_toolbar_items[i].tooltip);
1504           gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, -1);
1505         }
1506
1507       gtk_container_add (GTK_CONTAINER (window), toolbar);
1508
1509       gtk_widget_set_size_request (toolbar, 200, -1);
1510     }
1511
1512   if (!gtk_widget_get_visible (window))
1513     gtk_widget_show_all (window);
1514   else
1515     gtk_widget_destroy (window);
1516 }
1517
1518 static GtkActionEntry make_toolbar_items[] = {
1519     { NULL, NULL, "Horizontal", NULL, "Horizontal toolbar layout",
1520       G_CALLBACK (set_toolbar_horizontal) },
1521     { NULL, NULL, "Vertical", NULL, "Vertical toolbar layout",
1522       G_CALLBACK (set_toolbar_vertical) },
1523     { NULL },
1524     { NULL, NULL, "Icons", NULL, "Only show toolbar icons",
1525       G_CALLBACK (set_toolbar_icons) },
1526     { NULL, NULL, "Text", NULL, "Only show toolbar text",
1527       G_CALLBACK (set_toolbar_text) },
1528     { NULL, NULL, "Both", NULL, "Show toolbar icons and text",
1529       G_CALLBACK (set_toolbar_both) },
1530     { NULL },
1531     { NULL, NULL, "Woot", NULL, "Woot woot woot",
1532       NULL },
1533     { NULL, NULL, "Blah", NULL, "Blah blah blah",
1534       NULL },
1535     { NULL },
1536     { NULL, NULL, "Enable", NULL, "Enable tooltips",
1537       G_CALLBACK (set_toolbar_enable) },
1538     { NULL, NULL, "Disable", NULL, "Disable tooltips",
1539       G_CALLBACK (set_toolbar_disable) },
1540     { NULL },
1541     { NULL, NULL, "Hoo", NULL, "Hoo tooltip",
1542       NULL },
1543     { NULL, NULL, "Woo", NULL, "Woo tooltip",
1544       NULL }
1545 };
1546
1547 static GtkWidget*
1548 make_toolbar (GtkWidget *window)
1549 {
1550   GtkWidget *toolbar;
1551   guint i;
1552
1553   if (!gtk_widget_get_realized (window))
1554     gtk_widget_realize (window);
1555
1556   toolbar = gtk_toolbar_new ();
1557   for (i = 0; i < G_N_ELEMENTS (make_toolbar_items); i++)
1558     {
1559       GtkWidget *icon;
1560       GtkToolItem *toolitem;
1561
1562       if (make_toolbar_items[i].label == NULL)
1563         {
1564           toolitem = gtk_separator_tool_item_new ();
1565           continue;
1566         }
1567       icon  = new_pixmap ("test.xpm", window->window,
1568                           &window->style->bg[GTK_STATE_NORMAL]);
1569       toolitem = gtk_tool_button_new (icon, make_toolbar_items[i].label);
1570       gtk_tool_item_set_tooltip_text (toolitem, make_toolbar_items[i].tooltip);
1571       if (make_toolbar_items[i].callback != NULL)
1572         g_signal_connect (toolitem, "clicked",  make_toolbar_items[i].callback, toolbar);
1573       gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, -1);
1574     }
1575
1576   return toolbar;
1577 }
1578
1579 /*
1580  * GtkStatusBar
1581  */
1582
1583 static guint statusbar_counter = 1;
1584
1585 static void
1586 statusbar_push (GtkWidget *button,
1587                 GtkStatusbar *statusbar)
1588 {
1589   gchar text[1024];
1590
1591   sprintf (text, "something %d", statusbar_counter++);
1592
1593   gtk_statusbar_push (statusbar, 1, text);
1594 }
1595
1596 static void
1597 statusbar_push_long (GtkWidget *button,
1598                      GtkStatusbar *statusbar)
1599 {
1600   gchar text[1024];
1601
1602   sprintf (text, "Just because a system has menu choices written with English words, phrases or sentences, that is no guarantee, that it is comprehensible. Individual words may not be familiar to some users (for example, \"repaginate\"), and two menu items may appear to satisfy the users's needs, whereas only one does (for example, \"put away\" or \"eject\").");
1603
1604   gtk_statusbar_push (statusbar, 1, text);
1605 }
1606
1607 static void
1608 statusbar_pop (GtkWidget *button,
1609                GtkStatusbar *statusbar)
1610 {
1611   gtk_statusbar_pop (statusbar, 1);
1612 }
1613
1614 static void
1615 statusbar_steal (GtkWidget *button,
1616                  GtkStatusbar *statusbar)
1617 {
1618   gtk_statusbar_remove (statusbar, 1, 4);
1619 }
1620
1621 static void
1622 statusbar_popped (GtkStatusbar  *statusbar,
1623                   guint          context_id,
1624                   const gchar   *text)
1625 {
1626   if (!statusbar->messages)
1627     statusbar_counter = 1;
1628 }
1629
1630 static void
1631 statusbar_contexts (GtkStatusbar *statusbar)
1632 {
1633   gchar *string;
1634
1635   string = "any context";
1636   g_print ("GtkStatusBar: context=\"%s\", context_id=%d\n",
1637            string,
1638            gtk_statusbar_get_context_id (statusbar, string));
1639   
1640   string = "idle messages";
1641   g_print ("GtkStatusBar: context=\"%s\", context_id=%d\n",
1642            string,
1643            gtk_statusbar_get_context_id (statusbar, string));
1644   
1645   string = "some text";
1646   g_print ("GtkStatusBar: context=\"%s\", context_id=%d\n",
1647            string,
1648            gtk_statusbar_get_context_id (statusbar, string));
1649
1650   string = "hit the mouse";
1651   g_print ("GtkStatusBar: context=\"%s\", context_id=%d\n",
1652            string,
1653            gtk_statusbar_get_context_id (statusbar, string));
1654
1655   string = "hit the mouse2";
1656   g_print ("GtkStatusBar: context=\"%s\", context_id=%d\n",
1657            string,
1658            gtk_statusbar_get_context_id (statusbar, string));
1659 }
1660
1661 static void
1662 create_statusbar (GtkWidget *widget)
1663 {
1664   static GtkWidget *window = NULL;
1665   GtkWidget *box1;
1666   GtkWidget *box2;
1667   GtkWidget *button;
1668   GtkWidget *separator;
1669   GtkWidget *statusbar;
1670
1671   if (!window)
1672     {
1673       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1674       gtk_window_set_screen (GTK_WINDOW (window),
1675                              gtk_widget_get_screen (widget));
1676
1677       g_signal_connect (window, "destroy",
1678                         G_CALLBACK (gtk_widget_destroyed),
1679                         &window);
1680
1681       gtk_window_set_title (GTK_WINDOW (window), "statusbar");
1682       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
1683
1684       box1 = gtk_vbox_new (FALSE, 0);
1685       gtk_container_add (GTK_CONTAINER (window), box1);
1686
1687       box2 = gtk_vbox_new (FALSE, 10);
1688       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
1689       gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
1690
1691       statusbar = gtk_statusbar_new ();
1692       gtk_box_pack_end (GTK_BOX (box1), statusbar, TRUE, TRUE, 0);
1693       g_signal_connect (statusbar,
1694                         "text_popped",
1695                         G_CALLBACK (statusbar_popped),
1696                         NULL);
1697
1698       button = g_object_new (gtk_button_get_type (),
1699                                "label", "push something",
1700                                "visible", TRUE,
1701                                "parent", box2,
1702                                NULL);
1703       g_object_connect (button,
1704                         "signal::clicked", statusbar_push, statusbar,
1705                         NULL);
1706
1707       button = g_object_connect (g_object_new (gtk_button_get_type (),
1708                                                  "label", "pop",
1709                                                  "visible", TRUE,
1710                                                  "parent", box2,
1711                                                  NULL),
1712                                  "signal_after::clicked", statusbar_pop, statusbar,
1713                                  NULL);
1714
1715       button = g_object_connect (g_object_new (gtk_button_get_type (),
1716                                                  "label", "steal #4",
1717                                                  "visible", TRUE,
1718                                                  "parent", box2,
1719                                                  NULL),
1720                                  "signal_after::clicked", statusbar_steal, statusbar,
1721                                  NULL);
1722
1723       button = g_object_connect (g_object_new (gtk_button_get_type (),
1724                                                  "label", "test contexts",
1725                                                  "visible", TRUE,
1726                                                  "parent", box2,
1727                                                  NULL),
1728                                  "swapped_signal_after::clicked", statusbar_contexts, statusbar,
1729                                  NULL);
1730
1731       button = g_object_connect (g_object_new (gtk_button_get_type (),
1732                                                  "label", "push something long",
1733                                                  "visible", TRUE,
1734                                                  "parent", box2,
1735                                                  NULL),
1736                                  "signal_after::clicked", statusbar_push_long, statusbar,
1737                                  NULL);
1738       
1739       separator = gtk_hseparator_new ();
1740       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
1741
1742       box2 = gtk_vbox_new (FALSE, 10);
1743       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
1744       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
1745
1746       button = gtk_button_new_with_label ("close");
1747       g_signal_connect_swapped (button, "clicked",
1748                                 G_CALLBACK (gtk_widget_destroy),
1749                                 window);
1750       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
1751       gtk_widget_set_can_default (button, TRUE);
1752       gtk_widget_grab_default (button);
1753     }
1754
1755   if (!gtk_widget_get_visible (window))
1756     gtk_widget_show_all (window);
1757   else
1758     gtk_widget_destroy (window);
1759 }
1760
1761 /*
1762  * Gridded geometry
1763  */
1764 #define GRID_SIZE 20
1765 #define DEFAULT_GEOMETRY "10x10"
1766
1767 static gboolean
1768 gridded_geometry_expose (GtkWidget      *widget,
1769                          GdkEventExpose *event)
1770 {
1771   int i, j;
1772
1773   gdk_draw_rectangle (widget->window, widget->style->base_gc[widget->state], TRUE,
1774                       0, 0, widget->allocation.width, widget->allocation.height);
1775   
1776   for (i = 0 ; i * GRID_SIZE < widget->allocation.width; i++)
1777     for (j = 0 ; j * GRID_SIZE < widget->allocation.height; j++)
1778       {
1779         if ((i + j) % 2 == 0)
1780           gdk_draw_rectangle (widget->window, widget->style->text_gc[widget->state], TRUE,
1781                               i * GRID_SIZE, j * GRID_SIZE, GRID_SIZE, GRID_SIZE);
1782       }
1783
1784   return FALSE;
1785 }
1786
1787 static void
1788 gridded_geometry_subresponse (GtkDialog *dialog,
1789                               gint       response_id,
1790                               gchar     *geometry_string)
1791 {
1792   if (response_id == GTK_RESPONSE_NONE)
1793     {
1794       gtk_widget_destroy (GTK_WIDGET (dialog));
1795     }
1796   else
1797     {
1798       if (!gtk_window_parse_geometry (GTK_WINDOW (dialog), geometry_string))
1799         {
1800           g_print ("Can't parse geometry string %s\n", geometry_string);
1801           gtk_window_parse_geometry (GTK_WINDOW (dialog), DEFAULT_GEOMETRY);
1802         }
1803     }
1804 }
1805
1806 static void
1807 gridded_geometry_response (GtkDialog *dialog,
1808                            gint       response_id,
1809                            GtkEntry  *entry)
1810 {
1811   if (response_id == GTK_RESPONSE_NONE)
1812     {
1813       gtk_widget_destroy (GTK_WIDGET (dialog));
1814     }
1815   else
1816     {
1817       gchar *geometry_string = g_strdup (gtk_entry_get_text (entry));
1818       gchar *title = g_strdup_printf ("Gridded window at: %s", geometry_string);
1819       GtkWidget *window;
1820       GtkWidget *drawing_area;
1821       GtkWidget *box;
1822       GdkGeometry geometry;
1823       
1824       window = gtk_dialog_new_with_buttons (title,
1825                                             NULL, 0,
1826                                             "Reset", 1,
1827                                             GTK_STOCK_CLOSE, GTK_RESPONSE_NONE,
1828                                             NULL);
1829
1830       gtk_window_set_screen (GTK_WINDOW (window), 
1831                              gtk_widget_get_screen (GTK_WIDGET (dialog)));
1832       g_free (title);
1833       g_signal_connect (window, "response",
1834                         G_CALLBACK (gridded_geometry_subresponse), geometry_string);
1835
1836       box = gtk_vbox_new (FALSE, 0);
1837       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), box, TRUE, TRUE, 0);
1838       
1839       gtk_container_set_border_width (GTK_CONTAINER (box), 7);
1840       
1841       drawing_area = gtk_drawing_area_new ();
1842       g_signal_connect (drawing_area, "expose_event",
1843                         G_CALLBACK (gridded_geometry_expose), NULL);
1844       gtk_box_pack_start (GTK_BOX (box), drawing_area, TRUE, TRUE, 0);
1845
1846       /* Gross hack to work around bug 68668... if we set the size request
1847        * large enough, then  the current
1848        *
1849        *   request_of_window - request_of_geometry_widget
1850        *
1851        * method of getting the base size works more or less works.
1852        */
1853       gtk_widget_set_size_request (drawing_area, 2000, 2000);
1854
1855       geometry.base_width = 0;
1856       geometry.base_height = 0;
1857       geometry.min_width = 2 * GRID_SIZE;
1858       geometry.min_height = 2 * GRID_SIZE;
1859       geometry.width_inc = GRID_SIZE;
1860       geometry.height_inc = GRID_SIZE;
1861
1862       gtk_window_set_geometry_hints (GTK_WINDOW (window), drawing_area,
1863                                      &geometry,
1864                                      GDK_HINT_BASE_SIZE | GDK_HINT_MIN_SIZE | GDK_HINT_RESIZE_INC);
1865
1866       if (!gtk_window_parse_geometry (GTK_WINDOW (window), geometry_string))
1867         {
1868           g_print ("Can't parse geometry string %s\n", geometry_string);
1869           gtk_window_parse_geometry (GTK_WINDOW (window), DEFAULT_GEOMETRY);
1870         }
1871
1872       gtk_widget_show_all (window);
1873     }
1874 }
1875
1876 static void 
1877 create_gridded_geometry (GtkWidget *widget)
1878 {
1879   static GtkWidget *window = NULL;
1880   gpointer window_ptr;
1881   GtkWidget *entry;
1882   GtkWidget *label;
1883
1884   if (!window)
1885     {
1886       window = gtk_dialog_new_with_buttons ("Gridded Geometry",
1887                                             NULL, 0,
1888                                             "Create", 1,
1889                                             GTK_STOCK_CLOSE, GTK_RESPONSE_NONE,
1890                                             NULL);
1891       
1892       gtk_window_set_screen (GTK_WINDOW (window),
1893                              gtk_widget_get_screen (widget));
1894
1895       label = gtk_label_new ("Geometry string:");
1896       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), label, FALSE, FALSE, 0);
1897
1898       entry = gtk_entry_new ();
1899       gtk_entry_set_text (GTK_ENTRY (entry), DEFAULT_GEOMETRY);
1900       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), entry, FALSE, FALSE, 0);
1901
1902       g_signal_connect (window, "response",
1903                         G_CALLBACK (gridded_geometry_response), entry);
1904       window_ptr = &window;
1905       g_object_add_weak_pointer (G_OBJECT (window), window_ptr);
1906
1907       gtk_widget_show_all (window);
1908     }
1909   else
1910     gtk_widget_destroy (window);
1911 }
1912
1913 /*
1914  * GtkHandleBox
1915  */
1916
1917 static void
1918 handle_box_child_signal (GtkHandleBox *hb,
1919                          GtkWidget    *child,
1920                          const gchar  *action)
1921 {
1922   printf ("%s: child <%s> %sed\n",
1923           g_type_name (G_OBJECT_TYPE (hb)),
1924           g_type_name (G_OBJECT_TYPE (child)),
1925           action);
1926 }
1927
1928 static void
1929 create_handle_box (GtkWidget *widget)
1930 {
1931   static GtkWidget* window = NULL;
1932   GtkWidget *handle_box;
1933   GtkWidget *handle_box2;
1934   GtkWidget *vbox;
1935   GtkWidget *hbox;
1936   GtkWidget *toolbar;
1937   GtkWidget *label;
1938   GtkWidget *separator;
1939
1940   if (!window)
1941   {
1942     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1943     
1944     gtk_window_set_screen (GTK_WINDOW (window),
1945                            gtk_widget_get_screen (widget));
1946     gtk_window_set_modal (GTK_WINDOW (window), FALSE);
1947     gtk_window_set_title (GTK_WINDOW (window),
1948                           "Handle Box Test");
1949     gtk_window_set_resizable (GTK_WINDOW (window), TRUE);
1950     
1951     g_signal_connect (window, "destroy",
1952                       G_CALLBACK (gtk_widget_destroyed),
1953                       &window);
1954     
1955     gtk_container_set_border_width (GTK_CONTAINER (window), 20);
1956
1957     vbox = gtk_vbox_new (FALSE, 0);
1958     gtk_container_add (GTK_CONTAINER (window), vbox);
1959     gtk_widget_show (vbox);
1960
1961     label = gtk_label_new ("Above");
1962     gtk_container_add (GTK_CONTAINER (vbox), label);
1963     gtk_widget_show (label);
1964
1965     separator = gtk_hseparator_new ();
1966     gtk_container_add (GTK_CONTAINER (vbox), separator);
1967     gtk_widget_show (separator);
1968     
1969     hbox = gtk_hbox_new (FALSE, 10);
1970     gtk_container_add (GTK_CONTAINER (vbox), hbox);
1971     gtk_widget_show (hbox);
1972
1973     separator = gtk_hseparator_new ();
1974     gtk_container_add (GTK_CONTAINER (vbox), separator);
1975     gtk_widget_show (separator);
1976
1977     label = gtk_label_new ("Below");
1978     gtk_container_add (GTK_CONTAINER (vbox), label);
1979     gtk_widget_show (label);
1980
1981     handle_box = gtk_handle_box_new ();
1982     gtk_box_pack_start (GTK_BOX (hbox), handle_box, FALSE, FALSE, 0);
1983     g_signal_connect (handle_box,
1984                       "child_attached",
1985                       G_CALLBACK (handle_box_child_signal),
1986                       "attached");
1987     g_signal_connect (handle_box,
1988                       "child_detached",
1989                       G_CALLBACK (handle_box_child_signal),
1990                       "detached");
1991     gtk_widget_show (handle_box);
1992
1993     toolbar = make_toolbar (window);
1994     
1995     gtk_container_add (GTK_CONTAINER (handle_box), toolbar);
1996     gtk_widget_show (toolbar);
1997
1998     handle_box = gtk_handle_box_new ();
1999     gtk_box_pack_start (GTK_BOX (hbox), handle_box, FALSE, FALSE, 0);
2000     g_signal_connect (handle_box,
2001                       "child_attached",
2002                       G_CALLBACK (handle_box_child_signal),
2003                       "attached");
2004     g_signal_connect (handle_box,
2005                       "child_detached",
2006                       G_CALLBACK (handle_box_child_signal),
2007                       "detached");
2008     gtk_widget_show (handle_box);
2009
2010     handle_box2 = gtk_handle_box_new ();
2011     gtk_container_add (GTK_CONTAINER (handle_box), handle_box2);
2012     g_signal_connect (handle_box2,
2013                       "child_attached",
2014                       G_CALLBACK (handle_box_child_signal),
2015                       "attached");
2016     g_signal_connect (handle_box2,
2017                       "child_detached",
2018                       G_CALLBACK (handle_box_child_signal),
2019                       "detached");
2020     gtk_widget_show (handle_box2);
2021
2022     hbox = g_object_new (GTK_TYPE_HBOX, "visible", 1, "parent", handle_box2, NULL);
2023     label = gtk_label_new ("Fooo!");
2024     gtk_container_add (GTK_CONTAINER (hbox), label);
2025     gtk_widget_show (label);
2026     g_object_new (GTK_TYPE_ARROW, "visible", 1, "parent", hbox, NULL);
2027   }
2028
2029   if (!gtk_widget_get_visible (window))
2030     gtk_widget_show (window);
2031   else
2032     gtk_widget_destroy (window);
2033 }
2034
2035 /*
2036  * Test for getting an image from a drawable
2037  */
2038
2039 struct GetImageData
2040 {
2041   GtkWidget *src;
2042   GtkWidget *snap;
2043   GtkWidget *sw;
2044 };
2045
2046 static void
2047 take_snapshot (GtkWidget *button,
2048                gpointer data)
2049 {
2050   struct GetImageData *gid = data;
2051   GdkRectangle visible;
2052   int width_fraction;
2053   int height_fraction;
2054   GdkGC *gc;
2055   GdkGC *black_gc;
2056   GdkColor color = { 0, 30000, 0, 0 };
2057   GdkRectangle target;
2058   GdkImage *shot;
2059   
2060   /* Do some begin_paint_rect on some random rects, draw some
2061    * distinctive stuff into those rects, then take the snapshot.
2062    * figure out whether any rects were overlapped and report to
2063    * user.
2064    */
2065
2066   visible = gid->sw->allocation;
2067
2068   visible.x = gtk_scrolled_window_get_hadjustment (GTK_SCROLLED_WINDOW (gid->sw))->value;
2069   visible.y = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (gid->sw))->value;
2070   
2071   width_fraction = visible.width / 4;
2072   height_fraction = visible.height / 4;
2073
2074   gc = gdk_gc_new (gid->src->window);
2075   black_gc = gid->src->style->black_gc;
2076   
2077   gdk_gc_set_rgb_fg_color (gc, &color);
2078
2079     
2080   target.x = visible.x + width_fraction;
2081   target.y = visible.y + height_fraction * 3;
2082   target.width = width_fraction;
2083   target.height = height_fraction / 2;
2084   
2085   gdk_window_begin_paint_rect (gid->src->window,
2086                                &target);
2087
2088   gdk_draw_rectangle (gid->src->window,
2089                       gc,
2090                       TRUE,
2091                       target.x, target.y,
2092                       target.width, target.height);
2093
2094   gdk_draw_rectangle (gid->src->window,
2095                       black_gc,
2096                       FALSE,
2097                       target.x + 10, target.y + 10,
2098                       target.width - 20, target.height - 20);
2099   
2100   target.x = visible.x + width_fraction;
2101   target.y = visible.y + height_fraction;
2102   target.width = width_fraction;
2103   target.height = height_fraction;
2104   
2105   gdk_window_begin_paint_rect (gid->src->window,
2106                                &target);
2107
2108   gdk_draw_rectangle (gid->src->window,
2109                       gc,
2110                       TRUE,
2111                       target.x, target.y,
2112                       target.width, target.height);
2113
2114   gdk_draw_rectangle (gid->src->window,
2115                       black_gc,
2116                       FALSE,
2117                       target.x + 10, target.y + 10,
2118                       target.width - 20, target.height - 20);
2119   
2120   target.x = visible.x + width_fraction * 3;
2121   target.y = visible.y + height_fraction;
2122   target.width = width_fraction / 2;
2123   target.height = height_fraction;
2124   
2125   gdk_window_begin_paint_rect (gid->src->window,
2126                                &target);
2127
2128   gdk_draw_rectangle (gid->src->window,
2129                       gc,
2130                       TRUE,
2131                       target.x, target.y,
2132                       target.width, target.height);
2133
2134   gdk_draw_rectangle (gid->src->window,
2135                       black_gc,
2136                       FALSE,
2137                       target.x + 10, target.y + 10,
2138                       target.width - 20, target.height - 20);
2139   
2140   target.x = visible.x + width_fraction * 2;
2141   target.y = visible.y + height_fraction * 2;
2142   target.width = width_fraction / 4;
2143   target.height = height_fraction / 4;
2144   
2145   gdk_window_begin_paint_rect (gid->src->window,
2146                                &target);
2147
2148   gdk_draw_rectangle (gid->src->window,
2149                       gc,
2150                       TRUE,
2151                       target.x, target.y,
2152                       target.width, target.height);
2153
2154   gdk_draw_rectangle (gid->src->window,
2155                       black_gc,
2156                       FALSE,
2157                       target.x + 10, target.y + 10,
2158                       target.width - 20, target.height - 20);  
2159
2160   target.x += target.width / 2;
2161   target.y += target.width / 2;
2162   
2163   gdk_window_begin_paint_rect (gid->src->window,
2164                                &target);
2165
2166   gdk_draw_rectangle (gid->src->window,
2167                       gc,
2168                       TRUE,
2169                       target.x, target.y,
2170                       target.width, target.height);
2171
2172   gdk_draw_rectangle (gid->src->window,
2173                       black_gc,
2174                       FALSE,
2175                       target.x + 10, target.y + 10,
2176                       target.width - 20, target.height - 20);
2177   
2178   /* Screen shot area */
2179
2180   target.x = visible.x + width_fraction * 1.5;
2181   target.y = visible.y + height_fraction * 1.5;
2182   target.width = width_fraction * 2;
2183   target.height = height_fraction * 2;  
2184
2185   shot = gdk_drawable_get_image (gid->src->window,
2186                                  target.x, target.y,
2187                                  target.width, target.height);
2188
2189   gtk_image_set_from_image (GTK_IMAGE (gid->snap),
2190                             shot, NULL);
2191
2192   g_object_unref (shot);
2193   
2194   gdk_window_end_paint (gid->src->window);
2195   gdk_window_end_paint (gid->src->window);
2196   gdk_window_end_paint (gid->src->window);
2197   gdk_window_end_paint (gid->src->window);
2198   gdk_window_end_paint (gid->src->window);
2199
2200   gdk_draw_rectangle (gid->src->window,
2201                       gid->src->style->black_gc,
2202                       FALSE,
2203                       target.x, target.y,
2204                       target.width, target.height);
2205   
2206   g_object_unref (gc);
2207 }
2208
2209 static gint
2210 image_source_expose (GtkWidget *da,
2211                      GdkEventExpose *event,
2212                      gpointer data)
2213 {
2214   int x = event->area.x;
2215   GdkColor red = { 0, 65535, 0, 0 };
2216   GdkColor green = { 0, 0, 65535, 0 };
2217   GdkColor blue = { 0, 0, 0, 65535 };
2218   GdkGC *gc;
2219
2220   gc = gdk_gc_new (event->window);
2221   
2222   while (x < (event->area.x + event->area.width))
2223     {
2224       switch (x % 7)
2225         {
2226         case 0:
2227         case 1:
2228         case 2:
2229           gdk_gc_set_rgb_fg_color (gc, &red);
2230           break;
2231
2232         case 3:
2233         case 4:
2234         case 5:
2235           gdk_gc_set_rgb_fg_color (gc, &green);
2236           break;
2237
2238         case 6:
2239         case 7:
2240         case 8:
2241           gdk_gc_set_rgb_fg_color (gc, &blue);
2242           break;
2243
2244         default:
2245           g_assert_not_reached ();
2246           break;
2247         }
2248
2249       gdk_draw_line (event->window,
2250                      gc,
2251                      x, event->area.y,
2252                      x, event->area.y + event->area.height);
2253       
2254       ++x;
2255     }
2256
2257   g_object_unref (gc);
2258   
2259   return TRUE;
2260 }
2261
2262 static void
2263 create_get_image (GtkWidget *widget)
2264 {
2265   static GtkWidget *window = NULL;
2266
2267   if (window)
2268     gtk_widget_destroy (window);
2269   else
2270     {
2271       GtkWidget *sw;
2272       GtkWidget *src;
2273       GtkWidget *snap;
2274       GtkWidget *hbox;
2275       GtkWidget *vbox;
2276       GtkWidget *button;
2277       struct GetImageData *gid;
2278
2279       gid = g_new (struct GetImageData, 1);
2280       
2281       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
2282       
2283       gtk_window_set_screen (GTK_WINDOW (window),
2284                              gtk_widget_get_screen (widget));
2285
2286       g_signal_connect (window,
2287                         "destroy",
2288                         G_CALLBACK (gtk_widget_destroyed),
2289                         &window);
2290
2291       g_object_set_data_full (G_OBJECT (window),
2292                               "testgtk-get-image-data",
2293                               gid,
2294                               g_free);
2295       
2296       hbox = gtk_hbox_new (FALSE, 0);
2297       
2298       gtk_container_add (GTK_CONTAINER (window), hbox);
2299       
2300       sw = gtk_scrolled_window_new (NULL, NULL);
2301       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
2302                                       GTK_POLICY_AUTOMATIC,
2303                                       GTK_POLICY_AUTOMATIC);
2304
2305       gid->sw = sw;
2306
2307       gtk_widget_set_size_request (sw, 400, 400);
2308       
2309       src = gtk_drawing_area_new ();
2310       gtk_widget_set_size_request (src, 10000, 10000);
2311
2312       g_signal_connect (src,
2313                         "expose_event",
2314                         G_CALLBACK (image_source_expose),
2315                         gid);
2316       
2317       gid->src = src;
2318       
2319       gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (sw),
2320                                              src);
2321       
2322       gtk_box_pack_start (GTK_BOX (hbox),
2323                           sw, TRUE, TRUE, 0);
2324
2325
2326       vbox = gtk_vbox_new (FALSE, 3);
2327
2328       snap = g_object_new (GTK_TYPE_IMAGE, NULL);
2329
2330       gid->snap = snap;
2331
2332       sw = gtk_scrolled_window_new (NULL, NULL);
2333       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
2334                                       GTK_POLICY_AUTOMATIC,
2335                                       GTK_POLICY_AUTOMATIC);
2336       gtk_widget_set_size_request (sw, 300, 300);
2337       
2338       gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (sw), snap);
2339
2340       gtk_box_pack_end (GTK_BOX (vbox), sw, FALSE, FALSE, 5);
2341
2342       button = gtk_button_new_with_label ("Get image from drawable");
2343
2344       g_signal_connect (button,
2345                         "clicked",
2346                         G_CALLBACK (take_snapshot),
2347                         gid);
2348       
2349       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
2350
2351       gtk_box_pack_end (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
2352       
2353       gtk_widget_show_all (window);
2354     }
2355 }
2356
2357 /* 
2358  * Label Demo
2359  */
2360 static void
2361 sensitivity_toggled (GtkWidget *toggle,
2362                      GtkWidget *widget)
2363 {
2364   gtk_widget_set_sensitive (widget,  GTK_TOGGLE_BUTTON (toggle)->active);  
2365 }
2366
2367 static GtkWidget*
2368 create_sensitivity_control (GtkWidget *widget)
2369 {
2370   GtkWidget *button;
2371
2372   button = gtk_toggle_button_new_with_label ("Sensitive");  
2373
2374   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
2375                                 gtk_widget_is_sensitive (widget));
2376   
2377   g_signal_connect (button,
2378                     "toggled",
2379                     G_CALLBACK (sensitivity_toggled),
2380                     widget);
2381   
2382   gtk_widget_show_all (button);
2383
2384   return button;
2385 }
2386
2387 static void
2388 set_selectable_recursive (GtkWidget *widget,
2389                           gboolean   setting)
2390 {
2391   if (GTK_IS_CONTAINER (widget))
2392     {
2393       GList *children;
2394       GList *tmp;
2395       
2396       children = gtk_container_get_children (GTK_CONTAINER (widget));
2397       tmp = children;
2398       while (tmp)
2399         {
2400           set_selectable_recursive (tmp->data, setting);
2401
2402           tmp = tmp->next;
2403         }
2404       g_list_free (children);
2405     }
2406   else if (GTK_IS_LABEL (widget))
2407     {
2408       gtk_label_set_selectable (GTK_LABEL (widget), setting);
2409     }
2410 }
2411
2412 static void
2413 selectable_toggled (GtkWidget *toggle,
2414                     GtkWidget *widget)
2415 {
2416   set_selectable_recursive (widget,
2417                             GTK_TOGGLE_BUTTON (toggle)->active);
2418 }
2419
2420 static GtkWidget*
2421 create_selectable_control (GtkWidget *widget)
2422 {
2423   GtkWidget *button;
2424
2425   button = gtk_toggle_button_new_with_label ("Selectable");  
2426
2427   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
2428                                 FALSE);
2429   
2430   g_signal_connect (button,
2431                     "toggled",
2432                     G_CALLBACK (selectable_toggled),
2433                     widget);
2434   
2435   gtk_widget_show_all (button);
2436
2437   return button;
2438 }
2439
2440 static void
2441 dialog_response (GtkWidget *dialog, gint response_id, GtkLabel *label)
2442 {
2443   const gchar *text;
2444
2445   gtk_widget_destroy (dialog);
2446
2447   text = "Some <a href=\"http://en.wikipedia.org/wiki/Text\" title=\"plain text\">text</a> may be marked up\n"
2448          "as hyperlinks, which can be clicked\n"
2449          "or activated via <a href=\"keynav\">keynav</a>.\n"
2450          "The links remain the same.";
2451   gtk_label_set_markup (label, text);
2452 }
2453
2454 static gboolean
2455 activate_link (GtkWidget *label, const gchar *uri, gpointer data)
2456 {
2457   if (g_strcmp0 (uri, "keynav") == 0)
2458     {
2459       GtkWidget *dialog;
2460
2461       dialog = gtk_message_dialog_new_with_markup (GTK_WINDOW (gtk_widget_get_toplevel (label)),
2462                                        GTK_DIALOG_DESTROY_WITH_PARENT,
2463                                        GTK_MESSAGE_INFO,
2464                                        GTK_BUTTONS_OK,
2465                                        "The term <i>keynav</i> is a shorthand for "
2466                                        "keyboard navigation and refers to the process of using a program "
2467                                        "(exclusively) via keyboard input.");
2468
2469       gtk_window_present (GTK_WINDOW (dialog));
2470
2471       g_signal_connect (dialog, "response", G_CALLBACK (dialog_response), label);
2472
2473       return TRUE;
2474     }
2475
2476   return FALSE;
2477 }
2478
2479 void create_labels (GtkWidget *widget)
2480 {
2481   static GtkWidget *window = NULL;
2482   GtkWidget *hbox;
2483   GtkWidget *vbox;
2484   GtkWidget *frame;
2485   GtkWidget *label;
2486   GtkWidget *button;
2487
2488   if (!window)
2489     {
2490       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
2491
2492       gtk_window_set_screen (GTK_WINDOW (window),
2493                              gtk_widget_get_screen (widget));
2494
2495       g_signal_connect (window, "destroy",
2496                         G_CALLBACK (gtk_widget_destroyed),
2497                         &window);
2498
2499       gtk_window_set_title (GTK_WINDOW (window), "Label");
2500
2501       vbox = gtk_vbox_new (FALSE, 5);
2502       
2503       hbox = gtk_hbox_new (FALSE, 5);
2504       gtk_container_add (GTK_CONTAINER (window), vbox);
2505
2506       gtk_box_pack_end (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
2507
2508       button = create_sensitivity_control (hbox);
2509
2510       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
2511
2512       button = create_selectable_control (hbox);
2513
2514       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
2515       
2516       vbox = gtk_vbox_new (FALSE, 5);
2517       
2518       gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
2519       gtk_container_set_border_width (GTK_CONTAINER (window), 5);
2520
2521       frame = gtk_frame_new ("Normal Label");
2522       label = gtk_label_new ("This is a Normal label");
2523       gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_START);
2524       gtk_container_add (GTK_CONTAINER (frame), label);
2525       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
2526
2527       frame = gtk_frame_new ("Multi-line Label");
2528       label = gtk_label_new ("This is a Multi-line label.\nSecond line\nThird line");
2529       gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_END);
2530       gtk_container_add (GTK_CONTAINER (frame), label);
2531       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
2532
2533       frame = gtk_frame_new ("Left Justified Label");
2534       label = gtk_label_new ("This is a Left-Justified\nMulti-line label.\nThird      line");
2535       gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_MIDDLE);
2536       gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
2537       gtk_container_add (GTK_CONTAINER (frame), label);
2538       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
2539
2540       frame = gtk_frame_new ("Right Justified Label");
2541       gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_START);
2542       label = gtk_label_new ("This is a Right-Justified\nMulti-line label.\nFourth line, (j/k)");
2543       gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_RIGHT);
2544       gtk_container_add (GTK_CONTAINER (frame), label);
2545       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
2546
2547       frame = gtk_frame_new ("Internationalized Label");
2548       label = gtk_label_new (NULL);
2549       gtk_label_set_markup (GTK_LABEL (label),
2550                             "French (Fran\303\247ais) Bonjour, Salut\n"
2551                             "Korean (\355\225\234\352\270\200)   \354\225\210\353\205\225\355\225\230\354\204\270\354\232\224, \354\225\210\353\205\225\355\225\230\354\213\255\353\213\210\352\271\214\n"
2552                             "Russian (\320\240\321\203\321\201\321\201\320\272\320\270\320\271) \320\227\320\264\321\200\320\260\320\262\321\201\321\202\320\262\321\203\320\271\321\202\320\265!\n"
2553                             "Chinese (Simplified) <span lang=\"zh-cn\">\345\205\203\346\260\224 \345\274\200\345\217\221</span>\n"
2554                             "Chinese (Traditional) <span lang=\"zh-tw\">\345\205\203\346\260\243        \351\226\213\347\231\274</span>\n"
2555                             "Japanese <span lang=\"ja\">\345\205\203\346\260\227        \351\226\213\347\231\272</span>");
2556       gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
2557       gtk_container_add (GTK_CONTAINER (frame), label);
2558       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
2559
2560       frame = gtk_frame_new ("Bidirection Label");
2561       label = gtk_label_new ("\342\200\217Arabic        \330\247\331\204\330\263\331\204\330\247\331\205 \330\271\331\204\331\212\331\203\331\205\n"
2562                              "\342\200\217Hebrew        \327\251\327\234\327\225\327\235");
2563       gtk_container_add (GTK_CONTAINER (frame), label);
2564       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
2565
2566       frame = gtk_frame_new ("Links in a label");
2567       label = gtk_label_new ("Some <a href=\"http://en.wikipedia.org/wiki/Text\" title=\"plain text\">text</a> may be marked up\n"
2568                              "as hyperlinks, which can be clicked\n"
2569                              "or activated via <a href=\"keynav\">keynav</a>");
2570       gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
2571       gtk_container_add (GTK_CONTAINER (frame), label);
2572       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
2573       g_signal_connect (label, "activate-link", G_CALLBACK (activate_link), NULL);
2574
2575       vbox = gtk_vbox_new (FALSE, 5);
2576       gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
2577       frame = gtk_frame_new ("Line wrapped label");
2578       label = gtk_label_new ("This is an example of a line-wrapped label.  It should not be taking "\
2579                              "up the entire             "/* big space to test spacing */\
2580                              "width allocated to it, but automatically wraps the words to fit.  "\
2581                              "The time has come, for all good men, to come to the aid of their party.  "\
2582                              "The sixth sheik's six sheep's sick.\n"\
2583                              "     It supports multiple paragraphs correctly, and  correctly   adds "\
2584                              "many          extra  spaces. ");
2585
2586       gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
2587       gtk_container_add (GTK_CONTAINER (frame), label);
2588       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
2589
2590       frame = gtk_frame_new ("Filled, wrapped label");
2591       label = gtk_label_new ("This is an example of a line-wrapped, filled label.  It should be taking "\
2592                              "up the entire              width allocated to it.  Here is a seneance to prove "\
2593                              "my point.  Here is another sentence. "\
2594                              "Here comes the sun, do de do de do.\n"\
2595                              "    This is a new paragraph.\n"\
2596                              "    This is another newer, longer, better paragraph.  It is coming to an end, "\
2597                              "unfortunately.");
2598       gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_FILL);
2599       gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
2600       gtk_container_add (GTK_CONTAINER (frame), label);
2601       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
2602
2603       frame = gtk_frame_new ("Underlined label");
2604       label = gtk_label_new ("This label is underlined!\n"
2605                              "This one is underlined (\343\201\223\343\202\223\343\201\253\343\201\241\343\201\257) in quite a funky fashion");
2606       gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
2607       gtk_label_set_pattern (GTK_LABEL (label), "_________________________ _ _________ _ _____ _ __ __  ___ ____ _____");
2608       gtk_container_add (GTK_CONTAINER (frame), label);
2609       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
2610
2611       frame = gtk_frame_new ("Markup label");
2612       label = gtk_label_new (NULL);
2613
2614       /* There's also a gtk_label_set_markup() without accel if you
2615        * don't have an accelerator key
2616        */
2617       gtk_label_set_markup_with_mnemonic (GTK_LABEL (label),
2618                                           "This <span foreground=\"blue\" background=\"orange\">label</span> has "
2619                                           "<b>markup</b> _such as "
2620                                           "<big><i>Big Italics</i></big>\n"
2621                                           "<tt>Monospace font</tt>\n"
2622                                           "<u>Underline!</u>\n"
2623                                           "foo\n"
2624                                           "<span foreground=\"green\" background=\"red\">Ugly colors</span>\n"
2625                                           "and nothing on this line,\n"
2626                                           "or this.\n"
2627                                           "or this either\n"
2628                                           "or even on this one\n"
2629                                           "la <big>la <big>la <big>la <big>la</big></big></big></big>\n"
2630                                           "but this _word is <span foreground=\"purple\"><big>purple</big></span>\n"
2631                                           "<span underline=\"double\">We like <sup>superscript</sup> and <sub>subscript</sub> too</span>");
2632
2633       g_assert (gtk_label_get_mnemonic_keyval (GTK_LABEL (label)) == GDK_s);
2634       
2635       gtk_container_add (GTK_CONTAINER (frame), label);
2636       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
2637     }
2638   
2639   if (!gtk_widget_get_visible (window))
2640     gtk_widget_show_all (window);
2641   else
2642     gtk_widget_destroy (window);
2643 }
2644
2645 static void
2646 on_angle_scale_changed (GtkRange *range,
2647                         GtkLabel *label)
2648 {
2649   gtk_label_set_angle (GTK_LABEL (label), gtk_range_get_value (range));
2650 }
2651
2652 static void
2653 create_rotated_label (GtkWidget *widget)
2654 {
2655   static GtkWidget *window = NULL;
2656   GtkWidget *vbox;
2657   GtkWidget *hscale;
2658   GtkWidget *label;  
2659   GtkWidget *scale_label;  
2660   GtkWidget *scale_hbox;  
2661
2662   if (!window)
2663     {
2664       window = gtk_dialog_new_with_buttons ("Rotated Label",
2665                                             GTK_WINDOW (gtk_widget_get_toplevel (widget)), 0,
2666                                             GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
2667                                             NULL);
2668
2669       gtk_window_set_resizable (GTK_WINDOW (window), TRUE);
2670
2671       gtk_window_set_screen (GTK_WINDOW (window),
2672                              gtk_widget_get_screen (widget));
2673
2674       g_signal_connect (window, "response",
2675                         G_CALLBACK (gtk_object_destroy), NULL);
2676       g_signal_connect (window, "destroy",
2677                         G_CALLBACK (gtk_widget_destroyed), &window);
2678
2679       vbox = gtk_vbox_new (FALSE, 5);
2680       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), vbox, TRUE, TRUE, 0);
2681       gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
2682
2683       label = gtk_label_new (NULL);
2684       gtk_label_set_markup (GTK_LABEL (label), "Hello World\n<i>Rotate</i> <span underline='single' foreground='blue'>me</span>");
2685       gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
2686
2687       scale_hbox = gtk_hbox_new (FALSE, 0);
2688       gtk_box_pack_start (GTK_BOX (vbox), scale_hbox, FALSE, FALSE, 0);
2689       
2690       scale_label = gtk_label_new (NULL);
2691       gtk_label_set_markup (GTK_LABEL (scale_label), "<i>Angle: </i>");
2692       gtk_box_pack_start (GTK_BOX (scale_hbox), scale_label, FALSE, FALSE, 0);
2693
2694       hscale = gtk_hscale_new_with_range (0, 360, 5);
2695       g_signal_connect (hscale, "value-changed",
2696                         G_CALLBACK (on_angle_scale_changed), label);
2697       
2698       gtk_range_set_value (GTK_RANGE (hscale), 45);
2699       gtk_widget_set_size_request (hscale, 200, -1);
2700       gtk_box_pack_start (GTK_BOX (scale_hbox), hscale, TRUE, TRUE, 0);
2701     }
2702   
2703   if (!gtk_widget_get_visible (window))
2704     gtk_widget_show_all (window);
2705   else
2706     gtk_widget_destroy (window);
2707 }
2708
2709 #define DEFAULT_TEXT_RADIUS 200
2710
2711 static void
2712 on_rotated_text_unrealize (GtkWidget *widget)
2713 {
2714   g_object_set_data (G_OBJECT (widget), "text-gc", NULL);
2715 }
2716
2717 static gboolean
2718 on_rotated_text_expose (GtkWidget      *widget,
2719                         GdkEventExpose *event,
2720                         GdkPixbuf      *tile_pixbuf)
2721 {
2722   static const gchar *words[] = { "The", "grand", "old", "Duke", "of", "York",
2723                                   "had", "10,000", "men" };
2724   PangoRenderer *renderer;
2725   GdkGC *gc;
2726   int n_words;
2727   int i;
2728   double radius;
2729   PangoMatrix matrix = PANGO_MATRIX_INIT;
2730   PangoLayout *layout;
2731   PangoContext *context;
2732   PangoFontDescription *desc;
2733
2734   gc = g_object_get_data (G_OBJECT (widget), "text-gc");
2735   if (!gc)
2736     {
2737       static GdkColor black = { 0, 0, 0, 0 };
2738       
2739       gc = gdk_gc_new (widget->window);
2740       gdk_gc_set_rgb_fg_color (gc, &black);
2741       
2742       if (tile_pixbuf)
2743         {
2744           GdkPixmap *tile;
2745           
2746           gint width = gdk_pixbuf_get_width (tile_pixbuf);
2747           gint height = gdk_pixbuf_get_height (tile_pixbuf);
2748           
2749           tile = gdk_pixmap_new (widget->window, width, height, -1);
2750           gdk_draw_pixbuf (tile, gc, tile_pixbuf,
2751                            0, 0, 0, 0, width, height,
2752                            GDK_RGB_DITHER_NORMAL, 0, 0);
2753
2754           gdk_gc_set_tile (gc, tile);
2755           gdk_gc_set_fill (gc, GDK_TILED);
2756
2757           g_object_unref (tile);
2758         }
2759
2760       g_object_set_data_full (G_OBJECT (widget), "text-gc", gc, (GDestroyNotify)g_object_unref);
2761     }
2762
2763   renderer = gdk_pango_renderer_get_default (gtk_widget_get_screen (widget));
2764   gdk_pango_renderer_set_drawable (GDK_PANGO_RENDERER (renderer), widget->window);
2765   gdk_pango_renderer_set_gc (GDK_PANGO_RENDERER (renderer), gc);
2766
2767   radius = MIN (widget->allocation.width, widget->allocation.height) / 2.;
2768
2769   pango_matrix_translate (&matrix,
2770                           radius + (widget->allocation.width - 2 * radius) / 2,
2771                           radius + (widget->allocation.height - 2 * radius) / 2);
2772   pango_matrix_scale (&matrix, radius / DEFAULT_TEXT_RADIUS, radius / DEFAULT_TEXT_RADIUS);
2773
2774   context = gtk_widget_get_pango_context (widget);
2775   layout = pango_layout_new (context);
2776   desc = pango_font_description_from_string ("Sans Bold 30");
2777   pango_layout_set_font_description (layout, desc);
2778   pango_font_description_free (desc);
2779     
2780   n_words = G_N_ELEMENTS (words);
2781   for (i = 0; i < n_words; i++)
2782     {
2783       PangoMatrix rotated_matrix = matrix;
2784       int width, height;
2785       
2786       pango_matrix_rotate (&rotated_matrix, - (360. * i) / n_words);
2787
2788       pango_context_set_matrix (context, &rotated_matrix);
2789       pango_layout_context_changed (layout);
2790       pango_layout_set_text (layout, words[i], -1);
2791       
2792       pango_layout_get_size (layout, &width, &height);
2793
2794       pango_renderer_draw_layout (renderer, layout,
2795                                   - width / 2, - DEFAULT_TEXT_RADIUS * PANGO_SCALE);
2796     }
2797
2798   gdk_pango_renderer_set_drawable (GDK_PANGO_RENDERER (renderer), NULL);
2799   gdk_pango_renderer_set_gc (GDK_PANGO_RENDERER (renderer), NULL);
2800   
2801   g_object_unref (layout);
2802
2803   return FALSE;
2804 }
2805
2806 static void
2807 create_rotated_text (GtkWidget *widget)
2808 {
2809   static GtkWidget *window = NULL;
2810
2811   if (!window)
2812     {
2813       const GdkColor white = { 0, 0xffff, 0xffff, 0xffff };
2814       GtkRequisition requisition;
2815       GtkWidget *drawing_area;
2816       GdkPixbuf *tile_pixbuf;
2817
2818       window = gtk_dialog_new_with_buttons ("Rotated Text",
2819                                             GTK_WINDOW (gtk_widget_get_toplevel (widget)), 0,
2820                                             GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
2821                                             NULL);
2822
2823       gtk_window_set_resizable (GTK_WINDOW (window), TRUE);
2824
2825       gtk_window_set_screen (GTK_WINDOW (window),
2826                              gtk_widget_get_screen (widget));
2827
2828       g_signal_connect (window, "response",
2829                         G_CALLBACK (gtk_object_destroy), NULL);
2830       g_signal_connect (window, "destroy",
2831                         G_CALLBACK (gtk_widget_destroyed), &window);
2832
2833       drawing_area = gtk_drawing_area_new ();
2834       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), drawing_area, TRUE, TRUE, 0);
2835       gtk_widget_modify_bg (drawing_area, GTK_STATE_NORMAL, &white);
2836
2837       tile_pixbuf = gdk_pixbuf_new_from_file ("marble.xpm", NULL);
2838       
2839       g_signal_connect (drawing_area, "expose-event",
2840                         G_CALLBACK (on_rotated_text_expose), tile_pixbuf);
2841       g_signal_connect (drawing_area, "unrealize",
2842                         G_CALLBACK (on_rotated_text_unrealize), NULL);
2843
2844       gtk_widget_show_all (GTK_BIN (window)->child);
2845       
2846       gtk_widget_set_size_request (drawing_area, DEFAULT_TEXT_RADIUS * 2, DEFAULT_TEXT_RADIUS * 2);
2847       gtk_widget_size_request (window, &requisition);
2848       gtk_widget_set_size_request (drawing_area, -1, -1);
2849       gtk_window_resize (GTK_WINDOW (window), requisition.width, requisition.height);
2850     }
2851   
2852   if (!gtk_widget_get_visible (window))
2853     gtk_widget_show (window);
2854   else
2855     gtk_widget_destroy (window);
2856 }
2857
2858 /*
2859  * Reparent demo
2860  */
2861
2862 static void
2863 reparent_label (GtkWidget *widget,
2864                 GtkWidget *new_parent)
2865 {
2866   GtkWidget *label;
2867
2868   label = g_object_get_data (G_OBJECT (widget), "user_data");
2869
2870   gtk_widget_reparent (label, new_parent);
2871 }
2872
2873 static void
2874 set_parent_signal (GtkWidget *child,
2875                    GtkWidget *old_parent,
2876                    gpointer   func_data)
2877 {
2878   g_message ("set_parent for \"%s\": new parent: \"%s\", old parent: \"%s\", data: %d\n",
2879              g_type_name (G_OBJECT_TYPE (child)),
2880              child->parent ? g_type_name (G_OBJECT_TYPE (child->parent)) : "NULL",
2881              old_parent ? g_type_name (G_OBJECT_TYPE (old_parent)) : "NULL",
2882              GPOINTER_TO_INT (func_data));
2883 }
2884
2885 static void
2886 create_reparent (GtkWidget *widget)
2887 {
2888   static GtkWidget *window = NULL;
2889   GtkWidget *box1;
2890   GtkWidget *box2;
2891   GtkWidget *box3;
2892   GtkWidget *frame;
2893   GtkWidget *button;
2894   GtkWidget *label;
2895   GtkWidget *separator;
2896   GtkWidget *event_box;
2897
2898   if (!window)
2899     {
2900       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
2901
2902       gtk_window_set_screen (GTK_WINDOW (window),
2903                              gtk_widget_get_screen (widget));
2904
2905       g_signal_connect (window, "destroy",
2906                         G_CALLBACK (gtk_widget_destroyed),
2907                         &window);
2908
2909       gtk_window_set_title (GTK_WINDOW (window), "reparent");
2910       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
2911
2912       box1 = gtk_vbox_new (FALSE, 0);
2913       gtk_container_add (GTK_CONTAINER (window), box1);
2914
2915       box2 = gtk_hbox_new (FALSE, 5);
2916       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2917       gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
2918
2919       label = gtk_label_new ("Hello World");
2920
2921       frame = gtk_frame_new ("Frame 1");
2922       gtk_box_pack_start (GTK_BOX (box2), frame, TRUE, TRUE, 0);
2923
2924       box3 = gtk_vbox_new (FALSE, 5);
2925       gtk_container_set_border_width (GTK_CONTAINER (box3), 5);
2926       gtk_container_add (GTK_CONTAINER (frame), box3);
2927
2928       button = gtk_button_new_with_label ("switch");
2929       g_object_set_data (G_OBJECT (button), "user_data", label);
2930       gtk_box_pack_start (GTK_BOX (box3), button, FALSE, TRUE, 0);
2931
2932       event_box = gtk_event_box_new ();
2933       gtk_box_pack_start (GTK_BOX (box3), event_box, FALSE, TRUE, 0);
2934       gtk_container_add (GTK_CONTAINER (event_box), label);
2935                          
2936       g_signal_connect (button, "clicked",
2937                         G_CALLBACK (reparent_label),
2938                         event_box);
2939       
2940       g_signal_connect (label, "parent_set",
2941                         G_CALLBACK (set_parent_signal),
2942                         GINT_TO_POINTER (42));
2943
2944       frame = gtk_frame_new ("Frame 2");
2945       gtk_box_pack_start (GTK_BOX (box2), frame, TRUE, TRUE, 0);
2946
2947       box3 = gtk_vbox_new (FALSE, 5);
2948       gtk_container_set_border_width (GTK_CONTAINER (box3), 5);
2949       gtk_container_add (GTK_CONTAINER (frame), box3);
2950
2951       button = gtk_button_new_with_label ("switch");
2952       g_object_set_data (G_OBJECT (button), "user_data", label);
2953       gtk_box_pack_start (GTK_BOX (box3), button, FALSE, TRUE, 0);
2954       
2955       event_box = gtk_event_box_new ();
2956       gtk_box_pack_start (GTK_BOX (box3), event_box, FALSE, TRUE, 0);
2957
2958       g_signal_connect (button, "clicked",
2959                         G_CALLBACK (reparent_label),
2960                         event_box);
2961
2962       separator = gtk_hseparator_new ();
2963       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
2964
2965       box2 = gtk_vbox_new (FALSE, 10);
2966       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
2967       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
2968
2969       button = gtk_button_new_with_label ("close");
2970       g_signal_connect_swapped (button, "clicked",
2971                                 G_CALLBACK (gtk_widget_destroy), window);
2972       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
2973       gtk_widget_set_can_default (button, TRUE);
2974       gtk_widget_grab_default (button);
2975     }
2976
2977   if (!gtk_widget_get_visible (window))
2978     gtk_widget_show_all (window);
2979   else
2980     gtk_widget_destroy (window);
2981 }
2982
2983 /*
2984  * Resize Grips
2985  */
2986 static gboolean
2987 grippy_button_press (GtkWidget *area, GdkEventButton *event, GdkWindowEdge edge)
2988 {
2989   if (event->type == GDK_BUTTON_PRESS) 
2990     {
2991       if (event->button == 1)
2992         gtk_window_begin_resize_drag (GTK_WINDOW (gtk_widget_get_toplevel (area)), edge,
2993                                       event->button, event->x_root, event->y_root,
2994                                       event->time);
2995       else if (event->button == 2)
2996         gtk_window_begin_move_drag (GTK_WINDOW (gtk_widget_get_toplevel (area)), 
2997                                     event->button, event->x_root, event->y_root,
2998                                     event->time);
2999     }
3000   return TRUE;
3001 }
3002
3003 static gboolean
3004 grippy_expose (GtkWidget *area, GdkEventExpose *event, GdkWindowEdge edge)
3005 {
3006   gtk_paint_resize_grip (area->style,
3007                          area->window,
3008                          gtk_widget_get_state (area),
3009                          &event->area,
3010                          area,
3011                          "statusbar",
3012                          edge,
3013                          0, 0,
3014                          area->allocation.width,
3015                          area->allocation.height);
3016
3017   return TRUE;
3018 }
3019
3020 static void
3021 create_resize_grips (GtkWidget *widget)
3022 {
3023   static GtkWidget *window = NULL;
3024   GtkWidget *area;
3025   GtkWidget *hbox, *vbox;
3026   if (!window)
3027     {
3028       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3029
3030       gtk_window_set_screen (GTK_WINDOW (window),
3031                              gtk_widget_get_screen (widget));
3032
3033       gtk_window_set_title (GTK_WINDOW (window), "resize grips");
3034       
3035       g_signal_connect (window, "destroy",
3036                         G_CALLBACK (gtk_widget_destroyed),
3037                         &window);
3038
3039       vbox = gtk_vbox_new (FALSE, 0);
3040       gtk_container_add (GTK_CONTAINER (window), vbox);
3041       
3042       hbox = gtk_hbox_new (FALSE, 0);
3043       gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);
3044
3045       /* North west */
3046       area = gtk_drawing_area_new ();
3047       gtk_widget_add_events (area, GDK_BUTTON_PRESS_MASK);
3048       gtk_box_pack_start (GTK_BOX (hbox), area, TRUE, TRUE, 0);
3049       g_signal_connect (area, "expose_event", G_CALLBACK (grippy_expose),
3050                         GINT_TO_POINTER (GDK_WINDOW_EDGE_NORTH_WEST));
3051       g_signal_connect (area, "button_press_event", G_CALLBACK (grippy_button_press),
3052                         GINT_TO_POINTER (GDK_WINDOW_EDGE_NORTH_WEST));
3053       
3054       /* North */
3055       area = gtk_drawing_area_new ();
3056       gtk_widget_add_events (area, GDK_BUTTON_PRESS_MASK);
3057       gtk_box_pack_start (GTK_BOX (hbox), area, TRUE, TRUE, 0);
3058       g_signal_connect (area, "expose_event", G_CALLBACK (grippy_expose),
3059                         GINT_TO_POINTER (GDK_WINDOW_EDGE_NORTH));
3060       g_signal_connect (area, "button_press_event", G_CALLBACK (grippy_button_press),
3061                         GINT_TO_POINTER (GDK_WINDOW_EDGE_NORTH));
3062
3063       /* North east */
3064       area = gtk_drawing_area_new ();
3065       gtk_widget_add_events (area, GDK_BUTTON_PRESS_MASK);
3066       gtk_box_pack_start (GTK_BOX (hbox), area, TRUE, TRUE, 0);
3067       g_signal_connect (area, "expose_event", G_CALLBACK (grippy_expose),
3068                         GINT_TO_POINTER (GDK_WINDOW_EDGE_NORTH_EAST));
3069       g_signal_connect (area, "button_press_event", G_CALLBACK (grippy_button_press),
3070                         GINT_TO_POINTER (GDK_WINDOW_EDGE_NORTH_EAST));
3071
3072       hbox = gtk_hbox_new (FALSE, 0);
3073       gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);
3074
3075       /* West */
3076       area = gtk_drawing_area_new ();
3077       gtk_widget_add_events (area, GDK_BUTTON_PRESS_MASK);
3078       gtk_box_pack_start (GTK_BOX (hbox), area, TRUE, TRUE, 0);
3079       g_signal_connect (area, "expose_event", G_CALLBACK (grippy_expose),
3080                         GINT_TO_POINTER (GDK_WINDOW_EDGE_WEST));
3081       g_signal_connect (area, "button_press_event", G_CALLBACK (grippy_button_press),
3082                         GINT_TO_POINTER (GDK_WINDOW_EDGE_WEST));
3083
3084       /* Middle */
3085       area = gtk_drawing_area_new ();
3086       gtk_box_pack_start (GTK_BOX (hbox), area, TRUE, TRUE, 0);
3087
3088       /* East */
3089       area = gtk_drawing_area_new ();
3090       gtk_widget_add_events (area, GDK_BUTTON_PRESS_MASK);
3091       gtk_box_pack_start (GTK_BOX (hbox), area, TRUE, TRUE, 0);
3092       g_signal_connect (area, "expose_event", G_CALLBACK (grippy_expose),
3093                         GINT_TO_POINTER (GDK_WINDOW_EDGE_EAST));
3094       g_signal_connect (area, "button_press_event", G_CALLBACK (grippy_button_press),
3095                         GINT_TO_POINTER (GDK_WINDOW_EDGE_EAST));
3096
3097
3098       hbox = gtk_hbox_new (FALSE, 0);
3099       gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);
3100
3101       /* South west */
3102       area = gtk_drawing_area_new ();
3103       gtk_widget_add_events (area, GDK_BUTTON_PRESS_MASK);
3104       gtk_box_pack_start (GTK_BOX (hbox), area, TRUE, TRUE, 0);
3105       g_signal_connect (area, "expose_event", G_CALLBACK (grippy_expose),
3106                         GINT_TO_POINTER (GDK_WINDOW_EDGE_SOUTH_WEST));
3107       g_signal_connect (area, "button_press_event", G_CALLBACK (grippy_button_press),
3108                         GINT_TO_POINTER (GDK_WINDOW_EDGE_SOUTH_WEST));
3109       /* South */
3110       area = gtk_drawing_area_new ();
3111       gtk_widget_add_events (area, GDK_BUTTON_PRESS_MASK);
3112       gtk_box_pack_start (GTK_BOX (hbox), area, TRUE, TRUE, 0);
3113       g_signal_connect (area, "expose_event", G_CALLBACK (grippy_expose),
3114                         GINT_TO_POINTER (GDK_WINDOW_EDGE_SOUTH));
3115       g_signal_connect (area, "button_press_event", G_CALLBACK (grippy_button_press),
3116                         GINT_TO_POINTER (GDK_WINDOW_EDGE_SOUTH));
3117       
3118       /* South east */
3119       area = gtk_drawing_area_new ();
3120       gtk_widget_add_events (area, GDK_BUTTON_PRESS_MASK);
3121       gtk_box_pack_start (GTK_BOX (hbox), area, TRUE, TRUE, 0);
3122       g_signal_connect (area, "expose_event", G_CALLBACK (grippy_expose),
3123                         GINT_TO_POINTER (GDK_WINDOW_EDGE_SOUTH_EAST));
3124       g_signal_connect (area, "button_press_event", G_CALLBACK (grippy_button_press),
3125                         GINT_TO_POINTER (GDK_WINDOW_EDGE_SOUTH_EAST));
3126     }
3127
3128   if (!gtk_widget_get_visible (window))
3129     gtk_widget_show_all (window);
3130   else
3131     gtk_widget_destroy (window);
3132 }
3133
3134 /*
3135  * Saved Position
3136  */
3137 gint upositionx = 0;
3138 gint upositiony = 0;
3139
3140 static gint
3141 uposition_configure (GtkWidget *window)
3142 {
3143   GtkLabel *lx;
3144   GtkLabel *ly;
3145   gchar buffer[64];
3146
3147   lx = g_object_get_data (G_OBJECT (window), "x");
3148   ly = g_object_get_data (G_OBJECT (window), "y");
3149
3150   gdk_window_get_root_origin (window->window, &upositionx, &upositiony);
3151   sprintf (buffer, "%d", upositionx);
3152   gtk_label_set_text (lx, buffer);
3153   sprintf (buffer, "%d", upositiony);
3154   gtk_label_set_text (ly, buffer);
3155
3156   return FALSE;
3157 }
3158
3159 static void
3160 uposition_stop_configure (GtkToggleButton *toggle,
3161                           GtkObject       *window)
3162 {
3163   if (toggle->active)
3164     g_signal_handlers_block_by_func (window, G_CALLBACK (uposition_configure), NULL);
3165   else
3166     g_signal_handlers_unblock_by_func (window, G_CALLBACK (uposition_configure), NULL);
3167 }
3168
3169 static void
3170 create_saved_position (GtkWidget *widget)
3171 {
3172   static GtkWidget *window = NULL;
3173
3174   if (!window)
3175     {
3176       GtkWidget *hbox;
3177       GtkWidget *main_vbox;
3178       GtkWidget *vbox;
3179       GtkWidget *x_label;
3180       GtkWidget *y_label;
3181       GtkWidget *button;
3182       GtkWidget *label;
3183       GtkWidget *any;
3184
3185       window = g_object_connect (g_object_new (GTK_TYPE_WINDOW,
3186                                                  "type", GTK_WINDOW_TOPLEVEL,
3187                                                  "title", "Saved Position",
3188                                                  NULL),
3189                                  "signal::configure_event", uposition_configure, NULL,
3190                                  NULL);
3191
3192       gtk_window_move (GTK_WINDOW (window), upositionx, upositiony);
3193
3194       gtk_window_set_screen (GTK_WINDOW (window),
3195                              gtk_widget_get_screen (widget));
3196       
3197
3198       g_signal_connect (window, "destroy",
3199                         G_CALLBACK (gtk_widget_destroyed),
3200                         &window);
3201
3202       main_vbox = gtk_vbox_new (FALSE, 5);
3203       gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 0);
3204       gtk_container_add (GTK_CONTAINER (window), main_vbox);
3205
3206       vbox =
3207         g_object_new (gtk_vbox_get_type (),
3208                         "GtkBox::homogeneous", FALSE,
3209                         "GtkBox::spacing", 5,
3210                         "GtkContainer::border_width", 10,
3211                         "GtkWidget::parent", main_vbox,
3212                         "GtkWidget::visible", TRUE,
3213                         "child", g_object_connect (g_object_new (GTK_TYPE_TOGGLE_BUTTON,
3214                                                                    "label", "Stop Events",
3215                                                                    "active", FALSE,
3216                                                                    "visible", TRUE,
3217                                                                    NULL),
3218                                                    "signal::clicked", uposition_stop_configure, window,
3219                                                    NULL),
3220                         NULL);
3221
3222       hbox = gtk_hbox_new (FALSE, 0);
3223       gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
3224       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
3225
3226       label = gtk_label_new ("X Origin : ");
3227       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
3228       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
3229
3230       x_label = gtk_label_new ("");
3231       gtk_box_pack_start (GTK_BOX (hbox), x_label, TRUE, TRUE, 0);
3232       g_object_set_data (G_OBJECT (window), "x", x_label);
3233
3234       hbox = gtk_hbox_new (FALSE, 0);
3235       gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
3236       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
3237
3238       label = gtk_label_new ("Y Origin : ");
3239       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
3240       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
3241
3242       y_label = gtk_label_new ("");
3243       gtk_box_pack_start (GTK_BOX (hbox), y_label, TRUE, TRUE, 0);
3244       g_object_set_data (G_OBJECT (window), "y", y_label);
3245
3246       any =
3247         g_object_new (gtk_hseparator_get_type (),
3248                         "GtkWidget::visible", TRUE,
3249                         NULL);
3250       gtk_box_pack_start (GTK_BOX (main_vbox), any, FALSE, TRUE, 0);
3251
3252       hbox = gtk_hbox_new (FALSE, 0);
3253       gtk_container_set_border_width (GTK_CONTAINER (hbox), 10);
3254       gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, TRUE, 0);
3255
3256       button = gtk_button_new_with_label ("Close");
3257       g_signal_connect_swapped (button, "clicked",
3258                                 G_CALLBACK (gtk_widget_destroy),
3259                                 window);
3260       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
3261       gtk_widget_set_can_default (button, TRUE);
3262       gtk_widget_grab_default (button);
3263       
3264       gtk_widget_show_all (window);
3265     }
3266   else
3267     gtk_widget_destroy (window);
3268 }
3269
3270 /*
3271  * GtkPixmap
3272  */
3273
3274 static void
3275 create_pixmap (GtkWidget *widget)
3276 {
3277   static GtkWidget *window = NULL;
3278   GtkWidget *box1;
3279   GtkWidget *box2;
3280   GtkWidget *box3;
3281   GtkWidget *button;
3282   GtkWidget *label;
3283   GtkWidget *separator;
3284   GtkWidget *pixmapwid;
3285
3286   if (!window)
3287     {
3288       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3289
3290       gtk_window_set_screen (GTK_WINDOW (window),
3291                              gtk_widget_get_screen (widget));
3292
3293       g_signal_connect (window, "destroy",
3294                         G_CALLBACK (gtk_widget_destroyed),
3295                         &window);
3296
3297       gtk_window_set_title (GTK_WINDOW (window), "GtkPixmap");
3298       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
3299       gtk_widget_realize(window);
3300
3301       box1 = gtk_vbox_new (FALSE, 0);
3302       gtk_container_add (GTK_CONTAINER (window), box1);
3303
3304       box2 = gtk_vbox_new (FALSE, 10);
3305       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
3306       gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
3307
3308       button = gtk_button_new ();
3309       gtk_box_pack_start (GTK_BOX (box2), button, FALSE, FALSE, 0);
3310
3311       pixmapwid = new_pixmap ("test.xpm", window->window, NULL);
3312
3313       label = gtk_label_new ("Pixmap\ntest");
3314       box3 = gtk_hbox_new (FALSE, 0);
3315       gtk_container_set_border_width (GTK_CONTAINER (box3), 2);
3316       gtk_container_add (GTK_CONTAINER (box3), pixmapwid);
3317       gtk_container_add (GTK_CONTAINER (box3), label);
3318       gtk_container_add (GTK_CONTAINER (button), box3);
3319
3320       button = gtk_button_new ();
3321       gtk_box_pack_start (GTK_BOX (box2), button, FALSE, FALSE, 0);
3322       
3323       pixmapwid = new_pixmap ("test.xpm", window->window, NULL);
3324
3325       label = gtk_label_new ("Pixmap\ntest");
3326       box3 = gtk_hbox_new (FALSE, 0);
3327       gtk_container_set_border_width (GTK_CONTAINER (box3), 2);
3328       gtk_container_add (GTK_CONTAINER (box3), pixmapwid);
3329       gtk_container_add (GTK_CONTAINER (box3), label);
3330       gtk_container_add (GTK_CONTAINER (button), box3);
3331
3332       gtk_widget_set_sensitive (button, FALSE);
3333       
3334       separator = gtk_hseparator_new ();
3335       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
3336
3337       box2 = gtk_vbox_new (FALSE, 10);
3338       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
3339       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
3340
3341       button = gtk_button_new_with_label ("close");
3342       g_signal_connect_swapped (button, "clicked",
3343                                 G_CALLBACK (gtk_widget_destroy),
3344                                 window);
3345       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
3346       gtk_widget_set_can_default (button, TRUE);
3347       gtk_widget_grab_default (button);
3348     }
3349
3350   if (!gtk_widget_get_visible (window))
3351     gtk_widget_show_all (window);
3352   else
3353     gtk_widget_destroy (window);
3354 }
3355
3356 static void
3357 create_tooltips (GtkWidget *widget)
3358 {
3359   static GtkWidget *window = NULL;
3360   GtkWidget *box1;
3361   GtkWidget *box2;
3362   GtkWidget *box3;
3363   GtkWidget *button;
3364   GtkWidget *toggle;
3365   GtkWidget *frame;
3366   GtkWidget *separator;
3367
3368   if (!window)
3369     {
3370       window =
3371         g_object_new (gtk_window_get_type (),
3372                         "GtkWindow::type", GTK_WINDOW_TOPLEVEL,
3373                         "GtkContainer::border_width", 0,
3374                         "GtkWindow::title", "Tooltips",
3375                         "GtkWindow::allow_shrink", TRUE,
3376                         "GtkWindow::allow_grow", FALSE,
3377                         NULL);
3378
3379       gtk_window_set_screen (GTK_WINDOW (window),
3380                              gtk_widget_get_screen (widget));
3381
3382       box1 = gtk_vbox_new (FALSE, 0);
3383       gtk_container_add (GTK_CONTAINER (window), box1);
3384
3385       box2 = gtk_vbox_new (FALSE, 10);
3386       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
3387       gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
3388
3389       button = gtk_toggle_button_new_with_label ("button1");
3390       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
3391
3392       gtk_widget_set_tooltip_text (button, "This is button 1");
3393
3394       button = gtk_toggle_button_new_with_label ("button2");
3395       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
3396
3397       gtk_widget_set_tooltip_text (button,
3398         "This is button 2. This is also a really long tooltip which probably "
3399         "won't fit on a single line and will therefore need to be wrapped. "
3400         "Hopefully the wrapping will work correctly.");
3401
3402       toggle = gtk_toggle_button_new_with_label ("Override TipsQuery Label");
3403       gtk_box_pack_start (GTK_BOX (box2), toggle, TRUE, TRUE, 0);
3404
3405       gtk_widget_set_tooltip_text (toggle, "Toggle TipsQuery view.");
3406
3407       box3 =
3408         g_object_new (gtk_vbox_get_type (),
3409                         "homogeneous", FALSE,
3410                         "spacing", 5,
3411                         "border_width", 5,
3412                         "visible", TRUE,
3413                         NULL);
3414
3415       button =
3416         g_object_new (gtk_button_get_type (),
3417                         "label", "[?]",
3418                         "visible", TRUE,
3419                         "parent", box3,
3420                         NULL);
3421       gtk_box_set_child_packing (GTK_BOX (box3), button, FALSE, FALSE, 0, GTK_PACK_START);
3422       gtk_widget_set_tooltip_text (button, "Start the Tooltips Inspector");
3423       
3424       frame = g_object_new (gtk_frame_get_type (),
3425                               "label", "ToolTips Inspector",
3426                               "label_xalign", (double) 0.5,
3427                               "border_width", 0,
3428                               "visible", TRUE,
3429                               "parent", box2,
3430                               "child", box3,
3431                               NULL);
3432       gtk_box_set_child_packing (GTK_BOX (box2), frame, TRUE, TRUE, 10, GTK_PACK_START);
3433
3434       separator = gtk_hseparator_new ();
3435       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
3436
3437       box2 = gtk_vbox_new (FALSE, 10);
3438       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
3439       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
3440
3441       button = gtk_button_new_with_label ("close");
3442       g_signal_connect_swapped (button, "clicked",
3443                                 G_CALLBACK (gtk_widget_destroy),
3444                                 window);
3445       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
3446       gtk_widget_set_can_default (button, TRUE);
3447       gtk_widget_grab_default (button);
3448
3449       gtk_widget_set_tooltip_text (button, "Push this button to close window");
3450     }
3451
3452   if (!gtk_widget_get_visible (window))
3453     gtk_widget_show_all (window);
3454   else
3455     gtk_widget_destroy (window);
3456 }
3457
3458 /*
3459  * GtkImage
3460  */
3461
3462 static void
3463 pack_image (GtkWidget *box,
3464             const gchar *text,
3465             GtkWidget *image)
3466 {
3467   gtk_box_pack_start (GTK_BOX (box),
3468                       gtk_label_new (text),
3469                       FALSE, FALSE, 0);
3470
3471   gtk_box_pack_start (GTK_BOX (box),
3472                       image,
3473                       TRUE, TRUE, 0);  
3474 }
3475
3476 static void
3477 create_image (GtkWidget *widget)
3478 {
3479   static GtkWidget *window = NULL;
3480
3481   if (window == NULL)
3482     {
3483       GtkWidget *vbox;
3484       GdkPixmap *pixmap;
3485       GdkBitmap *mask;
3486         
3487       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3488       
3489       gtk_window_set_screen (GTK_WINDOW (window),
3490                              gtk_widget_get_screen (widget));
3491
3492       /* this is bogus for testing drawing when allocation < request,
3493        * don't copy into real code
3494        */
3495       g_object_set (window, "allow_shrink", TRUE, "allow_grow", TRUE, NULL);
3496       
3497       g_signal_connect (window, "destroy",
3498                         G_CALLBACK (gtk_widget_destroyed),
3499                         &window);
3500
3501       vbox = gtk_vbox_new (FALSE, 5);
3502
3503       gtk_container_add (GTK_CONTAINER (window), vbox);
3504
3505       pack_image (vbox, "Stock Warning Dialog",
3506                   gtk_image_new_from_stock (GTK_STOCK_DIALOG_WARNING,
3507                                             GTK_ICON_SIZE_DIALOG));
3508
3509       pixmap = gdk_pixmap_colormap_create_from_xpm_d (NULL,
3510                                                       gtk_widget_get_colormap (window),
3511                                                       &mask,
3512                                                       NULL,
3513                                                       openfile);
3514       
3515       pack_image (vbox, "Pixmap",
3516                   gtk_image_new_from_pixmap (pixmap, mask));
3517     }
3518
3519   if (!gtk_widget_get_visible (window))
3520     gtk_widget_show_all (window);
3521   else
3522     gtk_widget_destroy (window);
3523 }
3524      
3525 /*
3526  * Menu demo
3527  */
3528
3529 static GtkWidget*
3530 create_menu (GdkScreen *screen, gint depth, gint length, gboolean tearoff)
3531 {
3532   GtkWidget *menu;
3533   GtkWidget *menuitem;
3534   GtkWidget *image;
3535   GSList *group;
3536   char buf[32];
3537   int i, j;
3538
3539   if (depth < 1)
3540     return NULL;
3541
3542   menu = gtk_menu_new ();
3543   gtk_menu_set_screen (GTK_MENU (menu), screen);
3544
3545   group = NULL;
3546
3547   if (tearoff)
3548     {
3549       menuitem = gtk_tearoff_menu_item_new ();
3550       gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
3551       gtk_widget_show (menuitem);
3552     }
3553
3554   image = gtk_image_new_from_stock (GTK_STOCK_OPEN,
3555                                     GTK_ICON_SIZE_MENU);
3556   gtk_widget_show (image);
3557   menuitem = gtk_image_menu_item_new_with_label ("Image item");
3558   gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), image);
3559   gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
3560   gtk_widget_show (menuitem);
3561   
3562   for (i = 0, j = 1; i < length; i++, j++)
3563     {
3564       sprintf (buf, "item %2d - %d", depth, j);
3565
3566       menuitem = gtk_radio_menu_item_new_with_label (group, buf);
3567       group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (menuitem));
3568
3569       gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
3570       gtk_widget_show (menuitem);
3571       if (i == 3)
3572         gtk_widget_set_sensitive (menuitem, FALSE);
3573
3574       if (i == 5)
3575         gtk_check_menu_item_set_inconsistent (GTK_CHECK_MENU_ITEM (menuitem),
3576                                               TRUE);
3577
3578       if (i < 5)
3579         gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), 
3580                                    create_menu (screen, depth - 1, 5,  TRUE));
3581     }
3582
3583   return menu;
3584 }
3585
3586 static GtkWidget*
3587 create_table_menu (GdkScreen *screen, gint cols, gint rows, gboolean tearoff)
3588 {
3589   GtkWidget *menu;
3590   GtkWidget *menuitem;
3591   GtkWidget *submenu;
3592   GtkWidget *image;
3593   char buf[32];
3594   int i, j;
3595
3596   menu = gtk_menu_new ();
3597   gtk_menu_set_screen (GTK_MENU (menu), screen);
3598
3599   j = 0;
3600   if (tearoff)
3601     {
3602       menuitem = gtk_tearoff_menu_item_new ();
3603       gtk_menu_attach (GTK_MENU (menu), menuitem, 0, cols, j, j + 1);
3604       gtk_widget_show (menuitem);
3605       j++;
3606     }
3607   
3608   menuitem = gtk_menu_item_new_with_label ("items");
3609   gtk_menu_attach (GTK_MENU (menu), menuitem, 0, cols, j, j + 1);
3610
3611   submenu = gtk_menu_new ();
3612   gtk_menu_set_screen (GTK_MENU (submenu), screen);
3613   gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), submenu);
3614   gtk_widget_show (menuitem);
3615   j++;
3616
3617   /* now fill the items submenu */
3618   image = gtk_image_new_from_stock (GTK_STOCK_HELP,
3619                                     GTK_ICON_SIZE_MENU);
3620   gtk_widget_show (image);
3621   menuitem = gtk_image_menu_item_new_with_label ("Image");
3622   gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), image);
3623   gtk_menu_attach (GTK_MENU (submenu), menuitem, 0, 1, 0, 1);
3624   gtk_widget_show (menuitem);
3625
3626   menuitem = gtk_menu_item_new_with_label ("x");
3627   gtk_menu_attach (GTK_MENU (submenu), menuitem, 1, 2, 0, 1);
3628   gtk_widget_show (menuitem);
3629
3630   menuitem = gtk_menu_item_new_with_label ("x");
3631   gtk_menu_attach (GTK_MENU (submenu), menuitem, 0, 1, 1, 2);
3632   gtk_widget_show (menuitem);
3633   
3634   image = gtk_image_new_from_stock (GTK_STOCK_HELP,
3635                                     GTK_ICON_SIZE_MENU);
3636   gtk_widget_show (image);
3637   menuitem = gtk_image_menu_item_new_with_label ("Image");
3638   gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), image);
3639   gtk_menu_attach (GTK_MENU (submenu), menuitem, 1, 2, 1, 2);
3640   gtk_widget_show (menuitem);
3641
3642   menuitem = gtk_radio_menu_item_new_with_label (NULL, "Radio");
3643   gtk_menu_attach (GTK_MENU (submenu), menuitem, 0, 1, 2, 3);
3644   gtk_widget_show (menuitem);
3645
3646   menuitem = gtk_menu_item_new_with_label ("x");
3647   gtk_menu_attach (GTK_MENU (submenu), menuitem, 1, 2, 2, 3);
3648   gtk_widget_show (menuitem);
3649
3650   menuitem = gtk_menu_item_new_with_label ("x");
3651   gtk_menu_attach (GTK_MENU (submenu), menuitem, 0, 1, 3, 4);
3652   gtk_widget_show (menuitem);
3653   
3654   menuitem = gtk_radio_menu_item_new_with_label (NULL, "Radio");
3655   gtk_menu_attach (GTK_MENU (submenu), menuitem, 1, 2, 3, 4);
3656   gtk_widget_show (menuitem);
3657
3658   menuitem = gtk_check_menu_item_new_with_label ("Check");
3659   gtk_menu_attach (GTK_MENU (submenu), menuitem, 0, 1, 4, 5);
3660   gtk_widget_show (menuitem);
3661
3662   menuitem = gtk_menu_item_new_with_label ("x");
3663   gtk_menu_attach (GTK_MENU (submenu), menuitem, 1, 2, 4, 5);
3664   gtk_widget_show (menuitem);
3665
3666   menuitem = gtk_menu_item_new_with_label ("x");
3667   gtk_menu_attach (GTK_MENU (submenu), menuitem, 0, 1, 5, 6);
3668   gtk_widget_show (menuitem);
3669   
3670   menuitem = gtk_check_menu_item_new_with_label ("Check");
3671   gtk_menu_attach (GTK_MENU (submenu), menuitem, 1, 2, 5, 6);
3672   gtk_widget_show (menuitem);
3673
3674   menuitem = gtk_menu_item_new_with_label ("1. Inserted normally (8)");
3675   gtk_widget_show (menuitem);
3676   gtk_menu_shell_insert (GTK_MENU_SHELL (submenu), menuitem, 8);
3677
3678   menuitem = gtk_menu_item_new_with_label ("2. Inserted normally (2)");
3679   gtk_widget_show (menuitem);
3680   gtk_menu_shell_insert (GTK_MENU_SHELL (submenu), menuitem, 2);
3681
3682   menuitem = gtk_menu_item_new_with_label ("3. Inserted normally (0)");
3683   gtk_widget_show (menuitem);
3684   gtk_menu_shell_insert (GTK_MENU_SHELL (submenu), menuitem, 0);
3685
3686   menuitem = gtk_menu_item_new_with_label ("4. Inserted normally (-1)");
3687   gtk_widget_show (menuitem);
3688   gtk_menu_shell_insert (GTK_MENU_SHELL (submenu), menuitem, -1);
3689   
3690   /* end of items submenu */
3691
3692   menuitem = gtk_menu_item_new_with_label ("spanning");
3693   gtk_menu_attach (GTK_MENU (menu), menuitem, 0, cols, j, j + 1);
3694
3695   submenu = gtk_menu_new ();
3696   gtk_menu_set_screen (GTK_MENU (submenu), screen);
3697   gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), submenu);
3698   gtk_widget_show (menuitem);
3699   j++;
3700
3701   /* now fill the spanning submenu */
3702   menuitem = gtk_menu_item_new_with_label ("a");
3703   gtk_menu_attach (GTK_MENU (submenu), menuitem, 0, 2, 0, 1);
3704   gtk_widget_show (menuitem);
3705
3706   menuitem = gtk_menu_item_new_with_label ("b");
3707   gtk_menu_attach (GTK_MENU (submenu), menuitem, 2, 3, 0, 2);
3708   gtk_widget_show (menuitem);
3709
3710   menuitem = gtk_menu_item_new_with_label ("c");
3711   gtk_menu_attach (GTK_MENU (submenu), menuitem, 0, 1, 1, 3);
3712   gtk_widget_show (menuitem);
3713
3714   menuitem = gtk_menu_item_new_with_label ("d");
3715   gtk_menu_attach (GTK_MENU (submenu), menuitem, 1, 2, 1, 2);
3716   gtk_widget_show (menuitem);
3717
3718   menuitem = gtk_menu_item_new_with_label ("e");
3719   gtk_menu_attach (GTK_MENU (submenu), menuitem, 1, 3, 2, 3);
3720   gtk_widget_show (menuitem);
3721   /* end of spanning submenu */
3722   
3723   menuitem = gtk_menu_item_new_with_label ("left");
3724   gtk_menu_attach (GTK_MENU (menu), menuitem, 0, 1, j, j + 1);
3725   submenu = gtk_menu_new ();
3726   gtk_menu_set_screen (GTK_MENU (submenu), screen);
3727   gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), submenu);
3728   gtk_widget_show (menuitem);
3729
3730   menuitem = gtk_menu_item_new_with_label ("Empty");
3731   gtk_menu_attach (GTK_MENU (submenu), menuitem, 0, 1, 0, 1);
3732   submenu = gtk_menu_new ();
3733   gtk_menu_set_screen (GTK_MENU (submenu), screen);
3734   gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), submenu);
3735   gtk_widget_show (menuitem);
3736
3737   menuitem = gtk_menu_item_new_with_label ("right");
3738   gtk_menu_attach (GTK_MENU (menu), menuitem, 1, 2, j, j + 1);
3739   submenu = gtk_menu_new ();
3740   gtk_menu_set_screen (GTK_MENU (submenu), screen);
3741   gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), submenu);
3742   gtk_widget_show (menuitem);
3743
3744   menuitem = gtk_menu_item_new_with_label ("Empty");
3745   gtk_menu_attach (GTK_MENU (submenu), menuitem, 0, 1, 0, 1);
3746   gtk_widget_show (menuitem);
3747
3748   j++;
3749
3750   for (; j < rows; j++)
3751       for (i = 0; i < cols; i++)
3752       {
3753         sprintf (buf, "(%d %d)", i, j);
3754         menuitem = gtk_menu_item_new_with_label (buf);
3755         gtk_menu_attach (GTK_MENU (menu), menuitem, i, i + 1, j, j + 1);
3756         gtk_widget_show (menuitem);
3757       }
3758   
3759   menuitem = gtk_menu_item_new_with_label ("1. Inserted normally (8)");
3760   gtk_menu_shell_insert (GTK_MENU_SHELL (menu), menuitem, 8);
3761   gtk_widget_show (menuitem);
3762   menuitem = gtk_menu_item_new_with_label ("2. Inserted normally (2)");
3763   gtk_menu_shell_insert (GTK_MENU_SHELL (menu), menuitem, 2);
3764   gtk_widget_show (menuitem);
3765   menuitem = gtk_menu_item_new_with_label ("3. Inserted normally (0)");
3766   gtk_menu_shell_insert (GTK_MENU_SHELL (menu), menuitem, 0);
3767   gtk_widget_show (menuitem);
3768   menuitem = gtk_menu_item_new_with_label ("4. Inserted normally (-1)");
3769   gtk_menu_shell_insert (GTK_MENU_SHELL (menu), menuitem, -1);
3770   gtk_widget_show (menuitem);
3771   
3772   return menu;
3773 }
3774
3775 static void
3776 create_menus (GtkWidget *widget)
3777 {
3778   static GtkWidget *window = NULL;
3779   GtkWidget *box1;
3780   GtkWidget *box2;
3781   GtkWidget *button;
3782   GtkWidget *optionmenu;
3783   GtkWidget *separator;
3784   
3785   if (!window)
3786     {
3787       GtkWidget *menubar;
3788       GtkWidget *menu;
3789       GtkWidget *menuitem;
3790       GtkAccelGroup *accel_group;
3791       GtkWidget *image;
3792       GdkScreen *screen = gtk_widget_get_screen (widget);
3793       
3794       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3795
3796       gtk_window_set_screen (GTK_WINDOW (window), screen);
3797       
3798       g_signal_connect (window, "destroy",
3799                         G_CALLBACK (gtk_widget_destroyed),
3800                         &window);
3801       g_signal_connect (window, "delete-event",
3802                         G_CALLBACK (gtk_true),
3803                         NULL);
3804       
3805       accel_group = gtk_accel_group_new ();
3806       gtk_window_add_accel_group (GTK_WINDOW (window), accel_group);
3807
3808       gtk_window_set_title (GTK_WINDOW (window), "menus");
3809       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
3810       
3811       
3812       box1 = gtk_vbox_new (FALSE, 0);
3813       gtk_container_add (GTK_CONTAINER (window), box1);
3814       gtk_widget_show (box1);
3815       
3816       menubar = gtk_menu_bar_new ();
3817       gtk_box_pack_start (GTK_BOX (box1), menubar, FALSE, TRUE, 0);
3818       gtk_widget_show (menubar);
3819       
3820       menu = create_menu (screen, 2, 50, TRUE);
3821       
3822       menuitem = gtk_menu_item_new_with_label ("test\nline2");
3823       gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), menu);
3824       gtk_menu_shell_append (GTK_MENU_SHELL (menubar), menuitem);
3825       gtk_widget_show (menuitem);
3826
3827       menu = create_table_menu (screen, 2, 50, TRUE);
3828       
3829       menuitem = gtk_menu_item_new_with_label ("table");
3830       gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), menu);
3831       gtk_menu_shell_append (GTK_MENU_SHELL (menubar), menuitem);
3832       gtk_widget_show (menuitem);
3833       
3834       menuitem = gtk_menu_item_new_with_label ("foo");
3835       gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), create_menu (screen, 3, 5, TRUE));
3836       gtk_menu_shell_append (GTK_MENU_SHELL (menubar), menuitem);
3837       gtk_widget_show (menuitem);
3838
3839       image = gtk_image_new_from_stock (GTK_STOCK_HELP,
3840                                         GTK_ICON_SIZE_MENU);
3841       gtk_widget_show (image);
3842       menuitem = gtk_image_menu_item_new_with_label ("Help");
3843       gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), image);
3844       gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), create_menu (screen, 4, 5, TRUE));
3845       gtk_menu_item_set_right_justified (GTK_MENU_ITEM (menuitem), TRUE);
3846       gtk_menu_shell_append (GTK_MENU_SHELL (menubar), menuitem);
3847       gtk_widget_show (menuitem);
3848       
3849       menubar = gtk_menu_bar_new ();
3850       gtk_box_pack_start (GTK_BOX (box1), menubar, FALSE, TRUE, 0);
3851       gtk_widget_show (menubar);
3852       
3853       menu = create_menu (screen, 2, 10, TRUE);
3854       
3855       menuitem = gtk_menu_item_new_with_label ("Second menu bar");
3856       gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), menu);
3857       gtk_menu_shell_append (GTK_MENU_SHELL (menubar), menuitem);
3858       gtk_widget_show (menuitem);
3859       
3860       box2 = gtk_vbox_new (FALSE, 10);
3861       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
3862       gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
3863       gtk_widget_show (box2);
3864       
3865       menu = create_menu (screen, 1, 5, FALSE);
3866       gtk_menu_set_accel_group (GTK_MENU (menu), accel_group);
3867
3868       menuitem = gtk_image_menu_item_new_from_stock (GTK_STOCK_NEW, accel_group);
3869       gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
3870       gtk_widget_show (menuitem);
3871       
3872       menuitem = gtk_check_menu_item_new_with_label ("Accelerate Me");
3873       gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
3874       gtk_widget_show (menuitem);
3875       gtk_widget_add_accelerator (menuitem,
3876                                   "activate",
3877                                   accel_group,
3878                                   GDK_F1,
3879                                   0,
3880                                   GTK_ACCEL_VISIBLE);
3881       menuitem = gtk_check_menu_item_new_with_label ("Accelerator Locked");
3882       gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
3883       gtk_widget_show (menuitem);
3884       gtk_widget_add_accelerator (menuitem,
3885                                   "activate",
3886                                   accel_group,
3887                                   GDK_F2,
3888                                   0,
3889                                   GTK_ACCEL_VISIBLE | GTK_ACCEL_LOCKED);
3890       menuitem = gtk_check_menu_item_new_with_label ("Accelerators Frozen");
3891       gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
3892       gtk_widget_show (menuitem);
3893       gtk_widget_add_accelerator (menuitem,
3894                                   "activate",
3895                                   accel_group,
3896                                   GDK_F2,
3897                                   0,
3898                                   GTK_ACCEL_VISIBLE);
3899       gtk_widget_add_accelerator (menuitem,
3900                                   "activate",
3901                                   accel_group,
3902                                   GDK_F3,
3903                                   0,
3904                                   GTK_ACCEL_VISIBLE);
3905       
3906       optionmenu = gtk_combo_box_new_text ();
3907       gtk_combo_box_set_active (GTK_COMBO_BOX (optionmenu), 3);
3908       gtk_box_pack_start (GTK_BOX (box2), optionmenu, TRUE, TRUE, 0);
3909       gtk_widget_show (optionmenu);
3910
3911       separator = gtk_hseparator_new ();
3912       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
3913       gtk_widget_show (separator);
3914
3915       box2 = gtk_vbox_new (FALSE, 10);
3916       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
3917       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
3918       gtk_widget_show (box2);
3919
3920       button = gtk_button_new_with_label ("close");
3921       g_signal_connect_swapped (button, "clicked",
3922                                 G_CALLBACK (gtk_widget_destroy),
3923                                 window);
3924       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
3925       gtk_widget_set_can_default (button, TRUE);
3926       gtk_widget_grab_default (button);
3927       gtk_widget_show (button);
3928     }
3929
3930   if (!gtk_widget_get_visible (window))
3931     gtk_widget_show (window);
3932   else
3933     gtk_widget_destroy (window);
3934 }
3935
3936 /* GdkPixbuf RGBA C-Source image dump */
3937
3938 static const guint8 apple[] = 
3939 { ""
3940   /* Pixbuf magic (0x47646b50) */
3941   "GdkP"
3942   /* length: header (24) + pixel_data (2304) */
3943   "\0\0\11\30"
3944   /* pixdata_type (0x1010002) */
3945   "\1\1\0\2"
3946   /* rowstride (96) */
3947   "\0\0\0`"
3948   /* width (24) */
3949   "\0\0\0\30"
3950   /* height (24) */
3951   "\0\0\0\30"
3952   /* pixel_data: */
3953   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
3954   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
3955   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
3956   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
3957   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
3958   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
3959   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\26\24"
3960   "\17\11\0\0\0\2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
3961   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`m"
3962   "[pn{a\344hv_\345_k[`\0\0\0\0\0\0\0\0\0\0\0\0D>/\305\0\0\0_\0\0\0\0\0"
3963   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
3964   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`l[Blza\373s\202d\354w\206g\372p~c"
3965   "\374`l[y\0\0\0\0[S\77/\27\25\17\335\0\0\0\20\0\0\0\0\0\0\0\0\0\0\0\0"
3966   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
3967   "\0\0\0\0\0\0`l\\\20iw_\356y\211h\373x\207g\364~\216i\364u\204e\366gt"
3968   "_\374^jX\241A;-_\0\0\0~\0\0\0\0SM4)SM21B9&\22\320\270\204\1\320\270\204"
3969   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0eq"
3970   "]\212r\200c\366v\205f\371jx_\323_kY\232_kZH^jY\26]iW\211@G9\272:6%j\220"
3971   "\211]\320\221\211`\377\212\203Z\377~xP\377mkE\331]^;|/0\37\21\0\0\0\0"
3972   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0ly`\40p~b\360lz`\353^kY\246["
3973   "eT<\216\200Z\203\227\211_\354\234\217c\377\232\217b\362\232\220c\337"
3974   "\243\233k\377\252\241p\377\250\236p\377\241\225h\377\231\214_\377\210"
3975   "\202U\377srI\377[]:\355KO0U\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0i"
3976   "v^\200`lY\211^jY\"\0\0\0\0\221\204\\\273\250\233r\377\302\267\224\377"
3977   "\311\300\237\377\272\256\204\377\271\256\177\377\271\257\200\377\267"
3978   "\260\177\377\260\251x\377\250\236l\377\242\225e\377\226\213]\377~zP\377"
3979   "ff@\377QT5\377LR2d\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0]iW(\0\0\0\0\0\0\0"
3980   "\0\213\203[v\253\240t\377\334\326\301\377\344\340\317\377\321\312\253"
3981   "\377\303\271\217\377\300\270\213\377\277\267\210\377\272\264\203\377"
3982   "\261\255z\377\250\242n\377\243\232h\377\232\220`\377\210\202V\377nnE"
3983   "\377SW6\377RX6\364Za<\34\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0b]@\20"
3984   "\234\222e\362\304\274\232\377\337\333\306\377\332\325\273\377\311\302"
3985   "\232\377\312\303\236\377\301\273\216\377\300\271\212\377\270\264\200"
3986   "\377\256\253v\377\246\243n\377\236\232h\377\230\220`\377\213\203V\377"
3987   "wvL\377X]:\377KR0\377NU5v\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\212"
3988   "\203Zl\242\234l\377\321\315\260\377\331\324\271\377\320\313\251\377\307"
3989   "\301\232\377\303\276\224\377\300\272\214\377\274\267\206\377\264\260"
3990   "|\377\253\251s\377\244\243n\377\232\230e\377\223\216^\377\207\200U\377"
3991   "ttJ\377[_<\377HO/\377GN0\200\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
3992   "\210\204Y\240\245\237o\377\316\310\253\377\310\303\237\377\304\300\230"
3993   "\377\303\277\225\377\277\272\216\377\274\270\210\377\266\263\200\377"
3994   "\256\254v\377\247\246p\377\237\236j\377\227\226d\377\215\212[\377\203"
3995   "\177T\377qsH\377X]8\377FN.\377DK-\200\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
3996   "\0\0\0\0\207\204X\257\244\240o\377\300\275\231\377\301\275\226\377\274"
3997   "\270\213\377\274\270\214\377\267\264\205\377\264\262\200\377\260\256"
3998   "z\377\251\251s\377\243\244n\377\231\232g\377\220\222`\377\210\211Y\377"
3999   "|}Q\377hlC\377PU3\377CK,\377DL/Y\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
4000   "\0\0\205\204X\220\232\230h\377\261\260\204\377\266\264\212\377\261\260"
4001   "\201\377\263\260\200\377\260\257}\377\256\256x\377\253\254t\377\244\246"
4002   "o\377\233\236i\377\221\224b\377\211\214\\\377\202\204V\377txM\377]b>"
4003   "\377HP0\377@H+\373CJ-\25\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0xxO>"
4004   "\215\215_\377\237\237r\377\247\247x\377\247\247t\377\252\252w\377\252"
4005   "\252u\377\252\253t\377\243\246o\377\235\240j\377\223\230c\377\213\217"
4006   "]\377\201\206V\377x}P\377gkD\377RY5\377BI,\377AI,\262\0\0\0\0\0\0\0\0"
4007   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\202\205W\312\216\220`\377\230"
4008   "\232g\377\234\236i\377\236\241l\377\241\244n\377\240\244m\377\232\237"
4009   "i\377\223\230c\377\212\221]\377\200\210W\377v|P\377jnG\377Za>\377HP2"
4010   "\377=D)\377HQ1:\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
4011   "\0wzQ6\177\201U\371\206\211Z\377\216\222`\377\220\225a\377\220\225b\377"
4012   "\220\226a\377\213\221_\377\204\213Z\377{\203R\377ryN\377iqH\377^fA\377"
4013   "R[;\377BJ-\3778@'\317\0\0\0>\0\0\0\36\0\0\0\7\0\0\0\0\0\0\0\0\0\0\0\0"
4014   "\0\0\0\0\0\0\0\0\0\0\0\0ptJTw|Q\371z\177R\377}\202T\377|\203T\377z\200"
4015   "R\377v|O\377pwL\377jpF\377dlB\377`hB\377Yb@\377LT6\377<C*\377\11\12\6"
4016   "\376\0\0\0\347\0\0\0\262\0\0\0Y\0\0\0\32\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
4017   "\0\0\0\0\0\0\0\0\0\0\\`=UgnE\370hnG\377gmE\377djB\377]d>\377[c<\377Y"
4018   "b<\377Zc>\377V_>\377OW8\377BK/\377\16\20\12\377\0\0\0\377\0\0\0\377\0"
4019   "\0\0\374\0\0\0\320\0\0\0I\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
4020   "\0\1\0\0\0\40\22\24\15\260@D+\377W`;\377OV5\377.3\36\377.3\37\377IP0"
4021   "\377RZ7\377PZ8\3776=&\377\14\15\10\377\0\0\0\377\0\0\0\377\0\0\0\377"
4022   "\0\0\0\347\0\0\0\217\0\0\0""4\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
4023   "\0\0\0\0\0\0\0\20\0\0\0P\0\0\0\252\7\10\5\346\7\7\5\375\0\0\0\377\0\0"
4024   "\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\377\0\0\0\374\0"
4025   "\0\0\336\0\0\0\254\0\0\0i\0\0\0""2\0\0\0\10\0\0\0\0\0\0\0\0\0\0\0\0\0"
4026   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\11\0\0\0\40\0\0\0D\0\0\0m\0\0\0"
4027   "\226\0\0\0\234\0\0\0\234\0\0\0\244\0\0\0\246\0\0\0\232\0\0\0\202\0\0"
4028   "\0i\0\0\0T\0\0\0,\0\0\0\15\0\0\0\2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
4029   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\2\0\0\0\6\0\0\0"
4030   "\16\0\0\0\22\0\0\0\24\0\0\0\23\0\0\0\17\0\0\0\14\0\0\0\13\0\0\0\10\0"
4031   "\0\0\5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"};
4032
4033
4034 static GtkWidget *
4035 accel_button_new (GtkAccelGroup *accel_group,
4036                   const gchar   *text,
4037                   const gchar   *accel)
4038 {
4039   guint keyval;
4040   GdkModifierType modifiers;
4041   GtkWidget *button;
4042   GtkWidget *label;
4043
4044   gtk_accelerator_parse (accel, &keyval, &modifiers);
4045   g_assert (keyval);
4046
4047   button = gtk_button_new ();
4048   gtk_widget_add_accelerator (button, "activate", accel_group,
4049                               keyval, modifiers, GTK_ACCEL_VISIBLE | GTK_ACCEL_LOCKED);
4050
4051   label = gtk_accel_label_new (text);
4052   gtk_accel_label_set_accel_widget (GTK_ACCEL_LABEL (label), button);
4053   gtk_widget_show (label);
4054   
4055   gtk_container_add (GTK_CONTAINER (button), label);
4056
4057   return button;
4058 }
4059
4060 static void
4061 create_key_lookup (GtkWidget *widget)
4062 {
4063   static GtkWidget *window = NULL;
4064   gpointer window_ptr;
4065
4066   if (!window)
4067     {
4068       GtkAccelGroup *accel_group = gtk_accel_group_new ();
4069       GtkWidget *button;
4070       
4071       window = gtk_dialog_new_with_buttons ("Key Lookup", NULL, 0,
4072                                             GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
4073                                             NULL);
4074
4075       gtk_window_set_screen (GTK_WINDOW (window),
4076                              gtk_widget_get_screen (widget));
4077
4078       /* We have to expand it so the accel labels will draw their labels
4079        */
4080       gtk_window_set_default_size (GTK_WINDOW (window), 300, -1);
4081       
4082       gtk_window_add_accel_group (GTK_WINDOW (window), accel_group);
4083       
4084       button = gtk_button_new_with_mnemonic ("Button 1 (_a)");
4085       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
4086       button = gtk_button_new_with_mnemonic ("Button 2 (_A)");
4087       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
4088       button = gtk_button_new_with_mnemonic ("Button 3 (_\321\204)");
4089       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
4090       button = gtk_button_new_with_mnemonic ("Button 4 (_\320\244)");
4091       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
4092       button = gtk_button_new_with_mnemonic ("Button 6 (_b)");
4093       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
4094       button = accel_button_new (accel_group, "Button 7", "<Alt><Shift>b");
4095       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
4096       button = accel_button_new (accel_group, "Button 8", "<Alt>d");
4097       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
4098       button = accel_button_new (accel_group, "Button 9", "<Alt>Cyrillic_ve");
4099       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
4100       button = gtk_button_new_with_mnemonic ("Button 10 (_1)");
4101       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
4102       button = gtk_button_new_with_mnemonic ("Button 11 (_!)");
4103       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
4104       button = accel_button_new (accel_group, "Button 12", "<Super>a");
4105       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
4106       button = accel_button_new (accel_group, "Button 13", "<Hyper>a");
4107       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
4108       button = accel_button_new (accel_group, "Button 14", "<Meta>a");
4109       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
4110       button = accel_button_new (accel_group, "Button 15", "<Shift><Mod4>b");
4111       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
4112
4113       window_ptr = &window;
4114       g_object_add_weak_pointer (G_OBJECT (window), window_ptr);
4115       g_signal_connect (window, "response", G_CALLBACK (gtk_object_destroy), NULL);
4116
4117       gtk_widget_show_all (window);
4118     }
4119   else
4120     gtk_widget_destroy (window);
4121 }
4122
4123
4124 /*
4125  create_modal_window
4126  */
4127
4128 static gboolean
4129 cmw_destroy_cb(GtkWidget *widget)
4130 {
4131   /* This is needed to get out of gtk_main */
4132   gtk_main_quit ();
4133
4134   return FALSE;
4135 }
4136
4137 static void
4138 cmw_color (GtkWidget *widget, GtkWidget *parent)
4139 {
4140     GtkWidget *csd;
4141
4142     csd = gtk_color_selection_dialog_new ("This is a modal color selection dialog");
4143
4144     gtk_window_set_screen (GTK_WINDOW (csd), gtk_widget_get_screen (parent));
4145
4146     gtk_color_selection_set_has_palette (GTK_COLOR_SELECTION (GTK_COLOR_SELECTION_DIALOG (csd)->colorsel),
4147                                          TRUE);
4148     
4149     /* Set as modal */
4150     gtk_window_set_modal (GTK_WINDOW(csd),TRUE);
4151
4152     /* And mark it as a transient dialog */
4153     gtk_window_set_transient_for (GTK_WINDOW (csd), GTK_WINDOW (parent));
4154     
4155     g_signal_connect (csd, "destroy",
4156                       G_CALLBACK (cmw_destroy_cb), NULL);
4157
4158     g_signal_connect_swapped (GTK_COLOR_SELECTION_DIALOG (csd)->ok_button,
4159                              "clicked", G_CALLBACK (gtk_widget_destroy), csd);
4160     g_signal_connect_swapped (GTK_COLOR_SELECTION_DIALOG (csd)->cancel_button,
4161                              "clicked", G_CALLBACK (gtk_widget_destroy), csd);
4162     
4163     /* wait until destroy calls gtk_main_quit */
4164     gtk_widget_show (csd);    
4165     gtk_main ();
4166 }
4167
4168 static void
4169 cmw_file (GtkWidget *widget, GtkWidget *parent)
4170 {
4171     GtkWidget *fs;
4172
4173     fs = gtk_file_chooser_dialog_new ("This is a modal file selection dialog",
4174       GTK_WINDOW (parent), GTK_FILE_CHOOSER_ACTION_OPEN,
4175       GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
4176       GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
4177       NULL);
4178     gtk_window_set_screen (GTK_WINDOW (fs), gtk_widget_get_screen (parent));
4179     gtk_window_set_modal (GTK_WINDOW (fs), TRUE);
4180
4181     g_signal_connect (fs, "destroy",
4182                       G_CALLBACK (cmw_destroy_cb), NULL);
4183     g_signal_connect_swapped (fs, "response",
4184                       G_CALLBACK (gtk_widget_destroy), fs);
4185
4186     /* wait until destroy calls gtk_main_quit */
4187     gtk_widget_show (fs);
4188     gtk_main();
4189 }
4190
4191
4192 static void
4193 create_modal_window (GtkWidget *widget)
4194 {
4195   GtkWidget *window = NULL;
4196   GtkWidget *box1,*box2;
4197   GtkWidget *frame1;
4198   GtkWidget *btnColor,*btnFile,*btnClose;
4199
4200   /* Create modal window (Here you can use any window descendent )*/
4201   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
4202   gtk_window_set_screen (GTK_WINDOW (window),
4203                          gtk_widget_get_screen (widget));
4204
4205   gtk_window_set_title (GTK_WINDOW(window),"This window is modal");
4206
4207   /* Set window as modal */
4208   gtk_window_set_modal (GTK_WINDOW(window),TRUE);
4209
4210   /* Create widgets */
4211   box1 = gtk_vbox_new (FALSE,5);
4212   frame1 = gtk_frame_new ("Standard dialogs in modal form");
4213   box2 = gtk_vbox_new (TRUE,5);
4214   btnColor = gtk_button_new_with_label ("Color");
4215   btnFile = gtk_button_new_with_label ("File Selection");
4216   btnClose = gtk_button_new_with_label ("Close");
4217
4218   /* Init widgets */
4219   gtk_container_set_border_width (GTK_CONTAINER (box1), 3);
4220   gtk_container_set_border_width (GTK_CONTAINER (box2), 3);
4221     
4222   /* Pack widgets */
4223   gtk_container_add (GTK_CONTAINER (window), box1);
4224   gtk_box_pack_start (GTK_BOX (box1), frame1, TRUE, TRUE, 4);
4225   gtk_container_add (GTK_CONTAINER (frame1), box2);
4226   gtk_box_pack_start (GTK_BOX (box2), btnColor, FALSE, FALSE, 4);
4227   gtk_box_pack_start (GTK_BOX (box2), btnFile, FALSE, FALSE, 4);
4228   gtk_box_pack_start (GTK_BOX (box1), gtk_hseparator_new (), FALSE, FALSE, 4);
4229   gtk_box_pack_start (GTK_BOX (box1), btnClose, FALSE, FALSE, 4);
4230    
4231   /* connect signals */
4232   g_signal_connect_swapped (btnClose, "clicked",
4233                             G_CALLBACK (gtk_widget_destroy), window);
4234
4235   g_signal_connect (window, "destroy",
4236                     G_CALLBACK (cmw_destroy_cb), NULL);
4237   
4238   g_signal_connect (btnColor, "clicked",
4239                     G_CALLBACK (cmw_color), window);
4240   g_signal_connect (btnFile, "clicked",
4241                     G_CALLBACK (cmw_file), window);
4242
4243   /* Show widgets */
4244   gtk_widget_show_all (window);
4245
4246   /* wait until dialog get destroyed */
4247   gtk_main();
4248 }
4249
4250 /*
4251  * GtkMessageDialog
4252  */
4253
4254 static void
4255 make_message_dialog (GdkScreen *screen,
4256                      GtkWidget **dialog,
4257                      GtkMessageType  type,
4258                      GtkButtonsType  buttons,
4259                      guint           default_response)
4260 {
4261   if (*dialog)
4262     {
4263       gtk_widget_destroy (*dialog);
4264
4265       return;
4266     }
4267
4268   *dialog = gtk_message_dialog_new (NULL, 0, type, buttons,
4269                                     "This is a message dialog; it can wrap long lines. This is a long line. La la la. Look this line is wrapped. Blah blah blah blah blah blah. (Note: testgtk has a nonstandard gtkrc that changes some of the message dialog icons.)");
4270
4271   gtk_window_set_screen (GTK_WINDOW (*dialog), screen);
4272
4273   g_signal_connect_swapped (*dialog,
4274                             "response",
4275                             G_CALLBACK (gtk_widget_destroy),
4276                             *dialog);
4277   
4278   g_signal_connect (*dialog,
4279                     "destroy",
4280                     G_CALLBACK (gtk_widget_destroyed),
4281                     dialog);
4282
4283   gtk_dialog_set_default_response (GTK_DIALOG (*dialog), default_response);
4284
4285   gtk_widget_show (*dialog);
4286 }
4287
4288 static void
4289 create_message_dialog (GtkWidget *widget)
4290 {
4291   static GtkWidget *info = NULL;
4292   static GtkWidget *warning = NULL;
4293   static GtkWidget *error = NULL;
4294   static GtkWidget *question = NULL;
4295   GdkScreen *screen = gtk_widget_get_screen (widget);
4296
4297   make_message_dialog (screen, &info, GTK_MESSAGE_INFO, GTK_BUTTONS_OK, GTK_RESPONSE_OK);
4298   make_message_dialog (screen, &warning, GTK_MESSAGE_WARNING, GTK_BUTTONS_CLOSE, GTK_RESPONSE_CLOSE);
4299   make_message_dialog (screen, &error, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK_CANCEL, GTK_RESPONSE_OK);
4300   make_message_dialog (screen, &question, GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO, GTK_RESPONSE_NO);
4301 }
4302
4303 /*
4304  * GtkScrolledWindow
4305  */
4306
4307 static GtkWidget *sw_parent = NULL;
4308 static GtkWidget *sw_float_parent;
4309 static guint sw_destroyed_handler = 0;
4310
4311 static gboolean
4312 scrolled_windows_delete_cb (GtkWidget *widget, GdkEventAny *event, GtkWidget *scrollwin)
4313 {
4314   gtk_widget_reparent (scrollwin, sw_parent);
4315   
4316   g_signal_handler_disconnect (sw_parent, sw_destroyed_handler);
4317   sw_float_parent = NULL;
4318   sw_parent = NULL;
4319   sw_destroyed_handler = 0;
4320
4321   return FALSE;
4322 }
4323
4324 static void
4325 scrolled_windows_destroy_cb (GtkWidget *widget, GtkWidget *scrollwin)
4326 {
4327   gtk_widget_destroy (sw_float_parent);
4328
4329   sw_float_parent = NULL;
4330   sw_parent = NULL;
4331   sw_destroyed_handler = 0;
4332 }
4333
4334 static void
4335 scrolled_windows_remove (GtkWidget *widget, GtkWidget *scrollwin)
4336 {
4337   if (sw_parent)
4338     {
4339       gtk_widget_reparent (scrollwin, sw_parent);
4340       gtk_widget_destroy (sw_float_parent);
4341
4342       g_signal_handler_disconnect (sw_parent, sw_destroyed_handler);
4343       sw_float_parent = NULL;
4344       sw_parent = NULL;
4345       sw_destroyed_handler = 0;
4346     }
4347   else
4348     {
4349       sw_parent = scrollwin->parent;
4350       sw_float_parent = gtk_window_new (GTK_WINDOW_TOPLEVEL);
4351       gtk_window_set_screen (GTK_WINDOW (sw_float_parent),
4352                              gtk_widget_get_screen (widget));
4353       
4354       gtk_window_set_default_size (GTK_WINDOW (sw_float_parent), 200, 200);
4355       
4356       gtk_widget_reparent (scrollwin, sw_float_parent);
4357       gtk_widget_show (sw_float_parent);
4358
4359       sw_destroyed_handler =
4360         g_signal_connect (sw_parent, "destroy",
4361                           G_CALLBACK (scrolled_windows_destroy_cb), scrollwin);
4362       g_signal_connect (sw_float_parent, "delete_event",
4363                         G_CALLBACK (scrolled_windows_delete_cb), scrollwin);
4364     }
4365 }
4366
4367 static void
4368 create_scrolled_windows (GtkWidget *widget)
4369 {
4370   static GtkWidget *window;
4371   GtkWidget *scrolled_window;
4372   GtkWidget *table;
4373   GtkWidget *button;
4374   char buffer[32];
4375   int i, j;
4376
4377   if (!window)
4378     {
4379       window = gtk_dialog_new ();
4380
4381       gtk_window_set_screen (GTK_WINDOW (window),
4382                              gtk_widget_get_screen (widget));
4383
4384       g_signal_connect (window, "destroy",
4385                         G_CALLBACK (gtk_widget_destroyed),
4386                         &window);
4387
4388       gtk_window_set_title (GTK_WINDOW (window), "dialog");
4389       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
4390
4391
4392       scrolled_window = gtk_scrolled_window_new (NULL, NULL);
4393       gtk_container_set_border_width (GTK_CONTAINER (scrolled_window), 10);
4394       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
4395                                       GTK_POLICY_AUTOMATIC,
4396                                       GTK_POLICY_AUTOMATIC);
4397       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
4398                           scrolled_window, TRUE, TRUE, 0);
4399       gtk_widget_show (scrolled_window);
4400
4401       table = gtk_table_new (20, 20, FALSE);
4402       gtk_table_set_row_spacings (GTK_TABLE (table), 10);
4403       gtk_table_set_col_spacings (GTK_TABLE (table), 10);
4404       gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_window), table);
4405       gtk_container_set_focus_hadjustment (GTK_CONTAINER (table),
4406                                            gtk_scrolled_window_get_hadjustment (GTK_SCROLLED_WINDOW (scrolled_window)));
4407       gtk_container_set_focus_vadjustment (GTK_CONTAINER (table),
4408                                            gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (scrolled_window)));
4409       gtk_widget_show (table);
4410
4411       for (i = 0; i < 20; i++)
4412         for (j = 0; j < 20; j++)
4413           {
4414             sprintf (buffer, "button (%d,%d)\n", i, j);
4415             button = gtk_toggle_button_new_with_label (buffer);
4416             gtk_table_attach_defaults (GTK_TABLE (table), button,
4417                                        i, i+1, j, j+1);
4418             gtk_widget_show (button);
4419           }
4420
4421
4422       button = gtk_button_new_with_label ("Close");
4423       g_signal_connect_swapped (button, "clicked",
4424                                 G_CALLBACK (gtk_widget_destroy),
4425                                 window);
4426       gtk_widget_set_can_default (button, TRUE);
4427       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
4428                           button, TRUE, TRUE, 0);
4429       gtk_widget_grab_default (button);
4430       gtk_widget_show (button);
4431
4432       button = gtk_button_new_with_label ("Reparent Out");
4433       g_signal_connect (button, "clicked",
4434                         G_CALLBACK (scrolled_windows_remove),
4435                         scrolled_window);
4436       gtk_widget_set_can_default (button, TRUE);
4437       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
4438                           button, TRUE, TRUE, 0);
4439       gtk_widget_grab_default (button);
4440       gtk_widget_show (button);
4441
4442       gtk_window_set_default_size (GTK_WINDOW (window), 300, 300);
4443     }
4444
4445   if (!gtk_widget_get_visible (window))
4446     gtk_widget_show (window);
4447   else
4448     gtk_widget_destroy (window);
4449 }
4450
4451 /*
4452  * GtkEntry
4453  */
4454
4455 static void
4456 entry_toggle_frame (GtkWidget *checkbutton,
4457                     GtkWidget *entry)
4458 {
4459    gtk_entry_set_has_frame (GTK_ENTRY(entry),
4460                             GTK_TOGGLE_BUTTON(checkbutton)->active);
4461 }
4462
4463 static void
4464 entry_toggle_sensitive (GtkWidget *checkbutton,
4465                         GtkWidget *entry)
4466 {
4467    gtk_widget_set_sensitive (entry, GTK_TOGGLE_BUTTON(checkbutton)->active);
4468 }
4469
4470 static gboolean
4471 entry_progress_timeout (gpointer data)
4472 {
4473   if (GPOINTER_TO_INT (g_object_get_data (G_OBJECT (data), "progress-pulse")))
4474     {
4475       gtk_entry_progress_pulse (GTK_ENTRY (data));
4476     }
4477   else
4478     {
4479       gdouble fraction;
4480
4481       fraction = gtk_entry_get_progress_fraction (GTK_ENTRY (data));
4482
4483       fraction += 0.05;
4484       if (fraction > 1.0001)
4485         fraction = 0.0;
4486
4487       gtk_entry_set_progress_fraction (GTK_ENTRY (data), fraction);
4488     }
4489
4490   return TRUE;
4491 }
4492
4493 static void
4494 entry_remove_timeout (gpointer data)
4495 {
4496   g_source_remove (GPOINTER_TO_UINT (data));
4497 }
4498
4499 static void
4500 entry_toggle_progress (GtkWidget *checkbutton,
4501                        GtkWidget *entry)
4502 {
4503   if (GTK_TOGGLE_BUTTON (checkbutton)->active)
4504     {
4505       guint timeout = gdk_threads_add_timeout (100,
4506                                                entry_progress_timeout,
4507                                                entry);
4508       g_object_set_data_full (G_OBJECT (entry), "timeout-id",
4509                               GUINT_TO_POINTER (timeout),
4510                               entry_remove_timeout);
4511     }
4512   else
4513     {
4514       g_object_set_data (G_OBJECT (entry), "timeout-id",
4515                          GUINT_TO_POINTER (0));
4516
4517       gtk_entry_set_progress_fraction (GTK_ENTRY (entry), 0.0);
4518     }
4519 }
4520
4521 static void
4522 entry_toggle_pulse (GtkWidget *checkbutton,
4523                     GtkWidget *entry)
4524 {
4525   g_object_set_data (G_OBJECT (entry), "progress-pulse",
4526                      GUINT_TO_POINTER ((guint) GTK_TOGGLE_BUTTON (checkbutton)->active));
4527 }
4528
4529 static void
4530 props_clicked (GtkWidget *button,
4531                GObject   *object)
4532 {
4533   GtkWidget *window = create_prop_editor (object, 0);
4534
4535   gtk_window_set_title (GTK_WINDOW (window), "Object Properties");
4536 }
4537
4538 static void
4539 create_entry (GtkWidget *widget)
4540 {
4541   static GtkWidget *window = NULL;
4542   GtkWidget *box1;
4543   GtkWidget *box2;
4544   GtkWidget *hbox;
4545   GtkWidget *has_frame_check;
4546   GtkWidget *sensitive_check;
4547   GtkWidget *progress_check;
4548   GtkWidget *entry;
4549   GtkComboBox *cb;
4550   GtkWidget *cb_entry;
4551   GtkWidget *button;
4552   GtkWidget *separator;
4553
4554   if (!window)
4555     {
4556       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
4557       gtk_window_set_screen (GTK_WINDOW (window),
4558                              gtk_widget_get_screen (widget));
4559
4560       g_signal_connect (window, "destroy",
4561                         G_CALLBACK (gtk_widget_destroyed),
4562                         &window);
4563
4564       gtk_window_set_title (GTK_WINDOW (window), "entry");
4565       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
4566
4567
4568       box1 = gtk_vbox_new (FALSE, 0);
4569       gtk_container_add (GTK_CONTAINER (window), box1);
4570
4571
4572       box2 = gtk_vbox_new (FALSE, 10);
4573       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
4574       gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
4575
4576       hbox = gtk_hbox_new (FALSE, 5);
4577       gtk_box_pack_start (GTK_BOX (box2), hbox, TRUE, TRUE, 0);
4578       
4579       entry = gtk_entry_new ();
4580       gtk_entry_set_text (GTK_ENTRY (entry), "hello world \330\247\331\204\330\263\331\204\330\247\331\205 \330\271\331\204\331\212\331\203\331\205");
4581       gtk_editable_select_region (GTK_EDITABLE (entry), 0, 5);
4582       gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0);
4583
4584       button = gtk_button_new_with_mnemonic ("_Props");
4585       gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
4586       g_signal_connect (button, "clicked",
4587                         G_CALLBACK (props_clicked),
4588                         entry);
4589
4590       cb = GTK_COMBO_BOX (gtk_combo_box_entry_new_text ());
4591       gtk_combo_box_append_text (cb, "item0");
4592       gtk_combo_box_append_text (cb, "item0");
4593       gtk_combo_box_append_text (cb, "item1 item1");
4594       gtk_combo_box_append_text (cb, "item2 item2 item2");
4595       gtk_combo_box_append_text (cb, "item3 item3 item3 item3");
4596       gtk_combo_box_append_text (cb, "item4 item4 item4 item4 item4");
4597       gtk_combo_box_append_text (cb, "item5 item5 item5 item5 item5 item5");
4598       gtk_combo_box_append_text (cb, "item6 item6 item6 item6 item6");
4599       gtk_combo_box_append_text (cb, "item7 item7 item7 item7");
4600       gtk_combo_box_append_text (cb, "item8 item8 item8");
4601       gtk_combo_box_append_text (cb, "item9 item9");
4602
4603       cb_entry = gtk_bin_get_child (GTK_BIN (cb));
4604       gtk_entry_set_text (GTK_ENTRY (cb_entry), "hello world \n\n\n foo");
4605       gtk_editable_select_region (GTK_EDITABLE (cb_entry), 0, -1);
4606       gtk_box_pack_start (GTK_BOX (box2), GTK_WIDGET (cb), TRUE, TRUE, 0);
4607
4608       sensitive_check = gtk_check_button_new_with_label("Sensitive");
4609       gtk_box_pack_start (GTK_BOX (box2), sensitive_check, FALSE, TRUE, 0);
4610       g_signal_connect (sensitive_check, "toggled",
4611                         G_CALLBACK (entry_toggle_sensitive), entry);
4612       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sensitive_check), TRUE);
4613
4614       has_frame_check = gtk_check_button_new_with_label("Has Frame");
4615       gtk_box_pack_start (GTK_BOX (box2), has_frame_check, FALSE, TRUE, 0);
4616       g_signal_connect (has_frame_check, "toggled",
4617                         G_CALLBACK (entry_toggle_frame), entry);
4618       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (has_frame_check), TRUE);
4619
4620       progress_check = gtk_check_button_new_with_label("Show Progress");
4621       gtk_box_pack_start (GTK_BOX (box2), progress_check, FALSE, TRUE, 0);
4622       g_signal_connect (progress_check, "toggled",
4623                         G_CALLBACK (entry_toggle_progress), entry);
4624
4625       progress_check = gtk_check_button_new_with_label("Pulse Progress");
4626       gtk_box_pack_start (GTK_BOX (box2), progress_check, FALSE, TRUE, 0);
4627       g_signal_connect (progress_check, "toggled",
4628                         G_CALLBACK (entry_toggle_pulse), entry);
4629
4630       separator = gtk_hseparator_new ();
4631       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
4632
4633       box2 = gtk_vbox_new (FALSE, 10);
4634       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
4635       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
4636
4637       button = gtk_button_new_with_label ("close");
4638       g_signal_connect_swapped (button, "clicked",
4639                                 G_CALLBACK (gtk_widget_destroy),
4640                                 window);
4641       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
4642       gtk_widget_set_can_default (button, TRUE);
4643       gtk_widget_grab_default (button);
4644     }
4645
4646   if (!gtk_widget_get_visible (window))
4647     gtk_widget_show_all (window);
4648   else
4649     gtk_widget_destroy (window);
4650 }
4651
4652 static void
4653 create_expander (GtkWidget *widget)
4654 {
4655   GtkWidget *box1;
4656   GtkWidget *expander;
4657   GtkWidget *hidden;
4658   static GtkWidget *window = NULL;
4659
4660   if (!window)
4661     {
4662       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
4663       gtk_window_set_screen (GTK_WINDOW (window),
4664                              gtk_widget_get_screen (widget));
4665       
4666       g_signal_connect (window, "destroy",
4667                         G_CALLBACK (gtk_widget_destroyed),
4668                         &window);
4669       
4670       gtk_window_set_title (GTK_WINDOW (window), "expander");
4671       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
4672       
4673       box1 = gtk_vbox_new (FALSE, 0);
4674       gtk_container_add (GTK_CONTAINER (window), box1);
4675       
4676       expander = gtk_expander_new ("The Hidden");
4677       
4678       gtk_box_pack_start (GTK_BOX (box1), expander, TRUE, TRUE, 0);
4679       
4680       hidden = gtk_label_new ("Revealed!");
4681       
4682       gtk_container_add (GTK_CONTAINER (expander), hidden);
4683     }
4684   
4685   if (!gtk_widget_get_visible (window))
4686     gtk_widget_show_all (window);
4687   else
4688     gtk_widget_destroy (window);
4689 }
4690
4691
4692 /* GtkEventBox */
4693
4694
4695 static void
4696 event_box_label_pressed (GtkWidget        *widget,
4697                          GdkEventButton   *event,
4698                          gpointer user_data)
4699 {
4700   g_print ("clicked on event box\n");
4701 }
4702
4703 static void
4704 event_box_button_clicked (GtkWidget *widget,
4705                           GtkWidget *button,
4706                           gpointer user_data)
4707 {
4708   g_print ("pushed button\n");
4709 }
4710
4711 static void
4712 event_box_toggle_visible_window (GtkWidget *checkbutton,
4713                                  GtkEventBox *event_box)
4714 {
4715   gtk_event_box_set_visible_window (event_box,
4716                                     GTK_TOGGLE_BUTTON(checkbutton)->active);
4717 }
4718
4719 static void
4720 event_box_toggle_above_child (GtkWidget *checkbutton,
4721                               GtkEventBox *event_box)
4722 {
4723   gtk_event_box_set_above_child (event_box,
4724                                  GTK_TOGGLE_BUTTON(checkbutton)->active);
4725 }
4726
4727 static void
4728 create_event_box (GtkWidget *widget)
4729 {
4730   static GtkWidget *window = NULL;
4731   GtkWidget *box1;
4732   GtkWidget *box2;
4733   GtkWidget *hbox;
4734   GtkWidget *vbox;
4735   GtkWidget *button;
4736   GtkWidget *separator;
4737   GtkWidget *event_box;
4738   GtkWidget *label;
4739   GtkWidget *visible_window_check;
4740   GtkWidget *above_child_check;
4741   GdkColor color;
4742
4743   if (!window)
4744     {
4745       color.red = 0;
4746       color.blue = 65535;
4747       color.green = 0;
4748       
4749       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
4750       gtk_window_set_screen (GTK_WINDOW (window),
4751                              gtk_widget_get_screen (widget));
4752
4753       g_signal_connect (window, "destroy",
4754                         G_CALLBACK (gtk_widget_destroyed),
4755                         &window);
4756
4757       gtk_window_set_title (GTK_WINDOW (window), "event box");
4758       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
4759
4760       box1 = gtk_vbox_new (FALSE, 0);
4761       gtk_container_add (GTK_CONTAINER (window), box1);
4762       gtk_widget_modify_bg (window, GTK_STATE_NORMAL, &color);
4763
4764       hbox = gtk_hbox_new (FALSE, 0);
4765       gtk_box_pack_start (GTK_BOX (box1), hbox, TRUE, FALSE, 0);
4766       
4767       event_box = gtk_event_box_new ();
4768       gtk_box_pack_start (GTK_BOX (hbox), event_box, TRUE, FALSE, 0);
4769
4770       vbox = gtk_vbox_new (FALSE, 0);
4771       gtk_container_add (GTK_CONTAINER (event_box), vbox);
4772       g_signal_connect (event_box, "button_press_event",
4773                         G_CALLBACK (event_box_label_pressed),
4774                         NULL);
4775       
4776       label = gtk_label_new ("Click on this label");
4777       gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, FALSE, 0);
4778
4779       button = gtk_button_new_with_label ("button in eventbox");
4780       gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, FALSE, 0);
4781       g_signal_connect (button, "clicked",
4782                         G_CALLBACK (event_box_button_clicked),
4783                         NULL);
4784       
4785
4786       visible_window_check = gtk_check_button_new_with_label("Visible Window");
4787       gtk_box_pack_start (GTK_BOX (box1), visible_window_check, FALSE, TRUE, 0);
4788       g_signal_connect (visible_window_check, "toggled",
4789                         G_CALLBACK (event_box_toggle_visible_window), event_box);
4790       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (visible_window_check), FALSE);
4791       
4792       above_child_check = gtk_check_button_new_with_label("Above Child");
4793       gtk_box_pack_start (GTK_BOX (box1), above_child_check, FALSE, TRUE, 0);
4794       g_signal_connect (above_child_check, "toggled",
4795                         G_CALLBACK (event_box_toggle_above_child), event_box);
4796       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (above_child_check), FALSE);
4797       
4798       separator = gtk_hseparator_new ();
4799       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
4800
4801       box2 = gtk_vbox_new (FALSE, 10);
4802       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
4803       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
4804
4805       button = gtk_button_new_with_label ("close");
4806       g_signal_connect_swapped (button, "clicked",
4807                                 G_CALLBACK (gtk_widget_destroy),
4808                                 window);
4809       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
4810       gtk_widget_set_can_default (button, TRUE);
4811       gtk_widget_grab_default (button);
4812     }
4813
4814   if (!gtk_widget_get_visible (window))
4815     gtk_widget_show_all (window);
4816   else
4817     gtk_widget_destroy (window);
4818 }
4819
4820
4821 /*
4822  * GtkSizeGroup
4823  */
4824
4825 #define SIZE_GROUP_INITIAL_SIZE 50
4826
4827 static void
4828 size_group_hsize_changed (GtkSpinButton *spin_button,
4829                           GtkWidget     *button)
4830 {
4831   gtk_widget_set_size_request (GTK_BIN (button)->child,
4832                                gtk_spin_button_get_value_as_int (spin_button),
4833                                -1);
4834 }
4835
4836 static void
4837 size_group_vsize_changed (GtkSpinButton *spin_button,
4838                           GtkWidget     *button)
4839 {
4840   gtk_widget_set_size_request (GTK_BIN (button)->child,
4841                                -1,
4842                                gtk_spin_button_get_value_as_int (spin_button));
4843 }
4844
4845 static GtkWidget *
4846 create_size_group_window (GdkScreen    *screen,
4847                           GtkSizeGroup *master_size_group)
4848 {
4849   GtkWidget *window;
4850   GtkWidget *table;
4851   GtkWidget *main_button;
4852   GtkWidget *button;
4853   GtkWidget *spin_button;
4854   GtkWidget *hbox;
4855   GtkSizeGroup *hgroup1;
4856   GtkSizeGroup *hgroup2;
4857   GtkSizeGroup *vgroup1;
4858   GtkSizeGroup *vgroup2;
4859
4860   window = gtk_dialog_new_with_buttons ("GtkSizeGroup",
4861                                         NULL, 0,
4862                                         GTK_STOCK_CLOSE,
4863                                         GTK_RESPONSE_NONE,
4864                                         NULL);
4865
4866   gtk_window_set_screen (GTK_WINDOW (window), screen);
4867
4868   gtk_window_set_resizable (GTK_WINDOW (window), TRUE);
4869
4870   g_signal_connect (window, "response",
4871                     G_CALLBACK (gtk_widget_destroy),
4872                     NULL);
4873
4874   table = gtk_table_new (2, 2, FALSE);
4875   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), table, TRUE, TRUE, 0);
4876
4877   gtk_table_set_row_spacings (GTK_TABLE (table), 5);
4878   gtk_table_set_col_spacings (GTK_TABLE (table), 5);
4879   gtk_container_set_border_width (GTK_CONTAINER (table), 5);
4880   gtk_widget_set_size_request (table, 250, 250);
4881
4882   hgroup1 = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
4883   hgroup2 = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
4884   vgroup1 = gtk_size_group_new (GTK_SIZE_GROUP_VERTICAL);
4885   vgroup2 = gtk_size_group_new (GTK_SIZE_GROUP_VERTICAL);
4886
4887   main_button = gtk_button_new_with_label ("X");
4888   
4889   gtk_table_attach (GTK_TABLE (table), main_button,
4890                     0, 1,       0, 1,
4891                     GTK_EXPAND, GTK_EXPAND,
4892                     0,          0);
4893   gtk_size_group_add_widget (master_size_group, main_button);
4894   gtk_size_group_add_widget (hgroup1, main_button);
4895   gtk_size_group_add_widget (vgroup1, main_button);
4896   gtk_widget_set_size_request (GTK_BIN (main_button)->child,
4897                                SIZE_GROUP_INITIAL_SIZE,
4898                                SIZE_GROUP_INITIAL_SIZE);
4899
4900   button = gtk_button_new ();
4901   gtk_table_attach (GTK_TABLE (table), button,
4902                     1, 2,       0, 1,
4903                     GTK_EXPAND, GTK_EXPAND,
4904                     0,          0);
4905   gtk_size_group_add_widget (vgroup1, button);
4906   gtk_size_group_add_widget (vgroup2, button);
4907
4908   button = gtk_button_new ();
4909   gtk_table_attach (GTK_TABLE (table), button,
4910                     0, 1,       1, 2,
4911                     GTK_EXPAND, GTK_EXPAND,
4912                     0,          0);
4913   gtk_size_group_add_widget (hgroup1, button);
4914   gtk_size_group_add_widget (hgroup2, button);
4915
4916   button = gtk_button_new ();
4917   gtk_table_attach (GTK_TABLE (table), button,
4918                     1, 2,       1, 2,
4919                     GTK_EXPAND, GTK_EXPAND,
4920                     0,          0);
4921   gtk_size_group_add_widget (hgroup2, button);
4922   gtk_size_group_add_widget (vgroup2, button);
4923
4924   g_object_unref (hgroup1);
4925   g_object_unref (hgroup2);
4926   g_object_unref (vgroup1);
4927   g_object_unref (vgroup2);
4928   
4929   hbox = gtk_hbox_new (FALSE, 5);
4930   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), hbox, FALSE, FALSE, 0);
4931   
4932   spin_button = gtk_spin_button_new_with_range (1, 100, 1);
4933   gtk_spin_button_set_value (GTK_SPIN_BUTTON (spin_button), SIZE_GROUP_INITIAL_SIZE);
4934   gtk_box_pack_start (GTK_BOX (hbox), spin_button, TRUE, TRUE, 0);
4935   g_signal_connect (spin_button, "value_changed",
4936                     G_CALLBACK (size_group_hsize_changed), main_button);
4937
4938   spin_button = gtk_spin_button_new_with_range (1, 100, 1);
4939   gtk_spin_button_set_value (GTK_SPIN_BUTTON (spin_button), SIZE_GROUP_INITIAL_SIZE);
4940   gtk_box_pack_start (GTK_BOX (hbox), spin_button, TRUE, TRUE, 0);
4941   g_signal_connect (spin_button, "value_changed",
4942                     G_CALLBACK (size_group_vsize_changed), main_button);
4943
4944   return window;
4945 }
4946
4947 static void
4948 create_size_groups (GtkWidget *widget)
4949 {
4950   static GtkWidget *window1 = NULL;
4951   static GtkWidget *window2 = NULL;
4952   static GtkSizeGroup *master_size_group;
4953
4954   if (!master_size_group)
4955     master_size_group = gtk_size_group_new (GTK_SIZE_GROUP_BOTH);
4956
4957   if (!window1)
4958     {
4959       window1 = create_size_group_window (gtk_widget_get_screen (widget),
4960                                           master_size_group);
4961
4962       g_signal_connect (window1, "destroy",
4963                         G_CALLBACK (gtk_widget_destroyed),
4964                         &window1);
4965     }
4966
4967   if (!window2)
4968     {
4969       window2 = create_size_group_window (gtk_widget_get_screen (widget),
4970                                           master_size_group);
4971
4972       g_signal_connect (window2, "destroy",
4973                         G_CALLBACK (gtk_widget_destroyed),
4974                         &window2);
4975     }
4976
4977   if (gtk_widget_get_visible (window1) && gtk_widget_get_visible (window2))
4978     {
4979       gtk_widget_destroy (window1);
4980       gtk_widget_destroy (window2);
4981     }
4982   else
4983     {
4984       if (!gtk_widget_get_visible (window1))
4985         gtk_widget_show_all (window1);
4986       if (!gtk_widget_get_visible (window2))
4987         gtk_widget_show_all (window2);
4988     }
4989 }
4990
4991 /*
4992  * GtkSpinButton
4993  */
4994
4995 static GtkWidget *spinner1;
4996
4997 static void
4998 toggle_snap (GtkWidget *widget, GtkSpinButton *spin)
4999 {
5000   gtk_spin_button_set_snap_to_ticks (spin, GTK_TOGGLE_BUTTON (widget)->active);
5001 }
5002
5003 static void
5004 toggle_numeric (GtkWidget *widget, GtkSpinButton *spin)
5005 {
5006   gtk_spin_button_set_numeric (spin, GTK_TOGGLE_BUTTON (widget)->active);
5007 }
5008
5009 static void
5010 change_digits (GtkWidget *widget, GtkSpinButton *spin)
5011 {
5012   gtk_spin_button_set_digits (GTK_SPIN_BUTTON (spinner1),
5013                               gtk_spin_button_get_value_as_int (spin));
5014 }
5015
5016 static void
5017 get_value (GtkWidget *widget, gpointer data)
5018 {
5019   gchar buf[32];
5020   GtkLabel *label;
5021   GtkSpinButton *spin;
5022
5023   spin = GTK_SPIN_BUTTON (spinner1);
5024   label = GTK_LABEL (g_object_get_data (G_OBJECT (widget), "user_data"));
5025   if (GPOINTER_TO_INT (data) == 1)
5026     sprintf (buf, "%d", gtk_spin_button_get_value_as_int (spin));
5027   else
5028     sprintf (buf, "%0.*f", spin->digits, gtk_spin_button_get_value (spin));
5029   gtk_label_set_text (label, buf);
5030 }
5031
5032 static void
5033 get_spin_value (GtkWidget *widget, gpointer data)
5034 {
5035   gchar *buffer;
5036   GtkLabel *label;
5037   GtkSpinButton *spin;
5038
5039   spin = GTK_SPIN_BUTTON (widget);
5040   label = GTK_LABEL (data);
5041
5042   buffer = g_strdup_printf ("%0.*f", spin->digits,
5043                             gtk_spin_button_get_value (spin));
5044   gtk_label_set_text (label, buffer);
5045
5046   g_free (buffer);
5047 }
5048
5049 static gint
5050 spin_button_time_output_func (GtkSpinButton *spin_button)
5051 {
5052   static gchar buf[6];
5053   gdouble hours;
5054   gdouble minutes;
5055
5056   hours = spin_button->adjustment->value / 60.0;
5057   minutes = (fabs(floor (hours) - hours) < 1e-5) ? 0.0 : 30;
5058   sprintf (buf, "%02.0f:%02.0f", floor (hours), minutes);
5059   if (strcmp (buf, gtk_entry_get_text (GTK_ENTRY (spin_button))))
5060     gtk_entry_set_text (GTK_ENTRY (spin_button), buf);
5061   return TRUE;
5062 }
5063
5064 static gint
5065 spin_button_month_input_func (GtkSpinButton *spin_button,
5066                               gdouble       *new_val)
5067 {
5068   gint i;
5069   static gchar *month[12] = { "January", "February", "March", "April",
5070                               "May", "June", "July", "August",
5071                               "September", "October", "November", "December" };
5072   gchar *tmp1, *tmp2;
5073   gboolean found = FALSE;
5074
5075   for (i = 1; i <= 12; i++)
5076     {
5077       tmp1 = g_ascii_strup (month[i - 1], -1);
5078       tmp2 = g_ascii_strup (gtk_entry_get_text (GTK_ENTRY (spin_button)), -1);
5079       if (strstr (tmp1, tmp2) == tmp1)
5080         found = TRUE;
5081       g_free (tmp1);
5082       g_free (tmp2);
5083       if (found)
5084         break;
5085     }
5086   if (!found)
5087     {
5088       *new_val = 0.0;
5089       return GTK_INPUT_ERROR;
5090     }
5091   *new_val = (gdouble) i;
5092   return TRUE;
5093 }
5094
5095 static gint
5096 spin_button_month_output_func (GtkSpinButton *spin_button)
5097 {
5098   gint i;
5099   static gchar *month[12] = { "January", "February", "March", "April",
5100                               "May", "June", "July", "August", "September",
5101                               "October", "November", "December" };
5102
5103   for (i = 1; i <= 12; i++)
5104     if (fabs (spin_button->adjustment->value - (double)i) < 1e-5)
5105       {
5106         if (strcmp (month[i-1], gtk_entry_get_text (GTK_ENTRY (spin_button))))
5107           gtk_entry_set_text (GTK_ENTRY (spin_button), month[i-1]);
5108       }
5109   return TRUE;
5110 }
5111
5112 static gint
5113 spin_button_hex_input_func (GtkSpinButton *spin_button,
5114                             gdouble       *new_val)
5115 {
5116   const gchar *buf;
5117   gchar *err;
5118   gdouble res;
5119
5120   buf = gtk_entry_get_text (GTK_ENTRY (spin_button));
5121   res = strtol(buf, &err, 16);
5122   *new_val = res;
5123   if (*err)
5124     return GTK_INPUT_ERROR;
5125   else
5126     return TRUE;
5127 }
5128
5129 static gint
5130 spin_button_hex_output_func (GtkSpinButton *spin_button)
5131 {
5132   static gchar buf[7];
5133   gint val;
5134
5135   val = (gint) spin_button->adjustment->value;
5136   if (fabs (val) < 1e-5)
5137     sprintf (buf, "0x00");
5138   else
5139     sprintf (buf, "0x%.2X", val);
5140   if (strcmp (buf, gtk_entry_get_text (GTK_ENTRY (spin_button))))
5141     gtk_entry_set_text (GTK_ENTRY (spin_button), buf);
5142   return TRUE;
5143 }
5144
5145 static void
5146 create_spins (GtkWidget *widget)
5147 {
5148   static GtkWidget *window = NULL;
5149   GtkWidget *frame;
5150   GtkWidget *hbox;
5151   GtkWidget *main_vbox;
5152   GtkWidget *vbox;
5153   GtkWidget *vbox2;
5154   GtkWidget *spinner2;
5155   GtkWidget *spinner;
5156   GtkWidget *button;
5157   GtkWidget *label;
5158   GtkWidget *val_label;
5159   GtkAdjustment *adj;
5160
5161   if (!window)
5162     {
5163       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
5164       gtk_window_set_screen (GTK_WINDOW (window),
5165                              gtk_widget_get_screen (widget));
5166       
5167       g_signal_connect (window, "destroy",
5168                         G_CALLBACK (gtk_widget_destroyed),
5169                         &window);
5170       
5171       gtk_window_set_title (GTK_WINDOW (window), "GtkSpinButton");
5172       
5173       main_vbox = gtk_vbox_new (FALSE, 5);
5174       gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 10);
5175       gtk_container_add (GTK_CONTAINER (window), main_vbox);
5176       
5177       frame = gtk_frame_new ("Not accelerated");
5178       gtk_box_pack_start (GTK_BOX (main_vbox), frame, TRUE, TRUE, 0);
5179       
5180       vbox = gtk_vbox_new (FALSE, 0);
5181       gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
5182       gtk_container_add (GTK_CONTAINER (frame), vbox);
5183       
5184       /* Time, month, hex spinners */
5185       
5186       hbox = gtk_hbox_new (FALSE, 0);
5187       gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 5);
5188       
5189       vbox2 = gtk_vbox_new (FALSE, 0);
5190       gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 5);
5191       
5192       label = gtk_label_new ("Time :");
5193       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
5194       gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
5195       
5196       adj = (GtkAdjustment *) gtk_adjustment_new (0, 0, 1410, 30, 60, 0);
5197       spinner = gtk_spin_button_new (adj, 0, 0);
5198       gtk_editable_set_editable (GTK_EDITABLE (spinner), FALSE);
5199       g_signal_connect (spinner,
5200                         "output",
5201                         G_CALLBACK (spin_button_time_output_func),
5202                         NULL);
5203       gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner), TRUE);
5204       gtk_entry_set_width_chars (GTK_ENTRY (spinner), 5);
5205       gtk_box_pack_start (GTK_BOX (vbox2), spinner, FALSE, TRUE, 0);
5206
5207       vbox2 = gtk_vbox_new (FALSE, 0);
5208       gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 5);
5209       
5210       label = gtk_label_new ("Month :");
5211       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
5212       gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
5213       
5214       adj = (GtkAdjustment *) gtk_adjustment_new (1.0, 1.0, 12.0, 1.0,
5215                                                   5.0, 0.0);
5216       spinner = gtk_spin_button_new (adj, 0, 0);
5217       gtk_spin_button_set_update_policy (GTK_SPIN_BUTTON (spinner),
5218                                          GTK_UPDATE_IF_VALID);
5219       g_signal_connect (spinner,
5220                         "input",
5221                         G_CALLBACK (spin_button_month_input_func),
5222                         NULL);
5223       g_signal_connect (spinner,
5224                         "output",
5225                         G_CALLBACK (spin_button_month_output_func),
5226                         NULL);
5227       gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner), TRUE);
5228       gtk_entry_set_width_chars (GTK_ENTRY (spinner), 9);
5229       gtk_box_pack_start (GTK_BOX (vbox2), spinner, FALSE, TRUE, 0);
5230       
5231       vbox2 = gtk_vbox_new (FALSE, 0);
5232       gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 5);
5233
5234       label = gtk_label_new ("Hex :");
5235       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
5236       gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
5237
5238       adj = (GtkAdjustment *) gtk_adjustment_new (0, 0, 255, 1, 16, 0);
5239       spinner = gtk_spin_button_new (adj, 0, 0);
5240       gtk_editable_set_editable (GTK_EDITABLE (spinner), TRUE);
5241       g_signal_connect (spinner,
5242                         "input",
5243                         G_CALLBACK (spin_button_hex_input_func),
5244                         NULL);
5245       g_signal_connect (spinner,
5246                         "output",
5247                         G_CALLBACK (spin_button_hex_output_func),
5248                         NULL);
5249       gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner), TRUE);
5250       gtk_entry_set_width_chars (GTK_ENTRY (spinner), 4);
5251       gtk_box_pack_start (GTK_BOX (vbox2), spinner, FALSE, TRUE, 0);
5252
5253       frame = gtk_frame_new ("Accelerated");
5254       gtk_box_pack_start (GTK_BOX (main_vbox), frame, TRUE, TRUE, 0);
5255   
5256       vbox = gtk_vbox_new (FALSE, 0);
5257       gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
5258       gtk_container_add (GTK_CONTAINER (frame), vbox);
5259       
5260       hbox = gtk_hbox_new (FALSE, 0);
5261       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 5);
5262       
5263       vbox2 = gtk_vbox_new (FALSE, 0);
5264       gtk_box_pack_start (GTK_BOX (hbox), vbox2, FALSE, FALSE, 5);
5265       
5266       label = gtk_label_new ("Value :");
5267       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
5268       gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
5269
5270       adj = (GtkAdjustment *) gtk_adjustment_new (0.0, -10000.0, 10000.0,
5271                                                   0.5, 100.0, 0.0);
5272       spinner1 = gtk_spin_button_new (adj, 1.0, 2);
5273       gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner1), TRUE);
5274       gtk_box_pack_start (GTK_BOX (vbox2), spinner1, FALSE, TRUE, 0);
5275
5276       vbox2 = gtk_vbox_new (FALSE, 0);
5277       gtk_box_pack_start (GTK_BOX (hbox), vbox2, FALSE, FALSE, 5);
5278
5279       label = gtk_label_new ("Digits :");
5280       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
5281       gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
5282
5283       adj = (GtkAdjustment *) gtk_adjustment_new (2, 1, 15, 1, 1, 0);
5284       spinner2 = gtk_spin_button_new (adj, 0.0, 0);
5285       g_signal_connect (adj, "value_changed",
5286                         G_CALLBACK (change_digits),
5287                         spinner2);
5288       gtk_box_pack_start (GTK_BOX (vbox2), spinner2, FALSE, TRUE, 0);
5289
5290       hbox = gtk_hbox_new (FALSE, 0);
5291       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 5);
5292
5293       button = gtk_check_button_new_with_label ("Snap to 0.5-ticks");
5294       g_signal_connect (button, "clicked",
5295                         G_CALLBACK (toggle_snap),
5296                         spinner1);
5297       gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
5298       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
5299
5300       button = gtk_check_button_new_with_label ("Numeric only input mode");
5301       g_signal_connect (button, "clicked",
5302                         G_CALLBACK (toggle_numeric),
5303                         spinner1);
5304       gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
5305       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
5306
5307       val_label = gtk_label_new ("");
5308
5309       hbox = gtk_hbox_new (FALSE, 0);
5310       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 5);
5311
5312       button = gtk_button_new_with_label ("Value as Int");
5313       g_object_set_data (G_OBJECT (button), "user_data", val_label);
5314       g_signal_connect (button, "clicked",
5315                         G_CALLBACK (get_value),
5316                         GINT_TO_POINTER (1));
5317       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
5318
5319       button = gtk_button_new_with_label ("Value as Float");
5320       g_object_set_data (G_OBJECT (button), "user_data", val_label);
5321       g_signal_connect (button, "clicked",
5322                         G_CALLBACK (get_value),
5323                         GINT_TO_POINTER (2));
5324       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
5325
5326       gtk_box_pack_start (GTK_BOX (vbox), val_label, TRUE, TRUE, 0);
5327       gtk_label_set_text (GTK_LABEL (val_label), "0");
5328
5329       frame = gtk_frame_new ("Using Convenience Constructor");
5330       gtk_box_pack_start (GTK_BOX (main_vbox), frame, TRUE, TRUE, 0);
5331   
5332       hbox = gtk_hbox_new (FALSE, 0);
5333       gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
5334       gtk_container_add (GTK_CONTAINER (frame), hbox);
5335       
5336       val_label = gtk_label_new ("0.0");
5337
5338       spinner = gtk_spin_button_new_with_range (0.0, 10.0, 0.009);
5339       gtk_spin_button_set_value (GTK_SPIN_BUTTON (spinner), 0.0);
5340       g_signal_connect (spinner, "value_changed",
5341                         G_CALLBACK (get_spin_value), val_label);
5342       gtk_box_pack_start (GTK_BOX (hbox), spinner, TRUE, TRUE, 5);
5343       gtk_box_pack_start (GTK_BOX (hbox), val_label, TRUE, TRUE, 5);
5344
5345       hbox = gtk_hbox_new (FALSE, 0);
5346       gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, TRUE, 0);
5347   
5348       button = gtk_button_new_with_label ("Close");
5349       g_signal_connect_swapped (button, "clicked",
5350                                 G_CALLBACK (gtk_widget_destroy),
5351                                 window);
5352       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
5353     }
5354
5355   if (!gtk_widget_get_visible (window))
5356     gtk_widget_show_all (window);
5357   else
5358     gtk_widget_destroy (window);
5359 }
5360
5361
5362 /*
5363  * Cursors
5364  */
5365
5366 static gint
5367 cursor_expose_event (GtkWidget *widget,
5368                      GdkEvent  *event,
5369                      gpointer   user_data)
5370 {
5371   GtkDrawingArea *darea;
5372   GdkDrawable *drawable;
5373   GdkGC *black_gc;
5374   GdkGC *gray_gc;
5375   GdkGC *white_gc;
5376   guint max_width;
5377   guint max_height;
5378
5379   g_return_val_if_fail (widget != NULL, TRUE);
5380   g_return_val_if_fail (GTK_IS_DRAWING_AREA (widget), TRUE);
5381
5382   darea = GTK_DRAWING_AREA (widget);
5383   drawable = widget->window;
5384   white_gc = widget->style->white_gc;
5385   gray_gc = widget->style->bg_gc[GTK_STATE_NORMAL];
5386   black_gc = widget->style->black_gc;
5387   max_width = widget->allocation.width;
5388   max_height = widget->allocation.height;
5389
5390   gdk_draw_rectangle (drawable, white_gc,
5391                       TRUE,
5392                       0,
5393                       0,
5394                       max_width,
5395                       max_height / 2);
5396
5397   gdk_draw_rectangle (drawable, black_gc,
5398                       TRUE,
5399                       0,
5400                       max_height / 2,
5401                       max_width,
5402                       max_height / 2);
5403
5404   gdk_draw_rectangle (drawable, gray_gc,
5405                       TRUE,
5406                       max_width / 3,
5407                       max_height / 3,
5408                       max_width / 3,
5409                       max_height / 3);
5410
5411   return TRUE;
5412 }
5413
5414 static void
5415 set_cursor (GtkWidget *spinner,
5416             GtkWidget *widget)
5417 {
5418   guint c;
5419   GdkCursor *cursor;
5420   GtkWidget *label;
5421   GEnumClass *class;
5422   GEnumValue *vals;
5423
5424   c = CLAMP (gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (spinner)), 0, 152);
5425   c &= 0xfe;
5426
5427   label = g_object_get_data (G_OBJECT (spinner), "user_data");
5428   
5429   class = g_type_class_ref (GDK_TYPE_CURSOR_TYPE);
5430   vals = class->values;
5431
5432   while (vals && vals->value != c)
5433     vals++;
5434   if (vals)
5435     gtk_label_set_text (GTK_LABEL (label), vals->value_nick);
5436   else
5437     gtk_label_set_text (GTK_LABEL (label), "<unknown>");
5438
5439   g_type_class_unref (class);
5440
5441   cursor = gdk_cursor_new_for_display (gtk_widget_get_display (widget), c);
5442   gdk_window_set_cursor (widget->window, cursor);
5443   gdk_cursor_unref (cursor);
5444 }
5445
5446 static gint
5447 cursor_event (GtkWidget          *widget,
5448               GdkEvent           *event,
5449               GtkSpinButton      *spinner)
5450 {
5451   if ((event->type == GDK_BUTTON_PRESS) &&
5452       ((event->button.button == 1) ||
5453        (event->button.button == 3)))
5454     {
5455       gtk_spin_button_spin (spinner, event->button.button == 1 ?
5456                             GTK_SPIN_STEP_FORWARD : GTK_SPIN_STEP_BACKWARD, 0);
5457       return TRUE;
5458     }
5459
5460   return FALSE;
5461 }
5462
5463 #ifdef GDK_WINDOWING_X11
5464 #include "x11/gdkx.h"
5465
5466 static void
5467 change_cursor_theme (GtkWidget *widget,
5468                      gpointer   data)
5469 {
5470   const gchar *theme;
5471   gint size;
5472   GList *children;
5473
5474   children = gtk_container_get_children (GTK_CONTAINER (data));
5475
5476   theme = gtk_entry_get_text (GTK_ENTRY (children->next->data));
5477   size = (gint) gtk_spin_button_get_value (GTK_SPIN_BUTTON (children->next->next->data));
5478
5479   g_list_free (children);
5480
5481   gdk_x11_display_set_cursor_theme (gtk_widget_get_display (widget),
5482                                     theme, size);
5483 }
5484 #endif
5485
5486
5487 static void
5488 create_cursors (GtkWidget *widget)
5489 {
5490   static GtkWidget *window = NULL;
5491   GtkWidget *frame;
5492   GtkWidget *hbox;
5493   GtkWidget *main_vbox;
5494   GtkWidget *vbox;
5495   GtkWidget *darea;
5496   GtkWidget *spinner;
5497   GtkWidget *button;
5498   GtkWidget *label;
5499   GtkWidget *any;
5500   GtkAdjustment *adj;
5501   GtkWidget *entry;
5502   GtkWidget *size;  
5503
5504   if (!window)
5505     {
5506       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
5507       gtk_window_set_screen (GTK_WINDOW (window), 
5508                              gtk_widget_get_screen (widget));
5509       
5510       g_signal_connect (window, "destroy",
5511                         G_CALLBACK (gtk_widget_destroyed),
5512                         &window);
5513       
5514       gtk_window_set_title (GTK_WINDOW (window), "Cursors");
5515       
5516       main_vbox = gtk_vbox_new (FALSE, 5);
5517       gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 0);
5518       gtk_container_add (GTK_CONTAINER (window), main_vbox);
5519
5520       vbox =
5521         g_object_new (gtk_vbox_get_type (),
5522                         "GtkBox::homogeneous", FALSE,
5523                         "GtkBox::spacing", 5,
5524                         "GtkContainer::border_width", 10,
5525                         "GtkWidget::parent", main_vbox,
5526                         "GtkWidget::visible", TRUE,
5527                         NULL);
5528
5529 #ifdef GDK_WINDOWING_X11
5530       hbox = gtk_hbox_new (FALSE, 0);
5531       gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
5532       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
5533
5534       label = gtk_label_new ("Cursor Theme : ");
5535       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
5536       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
5537
5538       entry = gtk_entry_new ();
5539       gtk_entry_set_text (GTK_ENTRY (entry), "default");
5540       gtk_box_pack_start (GTK_BOX (hbox), entry, FALSE, TRUE, 0);
5541
5542       size = gtk_spin_button_new_with_range (1.0, 64.0, 1.0);
5543       gtk_spin_button_set_value (GTK_SPIN_BUTTON (size), 24.0);
5544       gtk_box_pack_start (GTK_BOX (hbox), size, TRUE, TRUE, 0);
5545       
5546       g_signal_connect (entry, "changed", 
5547                         G_CALLBACK (change_cursor_theme), hbox);
5548       g_signal_connect (size, "changed", 
5549                         G_CALLBACK (change_cursor_theme), hbox);
5550 #endif
5551
5552       hbox = gtk_hbox_new (FALSE, 0);
5553       gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
5554       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
5555
5556       label = gtk_label_new ("Cursor Value : ");
5557       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
5558       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
5559       
5560       adj = (GtkAdjustment *) gtk_adjustment_new (0,
5561                                                   0, 152,
5562                                                   2,
5563                                                   10, 0);
5564       spinner = gtk_spin_button_new (adj, 0, 0);
5565       gtk_box_pack_start (GTK_BOX (hbox), spinner, TRUE, TRUE, 0);
5566
5567       frame =
5568         g_object_new (gtk_frame_get_type (),
5569                         "GtkFrame::shadow", GTK_SHADOW_ETCHED_IN,
5570                         "GtkFrame::label_xalign", 0.5,
5571                         "GtkFrame::label", "Cursor Area",
5572                         "GtkContainer::border_width", 10,
5573                         "GtkWidget::parent", vbox,
5574                         "GtkWidget::visible", TRUE,
5575                         NULL);
5576
5577       darea = gtk_drawing_area_new ();
5578       gtk_widget_set_size_request (darea, 80, 80);
5579       gtk_container_add (GTK_CONTAINER (frame), darea);
5580       g_signal_connect (darea,
5581                         "expose_event",
5582                         G_CALLBACK (cursor_expose_event),
5583                         NULL);
5584       gtk_widget_set_events (darea, GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK);
5585       g_signal_connect (darea,
5586                         "button_press_event",
5587                         G_CALLBACK (cursor_event),
5588                         spinner);
5589       gtk_widget_show (darea);
5590
5591       g_signal_connect (spinner, "changed",
5592                         G_CALLBACK (set_cursor),
5593                         darea);
5594
5595       label = g_object_new (GTK_TYPE_LABEL,
5596                               "visible", TRUE,
5597                               "label", "XXX",
5598                               "parent", vbox,
5599                               NULL);
5600       gtk_container_child_set (GTK_CONTAINER (vbox), label,
5601                                "expand", FALSE,
5602                                NULL);
5603       g_object_set_data (G_OBJECT (spinner), "user_data", label);
5604
5605       any =
5606         g_object_new (gtk_hseparator_get_type (),
5607                         "GtkWidget::visible", TRUE,
5608                         NULL);
5609       gtk_box_pack_start (GTK_BOX (main_vbox), any, FALSE, TRUE, 0);
5610   
5611       hbox = gtk_hbox_new (FALSE, 0);
5612       gtk_container_set_border_width (GTK_CONTAINER (hbox), 10);
5613       gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, TRUE, 0);
5614
5615       button = gtk_button_new_with_label ("Close");
5616       g_signal_connect_swapped (button, "clicked",
5617                                 G_CALLBACK (gtk_widget_destroy),
5618                                 window);
5619       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
5620
5621       gtk_widget_show_all (window);
5622
5623       set_cursor (spinner, darea);
5624     }
5625   else
5626     gtk_widget_destroy (window);
5627 }
5628
5629 /*
5630  * GtkColorSelection
5631  */
5632
5633 void
5634 color_selection_ok (GtkWidget               *w,
5635                     GtkColorSelectionDialog *cs)
5636 {
5637   GtkWidget *colorsel;
5638   GdkColor color;
5639
5640   colorsel = gtk_color_selection_dialog_get_color_selection (cs);
5641
5642   gtk_color_selection_get_current_color (GTK_COLOR_SELECTION (colorsel), &color);
5643   gtk_color_selection_set_current_color (GTK_COLOR_SELECTION (colorsel), &color);
5644 }
5645
5646 void
5647 color_selection_changed (GtkWidget *w,
5648                          GtkColorSelectionDialog *cs)
5649 {
5650   GtkWidget *colorsel;
5651   GdkColor color;
5652
5653   colorsel = gtk_color_selection_dialog_get_color_selection (cs);
5654   gtk_color_selection_get_current_color (GTK_COLOR_SELECTION (colorsel), &color);
5655   gtk_color_selection_set_current_color (GTK_COLOR_SELECTION (colorsel), &color);
5656 }
5657
5658 #if 0 /* unused */
5659 static void
5660 opacity_toggled_cb (GtkWidget *w,
5661                     GtkColorSelectionDialog *cs)
5662 {
5663   GtkColorSelection *colorsel;
5664
5665   colorsel = GTK_COLOR_SELECTION (cs->colorsel);
5666   gtk_color_selection_set_has_opacity_control (colorsel,
5667                                                gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w)));
5668 }
5669
5670 static void
5671 palette_toggled_cb (GtkWidget *w,
5672                     GtkColorSelectionDialog *cs)
5673 {
5674   GtkColorSelection *colorsel;
5675
5676   colorsel = GTK_COLOR_SELECTION (cs->colorsel);
5677   gtk_color_selection_set_has_palette (colorsel,
5678                                        gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w)));
5679 }
5680 #endif
5681
5682 void
5683 create_color_selection (GtkWidget *widget)
5684 {
5685   static GtkWidget *window = NULL;
5686
5687   if (!window)
5688     {
5689       GtkWidget *picker;
5690       GtkWidget *hbox;
5691       GtkWidget *label;
5692       GtkWidget *button;
5693       
5694       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
5695       gtk_window_set_screen (GTK_WINDOW (window), 
5696                              gtk_widget_get_screen (widget));
5697                              
5698       g_signal_connect (window, "destroy",
5699                         G_CALLBACK (gtk_widget_destroyed),
5700                         &window);
5701
5702       gtk_window_set_title (GTK_WINDOW (window), "GtkColorButton");
5703       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
5704
5705       hbox = gtk_hbox_new (FALSE, 8);
5706       gtk_container_set_border_width (GTK_CONTAINER (hbox), 8);
5707       gtk_container_add (GTK_CONTAINER (window), hbox);
5708       
5709       label = gtk_label_new ("Pick a color");
5710       gtk_container_add (GTK_CONTAINER (hbox), label);
5711
5712       picker = gtk_color_button_new ();
5713       gtk_color_button_set_use_alpha (GTK_COLOR_BUTTON (picker), TRUE);
5714       gtk_container_add (GTK_CONTAINER (hbox), picker);
5715
5716       button = gtk_button_new_with_mnemonic ("_Props");
5717       gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
5718       g_signal_connect (button, "clicked",
5719                         G_CALLBACK (props_clicked),
5720                         picker);
5721     }
5722
5723   if (!gtk_widget_get_visible (window))
5724     gtk_widget_show_all (window);
5725   else
5726     gtk_widget_destroy (window);
5727 }
5728
5729 void
5730 flipping_toggled_cb (GtkWidget *widget, gpointer data)
5731 {
5732   int state = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
5733   int new_direction = state ? GTK_TEXT_DIR_RTL : GTK_TEXT_DIR_LTR;
5734
5735   gtk_widget_set_default_direction (new_direction);
5736 }
5737
5738 static void
5739 orientable_toggle_orientation (GtkOrientable *orientable)
5740 {
5741   GtkOrientation orientation;
5742
5743   orientation = gtk_orientable_get_orientation (orientable);
5744   gtk_orientable_set_orientation (orientable,
5745                                   orientation == GTK_ORIENTATION_HORIZONTAL ?
5746                                   GTK_ORIENTATION_VERTICAL :
5747                                   GTK_ORIENTATION_HORIZONTAL);
5748
5749   if (GTK_IS_CONTAINER (orientable))
5750     {
5751       GList *children;
5752       GList *child;
5753
5754       children = gtk_container_get_children (GTK_CONTAINER (orientable));
5755
5756       for (child = children; child; child = child->next)
5757         {
5758           if (GTK_IS_ORIENTABLE (child->data))
5759             orientable_toggle_orientation (child->data);
5760         }
5761
5762       g_list_free (children);
5763     }
5764 }
5765
5766 void
5767 flipping_orientation_toggled_cb (GtkWidget *widget, gpointer data)
5768 {
5769   orientable_toggle_orientation (GTK_ORIENTABLE (GTK_DIALOG (gtk_widget_get_toplevel (widget))->vbox));
5770 }
5771
5772 static void
5773 set_direction_recurse (GtkWidget *widget,
5774                        gpointer   data)
5775 {
5776   GtkTextDirection *dir = data;
5777   
5778   gtk_widget_set_direction (widget, *dir);
5779   if (GTK_IS_CONTAINER (widget))
5780     gtk_container_foreach (GTK_CONTAINER (widget),
5781                            set_direction_recurse,
5782                            data);
5783 }
5784
5785 static GtkWidget *
5786 create_forward_back (const char       *title,
5787                      GtkTextDirection  text_dir)
5788 {
5789   GtkWidget *frame = gtk_frame_new (title);
5790   GtkWidget *bbox = gtk_hbutton_box_new ();
5791   GtkWidget *back_button = gtk_button_new_from_stock (GTK_STOCK_GO_BACK);
5792   GtkWidget *forward_button = gtk_button_new_from_stock (GTK_STOCK_GO_FORWARD);
5793
5794   gtk_container_set_border_width (GTK_CONTAINER (bbox), 5);
5795   
5796   gtk_container_add (GTK_CONTAINER (frame), bbox);
5797   gtk_container_add (GTK_CONTAINER (bbox), back_button);
5798   gtk_container_add (GTK_CONTAINER (bbox), forward_button);
5799
5800   set_direction_recurse (frame, &text_dir);
5801
5802   return frame;
5803 }
5804
5805 void
5806 create_flipping (GtkWidget *widget)
5807 {
5808   static GtkWidget *window = NULL;
5809   GtkWidget *check_button, *button;
5810
5811   if (!window)
5812     {
5813       window = gtk_dialog_new ();
5814
5815       gtk_window_set_screen (GTK_WINDOW (window),
5816                              gtk_widget_get_screen (widget));
5817
5818       g_signal_connect (window, "destroy",
5819                         G_CALLBACK (gtk_widget_destroyed),
5820                         &window);
5821
5822       gtk_window_set_title (GTK_WINDOW (window), "Bidirectional Flipping");
5823
5824       check_button = gtk_check_button_new_with_label ("Right-to-left global direction");
5825       gtk_container_set_border_width (GTK_CONTAINER (check_button), 10);
5826       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox),
5827                           check_button, TRUE, TRUE, 0);
5828
5829       if (gtk_widget_get_default_direction () == GTK_TEXT_DIR_RTL)
5830         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button), TRUE);
5831
5832       g_signal_connect (check_button, "toggled",
5833                         G_CALLBACK (flipping_toggled_cb), NULL);
5834
5835       check_button = gtk_check_button_new_with_label ("Toggle orientation of all boxes");
5836       gtk_container_set_border_width (GTK_CONTAINER (check_button), 10);
5837       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
5838                           check_button, TRUE, TRUE, 0);
5839
5840       g_signal_connect (check_button, "toggled",
5841                         G_CALLBACK (flipping_orientation_toggled_cb), NULL);
5842
5843       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
5844                           create_forward_back ("Default", GTK_TEXT_DIR_NONE),
5845                           TRUE, TRUE, 0);
5846
5847       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
5848                           create_forward_back ("Left-to-Right", GTK_TEXT_DIR_LTR),
5849                           TRUE, TRUE, 0);
5850
5851       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
5852                           create_forward_back ("Right-to-Left", GTK_TEXT_DIR_RTL),
5853                           TRUE, TRUE, 0);
5854
5855       button = gtk_button_new_with_label ("Close");
5856       g_signal_connect_swapped (button, "clicked",
5857                                 G_CALLBACK (gtk_widget_destroy), window);
5858       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
5859                           button, TRUE, TRUE, 0);
5860     }
5861   
5862   if (!gtk_widget_get_visible (window))
5863     gtk_widget_show_all (window);
5864   else
5865     gtk_widget_destroy (window);
5866 }
5867
5868 /*
5869  * Focus test
5870  */
5871
5872 static GtkWidget*
5873 make_focus_table (GList **list)
5874 {
5875   GtkWidget *table;
5876   gint i, j;
5877   
5878   table = gtk_table_new (5, 5, FALSE);
5879
5880   i = 0;
5881   j = 0;
5882
5883   while (i < 5)
5884     {
5885       j = 0;
5886       while (j < 5)
5887         {
5888           GtkWidget *widget;
5889           
5890           if ((i + j) % 2)
5891             widget = gtk_entry_new ();
5892           else
5893             widget = gtk_button_new_with_label ("Foo");
5894
5895           *list = g_list_prepend (*list, widget);
5896           
5897           gtk_table_attach (GTK_TABLE (table),
5898                             widget,
5899                             i, i + 1,
5900                             j, j + 1,
5901                             GTK_EXPAND | GTK_FILL,
5902                             GTK_EXPAND | GTK_FILL,
5903                             5, 5);
5904           
5905           ++j;
5906         }
5907
5908       ++i;
5909     }
5910
5911   *list = g_list_reverse (*list);
5912   
5913   return table;
5914 }
5915
5916 static void
5917 create_focus (GtkWidget *widget)
5918 {
5919   static GtkWidget *window = NULL;
5920   
5921   if (!window)
5922     {
5923       GtkWidget *table;
5924       GtkWidget *frame;
5925       GList *list = NULL;
5926       
5927       window = gtk_dialog_new_with_buttons ("Keyboard focus navigation",
5928                                             NULL, 0,
5929                                             GTK_STOCK_CLOSE,
5930                                             GTK_RESPONSE_NONE,
5931                                             NULL);
5932
5933       gtk_window_set_screen (GTK_WINDOW (window),
5934                              gtk_widget_get_screen (widget));
5935
5936       g_signal_connect (window, "destroy",
5937                         G_CALLBACK (gtk_widget_destroyed),
5938                         &window);
5939
5940       g_signal_connect (window, "response",
5941                         G_CALLBACK (gtk_widget_destroy),
5942                         NULL);
5943       
5944       gtk_window_set_title (GTK_WINDOW (window), "Keyboard Focus Navigation");
5945
5946       frame = gtk_frame_new ("Weird tab focus chain");
5947
5948       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
5949                           frame, TRUE, TRUE, 0);
5950       
5951       table = make_focus_table (&list);
5952
5953       gtk_container_add (GTK_CONTAINER (frame), table);
5954
5955       gtk_container_set_focus_chain (GTK_CONTAINER (table),
5956                                      list);
5957
5958       g_list_free (list);
5959       
5960       frame = gtk_frame_new ("Default tab focus chain");
5961
5962       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
5963                           frame, TRUE, TRUE, 0);
5964
5965       list = NULL;
5966       table = make_focus_table (&list);
5967
5968       g_list_free (list);
5969       
5970       gtk_container_add (GTK_CONTAINER (frame), table);      
5971     }
5972   
5973   if (!gtk_widget_get_visible (window))
5974     gtk_widget_show_all (window);
5975   else
5976     gtk_widget_destroy (window);
5977 }
5978
5979 /*
5980  * GtkFontSelection
5981  */
5982
5983 void
5984 font_selection_ok (GtkWidget              *w,
5985                    GtkFontSelectionDialog *fs)
5986 {
5987   gchar *s = gtk_font_selection_dialog_get_font_name (fs);
5988
5989   g_print ("%s\n", s);
5990   g_free (s);
5991   gtk_widget_destroy (GTK_WIDGET (fs));
5992 }
5993
5994 void
5995 create_font_selection (GtkWidget *widget)
5996 {
5997   static GtkWidget *window = NULL;
5998
5999   if (!window)
6000     {
6001       GtkWidget *picker;
6002       GtkWidget *hbox;
6003       GtkWidget *label;
6004       
6005       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6006       gtk_window_set_screen (GTK_WINDOW (window),
6007                              gtk_widget_get_screen (widget));
6008
6009       g_signal_connect (window, "destroy",
6010                         G_CALLBACK (gtk_widget_destroyed),
6011                         &window);
6012
6013       gtk_window_set_title (GTK_WINDOW (window), "GtkFontButton");
6014       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
6015
6016       hbox = gtk_hbox_new (FALSE, 8);
6017       gtk_container_set_border_width (GTK_CONTAINER (hbox), 8);
6018       gtk_container_add (GTK_CONTAINER (window), hbox);
6019       
6020       label = gtk_label_new ("Pick a font");
6021       gtk_container_add (GTK_CONTAINER (hbox), label);
6022
6023       picker = gtk_font_button_new ();
6024       gtk_font_button_set_use_font (GTK_FONT_BUTTON (picker), TRUE);
6025       gtk_container_add (GTK_CONTAINER (hbox), picker);
6026     }
6027   
6028   if (!gtk_widget_get_visible (window))
6029     gtk_widget_show_all (window);
6030   else
6031     gtk_widget_destroy (window);
6032 }
6033
6034 /*
6035  * GtkDialog
6036  */
6037
6038 static GtkWidget *dialog_window = NULL;
6039
6040 static void
6041 label_toggle (GtkWidget  *widget,
6042               GtkWidget **label)
6043 {
6044   if (!(*label))
6045     {
6046       *label = gtk_label_new ("Dialog Test");
6047       g_signal_connect (*label,
6048                         "destroy",
6049                         G_CALLBACK (gtk_widget_destroyed),
6050                         label);
6051       gtk_misc_set_padding (GTK_MISC (*label), 10, 10);
6052       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog_window)->vbox), 
6053                           *label, TRUE, TRUE, 0);
6054       gtk_widget_show (*label);
6055     }
6056   else
6057     gtk_widget_destroy (*label);
6058 }
6059
6060 #define RESPONSE_TOGGLE_SEPARATOR 1
6061
6062 static void
6063 print_response (GtkWidget *dialog,
6064                 gint       response_id,
6065                 gpointer   data)
6066 {
6067   g_print ("response signal received (%d)\n", response_id);
6068
6069   if (response_id == RESPONSE_TOGGLE_SEPARATOR)
6070     {
6071       gtk_dialog_set_has_separator (GTK_DIALOG (dialog),
6072                                     !gtk_dialog_get_has_separator (GTK_DIALOG (dialog)));
6073     }
6074 }
6075
6076 static void
6077 create_dialog (GtkWidget *widget)
6078 {
6079   static GtkWidget *label;
6080   GtkWidget *button;
6081
6082   if (!dialog_window)
6083     {
6084       /* This is a terrible example; it's much simpler to create
6085        * dialogs than this. Don't use testgtk for example code,
6086        * use gtk-demo ;-)
6087        */
6088       
6089       dialog_window = gtk_dialog_new ();
6090       gtk_window_set_screen (GTK_WINDOW (dialog_window),
6091                              gtk_widget_get_screen (widget));
6092
6093       g_signal_connect (dialog_window,
6094                         "response",
6095                         G_CALLBACK (print_response),
6096                         NULL);
6097       
6098       g_signal_connect (dialog_window, "destroy",
6099                         G_CALLBACK (gtk_widget_destroyed),
6100                         &dialog_window);
6101
6102       gtk_window_set_title (GTK_WINDOW (dialog_window), "GtkDialog");
6103       gtk_container_set_border_width (GTK_CONTAINER (dialog_window), 0);
6104
6105       button = gtk_button_new_with_label ("OK");
6106       gtk_widget_set_can_default (button, TRUE);
6107       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog_window)->action_area), 
6108                           button, TRUE, TRUE, 0);
6109       gtk_widget_grab_default (button);
6110       gtk_widget_show (button);
6111
6112       button = gtk_button_new_with_label ("Toggle");
6113       g_signal_connect (button, "clicked",
6114                         G_CALLBACK (label_toggle),
6115                         &label);
6116       gtk_widget_set_can_default (button, TRUE);
6117       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog_window)->action_area),
6118                           button, TRUE, TRUE, 0);
6119       gtk_widget_show (button);
6120
6121       label = NULL;
6122       
6123       button = gtk_button_new_with_label ("Separator");
6124
6125       gtk_widget_set_can_default (button, TRUE);
6126
6127       gtk_dialog_add_action_widget (GTK_DIALOG (dialog_window),
6128                                     button,
6129                                     RESPONSE_TOGGLE_SEPARATOR);
6130       gtk_widget_show (button);
6131     }
6132
6133   if (!gtk_widget_get_visible (dialog_window))
6134     gtk_widget_show (dialog_window);
6135   else
6136     gtk_widget_destroy (dialog_window);
6137 }
6138
6139 /* Display & Screen test 
6140  */
6141
6142 typedef struct
6143 {
6144   GtkWidget *combo;
6145   GtkWidget *entry;
6146   GtkWidget *radio_dpy;
6147   GtkWidget *toplevel;
6148   GtkWidget *dialog_window;
6149 } ScreenDisplaySelection;
6150
6151 static void
6152 screen_display_check (GtkWidget *widget, ScreenDisplaySelection *data)
6153 {
6154   const gchar *display_name;
6155   GdkDisplay *display = gtk_widget_get_display (widget);
6156   GtkWidget *dialog;
6157   GdkScreen *new_screen = NULL;
6158   GdkScreen *current_screen = gtk_widget_get_screen (widget);
6159   
6160   if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (data->radio_dpy)))
6161     {
6162       display_name = gtk_entry_get_text (GTK_ENTRY (data->entry));
6163       display = gdk_display_open (display_name);
6164       
6165       if (!display)
6166         {
6167           dialog = gtk_message_dialog_new (GTK_WINDOW (gtk_widget_get_toplevel (widget)),
6168                                            GTK_DIALOG_DESTROY_WITH_PARENT,
6169                                            GTK_MESSAGE_ERROR,
6170                                            GTK_BUTTONS_OK,
6171                                            "The display :\n%s\ncannot be opened",
6172                                            display_name);
6173           gtk_window_set_screen (GTK_WINDOW (dialog), current_screen);
6174           gtk_widget_show (dialog);
6175           g_signal_connect (dialog, "response",
6176                             G_CALLBACK (gtk_widget_destroy),
6177                             NULL);
6178         }
6179       else
6180         {
6181           GtkTreeModel *model = gtk_combo_box_get_model (GTK_COMBO_BOX (data->combo));
6182           gint i = 0;
6183           GtkTreeIter iter;
6184           gboolean found = FALSE;
6185           while (gtk_tree_model_iter_nth_child (model, &iter, NULL, i++))
6186             {
6187               gchar *name;
6188               gtk_tree_model_get (model, &iter, 0, &name, -1);
6189               found = !g_ascii_strcasecmp (display_name, name);
6190               g_free (name);
6191
6192               if (found)
6193                 break;
6194             }
6195           if (!found)
6196             gtk_combo_box_append_text (GTK_COMBO_BOX (data->combo), display_name);
6197           new_screen = gdk_display_get_default_screen (display);
6198         }
6199     }
6200   else
6201     {
6202       gint number_of_screens = gdk_display_get_n_screens (display);
6203       gint screen_num = gdk_screen_get_number (current_screen);
6204       if ((screen_num +1) < number_of_screens)
6205         new_screen = gdk_display_get_screen (display, screen_num + 1);
6206       else
6207         new_screen = gdk_display_get_screen (display, 0);
6208     }
6209   
6210   if (new_screen) 
6211     {
6212       gtk_window_set_screen (GTK_WINDOW (data->toplevel), new_screen);
6213       gtk_widget_destroy (data->dialog_window);
6214     }
6215 }
6216
6217 void
6218 screen_display_destroy_diag (GtkWidget *widget, GtkWidget *data)
6219 {
6220   gtk_widget_destroy (data);
6221 }
6222
6223 void
6224 create_display_screen (GtkWidget *widget)
6225 {
6226   GtkWidget *table, *frame, *window, *combo_dpy, *vbox;
6227   GtkWidget *radio_dpy, *radio_scr, *applyb, *cancelb;
6228   GtkWidget *bbox;
6229   ScreenDisplaySelection *scr_dpy_data;
6230   GdkScreen *screen = gtk_widget_get_screen (widget);
6231   GdkDisplay *display = gdk_screen_get_display (screen);
6232
6233   window = g_object_new (gtk_window_get_type (),
6234                            "screen", screen,
6235                            "user_data", NULL,
6236                            "type", GTK_WINDOW_TOPLEVEL,
6237                            "title",
6238                            "Screen or Display selection",
6239                            "border_width", 10, NULL);
6240   g_signal_connect (window, "destroy", 
6241                     G_CALLBACK (gtk_widget_destroy), NULL);
6242
6243   vbox = gtk_vbox_new (FALSE, 3);
6244   gtk_container_add (GTK_CONTAINER (window), vbox);
6245   
6246   frame = gtk_frame_new ("Select screen or display");
6247   gtk_container_add (GTK_CONTAINER (vbox), frame);
6248   
6249   table = gtk_table_new (2, 2, TRUE);
6250   gtk_table_set_row_spacings (GTK_TABLE (table), 3);
6251   gtk_table_set_col_spacings (GTK_TABLE (table), 3);
6252
6253   gtk_container_add (GTK_CONTAINER (frame), table);
6254
6255   radio_dpy = gtk_radio_button_new_with_label (NULL, "move to another X display");
6256   if (gdk_display_get_n_screens(display) > 1)
6257     radio_scr = gtk_radio_button_new_with_label 
6258     (gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio_dpy)), "move to next screen");
6259   else
6260     {    
6261       radio_scr = gtk_radio_button_new_with_label 
6262         (gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio_dpy)), 
6263          "only one screen on the current display");
6264       gtk_widget_set_sensitive (radio_scr, FALSE);
6265     }
6266   combo_dpy = gtk_combo_box_new_text ();
6267   gtk_combo_box_append_text (GTK_COMBO_BOX (combo_dpy), "diabolo:0.0");
6268   gtk_entry_set_text (GTK_ENTRY (gtk_bin_get_child (GTK_BIN (combo_dpy))),
6269                       "<hostname>:<X Server Num>.<Screen Num>");
6270
6271   gtk_table_attach_defaults (GTK_TABLE (table), radio_dpy, 0, 1, 0, 1);
6272   gtk_table_attach_defaults (GTK_TABLE (table), radio_scr, 0, 1, 1, 2);
6273   gtk_table_attach_defaults (GTK_TABLE (table), combo_dpy, 1, 2, 0, 1);
6274
6275   bbox = gtk_hbutton_box_new ();
6276   applyb = gtk_button_new_from_stock (GTK_STOCK_APPLY);
6277   cancelb = gtk_button_new_from_stock (GTK_STOCK_CANCEL);
6278   
6279   gtk_container_add (GTK_CONTAINER (vbox), bbox);
6280
6281   gtk_container_add (GTK_CONTAINER (bbox), applyb);
6282   gtk_container_add (GTK_CONTAINER (bbox), cancelb);
6283
6284   scr_dpy_data = g_new0 (ScreenDisplaySelection, 1);
6285
6286   scr_dpy_data->entry = gtk_bin_get_child (GTK_BIN (combo_dpy));
6287   scr_dpy_data->radio_dpy = radio_dpy;
6288   scr_dpy_data->toplevel = gtk_widget_get_toplevel (widget);
6289   scr_dpy_data->dialog_window = window;
6290
6291   g_signal_connect (cancelb, "clicked", 
6292                     G_CALLBACK (screen_display_destroy_diag), window);
6293   g_signal_connect (applyb, "clicked", 
6294                     G_CALLBACK (screen_display_check), scr_dpy_data);
6295   gtk_widget_show_all (window);
6296 }
6297
6298 /* Event Watcher
6299  */
6300 static gboolean event_watcher_enter_id = 0;
6301 static gboolean event_watcher_leave_id = 0;
6302
6303 static gboolean
6304 event_watcher (GSignalInvocationHint *ihint,
6305                guint                  n_param_values,
6306                const GValue          *param_values,
6307                gpointer               data)
6308 {
6309   g_print ("Watch: \"%s\" emitted for %s\n",
6310            g_signal_name (ihint->signal_id),
6311            G_OBJECT_TYPE_NAME (g_value_get_object (param_values + 0)));
6312
6313   return TRUE;
6314 }
6315
6316 static void
6317 event_watcher_down (void)
6318 {
6319   if (event_watcher_enter_id)
6320     {
6321       guint signal_id;
6322
6323       signal_id = g_signal_lookup ("enter_notify_event", GTK_TYPE_WIDGET);
6324       g_signal_remove_emission_hook (signal_id, event_watcher_enter_id);
6325       event_watcher_enter_id = 0;
6326       signal_id = g_signal_lookup ("leave_notify_event", GTK_TYPE_WIDGET);
6327       g_signal_remove_emission_hook (signal_id, event_watcher_leave_id);
6328       event_watcher_leave_id = 0;
6329     }
6330 }
6331
6332 static void
6333 event_watcher_toggle (void)
6334 {
6335   if (event_watcher_enter_id)
6336     event_watcher_down ();
6337   else
6338     {
6339       guint signal_id;
6340
6341       signal_id = g_signal_lookup ("enter_notify_event", GTK_TYPE_WIDGET);
6342       event_watcher_enter_id = g_signal_add_emission_hook (signal_id, 0, event_watcher, NULL, NULL);
6343       signal_id = g_signal_lookup ("leave_notify_event", GTK_TYPE_WIDGET);
6344       event_watcher_leave_id = g_signal_add_emission_hook (signal_id, 0, event_watcher, NULL, NULL);
6345     }
6346 }
6347
6348 static void
6349 create_event_watcher (GtkWidget *widget)
6350 {
6351   GtkWidget *button;
6352
6353   if (!dialog_window)
6354     {
6355       dialog_window = gtk_dialog_new ();
6356       gtk_window_set_screen (GTK_WINDOW (dialog_window),
6357                              gtk_widget_get_screen (widget));
6358
6359       g_signal_connect (dialog_window, "destroy",
6360                         G_CALLBACK (gtk_widget_destroyed),
6361                         &dialog_window);
6362       g_signal_connect (dialog_window, "destroy",
6363                         G_CALLBACK (event_watcher_down),
6364                         NULL);
6365
6366       gtk_window_set_title (GTK_WINDOW (dialog_window), "Event Watcher");
6367       gtk_container_set_border_width (GTK_CONTAINER (dialog_window), 0);
6368       gtk_widget_set_size_request (dialog_window, 200, 110);
6369
6370       button = gtk_toggle_button_new_with_label ("Activate Watch");
6371       g_signal_connect (button, "clicked",
6372                         G_CALLBACK (event_watcher_toggle),
6373                         NULL);
6374       gtk_container_set_border_width (GTK_CONTAINER (button), 10);
6375       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog_window)->vbox), 
6376                           button, TRUE, TRUE, 0);
6377       gtk_widget_show (button);
6378
6379       button = gtk_button_new_with_label ("Close");
6380       g_signal_connect_swapped (button, "clicked",
6381                                 G_CALLBACK (gtk_widget_destroy),
6382                                 dialog_window);
6383       gtk_widget_set_can_default (button, TRUE);
6384       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog_window)->action_area),
6385                           button, TRUE, TRUE, 0);
6386       gtk_widget_grab_default (button);
6387       gtk_widget_show (button);
6388     }
6389
6390   if (!gtk_widget_get_visible (dialog_window))
6391     gtk_widget_show (dialog_window);
6392   else
6393     gtk_widget_destroy (dialog_window);
6394 }
6395
6396 /*
6397  * GtkRange
6398  */
6399
6400 static gchar*
6401 reformat_value (GtkScale *scale,
6402                 gdouble   value)
6403 {
6404   return g_strdup_printf ("-->%0.*g<--",
6405                           gtk_scale_get_digits (scale), value);
6406 }
6407
6408 static void
6409 create_range_controls (GtkWidget *widget)
6410 {
6411   static GtkWidget *window = NULL;
6412   GtkWidget *box1;
6413   GtkWidget *box2;
6414   GtkWidget *button;
6415   GtkWidget *scrollbar;
6416   GtkWidget *scale;
6417   GtkWidget *separator;
6418   GtkObject *adjustment;
6419   GtkWidget *hbox;
6420
6421   if (!window)
6422     {
6423       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6424
6425       gtk_window_set_screen (GTK_WINDOW (window),
6426                              gtk_widget_get_screen (widget));
6427
6428       g_signal_connect (window, "destroy",
6429                         G_CALLBACK (gtk_widget_destroyed),
6430                         &window);
6431
6432       gtk_window_set_title (GTK_WINDOW (window), "range controls");
6433       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
6434
6435
6436       box1 = gtk_vbox_new (FALSE, 0);
6437       gtk_container_add (GTK_CONTAINER (window), box1);
6438       gtk_widget_show (box1);
6439
6440
6441       box2 = gtk_vbox_new (FALSE, 10);
6442       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
6443       gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
6444       gtk_widget_show (box2);
6445
6446
6447       adjustment = gtk_adjustment_new (0.0, 0.0, 101.0, 0.1, 1.0, 1.0);
6448
6449       scale = gtk_hscale_new (GTK_ADJUSTMENT (adjustment));
6450       gtk_widget_set_size_request (GTK_WIDGET (scale), 150, -1);
6451       gtk_range_set_update_policy (GTK_RANGE (scale), GTK_UPDATE_DELAYED);
6452       gtk_scale_set_digits (GTK_SCALE (scale), 1);
6453       gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE);
6454       gtk_box_pack_start (GTK_BOX (box2), scale, TRUE, TRUE, 0);
6455       gtk_widget_show (scale);
6456
6457       scrollbar = gtk_hscrollbar_new (GTK_ADJUSTMENT (adjustment));
6458       gtk_range_set_update_policy (GTK_RANGE (scrollbar), 
6459                                    GTK_UPDATE_CONTINUOUS);
6460       gtk_box_pack_start (GTK_BOX (box2), scrollbar, TRUE, TRUE, 0);
6461       gtk_widget_show (scrollbar);
6462
6463       scale = gtk_hscale_new (GTK_ADJUSTMENT (adjustment));
6464       gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE);
6465       g_signal_connect (scale,
6466                         "format_value",
6467                         G_CALLBACK (reformat_value),
6468                         NULL);
6469       gtk_box_pack_start (GTK_BOX (box2), scale, TRUE, TRUE, 0);
6470       gtk_widget_show (scale);
6471       
6472       hbox = gtk_hbox_new (FALSE, 0);
6473
6474       scale = gtk_vscale_new (GTK_ADJUSTMENT (adjustment));
6475       gtk_widget_set_size_request (scale, -1, 200);
6476       gtk_scale_set_digits (GTK_SCALE (scale), 2);
6477       gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE);
6478       gtk_box_pack_start (GTK_BOX (hbox), scale, TRUE, TRUE, 0);
6479       gtk_widget_show (scale);
6480
6481       scale = gtk_vscale_new (GTK_ADJUSTMENT (adjustment));
6482       gtk_widget_set_size_request (scale, -1, 200);
6483       gtk_scale_set_digits (GTK_SCALE (scale), 2);
6484       gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE);
6485       gtk_range_set_inverted (GTK_RANGE (scale), TRUE);
6486       gtk_box_pack_start (GTK_BOX (hbox), scale, TRUE, TRUE, 0);
6487       gtk_widget_show (scale);
6488
6489       scale = gtk_vscale_new (GTK_ADJUSTMENT (adjustment));
6490       gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE);
6491       g_signal_connect (scale,
6492                         "format_value",
6493                         G_CALLBACK (reformat_value),
6494                         NULL);
6495       gtk_box_pack_start (GTK_BOX (hbox), scale, TRUE, TRUE, 0);
6496       gtk_widget_show (scale);
6497
6498       
6499       gtk_box_pack_start (GTK_BOX (box2), hbox, TRUE, TRUE, 0);
6500       gtk_widget_show (hbox);
6501       
6502       separator = gtk_hseparator_new ();
6503       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
6504       gtk_widget_show (separator);
6505
6506
6507       box2 = gtk_vbox_new (FALSE, 10);
6508       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
6509       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
6510       gtk_widget_show (box2);
6511
6512
6513       button = gtk_button_new_with_label ("close");
6514       g_signal_connect_swapped (button, "clicked",
6515                                 G_CALLBACK (gtk_widget_destroy),
6516                                 window);
6517       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
6518       gtk_widget_set_can_default (button, TRUE);
6519       gtk_widget_grab_default (button);
6520       gtk_widget_show (button);
6521     }
6522
6523   if (!gtk_widget_get_visible (window))
6524     gtk_widget_show (window);
6525   else
6526     gtk_widget_destroy (window);
6527 }
6528
6529 /*
6530  * GtkRulers
6531  */
6532
6533 void
6534 create_rulers (GtkWidget *widget)
6535 {
6536   static GtkWidget *window = NULL;
6537   GtkWidget *table;
6538   GtkWidget *ruler;
6539
6540   if (!window)
6541     {
6542       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6543
6544       gtk_window_set_screen (GTK_WINDOW (window),
6545                              gtk_widget_get_screen (widget));
6546
6547       g_object_set (window, "allow_shrink", TRUE, "allow_grow", TRUE, NULL);
6548
6549       g_signal_connect (window, "destroy",
6550                         G_CALLBACK (gtk_widget_destroyed),
6551                         &window);
6552
6553       gtk_window_set_title (GTK_WINDOW (window), "rulers");
6554       gtk_widget_set_size_request (window, 300, 300);
6555       gtk_widget_set_events (window, 
6556                              GDK_POINTER_MOTION_MASK 
6557                              | GDK_POINTER_MOTION_HINT_MASK);
6558       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
6559
6560       table = gtk_table_new (2, 2, FALSE);
6561       gtk_container_add (GTK_CONTAINER (window), table);
6562       gtk_widget_show (table);
6563
6564       ruler = gtk_hruler_new ();
6565       gtk_ruler_set_metric (GTK_RULER (ruler), GTK_CENTIMETERS);
6566       gtk_ruler_set_range (GTK_RULER (ruler), 100, 0, 0, 20);
6567
6568       g_signal_connect_swapped (window, 
6569                                 "motion_notify_event",
6570                                 G_CALLBACK (GTK_WIDGET_GET_CLASS (ruler)->motion_notify_event),
6571                                 ruler);
6572       
6573       gtk_table_attach (GTK_TABLE (table), ruler, 1, 2, 0, 1,
6574                         GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
6575       gtk_widget_show (ruler);
6576
6577
6578       ruler = gtk_vruler_new ();
6579       gtk_ruler_set_range (GTK_RULER (ruler), 5, 15, 0, 20);
6580
6581       g_signal_connect_swapped (window, 
6582                                 "motion_notify_event",
6583                                 G_CALLBACK (GTK_WIDGET_GET_CLASS (ruler)->motion_notify_event),
6584                                 ruler);
6585       
6586       gtk_table_attach (GTK_TABLE (table), ruler, 0, 1, 1, 2,
6587                         GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
6588       gtk_widget_show (ruler);
6589     }
6590
6591   if (!gtk_widget_get_visible (window))
6592     gtk_widget_show (window);
6593   else
6594     gtk_widget_destroy (window);
6595 }
6596
6597 struct {
6598   GdkColor color;
6599   gchar *name;
6600 } text_colors[] = {
6601  { { 0, 0x0000, 0x0000, 0x0000 }, "black" },
6602  { { 0, 0xFFFF, 0xFFFF, 0xFFFF }, "white" },
6603  { { 0, 0xFFFF, 0x0000, 0x0000 }, "red" },
6604  { { 0, 0x0000, 0xFFFF, 0x0000 }, "green" },
6605  { { 0, 0x0000, 0x0000, 0xFFFF }, "blue" }, 
6606  { { 0, 0x0000, 0xFFFF, 0xFFFF }, "cyan" },
6607  { { 0, 0xFFFF, 0x0000, 0xFFFF }, "magenta" },
6608  { { 0, 0xFFFF, 0xFFFF, 0x0000 }, "yellow" }
6609 };
6610
6611 int ntext_colors = sizeof(text_colors) / sizeof(text_colors[0]);
6612
6613 /*
6614  * GtkNotebook
6615  */
6616
6617 static char * book_open_xpm[] = {
6618 "16 16 4 1",
6619 "       c None s None",
6620 ".      c black",
6621 "X      c #808080",
6622 "o      c white",
6623 "                ",
6624 "  ..            ",
6625 " .Xo.    ...    ",
6626 " .Xoo. ..oo.    ",
6627 " .Xooo.Xooo...  ",
6628 " .Xooo.oooo.X.  ",
6629 " .Xooo.Xooo.X.  ",
6630 " .Xooo.oooo.X.  ",
6631 " .Xooo.Xooo.X.  ",
6632 " .Xooo.oooo.X.  ",
6633 "  .Xoo.Xoo..X.  ",
6634 "   .Xo.o..ooX.  ",
6635 "    .X..XXXXX.  ",
6636 "    ..X.......  ",
6637 "     ..         ",
6638 "                "};
6639
6640 static char * book_closed_xpm[] = {
6641 "16 16 6 1",
6642 "       c None s None",
6643 ".      c black",
6644 "X      c red",
6645 "o      c yellow",
6646 "O      c #808080",
6647 "#      c white",
6648 "                ",
6649 "       ..       ",
6650 "     ..XX.      ",
6651 "   ..XXXXX.     ",
6652 " ..XXXXXXXX.    ",
6653 ".ooXXXXXXXXX.   ",
6654 "..ooXXXXXXXXX.  ",
6655 ".X.ooXXXXXXXXX. ",
6656 ".XX.ooXXXXXX..  ",
6657 " .XX.ooXXX..#O  ",
6658 "  .XX.oo..##OO. ",
6659 "   .XX..##OO..  ",
6660 "    .X.#OO..    ",
6661 "     ..O..      ",
6662 "      ..        ",
6663 "                "};
6664
6665 GdkPixbuf *book_open;
6666 GdkPixbuf *book_closed;
6667 GtkWidget *sample_notebook;
6668
6669 static void
6670 set_page_image (GtkNotebook *notebook, gint page_num, GdkPixbuf *pixbuf)
6671 {
6672   GtkWidget *page_widget;
6673   GtkWidget *pixwid;
6674
6675   page_widget = gtk_notebook_get_nth_page (notebook, page_num);
6676
6677   pixwid = g_object_get_data (G_OBJECT (page_widget), "tab_pixmap");
6678   gtk_image_set_from_pixbuf (GTK_IMAGE (pixwid), pixbuf);
6679   
6680   pixwid = g_object_get_data (G_OBJECT (page_widget), "menu_pixmap");
6681   gtk_image_set_from_pixbuf (GTK_IMAGE (pixwid), pixbuf);
6682 }
6683
6684 static void
6685 page_switch (GtkWidget *widget, GtkNotebookPage *page, gint page_num)
6686 {
6687   GtkNotebook *notebook = GTK_NOTEBOOK (widget);
6688   gint old_page_num = gtk_notebook_get_current_page (notebook);
6689  
6690   if (page_num == old_page_num)
6691     return;
6692
6693   set_page_image (notebook, page_num, book_open);
6694
6695   if (old_page_num != -1)
6696     set_page_image (notebook, old_page_num, book_closed);
6697 }
6698
6699 static void
6700 tab_fill (GtkToggleButton *button, GtkWidget *child)
6701 {
6702   gtk_container_child_set (GTK_CONTAINER (sample_notebook), child,
6703                            "tab-fill", gtk_toggle_button_get_active (button),
6704                            NULL);
6705 }
6706
6707 static void
6708 tab_expand (GtkToggleButton *button, GtkWidget *child)
6709 {
6710   gtk_container_child_set (GTK_CONTAINER (sample_notebook), child,
6711                            "tab-expand", gtk_toggle_button_get_active (button),
6712                            NULL);
6713 }
6714
6715 static void
6716 create_pages (GtkNotebook *notebook, gint start, gint end)
6717 {
6718   GtkWidget *child = NULL;
6719   GtkWidget *button;
6720   GtkWidget *label;
6721   GtkWidget *hbox;
6722   GtkWidget *vbox;
6723   GtkWidget *label_box;
6724   GtkWidget *menu_box;
6725   GtkWidget *pixwid;
6726   gint i;
6727   char buffer[32];
6728   char accel_buffer[32];
6729
6730   for (i = start; i <= end; i++)
6731     {
6732       sprintf (buffer, "Page %d", i);
6733       sprintf (accel_buffer, "Page _%d", i);
6734
6735       child = gtk_frame_new (buffer);
6736       gtk_container_set_border_width (GTK_CONTAINER (child), 10);
6737
6738       vbox = gtk_vbox_new (TRUE,0);
6739       gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
6740       gtk_container_add (GTK_CONTAINER (child), vbox);
6741
6742       hbox = gtk_hbox_new (TRUE,0);
6743       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 5);
6744
6745       button = gtk_check_button_new_with_label ("Fill Tab");
6746       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
6747       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
6748       g_signal_connect (button, "toggled",
6749                         G_CALLBACK (tab_fill), child);
6750
6751       button = gtk_check_button_new_with_label ("Expand Tab");
6752       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
6753       g_signal_connect (button, "toggled",
6754                         G_CALLBACK (tab_expand), child);
6755
6756       button = gtk_button_new_with_label ("Hide Page");
6757       gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 5);
6758       g_signal_connect_swapped (button, "clicked",
6759                                 G_CALLBACK (gtk_widget_hide),
6760                                 child);
6761
6762       gtk_widget_show_all (child);
6763
6764       label_box = gtk_hbox_new (FALSE, 0);
6765       pixwid = gtk_image_new_from_pixbuf (book_closed);
6766       g_object_set_data (G_OBJECT (child), "tab_pixmap", pixwid);
6767                            
6768       gtk_box_pack_start (GTK_BOX (label_box), pixwid, FALSE, TRUE, 0);
6769       gtk_misc_set_padding (GTK_MISC (pixwid), 3, 1);
6770       label = gtk_label_new_with_mnemonic (accel_buffer);
6771       gtk_box_pack_start (GTK_BOX (label_box), label, FALSE, TRUE, 0);
6772       gtk_widget_show_all (label_box);
6773       
6774                                        
6775       menu_box = gtk_hbox_new (FALSE, 0);
6776       pixwid = gtk_image_new_from_pixbuf (book_closed);
6777       g_object_set_data (G_OBJECT (child), "menu_pixmap", pixwid);
6778       
6779       gtk_box_pack_start (GTK_BOX (menu_box), pixwid, FALSE, TRUE, 0);
6780       gtk_misc_set_padding (GTK_MISC (pixwid), 3, 1);
6781       label = gtk_label_new (buffer);
6782       gtk_box_pack_start (GTK_BOX (menu_box), label, FALSE, TRUE, 0);
6783       gtk_widget_show_all (menu_box);
6784
6785       gtk_notebook_append_page_menu (notebook, child, label_box, menu_box);
6786     }
6787 }
6788
6789 static void
6790 rotate_notebook (GtkButton   *button,
6791                  GtkNotebook *notebook)
6792 {
6793   gtk_notebook_set_tab_pos (notebook, (notebook->tab_pos + 1) % 4);
6794 }
6795
6796 static void
6797 show_all_pages (GtkButton   *button,
6798                 GtkNotebook *notebook)
6799 {  
6800   gtk_container_foreach (GTK_CONTAINER (notebook),
6801                          (GtkCallback) gtk_widget_show, NULL);
6802 }
6803
6804 static void
6805 notebook_type_changed (GtkWidget *optionmenu,
6806                        gpointer   data)
6807 {
6808   GtkNotebook *notebook;
6809   gint i, c;
6810
6811   enum {
6812     STANDARD,
6813     NOTABS,
6814     BORDERLESS,
6815     SCROLLABLE
6816   };
6817
6818   notebook = GTK_NOTEBOOK (data);
6819
6820   c = gtk_combo_box_get_active (GTK_COMBO_BOX (optionmenu));
6821
6822   switch (c)
6823     {
6824     case STANDARD:
6825       /* standard notebook */
6826       gtk_notebook_set_show_tabs (notebook, TRUE);
6827       gtk_notebook_set_show_border (notebook, TRUE);
6828       gtk_notebook_set_scrollable (notebook, FALSE);
6829       break;
6830
6831     case NOTABS:
6832       /* notabs notebook */
6833       gtk_notebook_set_show_tabs (notebook, FALSE);
6834       gtk_notebook_set_show_border (notebook, TRUE);
6835       break;
6836
6837     case BORDERLESS:
6838       /* borderless */
6839       gtk_notebook_set_show_tabs (notebook, FALSE);
6840       gtk_notebook_set_show_border (notebook, FALSE);
6841       break;
6842
6843     case SCROLLABLE:  
6844       /* scrollable */
6845       gtk_notebook_set_show_tabs (notebook, TRUE);
6846       gtk_notebook_set_show_border (notebook, TRUE);
6847       gtk_notebook_set_scrollable (notebook, TRUE);
6848       if (g_list_length (notebook->children) == 5)
6849         create_pages (notebook, 6, 15);
6850       
6851       return;
6852       break;
6853     }
6854   
6855   if (g_list_length (notebook->children) == 15)
6856     for (i = 0; i < 10; i++)
6857       gtk_notebook_remove_page (notebook, 5);
6858 }
6859
6860 static void
6861 notebook_popup (GtkToggleButton *button,
6862                 GtkNotebook     *notebook)
6863 {
6864   if (button->active)
6865     gtk_notebook_popup_enable (notebook);
6866   else
6867     gtk_notebook_popup_disable (notebook);
6868 }
6869
6870 static void
6871 create_notebook (GtkWidget *widget)
6872 {
6873   static GtkWidget *window = NULL;
6874   GtkWidget *box1;
6875   GtkWidget *box2;
6876   GtkWidget *button;
6877   GtkWidget *separator;
6878   GtkWidget *omenu;
6879   GtkWidget *label;
6880
6881   static gchar *items[] =
6882   {
6883     "Standard",
6884     "No tabs",
6885     "Borderless",
6886     "Scrollable"
6887   };
6888   
6889   if (!window)
6890     {
6891       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6892       gtk_window_set_screen (GTK_WINDOW (window),
6893                              gtk_widget_get_screen (widget));
6894
6895       g_signal_connect (window, "destroy",
6896                         G_CALLBACK (gtk_widget_destroyed),
6897                         &window);
6898
6899       gtk_window_set_title (GTK_WINDOW (window), "notebook");
6900       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
6901
6902       box1 = gtk_vbox_new (FALSE, 0);
6903       gtk_container_add (GTK_CONTAINER (window), box1);
6904
6905       sample_notebook = gtk_notebook_new ();
6906       g_signal_connect (sample_notebook, "switch_page",
6907                         G_CALLBACK (page_switch), NULL);
6908       gtk_notebook_set_tab_pos (GTK_NOTEBOOK (sample_notebook), GTK_POS_TOP);
6909       gtk_box_pack_start (GTK_BOX (box1), sample_notebook, TRUE, TRUE, 0);
6910       gtk_container_set_border_width (GTK_CONTAINER (sample_notebook), 10);
6911
6912       gtk_widget_realize (sample_notebook);
6913
6914       if (!book_open)
6915         book_open = gdk_pixbuf_new_from_xpm_data ((const char **)book_open_xpm);
6916                                                   
6917       if (!book_closed)
6918         book_closed = gdk_pixbuf_new_from_xpm_data ((const char **)book_closed_xpm);
6919
6920       create_pages (GTK_NOTEBOOK (sample_notebook), 1, 5);
6921
6922       separator = gtk_hseparator_new ();
6923       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 10);
6924       
6925       box2 = gtk_hbox_new (FALSE, 5);
6926       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
6927       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
6928
6929       button = gtk_check_button_new_with_label ("popup menu");
6930       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, FALSE, 0);
6931       g_signal_connect (button, "clicked",
6932                         G_CALLBACK (notebook_popup),
6933                         sample_notebook);
6934
6935       box2 = gtk_hbox_new (FALSE, 5);
6936       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
6937       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
6938
6939       label = gtk_label_new ("Notebook Style :");
6940       gtk_box_pack_start (GTK_BOX (box2), label, FALSE, TRUE, 0);
6941
6942       omenu = build_option_menu (items, G_N_ELEMENTS (items), 0,
6943                                  notebook_type_changed,
6944                                  sample_notebook);
6945       gtk_box_pack_start (GTK_BOX (box2), omenu, FALSE, TRUE, 0);
6946
6947       button = gtk_button_new_with_label ("Show all Pages");
6948       gtk_box_pack_start (GTK_BOX (box2), button, FALSE, TRUE, 0);
6949       g_signal_connect (button, "clicked",
6950                         G_CALLBACK (show_all_pages), sample_notebook);
6951
6952       box2 = gtk_hbox_new (TRUE, 10);
6953       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
6954       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
6955
6956       button = gtk_button_new_with_label ("prev");
6957       g_signal_connect_swapped (button, "clicked",
6958                                 G_CALLBACK (gtk_notebook_prev_page),
6959                                 sample_notebook);
6960       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
6961
6962       button = gtk_button_new_with_label ("next");
6963       g_signal_connect_swapped (button, "clicked",
6964                                 G_CALLBACK (gtk_notebook_next_page),
6965                                 sample_notebook);
6966       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
6967
6968       button = gtk_button_new_with_label ("rotate");
6969       g_signal_connect (button, "clicked",
6970                         G_CALLBACK (rotate_notebook), sample_notebook);
6971       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
6972
6973       separator = gtk_hseparator_new ();
6974       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
6975
6976       button = gtk_button_new_with_label ("close");
6977       gtk_container_set_border_width (GTK_CONTAINER (button), 5);
6978       g_signal_connect_swapped (button, "clicked",
6979                                 G_CALLBACK (gtk_widget_destroy),
6980                                 window);
6981       gtk_box_pack_start (GTK_BOX (box1), button, FALSE, FALSE, 0);
6982       gtk_widget_set_can_default (button, TRUE);
6983       gtk_widget_grab_default (button);
6984     }
6985
6986   if (!gtk_widget_get_visible (window))
6987     gtk_widget_show_all (window);
6988   else
6989     gtk_widget_destroy (window);
6990 }
6991
6992 /*
6993  * GtkPanes
6994  */
6995
6996 void
6997 toggle_resize (GtkWidget *widget, GtkWidget *child)
6998 {
6999   GtkContainer *container = GTK_CONTAINER (gtk_widget_get_parent (child));
7000   GValue value = { 0, };
7001   g_value_init (&value, G_TYPE_BOOLEAN);
7002   gtk_container_child_get_property (container, child, "resize", &value);
7003   g_value_set_boolean (&value, !g_value_get_boolean (&value));
7004   gtk_container_child_set_property (container, child, "resize", &value);
7005 }
7006
7007 void
7008 toggle_shrink (GtkWidget *widget, GtkWidget *child)
7009 {
7010   GtkContainer *container = GTK_CONTAINER (gtk_widget_get_parent (child));
7011   GValue value = { 0, };
7012   g_value_init (&value, G_TYPE_BOOLEAN);
7013   gtk_container_child_get_property (container, child, "shrink", &value);
7014   g_value_set_boolean (&value, !g_value_get_boolean (&value));
7015   gtk_container_child_set_property (container, child, "shrink", &value);
7016 }
7017
7018 static void
7019 paned_props_clicked (GtkWidget *button,
7020                      GObject   *paned)
7021 {
7022   GtkWidget *window = create_prop_editor (paned, GTK_TYPE_PANED);
7023   
7024   gtk_window_set_title (GTK_WINDOW (window), "Paned Properties");
7025 }
7026
7027 GtkWidget *
7028 create_pane_options (GtkPaned    *paned,
7029                      const gchar *frame_label,
7030                      const gchar *label1,
7031                      const gchar *label2)
7032 {
7033   GtkWidget *frame;
7034   GtkWidget *table;
7035   GtkWidget *label;
7036   GtkWidget *button;
7037   GtkWidget *check_button;
7038   
7039   frame = gtk_frame_new (frame_label);
7040   gtk_container_set_border_width (GTK_CONTAINER (frame), 4);
7041   
7042   table = gtk_table_new (4, 2, 4);
7043   gtk_container_add (GTK_CONTAINER (frame), table);
7044   
7045   label = gtk_label_new (label1);
7046   gtk_table_attach_defaults (GTK_TABLE (table), label,
7047                              0, 1, 0, 1);
7048   
7049   check_button = gtk_check_button_new_with_label ("Resize");
7050   gtk_table_attach_defaults (GTK_TABLE (table), check_button,
7051                              0, 1, 1, 2);
7052   g_signal_connect (check_button, "toggled",
7053                     G_CALLBACK (toggle_resize),
7054                     paned->child1);
7055   
7056   check_button = gtk_check_button_new_with_label ("Shrink");
7057   gtk_table_attach_defaults (GTK_TABLE (table), check_button,
7058                              0, 1, 2, 3);
7059   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button),
7060                                TRUE);
7061   g_signal_connect (check_button, "toggled",
7062                     G_CALLBACK (toggle_shrink),
7063                     paned->child1);
7064   
7065   label = gtk_label_new (label2);
7066   gtk_table_attach_defaults (GTK_TABLE (table), label,
7067                              1, 2, 0, 1);
7068   
7069   check_button = gtk_check_button_new_with_label ("Resize");
7070   gtk_table_attach_defaults (GTK_TABLE (table), check_button,
7071                              1, 2, 1, 2);
7072   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button),
7073                                TRUE);
7074   g_signal_connect (check_button, "toggled",
7075                     G_CALLBACK (toggle_resize),
7076                     paned->child2);
7077   
7078   check_button = gtk_check_button_new_with_label ("Shrink");
7079   gtk_table_attach_defaults (GTK_TABLE (table), check_button,
7080                              1, 2, 2, 3);
7081   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button),
7082                                TRUE);
7083   g_signal_connect (check_button, "toggled",
7084                     G_CALLBACK (toggle_shrink),
7085                     paned->child2);
7086
7087   button = gtk_button_new_with_mnemonic ("_Properties");
7088   gtk_table_attach_defaults (GTK_TABLE (table), button,
7089                              0, 2, 3, 4);
7090   g_signal_connect (button, "clicked",
7091                     G_CALLBACK (paned_props_clicked),
7092                     paned);
7093
7094   return frame;
7095 }
7096
7097 void
7098 create_panes (GtkWidget *widget)
7099 {
7100   static GtkWidget *window = NULL;
7101   GtkWidget *frame;
7102   GtkWidget *hpaned;
7103   GtkWidget *vpaned;
7104   GtkWidget *button;
7105   GtkWidget *vbox;
7106
7107   if (!window)
7108     {
7109       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7110
7111       gtk_window_set_screen (GTK_WINDOW (window),
7112                              gtk_widget_get_screen (widget));
7113       
7114       g_signal_connect (window, "destroy",
7115                         G_CALLBACK (gtk_widget_destroyed),
7116                         &window);
7117
7118       gtk_window_set_title (GTK_WINDOW (window), "Panes");
7119       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
7120
7121       vbox = gtk_vbox_new (FALSE, 0);
7122       gtk_container_add (GTK_CONTAINER (window), vbox);
7123       
7124       vpaned = gtk_vpaned_new ();
7125       gtk_box_pack_start (GTK_BOX (vbox), vpaned, TRUE, TRUE, 0);
7126       gtk_container_set_border_width (GTK_CONTAINER(vpaned), 5);
7127
7128       hpaned = gtk_hpaned_new ();
7129       gtk_paned_add1 (GTK_PANED (vpaned), hpaned);
7130
7131       frame = gtk_frame_new (NULL);
7132       gtk_frame_set_shadow_type (GTK_FRAME(frame), GTK_SHADOW_IN);
7133       gtk_widget_set_size_request (frame, 60, 60);
7134       gtk_paned_add1 (GTK_PANED (hpaned), frame);
7135       
7136       button = gtk_button_new_with_label ("Hi there");
7137       gtk_container_add (GTK_CONTAINER(frame), button);
7138
7139       frame = gtk_frame_new (NULL);
7140       gtk_frame_set_shadow_type (GTK_FRAME(frame), GTK_SHADOW_IN);
7141       gtk_widget_set_size_request (frame, 80, 60);
7142       gtk_paned_add2 (GTK_PANED (hpaned), frame);
7143
7144       frame = gtk_frame_new (NULL);
7145       gtk_frame_set_shadow_type (GTK_FRAME(frame), GTK_SHADOW_IN);
7146       gtk_widget_set_size_request (frame, 60, 80);
7147       gtk_paned_add2 (GTK_PANED (vpaned), frame);
7148
7149       /* Now create toggle buttons to control sizing */
7150
7151       gtk_box_pack_start (GTK_BOX (vbox),
7152                           create_pane_options (GTK_PANED (hpaned),
7153                                                "Horizontal",
7154                                                "Left",
7155                                                "Right"),
7156                           FALSE, FALSE, 0);
7157
7158       gtk_box_pack_start (GTK_BOX (vbox),
7159                           create_pane_options (GTK_PANED (vpaned),
7160                                                "Vertical",
7161                                                "Top",
7162                                                "Bottom"),
7163                           FALSE, FALSE, 0);
7164
7165       gtk_widget_show_all (vbox);
7166     }
7167
7168   if (!gtk_widget_get_visible (window))
7169     gtk_widget_show (window);
7170   else
7171     gtk_widget_destroy (window);
7172 }
7173
7174 /*
7175  * Paned keyboard navigation
7176  */
7177
7178 static GtkWidget*
7179 paned_keyboard_window1 (GtkWidget *widget)
7180 {
7181   GtkWidget *window1;
7182   GtkWidget *hpaned1;
7183   GtkWidget *frame1;
7184   GtkWidget *vbox1;
7185   GtkWidget *button7;
7186   GtkWidget *button8;
7187   GtkWidget *button9;
7188   GtkWidget *vpaned1;
7189   GtkWidget *frame2;
7190   GtkWidget *frame5;
7191   GtkWidget *hbox1;
7192   GtkWidget *button5;
7193   GtkWidget *button6;
7194   GtkWidget *frame3;
7195   GtkWidget *frame4;
7196   GtkWidget *table1;
7197   GtkWidget *button1;
7198   GtkWidget *button2;
7199   GtkWidget *button3;
7200   GtkWidget *button4;
7201
7202   window1 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7203   gtk_window_set_title (GTK_WINDOW (window1), "Basic paned navigation");
7204   gtk_window_set_screen (GTK_WINDOW (window1), 
7205                          gtk_widget_get_screen (widget));
7206
7207   hpaned1 = gtk_hpaned_new ();
7208   gtk_container_add (GTK_CONTAINER (window1), hpaned1);
7209
7210   frame1 = gtk_frame_new (NULL);
7211   gtk_paned_pack1 (GTK_PANED (hpaned1), frame1, FALSE, TRUE);
7212   gtk_frame_set_shadow_type (GTK_FRAME (frame1), GTK_SHADOW_IN);
7213
7214   vbox1 = gtk_vbox_new (FALSE, 0);
7215   gtk_container_add (GTK_CONTAINER (frame1), vbox1);
7216
7217   button7 = gtk_button_new_with_label ("button7");
7218   gtk_box_pack_start (GTK_BOX (vbox1), button7, FALSE, FALSE, 0);
7219
7220   button8 = gtk_button_new_with_label ("button8");
7221   gtk_box_pack_start (GTK_BOX (vbox1), button8, FALSE, FALSE, 0);
7222
7223   button9 = gtk_button_new_with_label ("button9");
7224   gtk_box_pack_start (GTK_BOX (vbox1), button9, FALSE, FALSE, 0);
7225
7226   vpaned1 = gtk_vpaned_new ();
7227   gtk_paned_pack2 (GTK_PANED (hpaned1), vpaned1, TRUE, TRUE);
7228
7229   frame2 = gtk_frame_new (NULL);
7230   gtk_paned_pack1 (GTK_PANED (vpaned1), frame2, FALSE, TRUE);
7231   gtk_frame_set_shadow_type (GTK_FRAME (frame2), GTK_SHADOW_IN);
7232
7233   frame5 = gtk_frame_new (NULL);
7234   gtk_container_add (GTK_CONTAINER (frame2), frame5);
7235
7236   hbox1 = gtk_hbox_new (FALSE, 0);
7237   gtk_container_add (GTK_CONTAINER (frame5), hbox1);
7238
7239   button5 = gtk_button_new_with_label ("button5");
7240   gtk_box_pack_start (GTK_BOX (hbox1), button5, FALSE, FALSE, 0);
7241
7242   button6 = gtk_button_new_with_label ("button6");
7243   gtk_box_pack_start (GTK_BOX (hbox1), button6, FALSE, FALSE, 0);
7244
7245   frame3 = gtk_frame_new (NULL);
7246   gtk_paned_pack2 (GTK_PANED (vpaned1), frame3, TRUE, TRUE);
7247   gtk_frame_set_shadow_type (GTK_FRAME (frame3), GTK_SHADOW_IN);
7248
7249   frame4 = gtk_frame_new ("Buttons");
7250   gtk_container_add (GTK_CONTAINER (frame3), frame4);
7251   gtk_container_set_border_width (GTK_CONTAINER (frame4), 15);
7252
7253   table1 = gtk_table_new (2, 2, FALSE);
7254   gtk_container_add (GTK_CONTAINER (frame4), table1);
7255   gtk_container_set_border_width (GTK_CONTAINER (table1), 11);
7256
7257   button1 = gtk_button_new_with_label ("button1");
7258   gtk_table_attach (GTK_TABLE (table1), button1, 0, 1, 0, 1,
7259                     (GtkAttachOptions) (GTK_FILL),
7260                     (GtkAttachOptions) (0), 0, 0);
7261
7262   button2 = gtk_button_new_with_label ("button2");
7263   gtk_table_attach (GTK_TABLE (table1), button2, 1, 2, 0, 1,
7264                     (GtkAttachOptions) (GTK_FILL),
7265                     (GtkAttachOptions) (0), 0, 0);
7266
7267   button3 = gtk_button_new_with_label ("button3");
7268   gtk_table_attach (GTK_TABLE (table1), button3, 0, 1, 1, 2,
7269                     (GtkAttachOptions) (GTK_FILL),
7270                     (GtkAttachOptions) (0), 0, 0);
7271
7272   button4 = gtk_button_new_with_label ("button4");
7273   gtk_table_attach (GTK_TABLE (table1), button4, 1, 2, 1, 2,
7274                     (GtkAttachOptions) (GTK_FILL),
7275                     (GtkAttachOptions) (0), 0, 0);
7276
7277   return window1;
7278 }
7279
7280 static GtkWidget*
7281 paned_keyboard_window2 (GtkWidget *widget)
7282 {
7283   GtkWidget *window2;
7284   GtkWidget *hpaned2;
7285   GtkWidget *frame6;
7286   GtkWidget *button13;
7287   GtkWidget *hbox2;
7288   GtkWidget *vpaned2;
7289   GtkWidget *frame7;
7290   GtkWidget *button12;
7291   GtkWidget *frame8;
7292   GtkWidget *button11;
7293   GtkWidget *button10;
7294
7295   window2 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7296   gtk_window_set_title (GTK_WINDOW (window2), "\"button 10\" is not inside the horisontal pane");
7297
7298   gtk_window_set_screen (GTK_WINDOW (window2), 
7299                          gtk_widget_get_screen (widget));
7300
7301   hpaned2 = gtk_hpaned_new ();
7302   gtk_container_add (GTK_CONTAINER (window2), hpaned2);
7303
7304   frame6 = gtk_frame_new (NULL);
7305   gtk_paned_pack1 (GTK_PANED (hpaned2), frame6, FALSE, TRUE);
7306   gtk_frame_set_shadow_type (GTK_FRAME (frame6), GTK_SHADOW_IN);
7307
7308   button13 = gtk_button_new_with_label ("button13");
7309   gtk_container_add (GTK_CONTAINER (frame6), button13);
7310
7311   hbox2 = gtk_hbox_new (FALSE, 0);
7312   gtk_paned_pack2 (GTK_PANED (hpaned2), hbox2, TRUE, TRUE);
7313
7314   vpaned2 = gtk_vpaned_new ();
7315   gtk_box_pack_start (GTK_BOX (hbox2), vpaned2, TRUE, TRUE, 0);
7316
7317   frame7 = gtk_frame_new (NULL);
7318   gtk_paned_pack1 (GTK_PANED (vpaned2), frame7, FALSE, TRUE);
7319   gtk_frame_set_shadow_type (GTK_FRAME (frame7), GTK_SHADOW_IN);
7320
7321   button12 = gtk_button_new_with_label ("button12");
7322   gtk_container_add (GTK_CONTAINER (frame7), button12);
7323
7324   frame8 = gtk_frame_new (NULL);
7325   gtk_paned_pack2 (GTK_PANED (vpaned2), frame8, TRUE, TRUE);
7326   gtk_frame_set_shadow_type (GTK_FRAME (frame8), GTK_SHADOW_IN);
7327
7328   button11 = gtk_button_new_with_label ("button11");
7329   gtk_container_add (GTK_CONTAINER (frame8), button11);
7330
7331   button10 = gtk_button_new_with_label ("button10");
7332   gtk_box_pack_start (GTK_BOX (hbox2), button10, FALSE, FALSE, 0);
7333
7334   return window2;
7335 }
7336
7337 static GtkWidget*
7338 paned_keyboard_window3 (GtkWidget *widget)
7339 {
7340   GtkWidget *window3;
7341   GtkWidget *vbox2;
7342   GtkWidget *label1;
7343   GtkWidget *hpaned3;
7344   GtkWidget *frame9;
7345   GtkWidget *button14;
7346   GtkWidget *hpaned4;
7347   GtkWidget *frame10;
7348   GtkWidget *button15;
7349   GtkWidget *hpaned5;
7350   GtkWidget *frame11;
7351   GtkWidget *button16;
7352   GtkWidget *frame12;
7353   GtkWidget *button17;
7354
7355   window3 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7356   g_object_set_data (G_OBJECT (window3), "window3", window3);
7357   gtk_window_set_title (GTK_WINDOW (window3), "Nested panes");
7358
7359   gtk_window_set_screen (GTK_WINDOW (window3), 
7360                          gtk_widget_get_screen (widget));
7361   
7362
7363   vbox2 = gtk_vbox_new (FALSE, 0);
7364   gtk_container_add (GTK_CONTAINER (window3), vbox2);
7365
7366   label1 = gtk_label_new ("Three panes nested inside each other");
7367   gtk_box_pack_start (GTK_BOX (vbox2), label1, FALSE, FALSE, 0);
7368
7369   hpaned3 = gtk_hpaned_new ();
7370   gtk_box_pack_start (GTK_BOX (vbox2), hpaned3, TRUE, TRUE, 0);
7371
7372   frame9 = gtk_frame_new (NULL);
7373   gtk_paned_pack1 (GTK_PANED (hpaned3), frame9, FALSE, TRUE);
7374   gtk_frame_set_shadow_type (GTK_FRAME (frame9), GTK_SHADOW_IN);
7375
7376   button14 = gtk_button_new_with_label ("button14");
7377   gtk_container_add (GTK_CONTAINER (frame9), button14);
7378
7379   hpaned4 = gtk_hpaned_new ();
7380   gtk_paned_pack2 (GTK_PANED (hpaned3), hpaned4, TRUE, TRUE);
7381
7382   frame10 = gtk_frame_new (NULL);
7383   gtk_paned_pack1 (GTK_PANED (hpaned4), frame10, FALSE, TRUE);
7384   gtk_frame_set_shadow_type (GTK_FRAME (frame10), GTK_SHADOW_IN);
7385
7386   button15 = gtk_button_new_with_label ("button15");
7387   gtk_container_add (GTK_CONTAINER (frame10), button15);
7388
7389   hpaned5 = gtk_hpaned_new ();
7390   gtk_paned_pack2 (GTK_PANED (hpaned4), hpaned5, TRUE, TRUE);
7391
7392   frame11 = gtk_frame_new (NULL);
7393   gtk_paned_pack1 (GTK_PANED (hpaned5), frame11, FALSE, TRUE);
7394   gtk_frame_set_shadow_type (GTK_FRAME (frame11), GTK_SHADOW_IN);
7395
7396   button16 = gtk_button_new_with_label ("button16");
7397   gtk_container_add (GTK_CONTAINER (frame11), button16);
7398
7399   frame12 = gtk_frame_new (NULL);
7400   gtk_paned_pack2 (GTK_PANED (hpaned5), frame12, TRUE, TRUE);
7401   gtk_frame_set_shadow_type (GTK_FRAME (frame12), GTK_SHADOW_IN);
7402
7403   button17 = gtk_button_new_with_label ("button17");
7404   gtk_container_add (GTK_CONTAINER (frame12), button17);
7405
7406   return window3;
7407 }
7408
7409 static GtkWidget*
7410 paned_keyboard_window4 (GtkWidget *widget)
7411 {
7412   GtkWidget *window4;
7413   GtkWidget *vbox3;
7414   GtkWidget *label2;
7415   GtkWidget *hpaned6;
7416   GtkWidget *vpaned3;
7417   GtkWidget *button19;
7418   GtkWidget *button18;
7419   GtkWidget *hbox3;
7420   GtkWidget *vpaned4;
7421   GtkWidget *button21;
7422   GtkWidget *button20;
7423   GtkWidget *vpaned5;
7424   GtkWidget *button23;
7425   GtkWidget *button22;
7426   GtkWidget *vpaned6;
7427   GtkWidget *button25;
7428   GtkWidget *button24;
7429
7430   window4 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7431   g_object_set_data (G_OBJECT (window4), "window4", window4);
7432   gtk_window_set_title (GTK_WINDOW (window4), "window4");
7433
7434   gtk_window_set_screen (GTK_WINDOW (window4), 
7435                          gtk_widget_get_screen (widget));
7436
7437   vbox3 = gtk_vbox_new (FALSE, 0);
7438   gtk_container_add (GTK_CONTAINER (window4), vbox3);
7439
7440   label2 = gtk_label_new ("Widget tree:\n\nhpaned \n - vpaned\n - hbox\n    - vpaned\n    - vpaned\n    - vpaned\n");
7441   gtk_box_pack_start (GTK_BOX (vbox3), label2, FALSE, FALSE, 0);
7442   gtk_label_set_justify (GTK_LABEL (label2), GTK_JUSTIFY_LEFT);
7443
7444   hpaned6 = gtk_hpaned_new ();
7445   gtk_box_pack_start (GTK_BOX (vbox3), hpaned6, TRUE, TRUE, 0);
7446
7447   vpaned3 = gtk_vpaned_new ();
7448   gtk_paned_pack1 (GTK_PANED (hpaned6), vpaned3, FALSE, TRUE);
7449
7450   button19 = gtk_button_new_with_label ("button19");
7451   gtk_paned_pack1 (GTK_PANED (vpaned3), button19, FALSE, TRUE);
7452
7453   button18 = gtk_button_new_with_label ("button18");
7454   gtk_paned_pack2 (GTK_PANED (vpaned3), button18, TRUE, TRUE);
7455
7456   hbox3 = gtk_hbox_new (FALSE, 0);
7457   gtk_paned_pack2 (GTK_PANED (hpaned6), hbox3, TRUE, TRUE);
7458
7459   vpaned4 = gtk_vpaned_new ();
7460   gtk_box_pack_start (GTK_BOX (hbox3), vpaned4, TRUE, TRUE, 0);
7461
7462   button21 = gtk_button_new_with_label ("button21");
7463   gtk_paned_pack1 (GTK_PANED (vpaned4), button21, FALSE, TRUE);
7464
7465   button20 = gtk_button_new_with_label ("button20");
7466   gtk_paned_pack2 (GTK_PANED (vpaned4), button20, TRUE, TRUE);
7467
7468   vpaned5 = gtk_vpaned_new ();
7469   gtk_box_pack_start (GTK_BOX (hbox3), vpaned5, TRUE, TRUE, 0);
7470
7471   button23 = gtk_button_new_with_label ("button23");
7472   gtk_paned_pack1 (GTK_PANED (vpaned5), button23, FALSE, TRUE);
7473
7474   button22 = gtk_button_new_with_label ("button22");
7475   gtk_paned_pack2 (GTK_PANED (vpaned5), button22, TRUE, TRUE);
7476
7477   vpaned6 = gtk_vpaned_new ();
7478   gtk_box_pack_start (GTK_BOX (hbox3), vpaned6, TRUE, TRUE, 0);
7479
7480   button25 = gtk_button_new_with_label ("button25");
7481   gtk_paned_pack1 (GTK_PANED (vpaned6), button25, FALSE, TRUE);
7482
7483   button24 = gtk_button_new_with_label ("button24");
7484   gtk_paned_pack2 (GTK_PANED (vpaned6), button24, TRUE, TRUE);
7485
7486   return window4;
7487 }
7488
7489 static void
7490 create_paned_keyboard_navigation (GtkWidget *widget)
7491 {
7492   static GtkWidget *window1 = NULL;
7493   static GtkWidget *window2 = NULL;
7494   static GtkWidget *window3 = NULL;
7495   static GtkWidget *window4 = NULL;
7496
7497   if (window1 && 
7498      (gtk_widget_get_screen (window1) != gtk_widget_get_screen (widget)))
7499     {
7500       gtk_widget_destroy (window1);
7501       gtk_widget_destroy (window2);
7502       gtk_widget_destroy (window3);
7503       gtk_widget_destroy (window4);
7504     }
7505   
7506   if (!window1)
7507     {
7508       window1 = paned_keyboard_window1 (widget);
7509       g_signal_connect (window1, "destroy",
7510                         G_CALLBACK (gtk_widget_destroyed),
7511                         &window1);
7512     }
7513
7514   if (!window2)
7515     {
7516       window2 = paned_keyboard_window2 (widget);
7517       g_signal_connect (window2, "destroy",
7518                         G_CALLBACK (gtk_widget_destroyed),
7519                         &window2);
7520     }
7521
7522   if (!window3)
7523     {
7524       window3 = paned_keyboard_window3 (widget);
7525       g_signal_connect (window3, "destroy",
7526                         G_CALLBACK (gtk_widget_destroyed),
7527                         &window3);
7528     }
7529
7530   if (!window4)
7531     {
7532       window4 = paned_keyboard_window4 (widget);
7533       g_signal_connect (window4, "destroy",
7534                         G_CALLBACK (gtk_widget_destroyed),
7535                         &window4);
7536     }
7537
7538   if (gtk_widget_get_visible (window1))
7539     gtk_widget_destroy (GTK_WIDGET (window1));
7540   else
7541     gtk_widget_show_all (GTK_WIDGET (window1));
7542
7543   if (gtk_widget_get_visible (window2))
7544     gtk_widget_destroy (GTK_WIDGET (window2));
7545   else
7546     gtk_widget_show_all (GTK_WIDGET (window2));
7547
7548   if (gtk_widget_get_visible (window3))
7549     gtk_widget_destroy (GTK_WIDGET (window3));
7550   else
7551     gtk_widget_show_all (GTK_WIDGET (window3));
7552
7553   if (gtk_widget_get_visible (window4))
7554     gtk_widget_destroy (GTK_WIDGET (window4));
7555   else
7556     gtk_widget_show_all (GTK_WIDGET (window4));
7557 }
7558
7559
7560 /*
7561  * Shaped Windows
7562  */
7563
7564 typedef struct _cursoroffset {gint x,y;} CursorOffset;
7565
7566 static void
7567 shape_pressed (GtkWidget *widget, GdkEventButton *event)
7568 {
7569   CursorOffset *p;
7570
7571   /* ignore double and triple click */
7572   if (event->type != GDK_BUTTON_PRESS)
7573     return;
7574
7575   p = g_object_get_data (G_OBJECT (widget), "cursor_offset");
7576   p->x = (int) event->x;
7577   p->y = (int) event->y;
7578
7579   gtk_grab_add (widget);
7580   gdk_pointer_grab (widget->window, TRUE,
7581                     GDK_BUTTON_RELEASE_MASK |
7582                     GDK_BUTTON_MOTION_MASK |
7583                     GDK_POINTER_MOTION_HINT_MASK,
7584                     NULL, NULL, 0);
7585 }
7586
7587 static void
7588 shape_released (GtkWidget *widget)
7589 {
7590   gtk_grab_remove (widget);
7591   gdk_display_pointer_ungrab (gtk_widget_get_display (widget),
7592                               GDK_CURRENT_TIME);
7593 }
7594
7595 static void
7596 shape_motion (GtkWidget      *widget, 
7597               GdkEventMotion *event)
7598 {
7599   gint xp, yp;
7600   CursorOffset * p;
7601   GdkModifierType mask;
7602
7603   p = g_object_get_data (G_OBJECT (widget), "cursor_offset");
7604
7605   /*
7606    * Can't use event->x / event->y here 
7607    * because I need absolute coordinates.
7608    */
7609   gdk_window_get_pointer (NULL, &xp, &yp, &mask);
7610   gtk_window_move (GTK_WINDOW (widget), xp  - p->x, yp  - p->y);
7611 }
7612
7613 GtkWidget *
7614 shape_create_icon (GdkScreen *screen,
7615                    char      *xpm_file,
7616                    gint       x,
7617                    gint       y,
7618                    gint       px,
7619                    gint       py,
7620                    gint       window_type)
7621 {
7622   GtkWidget *window;
7623   GtkWidget *pixmap;
7624   GtkWidget *fixed;
7625   CursorOffset* icon_pos;
7626   GdkGC* gc;
7627   GdkBitmap *gdk_pixmap_mask;
7628   GdkPixmap *gdk_pixmap;
7629   GtkStyle *style;
7630
7631   style = gtk_widget_get_default_style ();
7632   gc = style->black_gc; 
7633
7634   /*
7635    * GDK_WINDOW_TOPLEVEL works also, giving you a title border
7636    */
7637   window = gtk_window_new (window_type);
7638   gtk_window_set_screen (GTK_WINDOW (window), screen);
7639   
7640   fixed = gtk_fixed_new ();
7641   gtk_widget_set_size_request (fixed, 100, 100);
7642   gtk_container_add (GTK_CONTAINER (window), fixed);
7643   gtk_widget_show (fixed);
7644   
7645   gtk_widget_set_events (window, 
7646                          gtk_widget_get_events (window) |
7647                          GDK_BUTTON_MOTION_MASK |
7648                          GDK_POINTER_MOTION_HINT_MASK |
7649                          GDK_BUTTON_PRESS_MASK);
7650
7651   gtk_widget_realize (window);
7652   gdk_pixmap = gdk_pixmap_create_from_xpm (window->window, &gdk_pixmap_mask, 
7653                                            &style->bg[GTK_STATE_NORMAL],
7654                                            xpm_file);
7655
7656   pixmap = gtk_image_new_from_pixmap (gdk_pixmap, gdk_pixmap_mask);
7657   gtk_fixed_put (GTK_FIXED (fixed), pixmap, px,py);
7658   gtk_widget_show (pixmap);
7659   
7660   gtk_widget_shape_combine_mask (window, gdk_pixmap_mask, px, py);
7661   
7662   g_object_unref (gdk_pixmap_mask);
7663   g_object_unref (gdk_pixmap);
7664
7665   g_signal_connect (window, "button_press_event",
7666                     G_CALLBACK (shape_pressed), NULL);
7667   g_signal_connect (window, "button_release_event",
7668                     G_CALLBACK (shape_released), NULL);
7669   g_signal_connect (window, "motion_notify_event",
7670                     G_CALLBACK (shape_motion), NULL);
7671
7672   icon_pos = g_new (CursorOffset, 1);
7673   g_object_set_data (G_OBJECT (window), "cursor_offset", icon_pos);
7674
7675   gtk_window_move (GTK_WINDOW (window), x, y);
7676   gtk_widget_show (window);
7677   
7678   return window;
7679 }
7680
7681 void 
7682 create_shapes (GtkWidget *widget)
7683 {
7684   /* Variables used by the Drag/Drop and Shape Window demos */
7685   static GtkWidget *modeller = NULL;
7686   static GtkWidget *sheets = NULL;
7687   static GtkWidget *rings = NULL;
7688   static GtkWidget *with_region = NULL;
7689   GdkScreen *screen = gtk_widget_get_screen (widget);
7690   
7691   if (!(file_exists ("Modeller.xpm") &&
7692         file_exists ("FilesQueue.xpm") &&
7693         file_exists ("3DRings.xpm")))
7694     return;
7695   
7696
7697   if (!modeller)
7698     {
7699       modeller = shape_create_icon (screen, "Modeller.xpm",
7700                                     440, 140, 0,0, GTK_WINDOW_POPUP);
7701
7702       g_signal_connect (modeller, "destroy",
7703                         G_CALLBACK (gtk_widget_destroyed),
7704                         &modeller);
7705     }
7706   else
7707     gtk_widget_destroy (modeller);
7708
7709   if (!sheets)
7710     {
7711       sheets = shape_create_icon (screen, "FilesQueue.xpm",
7712                                   580, 170, 0,0, GTK_WINDOW_POPUP);
7713
7714       g_signal_connect (sheets, "destroy",
7715                         G_CALLBACK (gtk_widget_destroyed),
7716                         &sheets);
7717
7718     }
7719   else
7720     gtk_widget_destroy (sheets);
7721
7722   if (!rings)
7723     {
7724       rings = shape_create_icon (screen, "3DRings.xpm",
7725                                  460, 270, 25,25, GTK_WINDOW_TOPLEVEL);
7726
7727       g_signal_connect (rings, "destroy",
7728                         G_CALLBACK (gtk_widget_destroyed),
7729                         &rings);
7730     }
7731   else
7732     gtk_widget_destroy (rings);
7733
7734   if (!with_region)
7735     {
7736       GdkRegion *region;
7737       gint x, y;
7738       
7739       with_region = shape_create_icon (screen, "3DRings.xpm",
7740                                        460, 270, 25,25, GTK_WINDOW_TOPLEVEL);
7741
7742       gtk_window_set_decorated (GTK_WINDOW (with_region), FALSE);
7743       
7744       g_signal_connect (with_region, "destroy",
7745                         G_CALLBACK (gtk_widget_destroyed),
7746                         &with_region);
7747
7748       /* reset shape from mask to a region */
7749       x = 0;
7750       y = 0;
7751       region = gdk_region_new ();
7752
7753       while (x < 460)
7754         {
7755           while (y < 270)
7756             {
7757               GdkRectangle rect;
7758               rect.x = x;
7759               rect.y = y;
7760               rect.width = 10;
7761               rect.height = 10;
7762
7763               gdk_region_union_with_rect (region, &rect);
7764               
7765               y += 20;
7766             }
7767           y = 0;
7768           x += 20;
7769         }
7770
7771       gdk_window_shape_combine_region (with_region->window,
7772                                        region,
7773                                        0, 0);
7774     }
7775   else
7776     gtk_widget_destroy (with_region);
7777 }
7778
7779 /*
7780  * WM Hints demo
7781  */
7782
7783 void
7784 create_wmhints (GtkWidget *widget)
7785 {
7786   static GtkWidget *window = NULL;
7787   GtkWidget *label;
7788   GtkWidget *separator;
7789   GtkWidget *button;
7790   GtkWidget *box1;
7791   GtkWidget *box2;
7792
7793   GdkBitmap *circles;
7794
7795   if (!window)
7796     {
7797       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7798
7799       gtk_window_set_screen (GTK_WINDOW (window),
7800                              gtk_widget_get_screen (widget));
7801       
7802       g_signal_connect (window, "destroy",
7803                         G_CALLBACK (gtk_widget_destroyed),
7804                         &window);
7805
7806       gtk_window_set_title (GTK_WINDOW (window), "WM Hints");
7807       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
7808
7809       gtk_widget_realize (window);
7810       
7811       circles = gdk_bitmap_create_from_data (window->window,
7812                                              (gchar *) circles_bits,
7813                                              circles_width,
7814                                              circles_height);
7815       gdk_window_set_icon (window->window, NULL,
7816                            circles, circles);
7817       
7818       gdk_window_set_icon_name (window->window, "WMHints Test Icon");
7819   
7820       gdk_window_set_decorations (window->window, GDK_DECOR_ALL | GDK_DECOR_MENU);
7821       gdk_window_set_functions (window->window, GDK_FUNC_ALL | GDK_FUNC_RESIZE);
7822       
7823       box1 = gtk_vbox_new (FALSE, 0);
7824       gtk_container_add (GTK_CONTAINER (window), box1);
7825       gtk_widget_show (box1);
7826
7827       label = gtk_label_new ("Try iconizing me!");
7828       gtk_widget_set_size_request (label, 150, 50);
7829       gtk_box_pack_start (GTK_BOX (box1), label, TRUE, TRUE, 0);
7830       gtk_widget_show (label);
7831
7832
7833       separator = gtk_hseparator_new ();
7834       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
7835       gtk_widget_show (separator);
7836
7837
7838       box2 = gtk_vbox_new (FALSE, 10);
7839       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
7840       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
7841       gtk_widget_show (box2);
7842
7843
7844       button = gtk_button_new_with_label ("close");
7845
7846       g_signal_connect_swapped (button, "clicked",
7847                                 G_CALLBACK (gtk_widget_destroy),
7848                                 window);
7849
7850       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
7851       gtk_widget_set_can_default (button, TRUE);
7852       gtk_widget_grab_default (button);
7853       gtk_widget_show (button);
7854     }
7855
7856   if (!gtk_widget_get_visible (window))
7857     gtk_widget_show (window);
7858   else
7859     gtk_widget_destroy (window);
7860 }
7861
7862
7863 /*
7864  * Window state tracking
7865  */
7866
7867 static gint
7868 window_state_callback (GtkWidget *widget,
7869                        GdkEventWindowState *event,
7870                        gpointer data)
7871 {
7872   GtkWidget *label = data;
7873   gchar *msg;
7874
7875   msg = g_strconcat (GTK_WINDOW (widget)->title, ": ",
7876                      (event->new_window_state & GDK_WINDOW_STATE_WITHDRAWN) ?
7877                      "withdrawn" : "not withdrawn", ", ",
7878                      (event->new_window_state & GDK_WINDOW_STATE_ICONIFIED) ?
7879                      "iconified" : "not iconified", ", ",
7880                      (event->new_window_state & GDK_WINDOW_STATE_STICKY) ?
7881                      "sticky" : "not sticky", ", ",
7882                      (event->new_window_state & GDK_WINDOW_STATE_MAXIMIZED) ?
7883                      "maximized" : "not maximized", ", ",
7884                      (event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN) ?
7885                      "fullscreen" : "not fullscreen",
7886                      (event->new_window_state & GDK_WINDOW_STATE_ABOVE) ?
7887                      "above" : "not above", ", ",
7888                      (event->new_window_state & GDK_WINDOW_STATE_BELOW) ?
7889                      "below" : "not below", ", ",
7890                      NULL);
7891   
7892   gtk_label_set_text (GTK_LABEL (label), msg);
7893
7894   g_free (msg);
7895
7896   return FALSE;
7897 }
7898
7899 static GtkWidget*
7900 tracking_label (GtkWidget *window)
7901 {
7902   GtkWidget *label;
7903   GtkWidget *hbox;
7904   GtkWidget *button;
7905
7906   hbox = gtk_hbox_new (FALSE, 5);
7907
7908   g_signal_connect_object (hbox,
7909                            "destroy",
7910                            G_CALLBACK (gtk_widget_destroy),
7911                            window,
7912                            G_CONNECT_SWAPPED);
7913   
7914   label = gtk_label_new ("<no window state events received>");
7915   gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
7916   gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
7917   
7918   g_signal_connect (window,
7919                     "window_state_event",
7920                     G_CALLBACK (window_state_callback),
7921                     label);
7922
7923   button = gtk_button_new_with_label ("Deiconify");
7924   g_signal_connect_object (button,
7925                            "clicked",
7926                            G_CALLBACK (gtk_window_deiconify),
7927                            window,
7928                            G_CONNECT_SWAPPED);
7929   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
7930
7931   button = gtk_button_new_with_label ("Iconify");
7932   g_signal_connect_object (button,
7933                            "clicked",
7934                            G_CALLBACK (gtk_window_iconify),
7935                            window,
7936                            G_CONNECT_SWAPPED);
7937   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
7938
7939   button = gtk_button_new_with_label ("Fullscreen");
7940   g_signal_connect_object (button,
7941                            "clicked",
7942                            G_CALLBACK (gtk_window_fullscreen),
7943                            window,
7944                            G_CONNECT_SWAPPED);
7945   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
7946
7947   button = gtk_button_new_with_label ("Unfullscreen");
7948   g_signal_connect_object (button,
7949                            "clicked",
7950                            G_CALLBACK (gtk_window_unfullscreen),
7951                            window,
7952                            G_CONNECT_SWAPPED);
7953   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
7954   
7955   button = gtk_button_new_with_label ("Present");
7956   g_signal_connect_object (button,
7957                            "clicked",
7958                            G_CALLBACK (gtk_window_present),
7959                            window,
7960                            G_CONNECT_SWAPPED);
7961   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
7962
7963   button = gtk_button_new_with_label ("Show");
7964   g_signal_connect_object (button,
7965                            "clicked",
7966                            G_CALLBACK (gtk_widget_show),
7967                            window,
7968                            G_CONNECT_SWAPPED);
7969   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
7970   
7971   gtk_widget_show_all (hbox);
7972   
7973   return hbox;
7974 }
7975
7976 void
7977 keep_window_above (GtkToggleButton *togglebutton, gpointer data)
7978 {
7979   GtkWidget *button = g_object_get_data (G_OBJECT (togglebutton), "radio");
7980
7981   gtk_window_set_keep_above (GTK_WINDOW (data),
7982                              gtk_toggle_button_get_active (togglebutton));
7983
7984   if (gtk_toggle_button_get_active (togglebutton))
7985     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE);
7986 }
7987
7988 void
7989 keep_window_below (GtkToggleButton *togglebutton, gpointer data)
7990 {
7991   GtkWidget *button = g_object_get_data (G_OBJECT (togglebutton), "radio");
7992
7993   gtk_window_set_keep_below (GTK_WINDOW (data),
7994                              gtk_toggle_button_get_active (togglebutton));
7995
7996   if (gtk_toggle_button_get_active (togglebutton))
7997     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE);
7998 }
7999
8000
8001 static GtkWidget*
8002 get_state_controls (GtkWidget *window)
8003 {
8004   GtkWidget *vbox;
8005   GtkWidget *button;
8006   GtkWidget *button_above;
8007   GtkWidget *button_below;
8008
8009   vbox = gtk_vbox_new (FALSE, 0);
8010   
8011   button = gtk_button_new_with_label ("Stick");
8012   g_signal_connect_object (button,
8013                            "clicked",
8014                            G_CALLBACK (gtk_window_stick),
8015                            window,
8016                            G_CONNECT_SWAPPED);
8017   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8018
8019   button = gtk_button_new_with_label ("Unstick");
8020   g_signal_connect_object (button,
8021                            "clicked",
8022                            G_CALLBACK (gtk_window_unstick),
8023                            window,
8024                            G_CONNECT_SWAPPED);
8025   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8026   
8027   button = gtk_button_new_with_label ("Maximize");
8028   g_signal_connect_object (button,
8029                            "clicked",
8030                            G_CALLBACK (gtk_window_maximize),
8031                            window,
8032                            G_CONNECT_SWAPPED);
8033   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8034
8035   button = gtk_button_new_with_label ("Unmaximize");
8036   g_signal_connect_object (button,
8037                            "clicked",
8038                            G_CALLBACK (gtk_window_unmaximize),
8039                            window,
8040                            G_CONNECT_SWAPPED);
8041   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8042
8043   button = gtk_button_new_with_label ("Iconify");
8044   g_signal_connect_object (button,
8045                            "clicked",
8046                            G_CALLBACK (gtk_window_iconify),
8047                            window,
8048                            G_CONNECT_SWAPPED);
8049   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8050
8051   button = gtk_button_new_with_label ("Fullscreen");
8052   g_signal_connect_object (button,
8053                            "clicked",
8054                            G_CALLBACK (gtk_window_fullscreen),
8055                            window,
8056                            G_CONNECT_SWAPPED);
8057   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8058
8059   button = gtk_button_new_with_label ("Unfullscreen");
8060   g_signal_connect_object (button,
8061                            "clicked",
8062                            G_CALLBACK (gtk_window_unfullscreen),
8063                            window,
8064                            G_CONNECT_SWAPPED);
8065   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8066
8067   button_above = gtk_toggle_button_new_with_label ("Keep above");
8068   g_signal_connect (button_above,
8069                     "toggled",
8070                     G_CALLBACK (keep_window_above),
8071                     window);
8072   gtk_box_pack_start (GTK_BOX (vbox), button_above, FALSE, FALSE, 0);
8073
8074   button_below = gtk_toggle_button_new_with_label ("Keep below");
8075   g_signal_connect (button_below,
8076                     "toggled",
8077                     G_CALLBACK (keep_window_below),
8078                     window);
8079   gtk_box_pack_start (GTK_BOX (vbox), button_below, FALSE, FALSE, 0);
8080
8081   g_object_set_data (G_OBJECT (button_above), "radio", button_below);
8082   g_object_set_data (G_OBJECT (button_below), "radio", button_above);
8083
8084   button = gtk_button_new_with_label ("Hide (withdraw)");
8085   g_signal_connect_object (button,
8086                            "clicked",
8087                            G_CALLBACK (gtk_widget_hide),
8088                            window,
8089                            G_CONNECT_SWAPPED);
8090   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8091   
8092   gtk_widget_show_all (vbox);
8093
8094   return vbox;
8095 }
8096
8097 void
8098 create_window_states (GtkWidget *widget)
8099 {
8100   static GtkWidget *window = NULL;
8101   GtkWidget *label;
8102   GtkWidget *box1;
8103   GtkWidget *iconified;
8104   GtkWidget *normal;
8105   GtkWidget *controls;
8106
8107   if (!window)
8108     {
8109       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8110       gtk_window_set_screen (GTK_WINDOW (window),
8111                              gtk_widget_get_screen (widget));
8112
8113       g_signal_connect (window, "destroy",
8114                         G_CALLBACK (gtk_widget_destroyed),
8115                         &window);
8116
8117       gtk_window_set_title (GTK_WINDOW (window), "Window states");
8118       
8119       box1 = gtk_vbox_new (FALSE, 0);
8120       gtk_container_add (GTK_CONTAINER (window), box1);
8121
8122       iconified = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8123
8124       gtk_window_set_screen (GTK_WINDOW (iconified),
8125                              gtk_widget_get_screen (widget));
8126       
8127       g_signal_connect_object (iconified, "destroy",
8128                                G_CALLBACK (gtk_widget_destroy),
8129                                window,
8130                                G_CONNECT_SWAPPED);
8131       gtk_window_iconify (GTK_WINDOW (iconified));
8132       gtk_window_set_title (GTK_WINDOW (iconified), "Iconified initially");
8133       controls = get_state_controls (iconified);
8134       gtk_container_add (GTK_CONTAINER (iconified), controls);
8135       
8136       normal = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8137
8138       gtk_window_set_screen (GTK_WINDOW (normal),
8139                              gtk_widget_get_screen (widget));
8140       
8141       g_signal_connect_object (normal, "destroy",
8142                                G_CALLBACK (gtk_widget_destroy),
8143                                window,
8144                                G_CONNECT_SWAPPED);
8145       
8146       gtk_window_set_title (GTK_WINDOW (normal), "Deiconified initially");
8147       controls = get_state_controls (normal);
8148       gtk_container_add (GTK_CONTAINER (normal), controls);
8149       
8150       label = tracking_label (iconified);
8151       gtk_container_add (GTK_CONTAINER (box1), label);
8152
8153       label = tracking_label (normal);
8154       gtk_container_add (GTK_CONTAINER (box1), label);
8155
8156       gtk_widget_show_all (iconified);
8157       gtk_widget_show_all (normal);
8158       gtk_widget_show_all (box1);
8159     }
8160
8161   if (!gtk_widget_get_visible (window))
8162     gtk_widget_show (window);
8163   else
8164     gtk_widget_destroy (window);
8165 }
8166
8167 /*
8168  * Window sizing
8169  */
8170
8171 static gint
8172 configure_event_callback (GtkWidget *widget,
8173                           GdkEventConfigure *event,
8174                           gpointer data)
8175 {
8176   GtkWidget *label = data;
8177   gchar *msg;
8178   gint x, y;
8179   
8180   gtk_window_get_position (GTK_WINDOW (widget), &x, &y);
8181   
8182   msg = g_strdup_printf ("event: %d,%d  %d x %d\n"
8183                          "position: %d, %d",
8184                          event->x, event->y, event->width, event->height,
8185                          x, y);
8186   
8187   gtk_label_set_text (GTK_LABEL (label), msg);
8188
8189   g_free (msg);
8190
8191   return FALSE;
8192 }
8193
8194 static void
8195 get_ints (GtkWidget *window,
8196           gint      *a,
8197           gint      *b)
8198 {
8199   GtkWidget *spin1;
8200   GtkWidget *spin2;
8201
8202   spin1 = g_object_get_data (G_OBJECT (window), "spin1");
8203   spin2 = g_object_get_data (G_OBJECT (window), "spin2");
8204
8205   *a = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (spin1));
8206   *b = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (spin2));
8207 }
8208
8209 static void
8210 set_size_callback (GtkWidget *widget,
8211                    gpointer   data)
8212 {
8213   gint w, h;
8214   
8215   get_ints (data, &w, &h);
8216
8217   gtk_window_resize (GTK_WINDOW (g_object_get_data (data, "target")), w, h);
8218 }
8219
8220 static void
8221 unset_default_size_callback (GtkWidget *widget,
8222                              gpointer   data)
8223 {
8224   gtk_window_set_default_size (g_object_get_data (data, "target"),
8225                                -1, -1);
8226 }
8227
8228 static void
8229 set_default_size_callback (GtkWidget *widget,
8230                            gpointer   data)
8231 {
8232   gint w, h;
8233   
8234   get_ints (data, &w, &h);
8235
8236   gtk_window_set_default_size (g_object_get_data (data, "target"),
8237                                w, h);
8238 }
8239
8240 static void
8241 unset_size_request_callback (GtkWidget *widget,
8242                              gpointer   data)
8243 {
8244   gtk_widget_set_size_request (g_object_get_data (data, "target"),
8245                                -1, -1);
8246 }
8247
8248 static void
8249 set_size_request_callback (GtkWidget *widget,
8250                            gpointer   data)
8251 {
8252   gint w, h;
8253   
8254   get_ints (data, &w, &h);
8255
8256   gtk_widget_set_size_request (g_object_get_data (data, "target"),
8257                                w, h);
8258 }
8259
8260 static void
8261 set_location_callback (GtkWidget *widget,
8262                        gpointer   data)
8263 {
8264   gint x, y;
8265   
8266   get_ints (data, &x, &y);
8267
8268   gtk_window_move (g_object_get_data (data, "target"), x, y);
8269 }
8270
8271 static void
8272 move_to_position_callback (GtkWidget *widget,
8273                            gpointer   data)
8274 {
8275   gint x, y;
8276   GtkWindow *window;
8277
8278   window = g_object_get_data (data, "target");
8279   
8280   gtk_window_get_position (window, &x, &y);
8281
8282   gtk_window_move (window, x, y);
8283 }
8284
8285 static void
8286 set_geometry_callback (GtkWidget *entry,
8287                        gpointer   data)
8288 {
8289   gchar *text;
8290   GtkWindow *target;
8291
8292   target = GTK_WINDOW (g_object_get_data (G_OBJECT (data), "target"));
8293   
8294   text = gtk_editable_get_chars (GTK_EDITABLE (entry), 0, -1);
8295
8296   if (!gtk_window_parse_geometry (target, text))
8297     g_print ("Bad geometry string '%s'\n", text);
8298
8299   g_free (text);
8300 }
8301
8302 static void
8303 allow_shrink_callback (GtkWidget *widget,
8304                        gpointer   data)
8305 {
8306   g_object_set (g_object_get_data (data, "target"),
8307                 "allow_shrink",
8308                 GTK_TOGGLE_BUTTON (widget)->active,
8309                 NULL);
8310 }
8311
8312 static void
8313 allow_grow_callback (GtkWidget *widget,
8314                      gpointer   data)
8315 {
8316   g_object_set (g_object_get_data (data, "target"),
8317                 "allow_grow",
8318                 GTK_TOGGLE_BUTTON (widget)->active,
8319                 NULL);
8320 }
8321
8322 static void
8323 gravity_selected (GtkWidget *widget,
8324                   gpointer   data)
8325 {
8326   gtk_window_set_gravity (GTK_WINDOW (g_object_get_data (data, "target")),
8327                           gtk_combo_box_get_active (GTK_COMBO_BOX (widget)) + GDK_GRAVITY_NORTH_WEST);
8328 }
8329
8330 static void
8331 pos_selected (GtkWidget *widget,
8332               gpointer   data)
8333 {
8334   gtk_window_set_position (GTK_WINDOW (g_object_get_data (data, "target")),
8335                            gtk_combo_box_get_active (GTK_COMBO_BOX (widget)) + GTK_WIN_POS_NONE);
8336 }
8337
8338 static void
8339 move_gravity_window_to_current_position (GtkWidget *widget,
8340                                          gpointer   data)
8341 {
8342   gint x, y;
8343   GtkWindow *window;
8344
8345   window = GTK_WINDOW (data);    
8346   
8347   gtk_window_get_position (window, &x, &y);
8348
8349   gtk_window_move (window, x, y);
8350 }
8351
8352 static void
8353 get_screen_corner (GtkWindow *window,
8354                    gint      *x,
8355                    gint      *y)
8356 {
8357   int w, h;
8358   GdkScreen * screen = gtk_window_get_screen (window);
8359   
8360   gtk_window_get_size (GTK_WINDOW (window), &w, &h);
8361
8362   switch (gtk_window_get_gravity (window))
8363     {
8364     case GDK_GRAVITY_SOUTH_EAST:
8365       *x = gdk_screen_get_width (screen) - w;
8366       *y = gdk_screen_get_height (screen) - h;
8367       break;
8368
8369     case GDK_GRAVITY_NORTH_EAST:
8370       *x = gdk_screen_get_width (screen) - w;
8371       *y = 0;
8372       break;
8373
8374     case GDK_GRAVITY_SOUTH_WEST:
8375       *x = 0;
8376       *y = gdk_screen_get_height (screen) - h;
8377       break;
8378
8379     case GDK_GRAVITY_NORTH_WEST:
8380       *x = 0;
8381       *y = 0;
8382       break;
8383       
8384     case GDK_GRAVITY_SOUTH:
8385       *x = (gdk_screen_get_width (screen) - w) / 2;
8386       *y = gdk_screen_get_height (screen) - h;
8387       break;
8388
8389     case GDK_GRAVITY_NORTH:
8390       *x = (gdk_screen_get_width (screen) - w) / 2;
8391       *y = 0;
8392       break;
8393
8394     case GDK_GRAVITY_WEST:
8395       *x = 0;
8396       *y = (gdk_screen_get_height (screen) - h) / 2;
8397       break;
8398
8399     case GDK_GRAVITY_EAST:
8400       *x = gdk_screen_get_width (screen) - w;
8401       *y = (gdk_screen_get_height (screen) - h) / 2;
8402       break;
8403
8404     case GDK_GRAVITY_CENTER:
8405       *x = (gdk_screen_get_width (screen) - w) / 2;
8406       *y = (gdk_screen_get_height (screen) - h) / 2;
8407       break;
8408
8409     case GDK_GRAVITY_STATIC:
8410       /* pick some random numbers */
8411       *x = 350;
8412       *y = 350;
8413       break;
8414
8415     default:
8416       g_assert_not_reached ();
8417       break;
8418     }
8419 }
8420
8421 static void
8422 move_gravity_window_to_starting_position (GtkWidget *widget,
8423                                           gpointer   data)
8424 {
8425   gint x, y;
8426   GtkWindow *window;
8427
8428   window = GTK_WINDOW (data);    
8429   
8430   get_screen_corner (window,
8431                      &x, &y);
8432   
8433   gtk_window_move (window, x, y);
8434 }
8435
8436 static GtkWidget*
8437 make_gravity_window (GtkWidget   *destroy_with,
8438                      GdkGravity   gravity,
8439                      const gchar *title)
8440 {
8441   GtkWidget *window;
8442   GtkWidget *button;
8443   GtkWidget *vbox;
8444   int x, y;
8445   
8446   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8447
8448   gtk_window_set_screen (GTK_WINDOW (window),
8449                          gtk_widget_get_screen (destroy_with));
8450
8451   vbox = gtk_vbox_new (FALSE, 0);
8452   gtk_widget_show (vbox);
8453   
8454   gtk_container_add (GTK_CONTAINER (window), vbox);
8455   gtk_window_set_title (GTK_WINDOW (window), title);
8456   gtk_window_set_gravity (GTK_WINDOW (window), gravity);
8457
8458   g_signal_connect_object (destroy_with,
8459                            "destroy",
8460                            G_CALLBACK (gtk_widget_destroy),
8461                            window,
8462                            G_CONNECT_SWAPPED);
8463
8464   
8465   button = gtk_button_new_with_mnemonic ("_Move to current position");
8466
8467   g_signal_connect (button, "clicked",
8468                     G_CALLBACK (move_gravity_window_to_current_position),
8469                     window);
8470
8471   gtk_container_add (GTK_CONTAINER (vbox), button);
8472   gtk_widget_show (button);
8473
8474   button = gtk_button_new_with_mnemonic ("Move to _starting position");
8475
8476   g_signal_connect (button, "clicked",
8477                     G_CALLBACK (move_gravity_window_to_starting_position),
8478                     window);
8479
8480   gtk_container_add (GTK_CONTAINER (vbox), button);
8481   gtk_widget_show (button);
8482   
8483   /* Pretend this is the result of --geometry.
8484    * DO NOT COPY THIS CODE unless you are setting --geometry results,
8485    * and in that case you probably should just use gtk_window_parse_geometry().
8486    * AGAIN, DO NOT SET GDK_HINT_USER_POS! It violates the ICCCM unless
8487    * you are parsing --geometry or equivalent.
8488    */
8489   gtk_window_set_geometry_hints (GTK_WINDOW (window),
8490                                  NULL, NULL,
8491                                  GDK_HINT_USER_POS);
8492
8493   gtk_window_set_default_size (GTK_WINDOW (window),
8494                                200, 200);
8495
8496   get_screen_corner (GTK_WINDOW (window), &x, &y);
8497   
8498   gtk_window_move (GTK_WINDOW (window),
8499                    x, y);
8500   
8501   return window;
8502 }
8503
8504 static void
8505 do_gravity_test (GtkWidget *widget,
8506                  gpointer   data)
8507 {
8508   GtkWidget *destroy_with = data;
8509   GtkWidget *window;
8510   
8511   /* We put a window at each gravity point on the screen. */
8512   window = make_gravity_window (destroy_with, GDK_GRAVITY_NORTH_WEST,
8513                                 "NorthWest");
8514   gtk_widget_show (window);
8515   
8516   window = make_gravity_window (destroy_with, GDK_GRAVITY_SOUTH_EAST,
8517                                 "SouthEast");
8518   gtk_widget_show (window);
8519
8520   window = make_gravity_window (destroy_with, GDK_GRAVITY_NORTH_EAST,
8521                                 "NorthEast");
8522   gtk_widget_show (window);
8523
8524   window = make_gravity_window (destroy_with, GDK_GRAVITY_SOUTH_WEST,
8525                                 "SouthWest");
8526   gtk_widget_show (window);
8527
8528   window = make_gravity_window (destroy_with, GDK_GRAVITY_SOUTH,
8529                                 "South");
8530   gtk_widget_show (window);
8531
8532   window = make_gravity_window (destroy_with, GDK_GRAVITY_NORTH,
8533                                 "North");
8534   gtk_widget_show (window);
8535
8536   
8537   window = make_gravity_window (destroy_with, GDK_GRAVITY_WEST,
8538                                 "West");
8539   gtk_widget_show (window);
8540
8541     
8542   window = make_gravity_window (destroy_with, GDK_GRAVITY_EAST,
8543                                 "East");
8544   gtk_widget_show (window);
8545
8546   window = make_gravity_window (destroy_with, GDK_GRAVITY_CENTER,
8547                                 "Center");
8548   gtk_widget_show (window);
8549
8550   window = make_gravity_window (destroy_with, GDK_GRAVITY_STATIC,
8551                                 "Static");
8552   gtk_widget_show (window);
8553 }
8554
8555 static GtkWidget*
8556 window_controls (GtkWidget *window)
8557 {
8558   GtkWidget *control_window;
8559   GtkWidget *label;
8560   GtkWidget *vbox;
8561   GtkWidget *button;
8562   GtkWidget *spin;
8563   GtkAdjustment *adj;
8564   GtkWidget *entry;
8565   GtkWidget *om;
8566   gint i;
8567   
8568   control_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8569
8570   gtk_window_set_screen (GTK_WINDOW (control_window),
8571                          gtk_widget_get_screen (window));
8572
8573   gtk_window_set_title (GTK_WINDOW (control_window), "Size controls");
8574   
8575   g_object_set_data (G_OBJECT (control_window),
8576                      "target",
8577                      window);
8578   
8579   g_signal_connect_object (control_window,
8580                            "destroy",
8581                            G_CALLBACK (gtk_widget_destroy),
8582                            window,
8583                            G_CONNECT_SWAPPED);
8584
8585   vbox = gtk_vbox_new (FALSE, 5);
8586   
8587   gtk_container_add (GTK_CONTAINER (control_window), vbox);
8588   
8589   label = gtk_label_new ("<no configure events>");
8590   gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
8591   
8592   g_signal_connect (window,
8593                     "configure_event",
8594                     G_CALLBACK (configure_event_callback),
8595                     label);
8596
8597   adj = (GtkAdjustment *) gtk_adjustment_new (10.0, -2000.0, 2000.0, 1.0,
8598                                               5.0, 0.0);
8599   spin = gtk_spin_button_new (adj, 0, 0);
8600
8601   gtk_box_pack_start (GTK_BOX (vbox), spin, FALSE, FALSE, 0);
8602
8603   g_object_set_data (G_OBJECT (control_window), "spin1", spin);
8604
8605   adj = (GtkAdjustment *) gtk_adjustment_new (10.0, -2000.0, 2000.0, 1.0,
8606                                               5.0, 0.0);
8607   spin = gtk_spin_button_new (adj, 0, 0);
8608
8609   gtk_box_pack_start (GTK_BOX (vbox), spin, FALSE, FALSE, 0);
8610
8611   g_object_set_data (G_OBJECT (control_window), "spin2", spin);
8612
8613   entry = gtk_entry_new ();
8614   gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
8615
8616   g_signal_connect (entry, "changed",
8617                     G_CALLBACK (set_geometry_callback),
8618                     control_window);
8619
8620   button = gtk_button_new_with_label ("Show gravity test windows");
8621   g_signal_connect_swapped (button,
8622                             "clicked",
8623                             G_CALLBACK (do_gravity_test),
8624                             control_window);
8625   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8626
8627   button = gtk_button_new_with_label ("Reshow with initial size");
8628   g_signal_connect_object (button,
8629                            "clicked",
8630                            G_CALLBACK (gtk_window_reshow_with_initial_size),
8631                            window,
8632                            G_CONNECT_SWAPPED);
8633   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8634   
8635   button = gtk_button_new_with_label ("Queue resize");
8636   g_signal_connect_object (button,
8637                            "clicked",
8638                            G_CALLBACK (gtk_widget_queue_resize),
8639                            window,
8640                            G_CONNECT_SWAPPED);
8641   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8642   
8643   button = gtk_button_new_with_label ("Resize");
8644   g_signal_connect (button,
8645                     "clicked",
8646                     G_CALLBACK (set_size_callback),
8647                     control_window);
8648   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8649
8650   button = gtk_button_new_with_label ("Set default size");
8651   g_signal_connect (button,
8652                     "clicked",
8653                     G_CALLBACK (set_default_size_callback),
8654                     control_window);
8655   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8656
8657   button = gtk_button_new_with_label ("Unset default size");
8658   g_signal_connect (button,
8659                     "clicked",
8660                     G_CALLBACK (unset_default_size_callback),
8661                     control_window);
8662   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8663   
8664   button = gtk_button_new_with_label ("Set size request");
8665   g_signal_connect (button,
8666                     "clicked",
8667                     G_CALLBACK (set_size_request_callback),
8668                     control_window);
8669   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8670
8671   button = gtk_button_new_with_label ("Unset size request");
8672   g_signal_connect (button,
8673                     "clicked",
8674                     G_CALLBACK (unset_size_request_callback),
8675                     control_window);
8676   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8677   
8678   button = gtk_button_new_with_label ("Move");
8679   g_signal_connect (button,
8680                     "clicked",
8681                     G_CALLBACK (set_location_callback),
8682                     control_window);
8683   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8684
8685   button = gtk_button_new_with_label ("Move to current position");
8686   g_signal_connect (button,
8687                     "clicked",
8688                     G_CALLBACK (move_to_position_callback),
8689                     control_window);
8690   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8691   
8692   button = gtk_check_button_new_with_label ("Allow shrink");
8693   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE);
8694   g_signal_connect (button,
8695                     "toggled",
8696                     G_CALLBACK (allow_shrink_callback),
8697                     control_window);
8698   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8699
8700   button = gtk_check_button_new_with_label ("Allow grow");
8701   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
8702   g_signal_connect (button,
8703                     "toggled",
8704                     G_CALLBACK (allow_grow_callback),
8705                     control_window);
8706   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8707   
8708   button = gtk_button_new_with_mnemonic ("_Show");
8709   g_signal_connect_object (button,
8710                            "clicked",
8711                            G_CALLBACK (gtk_widget_show),
8712                            window,
8713                            G_CONNECT_SWAPPED);
8714   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8715
8716   button = gtk_button_new_with_mnemonic ("_Hide");
8717   g_signal_connect_object (button,
8718                            "clicked",
8719                            G_CALLBACK (gtk_widget_hide),
8720                            window,
8721                            G_CONNECT_SWAPPED);
8722   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8723   
8724   om = gtk_combo_box_new_text ();
8725   i = 0;
8726   while (i < 10)
8727     {
8728       static gchar *names[] = {
8729         "GDK_GRAVITY_NORTH_WEST",
8730         "GDK_GRAVITY_NORTH",
8731         "GDK_GRAVITY_NORTH_EAST",
8732         "GDK_GRAVITY_WEST",
8733         "GDK_GRAVITY_CENTER",
8734         "GDK_GRAVITY_EAST",
8735         "GDK_GRAVITY_SOUTH_WEST",
8736         "GDK_GRAVITY_SOUTH",
8737         "GDK_GRAVITY_SOUTH_EAST",
8738         "GDK_GRAVITY_STATIC",
8739         NULL
8740       };
8741
8742       g_assert (names[i]);
8743       gtk_combo_box_append_text (GTK_COMBO_BOX (om), names[i]);
8744
8745       ++i;
8746     }
8747   
8748   g_signal_connect (om,
8749                     "changed",
8750                     G_CALLBACK (gravity_selected),
8751                     control_window);
8752
8753   gtk_box_pack_end (GTK_BOX (vbox), om, FALSE, FALSE, 0);
8754
8755
8756   om = gtk_combo_box_new_text ();
8757   i = 0;
8758   while (i < 5)
8759     {
8760       static gchar *names[] = {
8761         "GTK_WIN_POS_NONE",
8762         "GTK_WIN_POS_CENTER",
8763         "GTK_WIN_POS_MOUSE",
8764         "GTK_WIN_POS_CENTER_ALWAYS",
8765         "GTK_WIN_POS_CENTER_ON_PARENT",
8766         NULL
8767       };
8768
8769       g_assert (names[i]);
8770       gtk_combo_box_append_text (GTK_COMBO_BOX (om), names[i]);
8771
8772       ++i;
8773     }
8774
8775   g_signal_connect (om,
8776                     "changed",
8777                     G_CALLBACK (pos_selected),
8778                     control_window);
8779
8780   gtk_box_pack_end (GTK_BOX (vbox), om, FALSE, FALSE, 0);
8781   
8782   gtk_widget_show_all (vbox);
8783   
8784   return control_window;
8785 }
8786
8787 void
8788 create_window_sizing (GtkWidget *widget)
8789 {
8790   static GtkWidget *window = NULL;
8791   static GtkWidget *target_window = NULL;
8792
8793   if (!target_window)
8794     {
8795       GtkWidget *label;
8796       
8797       target_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8798       gtk_window_set_screen (GTK_WINDOW (target_window),
8799                              gtk_widget_get_screen (widget));
8800       label = gtk_label_new (NULL);
8801       gtk_label_set_markup (GTK_LABEL (label), "<span foreground=\"purple\"><big>Window being resized</big></span>\nBlah blah blah blah\nblah blah blah\nblah blah blah blah blah");
8802       gtk_container_add (GTK_CONTAINER (target_window), label);
8803       gtk_widget_show (label);
8804       
8805       g_signal_connect (target_window, "destroy",
8806                         G_CALLBACK (gtk_widget_destroyed),
8807                         &target_window);
8808
8809       window = window_controls (target_window);
8810       
8811       g_signal_connect (window, "destroy",
8812                         G_CALLBACK (gtk_widget_destroyed),
8813                         &window);
8814       
8815       gtk_window_set_title (GTK_WINDOW (target_window), "Window to size");
8816     }
8817
8818   /* don't show target window by default, we want to allow testing
8819    * of behavior on first show.
8820    */
8821   
8822   if (!gtk_widget_get_visible (window))
8823     gtk_widget_show (window);
8824   else
8825     gtk_widget_destroy (window);
8826 }
8827
8828 /*
8829  * GtkProgressBar
8830  */
8831
8832 typedef struct _ProgressData {
8833   GtkWidget *window;
8834   GtkWidget *pbar;
8835   GtkWidget *block_spin;
8836   GtkWidget *x_align_spin;
8837   GtkWidget *y_align_spin;
8838   GtkWidget *step_spin;
8839   GtkWidget *act_blocks_spin;
8840   GtkWidget *label;
8841   GtkWidget *omenu1;
8842   GtkWidget *elmenu;
8843   GtkWidget *omenu2;
8844   GtkWidget *entry;
8845   int timer;
8846   gboolean activity;
8847 } ProgressData;
8848
8849 gboolean
8850 progress_timeout (gpointer data)
8851 {
8852   ProgressData *pdata = data;
8853   gdouble new_val;
8854   gchar *text;
8855
8856   if (pdata->activity)
8857     {
8858       gtk_progress_bar_pulse (GTK_PROGRESS_BAR (pdata->pbar));
8859
8860       text = g_strdup_printf ("%s", "???");
8861     }
8862   else
8863     {
8864       new_val = gtk_progress_bar_get_fraction (GTK_PROGRESS_BAR (pdata->pbar)) + 0.01;
8865       if (new_val > 1.00)
8866         new_val = 0.00;
8867       gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (pdata->pbar), new_val);
8868
8869       text = g_strdup_printf ("%.0f%%", 100 * new_val);
8870     }
8871
8872   gtk_label_set_text (GTK_LABEL (pdata->label), text);
8873   g_free (text);
8874
8875   return TRUE;
8876 }
8877
8878 static void
8879 destroy_progress (GtkWidget     *widget,
8880                   ProgressData **pdata)
8881 {
8882   g_source_remove ((*pdata)->timer);
8883   (*pdata)->timer = 0;
8884   (*pdata)->window = NULL;
8885   g_free (*pdata);
8886   *pdata = NULL;
8887 }
8888
8889 static void
8890 progressbar_toggle_orientation (GtkWidget *widget, gpointer data)
8891 {
8892   ProgressData *pdata;
8893   gint i;
8894
8895   pdata = (ProgressData *) data;
8896
8897   if (!gtk_widget_get_mapped (widget))
8898     return;
8899
8900   i = gtk_combo_box_get_active (GTK_COMBO_BOX (widget));
8901
8902   gtk_progress_bar_set_orientation (GTK_PROGRESS_BAR (pdata->pbar),
8903                                     (GtkProgressBarOrientation) i);
8904 }
8905
8906 static void
8907 toggle_show_text (GtkWidget *widget, ProgressData *pdata)
8908 {
8909   gboolean active;
8910
8911   active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
8912   gtk_progress_bar_set_text (GTK_PROGRESS_BAR (pdata->pbar),
8913                              active ? gtk_entry_get_text (GTK_ENTRY (pdata->entry)) : NULL);
8914
8915   gtk_widget_set_sensitive (pdata->entry, active);
8916 }
8917
8918 static void
8919 progressbar_toggle_ellipsize (GtkWidget *widget,
8920                               gpointer   data)
8921 {
8922   ProgressData *pdata = data;
8923   if (gtk_widget_is_drawable (widget))
8924     {
8925       gint i = gtk_combo_box_get_active (GTK_COMBO_BOX (widget));
8926       gtk_progress_bar_set_ellipsize (GTK_PROGRESS_BAR (pdata->pbar), i);
8927     }
8928 }
8929
8930 static void
8931 toggle_activity_mode (GtkWidget *widget, ProgressData *pdata)
8932 {
8933   pdata->activity = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
8934 }
8935
8936 static void
8937 entry_changed (GtkWidget *widget, ProgressData *pdata)
8938 {
8939   gtk_progress_bar_set_text (GTK_PROGRESS_BAR (pdata->pbar),
8940                           gtk_entry_get_text (GTK_ENTRY (pdata->entry)));
8941 }
8942
8943 void
8944 create_progress_bar (GtkWidget *widget)
8945 {
8946   GtkWidget *button;
8947   GtkWidget *vbox;
8948   GtkWidget *vbox2;
8949   GtkWidget *hbox;
8950   GtkWidget *check;
8951   GtkWidget *frame;
8952   GtkWidget *tab;
8953   GtkWidget *label;
8954   GtkWidget *align;
8955   static ProgressData *pdata = NULL;
8956
8957   static gchar *items1[] =
8958   {
8959     "Left-Right",
8960     "Right-Left",
8961     "Bottom-Top",
8962     "Top-Bottom"
8963   };
8964
8965     static char *ellipsize_items[] = {
8966     "None",     // PANGO_ELLIPSIZE_NONE,
8967     "Start",    // PANGO_ELLIPSIZE_START,
8968     "Middle",   // PANGO_ELLIPSIZE_MIDDLE,
8969     "End",      // PANGO_ELLIPSIZE_END
8970   };
8971   
8972   if (!pdata)
8973     pdata = g_new0 (ProgressData, 1);
8974
8975   if (!pdata->window)
8976     {
8977       pdata->window = gtk_dialog_new ();
8978
8979       gtk_window_set_screen (GTK_WINDOW (pdata->window),
8980                              gtk_widget_get_screen (widget));
8981
8982       gtk_window_set_resizable (GTK_WINDOW (pdata->window), TRUE);
8983
8984       g_signal_connect (pdata->window, "destroy",
8985                         G_CALLBACK (destroy_progress),
8986                         &pdata);
8987
8988       pdata->timer = 0;
8989
8990       gtk_window_set_title (GTK_WINDOW (pdata->window), "GtkProgressBar");
8991       gtk_container_set_border_width (GTK_CONTAINER (pdata->window), 0);
8992
8993       vbox = gtk_vbox_new (FALSE, 5);
8994       gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
8995       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (pdata->window)->vbox), 
8996                           vbox, FALSE, TRUE, 0);
8997
8998       frame = gtk_frame_new ("Progress");
8999       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
9000
9001       vbox2 = gtk_vbox_new (FALSE, 5);
9002       gtk_container_add (GTK_CONTAINER (frame), vbox2);
9003
9004       align = gtk_alignment_new (0.5, 0.5, 0, 0);
9005       gtk_box_pack_start (GTK_BOX (vbox2), align, FALSE, FALSE, 5);
9006
9007       pdata->pbar = gtk_progress_bar_new ();
9008       gtk_progress_bar_set_ellipsize (GTK_PROGRESS_BAR (pdata->pbar),
9009                                       PANGO_ELLIPSIZE_MIDDLE);
9010
9011       gtk_container_add (GTK_CONTAINER (align), pdata->pbar);
9012       pdata->timer = g_timeout_add (100, (GSourceFunc)progress_timeout, pdata);
9013
9014       align = gtk_alignment_new (0.5, 0.5, 0, 0);
9015       gtk_box_pack_start (GTK_BOX (vbox2), align, FALSE, FALSE, 5);
9016
9017       hbox = gtk_hbox_new (FALSE, 5);
9018       gtk_container_add (GTK_CONTAINER (align), hbox);
9019       label = gtk_label_new ("Label updated by user :"); 
9020       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
9021       pdata->label = gtk_label_new ("");
9022       gtk_box_pack_start (GTK_BOX (hbox), pdata->label, FALSE, TRUE, 0);
9023
9024       frame = gtk_frame_new ("Options");
9025       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
9026
9027       vbox2 = gtk_vbox_new (FALSE, 5);
9028       gtk_container_add (GTK_CONTAINER (frame), vbox2);
9029
9030       tab = gtk_table_new (7, 2, FALSE);
9031       gtk_box_pack_start (GTK_BOX (vbox2), tab, FALSE, TRUE, 0);
9032
9033       label = gtk_label_new ("Orientation :");
9034       gtk_table_attach (GTK_TABLE (tab), label, 0, 1, 0, 1,
9035                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
9036                         5, 5);
9037       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
9038
9039       pdata->omenu1 = build_option_menu (items1, 4, 0,
9040                                          progressbar_toggle_orientation,
9041                                          pdata);
9042       hbox = gtk_hbox_new (FALSE, 0);
9043       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 0, 1,
9044                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
9045                         5, 5);
9046       gtk_box_pack_start (GTK_BOX (hbox), pdata->omenu1, TRUE, TRUE, 0);
9047       
9048       check = gtk_check_button_new_with_label ("Show text");
9049       g_signal_connect (check, "clicked",
9050                         G_CALLBACK (toggle_show_text),
9051                         pdata);
9052       gtk_table_attach (GTK_TABLE (tab), check, 0, 1, 1, 2,
9053                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
9054                         5, 5);
9055
9056       hbox = gtk_hbox_new (FALSE, 0);
9057       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 1, 2,
9058                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
9059                         5, 5);
9060
9061       label = gtk_label_new ("Text: ");
9062       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
9063
9064       pdata->entry = gtk_entry_new ();
9065       gtk_entry_set_text (GTK_ENTRY (pdata->entry), "Installing ...");
9066       g_signal_connect (pdata->entry, "changed",
9067                         G_CALLBACK (entry_changed),
9068                         pdata);
9069       gtk_box_pack_start (GTK_BOX (hbox), pdata->entry, TRUE, TRUE, 0);
9070       gtk_widget_set_size_request (pdata->entry, 100, -1);
9071       gtk_widget_set_sensitive (pdata->entry, FALSE);
9072
9073       label = gtk_label_new ("Ellipsize text :");
9074       gtk_table_attach (GTK_TABLE (tab), label, 0, 1, 10, 11,
9075                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
9076                         5, 5);
9077       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
9078       pdata->elmenu = build_option_menu (ellipsize_items,
9079                                          sizeof (ellipsize_items) / sizeof (ellipsize_items[0]),
9080                                          2, // PANGO_ELLIPSIZE_MIDDLE
9081                                          progressbar_toggle_ellipsize,
9082                                          pdata);
9083       hbox = gtk_hbox_new (FALSE, 0);
9084       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 10, 11,
9085                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
9086                         5, 5);
9087       gtk_box_pack_start (GTK_BOX (hbox), pdata->elmenu, TRUE, TRUE, 0);
9088
9089       check = gtk_check_button_new_with_label ("Activity mode");
9090       g_signal_connect (check, "clicked",
9091                         G_CALLBACK (toggle_activity_mode), pdata);
9092       gtk_table_attach (GTK_TABLE (tab), check, 0, 1, 15, 16,
9093                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
9094                         5, 5);
9095
9096       button = gtk_button_new_with_label ("close");
9097       g_signal_connect_swapped (button, "clicked",
9098                                 G_CALLBACK (gtk_widget_destroy),
9099                                 pdata->window);
9100       gtk_widget_set_can_default (button, TRUE);
9101       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (pdata->window)->action_area), 
9102                           button, TRUE, TRUE, 0);
9103       gtk_widget_grab_default (button);
9104     }
9105
9106   if (!gtk_widget_get_visible (pdata->window))
9107     gtk_widget_show_all (pdata->window);
9108   else
9109     gtk_widget_destroy (pdata->window);
9110 }
9111
9112 /*
9113  * Properties
9114  */
9115
9116 typedef struct {
9117   int x;
9118   int y;
9119   gboolean found;
9120   gboolean first;
9121   GtkWidget *res_widget;
9122 } FindWidgetData;
9123
9124 static void
9125 find_widget (GtkWidget *widget, FindWidgetData *data)
9126 {
9127   GtkAllocation new_allocation;
9128   gint x_offset = 0;
9129   gint y_offset = 0;
9130
9131   new_allocation = widget->allocation;
9132
9133   if (data->found || !gtk_widget_get_mapped (widget))
9134     return;
9135
9136   /* Note that in the following code, we only count the
9137    * position as being inside a WINDOW widget if it is inside
9138    * widget->window; points that are outside of widget->window
9139    * but within the allocation are not counted. This is consistent
9140    * with the way we highlight drag targets.
9141    */
9142   if (gtk_widget_get_has_window (widget))
9143     {
9144       new_allocation.x = 0;
9145       new_allocation.y = 0;
9146     }
9147   
9148   if (widget->parent && !data->first)
9149     {
9150       GdkWindow *window = widget->window;
9151       while (window != widget->parent->window)
9152         {
9153           gint tx, ty, twidth, theight;
9154           gdk_drawable_get_size (window, &twidth, &theight);
9155
9156           if (new_allocation.x < 0)
9157             {
9158               new_allocation.width += new_allocation.x;
9159               new_allocation.x = 0;
9160             }
9161           if (new_allocation.y < 0)
9162             {
9163               new_allocation.height += new_allocation.y;
9164               new_allocation.y = 0;
9165             }
9166           if (new_allocation.x + new_allocation.width > twidth)
9167             new_allocation.width = twidth - new_allocation.x;
9168           if (new_allocation.y + new_allocation.height > theight)
9169             new_allocation.height = theight - new_allocation.y;
9170
9171           gdk_window_get_position (window, &tx, &ty);
9172           new_allocation.x += tx;
9173           x_offset += tx;
9174           new_allocation.y += ty;
9175           y_offset += ty;
9176           
9177           window = gdk_window_get_parent (window);
9178         }
9179     }
9180
9181   if ((data->x >= new_allocation.x) && (data->y >= new_allocation.y) &&
9182       (data->x < new_allocation.x + new_allocation.width) && 
9183       (data->y < new_allocation.y + new_allocation.height))
9184     {
9185       /* First, check if the drag is in a valid drop site in
9186        * one of our children 
9187        */
9188       if (GTK_IS_CONTAINER (widget))
9189         {
9190           FindWidgetData new_data = *data;
9191           
9192           new_data.x -= x_offset;
9193           new_data.y -= y_offset;
9194           new_data.found = FALSE;
9195           new_data.first = FALSE;
9196           
9197           gtk_container_forall (GTK_CONTAINER (widget),
9198                                 (GtkCallback)find_widget,
9199                                 &new_data);
9200           
9201           data->found = new_data.found;
9202           if (data->found)
9203             data->res_widget = new_data.res_widget;
9204         }
9205
9206       /* If not, and this widget is registered as a drop site, check to
9207        * emit "drag_motion" to check if we are actually in
9208        * a drop site.
9209        */
9210       if (!data->found)
9211         {
9212           data->found = TRUE;
9213           data->res_widget = widget;
9214         }
9215     }
9216 }
9217
9218 static GtkWidget *
9219 find_widget_at_pointer (GdkDisplay *display)
9220 {
9221   GtkWidget *widget = NULL;
9222   GdkWindow *pointer_window;
9223   gint x, y;
9224   FindWidgetData data;
9225  
9226  pointer_window = gdk_display_get_window_at_pointer (display, NULL, NULL);
9227  
9228  if (pointer_window)
9229    {
9230      gpointer widget_ptr;
9231
9232      gdk_window_get_user_data (pointer_window, &widget_ptr);
9233      widget = widget_ptr;
9234    }
9235
9236  if (widget)
9237    {
9238      gdk_window_get_pointer (widget->window,
9239                              &x, &y, NULL);
9240      
9241      data.x = x;
9242      data.y = y;
9243      data.found = FALSE;
9244      data.first = TRUE;
9245
9246      find_widget (widget, &data);
9247      if (data.found)
9248        return data.res_widget;
9249      return widget;
9250    }
9251  return NULL;
9252 }
9253
9254 struct PropertiesData {
9255   GtkWidget **window;
9256   GdkCursor *cursor;
9257   gboolean in_query;
9258   gint handler;
9259 };
9260
9261 static void
9262 destroy_properties (GtkWidget             *widget,
9263                     struct PropertiesData *data)
9264 {
9265   if (data->window)
9266     {
9267       *data->window = NULL;
9268       data->window = NULL;
9269     }
9270
9271   if (data->cursor)
9272     {
9273       gdk_cursor_unref (data->cursor);
9274       data->cursor = NULL;
9275     }
9276
9277   if (data->handler)
9278     {
9279       g_signal_handler_disconnect (widget, data->handler);
9280       data->handler = 0;
9281     }
9282
9283   g_free (data);
9284 }
9285
9286 static gint
9287 property_query_event (GtkWidget        *widget,
9288                       GdkEvent         *event,
9289                       struct PropertiesData *data)
9290 {
9291   GtkWidget *res_widget = NULL;
9292
9293   if (!data->in_query)
9294     return FALSE;
9295   
9296   if (event->type == GDK_BUTTON_RELEASE)
9297     {
9298       gtk_grab_remove (widget);
9299       gdk_display_pointer_ungrab (gtk_widget_get_display (widget),
9300                                   GDK_CURRENT_TIME);
9301       
9302       res_widget = find_widget_at_pointer (gtk_widget_get_display (widget));
9303       if (res_widget)
9304         {
9305           g_object_set_data (G_OBJECT (res_widget), "prop-editor-screen",
9306                              gtk_widget_get_screen (widget));
9307           create_prop_editor (G_OBJECT (res_widget), 0);
9308         }
9309
9310       data->in_query = FALSE;
9311     }
9312   return FALSE;
9313 }
9314
9315
9316 static void
9317 query_properties (GtkButton *button,
9318                   struct PropertiesData *data)
9319 {
9320   gint failure;
9321
9322   g_signal_connect (button, "event",
9323                     G_CALLBACK (property_query_event), data);
9324
9325
9326   if (!data->cursor)
9327     data->cursor = gdk_cursor_new_for_display (gtk_widget_get_display (GTK_WIDGET (button)),
9328                                                GDK_TARGET);
9329   
9330   failure = gdk_pointer_grab (GTK_WIDGET (button)->window,
9331                               TRUE,
9332                               GDK_BUTTON_RELEASE_MASK,
9333                               NULL,
9334                               data->cursor,
9335                               GDK_CURRENT_TIME);
9336
9337   gtk_grab_add (GTK_WIDGET (button));
9338
9339   data->in_query = TRUE;
9340 }
9341
9342 static void
9343 create_properties (GtkWidget *widget)
9344 {
9345   static GtkWidget *window = NULL;
9346   GtkWidget *button;
9347   GtkWidget *vbox;
9348   GtkWidget *label;
9349   struct PropertiesData *data;
9350
9351   data = g_new (struct PropertiesData, 1);
9352   data->window = &window;
9353   data->in_query = FALSE;
9354   data->cursor = NULL;
9355   data->handler = 0;
9356
9357   if (!window)
9358     {
9359       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9360
9361       gtk_window_set_screen (GTK_WINDOW (window),
9362                              gtk_widget_get_screen (widget));      
9363
9364       data->handler = g_signal_connect (window, "destroy",
9365                                         G_CALLBACK (destroy_properties),
9366                                         data);
9367
9368       gtk_window_set_title (GTK_WINDOW (window), "test properties");
9369       gtk_container_set_border_width (GTK_CONTAINER (window), 10);
9370
9371       vbox = gtk_vbox_new (FALSE, 1);
9372       gtk_container_add (GTK_CONTAINER (window), vbox);
9373             
9374       label = gtk_label_new ("This is just a dumb test to test properties.\nIf you need a generic module, get GLE.");
9375       gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
9376       
9377       button = gtk_button_new_with_label ("Query properties");
9378       gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
9379       g_signal_connect (button, "clicked",
9380                         G_CALLBACK (query_properties),
9381                         data);
9382     }
9383
9384   if (!gtk_widget_get_visible (window))
9385     gtk_widget_show_all (window);
9386   else
9387     gtk_widget_destroy (window);
9388   
9389 }
9390
9391 struct SnapshotData {
9392   GtkWidget *toplevel_button;
9393   GtkWidget **window;
9394   GdkCursor *cursor;
9395   gboolean in_query;
9396   gboolean is_toplevel;
9397   gint handler;
9398 };
9399
9400 static void
9401 destroy_snapshot_data (GtkWidget             *widget,
9402                        struct SnapshotData *data)
9403 {
9404   if (*data->window)
9405     *data->window = NULL;
9406   
9407   if (data->cursor)
9408     {
9409       gdk_cursor_unref (data->cursor);
9410       data->cursor = NULL;
9411     }
9412
9413   if (data->handler)
9414     {
9415       g_signal_handler_disconnect (widget, data->handler);
9416       data->handler = 0;
9417     }
9418
9419   g_free (data);
9420 }
9421
9422 static gint
9423 snapshot_widget_event (GtkWidget               *widget,
9424                        GdkEvent        *event,
9425                        struct SnapshotData *data)
9426 {
9427   GtkWidget *res_widget = NULL;
9428
9429   if (!data->in_query)
9430     return FALSE;
9431   
9432   if (event->type == GDK_BUTTON_RELEASE)
9433     {
9434       gtk_grab_remove (widget);
9435       gdk_display_pointer_ungrab (gtk_widget_get_display (widget),
9436                                   GDK_CURRENT_TIME);
9437       
9438       res_widget = find_widget_at_pointer (gtk_widget_get_display (widget));
9439       if (data->is_toplevel && res_widget)
9440         res_widget = gtk_widget_get_toplevel (res_widget);
9441       if (res_widget)
9442         {
9443           GdkPixmap *pixmap;
9444           GtkWidget *window, *image;
9445
9446           window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9447           pixmap = gtk_widget_get_snapshot (res_widget, NULL);
9448           gtk_widget_realize (window);
9449           if (gdk_drawable_get_depth (window->window) != gdk_drawable_get_depth (pixmap))
9450             {
9451               /* this branch is needed to convert ARGB -> RGB */
9452               int width, height;
9453               GdkPixbuf *pixbuf;
9454               gdk_drawable_get_size (pixmap, &width, &height);
9455               pixbuf = gdk_pixbuf_get_from_drawable (NULL, pixmap,
9456                                                      gtk_widget_get_colormap (res_widget),
9457                                                      0, 0,
9458                                                      0, 0,
9459                                                      width, height);
9460               image = gtk_image_new_from_pixbuf (pixbuf);
9461               g_object_unref (pixbuf);
9462             }
9463           else
9464             image = gtk_image_new_from_pixmap (pixmap, NULL);
9465           gtk_container_add (GTK_CONTAINER (window), image);
9466           g_object_unref (pixmap);
9467           gtk_widget_show_all (window);
9468         }
9469
9470       data->in_query = FALSE;
9471     }
9472   return FALSE;
9473 }
9474
9475
9476 static void
9477 snapshot_widget (GtkButton *button,
9478                  struct SnapshotData *data)
9479 {
9480   gint failure;
9481
9482   g_signal_connect (button, "event",
9483                     G_CALLBACK (snapshot_widget_event), data);
9484
9485   data->is_toplevel = GTK_WIDGET (button) == data->toplevel_button;
9486   
9487   if (!data->cursor)
9488     data->cursor = gdk_cursor_new_for_display (gtk_widget_get_display (GTK_WIDGET (button)),
9489                                                GDK_TARGET);
9490   
9491   failure = gdk_pointer_grab (GTK_WIDGET (button)->window,
9492                               TRUE,
9493                               GDK_BUTTON_RELEASE_MASK,
9494                               NULL,
9495                               data->cursor,
9496                               GDK_CURRENT_TIME);
9497
9498   gtk_grab_add (GTK_WIDGET (button));
9499
9500   data->in_query = TRUE;
9501 }
9502
9503 static void
9504 create_snapshot (GtkWidget *widget)
9505 {
9506   static GtkWidget *window = NULL;
9507   GtkWidget *button;
9508   GtkWidget *vbox;
9509   struct SnapshotData *data;
9510
9511   data = g_new (struct SnapshotData, 1);
9512   data->window = &window;
9513   data->in_query = FALSE;
9514   data->cursor = NULL;
9515   data->handler = 0;
9516
9517   if (!window)
9518     {
9519       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9520
9521       gtk_window_set_screen (GTK_WINDOW (window),
9522                              gtk_widget_get_screen (widget));      
9523
9524       data->handler = g_signal_connect (window, "destroy",
9525                                         G_CALLBACK (destroy_snapshot_data),
9526                                         data);
9527
9528       gtk_window_set_title (GTK_WINDOW (window), "test snapshot");
9529       gtk_container_set_border_width (GTK_CONTAINER (window), 10);
9530
9531       vbox = gtk_vbox_new (FALSE, 1);
9532       gtk_container_add (GTK_CONTAINER (window), vbox);
9533             
9534       button = gtk_button_new_with_label ("Snapshot widget");
9535       gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
9536       g_signal_connect (button, "clicked",
9537                         G_CALLBACK (snapshot_widget),
9538                         data);
9539       
9540       button = gtk_button_new_with_label ("Snapshot toplevel");
9541       data->toplevel_button = button;
9542       gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
9543       g_signal_connect (button, "clicked",
9544                         G_CALLBACK (snapshot_widget),
9545                         data);
9546     }
9547
9548   if (!gtk_widget_get_visible (window))
9549     gtk_widget_show_all (window);
9550   else
9551     gtk_widget_destroy (window);
9552   
9553 }
9554
9555 /*
9556  * Selection Test
9557  */
9558
9559 void
9560 selection_test_received (GtkWidget        *tree_view,
9561                          GtkSelectionData *data)
9562 {
9563   GtkTreeModel *model;
9564   GtkListStore *store;
9565   GdkAtom *atoms;
9566   int i, l;
9567
9568   if (data->length < 0)
9569     {
9570       g_print ("Selection retrieval failed\n");
9571       return;
9572     }
9573   if (data->type != GDK_SELECTION_TYPE_ATOM)
9574     {
9575       g_print ("Selection \"TARGETS\" was not returned as atoms!\n");
9576       return;
9577     }
9578
9579   /* Clear out any current list items */
9580
9581   model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree_view));
9582   store = GTK_LIST_STORE (model);
9583   gtk_list_store_clear (store);
9584
9585   /* Add new items to list */
9586
9587   atoms = (GdkAtom *)data->data;
9588
9589   l = data->length / sizeof (GdkAtom);
9590   for (i = 0; i < l; i++)
9591     {
9592       char *name;
9593       GtkTreeIter iter;
9594
9595       name = gdk_atom_name (atoms[i]);
9596       if (name != NULL)
9597         {
9598           gtk_list_store_insert_with_values (store, &iter, i, 0, name, -1);
9599           g_free (name);
9600         }
9601       else
9602        gtk_list_store_insert_with_values (store, &iter, i, 0,  "(bad atom)", -1);
9603     }
9604
9605   return;
9606 }
9607
9608 void
9609 selection_test_get_targets (GtkWidget *widget, GtkWidget *tree_view)
9610 {
9611   static GdkAtom targets_atom = GDK_NONE;
9612
9613   if (targets_atom == GDK_NONE)
9614     targets_atom = gdk_atom_intern ("TARGETS", FALSE);
9615
9616   gtk_selection_convert (tree_view, GDK_SELECTION_PRIMARY, targets_atom,
9617                          GDK_CURRENT_TIME);
9618 }
9619
9620 void
9621 create_selection_test (GtkWidget *widget)
9622 {
9623   static GtkWidget *window = NULL;
9624   GtkWidget *button;
9625   GtkWidget *vbox;
9626   GtkWidget *scrolled_win;
9627   GtkListStore* store;
9628   GtkWidget *tree_view;
9629   GtkTreeViewColumn *column;
9630   GtkCellRenderer *renderer;
9631   GtkWidget *label;
9632
9633   if (!window)
9634     {
9635       window = gtk_dialog_new ();
9636       
9637       gtk_window_set_screen (GTK_WINDOW (window),
9638                              gtk_widget_get_screen (widget));
9639
9640       g_signal_connect (window, "destroy",
9641                         G_CALLBACK (gtk_widget_destroyed),
9642                         &window);
9643
9644       gtk_window_set_title (GTK_WINDOW (window), "Selection Test");
9645       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
9646
9647       /* Create the list */
9648
9649       vbox = gtk_vbox_new (FALSE, 5);
9650       gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
9651       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), vbox,
9652                           TRUE, TRUE, 0);
9653
9654       label = gtk_label_new ("Gets available targets for current selection");
9655       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
9656
9657       scrolled_win = gtk_scrolled_window_new (NULL, NULL);
9658       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
9659                                       GTK_POLICY_AUTOMATIC, 
9660                                       GTK_POLICY_AUTOMATIC);
9661       gtk_box_pack_start (GTK_BOX (vbox), scrolled_win, TRUE, TRUE, 0);
9662       gtk_widget_set_size_request (scrolled_win, 100, 200);
9663
9664       store = gtk_list_store_new (1, G_TYPE_STRING);
9665       tree_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store));
9666       gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_win), tree_view);
9667
9668       renderer = gtk_cell_renderer_text_new ();
9669       column = gtk_tree_view_column_new_with_attributes ("Target", renderer,
9670                                                          "text", 0, NULL);
9671       gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), column);
9672
9673       g_signal_connect (tree_view, "selection_received",
9674                         G_CALLBACK (selection_test_received), NULL);
9675
9676       /* .. And create some buttons */
9677       button = gtk_button_new_with_label ("Get Targets");
9678       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area),
9679                           button, TRUE, TRUE, 0);
9680
9681       g_signal_connect (button, "clicked",
9682                         G_CALLBACK (selection_test_get_targets), tree_view);
9683
9684       button = gtk_button_new_with_label ("Quit");
9685       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area),
9686                           button, TRUE, TRUE, 0);
9687
9688       g_signal_connect_swapped (button, "clicked",
9689                                 G_CALLBACK (gtk_widget_destroy),
9690                                 window);
9691     }
9692
9693   if (!gtk_widget_get_visible (window))
9694     gtk_widget_show_all (window);
9695   else
9696     gtk_widget_destroy (window);
9697 }
9698
9699 /*
9700  * Test scrolling
9701  */
9702
9703 static int scroll_test_pos = 0.0;
9704
9705 static gint
9706 scroll_test_expose (GtkWidget *widget, GdkEventExpose *event,
9707                     GtkAdjustment *adj)
9708 {
9709   gint i,j;
9710   gint imin, imax, jmin, jmax;
9711   
9712   imin = (event->area.x) / 10;
9713   imax = (event->area.x + event->area.width + 9) / 10;
9714
9715   jmin = ((int)adj->value + event->area.y) / 10;
9716   jmax = ((int)adj->value + event->area.y + event->area.height + 9) / 10;
9717
9718   gdk_window_clear_area (widget->window,
9719                          event->area.x, event->area.y,
9720                          event->area.width, event->area.height);
9721
9722   for (i=imin; i<imax; i++)
9723     for (j=jmin; j<jmax; j++)
9724       if ((i+j) % 2)
9725         gdk_draw_rectangle (widget->window, 
9726                             widget->style->black_gc,
9727                             TRUE,
9728                             10*i, 10*j - (int)adj->value, 1+i%10, 1+j%10);
9729
9730   return TRUE;
9731 }
9732
9733 static gint
9734 scroll_test_scroll (GtkWidget *widget, GdkEventScroll *event,
9735                     GtkAdjustment *adj)
9736 {
9737   gdouble new_value = adj->value + ((event->direction == GDK_SCROLL_UP) ?
9738                                     -adj->page_increment / 2:
9739                                     adj->page_increment / 2);
9740   new_value = CLAMP (new_value, adj->lower, adj->upper - adj->page_size);
9741   gtk_adjustment_set_value (adj, new_value);  
9742   
9743   return TRUE;
9744 }
9745
9746 static void
9747 scroll_test_configure (GtkWidget *widget, GdkEventConfigure *event,
9748                        GtkAdjustment *adj)
9749 {
9750   adj->page_increment = 0.9 * widget->allocation.height;
9751   adj->page_size = widget->allocation.height;
9752
9753   g_signal_emit_by_name (adj, "changed");
9754 }
9755
9756 static void
9757 scroll_test_adjustment_changed (GtkAdjustment *adj, GtkWidget *widget)
9758 {
9759   /* gint source_min = (int)adj->value - scroll_test_pos; */
9760   gint dy;
9761
9762   dy = scroll_test_pos - (int)adj->value;
9763   scroll_test_pos = adj->value;
9764
9765   if (!gtk_widget_is_drawable (widget))
9766     return;
9767   gdk_window_scroll (widget->window, 0, dy);
9768   gdk_window_process_updates (widget->window, FALSE);
9769 }
9770
9771
9772 void
9773 create_scroll_test (GtkWidget *widget)
9774 {
9775   static GtkWidget *window = NULL;
9776   GtkWidget *hbox;
9777   GtkWidget *drawing_area;
9778   GtkWidget *scrollbar;
9779   GtkWidget *button;
9780   GtkAdjustment *adj;
9781   GdkGeometry geometry;
9782   GdkWindowHints geometry_mask;
9783
9784   if (!window)
9785     {
9786       window = gtk_dialog_new ();
9787
9788       gtk_window_set_screen (GTK_WINDOW (window),
9789                              gtk_widget_get_screen (widget));
9790
9791       g_signal_connect (window, "destroy",
9792                         G_CALLBACK (gtk_widget_destroyed),
9793                         &window);
9794
9795       gtk_window_set_title (GTK_WINDOW (window), "Scroll Test");
9796       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
9797
9798       hbox = gtk_hbox_new (FALSE, 0);
9799       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), hbox,
9800                           TRUE, TRUE, 0);
9801       gtk_widget_show (hbox);
9802
9803       drawing_area = gtk_drawing_area_new ();
9804       gtk_widget_set_size_request (drawing_area, 200, 200);
9805       gtk_box_pack_start (GTK_BOX (hbox), drawing_area, TRUE, TRUE, 0);
9806       gtk_widget_show (drawing_area);
9807
9808       gtk_widget_set_events (drawing_area, GDK_EXPOSURE_MASK | GDK_SCROLL_MASK);
9809
9810       adj = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 1000.0, 1.0, 180.0, 200.0));
9811       scroll_test_pos = 0.0;
9812
9813       scrollbar = gtk_vscrollbar_new (adj);
9814       gtk_box_pack_start (GTK_BOX (hbox), scrollbar, FALSE, FALSE, 0);
9815       gtk_widget_show (scrollbar);
9816
9817       g_signal_connect (drawing_area, "expose_event",
9818                         G_CALLBACK (scroll_test_expose), adj);
9819       g_signal_connect (drawing_area, "configure_event",
9820                         G_CALLBACK (scroll_test_configure), adj);
9821       g_signal_connect (drawing_area, "scroll_event",
9822                         G_CALLBACK (scroll_test_scroll), adj);
9823       
9824       g_signal_connect (adj, "value_changed",
9825                         G_CALLBACK (scroll_test_adjustment_changed),
9826                         drawing_area);
9827       
9828       /* .. And create some buttons */
9829
9830       button = gtk_button_new_with_label ("Quit");
9831       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area),
9832                           button, TRUE, TRUE, 0);
9833
9834       g_signal_connect_swapped (button, "clicked",
9835                                 G_CALLBACK (gtk_widget_destroy),
9836                                 window);
9837       gtk_widget_show (button);
9838
9839       /* Set up gridded geometry */
9840
9841       geometry_mask = GDK_HINT_MIN_SIZE | 
9842                        GDK_HINT_BASE_SIZE | 
9843                        GDK_HINT_RESIZE_INC;
9844
9845       geometry.min_width = 20;
9846       geometry.min_height = 20;
9847       geometry.base_width = 0;
9848       geometry.base_height = 0;
9849       geometry.width_inc = 10;
9850       geometry.height_inc = 10;
9851       
9852       gtk_window_set_geometry_hints (GTK_WINDOW (window),
9853                                drawing_area, &geometry, geometry_mask);
9854     }
9855
9856   if (!gtk_widget_get_visible (window))
9857     gtk_widget_show (window);
9858   else
9859     gtk_widget_destroy (window);
9860 }
9861
9862 /*
9863  * Timeout Test
9864  */
9865
9866 static int timer = 0;
9867
9868 gint
9869 timeout_test (GtkWidget *label)
9870 {
9871   static int count = 0;
9872   static char buffer[32];
9873
9874   sprintf (buffer, "count: %d", ++count);
9875   gtk_label_set_text (GTK_LABEL (label), buffer);
9876
9877   return TRUE;
9878 }
9879
9880 void
9881 start_timeout_test (GtkWidget *widget,
9882                     GtkWidget *label)
9883 {
9884   if (!timer)
9885     {
9886       timer = g_timeout_add (100, (GSourceFunc)timeout_test, label);
9887     }
9888 }
9889
9890 void
9891 stop_timeout_test (GtkWidget *widget,
9892                    gpointer   data)
9893 {
9894   if (timer)
9895     {
9896       g_source_remove (timer);
9897       timer = 0;
9898     }
9899 }
9900
9901 void
9902 destroy_timeout_test (GtkWidget  *widget,
9903                       GtkWidget **window)
9904 {
9905   stop_timeout_test (NULL, NULL);
9906
9907   *window = NULL;
9908 }
9909
9910 void
9911 create_timeout_test (GtkWidget *widget)
9912 {
9913   static GtkWidget *window = NULL;
9914   GtkWidget *button;
9915   GtkWidget *label;
9916
9917   if (!window)
9918     {
9919       window = gtk_dialog_new ();
9920
9921       gtk_window_set_screen (GTK_WINDOW (window),
9922                              gtk_widget_get_screen (widget));
9923
9924       g_signal_connect (window, "destroy",
9925                         G_CALLBACK (destroy_timeout_test),
9926                         &window);
9927
9928       gtk_window_set_title (GTK_WINDOW (window), "Timeout Test");
9929       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
9930
9931       label = gtk_label_new ("count: 0");
9932       gtk_misc_set_padding (GTK_MISC (label), 10, 10);
9933       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
9934                           label, TRUE, TRUE, 0);
9935       gtk_widget_show (label);
9936
9937       button = gtk_button_new_with_label ("close");
9938       g_signal_connect_swapped (button, "clicked",
9939                                 G_CALLBACK (gtk_widget_destroy),
9940                                 window);
9941       gtk_widget_set_can_default (button, TRUE);
9942       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
9943                           button, TRUE, TRUE, 0);
9944       gtk_widget_grab_default (button);
9945       gtk_widget_show (button);
9946
9947       button = gtk_button_new_with_label ("start");
9948       g_signal_connect (button, "clicked",
9949                         G_CALLBACK(start_timeout_test),
9950                         label);
9951       gtk_widget_set_can_default (button, TRUE);
9952       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
9953                           button, TRUE, TRUE, 0);
9954       gtk_widget_show (button);
9955
9956       button = gtk_button_new_with_label ("stop");
9957       g_signal_connect (button, "clicked",
9958                         G_CALLBACK (stop_timeout_test),
9959                         NULL);
9960       gtk_widget_set_can_default (button, TRUE);
9961       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
9962                           button, TRUE, TRUE, 0);
9963       gtk_widget_show (button);
9964     }
9965
9966   if (!gtk_widget_get_visible (window))
9967     gtk_widget_show (window);
9968   else
9969     gtk_widget_destroy (window);
9970 }
9971
9972 /*
9973  * Idle Test
9974  */
9975
9976 static int idle_id = 0;
9977
9978 static gint
9979 idle_test (GtkWidget *label)
9980 {
9981   static int count = 0;
9982   static char buffer[32];
9983
9984   sprintf (buffer, "count: %d", ++count);
9985   gtk_label_set_text (GTK_LABEL (label), buffer);
9986
9987   return TRUE;
9988 }
9989
9990 static void
9991 start_idle_test (GtkWidget *widget,
9992                  GtkWidget *label)
9993 {
9994   if (!idle_id)
9995     {
9996       idle_id = g_idle_add ((GSourceFunc) idle_test, label);
9997     }
9998 }
9999
10000 static void
10001 stop_idle_test (GtkWidget *widget,
10002                 gpointer   data)
10003 {
10004   if (idle_id)
10005     {
10006       g_source_remove (idle_id);
10007       idle_id = 0;
10008     }
10009 }
10010
10011 static void
10012 destroy_idle_test (GtkWidget  *widget,
10013                    GtkWidget **window)
10014 {
10015   stop_idle_test (NULL, NULL);
10016
10017   *window = NULL;
10018 }
10019
10020 static void
10021 toggle_idle_container (GObject *button,
10022                        GtkContainer *container)
10023 {
10024   gtk_container_set_resize_mode (container, GPOINTER_TO_INT (g_object_get_data (button, "user_data")));
10025 }
10026
10027 static void
10028 create_idle_test (GtkWidget *widget)
10029 {
10030   static GtkWidget *window = NULL;
10031   GtkWidget *button;
10032   GtkWidget *label;
10033   GtkWidget *container;
10034
10035   if (!window)
10036     {
10037       GtkWidget *button2;
10038       GtkWidget *frame;
10039       GtkWidget *box;
10040
10041       window = gtk_dialog_new ();
10042
10043       gtk_window_set_screen (GTK_WINDOW (window),
10044                              gtk_widget_get_screen (widget));
10045
10046       g_signal_connect (window, "destroy",
10047                         G_CALLBACK (destroy_idle_test),
10048                         &window);
10049
10050       gtk_window_set_title (GTK_WINDOW (window), "Idle Test");
10051       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
10052
10053       label = gtk_label_new ("count: 0");
10054       gtk_misc_set_padding (GTK_MISC (label), 10, 10);
10055       gtk_widget_show (label);
10056       
10057       container =
10058         g_object_new (GTK_TYPE_HBOX,
10059                         "visible", TRUE,
10060                         /* "GtkContainer::child", g_object_new (GTK_TYPE_HBOX,
10061                          * "GtkWidget::visible", TRUE,
10062                          */
10063                          "child", label,
10064                         /* NULL), */
10065                         NULL);
10066       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
10067                           container, TRUE, TRUE, 0);
10068
10069       frame =
10070         g_object_new (GTK_TYPE_FRAME,
10071                         "border_width", 5,
10072                         "label", "Label Container",
10073                         "visible", TRUE,
10074                         "parent", GTK_DIALOG (window)->vbox,
10075                         NULL);
10076       box =
10077         g_object_new (GTK_TYPE_VBOX,
10078                         "visible", TRUE,
10079                         "parent", frame,
10080                         NULL);
10081       button =
10082         g_object_connect (g_object_new (GTK_TYPE_RADIO_BUTTON,
10083                                           "label", "Resize-Parent",
10084                                           "user_data", (void*)GTK_RESIZE_PARENT,
10085                                           "visible", TRUE,
10086                                           "parent", box,
10087                                           NULL),
10088                           "signal::clicked", toggle_idle_container, container,
10089                           NULL);
10090       button = g_object_new (GTK_TYPE_RADIO_BUTTON,
10091                                "label", "Resize-Queue",
10092                                "user_data", (void*)GTK_RESIZE_QUEUE,
10093                                "group", button,
10094                                "visible", TRUE,
10095                                "parent", box,
10096                                NULL);
10097       g_object_connect (button,
10098                         "signal::clicked", toggle_idle_container, container,
10099                         NULL);
10100       button2 = g_object_new (GTK_TYPE_RADIO_BUTTON,
10101                                 "label", "Resize-Immediate",
10102                                 "user_data", (void*)GTK_RESIZE_IMMEDIATE,
10103                                 NULL);
10104       g_object_connect (button2,
10105                         "signal::clicked", toggle_idle_container, container,
10106                         NULL);
10107       g_object_set (button2,
10108                     "group", button,
10109                     "visible", TRUE,
10110                     "parent", box,
10111                     NULL);
10112
10113       button = gtk_button_new_with_label ("close");
10114       g_signal_connect_swapped (button, "clicked",
10115                                 G_CALLBACK (gtk_widget_destroy),
10116                                 window);
10117       gtk_widget_set_can_default (button, TRUE);
10118       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
10119                           button, TRUE, TRUE, 0);
10120       gtk_widget_grab_default (button);
10121       gtk_widget_show (button);
10122
10123       button = gtk_button_new_with_label ("start");
10124       g_signal_connect (button, "clicked",
10125                         G_CALLBACK (start_idle_test),
10126                         label);
10127       gtk_widget_set_can_default (button, TRUE);
10128       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
10129                           button, TRUE, TRUE, 0);
10130       gtk_widget_show (button);
10131
10132       button = gtk_button_new_with_label ("stop");
10133       g_signal_connect (button, "clicked",
10134                         G_CALLBACK (stop_idle_test),
10135                         NULL);
10136       gtk_widget_set_can_default (button, TRUE);
10137       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
10138                           button, TRUE, TRUE, 0);
10139       gtk_widget_show (button);
10140     }
10141
10142   if (!gtk_widget_get_visible (window))
10143     gtk_widget_show (window);
10144   else
10145     gtk_widget_destroy (window);
10146 }
10147
10148 /*
10149  * rc file test
10150  */
10151
10152 void
10153 reload_all_rc_files (void)
10154 {
10155   static GdkAtom atom_rcfiles = GDK_NONE;
10156
10157   GdkEvent *send_event = gdk_event_new (GDK_CLIENT_EVENT);
10158   int i;
10159   
10160   if (!atom_rcfiles)
10161     atom_rcfiles = gdk_atom_intern("_GTK_READ_RCFILES", FALSE);
10162
10163   for(i = 0; i < 5; i++)
10164     send_event->client.data.l[i] = 0;
10165   send_event->client.data_format = 32;
10166   send_event->client.message_type = atom_rcfiles;
10167   gdk_event_send_clientmessage_toall (send_event);
10168
10169   gdk_event_free (send_event);
10170 }
10171
10172 void
10173 create_rc_file (GtkWidget *widget)
10174 {
10175   static GtkWidget *window = NULL;
10176   GtkWidget *button;
10177   GtkWidget *frame;
10178   GtkWidget *vbox;
10179   GtkWidget *label;
10180
10181   if (!window)
10182     {
10183       window = gtk_dialog_new ();
10184
10185       gtk_window_set_screen (GTK_WINDOW (window),
10186                              gtk_widget_get_screen (widget));
10187
10188       g_signal_connect (window, "destroy",
10189                         G_CALLBACK (gtk_widget_destroyed),
10190                         &window);
10191
10192       frame = gtk_aspect_frame_new ("Testing RC file prioritization", 0.5, 0.5, 0.0, TRUE);
10193       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), frame, FALSE, FALSE, 0);
10194
10195       vbox = gtk_vbox_new (FALSE, 0);
10196       gtk_container_add (GTK_CONTAINER (frame), vbox);
10197       
10198       label = gtk_label_new ("This label should be red");
10199       gtk_widget_set_name (label, "testgtk-red-label");
10200       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
10201
10202       label = gtk_label_new ("This label should be green");
10203       gtk_widget_set_name (label, "testgtk-green-label");
10204       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
10205
10206       label = gtk_label_new ("This label should be blue");
10207       gtk_widget_set_name (label, "testgtk-blue-label");
10208       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
10209
10210       gtk_window_set_title (GTK_WINDOW (window), "Reload Rc file");
10211       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
10212
10213       button = gtk_button_new_with_label ("Reload");
10214       g_signal_connect (button, "clicked",
10215                         G_CALLBACK (gtk_rc_reparse_all), NULL);
10216       gtk_widget_set_can_default (button, TRUE);
10217       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
10218                           button, TRUE, TRUE, 0);
10219       gtk_widget_grab_default (button);
10220
10221       button = gtk_button_new_with_label ("Reload All");
10222       g_signal_connect (button, "clicked",
10223                         G_CALLBACK (reload_all_rc_files), NULL);
10224       gtk_widget_set_can_default (button, TRUE);
10225       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
10226                           button, TRUE, TRUE, 0);
10227
10228       button = gtk_button_new_with_label ("Close");
10229       g_signal_connect_swapped (button, "clicked",
10230                                 G_CALLBACK (gtk_widget_destroy),
10231                                 window);
10232       gtk_widget_set_can_default (button, TRUE);
10233       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
10234                           button, TRUE, TRUE, 0);
10235     }
10236
10237   if (!gtk_widget_get_visible (window))
10238     gtk_widget_show_all (window);
10239   else
10240     gtk_widget_destroy (window);
10241 }
10242
10243 /*
10244  * Test of recursive mainloop
10245  */
10246
10247 void
10248 mainloop_destroyed (GtkWidget *w, GtkWidget **window)
10249 {
10250   *window = NULL;
10251   gtk_main_quit ();
10252 }
10253
10254 void
10255 create_mainloop (GtkWidget *widget)
10256 {
10257   static GtkWidget *window = NULL;
10258   GtkWidget *label;
10259   GtkWidget *button;
10260
10261   if (!window)
10262     {
10263       window = gtk_dialog_new ();
10264
10265       gtk_window_set_screen (GTK_WINDOW (window),
10266                              gtk_widget_get_screen (widget));
10267
10268       gtk_window_set_title (GTK_WINDOW (window), "Test Main Loop");
10269
10270       g_signal_connect (window, "destroy",
10271                         G_CALLBACK (mainloop_destroyed),
10272                         &window);
10273
10274       label = gtk_label_new ("In recursive main loop...");
10275       gtk_misc_set_padding (GTK_MISC(label), 20, 20);
10276
10277       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), label,
10278                           TRUE, TRUE, 0);
10279       gtk_widget_show (label);
10280
10281       button = gtk_button_new_with_label ("Leave");
10282       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), button, 
10283                           FALSE, TRUE, 0);
10284
10285       g_signal_connect_swapped (button, "clicked",
10286                                 G_CALLBACK (gtk_widget_destroy),
10287                                 window);
10288
10289       gtk_widget_set_can_default (button, TRUE);
10290       gtk_widget_grab_default (button);
10291
10292       gtk_widget_show (button);
10293     }
10294
10295   if (!gtk_widget_get_visible (window))
10296     {
10297       gtk_widget_show (window);
10298
10299       g_print ("create_mainloop: start\n");
10300       gtk_main ();
10301       g_print ("create_mainloop: done\n");
10302     }
10303   else
10304     gtk_widget_destroy (window);
10305 }
10306
10307 gboolean
10308 layout_expose_handler (GtkWidget *widget, GdkEventExpose *event)
10309 {
10310   GtkLayout *layout;
10311
10312   gint i,j;
10313   gint imin, imax, jmin, jmax;
10314
10315   layout = GTK_LAYOUT (widget);
10316
10317   if (event->window != layout->bin_window)
10318     return FALSE;
10319   
10320   imin = (event->area.x) / 10;
10321   imax = (event->area.x + event->area.width + 9) / 10;
10322
10323   jmin = (event->area.y) / 10;
10324   jmax = (event->area.y + event->area.height + 9) / 10;
10325
10326   for (i=imin; i<imax; i++)
10327     for (j=jmin; j<jmax; j++)
10328       if ((i+j) % 2)
10329         gdk_draw_rectangle (layout->bin_window,
10330                             widget->style->black_gc,
10331                             TRUE,
10332                             10*i, 10*j, 
10333                             1+i%10, 1+j%10);
10334   
10335   return FALSE;
10336 }
10337
10338 void create_layout (GtkWidget *widget)
10339 {
10340   static GtkWidget *window = NULL;
10341   GtkWidget *layout;
10342   GtkWidget *scrolledwindow;
10343   GtkWidget *button;
10344
10345   if (!window)
10346     {
10347       gchar buf[16];
10348
10349       gint i, j;
10350       
10351       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
10352       gtk_window_set_screen (GTK_WINDOW (window),
10353                              gtk_widget_get_screen (widget));
10354
10355       g_signal_connect (window, "destroy",
10356                         G_CALLBACK (gtk_widget_destroyed),
10357                         &window);
10358
10359       gtk_window_set_title (GTK_WINDOW (window), "Layout");
10360       gtk_widget_set_size_request (window, 200, 200);
10361
10362       scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
10363       gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolledwindow),
10364                                            GTK_SHADOW_IN);
10365       gtk_scrolled_window_set_placement (GTK_SCROLLED_WINDOW (scrolledwindow),
10366                                          GTK_CORNER_TOP_RIGHT);
10367
10368       gtk_container_add (GTK_CONTAINER (window), scrolledwindow);
10369       
10370       layout = gtk_layout_new (NULL, NULL);
10371       gtk_container_add (GTK_CONTAINER (scrolledwindow), layout);
10372
10373       /* We set step sizes here since GtkLayout does not set
10374        * them itself.
10375        */
10376       GTK_LAYOUT (layout)->hadjustment->step_increment = 10.0;
10377       GTK_LAYOUT (layout)->vadjustment->step_increment = 10.0;
10378       
10379       gtk_widget_set_events (layout, GDK_EXPOSURE_MASK);
10380       g_signal_connect (layout, "expose_event",
10381                         G_CALLBACK (layout_expose_handler), NULL);
10382       
10383       gtk_layout_set_size (GTK_LAYOUT (layout), 1600, 128000);
10384       
10385       for (i=0 ; i < 16 ; i++)
10386         for (j=0 ; j < 16 ; j++)
10387           {
10388             sprintf(buf, "Button %d, %d", i, j);
10389             if ((i + j) % 2)
10390               button = gtk_button_new_with_label (buf);
10391             else
10392               button = gtk_label_new (buf);
10393
10394             gtk_layout_put (GTK_LAYOUT (layout), button,
10395                             j*100, i*100);
10396           }
10397
10398       for (i=16; i < 1280; i++)
10399         {
10400           sprintf(buf, "Button %d, %d", i, 0);
10401           if (i % 2)
10402             button = gtk_button_new_with_label (buf);
10403           else
10404             button = gtk_label_new (buf);
10405
10406           gtk_layout_put (GTK_LAYOUT (layout), button,
10407                           0, i*100);
10408         }
10409     }
10410
10411   if (!gtk_widget_get_visible (window))
10412     gtk_widget_show_all (window);
10413   else
10414     gtk_widget_destroy (window);
10415 }
10416
10417 void
10418 create_styles (GtkWidget *widget)
10419 {
10420   static GtkWidget *window = NULL;
10421   GtkWidget *label;
10422   GtkWidget *button;
10423   GtkWidget *entry;
10424   GtkWidget *vbox;
10425   static GdkColor red =    { 0, 0xffff, 0,      0      };
10426   static GdkColor green =  { 0, 0,      0xffff, 0      };
10427   static GdkColor blue =   { 0, 0,      0,      0xffff };
10428   static GdkColor yellow = { 0, 0xffff, 0xffff, 0      };
10429   static GdkColor cyan =   { 0, 0     , 0xffff, 0xffff };
10430   PangoFontDescription *font_desc;
10431
10432   GtkRcStyle *rc_style;
10433
10434   if (!window)
10435     {
10436       window = gtk_dialog_new ();
10437       gtk_window_set_screen (GTK_WINDOW (window),
10438                              gtk_widget_get_screen (widget));
10439      
10440       g_signal_connect (window, "destroy",
10441                         G_CALLBACK (gtk_widget_destroyed),
10442                         &window);
10443
10444       
10445       button = gtk_button_new_with_label ("Close");
10446       g_signal_connect_swapped (button, "clicked",
10447                                 G_CALLBACK (gtk_widget_destroy),
10448                                 window);
10449       gtk_widget_set_can_default (button, TRUE);
10450       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
10451                           button, TRUE, TRUE, 0);
10452       gtk_widget_show (button);
10453
10454       vbox = gtk_vbox_new (FALSE, 5);
10455       gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
10456       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), vbox, FALSE, FALSE, 0);
10457       
10458       label = gtk_label_new ("Font:");
10459       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
10460       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
10461
10462       font_desc = pango_font_description_from_string ("Helvetica,Sans Oblique 18");
10463
10464       button = gtk_button_new_with_label ("Some Text");
10465       gtk_widget_modify_font (GTK_BIN (button)->child, font_desc);
10466       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
10467
10468       label = gtk_label_new ("Foreground:");
10469       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
10470       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
10471
10472       button = gtk_button_new_with_label ("Some Text");
10473       gtk_widget_modify_fg (GTK_BIN (button)->child, GTK_STATE_NORMAL, &red);
10474       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
10475
10476       label = gtk_label_new ("Background:");
10477       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
10478       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
10479
10480       button = gtk_button_new_with_label ("Some Text");
10481       gtk_widget_modify_bg (button, GTK_STATE_NORMAL, &green);
10482       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
10483
10484       label = gtk_label_new ("Text:");
10485       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
10486       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
10487
10488       entry = gtk_entry_new ();
10489       gtk_entry_set_text (GTK_ENTRY (entry), "Some Text");
10490       gtk_widget_modify_text (entry, GTK_STATE_NORMAL, &blue);
10491       gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
10492
10493       label = gtk_label_new ("Base:");
10494       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
10495       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
10496
10497       entry = gtk_entry_new ();
10498       gtk_entry_set_text (GTK_ENTRY (entry), "Some Text");
10499       gtk_widget_modify_base (entry, GTK_STATE_NORMAL, &yellow);
10500       gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
10501
10502       label = gtk_label_new ("Cursor:");
10503       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
10504       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
10505
10506       entry = gtk_entry_new ();
10507       gtk_entry_set_text (GTK_ENTRY (entry), "Some Text");
10508       gtk_widget_modify_cursor (entry, &red, &red);
10509       gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
10510
10511       label = gtk_label_new ("Multiple:");
10512       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
10513       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
10514
10515       button = gtk_button_new_with_label ("Some Text");
10516
10517       rc_style = gtk_rc_style_new ();
10518
10519       rc_style->font_desc = pango_font_description_copy (font_desc);
10520       rc_style->color_flags[GTK_STATE_NORMAL] = GTK_RC_FG | GTK_RC_BG;
10521       rc_style->color_flags[GTK_STATE_PRELIGHT] = GTK_RC_FG | GTK_RC_BG;
10522       rc_style->color_flags[GTK_STATE_ACTIVE] = GTK_RC_FG | GTK_RC_BG;
10523       rc_style->fg[GTK_STATE_NORMAL] = yellow;
10524       rc_style->bg[GTK_STATE_NORMAL] = blue;
10525       rc_style->fg[GTK_STATE_PRELIGHT] = blue;
10526       rc_style->bg[GTK_STATE_PRELIGHT] = yellow;
10527       rc_style->fg[GTK_STATE_ACTIVE] = red;
10528       rc_style->bg[GTK_STATE_ACTIVE] = cyan;
10529       rc_style->xthickness = 5;
10530       rc_style->ythickness = 5;
10531
10532       gtk_widget_modify_style (button, rc_style);
10533       gtk_widget_modify_style (GTK_BIN (button)->child, rc_style);
10534
10535       g_object_unref (rc_style);
10536       
10537       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
10538     }
10539   
10540   if (!gtk_widget_get_visible (window))
10541     gtk_widget_show_all (window);
10542   else
10543     gtk_widget_destroy (window);
10544 }
10545
10546 /*
10547  * Main Window and Exit
10548  */
10549
10550 void
10551 do_exit (GtkWidget *widget, GtkWidget *window)
10552 {
10553   gtk_widget_destroy (window);
10554   gtk_main_quit ();
10555 }
10556
10557 struct {
10558   char *label;
10559   void (*func) (GtkWidget *widget);
10560   gboolean do_not_benchmark;
10561 } buttons[] =
10562 {
10563   { "alpha window", create_alpha_window },
10564   { "big windows", create_big_windows },
10565   { "button box", create_button_box },
10566   { "buttons", create_buttons },
10567   { "check buttons", create_check_buttons },
10568   { "color selection", create_color_selection },
10569   { "composited window", create_composited_window },
10570   { "cursors", create_cursors },
10571   { "dialog", create_dialog },
10572   { "display & screen", create_display_screen, TRUE },
10573   { "entry", create_entry },
10574   { "event box", create_event_box },
10575   { "event watcher", create_event_watcher },
10576   { "expander", create_expander },
10577   { "flipping", create_flipping },
10578   { "focus", create_focus },
10579   { "font selection", create_font_selection },
10580   { "gridded geometry", create_gridded_geometry },
10581   { "handle box", create_handle_box },
10582   { "image from drawable", create_get_image },
10583   { "image", create_image },
10584   { "key lookup", create_key_lookup },
10585   { "labels", create_labels },
10586   { "layout", create_layout },
10587   { "menus", create_menus },
10588   { "message dialog", create_message_dialog },
10589   { "modal window", create_modal_window, TRUE },
10590   { "notebook", create_notebook },
10591   { "panes", create_panes },
10592   { "paned keyboard", create_paned_keyboard_navigation },
10593   { "pixmap", create_pixmap },
10594   { "progress bar", create_progress_bar },
10595   { "properties", create_properties },
10596   { "radio buttons", create_radio_buttons },
10597   { "range controls", create_range_controls },
10598   { "rc file", create_rc_file },
10599   { "reparent", create_reparent },
10600   { "resize grips", create_resize_grips },
10601   { "rotated label", create_rotated_label },
10602   { "rotated text", create_rotated_text },
10603   { "rulers", create_rulers },
10604   { "saved position", create_saved_position },
10605   { "scrolled windows", create_scrolled_windows },
10606   { "shapes", create_shapes },
10607   { "size groups", create_size_groups },
10608   { "snapshot", create_snapshot },
10609   { "spinbutton", create_spins },
10610   { "statusbar", create_statusbar },
10611   { "styles", create_styles },
10612   { "test idle", create_idle_test },
10613   { "test mainloop", create_mainloop, TRUE },
10614   { "test scrolling", create_scroll_test },
10615   { "test selection", create_selection_test },
10616   { "test timeout", create_timeout_test },
10617   { "toggle buttons", create_toggle_buttons },
10618   { "toolbar", create_toolbar },
10619   { "tooltips", create_tooltips },
10620   { "WM hints", create_wmhints },
10621   { "window sizing", create_window_sizing },
10622   { "window states", create_window_states }
10623 };
10624 int nbuttons = sizeof (buttons) / sizeof (buttons[0]);
10625
10626 void
10627 create_main_window (void)
10628 {
10629   GtkWidget *window;
10630   GtkWidget *box1;
10631   GtkWidget *box2;
10632   GtkWidget *scrolled_window;
10633   GtkWidget *button;
10634   GtkWidget *label;
10635   gchar buffer[64];
10636   GtkWidget *separator;
10637   GdkGeometry geometry;
10638   int i;
10639
10640   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
10641   gtk_widget_set_name (window, "main window");
10642   gtk_window_move (GTK_WINDOW (window), 50, 20);
10643   gtk_window_set_default_size (GTK_WINDOW (window), -1, 400);
10644
10645   geometry.min_width = -1;
10646   geometry.min_height = -1;
10647   geometry.max_width = -1;
10648   geometry.max_height = G_MAXSHORT;
10649   gtk_window_set_geometry_hints (GTK_WINDOW (window), NULL,
10650                                  &geometry,
10651                                  GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE);
10652
10653   g_signal_connect (window, "destroy",
10654                     G_CALLBACK (gtk_main_quit),
10655                     NULL);
10656   g_signal_connect (window, "delete-event",
10657                     G_CALLBACK (gtk_false),
10658                     NULL);
10659
10660   box1 = gtk_vbox_new (FALSE, 0);
10661   gtk_container_add (GTK_CONTAINER (window), box1);
10662
10663   if (gtk_micro_version > 0)
10664     sprintf (buffer,
10665              "Gtk+ v%d.%d.%d",
10666              gtk_major_version,
10667              gtk_minor_version,
10668              gtk_micro_version);
10669   else
10670     sprintf (buffer,
10671              "Gtk+ v%d.%d",
10672              gtk_major_version,
10673              gtk_minor_version);
10674
10675   label = gtk_label_new (buffer);
10676   gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);
10677   gtk_widget_set_name (label, "testgtk-version-label");
10678
10679   scrolled_window = gtk_scrolled_window_new (NULL, NULL);
10680   gtk_container_set_border_width (GTK_CONTAINER (scrolled_window), 10);
10681   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
10682                                   GTK_POLICY_NEVER, 
10683                                   GTK_POLICY_AUTOMATIC);
10684   gtk_box_pack_start (GTK_BOX (box1), scrolled_window, TRUE, TRUE, 0);
10685
10686   box2 = gtk_vbox_new (FALSE, 0);
10687   gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
10688   gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_window), box2);
10689   gtk_container_set_focus_vadjustment (GTK_CONTAINER (box2),
10690                                        gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (scrolled_window)));
10691   gtk_widget_show (box2);
10692
10693   for (i = 0; i < nbuttons; i++)
10694     {
10695       button = gtk_button_new_with_label (buttons[i].label);
10696       if (buttons[i].func)
10697         g_signal_connect (button, 
10698                           "clicked", 
10699                           G_CALLBACK(buttons[i].func),
10700                           NULL);
10701       else
10702         gtk_widget_set_sensitive (button, FALSE);
10703       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
10704     }
10705
10706   separator = gtk_hseparator_new ();
10707   gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
10708
10709   box2 = gtk_vbox_new (FALSE, 10);
10710   gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
10711   gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
10712
10713   button = gtk_button_new_with_mnemonic ("_Close");
10714   g_signal_connect (button, "clicked",
10715                     G_CALLBACK (do_exit),
10716                     window);
10717   gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
10718   gtk_widget_set_can_default (button, TRUE);
10719   gtk_widget_grab_default (button);
10720
10721   gtk_widget_show_all (window);
10722 }
10723
10724 static void
10725 test_init (void)
10726 {
10727   if (g_file_test ("../gdk-pixbuf/libpixbufloader-pnm.la",
10728                    G_FILE_TEST_EXISTS))
10729     {
10730       g_setenv ("GDK_PIXBUF_MODULE_FILE", "../gdk-pixbuf/gdk-pixbuf.loaders", TRUE);
10731       g_setenv ("GTK_IM_MODULE_FILE", "../modules/input/gtk.immodules", TRUE);
10732     }
10733 }
10734
10735 static char *
10736 pad (const char *str, int to)
10737 {
10738   static char buf[256];
10739   int len = strlen (str);
10740   int i;
10741
10742   for (i = 0; i < to; i++)
10743     buf[i] = ' ';
10744
10745   buf[to] = '\0';
10746
10747   memcpy (buf, str, len);
10748
10749   return buf;
10750 }
10751
10752 static void
10753 bench_iteration (GtkWidget *widget, void (* fn) (GtkWidget *widget))
10754 {
10755   fn (widget); /* on */
10756   while (g_main_context_iteration (NULL, FALSE));
10757   fn (widget); /* off */
10758   while (g_main_context_iteration (NULL, FALSE));
10759 }
10760
10761 void
10762 do_real_bench (GtkWidget *widget, void (* fn) (GtkWidget *widget), char *name, int num)
10763 {
10764   GTimeVal tv0, tv1;
10765   double dt_first;
10766   double dt;
10767   int n;
10768   static gboolean printed_headers = FALSE;
10769
10770   if (!printed_headers) {
10771     g_print ("Test                 Iters      First      Other\n");
10772     g_print ("-------------------- ----- ---------- ----------\n");
10773     printed_headers = TRUE;
10774   }
10775
10776   g_get_current_time (&tv0);
10777   bench_iteration (widget, fn); 
10778   g_get_current_time (&tv1);
10779
10780   dt_first = ((double)tv1.tv_sec - tv0.tv_sec) * 1000.0
10781         + (tv1.tv_usec - tv0.tv_usec) / 1000.0;
10782
10783   g_get_current_time (&tv0);
10784   for (n = 0; n < num - 1; n++)
10785     bench_iteration (widget, fn); 
10786   g_get_current_time (&tv1);
10787   dt = ((double)tv1.tv_sec - tv0.tv_sec) * 1000.0
10788         + (tv1.tv_usec - tv0.tv_usec) / 1000.0;
10789
10790   g_print ("%s %5d ", pad (name, 20), num);
10791   if (num > 1)
10792     g_print ("%10.1f %10.1f\n", dt_first, dt/(num-1));
10793   else
10794     g_print ("%10.1f\n", dt_first);
10795 }
10796
10797 void
10798 do_bench (char* what, int num)
10799 {
10800   int i;
10801   GtkWidget *widget;
10802   void (* fn) (GtkWidget *widget);
10803   fn = NULL;
10804   widget = gtk_window_new (GTK_WINDOW_TOPLEVEL);
10805
10806   if (g_ascii_strcasecmp (what, "ALL") == 0)
10807     {
10808       for (i = 0; i < nbuttons; i++)
10809         {
10810           if (!buttons[i].do_not_benchmark)
10811             do_real_bench (widget, buttons[i].func, buttons[i].label, num);
10812         }
10813
10814       return;
10815     }
10816   else
10817     {
10818       for (i = 0; i < nbuttons; i++)
10819         {
10820           if (strcmp (buttons[i].label, what) == 0)
10821             {
10822               fn = buttons[i].func;
10823               break;
10824             }
10825         }
10826       
10827       if (!fn)
10828         g_print ("Can't bench: \"%s\" not found.\n", what);
10829       else
10830         do_real_bench (widget, fn, buttons[i].label, num);
10831     }
10832 }
10833
10834 void 
10835 usage (void)
10836 {
10837   fprintf (stderr, "Usage: testgtk [--bench ALL|<bench>[:<count>]]\n");
10838   exit (1);
10839 }
10840
10841 int
10842 main (int argc, char *argv[])
10843 {
10844   GtkBindingSet *binding_set;
10845   int i;
10846   gboolean done_benchmarks = FALSE;
10847
10848   srand (time (NULL));
10849
10850   test_init ();
10851
10852   /* Check to see if we are being run from the correct
10853    * directory.
10854    */
10855   if (file_exists ("testgtkrc"))
10856     gtk_rc_add_default_file ("testgtkrc");
10857   else if (file_exists ("tests/testgtkrc"))
10858     gtk_rc_add_default_file ("tests/testgtkrc");
10859   else
10860     g_warning ("Couldn't find file \"testgtkrc\".");
10861
10862   g_set_application_name ("GTK+ Test Program");
10863
10864   gtk_init (&argc, &argv);
10865
10866   gtk_accelerator_set_default_mod_mask (GDK_SHIFT_MASK |
10867                                         GDK_CONTROL_MASK |
10868                                         GDK_MOD1_MASK | 
10869                                         GDK_META_MASK |
10870                                         GDK_SUPER_MASK |
10871                                         GDK_HYPER_MASK |
10872                                         GDK_MOD4_MASK);
10873   /*  benchmarking
10874    */
10875   for (i = 1; i < argc; i++)
10876     {
10877       if (strncmp (argv[i], "--bench", strlen("--bench")) == 0)
10878         {
10879           int num = 1;
10880           char *nextarg;
10881           char *what;
10882           char *count;
10883           
10884           nextarg = strchr (argv[i], '=');
10885           if (nextarg)
10886             nextarg++;
10887           else
10888             {
10889               i++;
10890               if (i == argc)
10891                 usage ();
10892               nextarg = argv[i];
10893             }
10894
10895           count = strchr (nextarg, ':');
10896           if (count)
10897             {
10898               what = g_strndup (nextarg, count - nextarg);
10899               count++;
10900               num = atoi (count);
10901               if (num <= 0)
10902                 usage ();
10903             }
10904           else
10905             what = g_strdup (nextarg);
10906
10907           do_bench (what, num ? num : 1);
10908           done_benchmarks = TRUE;
10909         }
10910       else
10911         usage ();
10912     }
10913   if (done_benchmarks)
10914     return 0;
10915
10916   /* bindings test
10917    */
10918   binding_set = gtk_binding_set_by_class (g_type_class_ref (GTK_TYPE_WIDGET));
10919   gtk_binding_entry_add_signal (binding_set,
10920                                 '9', GDK_CONTROL_MASK | GDK_RELEASE_MASK,
10921                                 "debug_msg",
10922                                 1,
10923                                 G_TYPE_STRING, "GtkWidgetClass <ctrl><release>9 test");
10924   
10925   /* We use gtk_rc_parse_string() here so we can make sure it works across theme
10926    * changes
10927    */
10928
10929   gtk_rc_parse_string ("style \"testgtk-version-label\" { "
10930                        "   fg[NORMAL] = \"#ff0000\"\n"
10931                        "   font = \"Sans 18\"\n"
10932                        "}\n"
10933                        "widget \"*.testgtk-version-label\" style \"testgtk-version-label\"");
10934   
10935   create_main_window ();
10936
10937   gtk_main ();
10938
10939   if (1)
10940     {
10941       while (g_main_context_pending (NULL))
10942         g_main_context_iteration (NULL, FALSE);
10943 #if 0
10944       sleep (1);
10945       while (g_main_context_pending (NULL))
10946         g_main_context_iteration (NULL, FALSE);
10947 #endif
10948     }
10949   return 0;
10950 }