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