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