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