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