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