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