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