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