]> Pileus Git - ~andy/gtk/blob - tests/testgtk.c
Make testgtk load CSS for custom styling.
[~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 struct {
5914   GdkColor color;
5915   gchar *name;
5916 } text_colors[] = {
5917  { { 0, 0x0000, 0x0000, 0x0000 }, "black" },
5918  { { 0, 0xFFFF, 0xFFFF, 0xFFFF }, "white" },
5919  { { 0, 0xFFFF, 0x0000, 0x0000 }, "red" },
5920  { { 0, 0x0000, 0xFFFF, 0x0000 }, "green" },
5921  { { 0, 0x0000, 0x0000, 0xFFFF }, "blue" }, 
5922  { { 0, 0x0000, 0xFFFF, 0xFFFF }, "cyan" },
5923  { { 0, 0xFFFF, 0x0000, 0xFFFF }, "magenta" },
5924  { { 0, 0xFFFF, 0xFFFF, 0x0000 }, "yellow" }
5925 };
5926
5927 int ntext_colors = sizeof(text_colors) / sizeof(text_colors[0]);
5928
5929 /*
5930  * GtkNotebook
5931  */
5932
5933 static const char * book_open_xpm[] = {
5934 "16 16 4 1",
5935 "       c None s None",
5936 ".      c black",
5937 "X      c #808080",
5938 "o      c white",
5939 "                ",
5940 "  ..            ",
5941 " .Xo.    ...    ",
5942 " .Xoo. ..oo.    ",
5943 " .Xooo.Xooo...  ",
5944 " .Xooo.oooo.X.  ",
5945 " .Xooo.Xooo.X.  ",
5946 " .Xooo.oooo.X.  ",
5947 " .Xooo.Xooo.X.  ",
5948 " .Xooo.oooo.X.  ",
5949 "  .Xoo.Xoo..X.  ",
5950 "   .Xo.o..ooX.  ",
5951 "    .X..XXXXX.  ",
5952 "    ..X.......  ",
5953 "     ..         ",
5954 "                "};
5955
5956 static const char * book_closed_xpm[] = {
5957 "16 16 6 1",
5958 "       c None s None",
5959 ".      c black",
5960 "X      c red",
5961 "o      c yellow",
5962 "O      c #808080",
5963 "#      c white",
5964 "                ",
5965 "       ..       ",
5966 "     ..XX.      ",
5967 "   ..XXXXX.     ",
5968 " ..XXXXXXXX.    ",
5969 ".ooXXXXXXXXX.   ",
5970 "..ooXXXXXXXXX.  ",
5971 ".X.ooXXXXXXXXX. ",
5972 ".XX.ooXXXXXX..  ",
5973 " .XX.ooXXX..#O  ",
5974 "  .XX.oo..##OO. ",
5975 "   .XX..##OO..  ",
5976 "    .X.#OO..    ",
5977 "     ..O..      ",
5978 "      ..        ",
5979 "                "};
5980
5981 GdkPixbuf *book_open;
5982 GdkPixbuf *book_closed;
5983 GtkWidget *sample_notebook;
5984
5985 static void
5986 set_page_image (GtkNotebook *notebook, gint page_num, GdkPixbuf *pixbuf)
5987 {
5988   GtkWidget *page_widget;
5989   GtkWidget *pixwid;
5990
5991   page_widget = gtk_notebook_get_nth_page (notebook, page_num);
5992
5993   pixwid = g_object_get_data (G_OBJECT (page_widget), "tab_pixmap");
5994   gtk_image_set_from_pixbuf (GTK_IMAGE (pixwid), pixbuf);
5995   
5996   pixwid = g_object_get_data (G_OBJECT (page_widget), "menu_pixmap");
5997   gtk_image_set_from_pixbuf (GTK_IMAGE (pixwid), pixbuf);
5998 }
5999
6000 static void
6001 page_switch (GtkWidget *widget, gpointer *page, gint page_num)
6002 {
6003   GtkNotebook *notebook = GTK_NOTEBOOK (widget);
6004   gint old_page_num = gtk_notebook_get_current_page (notebook);
6005  
6006   if (page_num == old_page_num)
6007     return;
6008
6009   set_page_image (notebook, page_num, book_open);
6010
6011   if (old_page_num != -1)
6012     set_page_image (notebook, old_page_num, book_closed);
6013 }
6014
6015 static void
6016 tab_fill (GtkToggleButton *button, GtkWidget *child)
6017 {
6018   gtk_container_child_set (GTK_CONTAINER (sample_notebook), child,
6019                            "tab-fill", gtk_toggle_button_get_active (button),
6020                            NULL);
6021 }
6022
6023 static void
6024 tab_expand (GtkToggleButton *button, GtkWidget *child)
6025 {
6026   gtk_container_child_set (GTK_CONTAINER (sample_notebook), child,
6027                            "tab-expand", gtk_toggle_button_get_active (button),
6028                            NULL);
6029 }
6030
6031 static void
6032 create_pages (GtkNotebook *notebook, gint start, gint end)
6033 {
6034   GtkWidget *child = NULL;
6035   GtkWidget *button;
6036   GtkWidget *label;
6037   GtkWidget *hbox;
6038   GtkWidget *vbox;
6039   GtkWidget *label_box;
6040   GtkWidget *menu_box;
6041   GtkWidget *pixwid;
6042   gint i;
6043   char buffer[32];
6044   char accel_buffer[32];
6045
6046   for (i = start; i <= end; i++)
6047     {
6048       sprintf (buffer, "Page %d", i);
6049       sprintf (accel_buffer, "Page _%d", i);
6050
6051       child = gtk_frame_new (buffer);
6052       gtk_container_set_border_width (GTK_CONTAINER (child), 10);
6053
6054       vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
6055       gtk_box_set_homogeneous (GTK_BOX (vbox), TRUE);
6056       gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
6057       gtk_container_add (GTK_CONTAINER (child), vbox);
6058
6059       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
6060       gtk_box_set_homogeneous (GTK_BOX (hbox), TRUE);
6061       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 5);
6062
6063       button = gtk_check_button_new_with_label ("Fill Tab");
6064       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
6065       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
6066       g_signal_connect (button, "toggled",
6067                         G_CALLBACK (tab_fill), child);
6068
6069       button = gtk_check_button_new_with_label ("Expand Tab");
6070       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
6071       g_signal_connect (button, "toggled",
6072                         G_CALLBACK (tab_expand), child);
6073
6074       button = gtk_button_new_with_label ("Hide Page");
6075       gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 5);
6076       g_signal_connect_swapped (button, "clicked",
6077                                 G_CALLBACK (gtk_widget_hide),
6078                                 child);
6079
6080       gtk_widget_show_all (child);
6081
6082       label_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
6083       pixwid = gtk_image_new_from_pixbuf (book_closed);
6084       g_object_set_data (G_OBJECT (child), "tab_pixmap", pixwid);
6085                            
6086       gtk_box_pack_start (GTK_BOX (label_box), pixwid, FALSE, TRUE, 0);
6087       gtk_misc_set_padding (GTK_MISC (pixwid), 3, 1);
6088       label = gtk_label_new_with_mnemonic (accel_buffer);
6089       gtk_box_pack_start (GTK_BOX (label_box), label, FALSE, TRUE, 0);
6090       gtk_widget_show_all (label_box);
6091       
6092                                        
6093       menu_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
6094       pixwid = gtk_image_new_from_pixbuf (book_closed);
6095       g_object_set_data (G_OBJECT (child), "menu_pixmap", pixwid);
6096       
6097       gtk_box_pack_start (GTK_BOX (menu_box), pixwid, FALSE, TRUE, 0);
6098       gtk_misc_set_padding (GTK_MISC (pixwid), 3, 1);
6099       label = gtk_label_new (buffer);
6100       gtk_box_pack_start (GTK_BOX (menu_box), label, FALSE, TRUE, 0);
6101       gtk_widget_show_all (menu_box);
6102
6103       gtk_notebook_append_page_menu (notebook, child, label_box, menu_box);
6104     }
6105 }
6106
6107 static void
6108 rotate_notebook (GtkButton   *button,
6109                  GtkNotebook *notebook)
6110 {
6111   gtk_notebook_set_tab_pos (notebook, (gtk_notebook_get_tab_pos (notebook) + 1) % 4);
6112 }
6113
6114 static void
6115 show_all_pages (GtkButton   *button,
6116                 GtkNotebook *notebook)
6117 {  
6118   gtk_container_foreach (GTK_CONTAINER (notebook),
6119                          (GtkCallback) gtk_widget_show, NULL);
6120 }
6121
6122 static void
6123 notebook_type_changed (GtkWidget *optionmenu,
6124                        gpointer   data)
6125 {
6126   GtkNotebook *notebook;
6127   gint i, c;
6128
6129   enum {
6130     STANDARD,
6131     NOTABS,
6132     BORDERLESS,
6133     SCROLLABLE
6134   };
6135
6136   notebook = GTK_NOTEBOOK (data);
6137
6138   c = gtk_combo_box_get_active (GTK_COMBO_BOX (optionmenu));
6139
6140   switch (c)
6141     {
6142     case STANDARD:
6143       /* standard notebook */
6144       gtk_notebook_set_show_tabs (notebook, TRUE);
6145       gtk_notebook_set_show_border (notebook, TRUE);
6146       gtk_notebook_set_scrollable (notebook, FALSE);
6147       break;
6148
6149     case NOTABS:
6150       /* notabs notebook */
6151       gtk_notebook_set_show_tabs (notebook, FALSE);
6152       gtk_notebook_set_show_border (notebook, TRUE);
6153       break;
6154
6155     case BORDERLESS:
6156       /* borderless */
6157       gtk_notebook_set_show_tabs (notebook, FALSE);
6158       gtk_notebook_set_show_border (notebook, FALSE);
6159       break;
6160
6161     case SCROLLABLE:  
6162       /* scrollable */
6163       gtk_notebook_set_show_tabs (notebook, TRUE);
6164       gtk_notebook_set_show_border (notebook, TRUE);
6165       gtk_notebook_set_scrollable (notebook, TRUE);
6166       if (gtk_notebook_get_n_pages (notebook) == 5)
6167         create_pages (notebook, 6, 15);
6168
6169       return;
6170       break;
6171     }
6172
6173   if (gtk_notebook_get_n_pages (notebook) == 15)
6174     for (i = 0; i < 10; i++)
6175       gtk_notebook_remove_page (notebook, 5);
6176 }
6177
6178 static void
6179 notebook_popup (GtkToggleButton *button,
6180                 GtkNotebook     *notebook)
6181 {
6182   if (gtk_toggle_button_get_active (button))
6183     gtk_notebook_popup_enable (notebook);
6184   else
6185     gtk_notebook_popup_disable (notebook);
6186 }
6187
6188 static void
6189 create_notebook (GtkWidget *widget)
6190 {
6191   static GtkWidget *window = NULL;
6192   GtkWidget *box1;
6193   GtkWidget *box2;
6194   GtkWidget *button;
6195   GtkWidget *separator;
6196   GtkWidget *omenu;
6197   GtkWidget *label;
6198
6199   static gchar *items[] =
6200   {
6201     "Standard",
6202     "No tabs",
6203     "Borderless",
6204     "Scrollable"
6205   };
6206   
6207   if (!window)
6208     {
6209       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6210       gtk_window_set_screen (GTK_WINDOW (window),
6211                              gtk_widget_get_screen (widget));
6212
6213       g_signal_connect (window, "destroy",
6214                         G_CALLBACK (gtk_widget_destroyed),
6215                         &window);
6216
6217       gtk_window_set_title (GTK_WINDOW (window), "notebook");
6218       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
6219
6220       box1 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
6221       gtk_container_add (GTK_CONTAINER (window), box1);
6222
6223       sample_notebook = gtk_notebook_new ();
6224       g_signal_connect (sample_notebook, "switch_page",
6225                         G_CALLBACK (page_switch), NULL);
6226       gtk_notebook_set_tab_pos (GTK_NOTEBOOK (sample_notebook), GTK_POS_TOP);
6227       gtk_box_pack_start (GTK_BOX (box1), sample_notebook, TRUE, TRUE, 0);
6228       gtk_container_set_border_width (GTK_CONTAINER (sample_notebook), 10);
6229
6230       gtk_widget_realize (sample_notebook);
6231
6232       if (!book_open)
6233         book_open = gdk_pixbuf_new_from_xpm_data (book_open_xpm);
6234                                                   
6235       if (!book_closed)
6236         book_closed = gdk_pixbuf_new_from_xpm_data (book_closed_xpm);
6237
6238       create_pages (GTK_NOTEBOOK (sample_notebook), 1, 5);
6239
6240       separator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
6241       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 10);
6242       
6243       box2 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
6244       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
6245       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
6246
6247       button = gtk_check_button_new_with_label ("popup menu");
6248       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, FALSE, 0);
6249       g_signal_connect (button, "clicked",
6250                         G_CALLBACK (notebook_popup),
6251                         sample_notebook);
6252
6253       box2 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
6254       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
6255       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
6256
6257       label = gtk_label_new ("Notebook Style :");
6258       gtk_box_pack_start (GTK_BOX (box2), label, FALSE, TRUE, 0);
6259
6260       omenu = build_option_menu (items, G_N_ELEMENTS (items), 0,
6261                                  notebook_type_changed,
6262                                  sample_notebook);
6263       gtk_box_pack_start (GTK_BOX (box2), omenu, FALSE, TRUE, 0);
6264
6265       button = gtk_button_new_with_label ("Show all Pages");
6266       gtk_box_pack_start (GTK_BOX (box2), button, FALSE, TRUE, 0);
6267       g_signal_connect (button, "clicked",
6268                         G_CALLBACK (show_all_pages), sample_notebook);
6269
6270       box2 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10);
6271       gtk_box_set_homogeneous (GTK_BOX (box2), TRUE);
6272       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
6273       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
6274
6275       button = gtk_button_new_with_label ("prev");
6276       g_signal_connect_swapped (button, "clicked",
6277                                 G_CALLBACK (gtk_notebook_prev_page),
6278                                 sample_notebook);
6279       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
6280
6281       button = gtk_button_new_with_label ("next");
6282       g_signal_connect_swapped (button, "clicked",
6283                                 G_CALLBACK (gtk_notebook_next_page),
6284                                 sample_notebook);
6285       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
6286
6287       button = gtk_button_new_with_label ("rotate");
6288       g_signal_connect (button, "clicked",
6289                         G_CALLBACK (rotate_notebook), sample_notebook);
6290       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
6291
6292       separator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
6293       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
6294
6295       button = gtk_button_new_with_label ("close");
6296       gtk_container_set_border_width (GTK_CONTAINER (button), 5);
6297       g_signal_connect_swapped (button, "clicked",
6298                                 G_CALLBACK (gtk_widget_destroy),
6299                                 window);
6300       gtk_box_pack_start (GTK_BOX (box1), button, FALSE, FALSE, 0);
6301       gtk_widget_set_can_default (button, TRUE);
6302       gtk_widget_grab_default (button);
6303     }
6304
6305   if (!gtk_widget_get_visible (window))
6306     gtk_widget_show_all (window);
6307   else
6308     gtk_widget_destroy (window);
6309 }
6310
6311 /*
6312  * GtkPanes
6313  */
6314
6315 void
6316 toggle_resize (GtkWidget *widget, GtkWidget *child)
6317 {
6318   GtkContainer *container = GTK_CONTAINER (gtk_widget_get_parent (child));
6319   GValue value = { 0, };
6320   g_value_init (&value, G_TYPE_BOOLEAN);
6321   gtk_container_child_get_property (container, child, "resize", &value);
6322   g_value_set_boolean (&value, !g_value_get_boolean (&value));
6323   gtk_container_child_set_property (container, child, "resize", &value);
6324 }
6325
6326 void
6327 toggle_shrink (GtkWidget *widget, GtkWidget *child)
6328 {
6329   GtkContainer *container = GTK_CONTAINER (gtk_widget_get_parent (child));
6330   GValue value = { 0, };
6331   g_value_init (&value, G_TYPE_BOOLEAN);
6332   gtk_container_child_get_property (container, child, "shrink", &value);
6333   g_value_set_boolean (&value, !g_value_get_boolean (&value));
6334   gtk_container_child_set_property (container, child, "shrink", &value);
6335 }
6336
6337 static void
6338 paned_props_clicked (GtkWidget *button,
6339                      GObject   *paned)
6340 {
6341   GtkWidget *window = create_prop_editor (paned, GTK_TYPE_PANED);
6342   
6343   gtk_window_set_title (GTK_WINDOW (window), "Paned Properties");
6344 }
6345
6346 GtkWidget *
6347 create_pane_options (GtkPaned    *paned,
6348                      const gchar *frame_label,
6349                      const gchar *label1,
6350                      const gchar *label2)
6351 {
6352   GtkWidget *child1, *child2;
6353   GtkWidget *frame;
6354   GtkWidget *table;
6355   GtkWidget *label;
6356   GtkWidget *button;
6357   GtkWidget *check_button;
6358
6359   child1 = gtk_paned_get_child1 (paned);
6360   child2 = gtk_paned_get_child2 (paned);
6361
6362   frame = gtk_frame_new (frame_label);
6363   gtk_container_set_border_width (GTK_CONTAINER (frame), 4);
6364   
6365   table = gtk_table_new (4, 2, 4);
6366   gtk_container_add (GTK_CONTAINER (frame), table);
6367   
6368   label = gtk_label_new (label1);
6369   gtk_table_attach_defaults (GTK_TABLE (table), label,
6370                              0, 1, 0, 1);
6371   
6372   check_button = gtk_check_button_new_with_label ("Resize");
6373   gtk_table_attach_defaults (GTK_TABLE (table), check_button,
6374                              0, 1, 1, 2);
6375   g_signal_connect (check_button, "toggled",
6376                     G_CALLBACK (toggle_resize),
6377                     child1);
6378
6379   check_button = gtk_check_button_new_with_label ("Shrink");
6380   gtk_table_attach_defaults (GTK_TABLE (table), check_button,
6381                              0, 1, 2, 3);
6382   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button),
6383                                TRUE);
6384   g_signal_connect (check_button, "toggled",
6385                     G_CALLBACK (toggle_shrink),
6386                     child1);
6387
6388   label = gtk_label_new (label2);
6389   gtk_table_attach_defaults (GTK_TABLE (table), label,
6390                              1, 2, 0, 1);
6391   
6392   check_button = gtk_check_button_new_with_label ("Resize");
6393   gtk_table_attach_defaults (GTK_TABLE (table), check_button,
6394                              1, 2, 1, 2);
6395   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button),
6396                                TRUE);
6397   g_signal_connect (check_button, "toggled",
6398                     G_CALLBACK (toggle_resize),
6399                     child2);
6400
6401   check_button = gtk_check_button_new_with_label ("Shrink");
6402   gtk_table_attach_defaults (GTK_TABLE (table), check_button,
6403                              1, 2, 2, 3);
6404   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button),
6405                                TRUE);
6406   g_signal_connect (check_button, "toggled",
6407                     G_CALLBACK (toggle_shrink),
6408                     child2);
6409
6410   button = gtk_button_new_with_mnemonic ("_Properties");
6411   gtk_table_attach_defaults (GTK_TABLE (table), button,
6412                              0, 2, 3, 4);
6413   g_signal_connect (button, "clicked",
6414                     G_CALLBACK (paned_props_clicked),
6415                     paned);
6416
6417   return frame;
6418 }
6419
6420 void
6421 create_panes (GtkWidget *widget)
6422 {
6423   static GtkWidget *window = NULL;
6424   GtkWidget *frame;
6425   GtkWidget *hpaned;
6426   GtkWidget *vpaned;
6427   GtkWidget *button;
6428   GtkWidget *vbox;
6429
6430   if (!window)
6431     {
6432       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6433
6434       gtk_window_set_screen (GTK_WINDOW (window),
6435                              gtk_widget_get_screen (widget));
6436       
6437       g_signal_connect (window, "destroy",
6438                         G_CALLBACK (gtk_widget_destroyed),
6439                         &window);
6440
6441       gtk_window_set_title (GTK_WINDOW (window), "Panes");
6442       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
6443
6444       vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
6445       gtk_container_add (GTK_CONTAINER (window), vbox);
6446       
6447       vpaned = gtk_paned_new (GTK_ORIENTATION_VERTICAL);
6448       gtk_box_pack_start (GTK_BOX (vbox), vpaned, TRUE, TRUE, 0);
6449       gtk_container_set_border_width (GTK_CONTAINER(vpaned), 5);
6450
6451       hpaned = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL);
6452       gtk_paned_add1 (GTK_PANED (vpaned), hpaned);
6453
6454       frame = gtk_frame_new (NULL);
6455       gtk_frame_set_shadow_type (GTK_FRAME(frame), GTK_SHADOW_IN);
6456       gtk_widget_set_size_request (frame, 60, 60);
6457       gtk_paned_add1 (GTK_PANED (hpaned), frame);
6458       
6459       button = gtk_button_new_with_label ("Hi there");
6460       gtk_container_add (GTK_CONTAINER(frame), button);
6461
6462       frame = gtk_frame_new (NULL);
6463       gtk_frame_set_shadow_type (GTK_FRAME(frame), GTK_SHADOW_IN);
6464       gtk_widget_set_size_request (frame, 80, 60);
6465       gtk_paned_add2 (GTK_PANED (hpaned), frame);
6466
6467       frame = gtk_frame_new (NULL);
6468       gtk_frame_set_shadow_type (GTK_FRAME(frame), GTK_SHADOW_IN);
6469       gtk_widget_set_size_request (frame, 60, 80);
6470       gtk_paned_add2 (GTK_PANED (vpaned), frame);
6471
6472       /* Now create toggle buttons to control sizing */
6473
6474       gtk_box_pack_start (GTK_BOX (vbox),
6475                           create_pane_options (GTK_PANED (hpaned),
6476                                                "Horizontal",
6477                                                "Left",
6478                                                "Right"),
6479                           FALSE, FALSE, 0);
6480
6481       gtk_box_pack_start (GTK_BOX (vbox),
6482                           create_pane_options (GTK_PANED (vpaned),
6483                                                "Vertical",
6484                                                "Top",
6485                                                "Bottom"),
6486                           FALSE, FALSE, 0);
6487
6488       gtk_widget_show_all (vbox);
6489     }
6490
6491   if (!gtk_widget_get_visible (window))
6492     gtk_widget_show (window);
6493   else
6494     gtk_widget_destroy (window);
6495 }
6496
6497 /*
6498  * Paned keyboard navigation
6499  */
6500
6501 static GtkWidget*
6502 paned_keyboard_window1 (GtkWidget *widget)
6503 {
6504   GtkWidget *window1;
6505   GtkWidget *hpaned1;
6506   GtkWidget *frame1;
6507   GtkWidget *vbox1;
6508   GtkWidget *button7;
6509   GtkWidget *button8;
6510   GtkWidget *button9;
6511   GtkWidget *vpaned1;
6512   GtkWidget *frame2;
6513   GtkWidget *frame5;
6514   GtkWidget *hbox1;
6515   GtkWidget *button5;
6516   GtkWidget *button6;
6517   GtkWidget *frame3;
6518   GtkWidget *frame4;
6519   GtkWidget *table1;
6520   GtkWidget *button1;
6521   GtkWidget *button2;
6522   GtkWidget *button3;
6523   GtkWidget *button4;
6524
6525   window1 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6526   gtk_window_set_title (GTK_WINDOW (window1), "Basic paned navigation");
6527   gtk_window_set_screen (GTK_WINDOW (window1), 
6528                          gtk_widget_get_screen (widget));
6529
6530   hpaned1 = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL);
6531   gtk_container_add (GTK_CONTAINER (window1), hpaned1);
6532
6533   frame1 = gtk_frame_new (NULL);
6534   gtk_paned_pack1 (GTK_PANED (hpaned1), frame1, FALSE, TRUE);
6535   gtk_frame_set_shadow_type (GTK_FRAME (frame1), GTK_SHADOW_IN);
6536
6537   vbox1 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
6538   gtk_container_add (GTK_CONTAINER (frame1), vbox1);
6539
6540   button7 = gtk_button_new_with_label ("button7");
6541   gtk_box_pack_start (GTK_BOX (vbox1), button7, FALSE, FALSE, 0);
6542
6543   button8 = gtk_button_new_with_label ("button8");
6544   gtk_box_pack_start (GTK_BOX (vbox1), button8, FALSE, FALSE, 0);
6545
6546   button9 = gtk_button_new_with_label ("button9");
6547   gtk_box_pack_start (GTK_BOX (vbox1), button9, FALSE, FALSE, 0);
6548
6549   vpaned1 = gtk_paned_new (GTK_ORIENTATION_VERTICAL);
6550   gtk_paned_pack2 (GTK_PANED (hpaned1), vpaned1, TRUE, TRUE);
6551
6552   frame2 = gtk_frame_new (NULL);
6553   gtk_paned_pack1 (GTK_PANED (vpaned1), frame2, FALSE, TRUE);
6554   gtk_frame_set_shadow_type (GTK_FRAME (frame2), GTK_SHADOW_IN);
6555
6556   frame5 = gtk_frame_new (NULL);
6557   gtk_container_add (GTK_CONTAINER (frame2), frame5);
6558
6559   hbox1 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
6560   gtk_container_add (GTK_CONTAINER (frame5), hbox1);
6561
6562   button5 = gtk_button_new_with_label ("button5");
6563   gtk_box_pack_start (GTK_BOX (hbox1), button5, FALSE, FALSE, 0);
6564
6565   button6 = gtk_button_new_with_label ("button6");
6566   gtk_box_pack_start (GTK_BOX (hbox1), button6, FALSE, FALSE, 0);
6567
6568   frame3 = gtk_frame_new (NULL);
6569   gtk_paned_pack2 (GTK_PANED (vpaned1), frame3, TRUE, TRUE);
6570   gtk_frame_set_shadow_type (GTK_FRAME (frame3), GTK_SHADOW_IN);
6571
6572   frame4 = gtk_frame_new ("Buttons");
6573   gtk_container_add (GTK_CONTAINER (frame3), frame4);
6574   gtk_container_set_border_width (GTK_CONTAINER (frame4), 15);
6575
6576   table1 = gtk_table_new (2, 2, FALSE);
6577   gtk_container_add (GTK_CONTAINER (frame4), table1);
6578   gtk_container_set_border_width (GTK_CONTAINER (table1), 11);
6579
6580   button1 = gtk_button_new_with_label ("button1");
6581   gtk_table_attach (GTK_TABLE (table1), button1, 0, 1, 0, 1,
6582                     (GtkAttachOptions) (GTK_FILL),
6583                     (GtkAttachOptions) (0), 0, 0);
6584
6585   button2 = gtk_button_new_with_label ("button2");
6586   gtk_table_attach (GTK_TABLE (table1), button2, 1, 2, 0, 1,
6587                     (GtkAttachOptions) (GTK_FILL),
6588                     (GtkAttachOptions) (0), 0, 0);
6589
6590   button3 = gtk_button_new_with_label ("button3");
6591   gtk_table_attach (GTK_TABLE (table1), button3, 0, 1, 1, 2,
6592                     (GtkAttachOptions) (GTK_FILL),
6593                     (GtkAttachOptions) (0), 0, 0);
6594
6595   button4 = gtk_button_new_with_label ("button4");
6596   gtk_table_attach (GTK_TABLE (table1), button4, 1, 2, 1, 2,
6597                     (GtkAttachOptions) (GTK_FILL),
6598                     (GtkAttachOptions) (0), 0, 0);
6599
6600   return window1;
6601 }
6602
6603 static GtkWidget*
6604 paned_keyboard_window2 (GtkWidget *widget)
6605 {
6606   GtkWidget *window2;
6607   GtkWidget *hpaned2;
6608   GtkWidget *frame6;
6609   GtkWidget *button13;
6610   GtkWidget *hbox2;
6611   GtkWidget *vpaned2;
6612   GtkWidget *frame7;
6613   GtkWidget *button12;
6614   GtkWidget *frame8;
6615   GtkWidget *button11;
6616   GtkWidget *button10;
6617
6618   window2 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6619   gtk_window_set_title (GTK_WINDOW (window2), "\"button 10\" is not inside the horisontal pane");
6620
6621   gtk_window_set_screen (GTK_WINDOW (window2), 
6622                          gtk_widget_get_screen (widget));
6623
6624   hpaned2 = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL);
6625   gtk_container_add (GTK_CONTAINER (window2), hpaned2);
6626
6627   frame6 = gtk_frame_new (NULL);
6628   gtk_paned_pack1 (GTK_PANED (hpaned2), frame6, FALSE, TRUE);
6629   gtk_frame_set_shadow_type (GTK_FRAME (frame6), GTK_SHADOW_IN);
6630
6631   button13 = gtk_button_new_with_label ("button13");
6632   gtk_container_add (GTK_CONTAINER (frame6), button13);
6633
6634   hbox2 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
6635   gtk_paned_pack2 (GTK_PANED (hpaned2), hbox2, TRUE, TRUE);
6636
6637   vpaned2 = gtk_paned_new (GTK_ORIENTATION_VERTICAL);
6638   gtk_box_pack_start (GTK_BOX (hbox2), vpaned2, TRUE, TRUE, 0);
6639
6640   frame7 = gtk_frame_new (NULL);
6641   gtk_paned_pack1 (GTK_PANED (vpaned2), frame7, FALSE, TRUE);
6642   gtk_frame_set_shadow_type (GTK_FRAME (frame7), GTK_SHADOW_IN);
6643
6644   button12 = gtk_button_new_with_label ("button12");
6645   gtk_container_add (GTK_CONTAINER (frame7), button12);
6646
6647   frame8 = gtk_frame_new (NULL);
6648   gtk_paned_pack2 (GTK_PANED (vpaned2), frame8, TRUE, TRUE);
6649   gtk_frame_set_shadow_type (GTK_FRAME (frame8), GTK_SHADOW_IN);
6650
6651   button11 = gtk_button_new_with_label ("button11");
6652   gtk_container_add (GTK_CONTAINER (frame8), button11);
6653
6654   button10 = gtk_button_new_with_label ("button10");
6655   gtk_box_pack_start (GTK_BOX (hbox2), button10, FALSE, FALSE, 0);
6656
6657   return window2;
6658 }
6659
6660 static GtkWidget*
6661 paned_keyboard_window3 (GtkWidget *widget)
6662 {
6663   GtkWidget *window3;
6664   GtkWidget *vbox2;
6665   GtkWidget *label1;
6666   GtkWidget *hpaned3;
6667   GtkWidget *frame9;
6668   GtkWidget *button14;
6669   GtkWidget *hpaned4;
6670   GtkWidget *frame10;
6671   GtkWidget *button15;
6672   GtkWidget *hpaned5;
6673   GtkWidget *frame11;
6674   GtkWidget *button16;
6675   GtkWidget *frame12;
6676   GtkWidget *button17;
6677
6678   window3 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6679   g_object_set_data (G_OBJECT (window3), "window3", window3);
6680   gtk_window_set_title (GTK_WINDOW (window3), "Nested panes");
6681
6682   gtk_window_set_screen (GTK_WINDOW (window3), 
6683                          gtk_widget_get_screen (widget));
6684   
6685
6686   vbox2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
6687   gtk_container_add (GTK_CONTAINER (window3), vbox2);
6688
6689   label1 = gtk_label_new ("Three panes nested inside each other");
6690   gtk_box_pack_start (GTK_BOX (vbox2), label1, FALSE, FALSE, 0);
6691
6692   hpaned3 = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL);
6693   gtk_box_pack_start (GTK_BOX (vbox2), hpaned3, TRUE, TRUE, 0);
6694
6695   frame9 = gtk_frame_new (NULL);
6696   gtk_paned_pack1 (GTK_PANED (hpaned3), frame9, FALSE, TRUE);
6697   gtk_frame_set_shadow_type (GTK_FRAME (frame9), GTK_SHADOW_IN);
6698
6699   button14 = gtk_button_new_with_label ("button14");
6700   gtk_container_add (GTK_CONTAINER (frame9), button14);
6701
6702   hpaned4 = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL);
6703   gtk_paned_pack2 (GTK_PANED (hpaned3), hpaned4, TRUE, TRUE);
6704
6705   frame10 = gtk_frame_new (NULL);
6706   gtk_paned_pack1 (GTK_PANED (hpaned4), frame10, FALSE, TRUE);
6707   gtk_frame_set_shadow_type (GTK_FRAME (frame10), GTK_SHADOW_IN);
6708
6709   button15 = gtk_button_new_with_label ("button15");
6710   gtk_container_add (GTK_CONTAINER (frame10), button15);
6711
6712   hpaned5 = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL);
6713   gtk_paned_pack2 (GTK_PANED (hpaned4), hpaned5, TRUE, TRUE);
6714
6715   frame11 = gtk_frame_new (NULL);
6716   gtk_paned_pack1 (GTK_PANED (hpaned5), frame11, FALSE, TRUE);
6717   gtk_frame_set_shadow_type (GTK_FRAME (frame11), GTK_SHADOW_IN);
6718
6719   button16 = gtk_button_new_with_label ("button16");
6720   gtk_container_add (GTK_CONTAINER (frame11), button16);
6721
6722   frame12 = gtk_frame_new (NULL);
6723   gtk_paned_pack2 (GTK_PANED (hpaned5), frame12, TRUE, TRUE);
6724   gtk_frame_set_shadow_type (GTK_FRAME (frame12), GTK_SHADOW_IN);
6725
6726   button17 = gtk_button_new_with_label ("button17");
6727   gtk_container_add (GTK_CONTAINER (frame12), button17);
6728
6729   return window3;
6730 }
6731
6732 static GtkWidget*
6733 paned_keyboard_window4 (GtkWidget *widget)
6734 {
6735   GtkWidget *window4;
6736   GtkWidget *vbox3;
6737   GtkWidget *label2;
6738   GtkWidget *hpaned6;
6739   GtkWidget *vpaned3;
6740   GtkWidget *button19;
6741   GtkWidget *button18;
6742   GtkWidget *hbox3;
6743   GtkWidget *vpaned4;
6744   GtkWidget *button21;
6745   GtkWidget *button20;
6746   GtkWidget *vpaned5;
6747   GtkWidget *button23;
6748   GtkWidget *button22;
6749   GtkWidget *vpaned6;
6750   GtkWidget *button25;
6751   GtkWidget *button24;
6752
6753   window4 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6754   g_object_set_data (G_OBJECT (window4), "window4", window4);
6755   gtk_window_set_title (GTK_WINDOW (window4), "window4");
6756
6757   gtk_window_set_screen (GTK_WINDOW (window4), 
6758                          gtk_widget_get_screen (widget));
6759
6760   vbox3 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
6761   gtk_container_add (GTK_CONTAINER (window4), vbox3);
6762
6763   label2 = gtk_label_new ("Widget tree:\n\nhpaned \n - vpaned\n - hbox\n    - vpaned\n    - vpaned\n    - vpaned\n");
6764   gtk_box_pack_start (GTK_BOX (vbox3), label2, FALSE, FALSE, 0);
6765   gtk_label_set_justify (GTK_LABEL (label2), GTK_JUSTIFY_LEFT);
6766
6767   hpaned6 = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL);
6768   gtk_box_pack_start (GTK_BOX (vbox3), hpaned6, TRUE, TRUE, 0);
6769
6770   vpaned3 = gtk_paned_new (GTK_ORIENTATION_VERTICAL);
6771   gtk_paned_pack1 (GTK_PANED (hpaned6), vpaned3, FALSE, TRUE);
6772
6773   button19 = gtk_button_new_with_label ("button19");
6774   gtk_paned_pack1 (GTK_PANED (vpaned3), button19, FALSE, TRUE);
6775
6776   button18 = gtk_button_new_with_label ("button18");
6777   gtk_paned_pack2 (GTK_PANED (vpaned3), button18, TRUE, TRUE);
6778
6779   hbox3 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
6780   gtk_paned_pack2 (GTK_PANED (hpaned6), hbox3, TRUE, TRUE);
6781
6782   vpaned4 = gtk_paned_new (GTK_ORIENTATION_VERTICAL);
6783   gtk_box_pack_start (GTK_BOX (hbox3), vpaned4, TRUE, TRUE, 0);
6784
6785   button21 = gtk_button_new_with_label ("button21");
6786   gtk_paned_pack1 (GTK_PANED (vpaned4), button21, FALSE, TRUE);
6787
6788   button20 = gtk_button_new_with_label ("button20");
6789   gtk_paned_pack2 (GTK_PANED (vpaned4), button20, TRUE, TRUE);
6790
6791   vpaned5 = gtk_paned_new (GTK_ORIENTATION_VERTICAL);
6792   gtk_box_pack_start (GTK_BOX (hbox3), vpaned5, TRUE, TRUE, 0);
6793
6794   button23 = gtk_button_new_with_label ("button23");
6795   gtk_paned_pack1 (GTK_PANED (vpaned5), button23, FALSE, TRUE);
6796
6797   button22 = gtk_button_new_with_label ("button22");
6798   gtk_paned_pack2 (GTK_PANED (vpaned5), button22, TRUE, TRUE);
6799
6800   vpaned6 = gtk_paned_new (GTK_ORIENTATION_VERTICAL);
6801   gtk_box_pack_start (GTK_BOX (hbox3), vpaned6, TRUE, TRUE, 0);
6802
6803   button25 = gtk_button_new_with_label ("button25");
6804   gtk_paned_pack1 (GTK_PANED (vpaned6), button25, FALSE, TRUE);
6805
6806   button24 = gtk_button_new_with_label ("button24");
6807   gtk_paned_pack2 (GTK_PANED (vpaned6), button24, TRUE, TRUE);
6808
6809   return window4;
6810 }
6811
6812 static void
6813 create_paned_keyboard_navigation (GtkWidget *widget)
6814 {
6815   static GtkWidget *window1 = NULL;
6816   static GtkWidget *window2 = NULL;
6817   static GtkWidget *window3 = NULL;
6818   static GtkWidget *window4 = NULL;
6819
6820   if (window1 && 
6821      (gtk_widget_get_screen (window1) != gtk_widget_get_screen (widget)))
6822     {
6823       gtk_widget_destroy (window1);
6824       gtk_widget_destroy (window2);
6825       gtk_widget_destroy (window3);
6826       gtk_widget_destroy (window4);
6827     }
6828   
6829   if (!window1)
6830     {
6831       window1 = paned_keyboard_window1 (widget);
6832       g_signal_connect (window1, "destroy",
6833                         G_CALLBACK (gtk_widget_destroyed),
6834                         &window1);
6835     }
6836
6837   if (!window2)
6838     {
6839       window2 = paned_keyboard_window2 (widget);
6840       g_signal_connect (window2, "destroy",
6841                         G_CALLBACK (gtk_widget_destroyed),
6842                         &window2);
6843     }
6844
6845   if (!window3)
6846     {
6847       window3 = paned_keyboard_window3 (widget);
6848       g_signal_connect (window3, "destroy",
6849                         G_CALLBACK (gtk_widget_destroyed),
6850                         &window3);
6851     }
6852
6853   if (!window4)
6854     {
6855       window4 = paned_keyboard_window4 (widget);
6856       g_signal_connect (window4, "destroy",
6857                         G_CALLBACK (gtk_widget_destroyed),
6858                         &window4);
6859     }
6860
6861   if (gtk_widget_get_visible (window1))
6862     gtk_widget_destroy (GTK_WIDGET (window1));
6863   else
6864     gtk_widget_show_all (GTK_WIDGET (window1));
6865
6866   if (gtk_widget_get_visible (window2))
6867     gtk_widget_destroy (GTK_WIDGET (window2));
6868   else
6869     gtk_widget_show_all (GTK_WIDGET (window2));
6870
6871   if (gtk_widget_get_visible (window3))
6872     gtk_widget_destroy (GTK_WIDGET (window3));
6873   else
6874     gtk_widget_show_all (GTK_WIDGET (window3));
6875
6876   if (gtk_widget_get_visible (window4))
6877     gtk_widget_destroy (GTK_WIDGET (window4));
6878   else
6879     gtk_widget_show_all (GTK_WIDGET (window4));
6880 }
6881
6882
6883 /*
6884  * Shaped Windows
6885  */
6886
6887 typedef struct _cursoroffset {gint x,y;} CursorOffset;
6888
6889 static void
6890 shape_pressed (GtkWidget *widget, GdkEventButton *event)
6891 {
6892   CursorOffset *p;
6893
6894   /* ignore double and triple click */
6895   if (event->type != GDK_BUTTON_PRESS)
6896     return;
6897
6898   p = g_object_get_data (G_OBJECT (widget), "cursor_offset");
6899   p->x = (int) event->x;
6900   p->y = (int) event->y;
6901
6902   gtk_grab_add (widget);
6903   gdk_pointer_grab (gtk_widget_get_window (widget), TRUE,
6904                     GDK_BUTTON_RELEASE_MASK |
6905                     GDK_BUTTON_MOTION_MASK |
6906                     GDK_POINTER_MOTION_HINT_MASK,
6907                     NULL, NULL, 0);
6908 }
6909
6910 static void
6911 shape_released (GtkWidget *widget)
6912 {
6913   gtk_grab_remove (widget);
6914   gdk_display_pointer_ungrab (gtk_widget_get_display (widget),
6915                               GDK_CURRENT_TIME);
6916 }
6917
6918 static void
6919 shape_motion (GtkWidget      *widget, 
6920               GdkEventMotion *event)
6921 {
6922   gint xp, yp;
6923   CursorOffset * p;
6924   GdkModifierType mask;
6925
6926   p = g_object_get_data (G_OBJECT (widget), "cursor_offset");
6927
6928   /*
6929    * Can't use event->x / event->y here 
6930    * because I need absolute coordinates.
6931    */
6932   gdk_window_get_pointer (NULL, &xp, &yp, &mask);
6933   gtk_window_move (GTK_WINDOW (widget), xp  - p->x, yp  - p->y);
6934 }
6935
6936 GtkWidget *
6937 shape_create_icon (GdkScreen *screen,
6938                    char      *xpm_file,
6939                    gint       x,
6940                    gint       y,
6941                    gint       px,
6942                    gint       py,
6943                    gint       window_type)
6944 {
6945   GtkWidget *window;
6946   GtkWidget *image;
6947   GtkWidget *fixed;
6948   CursorOffset* icon_pos;
6949   cairo_surface_t *mask;
6950   cairo_region_t *mask_region;
6951   GdkPixbuf *pixbuf;
6952   cairo_t *cr;
6953
6954   /*
6955    * GDK_WINDOW_TOPLEVEL works also, giving you a title border
6956    */
6957   window = gtk_window_new (window_type);
6958   gtk_window_set_screen (GTK_WINDOW (window), screen);
6959   
6960   fixed = gtk_fixed_new ();
6961   gtk_widget_set_size_request (fixed, 100, 100);
6962   gtk_container_add (GTK_CONTAINER (window), fixed);
6963   gtk_widget_show (fixed);
6964   
6965   gtk_widget_set_events (window, 
6966                          gtk_widget_get_events (window) |
6967                          GDK_BUTTON_MOTION_MASK |
6968                          GDK_POINTER_MOTION_HINT_MASK |
6969                          GDK_BUTTON_PRESS_MASK);
6970
6971   gtk_widget_realize (window);
6972
6973   pixbuf = gdk_pixbuf_new_from_file (xpm_file, NULL);
6974   g_assert (pixbuf); /* FIXME: error handling */
6975
6976   mask = cairo_image_surface_create (CAIRO_FORMAT_A1,
6977                                      gdk_pixbuf_get_width (pixbuf),
6978                                      gdk_pixbuf_get_height (pixbuf));
6979   cr = cairo_create (mask);
6980   gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0);
6981   cairo_paint (cr);
6982   cairo_destroy (cr);
6983
6984   mask_region = gdk_cairo_region_create_from_surface (mask);
6985                                                   
6986   cairo_region_translate (mask_region, px, py);
6987
6988   image = gtk_image_new_from_pixbuf (pixbuf);
6989   gtk_fixed_put (GTK_FIXED (fixed), image, px,py);
6990   gtk_widget_show (image);
6991   
6992   gtk_widget_shape_combine_region (window, mask_region);
6993   
6994   cairo_region_destroy (mask_region);
6995   cairo_surface_destroy (mask);
6996   g_object_unref (pixbuf);
6997
6998   g_signal_connect (window, "button_press_event",
6999                     G_CALLBACK (shape_pressed), NULL);
7000   g_signal_connect (window, "button_release_event",
7001                     G_CALLBACK (shape_released), NULL);
7002   g_signal_connect (window, "motion_notify_event",
7003                     G_CALLBACK (shape_motion), NULL);
7004
7005   icon_pos = g_new (CursorOffset, 1);
7006   g_object_set_data (G_OBJECT (window), "cursor_offset", icon_pos);
7007
7008   gtk_window_move (GTK_WINDOW (window), x, y);
7009   gtk_widget_show (window);
7010   
7011   return window;
7012 }
7013
7014 void 
7015 create_shapes (GtkWidget *widget)
7016 {
7017   /* Variables used by the Drag/Drop and Shape Window demos */
7018   static GtkWidget *modeller = NULL;
7019   static GtkWidget *sheets = NULL;
7020   static GtkWidget *rings = NULL;
7021   static GtkWidget *with_region = NULL;
7022   GdkScreen *screen = gtk_widget_get_screen (widget);
7023   
7024   if (!(file_exists ("Modeller.xpm") &&
7025         file_exists ("FilesQueue.xpm") &&
7026         file_exists ("3DRings.xpm")))
7027     return;
7028   
7029
7030   if (!modeller)
7031     {
7032       modeller = shape_create_icon (screen, "Modeller.xpm",
7033                                     440, 140, 0,0, GTK_WINDOW_POPUP);
7034
7035       g_signal_connect (modeller, "destroy",
7036                         G_CALLBACK (gtk_widget_destroyed),
7037                         &modeller);
7038     }
7039   else
7040     gtk_widget_destroy (modeller);
7041
7042   if (!sheets)
7043     {
7044       sheets = shape_create_icon (screen, "FilesQueue.xpm",
7045                                   580, 170, 0,0, GTK_WINDOW_POPUP);
7046
7047       g_signal_connect (sheets, "destroy",
7048                         G_CALLBACK (gtk_widget_destroyed),
7049                         &sheets);
7050
7051     }
7052   else
7053     gtk_widget_destroy (sheets);
7054
7055   if (!rings)
7056     {
7057       rings = shape_create_icon (screen, "3DRings.xpm",
7058                                  460, 270, 25,25, GTK_WINDOW_TOPLEVEL);
7059
7060       g_signal_connect (rings, "destroy",
7061                         G_CALLBACK (gtk_widget_destroyed),
7062                         &rings);
7063     }
7064   else
7065     gtk_widget_destroy (rings);
7066
7067   if (!with_region)
7068     {
7069       cairo_region_t *region;
7070       gint x, y;
7071       
7072       with_region = shape_create_icon (screen, "3DRings.xpm",
7073                                        460, 270, 25,25, GTK_WINDOW_TOPLEVEL);
7074
7075       gtk_window_set_decorated (GTK_WINDOW (with_region), FALSE);
7076       
7077       g_signal_connect (with_region, "destroy",
7078                         G_CALLBACK (gtk_widget_destroyed),
7079                         &with_region);
7080
7081       /* reset shape from mask to a region */
7082       x = 0;
7083       y = 0;
7084       region = cairo_region_create ();
7085
7086       while (x < 460)
7087         {
7088           while (y < 270)
7089             {
7090               GdkRectangle rect;
7091               rect.x = x;
7092               rect.y = y;
7093               rect.width = 10;
7094               rect.height = 10;
7095
7096               cairo_region_union_rectangle (region, &rect);
7097               
7098               y += 20;
7099             }
7100           y = 0;
7101           x += 20;
7102         }
7103
7104       gdk_window_shape_combine_region (gtk_widget_get_window (with_region),
7105                                        region,
7106                                        0, 0);
7107     }
7108   else
7109     gtk_widget_destroy (with_region);
7110 }
7111
7112 /*
7113  * WM Hints demo
7114  */
7115
7116 void
7117 create_wmhints (GtkWidget *widget)
7118 {
7119   static GtkWidget *window = NULL;
7120   GtkWidget *label;
7121   GtkWidget *separator;
7122   GtkWidget *button;
7123   GtkWidget *box1;
7124   GtkWidget *box2;
7125   GdkWindow *gdk_window;
7126   GdkPixbuf *pixbuf;
7127   GList *list;
7128
7129   if (!window)
7130     {
7131       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7132
7133       gtk_window_set_screen (GTK_WINDOW (window),
7134                              gtk_widget_get_screen (widget));
7135       
7136       g_signal_connect (window, "destroy",
7137                         G_CALLBACK (gtk_widget_destroyed),
7138                         &window);
7139
7140       gtk_window_set_title (GTK_WINDOW (window), "WM Hints");
7141       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
7142
7143       gtk_widget_realize (window);
7144
7145       gdk_window = gtk_widget_get_window (window);
7146
7147       pixbuf = gdk_pixbuf_new_from_xpm_data ((const char **) openfile);
7148       list = g_list_prepend (NULL, pixbuf);
7149
7150       gdk_window_set_icon_list (gdk_window, list);
7151       
7152       g_list_free (list);
7153       g_object_unref (pixbuf);
7154
7155       gdk_window_set_icon_name (gdk_window, "WMHints Test Icon");
7156   
7157       gdk_window_set_decorations (gdk_window, GDK_DECOR_ALL | GDK_DECOR_MENU);
7158       gdk_window_set_functions (gdk_window, GDK_FUNC_ALL | GDK_FUNC_RESIZE);
7159       
7160       box1 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
7161       gtk_container_add (GTK_CONTAINER (window), box1);
7162       gtk_widget_show (box1);
7163
7164       label = gtk_label_new ("Try iconizing me!");
7165       gtk_widget_set_size_request (label, 150, 50);
7166       gtk_box_pack_start (GTK_BOX (box1), label, TRUE, TRUE, 0);
7167       gtk_widget_show (label);
7168
7169
7170       separator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
7171       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
7172       gtk_widget_show (separator);
7173
7174
7175       box2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 10);
7176       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
7177       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
7178       gtk_widget_show (box2);
7179
7180
7181       button = gtk_button_new_with_label ("close");
7182
7183       g_signal_connect_swapped (button, "clicked",
7184                                 G_CALLBACK (gtk_widget_destroy),
7185                                 window);
7186
7187       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
7188       gtk_widget_set_can_default (button, TRUE);
7189       gtk_widget_grab_default (button);
7190       gtk_widget_show (button);
7191     }
7192
7193   if (!gtk_widget_get_visible (window))
7194     gtk_widget_show (window);
7195   else
7196     gtk_widget_destroy (window);
7197 }
7198
7199
7200 /*
7201  * Window state tracking
7202  */
7203
7204 static gint
7205 window_state_callback (GtkWidget *widget,
7206                        GdkEventWindowState *event,
7207                        gpointer data)
7208 {
7209   GtkWidget *label = data;
7210   gchar *msg;
7211
7212   msg = g_strconcat (gtk_window_get_title (GTK_WINDOW (widget)), ": ",
7213                      (event->new_window_state & GDK_WINDOW_STATE_WITHDRAWN) ?
7214                      "withdrawn" : "not withdrawn", ", ",
7215                      (event->new_window_state & GDK_WINDOW_STATE_ICONIFIED) ?
7216                      "iconified" : "not iconified", ", ",
7217                      (event->new_window_state & GDK_WINDOW_STATE_STICKY) ?
7218                      "sticky" : "not sticky", ", ",
7219                      (event->new_window_state & GDK_WINDOW_STATE_MAXIMIZED) ?
7220                      "maximized" : "not maximized", ", ",
7221                      (event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN) ?
7222                      "fullscreen" : "not fullscreen",
7223                      (event->new_window_state & GDK_WINDOW_STATE_ABOVE) ?
7224                      "above" : "not above", ", ",
7225                      (event->new_window_state & GDK_WINDOW_STATE_BELOW) ?
7226                      "below" : "not below", ", ",
7227                      NULL);
7228   
7229   gtk_label_set_text (GTK_LABEL (label), msg);
7230
7231   g_free (msg);
7232
7233   return FALSE;
7234 }
7235
7236 static GtkWidget*
7237 tracking_label (GtkWidget *window)
7238 {
7239   GtkWidget *label;
7240   GtkWidget *hbox;
7241   GtkWidget *button;
7242
7243   hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
7244
7245   g_signal_connect_object (hbox,
7246                            "destroy",
7247                            G_CALLBACK (gtk_widget_destroy),
7248                            window,
7249                            G_CONNECT_SWAPPED);
7250   
7251   label = gtk_label_new ("<no window state events received>");
7252   gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
7253   gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
7254   
7255   g_signal_connect (window,
7256                     "window_state_event",
7257                     G_CALLBACK (window_state_callback),
7258                     label);
7259
7260   button = gtk_button_new_with_label ("Deiconify");
7261   g_signal_connect_object (button,
7262                            "clicked",
7263                            G_CALLBACK (gtk_window_deiconify),
7264                            window,
7265                            G_CONNECT_SWAPPED);
7266   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
7267
7268   button = gtk_button_new_with_label ("Iconify");
7269   g_signal_connect_object (button,
7270                            "clicked",
7271                            G_CALLBACK (gtk_window_iconify),
7272                            window,
7273                            G_CONNECT_SWAPPED);
7274   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
7275
7276   button = gtk_button_new_with_label ("Fullscreen");
7277   g_signal_connect_object (button,
7278                            "clicked",
7279                            G_CALLBACK (gtk_window_fullscreen),
7280                            window,
7281                            G_CONNECT_SWAPPED);
7282   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
7283
7284   button = gtk_button_new_with_label ("Unfullscreen");
7285   g_signal_connect_object (button,
7286                            "clicked",
7287                            G_CALLBACK (gtk_window_unfullscreen),
7288                            window,
7289                            G_CONNECT_SWAPPED);
7290   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
7291   
7292   button = gtk_button_new_with_label ("Present");
7293   g_signal_connect_object (button,
7294                            "clicked",
7295                            G_CALLBACK (gtk_window_present),
7296                            window,
7297                            G_CONNECT_SWAPPED);
7298   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
7299
7300   button = gtk_button_new_with_label ("Show");
7301   g_signal_connect_object (button,
7302                            "clicked",
7303                            G_CALLBACK (gtk_widget_show),
7304                            window,
7305                            G_CONNECT_SWAPPED);
7306   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
7307   
7308   gtk_widget_show_all (hbox);
7309   
7310   return hbox;
7311 }
7312
7313 void
7314 keep_window_above (GtkToggleButton *togglebutton, gpointer data)
7315 {
7316   GtkWidget *button = g_object_get_data (G_OBJECT (togglebutton), "radio");
7317
7318   gtk_window_set_keep_above (GTK_WINDOW (data),
7319                              gtk_toggle_button_get_active (togglebutton));
7320
7321   if (gtk_toggle_button_get_active (togglebutton))
7322     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE);
7323 }
7324
7325 void
7326 keep_window_below (GtkToggleButton *togglebutton, gpointer data)
7327 {
7328   GtkWidget *button = g_object_get_data (G_OBJECT (togglebutton), "radio");
7329
7330   gtk_window_set_keep_below (GTK_WINDOW (data),
7331                              gtk_toggle_button_get_active (togglebutton));
7332
7333   if (gtk_toggle_button_get_active (togglebutton))
7334     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE);
7335 }
7336
7337
7338 static GtkWidget*
7339 get_state_controls (GtkWidget *window)
7340 {
7341   GtkWidget *vbox;
7342   GtkWidget *button;
7343   GtkWidget *button_above;
7344   GtkWidget *button_below;
7345
7346   vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
7347   
7348   button = gtk_button_new_with_label ("Stick");
7349   g_signal_connect_object (button,
7350                            "clicked",
7351                            G_CALLBACK (gtk_window_stick),
7352                            window,
7353                            G_CONNECT_SWAPPED);
7354   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7355
7356   button = gtk_button_new_with_label ("Unstick");
7357   g_signal_connect_object (button,
7358                            "clicked",
7359                            G_CALLBACK (gtk_window_unstick),
7360                            window,
7361                            G_CONNECT_SWAPPED);
7362   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7363   
7364   button = gtk_button_new_with_label ("Maximize");
7365   g_signal_connect_object (button,
7366                            "clicked",
7367                            G_CALLBACK (gtk_window_maximize),
7368                            window,
7369                            G_CONNECT_SWAPPED);
7370   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7371
7372   button = gtk_button_new_with_label ("Unmaximize");
7373   g_signal_connect_object (button,
7374                            "clicked",
7375                            G_CALLBACK (gtk_window_unmaximize),
7376                            window,
7377                            G_CONNECT_SWAPPED);
7378   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7379
7380   button = gtk_button_new_with_label ("Iconify");
7381   g_signal_connect_object (button,
7382                            "clicked",
7383                            G_CALLBACK (gtk_window_iconify),
7384                            window,
7385                            G_CONNECT_SWAPPED);
7386   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7387
7388   button = gtk_button_new_with_label ("Fullscreen");
7389   g_signal_connect_object (button,
7390                            "clicked",
7391                            G_CALLBACK (gtk_window_fullscreen),
7392                            window,
7393                            G_CONNECT_SWAPPED);
7394   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7395
7396   button = gtk_button_new_with_label ("Unfullscreen");
7397   g_signal_connect_object (button,
7398                            "clicked",
7399                            G_CALLBACK (gtk_window_unfullscreen),
7400                            window,
7401                            G_CONNECT_SWAPPED);
7402   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7403
7404   button_above = gtk_toggle_button_new_with_label ("Keep above");
7405   g_signal_connect (button_above,
7406                     "toggled",
7407                     G_CALLBACK (keep_window_above),
7408                     window);
7409   gtk_box_pack_start (GTK_BOX (vbox), button_above, FALSE, FALSE, 0);
7410
7411   button_below = gtk_toggle_button_new_with_label ("Keep below");
7412   g_signal_connect (button_below,
7413                     "toggled",
7414                     G_CALLBACK (keep_window_below),
7415                     window);
7416   gtk_box_pack_start (GTK_BOX (vbox), button_below, FALSE, FALSE, 0);
7417
7418   g_object_set_data (G_OBJECT (button_above), "radio", button_below);
7419   g_object_set_data (G_OBJECT (button_below), "radio", button_above);
7420
7421   button = gtk_button_new_with_label ("Hide (withdraw)");
7422   g_signal_connect_object (button,
7423                            "clicked",
7424                            G_CALLBACK (gtk_widget_hide),
7425                            window,
7426                            G_CONNECT_SWAPPED);
7427   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7428   
7429   gtk_widget_show_all (vbox);
7430
7431   return vbox;
7432 }
7433
7434 void
7435 create_window_states (GtkWidget *widget)
7436 {
7437   static GtkWidget *window = NULL;
7438   GtkWidget *label;
7439   GtkWidget *box1;
7440   GtkWidget *iconified;
7441   GtkWidget *normal;
7442   GtkWidget *controls;
7443
7444   if (!window)
7445     {
7446       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7447       gtk_window_set_screen (GTK_WINDOW (window),
7448                              gtk_widget_get_screen (widget));
7449
7450       g_signal_connect (window, "destroy",
7451                         G_CALLBACK (gtk_widget_destroyed),
7452                         &window);
7453
7454       gtk_window_set_title (GTK_WINDOW (window), "Window states");
7455       
7456       box1 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
7457       gtk_container_add (GTK_CONTAINER (window), box1);
7458
7459       iconified = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7460
7461       gtk_window_set_screen (GTK_WINDOW (iconified),
7462                              gtk_widget_get_screen (widget));
7463       
7464       g_signal_connect_object (iconified, "destroy",
7465                                G_CALLBACK (gtk_widget_destroy),
7466                                window,
7467                                G_CONNECT_SWAPPED);
7468       gtk_window_iconify (GTK_WINDOW (iconified));
7469       gtk_window_set_title (GTK_WINDOW (iconified), "Iconified initially");
7470       controls = get_state_controls (iconified);
7471       gtk_container_add (GTK_CONTAINER (iconified), controls);
7472       
7473       normal = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7474
7475       gtk_window_set_screen (GTK_WINDOW (normal),
7476                              gtk_widget_get_screen (widget));
7477       
7478       g_signal_connect_object (normal, "destroy",
7479                                G_CALLBACK (gtk_widget_destroy),
7480                                window,
7481                                G_CONNECT_SWAPPED);
7482       
7483       gtk_window_set_title (GTK_WINDOW (normal), "Deiconified initially");
7484       controls = get_state_controls (normal);
7485       gtk_container_add (GTK_CONTAINER (normal), controls);
7486       
7487       label = tracking_label (iconified);
7488       gtk_container_add (GTK_CONTAINER (box1), label);
7489
7490       label = tracking_label (normal);
7491       gtk_container_add (GTK_CONTAINER (box1), label);
7492
7493       gtk_widget_show_all (iconified);
7494       gtk_widget_show_all (normal);
7495       gtk_widget_show_all (box1);
7496     }
7497
7498   if (!gtk_widget_get_visible (window))
7499     gtk_widget_show (window);
7500   else
7501     gtk_widget_destroy (window);
7502 }
7503
7504 /*
7505  * Window sizing
7506  */
7507
7508 static gint
7509 configure_event_callback (GtkWidget *widget,
7510                           GdkEventConfigure *event,
7511                           gpointer data)
7512 {
7513   GtkWidget *label = data;
7514   gchar *msg;
7515   gint x, y;
7516   
7517   gtk_window_get_position (GTK_WINDOW (widget), &x, &y);
7518   
7519   msg = g_strdup_printf ("event: %d,%d  %d x %d\n"
7520                          "position: %d, %d",
7521                          event->x, event->y, event->width, event->height,
7522                          x, y);
7523   
7524   gtk_label_set_text (GTK_LABEL (label), msg);
7525
7526   g_free (msg);
7527
7528   return FALSE;
7529 }
7530
7531 static void
7532 get_ints (GtkWidget *window,
7533           gint      *a,
7534           gint      *b)
7535 {
7536   GtkWidget *spin1;
7537   GtkWidget *spin2;
7538
7539   spin1 = g_object_get_data (G_OBJECT (window), "spin1");
7540   spin2 = g_object_get_data (G_OBJECT (window), "spin2");
7541
7542   *a = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (spin1));
7543   *b = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (spin2));
7544 }
7545
7546 static void
7547 set_size_callback (GtkWidget *widget,
7548                    gpointer   data)
7549 {
7550   gint w, h;
7551   
7552   get_ints (data, &w, &h);
7553
7554   gtk_window_resize (GTK_WINDOW (g_object_get_data (data, "target")), w, h);
7555 }
7556
7557 static void
7558 unset_default_size_callback (GtkWidget *widget,
7559                              gpointer   data)
7560 {
7561   gtk_window_set_default_size (g_object_get_data (data, "target"),
7562                                -1, -1);
7563 }
7564
7565 static void
7566 set_default_size_callback (GtkWidget *widget,
7567                            gpointer   data)
7568 {
7569   gint w, h;
7570   
7571   get_ints (data, &w, &h);
7572
7573   gtk_window_set_default_size (g_object_get_data (data, "target"),
7574                                w, h);
7575 }
7576
7577 static void
7578 unset_size_request_callback (GtkWidget *widget,
7579                              gpointer   data)
7580 {
7581   gtk_widget_set_size_request (g_object_get_data (data, "target"),
7582                                -1, -1);
7583 }
7584
7585 static void
7586 set_size_request_callback (GtkWidget *widget,
7587                            gpointer   data)
7588 {
7589   gint w, h;
7590   
7591   get_ints (data, &w, &h);
7592
7593   gtk_widget_set_size_request (g_object_get_data (data, "target"),
7594                                w, h);
7595 }
7596
7597 static void
7598 set_location_callback (GtkWidget *widget,
7599                        gpointer   data)
7600 {
7601   gint x, y;
7602   
7603   get_ints (data, &x, &y);
7604
7605   gtk_window_move (g_object_get_data (data, "target"), x, y);
7606 }
7607
7608 static void
7609 move_to_position_callback (GtkWidget *widget,
7610                            gpointer   data)
7611 {
7612   gint x, y;
7613   GtkWindow *window;
7614
7615   window = g_object_get_data (data, "target");
7616   
7617   gtk_window_get_position (window, &x, &y);
7618
7619   gtk_window_move (window, x, y);
7620 }
7621
7622 static void
7623 set_geometry_callback (GtkWidget *entry,
7624                        gpointer   data)
7625 {
7626   gchar *text;
7627   GtkWindow *target;
7628
7629   target = GTK_WINDOW (g_object_get_data (G_OBJECT (data), "target"));
7630   
7631   text = gtk_editable_get_chars (GTK_EDITABLE (entry), 0, -1);
7632
7633   if (!gtk_window_parse_geometry (target, text))
7634     g_print ("Bad geometry string '%s'\n", text);
7635
7636   g_free (text);
7637 }
7638
7639 static void
7640 resizable_callback (GtkWidget *widget,
7641                      gpointer   data)
7642 {
7643   g_object_set (g_object_get_data (data, "target"),
7644                 "resizable", gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)),
7645                 NULL);
7646 }
7647
7648 static void
7649 gravity_selected (GtkWidget *widget,
7650                   gpointer   data)
7651 {
7652   gtk_window_set_gravity (GTK_WINDOW (g_object_get_data (data, "target")),
7653                           gtk_combo_box_get_active (GTK_COMBO_BOX (widget)) + GDK_GRAVITY_NORTH_WEST);
7654 }
7655
7656 static void
7657 pos_selected (GtkWidget *widget,
7658               gpointer   data)
7659 {
7660   gtk_window_set_position (GTK_WINDOW (g_object_get_data (data, "target")),
7661                            gtk_combo_box_get_active (GTK_COMBO_BOX (widget)) + GTK_WIN_POS_NONE);
7662 }
7663
7664 static void
7665 move_gravity_window_to_current_position (GtkWidget *widget,
7666                                          gpointer   data)
7667 {
7668   gint x, y;
7669   GtkWindow *window;
7670
7671   window = GTK_WINDOW (data);    
7672   
7673   gtk_window_get_position (window, &x, &y);
7674
7675   gtk_window_move (window, x, y);
7676 }
7677
7678 static void
7679 get_screen_corner (GtkWindow *window,
7680                    gint      *x,
7681                    gint      *y)
7682 {
7683   int w, h;
7684   GdkScreen * screen = gtk_window_get_screen (window);
7685   
7686   gtk_window_get_size (GTK_WINDOW (window), &w, &h);
7687
7688   switch (gtk_window_get_gravity (window))
7689     {
7690     case GDK_GRAVITY_SOUTH_EAST:
7691       *x = gdk_screen_get_width (screen) - w;
7692       *y = gdk_screen_get_height (screen) - h;
7693       break;
7694
7695     case GDK_GRAVITY_NORTH_EAST:
7696       *x = gdk_screen_get_width (screen) - w;
7697       *y = 0;
7698       break;
7699
7700     case GDK_GRAVITY_SOUTH_WEST:
7701       *x = 0;
7702       *y = gdk_screen_get_height (screen) - h;
7703       break;
7704
7705     case GDK_GRAVITY_NORTH_WEST:
7706       *x = 0;
7707       *y = 0;
7708       break;
7709       
7710     case GDK_GRAVITY_SOUTH:
7711       *x = (gdk_screen_get_width (screen) - w) / 2;
7712       *y = gdk_screen_get_height (screen) - h;
7713       break;
7714
7715     case GDK_GRAVITY_NORTH:
7716       *x = (gdk_screen_get_width (screen) - w) / 2;
7717       *y = 0;
7718       break;
7719
7720     case GDK_GRAVITY_WEST:
7721       *x = 0;
7722       *y = (gdk_screen_get_height (screen) - h) / 2;
7723       break;
7724
7725     case GDK_GRAVITY_EAST:
7726       *x = gdk_screen_get_width (screen) - w;
7727       *y = (gdk_screen_get_height (screen) - h) / 2;
7728       break;
7729
7730     case GDK_GRAVITY_CENTER:
7731       *x = (gdk_screen_get_width (screen) - w) / 2;
7732       *y = (gdk_screen_get_height (screen) - h) / 2;
7733       break;
7734
7735     case GDK_GRAVITY_STATIC:
7736       /* pick some random numbers */
7737       *x = 350;
7738       *y = 350;
7739       break;
7740
7741     default:
7742       g_assert_not_reached ();
7743       break;
7744     }
7745 }
7746
7747 static void
7748 move_gravity_window_to_starting_position (GtkWidget *widget,
7749                                           gpointer   data)
7750 {
7751   gint x, y;
7752   GtkWindow *window;
7753
7754   window = GTK_WINDOW (data);    
7755   
7756   get_screen_corner (window,
7757                      &x, &y);
7758   
7759   gtk_window_move (window, x, y);
7760 }
7761
7762 static GtkWidget*
7763 make_gravity_window (GtkWidget   *destroy_with,
7764                      GdkGravity   gravity,
7765                      const gchar *title)
7766 {
7767   GtkWidget *window;
7768   GtkWidget *button;
7769   GtkWidget *vbox;
7770   int x, y;
7771   
7772   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7773
7774   gtk_window_set_screen (GTK_WINDOW (window),
7775                          gtk_widget_get_screen (destroy_with));
7776
7777   vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
7778   gtk_widget_show (vbox);
7779   
7780   gtk_container_add (GTK_CONTAINER (window), vbox);
7781   gtk_window_set_title (GTK_WINDOW (window), title);
7782   gtk_window_set_gravity (GTK_WINDOW (window), gravity);
7783
7784   g_signal_connect_object (destroy_with,
7785                            "destroy",
7786                            G_CALLBACK (gtk_widget_destroy),
7787                            window,
7788                            G_CONNECT_SWAPPED);
7789
7790   
7791   button = gtk_button_new_with_mnemonic ("_Move to current position");
7792
7793   g_signal_connect (button, "clicked",
7794                     G_CALLBACK (move_gravity_window_to_current_position),
7795                     window);
7796
7797   gtk_container_add (GTK_CONTAINER (vbox), button);
7798   gtk_widget_show (button);
7799
7800   button = gtk_button_new_with_mnemonic ("Move to _starting position");
7801
7802   g_signal_connect (button, "clicked",
7803                     G_CALLBACK (move_gravity_window_to_starting_position),
7804                     window);
7805
7806   gtk_container_add (GTK_CONTAINER (vbox), button);
7807   gtk_widget_show (button);
7808   
7809   /* Pretend this is the result of --geometry.
7810    * DO NOT COPY THIS CODE unless you are setting --geometry results,
7811    * and in that case you probably should just use gtk_window_parse_geometry().
7812    * AGAIN, DO NOT SET GDK_HINT_USER_POS! It violates the ICCCM unless
7813    * you are parsing --geometry or equivalent.
7814    */
7815   gtk_window_set_geometry_hints (GTK_WINDOW (window),
7816                                  NULL, NULL,
7817                                  GDK_HINT_USER_POS);
7818
7819   gtk_window_set_default_size (GTK_WINDOW (window),
7820                                200, 200);
7821
7822   get_screen_corner (GTK_WINDOW (window), &x, &y);
7823   
7824   gtk_window_move (GTK_WINDOW (window),
7825                    x, y);
7826   
7827   return window;
7828 }
7829
7830 static void
7831 do_gravity_test (GtkWidget *widget,
7832                  gpointer   data)
7833 {
7834   GtkWidget *destroy_with = data;
7835   GtkWidget *window;
7836   
7837   /* We put a window at each gravity point on the screen. */
7838   window = make_gravity_window (destroy_with, GDK_GRAVITY_NORTH_WEST,
7839                                 "NorthWest");
7840   gtk_widget_show (window);
7841   
7842   window = make_gravity_window (destroy_with, GDK_GRAVITY_SOUTH_EAST,
7843                                 "SouthEast");
7844   gtk_widget_show (window);
7845
7846   window = make_gravity_window (destroy_with, GDK_GRAVITY_NORTH_EAST,
7847                                 "NorthEast");
7848   gtk_widget_show (window);
7849
7850   window = make_gravity_window (destroy_with, GDK_GRAVITY_SOUTH_WEST,
7851                                 "SouthWest");
7852   gtk_widget_show (window);
7853
7854   window = make_gravity_window (destroy_with, GDK_GRAVITY_SOUTH,
7855                                 "South");
7856   gtk_widget_show (window);
7857
7858   window = make_gravity_window (destroy_with, GDK_GRAVITY_NORTH,
7859                                 "North");
7860   gtk_widget_show (window);
7861
7862   
7863   window = make_gravity_window (destroy_with, GDK_GRAVITY_WEST,
7864                                 "West");
7865   gtk_widget_show (window);
7866
7867     
7868   window = make_gravity_window (destroy_with, GDK_GRAVITY_EAST,
7869                                 "East");
7870   gtk_widget_show (window);
7871
7872   window = make_gravity_window (destroy_with, GDK_GRAVITY_CENTER,
7873                                 "Center");
7874   gtk_widget_show (window);
7875
7876   window = make_gravity_window (destroy_with, GDK_GRAVITY_STATIC,
7877                                 "Static");
7878   gtk_widget_show (window);
7879 }
7880
7881 static GtkWidget*
7882 window_controls (GtkWidget *window)
7883 {
7884   GtkWidget *control_window;
7885   GtkWidget *label;
7886   GtkWidget *vbox;
7887   GtkWidget *button;
7888   GtkWidget *spin;
7889   GtkAdjustment *adj;
7890   GtkWidget *entry;
7891   GtkWidget *om;
7892   gint i;
7893   
7894   control_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7895
7896   gtk_window_set_screen (GTK_WINDOW (control_window),
7897                          gtk_widget_get_screen (window));
7898
7899   gtk_window_set_title (GTK_WINDOW (control_window), "Size controls");
7900   
7901   g_object_set_data (G_OBJECT (control_window),
7902                      "target",
7903                      window);
7904   
7905   g_signal_connect_object (control_window,
7906                            "destroy",
7907                            G_CALLBACK (gtk_widget_destroy),
7908                            window,
7909                            G_CONNECT_SWAPPED);
7910
7911   vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
7912   
7913   gtk_container_add (GTK_CONTAINER (control_window), vbox);
7914   
7915   label = gtk_label_new ("<no configure events>");
7916   gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
7917   
7918   g_signal_connect (window,
7919                     "configure_event",
7920                     G_CALLBACK (configure_event_callback),
7921                     label);
7922
7923   adj = gtk_adjustment_new (10.0, -2000.0, 2000.0, 1.0, 5.0, 0.0);
7924   spin = gtk_spin_button_new (adj, 0, 0);
7925
7926   gtk_box_pack_start (GTK_BOX (vbox), spin, FALSE, FALSE, 0);
7927
7928   g_object_set_data (G_OBJECT (control_window), "spin1", spin);
7929
7930   adj = gtk_adjustment_new (10.0, -2000.0, 2000.0, 1.0, 5.0, 0.0);
7931   spin = gtk_spin_button_new (adj, 0, 0);
7932
7933   gtk_box_pack_start (GTK_BOX (vbox), spin, FALSE, FALSE, 0);
7934
7935   g_object_set_data (G_OBJECT (control_window), "spin2", spin);
7936
7937   entry = gtk_entry_new ();
7938   gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
7939
7940   g_signal_connect (entry, "changed",
7941                     G_CALLBACK (set_geometry_callback),
7942                     control_window);
7943
7944   button = gtk_button_new_with_label ("Show gravity test windows");
7945   g_signal_connect_swapped (button,
7946                             "clicked",
7947                             G_CALLBACK (do_gravity_test),
7948                             control_window);
7949   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7950
7951   button = gtk_button_new_with_label ("Reshow with initial size");
7952   g_signal_connect_object (button,
7953                            "clicked",
7954                            G_CALLBACK (gtk_window_reshow_with_initial_size),
7955                            window,
7956                            G_CONNECT_SWAPPED);
7957   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7958   
7959   button = gtk_button_new_with_label ("Queue resize");
7960   g_signal_connect_object (button,
7961                            "clicked",
7962                            G_CALLBACK (gtk_widget_queue_resize),
7963                            window,
7964                            G_CONNECT_SWAPPED);
7965   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7966   
7967   button = gtk_button_new_with_label ("Resize");
7968   g_signal_connect (button,
7969                     "clicked",
7970                     G_CALLBACK (set_size_callback),
7971                     control_window);
7972   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7973
7974   button = gtk_button_new_with_label ("Set default size");
7975   g_signal_connect (button,
7976                     "clicked",
7977                     G_CALLBACK (set_default_size_callback),
7978                     control_window);
7979   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7980
7981   button = gtk_button_new_with_label ("Unset default size");
7982   g_signal_connect (button,
7983                     "clicked",
7984                     G_CALLBACK (unset_default_size_callback),
7985                     control_window);
7986   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7987   
7988   button = gtk_button_new_with_label ("Set size request");
7989   g_signal_connect (button,
7990                     "clicked",
7991                     G_CALLBACK (set_size_request_callback),
7992                     control_window);
7993   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
7994
7995   button = gtk_button_new_with_label ("Unset size request");
7996   g_signal_connect (button,
7997                     "clicked",
7998                     G_CALLBACK (unset_size_request_callback),
7999                     control_window);
8000   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8001   
8002   button = gtk_button_new_with_label ("Move");
8003   g_signal_connect (button,
8004                     "clicked",
8005                     G_CALLBACK (set_location_callback),
8006                     control_window);
8007   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8008
8009   button = gtk_button_new_with_label ("Move to current position");
8010   g_signal_connect (button,
8011                     "clicked",
8012                     G_CALLBACK (move_to_position_callback),
8013                     control_window);
8014   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8015
8016   button = gtk_check_button_new_with_label ("Allow resize");
8017   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
8018   g_signal_connect (button,
8019                     "toggled",
8020                     G_CALLBACK (resizable_callback),
8021                     control_window);
8022   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8023   
8024   button = gtk_button_new_with_mnemonic ("_Show");
8025   g_signal_connect_object (button,
8026                            "clicked",
8027                            G_CALLBACK (gtk_widget_show),
8028                            window,
8029                            G_CONNECT_SWAPPED);
8030   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8031
8032   button = gtk_button_new_with_mnemonic ("_Hide");
8033   g_signal_connect_object (button,
8034                            "clicked",
8035                            G_CALLBACK (gtk_widget_hide),
8036                            window,
8037                            G_CONNECT_SWAPPED);
8038   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8039
8040   om = gtk_combo_box_text_new ();
8041   i = 0;
8042   while (i < 10)
8043     {
8044       static gchar *names[] = {
8045         "GDK_GRAVITY_NORTH_WEST",
8046         "GDK_GRAVITY_NORTH",
8047         "GDK_GRAVITY_NORTH_EAST",
8048         "GDK_GRAVITY_WEST",
8049         "GDK_GRAVITY_CENTER",
8050         "GDK_GRAVITY_EAST",
8051         "GDK_GRAVITY_SOUTH_WEST",
8052         "GDK_GRAVITY_SOUTH",
8053         "GDK_GRAVITY_SOUTH_EAST",
8054         "GDK_GRAVITY_STATIC",
8055         NULL
8056       };
8057
8058       g_assert (names[i]);
8059       gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (om), names[i]);
8060
8061       ++i;
8062     }
8063   
8064   g_signal_connect (om,
8065                     "changed",
8066                     G_CALLBACK (gravity_selected),
8067                     control_window);
8068
8069   gtk_box_pack_end (GTK_BOX (vbox), om, FALSE, FALSE, 0);
8070
8071
8072   om = gtk_combo_box_text_new ();
8073   i = 0;
8074   while (i < 5)
8075     {
8076       static gchar *names[] = {
8077         "GTK_WIN_POS_NONE",
8078         "GTK_WIN_POS_CENTER",
8079         "GTK_WIN_POS_MOUSE",
8080         "GTK_WIN_POS_CENTER_ALWAYS",
8081         "GTK_WIN_POS_CENTER_ON_PARENT",
8082         NULL
8083       };
8084
8085       g_assert (names[i]);
8086       gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (om), names[i]);
8087
8088       ++i;
8089     }
8090
8091   g_signal_connect (om,
8092                     "changed",
8093                     G_CALLBACK (pos_selected),
8094                     control_window);
8095
8096   gtk_box_pack_end (GTK_BOX (vbox), om, FALSE, FALSE, 0);
8097   
8098   gtk_widget_show_all (vbox);
8099   
8100   return control_window;
8101 }
8102
8103 void
8104 create_window_sizing (GtkWidget *widget)
8105 {
8106   static GtkWidget *window = NULL;
8107   static GtkWidget *target_window = NULL;
8108
8109   if (!target_window)
8110     {
8111       GtkWidget *label;
8112       
8113       target_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8114       gtk_window_set_screen (GTK_WINDOW (target_window),
8115                              gtk_widget_get_screen (widget));
8116       label = gtk_label_new (NULL);
8117       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");
8118       gtk_container_add (GTK_CONTAINER (target_window), label);
8119       gtk_widget_show (label);
8120       
8121       g_signal_connect (target_window, "destroy",
8122                         G_CALLBACK (gtk_widget_destroyed),
8123                         &target_window);
8124
8125       window = window_controls (target_window);
8126       
8127       g_signal_connect (window, "destroy",
8128                         G_CALLBACK (gtk_widget_destroyed),
8129                         &window);
8130       
8131       gtk_window_set_title (GTK_WINDOW (target_window), "Window to size");
8132     }
8133
8134   /* don't show target window by default, we want to allow testing
8135    * of behavior on first show.
8136    */
8137   
8138   if (!gtk_widget_get_visible (window))
8139     gtk_widget_show (window);
8140   else
8141     gtk_widget_destroy (window);
8142 }
8143
8144 /*
8145  * GtkProgressBar
8146  */
8147
8148 typedef struct _ProgressData {
8149   GtkWidget *window;
8150   GtkWidget *pbar;
8151   GtkWidget *block_spin;
8152   GtkWidget *x_align_spin;
8153   GtkWidget *y_align_spin;
8154   GtkWidget *step_spin;
8155   GtkWidget *act_blocks_spin;
8156   GtkWidget *label;
8157   GtkWidget *omenu1;
8158   GtkWidget *elmenu;
8159   GtkWidget *omenu2;
8160   GtkWidget *entry;
8161   int timer;
8162   gboolean activity;
8163 } ProgressData;
8164
8165 gboolean
8166 progress_timeout (gpointer data)
8167 {
8168   ProgressData *pdata = data;
8169   gdouble new_val;
8170   gchar *text;
8171
8172   if (pdata->activity)
8173     {
8174       gtk_progress_bar_pulse (GTK_PROGRESS_BAR (pdata->pbar));
8175
8176       text = g_strdup_printf ("%s", "???");
8177     }
8178   else
8179     {
8180       new_val = gtk_progress_bar_get_fraction (GTK_PROGRESS_BAR (pdata->pbar)) + 0.01;
8181       if (new_val > 1.00)
8182         new_val = 0.00;
8183       gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (pdata->pbar), new_val);
8184
8185       text = g_strdup_printf ("%.0f%%", 100 * new_val);
8186     }
8187
8188   gtk_label_set_text (GTK_LABEL (pdata->label), text);
8189   g_free (text);
8190
8191   return TRUE;
8192 }
8193
8194 static void
8195 destroy_progress (GtkWidget     *widget,
8196                   ProgressData **pdata)
8197 {
8198   g_source_remove ((*pdata)->timer);
8199   (*pdata)->timer = 0;
8200   (*pdata)->window = NULL;
8201   g_free (*pdata);
8202   *pdata = NULL;
8203 }
8204
8205 static void
8206 progressbar_toggle_orientation (GtkWidget *widget, gpointer data)
8207 {
8208   ProgressData *pdata;
8209   gint i;
8210
8211   pdata = (ProgressData *) data;
8212
8213   if (!gtk_widget_get_mapped (widget))
8214     return;
8215
8216   i = gtk_combo_box_get_active (GTK_COMBO_BOX (widget));
8217
8218   if (i == 0 || i == 1)
8219     gtk_orientable_set_orientation (GTK_ORIENTABLE (pdata->pbar), GTK_ORIENTATION_HORIZONTAL);
8220   else
8221     gtk_orientable_set_orientation (GTK_ORIENTABLE (pdata->pbar), GTK_ORIENTATION_VERTICAL);
8222  
8223   if (i == 1 || i == 2)
8224     gtk_progress_bar_set_inverted (GTK_PROGRESS_BAR (pdata->pbar), TRUE);
8225   else
8226     gtk_progress_bar_set_inverted (GTK_PROGRESS_BAR (pdata->pbar), FALSE);
8227 }
8228
8229 static void
8230 toggle_show_text (GtkWidget *widget, ProgressData *pdata)
8231 {
8232   gboolean active;
8233
8234   active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
8235   gtk_progress_bar_set_show_text (GTK_PROGRESS_BAR (pdata->pbar), active);
8236 }
8237
8238 static void
8239 progressbar_toggle_ellipsize (GtkWidget *widget,
8240                               gpointer   data)
8241 {
8242   ProgressData *pdata = data;
8243   if (gtk_widget_is_drawable (widget))
8244     {
8245       gint i = gtk_combo_box_get_active (GTK_COMBO_BOX (widget));
8246       gtk_progress_bar_set_ellipsize (GTK_PROGRESS_BAR (pdata->pbar), i);
8247     }
8248 }
8249
8250 static void
8251 toggle_activity_mode (GtkWidget *widget, ProgressData *pdata)
8252 {
8253   pdata->activity = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
8254 }
8255
8256 static void
8257 entry_changed (GtkWidget *widget, ProgressData *pdata)
8258 {
8259   gtk_progress_bar_set_text (GTK_PROGRESS_BAR (pdata->pbar),
8260                           gtk_entry_get_text (GTK_ENTRY (pdata->entry)));
8261 }
8262
8263 void
8264 create_progress_bar (GtkWidget *widget)
8265 {
8266   GtkWidget *action_area, *content_area;
8267   GtkWidget *button;
8268   GtkWidget *vbox;
8269   GtkWidget *vbox2;
8270   GtkWidget *hbox;
8271   GtkWidget *check;
8272   GtkWidget *frame;
8273   GtkWidget *tab;
8274   GtkWidget *label;
8275   GtkWidget *align;
8276   static ProgressData *pdata = NULL;
8277
8278   static gchar *items1[] =
8279   {
8280     "Left-Right",
8281     "Right-Left",
8282     "Bottom-Top",
8283     "Top-Bottom"
8284   };
8285
8286     static char *ellipsize_items[] = {
8287     "None",     // PANGO_ELLIPSIZE_NONE,
8288     "Start",    // PANGO_ELLIPSIZE_START,
8289     "Middle",   // PANGO_ELLIPSIZE_MIDDLE,
8290     "End",      // PANGO_ELLIPSIZE_END
8291   };
8292   
8293   if (!pdata)
8294     pdata = g_new0 (ProgressData, 1);
8295
8296   if (!pdata->window)
8297     {
8298       pdata->window = gtk_dialog_new ();
8299
8300       gtk_window_set_screen (GTK_WINDOW (pdata->window),
8301                              gtk_widget_get_screen (widget));
8302
8303       gtk_window_set_resizable (GTK_WINDOW (pdata->window), TRUE);
8304
8305       g_signal_connect (pdata->window, "destroy",
8306                         G_CALLBACK (destroy_progress),
8307                         &pdata);
8308       pdata->timer = 0;
8309
8310       content_area = gtk_dialog_get_content_area (GTK_DIALOG (pdata->window));
8311       action_area = gtk_dialog_get_action_area (GTK_DIALOG (pdata->window));
8312
8313       gtk_window_set_title (GTK_WINDOW (pdata->window), "GtkProgressBar");
8314       gtk_container_set_border_width (GTK_CONTAINER (pdata->window), 0);
8315
8316       vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
8317       gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
8318       gtk_box_pack_start (GTK_BOX (content_area), vbox, FALSE, TRUE, 0);
8319
8320       frame = gtk_frame_new ("Progress");
8321       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
8322
8323       vbox2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
8324       gtk_container_add (GTK_CONTAINER (frame), vbox2);
8325
8326       align = gtk_alignment_new (0.5, 0.5, 0, 0);
8327       gtk_box_pack_start (GTK_BOX (vbox2), align, FALSE, FALSE, 5);
8328
8329       pdata->pbar = gtk_progress_bar_new ();
8330       gtk_progress_bar_set_ellipsize (GTK_PROGRESS_BAR (pdata->pbar),
8331                                       PANGO_ELLIPSIZE_MIDDLE);
8332
8333       gtk_container_add (GTK_CONTAINER (align), pdata->pbar);
8334       pdata->timer = g_timeout_add (100, (GSourceFunc)progress_timeout, pdata);
8335
8336       align = gtk_alignment_new (0.5, 0.5, 0, 0);
8337       gtk_box_pack_start (GTK_BOX (vbox2), align, FALSE, FALSE, 5);
8338
8339       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
8340       gtk_container_add (GTK_CONTAINER (align), hbox);
8341       label = gtk_label_new ("Label updated by user :"); 
8342       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
8343       pdata->label = gtk_label_new ("");
8344       gtk_box_pack_start (GTK_BOX (hbox), pdata->label, FALSE, TRUE, 0);
8345
8346       frame = gtk_frame_new ("Options");
8347       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
8348
8349       vbox2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
8350       gtk_container_add (GTK_CONTAINER (frame), vbox2);
8351
8352       tab = gtk_table_new (7, 2, FALSE);
8353       gtk_box_pack_start (GTK_BOX (vbox2), tab, FALSE, TRUE, 0);
8354
8355       label = gtk_label_new ("Orientation :");
8356       gtk_table_attach (GTK_TABLE (tab), label, 0, 1, 0, 1,
8357                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
8358                         5, 5);
8359       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
8360
8361       pdata->omenu1 = build_option_menu (items1, 4, 0,
8362                                          progressbar_toggle_orientation,
8363                                          pdata);
8364       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
8365       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 0, 1,
8366                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
8367                         5, 5);
8368       gtk_box_pack_start (GTK_BOX (hbox), pdata->omenu1, TRUE, TRUE, 0);
8369       
8370       check = gtk_check_button_new_with_label ("Show text");
8371       g_signal_connect (check, "clicked",
8372                         G_CALLBACK (toggle_show_text),
8373                         pdata);
8374       gtk_table_attach (GTK_TABLE (tab), check, 0, 1, 1, 2,
8375                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
8376                         5, 5);
8377
8378       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
8379       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 1, 2,
8380                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
8381                         5, 5);
8382
8383       label = gtk_label_new ("Text: ");
8384       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
8385
8386       pdata->entry = gtk_entry_new ();
8387       g_signal_connect (pdata->entry, "changed",
8388                         G_CALLBACK (entry_changed),
8389                         pdata);
8390       gtk_box_pack_start (GTK_BOX (hbox), pdata->entry, TRUE, TRUE, 0);
8391       gtk_widget_set_size_request (pdata->entry, 100, -1);
8392
8393       label = gtk_label_new ("Ellipsize text :");
8394       gtk_table_attach (GTK_TABLE (tab), label, 0, 1, 10, 11,
8395                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
8396                         5, 5);
8397       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
8398       pdata->elmenu = build_option_menu (ellipsize_items,
8399                                          sizeof (ellipsize_items) / sizeof (ellipsize_items[0]),
8400                                          2, // PANGO_ELLIPSIZE_MIDDLE
8401                                          progressbar_toggle_ellipsize,
8402                                          pdata);
8403       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
8404       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 10, 11,
8405                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
8406                         5, 5);
8407       gtk_box_pack_start (GTK_BOX (hbox), pdata->elmenu, TRUE, TRUE, 0);
8408
8409       check = gtk_check_button_new_with_label ("Activity mode");
8410       g_signal_connect (check, "clicked",
8411                         G_CALLBACK (toggle_activity_mode), pdata);
8412       gtk_table_attach (GTK_TABLE (tab), check, 0, 1, 15, 16,
8413                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
8414                         5, 5);
8415
8416       button = gtk_button_new_with_label ("close");
8417       g_signal_connect_swapped (button, "clicked",
8418                                 G_CALLBACK (gtk_widget_destroy),
8419                                 pdata->window);
8420       gtk_widget_set_can_default (button, TRUE);
8421       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
8422       gtk_widget_grab_default (button);
8423     }
8424
8425   if (!gtk_widget_get_visible (pdata->window))
8426     gtk_widget_show_all (pdata->window);
8427   else
8428     gtk_widget_destroy (pdata->window);
8429 }
8430
8431 /*
8432  * Properties
8433  */
8434
8435 typedef struct {
8436   int x;
8437   int y;
8438   gboolean found;
8439   gboolean first;
8440   GtkWidget *res_widget;
8441 } FindWidgetData;
8442
8443 static void
8444 find_widget (GtkWidget *widget, FindWidgetData *data)
8445 {
8446   GtkAllocation new_allocation;
8447   gint x_offset = 0;
8448   gint y_offset = 0;
8449
8450   gtk_widget_get_allocation (widget, &new_allocation);
8451
8452   if (data->found || !gtk_widget_get_mapped (widget))
8453     return;
8454
8455   /* Note that in the following code, we only count the
8456    * position as being inside a WINDOW widget if it is inside
8457    * widget->window; points that are outside of widget->window
8458    * but within the allocation are not counted. This is consistent
8459    * with the way we highlight drag targets.
8460    */
8461   if (gtk_widget_get_has_window (widget))
8462     {
8463       new_allocation.x = 0;
8464       new_allocation.y = 0;
8465     }
8466
8467   if (gtk_widget_get_parent (widget) && !data->first)
8468     {
8469       GdkWindow *window = gtk_widget_get_window (widget);
8470       while (window != gtk_widget_get_window (gtk_widget_get_parent (widget)))
8471         {
8472           gint tx, ty, twidth, theight;
8473           
8474           twidth = gdk_window_get_width (window);
8475           theight = gdk_window_get_height (window);
8476
8477           if (new_allocation.x < 0)
8478             {
8479               new_allocation.width += new_allocation.x;
8480               new_allocation.x = 0;
8481             }
8482           if (new_allocation.y < 0)
8483             {
8484               new_allocation.height += new_allocation.y;
8485               new_allocation.y = 0;
8486             }
8487           if (new_allocation.x + new_allocation.width > twidth)
8488             new_allocation.width = twidth - new_allocation.x;
8489           if (new_allocation.y + new_allocation.height > theight)
8490             new_allocation.height = theight - new_allocation.y;
8491
8492           gdk_window_get_position (window, &tx, &ty);
8493           new_allocation.x += tx;
8494           x_offset += tx;
8495           new_allocation.y += ty;
8496           y_offset += ty;
8497
8498           window = gdk_window_get_parent (window);
8499         }
8500     }
8501
8502   if ((data->x >= new_allocation.x) && (data->y >= new_allocation.y) &&
8503       (data->x < new_allocation.x + new_allocation.width) && 
8504       (data->y < new_allocation.y + new_allocation.height))
8505     {
8506       /* First, check if the drag is in a valid drop site in
8507        * one of our children 
8508        */
8509       if (GTK_IS_CONTAINER (widget))
8510         {
8511           FindWidgetData new_data = *data;
8512           
8513           new_data.x -= x_offset;
8514           new_data.y -= y_offset;
8515           new_data.found = FALSE;
8516           new_data.first = FALSE;
8517           
8518           gtk_container_forall (GTK_CONTAINER (widget),
8519                                 (GtkCallback)find_widget,
8520                                 &new_data);
8521           
8522           data->found = new_data.found;
8523           if (data->found)
8524             data->res_widget = new_data.res_widget;
8525         }
8526
8527       /* If not, and this widget is registered as a drop site, check to
8528        * emit "drag_motion" to check if we are actually in
8529        * a drop site.
8530        */
8531       if (!data->found)
8532         {
8533           data->found = TRUE;
8534           data->res_widget = widget;
8535         }
8536     }
8537 }
8538
8539 static GtkWidget *
8540 find_widget_at_pointer (GdkDisplay *display)
8541 {
8542   GtkWidget *widget = NULL;
8543   GdkWindow *pointer_window;
8544   gint x, y;
8545   FindWidgetData data;
8546  
8547  pointer_window = gdk_display_get_window_at_pointer (display, NULL, NULL);
8548  
8549  if (pointer_window)
8550    {
8551      gpointer widget_ptr;
8552
8553      gdk_window_get_user_data (pointer_window, &widget_ptr);
8554      widget = widget_ptr;
8555    }
8556
8557  if (widget)
8558    {
8559      gdk_window_get_pointer (gtk_widget_get_window (widget),
8560                              &x, &y, NULL);
8561      
8562      data.x = x;
8563      data.y = y;
8564      data.found = FALSE;
8565      data.first = TRUE;
8566
8567      find_widget (widget, &data);
8568      if (data.found)
8569        return data.res_widget;
8570      return widget;
8571    }
8572  return NULL;
8573 }
8574
8575 struct PropertiesData {
8576   GtkWidget **window;
8577   GdkCursor *cursor;
8578   gboolean in_query;
8579   gulong handler;
8580 };
8581
8582 static void
8583 destroy_properties (GtkWidget             *widget,
8584                     struct PropertiesData *data)
8585 {
8586   if (data->window)
8587     {
8588       *data->window = NULL;
8589       data->window = NULL;
8590     }
8591
8592   if (data->cursor)
8593     {
8594       gdk_cursor_unref (data->cursor);
8595       data->cursor = NULL;
8596     }
8597
8598   if (data->handler)
8599     {
8600       g_signal_handler_disconnect (widget, data->handler);
8601       data->handler = 0;
8602     }
8603
8604   g_free (data);
8605 }
8606
8607 static gint
8608 property_query_event (GtkWidget        *widget,
8609                       GdkEvent         *event,
8610                       struct PropertiesData *data)
8611 {
8612   GtkWidget *res_widget = NULL;
8613
8614   if (!data->in_query)
8615     return FALSE;
8616   
8617   if (event->type == GDK_BUTTON_RELEASE)
8618     {
8619       gtk_grab_remove (widget);
8620       gdk_display_pointer_ungrab (gtk_widget_get_display (widget),
8621                                   GDK_CURRENT_TIME);
8622       
8623       res_widget = find_widget_at_pointer (gtk_widget_get_display (widget));
8624       if (res_widget)
8625         {
8626           g_object_set_data (G_OBJECT (res_widget), "prop-editor-screen",
8627                              gtk_widget_get_screen (widget));
8628           create_prop_editor (G_OBJECT (res_widget), 0);
8629         }
8630
8631       data->in_query = FALSE;
8632     }
8633   return FALSE;
8634 }
8635
8636
8637 static void
8638 query_properties (GtkButton *button,
8639                   struct PropertiesData *data)
8640 {
8641   GtkWidget *widget = GTK_WIDGET (button);
8642   gint failure;
8643
8644   g_signal_connect (button, "event",
8645                     G_CALLBACK (property_query_event), data);
8646
8647
8648   if (!data->cursor)
8649     data->cursor = gdk_cursor_new_for_display (gtk_widget_get_display (widget),
8650                                                GDK_TARGET);
8651
8652   failure = gdk_pointer_grab (gtk_widget_get_window (widget),
8653                               TRUE,
8654                               GDK_BUTTON_RELEASE_MASK,
8655                               NULL,
8656                               data->cursor,
8657                               GDK_CURRENT_TIME);
8658
8659   gtk_grab_add (widget);
8660
8661   data->in_query = TRUE;
8662 }
8663
8664 static void
8665 create_properties (GtkWidget *widget)
8666 {
8667   static GtkWidget *window = NULL;
8668   GtkWidget *button;
8669   GtkWidget *vbox;
8670   GtkWidget *label;
8671   struct PropertiesData *data;
8672
8673   data = g_new (struct PropertiesData, 1);
8674   data->window = &window;
8675   data->in_query = FALSE;
8676   data->cursor = NULL;
8677   data->handler = 0;
8678
8679   if (!window)
8680     {
8681       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8682
8683       gtk_window_set_screen (GTK_WINDOW (window),
8684                              gtk_widget_get_screen (widget));      
8685
8686       data->handler = g_signal_connect (window, "destroy",
8687                                         G_CALLBACK (destroy_properties),
8688                                         data);
8689
8690       gtk_window_set_title (GTK_WINDOW (window), "test properties");
8691       gtk_container_set_border_width (GTK_CONTAINER (window), 10);
8692
8693       vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 1);
8694       gtk_container_add (GTK_CONTAINER (window), vbox);
8695             
8696       label = gtk_label_new ("This is just a dumb test to test properties.\nIf you need a generic module, get GLE.");
8697       gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
8698       
8699       button = gtk_button_new_with_label ("Query properties");
8700       gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
8701       g_signal_connect (button, "clicked",
8702                         G_CALLBACK (query_properties),
8703                         data);
8704     }
8705
8706   if (!gtk_widget_get_visible (window))
8707     gtk_widget_show_all (window);
8708   else
8709     gtk_widget_destroy (window);
8710   
8711 }
8712
8713 struct SnapshotData {
8714   GtkWidget *toplevel_button;
8715   GtkWidget **window;
8716   GdkCursor *cursor;
8717   gboolean in_query;
8718   gboolean is_toplevel;
8719   gint handler;
8720 };
8721
8722 static void
8723 destroy_snapshot_data (GtkWidget             *widget,
8724                        struct SnapshotData *data)
8725 {
8726   if (*data->window)
8727     *data->window = NULL;
8728   
8729   if (data->cursor)
8730     {
8731       gdk_cursor_unref (data->cursor);
8732       data->cursor = NULL;
8733     }
8734
8735   if (data->handler)
8736     {
8737       g_signal_handler_disconnect (widget, data->handler);
8738       data->handler = 0;
8739     }
8740
8741   g_free (data);
8742 }
8743
8744 static gint
8745 snapshot_widget_event (GtkWidget               *widget,
8746                        GdkEvent        *event,
8747                        struct SnapshotData *data)
8748 {
8749   GtkWidget *res_widget = NULL;
8750
8751   if (!data->in_query)
8752     return FALSE;
8753   
8754   if (event->type == GDK_BUTTON_RELEASE)
8755     {
8756       gtk_grab_remove (widget);
8757       gdk_display_pointer_ungrab (gtk_widget_get_display (widget),
8758                                   GDK_CURRENT_TIME);
8759       
8760       res_widget = find_widget_at_pointer (gtk_widget_get_display (widget));
8761       if (data->is_toplevel && res_widget)
8762         res_widget = gtk_widget_get_toplevel (res_widget);
8763       if (res_widget)
8764         {
8765           cairo_surface_t *surface;
8766           GtkWidget *window, *image;
8767           GdkPixbuf *pixbuf;
8768           int width, height;
8769           cairo_t *cr;
8770
8771           width = gtk_widget_get_allocated_width (res_widget);
8772           height = gtk_widget_get_allocated_height (res_widget);
8773
8774           surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
8775
8776           cr = cairo_create (surface);
8777           gtk_widget_draw (res_widget, cr);
8778           cairo_destroy (cr);
8779
8780           pixbuf = gdk_pixbuf_get_from_surface (surface,
8781                                                 0, 0,
8782                                                 width, height);
8783           cairo_surface_destroy (surface);
8784
8785           window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8786           image = gtk_image_new_from_pixbuf (pixbuf);
8787           g_object_unref (pixbuf);
8788
8789           gtk_container_add (GTK_CONTAINER (window), image);
8790           gtk_widget_show_all (window);
8791         }
8792
8793       data->in_query = FALSE;
8794     }
8795   return FALSE;
8796 }
8797
8798
8799 static void
8800 snapshot_widget (GtkButton *button,
8801                  struct SnapshotData *data)
8802 {
8803   GtkWidget *widget = GTK_WIDGET (button);
8804   gint failure;
8805
8806   g_signal_connect (button, "event",
8807                     G_CALLBACK (snapshot_widget_event), data);
8808
8809   data->is_toplevel = widget == data->toplevel_button;
8810
8811   if (!data->cursor)
8812     data->cursor = gdk_cursor_new_for_display (gtk_widget_get_display (widget),
8813                                                GDK_TARGET);
8814
8815   failure = gdk_pointer_grab (gtk_widget_get_window (widget),
8816                               TRUE,
8817                               GDK_BUTTON_RELEASE_MASK,
8818                               NULL,
8819                               data->cursor,
8820                               GDK_CURRENT_TIME);
8821
8822   gtk_grab_add (widget);
8823
8824   data->in_query = TRUE;
8825 }
8826
8827 static void
8828 create_snapshot (GtkWidget *widget)
8829 {
8830   static GtkWidget *window = NULL;
8831   GtkWidget *button;
8832   GtkWidget *vbox;
8833   struct SnapshotData *data;
8834
8835   data = g_new (struct SnapshotData, 1);
8836   data->window = &window;
8837   data->in_query = FALSE;
8838   data->cursor = NULL;
8839   data->handler = 0;
8840
8841   if (!window)
8842     {
8843       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8844
8845       gtk_window_set_screen (GTK_WINDOW (window),
8846                              gtk_widget_get_screen (widget));      
8847
8848       data->handler = g_signal_connect (window, "destroy",
8849                                         G_CALLBACK (destroy_snapshot_data),
8850                                         data);
8851
8852       gtk_window_set_title (GTK_WINDOW (window), "test snapshot");
8853       gtk_container_set_border_width (GTK_CONTAINER (window), 10);
8854
8855       vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 1);
8856       gtk_container_add (GTK_CONTAINER (window), vbox);
8857             
8858       button = gtk_button_new_with_label ("Snapshot widget");
8859       gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
8860       g_signal_connect (button, "clicked",
8861                         G_CALLBACK (snapshot_widget),
8862                         data);
8863       
8864       button = gtk_button_new_with_label ("Snapshot toplevel");
8865       data->toplevel_button = button;
8866       gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
8867       g_signal_connect (button, "clicked",
8868                         G_CALLBACK (snapshot_widget),
8869                         data);
8870     }
8871
8872   if (!gtk_widget_get_visible (window))
8873     gtk_widget_show_all (window);
8874   else
8875     gtk_widget_destroy (window);
8876   
8877 }
8878
8879 /*
8880  * Selection Test
8881  */
8882
8883 void
8884 selection_test_received (GtkWidget        *tree_view,
8885                          GtkSelectionData *data)
8886 {
8887   GtkTreeModel *model;
8888   GtkListStore *store;
8889   GdkAtom *atoms;
8890   int i, l;
8891
8892   if (data->length < 0)
8893     {
8894       g_print ("Selection retrieval failed\n");
8895       return;
8896     }
8897   if (data->type != GDK_SELECTION_TYPE_ATOM)
8898     {
8899       g_print ("Selection \"TARGETS\" was not returned as atoms!\n");
8900       return;
8901     }
8902
8903   /* Clear out any current list items */
8904
8905   model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree_view));
8906   store = GTK_LIST_STORE (model);
8907   gtk_list_store_clear (store);
8908
8909   /* Add new items to list */
8910
8911   atoms = (GdkAtom *)data->data;
8912
8913   l = data->length / sizeof (GdkAtom);
8914   for (i = 0; i < l; i++)
8915     {
8916       char *name;
8917       GtkTreeIter iter;
8918
8919       name = gdk_atom_name (atoms[i]);
8920       if (name != NULL)
8921         {
8922           gtk_list_store_insert_with_values (store, &iter, i, 0, name, -1);
8923           g_free (name);
8924         }
8925       else
8926        gtk_list_store_insert_with_values (store, &iter, i, 0,  "(bad atom)", -1);
8927     }
8928
8929   return;
8930 }
8931
8932 void
8933 selection_test_get_targets (GtkWidget *widget, GtkWidget *tree_view)
8934 {
8935   static GdkAtom targets_atom = GDK_NONE;
8936
8937   if (targets_atom == GDK_NONE)
8938     targets_atom = gdk_atom_intern ("TARGETS", FALSE);
8939
8940   gtk_selection_convert (tree_view, GDK_SELECTION_PRIMARY, targets_atom,
8941                          GDK_CURRENT_TIME);
8942 }
8943
8944 void
8945 create_selection_test (GtkWidget *widget)
8946 {
8947   static GtkWidget *window = NULL;
8948   GtkWidget *action_area, *content_area;
8949   GtkWidget *button;
8950   GtkWidget *vbox;
8951   GtkWidget *scrolled_win;
8952   GtkListStore* store;
8953   GtkWidget *tree_view;
8954   GtkTreeViewColumn *column;
8955   GtkCellRenderer *renderer;
8956   GtkWidget *label;
8957
8958   if (!window)
8959     {
8960       window = gtk_dialog_new ();
8961       
8962       gtk_window_set_screen (GTK_WINDOW (window),
8963                              gtk_widget_get_screen (widget));
8964
8965       g_signal_connect (window, "destroy",
8966                         G_CALLBACK (gtk_widget_destroyed),
8967                         &window);
8968
8969       content_area = gtk_dialog_get_content_area (GTK_DIALOG (window));
8970       action_area = gtk_dialog_get_action_area (GTK_DIALOG (window));
8971
8972       gtk_window_set_title (GTK_WINDOW (window), "Selection Test");
8973       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
8974
8975       /* Create the list */
8976
8977       vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
8978       gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
8979       gtk_box_pack_start (GTK_BOX (content_area), vbox, TRUE, TRUE, 0);
8980
8981       label = gtk_label_new ("Gets available targets for current selection");
8982       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
8983
8984       scrolled_win = gtk_scrolled_window_new (NULL, NULL);
8985       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
8986                                       GTK_POLICY_AUTOMATIC, 
8987                                       GTK_POLICY_AUTOMATIC);
8988       gtk_box_pack_start (GTK_BOX (vbox), scrolled_win, TRUE, TRUE, 0);
8989       gtk_widget_set_size_request (scrolled_win, 100, 200);
8990
8991       store = gtk_list_store_new (1, G_TYPE_STRING);
8992       tree_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store));
8993       gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_win), tree_view);
8994
8995       renderer = gtk_cell_renderer_text_new ();
8996       column = gtk_tree_view_column_new_with_attributes ("Target", renderer,
8997                                                          "text", 0, NULL);
8998       gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), column);
8999
9000       g_signal_connect (tree_view, "selection_received",
9001                         G_CALLBACK (selection_test_received), NULL);
9002
9003       /* .. And create some buttons */
9004       button = gtk_button_new_with_label ("Get Targets");
9005       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
9006
9007       g_signal_connect (button, "clicked",
9008                         G_CALLBACK (selection_test_get_targets), tree_view);
9009
9010       button = gtk_button_new_with_label ("Quit");
9011       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
9012
9013       g_signal_connect_swapped (button, "clicked",
9014                                 G_CALLBACK (gtk_widget_destroy),
9015                                 window);
9016     }
9017
9018   if (!gtk_widget_get_visible (window))
9019     gtk_widget_show_all (window);
9020   else
9021     gtk_widget_destroy (window);
9022 }
9023
9024 /*
9025  * Test scrolling
9026  */
9027
9028 static int scroll_test_pos = 0.0;
9029
9030 static gint
9031 scroll_test_draw (GtkWidget     *widget,
9032                   cairo_t       *cr,
9033                   GtkAdjustment *adj)
9034 {
9035   gint i,j;
9036   gint imin, imax, jmin, jmax;
9037   GdkRectangle clip;
9038   
9039   gdk_cairo_get_clip_rectangle (cr, &clip);
9040
9041   imin = (clip.x) / 10;
9042   imax = (clip.x + clip.width + 9) / 10;
9043
9044   jmin = ((int)adj->value + clip.y) / 10;
9045   jmax = ((int)adj->value + clip.y + clip.height + 9) / 10;
9046
9047   for (i=imin; i<imax; i++)
9048     for (j=jmin; j<jmax; j++)
9049       if ((i+j) % 2)
9050         cairo_rectangle (cr, 10*i, 10*j - (int)adj->value, 1+i%10, 1+j%10);
9051
9052   cairo_fill (cr);
9053
9054   return TRUE;
9055 }
9056
9057 static gint
9058 scroll_test_scroll (GtkWidget *widget, GdkEventScroll *event,
9059                     GtkAdjustment *adj)
9060 {
9061   gdouble new_value = adj->value + ((event->direction == GDK_SCROLL_UP) ?
9062                                     -adj->page_increment / 2:
9063                                     adj->page_increment / 2);
9064   new_value = CLAMP (new_value, adj->lower, adj->upper - adj->page_size);
9065   gtk_adjustment_set_value (adj, new_value);  
9066   
9067   return TRUE;
9068 }
9069
9070 static void
9071 scroll_test_configure (GtkWidget *widget, GdkEventConfigure *event,
9072                        GtkAdjustment *adj)
9073 {
9074   GtkAllocation allocation;
9075
9076   gtk_widget_get_allocation (widget, &allocation);
9077   adj->page_increment = 0.9 * allocation.height;
9078   adj->page_size = allocation.height;
9079
9080   g_signal_emit_by_name (adj, "changed");
9081 }
9082
9083 static void
9084 scroll_test_adjustment_changed (GtkAdjustment *adj, GtkWidget *widget)
9085 {
9086   GdkWindow *window;
9087   gint dy;
9088
9089   dy = scroll_test_pos - (int)adj->value;
9090   scroll_test_pos = adj->value;
9091
9092   if (!gtk_widget_is_drawable (widget))
9093     return;
9094
9095   window = gtk_widget_get_window (widget);
9096   gdk_window_scroll (window, 0, dy);
9097   gdk_window_process_updates (window, FALSE);
9098 }
9099
9100
9101 void
9102 create_scroll_test (GtkWidget *widget)
9103 {
9104   static GtkWidget *window = NULL;
9105   GtkWidget *action_area, *content_area;
9106   GtkWidget *hbox;
9107   GtkWidget *drawing_area;
9108   GtkWidget *scrollbar;
9109   GtkWidget *button;
9110   GtkAdjustment *adj;
9111   GdkGeometry geometry;
9112   GdkWindowHints geometry_mask;
9113
9114   if (!window)
9115     {
9116       window = gtk_dialog_new ();
9117
9118       gtk_window_set_screen (GTK_WINDOW (window),
9119                              gtk_widget_get_screen (widget));
9120
9121       g_signal_connect (window, "destroy",
9122                         G_CALLBACK (gtk_widget_destroyed),
9123                         &window);
9124
9125       content_area = gtk_dialog_get_content_area (GTK_DIALOG (window));
9126       action_area = gtk_dialog_get_action_area (GTK_DIALOG (window));
9127
9128       gtk_window_set_title (GTK_WINDOW (window), "Scroll Test");
9129       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
9130
9131       hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
9132       gtk_box_pack_start (GTK_BOX (content_area), hbox, TRUE, TRUE, 0);
9133       gtk_widget_show (hbox);
9134
9135       drawing_area = gtk_drawing_area_new ();
9136       gtk_widget_set_size_request (drawing_area, 200, 200);
9137       gtk_box_pack_start (GTK_BOX (hbox), drawing_area, TRUE, TRUE, 0);
9138       gtk_widget_show (drawing_area);
9139
9140       gtk_widget_set_events (drawing_area, GDK_EXPOSURE_MASK | GDK_SCROLL_MASK);
9141
9142       adj = gtk_adjustment_new (0.0, 0.0, 1000.0, 1.0, 180.0, 200.0);
9143       scroll_test_pos = 0.0;
9144
9145       scrollbar = gtk_scrollbar_new (GTK_ORIENTATION_VERTICAL, adj);
9146       gtk_box_pack_start (GTK_BOX (hbox), scrollbar, FALSE, FALSE, 0);
9147       gtk_widget_show (scrollbar);
9148
9149       g_signal_connect (drawing_area, "draw",
9150                         G_CALLBACK (scroll_test_draw), adj);
9151       g_signal_connect (drawing_area, "configure_event",
9152                         G_CALLBACK (scroll_test_configure), adj);
9153       g_signal_connect (drawing_area, "scroll_event",
9154                         G_CALLBACK (scroll_test_scroll), adj);
9155       
9156       g_signal_connect (adj, "value_changed",
9157                         G_CALLBACK (scroll_test_adjustment_changed),
9158                         drawing_area);
9159       
9160       /* .. And create some buttons */
9161
9162       button = gtk_button_new_with_label ("Quit");
9163       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
9164
9165       g_signal_connect_swapped (button, "clicked",
9166                                 G_CALLBACK (gtk_widget_destroy),
9167                                 window);
9168       gtk_widget_show (button);
9169
9170       /* Set up gridded geometry */
9171
9172       geometry_mask = GDK_HINT_MIN_SIZE | 
9173                        GDK_HINT_BASE_SIZE | 
9174                        GDK_HINT_RESIZE_INC;
9175
9176       geometry.min_width = 20;
9177       geometry.min_height = 20;
9178       geometry.base_width = 0;
9179       geometry.base_height = 0;
9180       geometry.width_inc = 10;
9181       geometry.height_inc = 10;
9182       
9183       gtk_window_set_geometry_hints (GTK_WINDOW (window),
9184                                drawing_area, &geometry, geometry_mask);
9185     }
9186
9187   if (!gtk_widget_get_visible (window))
9188     gtk_widget_show (window);
9189   else
9190     gtk_widget_destroy (window);
9191 }
9192
9193 /*
9194  * Timeout Test
9195  */
9196
9197 static int timer = 0;
9198
9199 gint
9200 timeout_test (GtkWidget *label)
9201 {
9202   static int count = 0;
9203   static char buffer[32];
9204
9205   sprintf (buffer, "count: %d", ++count);
9206   gtk_label_set_text (GTK_LABEL (label), buffer);
9207
9208   return TRUE;
9209 }
9210
9211 void
9212 start_timeout_test (GtkWidget *widget,
9213                     GtkWidget *label)
9214 {
9215   if (!timer)
9216     {
9217       timer = g_timeout_add (100, (GSourceFunc)timeout_test, label);
9218     }
9219 }
9220
9221 void
9222 stop_timeout_test (GtkWidget *widget,
9223                    gpointer   data)
9224 {
9225   if (timer)
9226     {
9227       g_source_remove (timer);
9228       timer = 0;
9229     }
9230 }
9231
9232 void
9233 destroy_timeout_test (GtkWidget  *widget,
9234                       GtkWidget **window)
9235 {
9236   stop_timeout_test (NULL, NULL);
9237
9238   *window = NULL;
9239 }
9240
9241 void
9242 create_timeout_test (GtkWidget *widget)
9243 {
9244   static GtkWidget *window = NULL;
9245   GtkWidget *action_area, *content_area;
9246   GtkWidget *button;
9247   GtkWidget *label;
9248
9249   if (!window)
9250     {
9251       window = gtk_dialog_new ();
9252
9253       gtk_window_set_screen (GTK_WINDOW (window),
9254                              gtk_widget_get_screen (widget));
9255
9256       g_signal_connect (window, "destroy",
9257                         G_CALLBACK (destroy_timeout_test),
9258                         &window);
9259
9260       content_area = gtk_dialog_get_content_area (GTK_DIALOG (window));
9261       action_area = gtk_dialog_get_content_area (GTK_DIALOG (window));
9262
9263       gtk_window_set_title (GTK_WINDOW (window), "Timeout Test");
9264       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
9265
9266       label = gtk_label_new ("count: 0");
9267       gtk_misc_set_padding (GTK_MISC (label), 10, 10);
9268       gtk_box_pack_start (GTK_BOX (content_area), label, TRUE, TRUE, 0);
9269       gtk_widget_show (label);
9270
9271       button = gtk_button_new_with_label ("close");
9272       g_signal_connect_swapped (button, "clicked",
9273                                 G_CALLBACK (gtk_widget_destroy),
9274                                 window);
9275       gtk_widget_set_can_default (button, TRUE);
9276       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
9277       gtk_widget_grab_default (button);
9278       gtk_widget_show (button);
9279
9280       button = gtk_button_new_with_label ("start");
9281       g_signal_connect (button, "clicked",
9282                         G_CALLBACK(start_timeout_test),
9283                         label);
9284       gtk_widget_set_can_default (button, TRUE);
9285       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
9286       gtk_widget_show (button);
9287
9288       button = gtk_button_new_with_label ("stop");
9289       g_signal_connect (button, "clicked",
9290                         G_CALLBACK (stop_timeout_test),
9291                         NULL);
9292       gtk_widget_set_can_default (button, TRUE);
9293       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
9294       gtk_widget_show (button);
9295     }
9296
9297   if (!gtk_widget_get_visible (window))
9298     gtk_widget_show (window);
9299   else
9300     gtk_widget_destroy (window);
9301 }
9302
9303 /*
9304  * Idle Test
9305  */
9306
9307 static int idle_id = 0;
9308
9309 static gint
9310 idle_test (GtkWidget *label)
9311 {
9312   static int count = 0;
9313   static char buffer[32];
9314
9315   sprintf (buffer, "count: %d", ++count);
9316   gtk_label_set_text (GTK_LABEL (label), buffer);
9317
9318   return TRUE;
9319 }
9320
9321 static void
9322 start_idle_test (GtkWidget *widget,
9323                  GtkWidget *label)
9324 {
9325   if (!idle_id)
9326     {
9327       idle_id = g_idle_add ((GSourceFunc) idle_test, label);
9328     }
9329 }
9330
9331 static void
9332 stop_idle_test (GtkWidget *widget,
9333                 gpointer   data)
9334 {
9335   if (idle_id)
9336     {
9337       g_source_remove (idle_id);
9338       idle_id = 0;
9339     }
9340 }
9341
9342 static void
9343 destroy_idle_test (GtkWidget  *widget,
9344                    GtkWidget **window)
9345 {
9346   stop_idle_test (NULL, NULL);
9347
9348   *window = NULL;
9349 }
9350
9351 static void
9352 toggle_idle_container (GObject *button,
9353                        GtkContainer *container)
9354 {
9355   gtk_container_set_resize_mode (container, GPOINTER_TO_INT (g_object_get_data (button, "user_data")));
9356 }
9357
9358 static void
9359 create_idle_test (GtkWidget *widget)
9360 {
9361   static GtkWidget *window = NULL;
9362   GtkWidget *button;
9363   GtkWidget *label;
9364   GtkWidget *container;
9365
9366   if (!window)
9367     {
9368       GtkWidget *action_area, *content_area;
9369       GtkWidget *button2;
9370       GtkWidget *frame;
9371       GtkWidget *box;
9372
9373       window = gtk_dialog_new ();
9374
9375       gtk_window_set_screen (GTK_WINDOW (window),
9376                              gtk_widget_get_screen (widget));
9377
9378       g_signal_connect (window, "destroy",
9379                         G_CALLBACK (destroy_idle_test),
9380                         &window);
9381
9382       content_area = gtk_dialog_get_content_area (GTK_DIALOG (window));
9383       action_area = gtk_dialog_get_action_area (GTK_DIALOG (window));
9384
9385       gtk_window_set_title (GTK_WINDOW (window), "Idle Test");
9386       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
9387
9388       label = gtk_label_new ("count: 0");
9389       gtk_misc_set_padding (GTK_MISC (label), 10, 10);
9390       gtk_widget_show (label);
9391       
9392       container =
9393         g_object_new (GTK_TYPE_HBOX,
9394                         "visible", TRUE,
9395                         /* "GtkContainer::child", g_object_new (GTK_TYPE_HBOX,
9396                          * "GtkWidget::visible", TRUE,
9397                          */
9398                          "child", label,
9399                         /* NULL), */
9400                         NULL);
9401       gtk_box_pack_start (GTK_BOX (content_area), container, TRUE, TRUE, 0);
9402
9403       frame =
9404         g_object_new (GTK_TYPE_FRAME,
9405                         "border_width", 5,
9406                         "label", "Label Container",
9407                         "visible", TRUE,
9408                         "parent", content_area,
9409                         NULL);
9410       box =
9411         g_object_new (GTK_TYPE_VBOX,
9412                         "visible", TRUE,
9413                         "parent", frame,
9414                         NULL);
9415       button =
9416         g_object_connect (g_object_new (GTK_TYPE_RADIO_BUTTON,
9417                                           "label", "Resize-Parent",
9418                                           "user_data", (void*)GTK_RESIZE_PARENT,
9419                                           "visible", TRUE,
9420                                           "parent", box,
9421                                           NULL),
9422                           "signal::clicked", toggle_idle_container, container,
9423                           NULL);
9424       button = g_object_new (GTK_TYPE_RADIO_BUTTON,
9425                                "label", "Resize-Queue",
9426                                "user_data", (void*)GTK_RESIZE_QUEUE,
9427                                "group", button,
9428                                "visible", TRUE,
9429                                "parent", box,
9430                                NULL);
9431       g_object_connect (button,
9432                         "signal::clicked", toggle_idle_container, container,
9433                         NULL);
9434       button2 = g_object_new (GTK_TYPE_RADIO_BUTTON,
9435                                 "label", "Resize-Immediate",
9436                                 "user_data", (void*)GTK_RESIZE_IMMEDIATE,
9437                                 NULL);
9438       g_object_connect (button2,
9439                         "signal::clicked", toggle_idle_container, container,
9440                         NULL);
9441       g_object_set (button2,
9442                     "group", button,
9443                     "visible", TRUE,
9444                     "parent", box,
9445                     NULL);
9446
9447       button = gtk_button_new_with_label ("close");
9448       g_signal_connect_swapped (button, "clicked",
9449                                 G_CALLBACK (gtk_widget_destroy),
9450                                 window);
9451       gtk_widget_set_can_default (button, TRUE);
9452       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
9453       gtk_widget_grab_default (button);
9454       gtk_widget_show (button);
9455
9456       button = gtk_button_new_with_label ("start");
9457       g_signal_connect (button, "clicked",
9458                         G_CALLBACK (start_idle_test),
9459                         label);
9460       gtk_widget_set_can_default (button, TRUE);
9461       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
9462       gtk_widget_show (button);
9463
9464       button = gtk_button_new_with_label ("stop");
9465       g_signal_connect (button, "clicked",
9466                         G_CALLBACK (stop_idle_test),
9467                         NULL);
9468       gtk_widget_set_can_default (button, TRUE);
9469       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
9470       gtk_widget_show (button);
9471     }
9472
9473   if (!gtk_widget_get_visible (window))
9474     gtk_widget_show (window);
9475   else
9476     gtk_widget_destroy (window);
9477 }
9478
9479 /*
9480  * rc file test
9481  */
9482
9483 void
9484 reload_all_rc_files (void)
9485 {
9486   static GdkAtom atom_rcfiles = GDK_NONE;
9487
9488   GdkEvent *send_event = gdk_event_new (GDK_CLIENT_EVENT);
9489   int i;
9490   
9491   if (!atom_rcfiles)
9492     atom_rcfiles = gdk_atom_intern("_GTK_READ_RCFILES", FALSE);
9493
9494   for(i = 0; i < 5; i++)
9495     send_event->client.data.l[i] = 0;
9496   send_event->client.data_format = 32;
9497   send_event->client.message_type = atom_rcfiles;
9498   gdk_event_send_clientmessage_toall (send_event);
9499
9500   gdk_event_free (send_event);
9501 }
9502
9503 void
9504 create_rc_file (GtkWidget *widget)
9505 {
9506   static GtkWidget *window = NULL;
9507   GtkWidget *action_area, *content_area;
9508   GtkWidget *button;
9509   GtkWidget *frame;
9510   GtkWidget *vbox;
9511   GtkWidget *label;
9512
9513   if (!window)
9514     {
9515       window = gtk_dialog_new ();
9516
9517       gtk_window_set_screen (GTK_WINDOW (window),
9518                              gtk_widget_get_screen (widget));
9519
9520       g_signal_connect (window, "destroy",
9521                         G_CALLBACK (gtk_widget_destroyed),
9522                         &window);
9523
9524       content_area = gtk_dialog_get_content_area (GTK_DIALOG (window));
9525       action_area = gtk_dialog_get_action_area (GTK_DIALOG (window));
9526
9527       frame = gtk_aspect_frame_new ("Testing RC file prioritization", 0.5, 0.5, 0.0, TRUE);
9528       gtk_box_pack_start (GTK_BOX (content_area), frame, FALSE, FALSE, 0);
9529
9530       vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
9531       gtk_container_add (GTK_CONTAINER (frame), vbox);
9532       
9533       label = gtk_label_new ("This label should be red");
9534       gtk_widget_set_name (label, "testgtk-red-label");
9535       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
9536
9537       label = gtk_label_new ("This label should be green");
9538       gtk_widget_set_name (label, "testgtk-green-label");
9539       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
9540
9541       label = gtk_label_new ("This label should be blue");
9542       gtk_widget_set_name (label, "testgtk-blue-label");
9543       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
9544
9545       gtk_window_set_title (GTK_WINDOW (window), "Reload Rc file");
9546       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
9547
9548       button = gtk_button_new_with_label ("Reload");
9549       g_signal_connect (button, "clicked",
9550                         G_CALLBACK (gtk_rc_reparse_all), NULL);
9551       gtk_widget_set_can_default (button, TRUE);
9552       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
9553       gtk_widget_grab_default (button);
9554
9555       button = gtk_button_new_with_label ("Reload All");
9556       g_signal_connect (button, "clicked",
9557                         G_CALLBACK (reload_all_rc_files), NULL);
9558       gtk_widget_set_can_default (button, TRUE);
9559       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
9560
9561       button = gtk_button_new_with_label ("Close");
9562       g_signal_connect_swapped (button, "clicked",
9563                                 G_CALLBACK (gtk_widget_destroy),
9564                                 window);
9565       gtk_widget_set_can_default (button, TRUE);
9566       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
9567     }
9568
9569   if (!gtk_widget_get_visible (window))
9570     gtk_widget_show_all (window);
9571   else
9572     gtk_widget_destroy (window);
9573 }
9574
9575 /*
9576  * Test of recursive mainloop
9577  */
9578
9579 void
9580 mainloop_destroyed (GtkWidget *w, GtkWidget **window)
9581 {
9582   *window = NULL;
9583   gtk_main_quit ();
9584 }
9585
9586 void
9587 create_mainloop (GtkWidget *widget)
9588 {
9589   static GtkWidget *window = NULL;
9590   GtkWidget *action_area, *content_area;
9591   GtkWidget *label;
9592   GtkWidget *button;
9593
9594   if (!window)
9595     {
9596       window = gtk_dialog_new ();
9597
9598       gtk_window_set_screen (GTK_WINDOW (window),
9599                              gtk_widget_get_screen (widget));
9600
9601       gtk_window_set_title (GTK_WINDOW (window), "Test Main Loop");
9602
9603       g_signal_connect (window, "destroy",
9604                         G_CALLBACK (mainloop_destroyed),
9605                         &window);
9606
9607       content_area = gtk_dialog_get_content_area (GTK_DIALOG (window));
9608       action_area = gtk_dialog_get_action_area (GTK_DIALOG (window));
9609
9610       label = gtk_label_new ("In recursive main loop...");
9611       gtk_misc_set_padding (GTK_MISC(label), 20, 20);
9612
9613       gtk_box_pack_start (GTK_BOX (content_area), label, TRUE, TRUE, 0);
9614       gtk_widget_show (label);
9615
9616       button = gtk_button_new_with_label ("Leave");
9617       gtk_box_pack_start (GTK_BOX (action_area), button, FALSE, TRUE, 0);
9618
9619       g_signal_connect_swapped (button, "clicked",
9620                                 G_CALLBACK (gtk_widget_destroy),
9621                                 window);
9622
9623       gtk_widget_set_can_default (button, TRUE);
9624       gtk_widget_grab_default (button);
9625
9626       gtk_widget_show (button);
9627     }
9628
9629   if (!gtk_widget_get_visible (window))
9630     {
9631       gtk_widget_show (window);
9632
9633       g_print ("create_mainloop: start\n");
9634       gtk_main ();
9635       g_print ("create_mainloop: done\n");
9636     }
9637   else
9638     gtk_widget_destroy (window);
9639 }
9640
9641 static gboolean
9642 layout_draw_handler (GtkWidget *widget, cairo_t *cr)
9643 {
9644   GtkLayout *layout;
9645   GdkWindow *bin_window;
9646   GdkRectangle clip;
9647   gint i,j,x,y;
9648   gint imin, imax, jmin, jmax;
9649
9650   layout = GTK_LAYOUT (widget);
9651   bin_window = gtk_layout_get_bin_window (layout);
9652
9653   if (!gtk_cairo_should_draw_window (cr, bin_window))
9654     return FALSE;
9655   
9656   gdk_window_get_position (bin_window, &x, &y);
9657   cairo_translate (cr, x, y);
9658
9659   gdk_cairo_get_clip_rectangle (cr, &clip);
9660
9661   imin = (clip.x) / 10;
9662   imax = (clip.x + clip.width + 9) / 10;
9663
9664   jmin = (clip.y) / 10;
9665   jmax = (clip.y + clip.height + 9) / 10;
9666
9667   for (i=imin; i<imax; i++)
9668     for (j=jmin; j<jmax; j++)
9669       if ((i+j) % 2)
9670         cairo_rectangle (cr,
9671                          10*i, 10*j, 
9672                          1+i%10, 1+j%10);
9673   
9674   cairo_fill (cr);
9675
9676   return FALSE;
9677 }
9678
9679 void create_layout (GtkWidget *widget)
9680 {
9681   GtkAdjustment *hadjustment, *vadjustment;
9682   GtkLayout *layout;
9683   static GtkWidget *window = NULL;
9684   GtkWidget *layout_widget;
9685   GtkWidget *scrolledwindow;
9686   GtkWidget *button;
9687
9688   if (!window)
9689     {
9690       gchar buf[16];
9691
9692       gint i, j;
9693       
9694       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9695       gtk_window_set_screen (GTK_WINDOW (window),
9696                              gtk_widget_get_screen (widget));
9697
9698       g_signal_connect (window, "destroy",
9699                         G_CALLBACK (gtk_widget_destroyed),
9700                         &window);
9701
9702       gtk_window_set_title (GTK_WINDOW (window), "Layout");
9703       gtk_widget_set_size_request (window, 200, 200);
9704
9705       scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
9706       gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolledwindow),
9707                                            GTK_SHADOW_IN);
9708       gtk_scrolled_window_set_placement (GTK_SCROLLED_WINDOW (scrolledwindow),
9709                                          GTK_CORNER_TOP_RIGHT);
9710
9711       gtk_container_add (GTK_CONTAINER (window), scrolledwindow);
9712
9713       layout_widget = gtk_layout_new (NULL, NULL);
9714       layout = GTK_LAYOUT (layout_widget);
9715       gtk_container_add (GTK_CONTAINER (scrolledwindow), layout_widget);
9716
9717       /* We set step sizes here since GtkLayout does not set
9718        * them itself.
9719        */
9720       hadjustment = gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (layout));
9721       vadjustment = gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (layout));
9722       gtk_adjustment_set_step_increment (hadjustment, 10.0);
9723       gtk_adjustment_set_step_increment (vadjustment, 10.0);
9724       gtk_scrollable_set_hadjustment (GTK_SCROLLABLE (layout), hadjustment);
9725       gtk_scrollable_set_vadjustment (GTK_SCROLLABLE (layout), vadjustment);
9726
9727       gtk_widget_set_events (layout_widget, GDK_EXPOSURE_MASK);
9728       g_signal_connect (layout, "draw",
9729                         G_CALLBACK (layout_draw_handler), NULL);
9730
9731       gtk_layout_set_size (layout, 1600, 128000);
9732
9733       for (i=0 ; i < 16 ; i++)
9734         for (j=0 ; j < 16 ; j++)
9735           {
9736             sprintf(buf, "Button %d, %d", i, j);
9737             if ((i + j) % 2)
9738               button = gtk_button_new_with_label (buf);
9739             else
9740               button = gtk_label_new (buf);
9741
9742             gtk_layout_put (layout, button, j*100, i*100);
9743           }
9744
9745       for (i=16; i < 1280; i++)
9746         {
9747           sprintf(buf, "Button %d, %d", i, 0);
9748           if (i % 2)
9749             button = gtk_button_new_with_label (buf);
9750           else
9751             button = gtk_label_new (buf);
9752
9753           gtk_layout_put (layout, button, 0, i*100);
9754         }
9755     }
9756
9757   if (!gtk_widget_get_visible (window))
9758     gtk_widget_show_all (window);
9759   else
9760     gtk_widget_destroy (window);
9761 }
9762
9763 void
9764 create_styles (GtkWidget *widget)
9765 {
9766   static GtkWidget *window = NULL;
9767   GtkWidget *content_area, *action_area;
9768   GtkWidget *label;
9769   GtkWidget *button;
9770   GtkWidget *entry;
9771   GtkWidget *vbox;
9772   static GdkColor red =    { 0, 0xffff, 0,      0      };
9773   static GdkColor green =  { 0, 0,      0xffff, 0      };
9774   static GdkColor blue =   { 0, 0,      0,      0xffff };
9775   static GdkColor yellow = { 0, 0xffff, 0xffff, 0      };
9776   static GdkColor cyan =   { 0, 0     , 0xffff, 0xffff };
9777   PangoFontDescription *font_desc;
9778
9779   GtkRcStyle *rc_style;
9780
9781   if (!window)
9782     {
9783       window = gtk_dialog_new ();
9784       gtk_window_set_screen (GTK_WINDOW (window),
9785                              gtk_widget_get_screen (widget));
9786      
9787       g_signal_connect (window, "destroy",
9788                         G_CALLBACK (gtk_widget_destroyed),
9789                         &window);
9790
9791       content_area = gtk_dialog_get_content_area (GTK_DIALOG (window));
9792       action_area = gtk_dialog_get_action_area (GTK_DIALOG (window));
9793
9794       button = gtk_button_new_with_label ("Close");
9795       g_signal_connect_swapped (button, "clicked",
9796                                 G_CALLBACK (gtk_widget_destroy),
9797                                 window);
9798       gtk_widget_set_can_default (button, TRUE);
9799       gtk_box_pack_start (GTK_BOX (action_area), button, TRUE, TRUE, 0);
9800       gtk_widget_show (button);
9801
9802       vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
9803       gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
9804       gtk_box_pack_start (GTK_BOX (content_area), vbox, FALSE, FALSE, 0);
9805       
9806       label = gtk_label_new ("Font:");
9807       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
9808       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
9809
9810       font_desc = pango_font_description_from_string ("Helvetica,Sans Oblique 18");
9811
9812       button = gtk_button_new_with_label ("Some Text");
9813       gtk_widget_modify_font (gtk_bin_get_child (GTK_BIN (button)),
9814                               font_desc);
9815       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
9816
9817       label = gtk_label_new ("Foreground:");
9818       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
9819       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
9820
9821       button = gtk_button_new_with_label ("Some Text");
9822       gtk_widget_modify_fg (gtk_bin_get_child (GTK_BIN (button)),
9823                             GTK_STATE_NORMAL, &red);
9824       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
9825
9826       label = gtk_label_new ("Background:");
9827       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
9828       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
9829
9830       button = gtk_button_new_with_label ("Some Text");
9831       gtk_widget_modify_bg (button, GTK_STATE_NORMAL, &green);
9832       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
9833
9834       label = gtk_label_new ("Text:");
9835       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
9836       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
9837
9838       entry = gtk_entry_new ();
9839       gtk_entry_set_text (GTK_ENTRY (entry), "Some Text");
9840       gtk_widget_modify_text (entry, GTK_STATE_NORMAL, &blue);
9841       gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
9842
9843       label = gtk_label_new ("Base:");
9844       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
9845       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
9846
9847       entry = gtk_entry_new ();
9848       gtk_entry_set_text (GTK_ENTRY (entry), "Some Text");
9849       gtk_widget_modify_base (entry, GTK_STATE_NORMAL, &yellow);
9850       gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
9851
9852       label = gtk_label_new ("Cursor:");
9853       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
9854       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
9855
9856       entry = gtk_entry_new ();
9857       gtk_entry_set_text (GTK_ENTRY (entry), "Some Text");
9858       gtk_widget_modify_cursor (entry, &red, &red);
9859       gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
9860
9861       label = gtk_label_new ("Multiple:");
9862       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
9863       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
9864
9865       button = gtk_button_new_with_label ("Some Text");
9866
9867       rc_style = gtk_rc_style_new ();
9868
9869       rc_style->font_desc = pango_font_description_copy (font_desc);
9870       rc_style->color_flags[GTK_STATE_NORMAL] = GTK_RC_FG | GTK_RC_BG;
9871       rc_style->color_flags[GTK_STATE_PRELIGHT] = GTK_RC_FG | GTK_RC_BG;
9872       rc_style->color_flags[GTK_STATE_ACTIVE] = GTK_RC_FG | GTK_RC_BG;
9873       rc_style->fg[GTK_STATE_NORMAL] = yellow;
9874       rc_style->bg[GTK_STATE_NORMAL] = blue;
9875       rc_style->fg[GTK_STATE_PRELIGHT] = blue;
9876       rc_style->bg[GTK_STATE_PRELIGHT] = yellow;
9877       rc_style->fg[GTK_STATE_ACTIVE] = red;
9878       rc_style->bg[GTK_STATE_ACTIVE] = cyan;
9879       rc_style->xthickness = 5;
9880       rc_style->ythickness = 5;
9881
9882       gtk_widget_modify_style (button, rc_style);
9883       gtk_widget_modify_style (gtk_bin_get_child (GTK_BIN (button)), rc_style);
9884
9885       g_object_unref (rc_style);
9886       
9887       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
9888     }
9889   
9890   if (!gtk_widget_get_visible (window))
9891     gtk_widget_show_all (window);
9892   else
9893     gtk_widget_destroy (window);
9894 }
9895
9896 /*
9897  * Main Window and Exit
9898  */
9899
9900 void
9901 do_exit (GtkWidget *widget, GtkWidget *window)
9902 {
9903   gtk_widget_destroy (window);
9904   gtk_main_quit ();
9905 }
9906
9907 struct {
9908   char *label;
9909   void (*func) (GtkWidget *widget);
9910   gboolean do_not_benchmark;
9911 } buttons[] =
9912 {
9913   { "alpha window", create_alpha_window },
9914   { "big windows", create_big_windows },
9915   { "button box", create_button_box },
9916   { "buttons", create_buttons },
9917   { "check buttons", create_check_buttons },
9918   { "color selection", create_color_selection },
9919   { "composited window", create_composited_window },
9920   { "cursors", create_cursors },
9921   { "dialog", create_dialog },
9922   { "display & screen", create_display_screen, TRUE },
9923   { "entry", create_entry },
9924   { "event box", create_event_box },
9925   { "event watcher", create_event_watcher },
9926   { "expander", create_expander },
9927   { "flipping", create_flipping },
9928   { "focus", create_focus },
9929   { "font selection", create_font_selection },
9930   { "handle box", create_handle_box },
9931   { "image", create_image },
9932   { "key lookup", create_key_lookup },
9933   { "labels", create_labels },
9934   { "layout", create_layout },
9935   { "menus", create_menus },
9936   { "message dialog", create_message_dialog },
9937   { "modal window", create_modal_window, TRUE },
9938   { "notebook", create_notebook },
9939   { "panes", create_panes },
9940   { "paned keyboard", create_paned_keyboard_navigation },
9941   { "pixbuf", create_pixbuf },
9942   { "progress bar", create_progress_bar },
9943   { "properties", create_properties },
9944   { "radio buttons", create_radio_buttons },
9945   { "range controls", create_range_controls },
9946   { "rc file", create_rc_file },
9947   { "reparent", create_reparent },
9948   { "resize grips", create_resize_grips },
9949   { "rotated label", create_rotated_label },
9950   { "rotated text", create_rotated_text },
9951   { "saved position", create_saved_position },
9952   { "scrolled windows", create_scrolled_windows },
9953   { "shapes", create_shapes },
9954   { "size groups", create_size_groups },
9955   { "snapshot", create_snapshot },
9956   { "spinbutton", create_spins },
9957   { "statusbar", create_statusbar },
9958   { "styles", create_styles },
9959   { "test idle", create_idle_test },
9960   { "test mainloop", create_mainloop, TRUE },
9961   { "test scrolling", create_scroll_test },
9962   { "test selection", create_selection_test },
9963   { "test timeout", create_timeout_test },
9964   { "toggle buttons", create_toggle_buttons },
9965   { "toolbar", create_toolbar },
9966   { "tooltips", create_tooltips },
9967   { "WM hints", create_wmhints },
9968   { "window sizing", create_window_sizing },
9969   { "window states", create_window_states }
9970 };
9971 int nbuttons = sizeof (buttons) / sizeof (buttons[0]);
9972
9973 void
9974 create_main_window (void)
9975 {
9976   GtkWidget *window;
9977   GtkWidget *box1;
9978   GtkWidget *box2;
9979   GtkWidget *scrolled_window;
9980   GtkWidget *button;
9981   GtkWidget *label;
9982   gchar buffer[64];
9983   GtkWidget *separator;
9984   GdkGeometry geometry;
9985   int i;
9986
9987   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9988   gtk_widget_set_name (window, "main_window");
9989   gtk_window_move (GTK_WINDOW (window), 50, 20);
9990   gtk_window_set_default_size (GTK_WINDOW (window), -1, 400);
9991
9992   geometry.min_width = -1;
9993   geometry.min_height = -1;
9994   geometry.max_width = -1;
9995   geometry.max_height = G_MAXSHORT;
9996   gtk_window_set_geometry_hints (GTK_WINDOW (window), NULL,
9997                                  &geometry,
9998                                  GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE);
9999
10000   g_signal_connect (window, "destroy",
10001                     G_CALLBACK (gtk_main_quit),
10002                     NULL);
10003   g_signal_connect (window, "delete-event",
10004                     G_CALLBACK (gtk_false),
10005                     NULL);
10006
10007   box1 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
10008   gtk_container_add (GTK_CONTAINER (window), box1);
10009
10010   if (gtk_micro_version > 0)
10011     sprintf (buffer,
10012              "Gtk+ v%d.%d.%d",
10013              gtk_get_major_version (),
10014              gtk_get_minor_version (),
10015              gtk_get_micro_version ());
10016   else
10017     sprintf (buffer,
10018              "Gtk+ v%d.%d",
10019              gtk_get_major_version (),
10020              gtk_get_minor_version ());
10021
10022   label = gtk_label_new (buffer);
10023   gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);
10024   gtk_widget_set_name (label, "testgtk-version-label");
10025
10026   scrolled_window = gtk_scrolled_window_new (NULL, NULL);
10027   gtk_container_set_border_width (GTK_CONTAINER (scrolled_window), 10);
10028   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
10029                                   GTK_POLICY_NEVER, 
10030                                   GTK_POLICY_AUTOMATIC);
10031   gtk_box_pack_start (GTK_BOX (box1), scrolled_window, TRUE, TRUE, 0);
10032
10033   box2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
10034   gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
10035   gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_window), box2);
10036   gtk_container_set_focus_vadjustment (GTK_CONTAINER (box2),
10037                                        gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (scrolled_window)));
10038   gtk_widget_show (box2);
10039
10040   for (i = 0; i < nbuttons; i++)
10041     {
10042       button = gtk_button_new_with_label (buttons[i].label);
10043       if (buttons[i].func)
10044         g_signal_connect (button, 
10045                           "clicked", 
10046                           G_CALLBACK(buttons[i].func),
10047                           NULL);
10048       else
10049         gtk_widget_set_sensitive (button, FALSE);
10050       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
10051     }
10052
10053   separator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
10054   gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
10055
10056   box2 = gtk_box_new (GTK_ORIENTATION_VERTICAL, 10);
10057   gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
10058   gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
10059
10060   button = gtk_button_new_with_mnemonic ("_Close");
10061   g_signal_connect (button, "clicked",
10062                     G_CALLBACK (do_exit),
10063                     window);
10064   gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
10065   gtk_widget_set_can_default (button, TRUE);
10066   gtk_widget_grab_default (button);
10067
10068   gtk_widget_show_all (window);
10069 }
10070
10071 static void
10072 test_init (void)
10073 {
10074   if (g_file_test ("../gdk-pixbuf/libpixbufloader-pnm.la",
10075                    G_FILE_TEST_EXISTS))
10076     {
10077       g_setenv ("GDK_PIXBUF_MODULE_FILE", "../gdk-pixbuf/loaders.cache", TRUE);
10078       g_setenv ("GTK_IM_MODULE_FILE", "../modules/input/immodules.cache", TRUE);
10079     }
10080 }
10081
10082 static char *
10083 pad (const char *str, int to)
10084 {
10085   static char buf[256];
10086   int len = strlen (str);
10087   int i;
10088
10089   for (i = 0; i < to; i++)
10090     buf[i] = ' ';
10091
10092   buf[to] = '\0';
10093
10094   memcpy (buf, str, len);
10095
10096   return buf;
10097 }
10098
10099 static void
10100 bench_iteration (GtkWidget *widget, void (* fn) (GtkWidget *widget))
10101 {
10102   fn (widget); /* on */
10103   while (g_main_context_iteration (NULL, FALSE));
10104   fn (widget); /* off */
10105   while (g_main_context_iteration (NULL, FALSE));
10106 }
10107
10108 void
10109 do_real_bench (GtkWidget *widget, void (* fn) (GtkWidget *widget), char *name, int num)
10110 {
10111   GTimeVal tv0, tv1;
10112   double dt_first;
10113   double dt;
10114   int n;
10115   static gboolean printed_headers = FALSE;
10116
10117   if (!printed_headers) {
10118     g_print ("Test                 Iters      First      Other\n");
10119     g_print ("-------------------- ----- ---------- ----------\n");
10120     printed_headers = TRUE;
10121   }
10122
10123   g_get_current_time (&tv0);
10124   bench_iteration (widget, fn); 
10125   g_get_current_time (&tv1);
10126
10127   dt_first = ((double)tv1.tv_sec - tv0.tv_sec) * 1000.0
10128         + (tv1.tv_usec - tv0.tv_usec) / 1000.0;
10129
10130   g_get_current_time (&tv0);
10131   for (n = 0; n < num - 1; n++)
10132     bench_iteration (widget, fn); 
10133   g_get_current_time (&tv1);
10134   dt = ((double)tv1.tv_sec - tv0.tv_sec) * 1000.0
10135         + (tv1.tv_usec - tv0.tv_usec) / 1000.0;
10136
10137   g_print ("%s %5d ", pad (name, 20), num);
10138   if (num > 1)
10139     g_print ("%10.1f %10.1f\n", dt_first, dt/(num-1));
10140   else
10141     g_print ("%10.1f\n", dt_first);
10142 }
10143
10144 void
10145 do_bench (char* what, int num)
10146 {
10147   int i;
10148   GtkWidget *widget;
10149   void (* fn) (GtkWidget *widget);
10150   fn = NULL;
10151   widget = gtk_window_new (GTK_WINDOW_TOPLEVEL);
10152
10153   if (g_ascii_strcasecmp (what, "ALL") == 0)
10154     {
10155       for (i = 0; i < nbuttons; i++)
10156         {
10157           if (!buttons[i].do_not_benchmark)
10158             do_real_bench (widget, buttons[i].func, buttons[i].label, num);
10159         }
10160
10161       return;
10162     }
10163   else
10164     {
10165       for (i = 0; i < nbuttons; i++)
10166         {
10167           if (strcmp (buttons[i].label, what) == 0)
10168             {
10169               fn = buttons[i].func;
10170               break;
10171             }
10172         }
10173       
10174       if (!fn)
10175         g_print ("Can't bench: \"%s\" not found.\n", what);
10176       else
10177         do_real_bench (widget, fn, buttons[i].label, num);
10178     }
10179 }
10180
10181 void 
10182 usage (void)
10183 {
10184   fprintf (stderr, "Usage: testgtk [--bench ALL|<bench>[:<count>]]\n");
10185   exit (1);
10186 }
10187
10188 int
10189 main (int argc, char *argv[])
10190 {
10191   GtkCssProvider *provider, *memory_provider;
10192   GdkDisplay *display;
10193   GdkScreen *screen;
10194   GtkBindingSet *binding_set;
10195   int i;
10196   gboolean done_benchmarks = FALSE;
10197
10198   srand (time (NULL));
10199
10200   test_init ();
10201
10202   g_set_application_name ("GTK+ Test Program");
10203
10204   gtk_init (&argc, &argv);
10205
10206   provider = gtk_css_provider_new ();
10207
10208   /* Check to see if we are being run from the correct
10209    * directory.
10210    */
10211   if (file_exists ("testgtk.css"))
10212     gtk_css_provider_load_from_path (provider, "testgtk.css", NULL);
10213   else if (file_exists ("tests/testgtkrc"))
10214     gtk_css_provider_load_from_path (provider, "tests/testgtk.css", NULL);
10215   else
10216     g_warning ("Couldn't find file \"testgtk.css\".");
10217
10218   display = gdk_display_get_default ();
10219   screen = gdk_display_get_default_screen (display);
10220
10221   gtk_style_context_add_provider_for_screen (screen, GTK_STYLE_PROVIDER (provider),
10222                                              GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
10223   g_object_unref (provider);
10224
10225   gtk_accelerator_set_default_mod_mask (GDK_SHIFT_MASK |
10226                                         GDK_CONTROL_MASK |
10227                                         GDK_MOD1_MASK | 
10228                                         GDK_META_MASK |
10229                                         GDK_SUPER_MASK |
10230                                         GDK_HYPER_MASK |
10231                                         GDK_MOD4_MASK);
10232   /*  benchmarking
10233    */
10234   for (i = 1; i < argc; i++)
10235     {
10236       if (strncmp (argv[i], "--bench", strlen("--bench")) == 0)
10237         {
10238           int num = 1;
10239           char *nextarg;
10240           char *what;
10241           char *count;
10242           
10243           nextarg = strchr (argv[i], '=');
10244           if (nextarg)
10245             nextarg++;
10246           else
10247             {
10248               i++;
10249               if (i == argc)
10250                 usage ();
10251               nextarg = argv[i];
10252             }
10253
10254           count = strchr (nextarg, ':');
10255           if (count)
10256             {
10257               what = g_strndup (nextarg, count - nextarg);
10258               count++;
10259               num = atoi (count);
10260               if (num <= 0)
10261                 usage ();
10262             }
10263           else
10264             what = g_strdup (nextarg);
10265
10266           do_bench (what, num ? num : 1);
10267           done_benchmarks = TRUE;
10268         }
10269       else
10270         usage ();
10271     }
10272   if (done_benchmarks)
10273     return 0;
10274
10275   /* bindings test
10276    */
10277   binding_set = gtk_binding_set_by_class (g_type_class_ref (GTK_TYPE_WIDGET));
10278   gtk_binding_entry_add_signal (binding_set,
10279                                 '9', GDK_CONTROL_MASK | GDK_RELEASE_MASK,
10280                                 "debug_msg",
10281                                 1,
10282                                 G_TYPE_STRING, "GtkWidgetClass <ctrl><release>9 test");
10283
10284   memory_provider = gtk_css_provider_new ();
10285   gtk_css_provider_load_from_data (memory_provider,
10286                                    "#testgtk-version-label {\n"
10287                                    "  color: #f00;\n"
10288                                    "  font: Sans 18;\n"
10289                                    "}",
10290                                    -1, NULL);
10291   gtk_style_context_add_provider_for_screen (screen, GTK_STYLE_PROVIDER (memory_provider),
10292                                              GTK_STYLE_PROVIDER_PRIORITY_APPLICATION + 1);
10293
10294   create_main_window ();
10295
10296   gtk_main ();
10297
10298   if (1)
10299     {
10300       while (g_main_context_pending (NULL))
10301         g_main_context_iteration (NULL, FALSE);
10302 #if 0
10303       sleep (1);
10304       while (g_main_context_pending (NULL))
10305         g_main_context_iteration (NULL, FALSE);
10306 #endif
10307     }
10308   return 0;
10309 }