]> Pileus Git - ~andy/gtk/blob - tests/testgtk.c
Deprecate widget flag: GTK_WIDGET_MAPPED
[~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_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_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_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_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  * GtkList
6404  */
6405
6406 static void
6407 list_add (GtkWidget *widget,
6408           GtkWidget *list)
6409 {
6410   static int i = 1;
6411   gchar buffer[64];
6412   GtkWidget *list_item;
6413   GtkContainer *container;
6414
6415   container = GTK_CONTAINER (list);
6416
6417   sprintf (buffer, "added item %d", i++);
6418   list_item = gtk_list_item_new_with_label (buffer);
6419   gtk_widget_show (list_item);
6420
6421   gtk_container_add (container, list_item);
6422 }
6423
6424 static void
6425 list_remove (GtkWidget *widget,
6426              GtkList   *list)
6427 {
6428   GList *clear_list = NULL;
6429   GList *sel_row = NULL;
6430   GList *work = NULL;
6431
6432   if (list->selection_mode == GTK_SELECTION_EXTENDED)
6433     {
6434       GtkWidget *item;
6435
6436       item = GTK_CONTAINER (list)->focus_child;
6437       if (!item && list->selection)
6438         item = list->selection->data;
6439
6440       if (item)
6441         {
6442           work = g_list_find (list->children, item);
6443           for (sel_row = work; sel_row; sel_row = sel_row->next)
6444             if (GTK_WIDGET (sel_row->data)->state != GTK_STATE_SELECTED)
6445               break;
6446
6447           if (!sel_row)
6448             {
6449               for (sel_row = work; sel_row; sel_row = sel_row->prev)
6450                 if (GTK_WIDGET (sel_row->data)->state != GTK_STATE_SELECTED)
6451                   break;
6452             }
6453         }
6454     }
6455
6456   for (work = list->selection; work; work = work->next)
6457     clear_list = g_list_prepend (clear_list, work->data);
6458
6459   clear_list = g_list_reverse (clear_list);
6460   gtk_list_remove_items (GTK_LIST (list), clear_list);
6461   g_list_free (clear_list);
6462
6463   if (list->selection_mode == GTK_SELECTION_EXTENDED && sel_row)
6464     gtk_list_select_child (list, GTK_WIDGET(sel_row->data));
6465 }
6466
6467 static void
6468 list_clear (GtkWidget *widget,
6469             GtkWidget *list)
6470 {
6471   gtk_list_clear_items (GTK_LIST (list), 0, -1);
6472 }
6473
6474 static gchar *selection_mode_items[] =
6475 {
6476   "Single",
6477   "Browse",
6478   "Multiple"
6479 };
6480
6481 static const GtkSelectionMode selection_modes[] = {
6482   GTK_SELECTION_SINGLE,
6483   GTK_SELECTION_BROWSE,
6484   GTK_SELECTION_MULTIPLE
6485 };
6486
6487 static GtkWidget *list_omenu;
6488
6489 static void 
6490 list_toggle_sel_mode (GtkWidget *widget, gpointer data)
6491 {
6492   GtkList *list;
6493   gint i;
6494
6495   list = GTK_LIST (data);
6496
6497   if (!gtk_widget_get_mapped (widget))
6498     return;
6499
6500   i = gtk_option_menu_get_history (GTK_OPTION_MENU (widget));
6501
6502   gtk_list_set_selection_mode (list, selection_modes[i]);
6503 }
6504
6505 static void
6506 create_list (GtkWidget *widget)
6507 {
6508   static GtkWidget *window = NULL;
6509
6510   if (!window)
6511     {
6512       GtkWidget *cbox;
6513       GtkWidget *vbox;
6514       GtkWidget *hbox;
6515       GtkWidget *label;
6516       GtkWidget *scrolled_win;
6517       GtkWidget *list;
6518       GtkWidget *button;
6519       GtkWidget *separator;
6520       FILE *infile;
6521
6522       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6523
6524       gtk_window_set_screen (GTK_WINDOW (window),
6525                              gtk_widget_get_screen (widget));
6526
6527       g_signal_connect (window, "destroy",
6528                         G_CALLBACK (gtk_widget_destroyed),
6529                         &window);
6530
6531       gtk_window_set_title (GTK_WINDOW (window), "list");
6532       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
6533
6534       vbox = gtk_vbox_new (FALSE, 0);
6535       gtk_container_add (GTK_CONTAINER (window), vbox);
6536
6537       scrolled_win = gtk_scrolled_window_new (NULL, NULL);
6538       gtk_container_set_border_width (GTK_CONTAINER (scrolled_win), 5);
6539       gtk_widget_set_size_request (scrolled_win, -1, 300);
6540       gtk_box_pack_start (GTK_BOX (vbox), scrolled_win, TRUE, TRUE, 0);
6541       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
6542                                       GTK_POLICY_AUTOMATIC,
6543                                       GTK_POLICY_AUTOMATIC);
6544
6545       list = gtk_list_new ();
6546       gtk_list_set_selection_mode (GTK_LIST (list), GTK_SELECTION_SINGLE);
6547       gtk_scrolled_window_add_with_viewport
6548         (GTK_SCROLLED_WINDOW (scrolled_win), list);
6549       gtk_container_set_focus_vadjustment
6550         (GTK_CONTAINER (list),
6551          gtk_scrolled_window_get_vadjustment
6552          (GTK_SCROLLED_WINDOW (scrolled_win)));
6553       gtk_container_set_focus_hadjustment
6554         (GTK_CONTAINER (list),
6555          gtk_scrolled_window_get_hadjustment
6556          (GTK_SCROLLED_WINDOW (scrolled_win)));
6557
6558       if ((infile = fopen("../gtk/gtkenums.h", "r")))
6559         {
6560           char buffer[256];
6561           char *pos;
6562           GtkWidget *item;
6563
6564           while (fgets (buffer, 256, infile))
6565             {
6566               if ((pos = strchr (buffer, '\n')))
6567                 *pos = 0;
6568               item = gtk_list_item_new_with_label (buffer);
6569               gtk_container_add (GTK_CONTAINER (list), item);
6570             }
6571           
6572           fclose (infile);
6573         }
6574
6575
6576       hbox = gtk_hbox_new (TRUE, 5);
6577       gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
6578       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
6579
6580       button = gtk_button_new_with_label ("Insert Row");
6581       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
6582       g_signal_connect (button, "clicked",
6583                         G_CALLBACK (list_add),
6584                         list);
6585
6586       button = gtk_button_new_with_label ("Clear List");
6587       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
6588       g_signal_connect (button, "clicked",
6589                         G_CALLBACK (list_clear),
6590                         list);
6591
6592       button = gtk_button_new_with_label ("Remove Selection");
6593       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
6594       g_signal_connect (button, "clicked",
6595                         G_CALLBACK (list_remove),
6596                         list);
6597
6598       cbox = gtk_hbox_new (FALSE, 0);
6599       gtk_box_pack_start (GTK_BOX (vbox), cbox, FALSE, TRUE, 0);
6600
6601       hbox = gtk_hbox_new (FALSE, 5);
6602       gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
6603       gtk_box_pack_start (GTK_BOX (cbox), hbox, TRUE, FALSE, 0);
6604
6605       label = gtk_label_new ("Selection Mode :");
6606       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
6607
6608       list_omenu = build_option_menu (selection_mode_items, 3, 3, 
6609                                       list_toggle_sel_mode,
6610                                       list);
6611       gtk_box_pack_start (GTK_BOX (hbox), list_omenu, FALSE, TRUE, 0);
6612
6613       separator = gtk_hseparator_new ();
6614       gtk_box_pack_start (GTK_BOX (vbox), separator, FALSE, TRUE, 0);
6615
6616       cbox = gtk_hbox_new (FALSE, 0);
6617       gtk_box_pack_start (GTK_BOX (vbox), cbox, FALSE, TRUE, 0);
6618
6619       button = gtk_button_new_with_label ("close");
6620       gtk_container_set_border_width (GTK_CONTAINER (button), 10);
6621       gtk_box_pack_start (GTK_BOX (cbox), button, TRUE, TRUE, 0);
6622       g_signal_connect_swapped (button, "clicked",
6623                                 G_CALLBACK (gtk_widget_destroy),
6624                                 window);
6625
6626       gtk_widget_set_can_default (button, TRUE);
6627       gtk_widget_grab_default (button);
6628     }
6629
6630   if (!gtk_widget_get_visible (window))
6631     gtk_widget_show_all (window);
6632   else
6633     gtk_widget_destroy (window);
6634 }
6635
6636 /*
6637  * GtkCList
6638  */
6639
6640 static char * book_open_xpm[] = {
6641 "16 16 4 1",
6642 "       c None s None",
6643 ".      c black",
6644 "X      c #808080",
6645 "o      c white",
6646 "                ",
6647 "  ..            ",
6648 " .Xo.    ...    ",
6649 " .Xoo. ..oo.    ",
6650 " .Xooo.Xooo...  ",
6651 " .Xooo.oooo.X.  ",
6652 " .Xooo.Xooo.X.  ",
6653 " .Xooo.oooo.X.  ",
6654 " .Xooo.Xooo.X.  ",
6655 " .Xooo.oooo.X.  ",
6656 "  .Xoo.Xoo..X.  ",
6657 "   .Xo.o..ooX.  ",
6658 "    .X..XXXXX.  ",
6659 "    ..X.......  ",
6660 "     ..         ",
6661 "                "};
6662
6663 static char * book_closed_xpm[] = {
6664 "16 16 6 1",
6665 "       c None s None",
6666 ".      c black",
6667 "X      c red",
6668 "o      c yellow",
6669 "O      c #808080",
6670 "#      c white",
6671 "                ",
6672 "       ..       ",
6673 "     ..XX.      ",
6674 "   ..XXXXX.     ",
6675 " ..XXXXXXXX.    ",
6676 ".ooXXXXXXXXX.   ",
6677 "..ooXXXXXXXXX.  ",
6678 ".X.ooXXXXXXXXX. ",
6679 ".XX.ooXXXXXX..  ",
6680 " .XX.ooXXX..#O  ",
6681 "  .XX.oo..##OO. ",
6682 "   .XX..##OO..  ",
6683 "    .X.#OO..    ",
6684 "     ..O..      ",
6685 "      ..        ",
6686 "                "};
6687
6688 static char * mini_page_xpm[] = {
6689 "16 16 4 1",
6690 "       c None s None",
6691 ".      c black",
6692 "X      c white",
6693 "o      c #808080",
6694 "                ",
6695 "   .......      ",
6696 "   .XXXXX..     ",
6697 "   .XoooX.X.    ",
6698 "   .XXXXX....   ",
6699 "   .XooooXoo.o  ",
6700 "   .XXXXXXXX.o  ",
6701 "   .XooooooX.o  ",
6702 "   .XXXXXXXX.o  ",
6703 "   .XooooooX.o  ",
6704 "   .XXXXXXXX.o  ",
6705 "   .XooooooX.o  ",
6706 "   .XXXXXXXX.o  ",
6707 "   ..........o  ",
6708 "    oooooooooo  ",
6709 "                "};
6710
6711 static char * gtk_mini_xpm[] = {
6712 "15 20 17 1",
6713 "       c None",
6714 ".      c #14121F",
6715 "+      c #278828",
6716 "@      c #9B3334",
6717 "#      c #284C72",
6718 "$      c #24692A",
6719 "%      c #69282E",
6720 "&      c #37C539",
6721 "*      c #1D2F4D",
6722 "=      c #6D7076",
6723 "-      c #7D8482",
6724 ";      c #E24A49",
6725 ">      c #515357",
6726 ",      c #9B9C9B",
6727 "'      c #2FA232",
6728 ")      c #3CE23D",
6729 "!      c #3B6CCB",
6730 "               ",
6731 "      ***>     ",
6732 "    >.*!!!*    ",
6733 "   ***....#*=  ",
6734 "  *!*.!!!**!!# ",
6735 " .!!#*!#*!!!!# ",
6736 " @%#!.##.*!!$& ",
6737 " @;%*!*.#!#')) ",
6738 " @;;@%!!*$&)'' ",
6739 " @%.%@%$'&)$+' ",
6740 " @;...@$'*'*)+ ",
6741 " @;%..@$+*.')$ ",
6742 " @;%%;;$+..$)# ",
6743 " @;%%;@$$$'.$# ",
6744 " %;@@;;$$+))&* ",
6745 "  %;;;@+$&)&*  ",
6746 "   %;;@'))+>   ",
6747 "    %;@'&#     ",
6748 "     >%$$      ",
6749 "      >=       "};
6750
6751 #define TESTGTK_CLIST_COLUMNS 12
6752 static gint clist_rows = 0;
6753 static GtkWidget *clist_omenu;
6754
6755 static void
6756 add1000_clist (GtkWidget *widget, gpointer data)
6757 {
6758   gint i, row;
6759   char text[TESTGTK_CLIST_COLUMNS][50];
6760   char *texts[TESTGTK_CLIST_COLUMNS];
6761   GdkBitmap *mask;
6762   GdkPixmap *pixmap;
6763   GtkCList  *clist;
6764
6765   clist = GTK_CLIST (data);
6766
6767   pixmap = gdk_pixmap_create_from_xpm_d (clist->clist_window,
6768                                          &mask, 
6769                                          &GTK_WIDGET (data)->style->white,
6770                                          gtk_mini_xpm);
6771
6772   for (i = 0; i < TESTGTK_CLIST_COLUMNS; i++)
6773     {
6774       texts[i] = text[i];
6775       sprintf (text[i], "Column %d", i);
6776     }
6777   
6778   texts[3] = NULL;
6779   sprintf (text[1], "Right");
6780   sprintf (text[2], "Center");
6781   
6782   gtk_clist_freeze (GTK_CLIST (data));
6783   for (i = 0; i < 1000; i++)
6784     {
6785       sprintf (text[0], "CListRow %d", rand() % 10000);
6786       row = gtk_clist_append (clist, texts);
6787       gtk_clist_set_pixtext (clist, row, 3, "gtk+", 5, pixmap, mask);
6788     }
6789
6790   gtk_clist_thaw (GTK_CLIST (data));
6791
6792   g_object_unref (pixmap);
6793   g_object_unref (mask);
6794 }
6795
6796 static void
6797 add10000_clist (GtkWidget *widget, gpointer data)
6798 {
6799   gint i;
6800   char text[TESTGTK_CLIST_COLUMNS][50];
6801   char *texts[TESTGTK_CLIST_COLUMNS];
6802
6803   for (i = 0; i < TESTGTK_CLIST_COLUMNS; i++)
6804     {
6805       texts[i] = text[i];
6806       sprintf (text[i], "Column %d", i);
6807     }
6808   
6809   sprintf (text[1], "Right");
6810   sprintf (text[2], "Center");
6811   
6812   gtk_clist_freeze (GTK_CLIST (data));
6813   for (i = 0; i < 10000; i++)
6814     {
6815       sprintf (text[0], "CListRow %d", rand() % 10000);
6816       gtk_clist_append (GTK_CLIST (data), texts);
6817     }
6818   gtk_clist_thaw (GTK_CLIST (data));
6819 }
6820
6821 void
6822 clear_clist (GtkWidget *widget, gpointer data)
6823 {
6824   gtk_clist_clear (GTK_CLIST (data));
6825   clist_rows = 0;
6826 }
6827
6828 void clist_remove_selection (GtkWidget *widget, GtkCList *clist)
6829 {
6830   gtk_clist_freeze (clist);
6831
6832   while (clist->selection)
6833     {
6834       gint row;
6835
6836       clist_rows--;
6837       row = GPOINTER_TO_INT (clist->selection->data);
6838
6839       gtk_clist_remove (clist, row);
6840
6841       if (clist->selection_mode == GTK_SELECTION_BROWSE)
6842         break;
6843     }
6844
6845   if (clist->selection_mode == GTK_SELECTION_EXTENDED && !clist->selection &&
6846       clist->focus_row >= 0)
6847     gtk_clist_select_row (clist, clist->focus_row, -1);
6848
6849   gtk_clist_thaw (clist);
6850 }
6851
6852 void toggle_title_buttons (GtkWidget *widget, GtkCList *clist)
6853 {
6854   if (GTK_TOGGLE_BUTTON (widget)->active)
6855     gtk_clist_column_titles_show (clist);
6856   else
6857     gtk_clist_column_titles_hide (clist);
6858 }
6859
6860 void toggle_reorderable (GtkWidget *widget, GtkCList *clist)
6861 {
6862   gtk_clist_set_reorderable (clist, GTK_TOGGLE_BUTTON (widget)->active);
6863 }
6864
6865 static void
6866 insert_row_clist (GtkWidget *widget, gpointer data)
6867 {
6868   static char *text[] =
6869   {
6870     "This", "is an", "inserted", "row.",
6871     "This", "is an", "inserted", "row.",
6872     "This", "is an", "inserted", "row."
6873   };
6874
6875   static GtkStyle *style1 = NULL;
6876   static GtkStyle *style2 = NULL;
6877   static GtkStyle *style3 = NULL;
6878   gint row;
6879   
6880   if (GTK_CLIST (data)->focus_row >= 0)
6881     row = gtk_clist_insert (GTK_CLIST (data), GTK_CLIST (data)->focus_row,
6882                             text);
6883   else
6884     row = gtk_clist_prepend (GTK_CLIST (data), text);
6885
6886   if (!style1)
6887     {
6888       GdkColor col1 = { 0, 0, 56000, 0};
6889       GdkColor col2 = { 0, 32000, 0, 56000};
6890
6891       style1 = gtk_style_copy (GTK_WIDGET (data)->style);
6892       style1->base[GTK_STATE_NORMAL] = col1;
6893       style1->base[GTK_STATE_SELECTED] = col2;
6894
6895       style2 = gtk_style_copy (GTK_WIDGET (data)->style);
6896       style2->fg[GTK_STATE_NORMAL] = col1;
6897       style2->fg[GTK_STATE_SELECTED] = col2;
6898
6899       style3 = gtk_style_copy (GTK_WIDGET (data)->style);
6900       style3->fg[GTK_STATE_NORMAL] = col1;
6901       style3->base[GTK_STATE_NORMAL] = col2;
6902       pango_font_description_free (style3->font_desc);
6903       style3->font_desc = pango_font_description_from_string ("courier 12");
6904     }
6905
6906   gtk_clist_set_cell_style (GTK_CLIST (data), row, 3, style1);
6907   gtk_clist_set_cell_style (GTK_CLIST (data), row, 4, style2);
6908   gtk_clist_set_cell_style (GTK_CLIST (data), row, 0, style3);
6909
6910   clist_rows++;
6911 }
6912
6913 static void
6914 clist_warning_test (GtkWidget *button,
6915                     GtkWidget *clist)
6916 {
6917   GtkWidget *child;
6918   static gboolean add_remove = FALSE;
6919
6920   add_remove = !add_remove;
6921
6922   child = gtk_label_new ("Test");
6923   g_object_ref (child);
6924   gtk_object_sink (GTK_OBJECT (child));
6925
6926   if (add_remove)
6927     gtk_container_add (GTK_CONTAINER (clist), child);
6928   else
6929     {
6930       child->parent = clist;
6931       gtk_container_remove (GTK_CONTAINER (clist), child);
6932       child->parent = NULL;
6933     }
6934
6935   gtk_widget_destroy (child);
6936   g_object_unref (child);
6937 }
6938
6939 static void
6940 undo_selection (GtkWidget *button, GtkCList *clist)
6941 {
6942   gtk_clist_undo_selection (clist);
6943 }
6944
6945 static void 
6946 clist_toggle_sel_mode (GtkWidget *widget, gpointer data)
6947 {
6948   GtkCList *clist;
6949   gint i;
6950
6951   clist = GTK_CLIST (data);
6952
6953   if (!gtk_widget_get_mapped (widget))
6954     return;
6955
6956   i = gtk_option_menu_get_history (GTK_OPTION_MENU (widget));
6957
6958   gtk_clist_set_selection_mode (clist, selection_modes[i]);
6959 }
6960
6961 static void 
6962 clist_click_column (GtkCList *clist, gint column, gpointer data)
6963 {
6964   if (column == 4)
6965     gtk_clist_set_column_visibility (clist, column, FALSE);
6966   else if (column == clist->sort_column)
6967     {
6968       if (clist->sort_type == GTK_SORT_ASCENDING)
6969         clist->sort_type = GTK_SORT_DESCENDING;
6970       else
6971         clist->sort_type = GTK_SORT_ASCENDING;
6972     }
6973   else
6974     gtk_clist_set_sort_column (clist, column);
6975
6976   gtk_clist_sort (clist);
6977 }
6978
6979 static void
6980 create_clist (GtkWidget *widget)
6981 {
6982   gint i;
6983   static GtkWidget *window = NULL;
6984
6985   static char *titles[] =
6986   {
6987     "auto resize", "not resizeable", "max width 100", "min width 50",
6988     "hide column", "Title 5", "Title 6", "Title 7",
6989     "Title 8",  "Title 9",  "Title 10", "Title 11"
6990   };
6991
6992   char text[TESTGTK_CLIST_COLUMNS][50];
6993   char *texts[TESTGTK_CLIST_COLUMNS];
6994
6995   GtkWidget *vbox;
6996   GtkWidget *hbox;
6997   GtkWidget *clist;
6998   GtkWidget *button;
6999   GtkWidget *separator;
7000   GtkWidget *scrolled_win;
7001   GtkWidget *check;
7002
7003   GtkWidget *undo_button;
7004   GtkWidget *label;
7005
7006   GtkStyle *style;
7007   GdkColor red_col = { 0, 56000, 0, 0};
7008   GdkColor light_green_col = { 0, 0, 56000, 32000};
7009
7010   if (!window)
7011     {
7012       clist_rows = 0;
7013       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7014       gtk_window_set_screen (GTK_WINDOW (window), 
7015                              gtk_widget_get_screen (widget));
7016
7017       g_signal_connect (window, "destroy",
7018                         G_CALLBACK (gtk_widget_destroyed), &window);
7019
7020       gtk_window_set_title (GTK_WINDOW (window), "clist");
7021       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
7022
7023       vbox = gtk_vbox_new (FALSE, 0);
7024       gtk_container_add (GTK_CONTAINER (window), vbox);
7025
7026       scrolled_win = gtk_scrolled_window_new (NULL, NULL);
7027       gtk_container_set_border_width (GTK_CONTAINER (scrolled_win), 5);
7028       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
7029                                       GTK_POLICY_AUTOMATIC, 
7030                                       GTK_POLICY_AUTOMATIC);
7031
7032       /* create GtkCList here so we have a pointer to throw at the 
7033        * button callbacks -- more is done with it later */
7034       clist = gtk_clist_new_with_titles (TESTGTK_CLIST_COLUMNS, titles);
7035       gtk_container_add (GTK_CONTAINER (scrolled_win), clist);
7036       g_signal_connect (clist, "click_column",
7037                         G_CALLBACK (clist_click_column), NULL);
7038
7039       /* control buttons */
7040       hbox = gtk_hbox_new (FALSE, 5);
7041       gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
7042       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
7043
7044       button = gtk_button_new_with_label ("Insert Row");
7045       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
7046       g_signal_connect (button, "clicked",
7047                         G_CALLBACK (insert_row_clist), clist);
7048
7049       button = gtk_button_new_with_label ("Add 1,000 Rows With Pixmaps");
7050       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
7051       g_signal_connect (button, "clicked",
7052                         G_CALLBACK (add1000_clist), clist);
7053
7054       button = gtk_button_new_with_label ("Add 10,000 Rows");
7055       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
7056       g_signal_connect (button, "clicked",
7057                         G_CALLBACK (add10000_clist), clist);
7058
7059       /* second layer of buttons */
7060       hbox = gtk_hbox_new (FALSE, 5);
7061       gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
7062       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
7063
7064       button = gtk_button_new_with_label ("Clear List");
7065       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
7066       g_signal_connect (button, "clicked",
7067                         G_CALLBACK (clear_clist), clist);
7068
7069       button = gtk_button_new_with_label ("Remove Selection");
7070       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
7071       g_signal_connect (button, "clicked",
7072                         G_CALLBACK (clist_remove_selection), clist);
7073
7074       undo_button = gtk_button_new_with_label ("Undo Selection");
7075       gtk_box_pack_start (GTK_BOX (hbox), undo_button, TRUE, TRUE, 0);
7076       g_signal_connect (undo_button, "clicked",
7077                         G_CALLBACK (undo_selection), clist);
7078
7079       button = gtk_button_new_with_label ("Warning Test");
7080       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
7081       g_signal_connect (button, "clicked",
7082                         G_CALLBACK (clist_warning_test), clist);
7083
7084       /* third layer of buttons */
7085       hbox = gtk_hbox_new (FALSE, 5);
7086       gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
7087       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
7088
7089       check = gtk_check_button_new_with_label ("Show Title Buttons");
7090       gtk_box_pack_start (GTK_BOX (hbox), check, FALSE, TRUE, 0);
7091       g_signal_connect (check, "clicked",
7092                         G_CALLBACK (toggle_title_buttons), clist);
7093       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check), TRUE);
7094
7095       check = gtk_check_button_new_with_label ("Reorderable");
7096       gtk_box_pack_start (GTK_BOX (hbox), check, FALSE, TRUE, 0);
7097       g_signal_connect (check, "clicked",
7098                         G_CALLBACK (toggle_reorderable), clist);
7099       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check), TRUE);
7100
7101       label = gtk_label_new ("Selection Mode :");
7102       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
7103
7104       clist_omenu = build_option_menu (selection_mode_items, 3, 3, 
7105                                        clist_toggle_sel_mode,
7106                                        clist);
7107       gtk_box_pack_start (GTK_BOX (hbox), clist_omenu, FALSE, TRUE, 0);
7108
7109       /* 
7110        * the rest of the clist configuration
7111        */
7112
7113       gtk_box_pack_start (GTK_BOX (vbox), scrolled_win, TRUE, TRUE, 0);
7114       gtk_clist_set_row_height (GTK_CLIST (clist), 18);
7115       gtk_widget_set_size_request (clist, -1, 300);
7116
7117       for (i = 1; i < TESTGTK_CLIST_COLUMNS; i++)
7118         gtk_clist_set_column_width (GTK_CLIST (clist), i, 80);
7119
7120       gtk_clist_set_column_auto_resize (GTK_CLIST (clist), 0, TRUE);
7121       gtk_clist_set_column_resizeable (GTK_CLIST (clist), 1, FALSE);
7122       gtk_clist_set_column_max_width (GTK_CLIST (clist), 2, 100);
7123       gtk_clist_set_column_min_width (GTK_CLIST (clist), 3, 50);
7124       gtk_clist_set_selection_mode (GTK_CLIST (clist), GTK_SELECTION_EXTENDED);
7125       gtk_clist_set_column_justification (GTK_CLIST (clist), 1,
7126                                           GTK_JUSTIFY_RIGHT);
7127       gtk_clist_set_column_justification (GTK_CLIST (clist), 2,
7128                                           GTK_JUSTIFY_CENTER);
7129       
7130       for (i = 0; i < TESTGTK_CLIST_COLUMNS; i++)
7131         {
7132           texts[i] = text[i];
7133           sprintf (text[i], "Column %d", i);
7134         }
7135
7136       sprintf (text[1], "Right");
7137       sprintf (text[2], "Center");
7138
7139       style = gtk_style_new ();
7140       style->fg[GTK_STATE_NORMAL] = red_col;
7141       style->base[GTK_STATE_NORMAL] = light_green_col;
7142
7143       pango_font_description_set_size (style->font_desc, 14 * PANGO_SCALE);
7144       pango_font_description_set_weight (style->font_desc, PANGO_WEIGHT_BOLD);
7145
7146       for (i = 0; i < 10; i++)
7147         {
7148           sprintf (text[0], "CListRow %d", clist_rows++);
7149           gtk_clist_append (GTK_CLIST (clist), texts);
7150
7151           switch (i % 4)
7152             {
7153             case 2:
7154               gtk_clist_set_row_style (GTK_CLIST (clist), i, style);
7155               break;
7156             default:
7157               gtk_clist_set_cell_style (GTK_CLIST (clist), i, i % 4, style);
7158               break;
7159             }
7160         }
7161
7162       g_object_unref (style);
7163       
7164       separator = gtk_hseparator_new ();
7165       gtk_box_pack_start (GTK_BOX (vbox), separator, FALSE, TRUE, 0);
7166
7167       hbox = gtk_hbox_new (FALSE, 0);
7168       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
7169
7170       button = gtk_button_new_with_label ("close");
7171       gtk_container_set_border_width (GTK_CONTAINER (button), 10);
7172       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
7173       g_signal_connect_swapped (button, "clicked",
7174                                 G_CALLBACK (gtk_widget_destroy),
7175                                 window);
7176
7177       gtk_widget_set_can_default (button, TRUE);
7178       gtk_widget_grab_default (button);
7179     }
7180
7181   if (!gtk_widget_get_visible (window))
7182     gtk_widget_show_all (window);
7183   else
7184     {
7185       clist_rows = 0;
7186       gtk_widget_destroy (window);
7187     }
7188 }
7189
7190 /*
7191  * GtkCTree
7192  */
7193
7194 typedef struct 
7195 {
7196   GdkPixmap *pixmap1;
7197   GdkPixmap *pixmap2;
7198   GdkPixmap *pixmap3;
7199   GdkBitmap *mask1;
7200   GdkBitmap *mask2;
7201   GdkBitmap *mask3;
7202 } CTreePixmaps;
7203
7204 static gint books = 0;
7205 static gint pages = 0;
7206
7207 static GtkWidget *book_label;
7208 static GtkWidget *page_label;
7209 static GtkWidget *sel_label;
7210 static GtkWidget *vis_label;
7211 static GtkWidget *omenu1;
7212 static GtkWidget *omenu2;
7213 static GtkWidget *omenu3;
7214 static GtkWidget *omenu4;
7215 static GtkWidget *spin1;
7216 static GtkWidget *spin2;
7217 static GtkWidget *spin3;
7218 static gint line_style;
7219
7220
7221 static CTreePixmaps *
7222 get_ctree_pixmaps (GtkCTree *ctree)
7223 {
7224   GdkScreen *screen = gtk_widget_get_screen (GTK_WIDGET (ctree));
7225   CTreePixmaps *pixmaps = g_object_get_data (G_OBJECT (screen), "ctree-pixmaps");
7226
7227   if (!pixmaps)
7228     {
7229       GdkColormap *colormap = gdk_screen_get_rgb_colormap (screen);
7230       pixmaps = g_new (CTreePixmaps, 1);
7231       
7232       pixmaps->pixmap1 = gdk_pixmap_colormap_create_from_xpm_d (NULL, colormap,
7233                                                                 &pixmaps->mask1, 
7234                                                                 NULL, book_closed_xpm);
7235       pixmaps->pixmap2 = gdk_pixmap_colormap_create_from_xpm_d (NULL, colormap,
7236                                                                 &pixmaps->mask2, 
7237                                                                 NULL, book_open_xpm);
7238       pixmaps->pixmap3 = gdk_pixmap_colormap_create_from_xpm_d (NULL, colormap,
7239                                                                 &pixmaps->mask3,
7240                                                                 NULL, mini_page_xpm);
7241       
7242       g_object_set_data (G_OBJECT (screen), "ctree-pixmaps", pixmaps);
7243     }
7244
7245   return pixmaps;
7246 }
7247
7248 void after_press (GtkCTree *ctree, gpointer data)
7249 {
7250   char buf[80];
7251
7252   sprintf (buf, "%d", g_list_length (GTK_CLIST (ctree)->selection));
7253   gtk_label_set_text (GTK_LABEL (sel_label), buf);
7254
7255   sprintf (buf, "%d", g_list_length (GTK_CLIST (ctree)->row_list));
7256   gtk_label_set_text (GTK_LABEL (vis_label), buf);
7257
7258   sprintf (buf, "%d", books);
7259   gtk_label_set_text (GTK_LABEL (book_label), buf);
7260
7261   sprintf (buf, "%d", pages);
7262   gtk_label_set_text (GTK_LABEL (page_label), buf);
7263 }
7264
7265 void after_move (GtkCTree *ctree, GtkCTreeNode *child, GtkCTreeNode *parent, 
7266                  GtkCTreeNode *sibling, gpointer data)
7267 {
7268   char *source;
7269   char *target1;
7270   char *target2;
7271
7272   gtk_ctree_get_node_info (ctree, child, &source, 
7273                            NULL, NULL, NULL, NULL, NULL, NULL, NULL);
7274   if (parent)
7275     gtk_ctree_get_node_info (ctree, parent, &target1, 
7276                              NULL, NULL, NULL, NULL, NULL, NULL, NULL);
7277   if (sibling)
7278     gtk_ctree_get_node_info (ctree, sibling, &target2, 
7279                              NULL, NULL, NULL, NULL, NULL, NULL, NULL);
7280
7281   g_print ("Moving \"%s\" to \"%s\" with sibling \"%s\".\n", source,
7282            (parent) ? target1 : "nil", (sibling) ? target2 : "nil");
7283 }
7284
7285 void count_items (GtkCTree *ctree, GtkCTreeNode *list)
7286 {
7287   if (GTK_CTREE_ROW (list)->is_leaf)
7288     pages--;
7289   else
7290     books--;
7291 }
7292
7293 void expand_all (GtkWidget *widget, GtkCTree *ctree)
7294 {
7295   gtk_ctree_expand_recursive (ctree, NULL);
7296   after_press (ctree, NULL);
7297 }
7298
7299 void collapse_all (GtkWidget *widget, GtkCTree *ctree)
7300 {
7301   gtk_ctree_collapse_recursive (ctree, NULL);
7302   after_press (ctree, NULL);
7303 }
7304
7305 void select_all (GtkWidget *widget, GtkCTree *ctree)
7306 {
7307   gtk_ctree_select_recursive (ctree, NULL);
7308   after_press (ctree, NULL);
7309 }
7310
7311 void change_style (GtkWidget *widget, GtkCTree *ctree)
7312 {
7313   static GtkStyle *style1 = NULL;
7314   static GtkStyle *style2 = NULL;
7315
7316   GtkCTreeNode *node;
7317   GdkColor green_col = { 0, 0, 56000, 0};
7318   GdkColor purple_col = { 0, 32000, 0, 56000};
7319
7320   if (GTK_CLIST (ctree)->focus_row >= 0)
7321     node = GTK_CTREE_NODE
7322       (g_list_nth (GTK_CLIST (ctree)->row_list,GTK_CLIST (ctree)->focus_row));
7323   else
7324     node = GTK_CTREE_NODE (GTK_CLIST (ctree)->row_list);
7325
7326   if (!node)
7327     return;
7328
7329   if (!style1)
7330     {
7331       style1 = gtk_style_new ();
7332       style1->base[GTK_STATE_NORMAL] = green_col;
7333       style1->fg[GTK_STATE_SELECTED] = purple_col;
7334
7335       style2 = gtk_style_new ();
7336       style2->base[GTK_STATE_SELECTED] = purple_col;
7337       style2->fg[GTK_STATE_NORMAL] = green_col;
7338       style2->base[GTK_STATE_NORMAL] = purple_col;
7339       pango_font_description_free (style2->font_desc);
7340       style2->font_desc = pango_font_description_from_string ("courier 30");
7341     }
7342
7343   gtk_ctree_node_set_cell_style (ctree, node, 1, style1);
7344   gtk_ctree_node_set_cell_style (ctree, node, 0, style2);
7345
7346   if (GTK_CTREE_ROW (node)->children)
7347     gtk_ctree_node_set_row_style (ctree, GTK_CTREE_ROW (node)->children,
7348                                   style2);
7349 }
7350
7351 void unselect_all (GtkWidget *widget, GtkCTree *ctree)
7352 {
7353   gtk_ctree_unselect_recursive (ctree, NULL);
7354   after_press (ctree, NULL);
7355 }
7356
7357 void remove_selection (GtkWidget *widget, GtkCTree *ctree)
7358 {
7359   GtkCList *clist;
7360   GtkCTreeNode *node;
7361
7362   clist = GTK_CLIST (ctree);
7363
7364   gtk_clist_freeze (clist);
7365
7366   while (clist->selection)
7367     {
7368       node = clist->selection->data;
7369
7370       if (GTK_CTREE_ROW (node)->is_leaf)
7371         pages--;
7372       else
7373         gtk_ctree_post_recursive (ctree, node,
7374                                   (GtkCTreeFunc) count_items, NULL);
7375
7376       gtk_ctree_remove_node (ctree, node);
7377
7378       if (clist->selection_mode == GTK_SELECTION_BROWSE)
7379         break;
7380     }
7381
7382   if (clist->selection_mode == GTK_SELECTION_EXTENDED && !clist->selection &&
7383       clist->focus_row >= 0)
7384     {
7385       node = gtk_ctree_node_nth (ctree, clist->focus_row);
7386
7387       if (node)
7388         gtk_ctree_select (ctree, node);
7389     }
7390     
7391   gtk_clist_thaw (clist);
7392   after_press (ctree, NULL);
7393 }
7394
7395 struct _ExportStruct {
7396   gchar *tree;
7397   gchar *info;
7398   gboolean is_leaf;
7399 };
7400
7401 typedef struct _ExportStruct ExportStruct;
7402
7403 gboolean
7404 gnode2ctree (GtkCTree   *ctree,
7405              guint       depth,
7406              GNode        *gnode,
7407              GtkCTreeNode *cnode,
7408              gpointer    data)
7409 {
7410   ExportStruct *es;
7411   GdkPixmap *pixmap_closed;
7412   GdkBitmap *mask_closed;
7413   GdkPixmap *pixmap_opened;
7414   GdkBitmap *mask_opened;
7415   CTreePixmaps *pixmaps;
7416
7417   if (!cnode || !gnode || (!(es = gnode->data)))
7418     return FALSE;
7419
7420   pixmaps = get_ctree_pixmaps (ctree);
7421
7422   if (es->is_leaf)
7423     {
7424       pixmap_closed = pixmaps->pixmap3;
7425       mask_closed = pixmaps->mask3;
7426       pixmap_opened = NULL;
7427       mask_opened = NULL;
7428     }
7429   else
7430     {
7431       pixmap_closed = pixmaps->pixmap1;
7432       mask_closed = pixmaps->mask1;
7433       pixmap_opened = pixmaps->pixmap2;
7434       mask_opened = pixmaps->mask2;
7435     }
7436
7437   gtk_ctree_set_node_info (ctree, cnode, es->tree, 2, pixmap_closed,
7438                            mask_closed, pixmap_opened, mask_opened,
7439                            es->is_leaf, (depth < 3));
7440   gtk_ctree_node_set_text (ctree, cnode, 1, es->info);
7441   g_free (es);
7442   gnode->data = NULL;
7443
7444   return TRUE;
7445 }
7446
7447 gboolean
7448 ctree2gnode (GtkCTree   *ctree,
7449              guint       depth,
7450              GNode        *gnode,
7451              GtkCTreeNode *cnode,
7452              gpointer    data)
7453 {
7454   ExportStruct *es;
7455
7456   if (!cnode || !gnode)
7457     return FALSE;
7458   
7459   es = g_new (ExportStruct, 1);
7460   gnode->data = es;
7461   es->is_leaf = GTK_CTREE_ROW (cnode)->is_leaf;
7462   es->tree = GTK_CELL_PIXTEXT (GTK_CTREE_ROW (cnode)->row.cell[0])->text;
7463   es->info = GTK_CELL_PIXTEXT (GTK_CTREE_ROW (cnode)->row.cell[1])->text;
7464   return TRUE;
7465 }
7466
7467 void export_ctree (GtkWidget *widget, GtkCTree *ctree)
7468 {
7469   char *title[] = { "Tree" , "Info" };
7470   static GtkWidget *export_window = NULL;
7471   static GtkCTree *export_ctree;
7472   GtkWidget *vbox;
7473   GtkWidget *scrolled_win;
7474   GtkWidget *button;
7475   GtkWidget *sep;
7476   GNode *gnode;
7477   GtkCTreeNode *node;
7478
7479   if (!export_window)
7480     {
7481       export_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7482
7483       gtk_window_set_screen (GTK_WINDOW (export_window),
7484                              gtk_widget_get_screen (widget));
7485   
7486       g_signal_connect (export_window, "destroy",
7487                         G_CALLBACK (gtk_widget_destroyed),
7488                         &export_window);
7489
7490       gtk_window_set_title (GTK_WINDOW (export_window), "exported ctree");
7491       gtk_container_set_border_width (GTK_CONTAINER (export_window), 5);
7492
7493       vbox = gtk_vbox_new (FALSE, 0);
7494       gtk_container_add (GTK_CONTAINER (export_window), vbox);
7495       
7496       button = gtk_button_new_with_label ("Close");
7497       gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, TRUE, 0);
7498
7499       g_signal_connect_swapped (button, "clicked",
7500                                 G_CALLBACK (gtk_widget_destroy),
7501                                 export_window);
7502
7503       sep = gtk_hseparator_new ();
7504       gtk_box_pack_end (GTK_BOX (vbox), sep, FALSE, TRUE, 10);
7505
7506       export_ctree = GTK_CTREE (gtk_ctree_new_with_titles (2, 0, title));
7507       gtk_ctree_set_line_style (export_ctree, GTK_CTREE_LINES_DOTTED);
7508
7509       scrolled_win = gtk_scrolled_window_new (NULL, NULL);
7510       gtk_container_add (GTK_CONTAINER (scrolled_win),
7511                          GTK_WIDGET (export_ctree));
7512       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
7513                                       GTK_POLICY_AUTOMATIC,
7514                                       GTK_POLICY_AUTOMATIC);
7515       gtk_box_pack_start (GTK_BOX (vbox), scrolled_win, TRUE, TRUE, 0);
7516       gtk_clist_set_selection_mode (GTK_CLIST (export_ctree),
7517                                     GTK_SELECTION_EXTENDED);
7518       gtk_clist_set_column_width (GTK_CLIST (export_ctree), 0, 200);
7519       gtk_clist_set_column_width (GTK_CLIST (export_ctree), 1, 200);
7520       gtk_widget_set_size_request (GTK_WIDGET (export_ctree), 300, 200);
7521     }
7522
7523   if (!gtk_widget_get_visible (export_window))
7524     gtk_widget_show_all (export_window);
7525       
7526   gtk_clist_clear (GTK_CLIST (export_ctree));
7527
7528   node = GTK_CTREE_NODE (g_list_nth (GTK_CLIST (ctree)->row_list,
7529                                      GTK_CLIST (ctree)->focus_row));
7530   if (!node)
7531     return;
7532
7533   gnode = gtk_ctree_export_to_gnode (ctree, NULL, NULL, node,
7534                                      ctree2gnode, NULL);
7535   if (gnode)
7536     {
7537       gtk_ctree_insert_gnode (export_ctree, NULL, NULL, gnode,
7538                               gnode2ctree, NULL);
7539       g_node_destroy (gnode);
7540     }
7541 }
7542
7543 void change_indent (GtkWidget *widget, GtkCTree *ctree)
7544 {
7545   gtk_ctree_set_indent (ctree, GTK_ADJUSTMENT (widget)->value);
7546 }
7547
7548 void change_spacing (GtkWidget *widget, GtkCTree *ctree)
7549 {
7550   gtk_ctree_set_spacing (ctree, GTK_ADJUSTMENT (widget)->value);
7551 }
7552
7553 void change_row_height (GtkWidget *widget, GtkCList *clist)
7554 {
7555   gtk_clist_set_row_height (clist, GTK_ADJUSTMENT (widget)->value);
7556 }
7557
7558 void set_background (GtkCTree *ctree, GtkCTreeNode *node, gpointer data)
7559 {
7560   GtkStyle *style = NULL;
7561   
7562   if (!node)
7563     return;
7564   
7565   if (ctree->line_style != GTK_CTREE_LINES_TABBED)
7566     {
7567       if (!GTK_CTREE_ROW (node)->is_leaf)
7568         style = GTK_CTREE_ROW (node)->row.data;
7569       else if (GTK_CTREE_ROW (node)->parent)
7570         style = GTK_CTREE_ROW (GTK_CTREE_ROW (node)->parent)->row.data;
7571     }
7572
7573   gtk_ctree_node_set_row_style (ctree, node, style);
7574 }
7575
7576 void 
7577 ctree_toggle_line_style (GtkWidget *widget, gpointer data)
7578 {
7579   GtkCTree *ctree;
7580   gint i;
7581
7582   ctree = GTK_CTREE (data);
7583
7584   if (!gtk_widget_get_mapped (widget))
7585     return;
7586
7587   i = gtk_option_menu_get_history (GTK_OPTION_MENU (widget));
7588
7589   if ((ctree->line_style == GTK_CTREE_LINES_TABBED && 
7590        ((GtkCTreeLineStyle) i) != GTK_CTREE_LINES_TABBED) ||
7591       (ctree->line_style != GTK_CTREE_LINES_TABBED && 
7592        ((GtkCTreeLineStyle) i) == GTK_CTREE_LINES_TABBED))
7593     gtk_ctree_pre_recursive (ctree, NULL, set_background, NULL);
7594   gtk_ctree_set_line_style (ctree, i);
7595   line_style = i;
7596 }
7597
7598 void 
7599 ctree_toggle_expander_style (GtkWidget *widget, gpointer data)
7600 {
7601   GtkCTree *ctree;
7602   gint i;
7603
7604   ctree = GTK_CTREE (data);
7605
7606   if (!gtk_widget_get_mapped (widget))
7607     return;
7608   
7609   i = gtk_option_menu_get_history (GTK_OPTION_MENU (widget));
7610   
7611   gtk_ctree_set_expander_style (ctree, (GtkCTreeExpanderStyle) i);
7612 }
7613
7614 void 
7615 ctree_toggle_justify (GtkWidget *widget, gpointer data)
7616 {
7617   GtkCTree *ctree;
7618   gint i;
7619
7620   ctree = GTK_CTREE (data);
7621
7622   if (!gtk_widget_get_mapped (widget))
7623     return;
7624
7625   i = gtk_option_menu_get_history (GTK_OPTION_MENU (widget));
7626
7627   gtk_clist_set_column_justification (GTK_CLIST (ctree), ctree->tree_column, 
7628                                       (GtkJustification) i);
7629 }
7630
7631 void 
7632 ctree_toggle_sel_mode (GtkWidget *widget, gpointer data)
7633 {
7634   GtkCTree *ctree;
7635   gint i;
7636
7637   ctree = GTK_CTREE (data);
7638
7639   if (!gtk_widget_get_mapped (widget))
7640     return;
7641
7642   i = gtk_option_menu_get_history (GTK_OPTION_MENU (widget));
7643
7644   gtk_clist_set_selection_mode (GTK_CLIST (ctree), selection_modes[i]);
7645   after_press (ctree, NULL);
7646 }
7647     
7648 void build_recursive (GtkCTree *ctree, gint cur_depth, gint depth, 
7649                       gint num_books, gint num_pages, GtkCTreeNode *parent)
7650 {
7651   gchar *text[2];
7652   gchar buf1[60];
7653   gchar buf2[60];
7654   GtkCTreeNode *sibling;
7655   CTreePixmaps *pixmaps;
7656   gint i;
7657
7658   text[0] = buf1;
7659   text[1] = buf2;
7660   sibling = NULL;
7661
7662   pixmaps = get_ctree_pixmaps (ctree);
7663
7664   for (i = num_pages + num_books; i > num_books; i--)
7665     {
7666       pages++;
7667       sprintf (buf1, "Page %02d", (gint) rand() % 100);
7668       sprintf (buf2, "Item %d-%d", cur_depth, i);
7669       sibling = gtk_ctree_insert_node (ctree, parent, sibling, text, 5,
7670                                        pixmaps->pixmap3, pixmaps->mask3, NULL, NULL,
7671                                        TRUE, FALSE);
7672
7673       if (parent && ctree->line_style == GTK_CTREE_LINES_TABBED)
7674         gtk_ctree_node_set_row_style (ctree, sibling,
7675                                       GTK_CTREE_ROW (parent)->row.style);
7676     }
7677
7678   if (cur_depth == depth)
7679     return;
7680
7681   for (i = num_books; i > 0; i--)
7682     {
7683       GtkStyle *style;
7684
7685       books++;
7686       sprintf (buf1, "Book %02d", (gint) rand() % 100);
7687       sprintf (buf2, "Item %d-%d", cur_depth, i);
7688       sibling = gtk_ctree_insert_node (ctree, parent, sibling, text, 5,
7689                                        pixmaps->pixmap1, pixmaps->mask1, pixmaps->pixmap2, pixmaps->mask2,
7690                                        FALSE, FALSE);
7691
7692       style = gtk_style_new ();
7693       switch (cur_depth % 3)
7694         {
7695         case 0:
7696           style->base[GTK_STATE_NORMAL].red   = 10000 * (cur_depth % 6);
7697           style->base[GTK_STATE_NORMAL].green = 0;
7698           style->base[GTK_STATE_NORMAL].blue  = 65535 - ((i * 10000) % 65535);
7699           break;
7700         case 1:
7701           style->base[GTK_STATE_NORMAL].red   = 10000 * (cur_depth % 6);
7702           style->base[GTK_STATE_NORMAL].green = 65535 - ((i * 10000) % 65535);
7703           style->base[GTK_STATE_NORMAL].blue  = 0;
7704           break;
7705         default:
7706           style->base[GTK_STATE_NORMAL].red   = 65535 - ((i * 10000) % 65535);
7707           style->base[GTK_STATE_NORMAL].green = 0;
7708           style->base[GTK_STATE_NORMAL].blue  = 10000 * (cur_depth % 6);
7709           break;
7710         }
7711       gtk_ctree_node_set_row_data_full (ctree, sibling, style,
7712                                         (GDestroyNotify) g_object_unref);
7713
7714       if (ctree->line_style == GTK_CTREE_LINES_TABBED)
7715         gtk_ctree_node_set_row_style (ctree, sibling, style);
7716
7717       build_recursive (ctree, cur_depth + 1, depth, num_books, num_pages,
7718                        sibling);
7719     }
7720 }
7721
7722 void rebuild_tree (GtkWidget *widget, GtkCTree *ctree)
7723 {
7724   gchar *text [2];
7725   gchar label1[] = "Root";
7726   gchar label2[] = "";
7727   GtkCTreeNode *parent;
7728   GtkStyle *style;
7729   guint b, d, p, n;
7730   CTreePixmaps *pixmaps;
7731
7732   pixmaps = get_ctree_pixmaps (ctree);
7733
7734   text[0] = label1;
7735   text[1] = label2;
7736   
7737   d = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (spin1)); 
7738   b = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (spin2));
7739   p = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (spin3));
7740
7741   n = ((pow (b, d) - 1) / (b - 1)) * (p + 1);
7742
7743   if (n > 100000)
7744     {
7745       g_print ("%d total items? Try less\n",n);
7746       return;
7747     }
7748
7749   gtk_clist_freeze (GTK_CLIST (ctree));
7750   gtk_clist_clear (GTK_CLIST (ctree));
7751
7752   books = 1;
7753   pages = 0;
7754
7755   parent = gtk_ctree_insert_node (ctree, NULL, NULL, text, 5, pixmaps->pixmap1,
7756                                   pixmaps->mask1, pixmaps->pixmap2, pixmaps->mask2, FALSE, TRUE);
7757
7758   style = gtk_style_new ();
7759   style->base[GTK_STATE_NORMAL].red   = 0;
7760   style->base[GTK_STATE_NORMAL].green = 45000;
7761   style->base[GTK_STATE_NORMAL].blue  = 55000;
7762   gtk_ctree_node_set_row_data_full (ctree, parent, style,
7763                                     (GDestroyNotify) g_object_unref);
7764
7765   if (ctree->line_style == GTK_CTREE_LINES_TABBED)
7766     gtk_ctree_node_set_row_style (ctree, parent, style);
7767
7768   build_recursive (ctree, 1, d, b, p, parent);
7769   gtk_clist_thaw (GTK_CLIST (ctree));
7770   after_press (ctree, NULL);
7771 }
7772
7773 static void 
7774 ctree_click_column (GtkCTree *ctree, gint column, gpointer data)
7775 {
7776   GtkCList *clist;
7777
7778   clist = GTK_CLIST (ctree);
7779
7780   if (column == clist->sort_column)
7781     {
7782       if (clist->sort_type == GTK_SORT_ASCENDING)
7783         clist->sort_type = GTK_SORT_DESCENDING;
7784       else
7785         clist->sort_type = GTK_SORT_ASCENDING;
7786     }
7787   else
7788     gtk_clist_set_sort_column (clist, column);
7789
7790   gtk_ctree_sort_recursive (ctree, NULL);
7791 }
7792
7793 void create_ctree (GtkWidget *widget)
7794 {
7795   static GtkWidget *window = NULL;
7796   GtkTooltips *tooltips;
7797   GtkCTree *ctree;
7798   GtkWidget *scrolled_win;
7799   GtkWidget *vbox;
7800   GtkWidget *bbox;
7801   GtkWidget *mbox;
7802   GtkWidget *hbox;
7803   GtkWidget *hbox2;
7804   GtkWidget *frame;
7805   GtkWidget *label;
7806   GtkWidget *button;
7807   GtkWidget *check;
7808   GtkAdjustment *adj;
7809   GtkWidget *spinner;
7810
7811   char *title[] = { "Tree" , "Info" };
7812   char buf[80];
7813
7814   static gchar *items1[] =
7815   {
7816     "No lines",
7817     "Solid",
7818     "Dotted",
7819     "Tabbed"
7820   };
7821
7822   static gchar *items2[] =
7823   {
7824     "None",
7825     "Square",
7826     "Triangle",
7827     "Circular"
7828   };
7829
7830   static gchar *items3[] =
7831   {
7832     "Left",
7833     "Right"
7834   };
7835   
7836   if (!window)
7837     {
7838       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7839       gtk_window_set_screen (GTK_WINDOW (window), 
7840                              gtk_widget_get_screen (widget));
7841
7842       g_signal_connect (window, "destroy",
7843                         G_CALLBACK (gtk_widget_destroyed),
7844                         &window);
7845
7846       gtk_window_set_title (GTK_WINDOW (window), "GtkCTree");
7847       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
7848
7849       tooltips = gtk_tooltips_new ();
7850       g_object_ref (tooltips);
7851       gtk_object_sink (GTK_OBJECT (tooltips));
7852
7853       g_object_set_data_full (G_OBJECT (window), "tooltips", tooltips,
7854                               g_object_unref);
7855
7856       vbox = gtk_vbox_new (FALSE, 0);
7857       gtk_container_add (GTK_CONTAINER (window), vbox);
7858
7859       hbox = gtk_hbox_new (FALSE, 5);
7860       gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
7861       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
7862       
7863       label = gtk_label_new ("Depth :");
7864       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
7865       
7866       adj = (GtkAdjustment *) gtk_adjustment_new (4, 1, 10, 1, 5, 0);
7867       spin1 = gtk_spin_button_new (adj, 0, 0);
7868       gtk_box_pack_start (GTK_BOX (hbox), spin1, FALSE, TRUE, 5);
7869   
7870       label = gtk_label_new ("Books :");
7871       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
7872       
7873       adj = (GtkAdjustment *) gtk_adjustment_new (3, 1, 20, 1, 5, 0);
7874       spin2 = gtk_spin_button_new (adj, 0, 0);
7875       gtk_box_pack_start (GTK_BOX (hbox), spin2, FALSE, TRUE, 5);
7876
7877       label = gtk_label_new ("Pages :");
7878       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
7879       
7880       adj = (GtkAdjustment *) gtk_adjustment_new (5, 1, 20, 1, 5, 0);
7881       spin3 = gtk_spin_button_new (adj, 0, 0);
7882       gtk_box_pack_start (GTK_BOX (hbox), spin3, FALSE, TRUE, 5);
7883
7884       button = gtk_button_new_with_label ("Close");
7885       gtk_box_pack_end (GTK_BOX (hbox), button, TRUE, TRUE, 0);
7886
7887       g_signal_connect_swapped (button, "clicked",
7888                                 G_CALLBACK (gtk_widget_destroy),
7889                                 window);
7890
7891       button = gtk_button_new_with_label ("Rebuild Tree");
7892       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
7893
7894       scrolled_win = gtk_scrolled_window_new (NULL, NULL);
7895       gtk_container_set_border_width (GTK_CONTAINER (scrolled_win), 5);
7896       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
7897                                       GTK_POLICY_AUTOMATIC,
7898                                       GTK_POLICY_ALWAYS);
7899       gtk_box_pack_start (GTK_BOX (vbox), scrolled_win, TRUE, TRUE, 0);
7900
7901       ctree = GTK_CTREE (gtk_ctree_new_with_titles (2, 0, title));
7902       gtk_container_add (GTK_CONTAINER (scrolled_win), GTK_WIDGET (ctree));
7903
7904       gtk_clist_set_column_auto_resize (GTK_CLIST (ctree), 0, TRUE);
7905       gtk_clist_set_column_width (GTK_CLIST (ctree), 1, 200);
7906       gtk_clist_set_selection_mode (GTK_CLIST (ctree), GTK_SELECTION_EXTENDED);
7907       gtk_ctree_set_line_style (ctree, GTK_CTREE_LINES_DOTTED);
7908       line_style = GTK_CTREE_LINES_DOTTED;
7909
7910       g_signal_connect (button, "clicked",
7911                         G_CALLBACK (rebuild_tree), ctree);
7912       g_signal_connect (ctree, "click_column",
7913                         G_CALLBACK (ctree_click_column), NULL);
7914
7915       g_signal_connect_after (ctree, "button_press_event",
7916                               G_CALLBACK (after_press), NULL);
7917       g_signal_connect_after (ctree, "button_release_event",
7918                               G_CALLBACK (after_press), NULL);
7919       g_signal_connect_after (ctree, "tree_move",
7920                               G_CALLBACK (after_move), NULL);
7921       g_signal_connect_after (ctree, "end_selection",
7922                               G_CALLBACK (after_press), NULL);
7923       g_signal_connect_after (ctree, "toggle_focus_row",
7924                               G_CALLBACK (after_press), NULL);
7925       g_signal_connect_after (ctree, "select_all",
7926                               G_CALLBACK (after_press), NULL);
7927       g_signal_connect_after (ctree, "unselect_all",
7928                               G_CALLBACK (after_press), NULL);
7929       g_signal_connect_after (ctree, "scroll_vertical",
7930                               G_CALLBACK (after_press), NULL);
7931
7932       bbox = gtk_hbox_new (FALSE, 5);
7933       gtk_container_set_border_width (GTK_CONTAINER (bbox), 5);
7934       gtk_box_pack_start (GTK_BOX (vbox), bbox, FALSE, TRUE, 0);
7935
7936       mbox = gtk_vbox_new (TRUE, 5);
7937       gtk_box_pack_start (GTK_BOX (bbox), mbox, FALSE, TRUE, 0);
7938
7939       label = gtk_label_new ("Row Height :");
7940       gtk_box_pack_start (GTK_BOX (mbox), label, FALSE, FALSE, 0);
7941
7942       label = gtk_label_new ("Indent :");
7943       gtk_box_pack_start (GTK_BOX (mbox), label, FALSE, FALSE, 0);
7944
7945       label = gtk_label_new ("Spacing :");
7946       gtk_box_pack_start (GTK_BOX (mbox), label, FALSE, FALSE, 0);
7947
7948       mbox = gtk_vbox_new (TRUE, 5);
7949       gtk_box_pack_start (GTK_BOX (bbox), mbox, FALSE, TRUE, 0);
7950
7951       adj = (GtkAdjustment *) gtk_adjustment_new (20, 12, 100, 1, 10, 0);
7952       spinner = gtk_spin_button_new (adj, 0, 0);
7953       gtk_box_pack_start (GTK_BOX (mbox), spinner, FALSE, FALSE, 5);
7954       gtk_tooltips_set_tip (tooltips, spinner,
7955                             "Row height of list items", NULL);
7956       g_signal_connect (adj, "value_changed",
7957                         G_CALLBACK (change_row_height), ctree);
7958       gtk_clist_set_row_height ( GTK_CLIST (ctree), adj->value);
7959
7960       adj = (GtkAdjustment *) gtk_adjustment_new (20, 0, 60, 1, 10, 0);
7961       spinner = gtk_spin_button_new (adj, 0, 0);
7962       gtk_box_pack_start (GTK_BOX (mbox), spinner, FALSE, FALSE, 5);
7963       gtk_tooltips_set_tip (tooltips, spinner, "Tree Indentation.", NULL);
7964       g_signal_connect (adj, "value_changed",
7965                         G_CALLBACK (change_indent), ctree);
7966
7967       adj = (GtkAdjustment *) gtk_adjustment_new (5, 0, 60, 1, 10, 0);
7968       spinner = gtk_spin_button_new (adj, 0, 0);
7969       gtk_box_pack_start (GTK_BOX (mbox), spinner, FALSE, FALSE, 5);
7970       gtk_tooltips_set_tip (tooltips, spinner, "Tree Spacing.", NULL);
7971       g_signal_connect (adj, "value_changed",
7972                         G_CALLBACK (change_spacing), ctree);
7973
7974       mbox = gtk_vbox_new (TRUE, 5);
7975       gtk_box_pack_start (GTK_BOX (bbox), mbox, FALSE, TRUE, 0);
7976
7977       hbox = gtk_hbox_new (FALSE, 5);
7978       gtk_box_pack_start (GTK_BOX (mbox), hbox, FALSE, FALSE, 0);
7979
7980       button = gtk_button_new_with_label ("Expand All");
7981       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
7982       g_signal_connect (button, "clicked",
7983                         G_CALLBACK (expand_all), ctree);
7984
7985       button = gtk_button_new_with_label ("Collapse All");
7986       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
7987       g_signal_connect (button, "clicked",
7988                         G_CALLBACK (collapse_all), ctree);
7989
7990       button = gtk_button_new_with_label ("Change Style");
7991       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
7992       g_signal_connect (button, "clicked",
7993                         G_CALLBACK (change_style), ctree);
7994
7995       button = gtk_button_new_with_label ("Export Tree");
7996       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
7997       g_signal_connect (button, "clicked",
7998                         G_CALLBACK (export_ctree), ctree);
7999
8000       hbox = gtk_hbox_new (FALSE, 5);
8001       gtk_box_pack_start (GTK_BOX (mbox), hbox, FALSE, FALSE, 0);
8002
8003       button = gtk_button_new_with_label ("Select All");
8004       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
8005       g_signal_connect (button, "clicked",
8006                         G_CALLBACK (select_all), ctree);
8007
8008       button = gtk_button_new_with_label ("Unselect All");
8009       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
8010       g_signal_connect (button, "clicked",
8011                         G_CALLBACK (unselect_all), ctree);
8012
8013       button = gtk_button_new_with_label ("Remove Selection");
8014       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
8015       g_signal_connect (button, "clicked",
8016                         G_CALLBACK (remove_selection), ctree);
8017
8018       check = gtk_check_button_new_with_label ("Reorderable");
8019       gtk_box_pack_start (GTK_BOX (hbox), check, FALSE, TRUE, 0);
8020       gtk_tooltips_set_tip (tooltips, check,
8021                             "Tree items can be reordered by dragging.", NULL);
8022       g_signal_connect (check, "clicked",
8023                         G_CALLBACK (toggle_reorderable), ctree);
8024       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check), TRUE);
8025
8026       hbox = gtk_hbox_new (TRUE, 5);
8027       gtk_box_pack_start (GTK_BOX (mbox), hbox, FALSE, FALSE, 0);
8028
8029       omenu1 = build_option_menu (items1, 4, 2, 
8030                                   ctree_toggle_line_style,
8031                                   ctree);
8032       gtk_box_pack_start (GTK_BOX (hbox), omenu1, FALSE, TRUE, 0);
8033       gtk_tooltips_set_tip (tooltips, omenu1, "The tree's line style.", NULL);
8034
8035       omenu2 = build_option_menu (items2, 4, 1, 
8036                                   ctree_toggle_expander_style,
8037                                   ctree);
8038       gtk_box_pack_start (GTK_BOX (hbox), omenu2, FALSE, TRUE, 0);
8039       gtk_tooltips_set_tip (tooltips, omenu2, "The tree's expander style.",
8040                             NULL);
8041
8042       omenu3 = build_option_menu (items3, 2, 0, 
8043                                   ctree_toggle_justify, ctree);
8044       gtk_box_pack_start (GTK_BOX (hbox), omenu3, FALSE, TRUE, 0);
8045       gtk_tooltips_set_tip (tooltips, omenu3, "The tree's justification.",
8046                             NULL);
8047
8048       omenu4 = build_option_menu (selection_mode_items, 3, 3, 
8049                                   ctree_toggle_sel_mode, ctree);
8050       gtk_box_pack_start (GTK_BOX (hbox), omenu4, FALSE, TRUE, 0);
8051       gtk_tooltips_set_tip (tooltips, omenu4, "The list's selection mode.",
8052                             NULL);
8053
8054       gtk_widget_realize (window);
8055       
8056       gtk_widget_set_size_request (GTK_WIDGET (ctree), -1, 300);
8057
8058       frame = gtk_frame_new (NULL);
8059       gtk_container_set_border_width (GTK_CONTAINER (frame), 0);
8060       gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT);
8061       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
8062
8063       hbox = gtk_hbox_new (TRUE, 2);
8064       gtk_container_set_border_width (GTK_CONTAINER (hbox), 2);
8065       gtk_container_add (GTK_CONTAINER (frame), hbox);
8066
8067       frame = gtk_frame_new (NULL);
8068       gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
8069       gtk_box_pack_start (GTK_BOX (hbox), frame, FALSE, TRUE, 0);
8070
8071       hbox2 = gtk_hbox_new (FALSE, 0);
8072       gtk_container_set_border_width (GTK_CONTAINER (hbox2), 2);
8073       gtk_container_add (GTK_CONTAINER (frame), hbox2);
8074
8075       label = gtk_label_new ("Books :");
8076       gtk_box_pack_start (GTK_BOX (hbox2), label, FALSE, TRUE, 0);
8077
8078       sprintf (buf, "%d", books);
8079       book_label = gtk_label_new (buf);
8080       gtk_box_pack_end (GTK_BOX (hbox2), book_label, FALSE, TRUE, 5);
8081
8082       frame = gtk_frame_new (NULL);
8083       gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
8084       gtk_box_pack_start (GTK_BOX (hbox), frame, FALSE, TRUE, 0);
8085
8086       hbox2 = gtk_hbox_new (FALSE, 0);
8087       gtk_container_set_border_width (GTK_CONTAINER (hbox2), 2);
8088       gtk_container_add (GTK_CONTAINER (frame), hbox2);
8089
8090       label = gtk_label_new ("Pages :");
8091       gtk_box_pack_start (GTK_BOX (hbox2), label, FALSE, TRUE, 0);
8092
8093       sprintf (buf, "%d", pages);
8094       page_label = gtk_label_new (buf);
8095       gtk_box_pack_end (GTK_BOX (hbox2), page_label, FALSE, TRUE, 5);
8096
8097       frame = gtk_frame_new (NULL);
8098       gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
8099       gtk_box_pack_start (GTK_BOX (hbox), frame, FALSE, TRUE, 0);
8100
8101       hbox2 = gtk_hbox_new (FALSE, 0);
8102       gtk_container_set_border_width (GTK_CONTAINER (hbox2), 2);
8103       gtk_container_add (GTK_CONTAINER (frame), hbox2);
8104
8105       label = gtk_label_new ("Selected :");
8106       gtk_box_pack_start (GTK_BOX (hbox2), label, FALSE, TRUE, 0);
8107
8108       sprintf (buf, "%d", g_list_length (GTK_CLIST (ctree)->selection));
8109       sel_label = gtk_label_new (buf);
8110       gtk_box_pack_end (GTK_BOX (hbox2), sel_label, FALSE, TRUE, 5);
8111
8112       frame = gtk_frame_new (NULL);
8113       gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
8114       gtk_box_pack_start (GTK_BOX (hbox), frame, FALSE, TRUE, 0);
8115
8116       hbox2 = gtk_hbox_new (FALSE, 0);
8117       gtk_container_set_border_width (GTK_CONTAINER (hbox2), 2);
8118       gtk_container_add (GTK_CONTAINER (frame), hbox2);
8119
8120       label = gtk_label_new ("Visible :");
8121       gtk_box_pack_start (GTK_BOX (hbox2), label, FALSE, TRUE, 0);
8122
8123       sprintf (buf, "%d", g_list_length (GTK_CLIST (ctree)->row_list));
8124       vis_label = gtk_label_new (buf);
8125       gtk_box_pack_end (GTK_BOX (hbox2), vis_label, FALSE, TRUE, 5);
8126
8127       rebuild_tree (NULL, ctree);
8128     }
8129
8130   if (!gtk_widget_get_visible (window))
8131     gtk_widget_show_all (window);
8132   else
8133     gtk_widget_destroy (window);
8134 }
8135
8136 /*
8137  * GtkColorSelection
8138  */
8139
8140 void
8141 color_selection_ok (GtkWidget               *w,
8142                     GtkColorSelectionDialog *cs)
8143 {
8144   GtkColorSelection *colorsel;
8145   gdouble color[4];
8146
8147   colorsel=GTK_COLOR_SELECTION(cs->colorsel);
8148
8149   gtk_color_selection_get_color(colorsel,color);
8150   gtk_color_selection_set_color(colorsel,color);
8151 }
8152
8153 void
8154 color_selection_changed (GtkWidget *w,
8155                          GtkColorSelectionDialog *cs)
8156 {
8157   GtkColorSelection *colorsel;
8158   gdouble color[4];
8159
8160   colorsel=GTK_COLOR_SELECTION(cs->colorsel);
8161   gtk_color_selection_get_color(colorsel,color);
8162 }
8163
8164 #if 0 /* unused */
8165 static void
8166 opacity_toggled_cb (GtkWidget *w,
8167                     GtkColorSelectionDialog *cs)
8168 {
8169   GtkColorSelection *colorsel;
8170
8171   colorsel = GTK_COLOR_SELECTION (cs->colorsel);
8172   gtk_color_selection_set_has_opacity_control (colorsel,
8173                                                gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w)));
8174 }
8175
8176 static void
8177 palette_toggled_cb (GtkWidget *w,
8178                     GtkColorSelectionDialog *cs)
8179 {
8180   GtkColorSelection *colorsel;
8181
8182   colorsel = GTK_COLOR_SELECTION (cs->colorsel);
8183   gtk_color_selection_set_has_palette (colorsel,
8184                                        gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w)));
8185 }
8186 #endif
8187
8188 void
8189 create_color_selection (GtkWidget *widget)
8190 {
8191   static GtkWidget *window = NULL;
8192
8193   if (!window)
8194     {
8195       GtkWidget *picker;
8196       GtkWidget *hbox;
8197       GtkWidget *label;
8198       GtkWidget *button;
8199       
8200       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8201       gtk_window_set_screen (GTK_WINDOW (window), 
8202                              gtk_widget_get_screen (widget));
8203                              
8204       g_signal_connect (window, "destroy",
8205                         G_CALLBACK (gtk_widget_destroyed),
8206                         &window);
8207
8208       gtk_window_set_title (GTK_WINDOW (window), "GtkColorButton");
8209       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
8210
8211       hbox = gtk_hbox_new (FALSE, 8);
8212       gtk_container_set_border_width (GTK_CONTAINER (hbox), 8);
8213       gtk_container_add (GTK_CONTAINER (window), hbox);
8214       
8215       label = gtk_label_new ("Pick a color");
8216       gtk_container_add (GTK_CONTAINER (hbox), label);
8217
8218       picker = gtk_color_button_new ();
8219       gtk_color_button_set_use_alpha (GTK_COLOR_BUTTON (picker), TRUE);
8220       gtk_container_add (GTK_CONTAINER (hbox), picker);
8221
8222       button = gtk_button_new_with_mnemonic ("_Props");
8223       gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
8224       g_signal_connect (button, "clicked",
8225                         G_CALLBACK (props_clicked),
8226                         picker);
8227     }
8228
8229   if (!gtk_widget_get_visible (window))
8230     gtk_widget_show_all (window);
8231   else
8232     gtk_widget_destroy (window);
8233 }
8234
8235 /*
8236  * GtkFileSelection
8237  */
8238
8239 void
8240 show_fileops (GtkWidget        *widget,
8241               GtkFileSelection *fs)
8242 {
8243   gboolean show_ops;
8244
8245   show_ops = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
8246
8247   if (show_ops)
8248     gtk_file_selection_show_fileop_buttons (fs);
8249   else
8250     gtk_file_selection_hide_fileop_buttons (fs);
8251 }
8252
8253 void
8254 select_multiple (GtkWidget        *widget,
8255                  GtkFileSelection *fs)
8256 {
8257   gboolean select_multiple;
8258
8259   select_multiple = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
8260   gtk_file_selection_set_select_multiple (fs, select_multiple);
8261 }
8262
8263 void
8264 file_selection_ok (GtkFileSelection *fs)
8265 {
8266   int i;
8267   gchar **selections;
8268
8269   selections = gtk_file_selection_get_selections (fs);
8270
8271   for (i = 0; selections[i] != NULL; i++)
8272     g_print ("%s\n", selections[i]);
8273
8274   g_strfreev (selections);
8275
8276   gtk_widget_destroy (GTK_WIDGET (fs));
8277 }
8278
8279 void
8280 create_file_selection (GtkWidget *widget)
8281 {
8282   static GtkWidget *window = NULL;
8283   GtkWidget *button;
8284
8285   if (!window)
8286     {
8287       window = gtk_file_selection_new ("file selection dialog");
8288       gtk_window_set_screen (GTK_WINDOW (window),
8289                              gtk_widget_get_screen (widget));
8290
8291       gtk_file_selection_hide_fileop_buttons (GTK_FILE_SELECTION (window));
8292
8293       gtk_window_set_position (GTK_WINDOW (window), GTK_WIN_POS_MOUSE);
8294
8295       g_signal_connect (window, "destroy",
8296                         G_CALLBACK (gtk_widget_destroyed),
8297                         &window);
8298
8299       g_signal_connect_swapped (GTK_FILE_SELECTION (window)->ok_button,
8300                                 "clicked",
8301                                 G_CALLBACK (file_selection_ok),
8302                                 window);
8303       g_signal_connect_swapped (GTK_FILE_SELECTION (window)->cancel_button,
8304                                 "clicked",
8305                                 G_CALLBACK (gtk_widget_destroy),
8306                                 window);
8307       
8308       button = gtk_check_button_new_with_label ("Show Fileops");
8309       g_signal_connect (button, "toggled",
8310                         G_CALLBACK (show_fileops),
8311                         window);
8312       gtk_box_pack_start (GTK_BOX (GTK_FILE_SELECTION (window)->action_area), 
8313                           button, FALSE, FALSE, 0);
8314       gtk_widget_show (button);
8315
8316       button = gtk_check_button_new_with_label ("Select Multiple");
8317       g_signal_connect (button, "clicked",
8318                         G_CALLBACK (select_multiple),
8319                         window);
8320       gtk_box_pack_start (GTK_BOX (GTK_FILE_SELECTION (window)->action_area), 
8321                           button, FALSE, FALSE, 0);
8322       gtk_widget_show (button);
8323     }
8324   
8325   if (!gtk_widget_get_visible (window))
8326     gtk_widget_show (window);
8327   else
8328     gtk_widget_destroy (window);
8329 }
8330
8331 void
8332 flipping_toggled_cb (GtkWidget *widget, gpointer data)
8333 {
8334   int state = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
8335   int new_direction = state ? GTK_TEXT_DIR_RTL : GTK_TEXT_DIR_LTR;
8336
8337   gtk_widget_set_default_direction (new_direction);
8338 }
8339
8340 static void
8341 orientable_toggle_orientation (GtkOrientable *orientable)
8342 {
8343   GtkOrientation orientation;
8344
8345   orientation = gtk_orientable_get_orientation (orientable);
8346   gtk_orientable_set_orientation (orientable,
8347                                   orientation == GTK_ORIENTATION_HORIZONTAL ?
8348                                   GTK_ORIENTATION_VERTICAL :
8349                                   GTK_ORIENTATION_HORIZONTAL);
8350
8351   if (GTK_IS_CONTAINER (orientable))
8352     {
8353       GList *children;
8354       GList *child;
8355
8356       children = gtk_container_get_children (GTK_CONTAINER (orientable));
8357
8358       for (child = children; child; child = child->next)
8359         {
8360           if (GTK_IS_ORIENTABLE (child->data))
8361             orientable_toggle_orientation (child->data);
8362         }
8363
8364       g_list_free (children);
8365     }
8366 }
8367
8368 void
8369 flipping_orientation_toggled_cb (GtkWidget *widget, gpointer data)
8370 {
8371   orientable_toggle_orientation (GTK_ORIENTABLE (GTK_DIALOG (gtk_widget_get_toplevel (widget))->vbox));
8372 }
8373
8374 static void
8375 set_direction_recurse (GtkWidget *widget,
8376                        gpointer   data)
8377 {
8378   GtkTextDirection *dir = data;
8379   
8380   gtk_widget_set_direction (widget, *dir);
8381   if (GTK_IS_CONTAINER (widget))
8382     gtk_container_foreach (GTK_CONTAINER (widget),
8383                            set_direction_recurse,
8384                            data);
8385 }
8386
8387 static GtkWidget *
8388 create_forward_back (const char       *title,
8389                      GtkTextDirection  text_dir)
8390 {
8391   GtkWidget *frame = gtk_frame_new (title);
8392   GtkWidget *bbox = gtk_hbutton_box_new ();
8393   GtkWidget *back_button = gtk_button_new_from_stock (GTK_STOCK_GO_BACK);
8394   GtkWidget *forward_button = gtk_button_new_from_stock (GTK_STOCK_GO_FORWARD);
8395
8396   gtk_container_set_border_width (GTK_CONTAINER (bbox), 5);
8397   
8398   gtk_container_add (GTK_CONTAINER (frame), bbox);
8399   gtk_container_add (GTK_CONTAINER (bbox), back_button);
8400   gtk_container_add (GTK_CONTAINER (bbox), forward_button);
8401
8402   set_direction_recurse (frame, &text_dir);
8403
8404   return frame;
8405 }
8406
8407 void
8408 create_flipping (GtkWidget *widget)
8409 {
8410   static GtkWidget *window = NULL;
8411   GtkWidget *check_button, *button;
8412
8413   if (!window)
8414     {
8415       window = gtk_dialog_new ();
8416
8417       gtk_window_set_screen (GTK_WINDOW (window),
8418                              gtk_widget_get_screen (widget));
8419
8420       g_signal_connect (window, "destroy",
8421                         G_CALLBACK (gtk_widget_destroyed),
8422                         &window);
8423
8424       gtk_window_set_title (GTK_WINDOW (window), "Bidirectional Flipping");
8425
8426       check_button = gtk_check_button_new_with_label ("Right-to-left global direction");
8427       gtk_container_set_border_width (GTK_CONTAINER (check_button), 10);
8428       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox),
8429                           check_button, TRUE, TRUE, 0);
8430
8431       if (gtk_widget_get_default_direction () == GTK_TEXT_DIR_RTL)
8432         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button), TRUE);
8433
8434       g_signal_connect (check_button, "toggled",
8435                         G_CALLBACK (flipping_toggled_cb), NULL);
8436
8437       check_button = gtk_check_button_new_with_label ("Toggle orientation of all boxes");
8438       gtk_container_set_border_width (GTK_CONTAINER (check_button), 10);
8439       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
8440                           check_button, TRUE, TRUE, 0);
8441
8442       g_signal_connect (check_button, "toggled",
8443                         G_CALLBACK (flipping_orientation_toggled_cb), NULL);
8444
8445       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
8446                           create_forward_back ("Default", GTK_TEXT_DIR_NONE),
8447                           TRUE, TRUE, 0);
8448
8449       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
8450                           create_forward_back ("Left-to-Right", GTK_TEXT_DIR_LTR),
8451                           TRUE, TRUE, 0);
8452
8453       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
8454                           create_forward_back ("Right-to-Left", GTK_TEXT_DIR_RTL),
8455                           TRUE, TRUE, 0);
8456
8457       button = gtk_button_new_with_label ("Close");
8458       g_signal_connect_swapped (button, "clicked",
8459                                 G_CALLBACK (gtk_widget_destroy), window);
8460       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
8461                           button, TRUE, TRUE, 0);
8462     }
8463   
8464   if (!gtk_widget_get_visible (window))
8465     gtk_widget_show_all (window);
8466   else
8467     gtk_widget_destroy (window);
8468 }
8469
8470 /*
8471  * Focus test
8472  */
8473
8474 static GtkWidget*
8475 make_focus_table (GList **list)
8476 {
8477   GtkWidget *table;
8478   gint i, j;
8479   
8480   table = gtk_table_new (5, 5, FALSE);
8481
8482   i = 0;
8483   j = 0;
8484
8485   while (i < 5)
8486     {
8487       j = 0;
8488       while (j < 5)
8489         {
8490           GtkWidget *widget;
8491           
8492           if ((i + j) % 2)
8493             widget = gtk_entry_new ();
8494           else
8495             widget = gtk_button_new_with_label ("Foo");
8496
8497           *list = g_list_prepend (*list, widget);
8498           
8499           gtk_table_attach (GTK_TABLE (table),
8500                             widget,
8501                             i, i + 1,
8502                             j, j + 1,
8503                             GTK_EXPAND | GTK_FILL,
8504                             GTK_EXPAND | GTK_FILL,
8505                             5, 5);
8506           
8507           ++j;
8508         }
8509
8510       ++i;
8511     }
8512
8513   *list = g_list_reverse (*list);
8514   
8515   return table;
8516 }
8517
8518 static void
8519 create_focus (GtkWidget *widget)
8520 {
8521   static GtkWidget *window = NULL;
8522   
8523   if (!window)
8524     {
8525       GtkWidget *table;
8526       GtkWidget *frame;
8527       GList *list = NULL;
8528       
8529       window = gtk_dialog_new_with_buttons ("Keyboard focus navigation",
8530                                             NULL, 0,
8531                                             GTK_STOCK_CLOSE,
8532                                             GTK_RESPONSE_NONE,
8533                                             NULL);
8534
8535       gtk_window_set_screen (GTK_WINDOW (window),
8536                              gtk_widget_get_screen (widget));
8537
8538       g_signal_connect (window, "destroy",
8539                         G_CALLBACK (gtk_widget_destroyed),
8540                         &window);
8541
8542       g_signal_connect (window, "response",
8543                         G_CALLBACK (gtk_widget_destroy),
8544                         NULL);
8545       
8546       gtk_window_set_title (GTK_WINDOW (window), "Keyboard Focus Navigation");
8547
8548       frame = gtk_frame_new ("Weird tab focus chain");
8549
8550       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
8551                           frame, TRUE, TRUE, 0);
8552       
8553       table = make_focus_table (&list);
8554
8555       gtk_container_add (GTK_CONTAINER (frame), table);
8556
8557       gtk_container_set_focus_chain (GTK_CONTAINER (table),
8558                                      list);
8559
8560       g_list_free (list);
8561       
8562       frame = gtk_frame_new ("Default tab focus chain");
8563
8564       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
8565                           frame, TRUE, TRUE, 0);
8566
8567       list = NULL;
8568       table = make_focus_table (&list);
8569
8570       g_list_free (list);
8571       
8572       gtk_container_add (GTK_CONTAINER (frame), table);      
8573     }
8574   
8575   if (!gtk_widget_get_visible (window))
8576     gtk_widget_show_all (window);
8577   else
8578     gtk_widget_destroy (window);
8579 }
8580
8581 /*
8582  * GtkFontSelection
8583  */
8584
8585 void
8586 font_selection_ok (GtkWidget              *w,
8587                    GtkFontSelectionDialog *fs)
8588 {
8589   gchar *s = gtk_font_selection_dialog_get_font_name (fs);
8590
8591   g_print ("%s\n", s);
8592   g_free (s);
8593   gtk_widget_destroy (GTK_WIDGET (fs));
8594 }
8595
8596 void
8597 create_font_selection (GtkWidget *widget)
8598 {
8599   static GtkWidget *window = NULL;
8600
8601   if (!window)
8602     {
8603       GtkWidget *picker;
8604       GtkWidget *hbox;
8605       GtkWidget *label;
8606       
8607       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8608       gtk_window_set_screen (GTK_WINDOW (window),
8609                              gtk_widget_get_screen (widget));
8610
8611       g_signal_connect (window, "destroy",
8612                         G_CALLBACK (gtk_widget_destroyed),
8613                         &window);
8614
8615       gtk_window_set_title (GTK_WINDOW (window), "GtkFontButton");
8616       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
8617
8618       hbox = gtk_hbox_new (FALSE, 8);
8619       gtk_container_set_border_width (GTK_CONTAINER (hbox), 8);
8620       gtk_container_add (GTK_CONTAINER (window), hbox);
8621       
8622       label = gtk_label_new ("Pick a font");
8623       gtk_container_add (GTK_CONTAINER (hbox), label);
8624
8625       picker = gtk_font_button_new ();
8626       gtk_font_button_set_use_font (GTK_FONT_BUTTON (picker), TRUE);
8627       gtk_container_add (GTK_CONTAINER (hbox), picker);
8628     }
8629   
8630   if (!gtk_widget_get_visible (window))
8631     gtk_widget_show_all (window);
8632   else
8633     gtk_widget_destroy (window);
8634 }
8635
8636 /*
8637  * GtkDialog
8638  */
8639
8640 static GtkWidget *dialog_window = NULL;
8641
8642 static void
8643 label_toggle (GtkWidget  *widget,
8644               GtkWidget **label)
8645 {
8646   if (!(*label))
8647     {
8648       *label = gtk_label_new ("Dialog Test");
8649       g_signal_connect (*label,
8650                         "destroy",
8651                         G_CALLBACK (gtk_widget_destroyed),
8652                         label);
8653       gtk_misc_set_padding (GTK_MISC (*label), 10, 10);
8654       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog_window)->vbox), 
8655                           *label, TRUE, TRUE, 0);
8656       gtk_widget_show (*label);
8657     }
8658   else
8659     gtk_widget_destroy (*label);
8660 }
8661
8662 #define RESPONSE_TOGGLE_SEPARATOR 1
8663
8664 static void
8665 print_response (GtkWidget *dialog,
8666                 gint       response_id,
8667                 gpointer   data)
8668 {
8669   g_print ("response signal received (%d)\n", response_id);
8670
8671   if (response_id == RESPONSE_TOGGLE_SEPARATOR)
8672     {
8673       gtk_dialog_set_has_separator (GTK_DIALOG (dialog),
8674                                     !gtk_dialog_get_has_separator (GTK_DIALOG (dialog)));
8675     }
8676 }
8677
8678 static void
8679 create_dialog (GtkWidget *widget)
8680 {
8681   static GtkWidget *label;
8682   GtkWidget *button;
8683
8684   if (!dialog_window)
8685     {
8686       /* This is a terrible example; it's much simpler to create
8687        * dialogs than this. Don't use testgtk for example code,
8688        * use gtk-demo ;-)
8689        */
8690       
8691       dialog_window = gtk_dialog_new ();
8692       gtk_window_set_screen (GTK_WINDOW (dialog_window),
8693                              gtk_widget_get_screen (widget));
8694
8695       g_signal_connect (dialog_window,
8696                         "response",
8697                         G_CALLBACK (print_response),
8698                         NULL);
8699       
8700       g_signal_connect (dialog_window, "destroy",
8701                         G_CALLBACK (gtk_widget_destroyed),
8702                         &dialog_window);
8703
8704       gtk_window_set_title (GTK_WINDOW (dialog_window), "GtkDialog");
8705       gtk_container_set_border_width (GTK_CONTAINER (dialog_window), 0);
8706
8707       button = gtk_button_new_with_label ("OK");
8708       gtk_widget_set_can_default (button, TRUE);
8709       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog_window)->action_area), 
8710                           button, TRUE, TRUE, 0);
8711       gtk_widget_grab_default (button);
8712       gtk_widget_show (button);
8713
8714       button = gtk_button_new_with_label ("Toggle");
8715       g_signal_connect (button, "clicked",
8716                         G_CALLBACK (label_toggle),
8717                         &label);
8718       gtk_widget_set_can_default (button, TRUE);
8719       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog_window)->action_area),
8720                           button, TRUE, TRUE, 0);
8721       gtk_widget_show (button);
8722
8723       label = NULL;
8724       
8725       button = gtk_button_new_with_label ("Separator");
8726
8727       gtk_widget_set_can_default (button, TRUE);
8728
8729       gtk_dialog_add_action_widget (GTK_DIALOG (dialog_window),
8730                                     button,
8731                                     RESPONSE_TOGGLE_SEPARATOR);
8732       gtk_widget_show (button);
8733     }
8734
8735   if (!gtk_widget_get_visible (dialog_window))
8736     gtk_widget_show (dialog_window);
8737   else
8738     gtk_widget_destroy (dialog_window);
8739 }
8740
8741 /* Display & Screen test 
8742  */
8743
8744 typedef struct 
8745
8746   GtkEntry *entry;
8747   GtkWidget *radio_dpy;
8748   GtkWidget *toplevel; 
8749   GtkWidget *dialog_window;
8750   GList *valid_display_list;
8751 } ScreenDisplaySelection;
8752
8753 static gint
8754 display_name_cmp (gconstpointer a,
8755                   gconstpointer b)
8756 {
8757   return g_ascii_strcasecmp (a,b);
8758 }
8759
8760 static void
8761 screen_display_check (GtkWidget *widget, ScreenDisplaySelection *data)
8762 {
8763   char *display_name;
8764   GdkDisplay *display = gtk_widget_get_display (widget);
8765   GtkWidget *dialog;
8766   GdkScreen *new_screen = NULL;
8767   GdkScreen *current_screen = gtk_widget_get_screen (widget);
8768   
8769   if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (data->radio_dpy)))
8770     {
8771       display_name = g_strdup (gtk_entry_get_text (data->entry));
8772       display = gdk_display_open (display_name);
8773       
8774       if (!display)
8775         {
8776           dialog = gtk_message_dialog_new (GTK_WINDOW (gtk_widget_get_toplevel (widget)),
8777                                            GTK_DIALOG_DESTROY_WITH_PARENT,
8778                                            GTK_MESSAGE_ERROR,
8779                                            GTK_BUTTONS_OK,
8780                                            "The display :\n%s\ncannot be opened",
8781                                            display_name);
8782           gtk_window_set_screen (GTK_WINDOW (dialog), current_screen);
8783           gtk_widget_show (dialog);
8784           g_signal_connect (dialog, "response",
8785                             G_CALLBACK (gtk_widget_destroy),
8786                             NULL);
8787         }
8788       else
8789         {
8790           if (!g_list_find_custom (data->valid_display_list, 
8791                                    display_name,
8792                                    display_name_cmp))
8793             data->valid_display_list = g_list_append (data->valid_display_list,
8794                                                       display_name);
8795           
8796           new_screen = gdk_display_get_default_screen (display);
8797         }
8798     }
8799   else
8800     {
8801       gint number_of_screens = gdk_display_get_n_screens (display);
8802       gint screen_num = gdk_screen_get_number (current_screen);
8803       if ((screen_num +1) < number_of_screens)
8804         new_screen = gdk_display_get_screen (display, screen_num + 1);
8805       else
8806         new_screen = gdk_display_get_screen (display, 0);
8807     }
8808   
8809   if (new_screen) 
8810     {
8811       gtk_window_set_screen (GTK_WINDOW (data->toplevel), new_screen);
8812       gtk_widget_destroy (data->dialog_window);
8813     }
8814 }
8815
8816 void
8817 screen_display_destroy_diag (GtkWidget *widget, GtkWidget *data)
8818 {
8819   gtk_widget_destroy (data);
8820 }
8821
8822 void
8823 create_display_screen (GtkWidget *widget)
8824 {
8825   GtkWidget *table, *frame, *window, *combo_dpy, *vbox;
8826   GtkWidget *radio_dpy, *radio_scr, *applyb, *cancelb;
8827   GtkWidget *bbox;
8828   ScreenDisplaySelection *scr_dpy_data;
8829   GdkScreen *screen = gtk_widget_get_screen (widget);
8830   static GList *valid_display_list = NULL;
8831   
8832   GdkDisplay *display = gdk_screen_get_display (screen);
8833
8834   window = g_object_new (gtk_window_get_type (),
8835                            "screen", screen,
8836                            "user_data", NULL,
8837                            "type", GTK_WINDOW_TOPLEVEL,
8838                            "title",
8839                            "Screen or Display selection",
8840                            "border_width", 10, NULL);
8841   g_signal_connect (window, "destroy", 
8842                     G_CALLBACK (gtk_widget_destroy), NULL);
8843
8844   vbox = gtk_vbox_new (FALSE, 3);
8845   gtk_container_add (GTK_CONTAINER (window), vbox);
8846   
8847   frame = gtk_frame_new ("Select screen or display");
8848   gtk_container_add (GTK_CONTAINER (vbox), frame);
8849   
8850   table = gtk_table_new (2, 2, TRUE);
8851   gtk_table_set_row_spacings (GTK_TABLE (table), 3);
8852   gtk_table_set_col_spacings (GTK_TABLE (table), 3);
8853
8854   gtk_container_add (GTK_CONTAINER (frame), table);
8855
8856   radio_dpy = gtk_radio_button_new_with_label (NULL, "move to another X display");
8857   if (gdk_display_get_n_screens(display) > 1)
8858     radio_scr = gtk_radio_button_new_with_label 
8859     (gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio_dpy)), "move to next screen");
8860   else
8861     {    
8862       radio_scr = gtk_radio_button_new_with_label 
8863         (gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio_dpy)), 
8864          "only one screen on the current display");
8865       gtk_widget_set_sensitive (radio_scr, FALSE);
8866     }
8867   combo_dpy = gtk_combo_new ();
8868   if (!valid_display_list)
8869     valid_display_list = g_list_append (valid_display_list, "diabolo:0.0");
8870     
8871   gtk_combo_set_popdown_strings (GTK_COMBO (combo_dpy), valid_display_list);
8872     
8873   gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (combo_dpy)->entry), 
8874                       "<hostname>:<X Server Num>.<Screen Num>");
8875
8876   gtk_table_attach_defaults (GTK_TABLE (table), radio_dpy, 0, 1, 0, 1);
8877   gtk_table_attach_defaults (GTK_TABLE (table), radio_scr, 0, 1, 1, 2);
8878   gtk_table_attach_defaults (GTK_TABLE (table), combo_dpy, 1, 2, 0, 1);
8879
8880   bbox = gtk_hbutton_box_new ();
8881   applyb = gtk_button_new_from_stock (GTK_STOCK_APPLY);
8882   cancelb = gtk_button_new_from_stock (GTK_STOCK_CANCEL);
8883   
8884   gtk_container_add (GTK_CONTAINER (vbox), bbox);
8885
8886   gtk_container_add (GTK_CONTAINER (bbox), applyb);
8887   gtk_container_add (GTK_CONTAINER (bbox), cancelb);
8888
8889   scr_dpy_data = g_new0 (ScreenDisplaySelection, 1);
8890
8891   scr_dpy_data->entry = GTK_ENTRY (GTK_COMBO (combo_dpy)->entry);
8892   scr_dpy_data->radio_dpy = radio_dpy;
8893   scr_dpy_data->toplevel = gtk_widget_get_toplevel (widget);
8894   scr_dpy_data->dialog_window = window;
8895   scr_dpy_data->valid_display_list = valid_display_list;
8896
8897   g_signal_connect (cancelb, "clicked", 
8898                     G_CALLBACK (screen_display_destroy_diag), window);
8899   g_signal_connect (applyb, "clicked", 
8900                     G_CALLBACK (screen_display_check), scr_dpy_data);
8901   gtk_widget_show_all (window);
8902 }
8903
8904 /* Event Watcher
8905  */
8906 static gboolean event_watcher_enter_id = 0;
8907 static gboolean event_watcher_leave_id = 0;
8908
8909 static gboolean
8910 event_watcher (GSignalInvocationHint *ihint,
8911                guint                  n_param_values,
8912                const GValue          *param_values,
8913                gpointer               data)
8914 {
8915   g_print ("Watch: \"%s\" emitted for %s\n",
8916            g_signal_name (ihint->signal_id),
8917            G_OBJECT_TYPE_NAME (g_value_get_object (param_values + 0)));
8918
8919   return TRUE;
8920 }
8921
8922 static void
8923 event_watcher_down (void)
8924 {
8925   if (event_watcher_enter_id)
8926     {
8927       guint signal_id;
8928
8929       signal_id = g_signal_lookup ("enter_notify_event", GTK_TYPE_WIDGET);
8930       g_signal_remove_emission_hook (signal_id, event_watcher_enter_id);
8931       event_watcher_enter_id = 0;
8932       signal_id = g_signal_lookup ("leave_notify_event", GTK_TYPE_WIDGET);
8933       g_signal_remove_emission_hook (signal_id, event_watcher_leave_id);
8934       event_watcher_leave_id = 0;
8935     }
8936 }
8937
8938 static void
8939 event_watcher_toggle (void)
8940 {
8941   if (event_watcher_enter_id)
8942     event_watcher_down ();
8943   else
8944     {
8945       guint signal_id;
8946
8947       signal_id = g_signal_lookup ("enter_notify_event", GTK_TYPE_WIDGET);
8948       event_watcher_enter_id = g_signal_add_emission_hook (signal_id, 0, event_watcher, NULL, NULL);
8949       signal_id = g_signal_lookup ("leave_notify_event", GTK_TYPE_WIDGET);
8950       event_watcher_leave_id = g_signal_add_emission_hook (signal_id, 0, event_watcher, NULL, NULL);
8951     }
8952 }
8953
8954 static void
8955 create_event_watcher (GtkWidget *widget)
8956 {
8957   GtkWidget *button;
8958
8959   if (!dialog_window)
8960     {
8961       dialog_window = gtk_dialog_new ();
8962       gtk_window_set_screen (GTK_WINDOW (dialog_window),
8963                              gtk_widget_get_screen (widget));
8964
8965       g_signal_connect (dialog_window, "destroy",
8966                         G_CALLBACK (gtk_widget_destroyed),
8967                         &dialog_window);
8968       g_signal_connect (dialog_window, "destroy",
8969                         G_CALLBACK (event_watcher_down),
8970                         NULL);
8971
8972       gtk_window_set_title (GTK_WINDOW (dialog_window), "Event Watcher");
8973       gtk_container_set_border_width (GTK_CONTAINER (dialog_window), 0);
8974       gtk_widget_set_size_request (dialog_window, 200, 110);
8975
8976       button = gtk_toggle_button_new_with_label ("Activate Watch");
8977       g_signal_connect (button, "clicked",
8978                         G_CALLBACK (event_watcher_toggle),
8979                         NULL);
8980       gtk_container_set_border_width (GTK_CONTAINER (button), 10);
8981       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog_window)->vbox), 
8982                           button, TRUE, TRUE, 0);
8983       gtk_widget_show (button);
8984
8985       button = gtk_button_new_with_label ("Close");
8986       g_signal_connect_swapped (button, "clicked",
8987                                 G_CALLBACK (gtk_widget_destroy),
8988                                 dialog_window);
8989       gtk_widget_set_can_default (button, TRUE);
8990       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog_window)->action_area),
8991                           button, TRUE, TRUE, 0);
8992       gtk_widget_grab_default (button);
8993       gtk_widget_show (button);
8994     }
8995
8996   if (!gtk_widget_get_visible (dialog_window))
8997     gtk_widget_show (dialog_window);
8998   else
8999     gtk_widget_destroy (dialog_window);
9000 }
9001
9002 /*
9003  * GtkRange
9004  */
9005
9006 static gchar*
9007 reformat_value (GtkScale *scale,
9008                 gdouble   value)
9009 {
9010   return g_strdup_printf ("-->%0.*g<--",
9011                           gtk_scale_get_digits (scale), value);
9012 }
9013
9014 static void
9015 create_range_controls (GtkWidget *widget)
9016 {
9017   static GtkWidget *window = NULL;
9018   GtkWidget *box1;
9019   GtkWidget *box2;
9020   GtkWidget *button;
9021   GtkWidget *scrollbar;
9022   GtkWidget *scale;
9023   GtkWidget *separator;
9024   GtkObject *adjustment;
9025   GtkWidget *hbox;
9026
9027   if (!window)
9028     {
9029       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9030
9031       gtk_window_set_screen (GTK_WINDOW (window),
9032                              gtk_widget_get_screen (widget));
9033
9034       g_signal_connect (window, "destroy",
9035                         G_CALLBACK (gtk_widget_destroyed),
9036                         &window);
9037
9038       gtk_window_set_title (GTK_WINDOW (window), "range controls");
9039       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
9040
9041
9042       box1 = gtk_vbox_new (FALSE, 0);
9043       gtk_container_add (GTK_CONTAINER (window), box1);
9044       gtk_widget_show (box1);
9045
9046
9047       box2 = gtk_vbox_new (FALSE, 10);
9048       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
9049       gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
9050       gtk_widget_show (box2);
9051
9052
9053       adjustment = gtk_adjustment_new (0.0, 0.0, 101.0, 0.1, 1.0, 1.0);
9054
9055       scale = gtk_hscale_new (GTK_ADJUSTMENT (adjustment));
9056       gtk_widget_set_size_request (GTK_WIDGET (scale), 150, -1);
9057       gtk_range_set_update_policy (GTK_RANGE (scale), GTK_UPDATE_DELAYED);
9058       gtk_scale_set_digits (GTK_SCALE (scale), 1);
9059       gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE);
9060       gtk_box_pack_start (GTK_BOX (box2), scale, TRUE, TRUE, 0);
9061       gtk_widget_show (scale);
9062
9063       scrollbar = gtk_hscrollbar_new (GTK_ADJUSTMENT (adjustment));
9064       gtk_range_set_update_policy (GTK_RANGE (scrollbar), 
9065                                    GTK_UPDATE_CONTINUOUS);
9066       gtk_box_pack_start (GTK_BOX (box2), scrollbar, TRUE, TRUE, 0);
9067       gtk_widget_show (scrollbar);
9068
9069       scale = gtk_hscale_new (GTK_ADJUSTMENT (adjustment));
9070       gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE);
9071       g_signal_connect (scale,
9072                         "format_value",
9073                         G_CALLBACK (reformat_value),
9074                         NULL);
9075       gtk_box_pack_start (GTK_BOX (box2), scale, TRUE, TRUE, 0);
9076       gtk_widget_show (scale);
9077       
9078       hbox = gtk_hbox_new (FALSE, 0);
9079
9080       scale = gtk_vscale_new (GTK_ADJUSTMENT (adjustment));
9081       gtk_widget_set_size_request (scale, -1, 200);
9082       gtk_scale_set_digits (GTK_SCALE (scale), 2);
9083       gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE);
9084       gtk_box_pack_start (GTK_BOX (hbox), scale, TRUE, TRUE, 0);
9085       gtk_widget_show (scale);
9086
9087       scale = gtk_vscale_new (GTK_ADJUSTMENT (adjustment));
9088       gtk_widget_set_size_request (scale, -1, 200);
9089       gtk_scale_set_digits (GTK_SCALE (scale), 2);
9090       gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE);
9091       gtk_range_set_inverted (GTK_RANGE (scale), TRUE);
9092       gtk_box_pack_start (GTK_BOX (hbox), scale, TRUE, TRUE, 0);
9093       gtk_widget_show (scale);
9094
9095       scale = gtk_vscale_new (GTK_ADJUSTMENT (adjustment));
9096       gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE);
9097       g_signal_connect (scale,
9098                         "format_value",
9099                         G_CALLBACK (reformat_value),
9100                         NULL);
9101       gtk_box_pack_start (GTK_BOX (hbox), scale, TRUE, TRUE, 0);
9102       gtk_widget_show (scale);
9103
9104       
9105       gtk_box_pack_start (GTK_BOX (box2), hbox, TRUE, TRUE, 0);
9106       gtk_widget_show (hbox);
9107       
9108       separator = gtk_hseparator_new ();
9109       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
9110       gtk_widget_show (separator);
9111
9112
9113       box2 = gtk_vbox_new (FALSE, 10);
9114       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
9115       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
9116       gtk_widget_show (box2);
9117
9118
9119       button = gtk_button_new_with_label ("close");
9120       g_signal_connect_swapped (button, "clicked",
9121                                 G_CALLBACK (gtk_widget_destroy),
9122                                 window);
9123       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
9124       gtk_widget_set_can_default (button, TRUE);
9125       gtk_widget_grab_default (button);
9126       gtk_widget_show (button);
9127     }
9128
9129   if (!gtk_widget_get_visible (window))
9130     gtk_widget_show (window);
9131   else
9132     gtk_widget_destroy (window);
9133 }
9134
9135 /*
9136  * GtkRulers
9137  */
9138
9139 void
9140 create_rulers (GtkWidget *widget)
9141 {
9142   static GtkWidget *window = NULL;
9143   GtkWidget *table;
9144   GtkWidget *ruler;
9145
9146   if (!window)
9147     {
9148       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9149
9150       gtk_window_set_screen (GTK_WINDOW (window),
9151                              gtk_widget_get_screen (widget));
9152
9153       g_object_set (window, "allow_shrink", TRUE, "allow_grow", TRUE, NULL);
9154
9155       g_signal_connect (window, "destroy",
9156                         G_CALLBACK (gtk_widget_destroyed),
9157                         &window);
9158
9159       gtk_window_set_title (GTK_WINDOW (window), "rulers");
9160       gtk_widget_set_size_request (window, 300, 300);
9161       gtk_widget_set_events (window, 
9162                              GDK_POINTER_MOTION_MASK 
9163                              | GDK_POINTER_MOTION_HINT_MASK);
9164       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
9165
9166       table = gtk_table_new (2, 2, FALSE);
9167       gtk_container_add (GTK_CONTAINER (window), table);
9168       gtk_widget_show (table);
9169
9170       ruler = gtk_hruler_new ();
9171       gtk_ruler_set_metric (GTK_RULER (ruler), GTK_CENTIMETERS);
9172       gtk_ruler_set_range (GTK_RULER (ruler), 100, 0, 0, 20);
9173
9174       g_signal_connect_swapped (window, 
9175                                 "motion_notify_event",
9176                                 G_CALLBACK (GTK_WIDGET_GET_CLASS (ruler)->motion_notify_event),
9177                                 ruler);
9178       
9179       gtk_table_attach (GTK_TABLE (table), ruler, 1, 2, 0, 1,
9180                         GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
9181       gtk_widget_show (ruler);
9182
9183
9184       ruler = gtk_vruler_new ();
9185       gtk_ruler_set_range (GTK_RULER (ruler), 5, 15, 0, 20);
9186
9187       g_signal_connect_swapped (window, 
9188                                 "motion_notify_event",
9189                                 G_CALLBACK (GTK_WIDGET_GET_CLASS (ruler)->motion_notify_event),
9190                                 ruler);
9191       
9192       gtk_table_attach (GTK_TABLE (table), ruler, 0, 1, 1, 2,
9193                         GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
9194       gtk_widget_show (ruler);
9195     }
9196
9197   if (!gtk_widget_get_visible (window))
9198     gtk_widget_show (window);
9199   else
9200     gtk_widget_destroy (window);
9201 }
9202
9203 static void
9204 text_toggle_editable (GtkWidget *checkbutton,
9205                        GtkWidget *text)
9206 {
9207    gtk_text_set_editable(GTK_TEXT(text),
9208                           GTK_TOGGLE_BUTTON(checkbutton)->active);
9209 }
9210
9211 static void
9212 text_toggle_word_wrap (GtkWidget *checkbutton,
9213                        GtkWidget *text)
9214 {
9215    gtk_text_set_word_wrap(GTK_TEXT(text),
9216                           GTK_TOGGLE_BUTTON(checkbutton)->active);
9217 }
9218
9219 struct {
9220   GdkColor color;
9221   gchar *name;
9222 } text_colors[] = {
9223  { { 0, 0x0000, 0x0000, 0x0000 }, "black" },
9224  { { 0, 0xFFFF, 0xFFFF, 0xFFFF }, "white" },
9225  { { 0, 0xFFFF, 0x0000, 0x0000 }, "red" },
9226  { { 0, 0x0000, 0xFFFF, 0x0000 }, "green" },
9227  { { 0, 0x0000, 0x0000, 0xFFFF }, "blue" }, 
9228  { { 0, 0x0000, 0xFFFF, 0xFFFF }, "cyan" },
9229  { { 0, 0xFFFF, 0x0000, 0xFFFF }, "magenta" },
9230  { { 0, 0xFFFF, 0xFFFF, 0x0000 }, "yellow" }
9231 };
9232
9233 int ntext_colors = sizeof(text_colors) / sizeof(text_colors[0]);
9234
9235 /*
9236  * GtkText
9237  */
9238 void
9239 text_insert_random (GtkWidget *w, GtkText *text)
9240 {
9241   int i;
9242   char c;
9243    for (i=0; i<10; i++)
9244     {
9245       c = 'A' + rand() % ('Z' - 'A');
9246       gtk_text_set_point (text, rand() % gtk_text_get_length (text));
9247       gtk_text_insert (text, NULL, NULL, NULL, &c, 1);
9248     }
9249 }
9250
9251 void
9252 create_text (GtkWidget *widget)
9253 {
9254   int i, j;
9255
9256   static GtkWidget *window = NULL;
9257   GtkWidget *box1;
9258   GtkWidget *box2;
9259   GtkWidget *hbox;
9260   GtkWidget *button;
9261   GtkWidget *check;
9262   GtkWidget *separator;
9263   GtkWidget *scrolled_window;
9264   GtkWidget *text;
9265
9266   FILE *infile;
9267
9268   if (!window)
9269     {
9270       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9271       gtk_window_set_screen (GTK_WINDOW (window),
9272                              gtk_widget_get_screen (widget));
9273
9274       gtk_widget_set_name (window, "text window");
9275       g_object_set (window, "allow_shrink", TRUE, "allow_grow", TRUE, NULL);
9276       gtk_widget_set_size_request (window, 500, 500);
9277
9278       g_signal_connect (window, "destroy",
9279                         G_CALLBACK (gtk_widget_destroyed),
9280                         &window);
9281
9282       gtk_window_set_title (GTK_WINDOW (window), "test");
9283       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
9284
9285
9286       box1 = gtk_vbox_new (FALSE, 0);
9287       gtk_container_add (GTK_CONTAINER (window), box1);
9288       gtk_widget_show (box1);
9289
9290
9291       box2 = gtk_vbox_new (FALSE, 10);
9292       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
9293       gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
9294       gtk_widget_show (box2);
9295
9296
9297       scrolled_window = gtk_scrolled_window_new (NULL, NULL);
9298       gtk_box_pack_start (GTK_BOX (box2), scrolled_window, TRUE, TRUE, 0);
9299       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
9300                                       GTK_POLICY_NEVER,
9301                                       GTK_POLICY_ALWAYS);
9302       gtk_widget_show (scrolled_window);
9303
9304       text = gtk_text_new (NULL, NULL);
9305       gtk_text_set_editable (GTK_TEXT (text), TRUE);
9306       gtk_container_add (GTK_CONTAINER (scrolled_window), text);
9307       gtk_widget_grab_focus (text);
9308       gtk_widget_show (text);
9309
9310
9311       gtk_text_freeze (GTK_TEXT (text));
9312
9313       for (i=0; i<ntext_colors; i++)
9314         {
9315           gtk_text_insert (GTK_TEXT (text), NULL, NULL, NULL, 
9316                            text_colors[i].name, -1);
9317           gtk_text_insert (GTK_TEXT (text), NULL, NULL, NULL, "\t", -1);
9318
9319           for (j=0; j<ntext_colors; j++)
9320             {
9321               gtk_text_insert (GTK_TEXT (text), NULL,
9322                                &text_colors[j].color, &text_colors[i].color,
9323                                "XYZ", -1);
9324             }
9325           gtk_text_insert (GTK_TEXT (text), NULL, NULL, NULL, "\n", -1);
9326         }
9327
9328       infile = fopen("testgtk.c", "r");
9329       
9330       if (infile)
9331         {
9332           char *buffer;
9333           int nbytes_read, nbytes_alloc;
9334           
9335           nbytes_read = 0;
9336           nbytes_alloc = 1024;
9337           buffer = g_new (char, nbytes_alloc);
9338           while (1)
9339             {
9340               int len;
9341               if (nbytes_alloc < nbytes_read + 1024)
9342                 {
9343                   nbytes_alloc *= 2;
9344                   buffer = g_realloc (buffer, nbytes_alloc);
9345                 }
9346               len = fread (buffer + nbytes_read, 1, 1024, infile);
9347               nbytes_read += len;
9348               if (len < 1024)
9349                 break;
9350             }
9351           
9352           gtk_text_insert (GTK_TEXT (text), NULL, NULL,
9353                            NULL, buffer, nbytes_read);
9354           g_free(buffer);
9355           fclose (infile);
9356         }
9357       
9358       gtk_text_thaw (GTK_TEXT (text));
9359
9360       hbox = gtk_hbutton_box_new ();
9361       gtk_box_pack_start (GTK_BOX (box2), hbox, FALSE, FALSE, 0);
9362       gtk_widget_show (hbox);
9363
9364       check = gtk_check_button_new_with_label("Editable");
9365       gtk_box_pack_start (GTK_BOX (hbox), check, FALSE, FALSE, 0);
9366       g_signal_connect (check, "toggled",
9367                         G_CALLBACK (text_toggle_editable), text);
9368       gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), TRUE);
9369       gtk_widget_show (check);
9370
9371       check = gtk_check_button_new_with_label("Wrap Words");
9372       gtk_box_pack_start (GTK_BOX (hbox), check, FALSE, TRUE, 0);
9373       g_signal_connect (check, "toggled",
9374                         G_CALLBACK (text_toggle_word_wrap), text);
9375       gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), FALSE);
9376       gtk_widget_show (check);
9377
9378       separator = gtk_hseparator_new ();
9379       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
9380       gtk_widget_show (separator);
9381
9382
9383       box2 = gtk_vbox_new (FALSE, 10);
9384       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
9385       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
9386       gtk_widget_show (box2);
9387
9388
9389       button = gtk_button_new_with_label ("insert random");
9390       g_signal_connect (button, "clicked",
9391                         G_CALLBACK (text_insert_random),
9392                         text);
9393       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
9394       gtk_widget_show (button);
9395
9396       button = gtk_button_new_with_label ("close");
9397       g_signal_connect_swapped (button, "clicked",
9398                                 G_CALLBACK (gtk_widget_destroy),
9399                                 window);
9400       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
9401       gtk_widget_set_can_default (button, TRUE);
9402       gtk_widget_grab_default (button);
9403       gtk_widget_show (button);
9404     }
9405
9406   if (!gtk_widget_get_visible (window))
9407     gtk_widget_show (window);
9408   else
9409     gtk_widget_destroy (window);
9410 }
9411
9412 /*
9413  * GtkNotebook
9414  */
9415
9416 GdkPixbuf *book_open;
9417 GdkPixbuf *book_closed;
9418 GtkWidget *sample_notebook;
9419
9420 static void
9421 set_page_image (GtkNotebook *notebook, gint page_num, GdkPixbuf *pixbuf)
9422 {
9423   GtkWidget *page_widget;
9424   GtkWidget *pixwid;
9425
9426   page_widget = gtk_notebook_get_nth_page (notebook, page_num);
9427
9428   pixwid = g_object_get_data (G_OBJECT (page_widget), "tab_pixmap");
9429   gtk_image_set_from_pixbuf (GTK_IMAGE (pixwid), pixbuf);
9430   
9431   pixwid = g_object_get_data (G_OBJECT (page_widget), "menu_pixmap");
9432   gtk_image_set_from_pixbuf (GTK_IMAGE (pixwid), pixbuf);
9433 }
9434
9435 static void
9436 page_switch (GtkWidget *widget, GtkNotebookPage *page, gint page_num)
9437 {
9438   GtkNotebook *notebook = GTK_NOTEBOOK (widget);
9439   gint old_page_num = gtk_notebook_get_current_page (notebook);
9440  
9441   if (page_num == old_page_num)
9442     return;
9443
9444   set_page_image (notebook, page_num, book_open);
9445
9446   if (old_page_num != -1)
9447     set_page_image (notebook, old_page_num, book_closed);
9448 }
9449
9450 static void
9451 tab_fill (GtkToggleButton *button, GtkWidget *child)
9452 {
9453   gboolean expand;
9454   GtkPackType pack_type;
9455
9456   gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (sample_notebook), child,
9457                                         &expand, NULL, &pack_type);
9458   gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (sample_notebook), child,
9459                                       expand, button->active, pack_type);
9460 }
9461
9462 static void
9463 tab_expand (GtkToggleButton *button, GtkWidget *child)
9464 {
9465   gboolean fill;
9466   GtkPackType pack_type;
9467
9468   gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (sample_notebook), child,
9469                                         NULL, &fill, &pack_type);
9470   gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (sample_notebook), child,
9471                                       button->active, fill, pack_type);
9472 }
9473
9474 static void
9475 tab_pack (GtkToggleButton *button, GtkWidget *child)
9476           
9477
9478   gboolean expand;
9479   gboolean fill;
9480
9481   gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (sample_notebook), child,
9482                                         &expand, &fill, NULL);
9483   gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (sample_notebook), child,
9484                                       expand, fill, button->active);
9485 }
9486
9487 static void
9488 create_pages (GtkNotebook *notebook, gint start, gint end)
9489 {
9490   GtkWidget *child = NULL;
9491   GtkWidget *button;
9492   GtkWidget *label;
9493   GtkWidget *hbox;
9494   GtkWidget *vbox;
9495   GtkWidget *label_box;
9496   GtkWidget *menu_box;
9497   GtkWidget *pixwid;
9498   gint i;
9499   char buffer[32];
9500   char accel_buffer[32];
9501
9502   for (i = start; i <= end; i++)
9503     {
9504       sprintf (buffer, "Page %d", i);
9505       sprintf (accel_buffer, "Page _%d", i);
9506
9507       child = gtk_frame_new (buffer);
9508       gtk_container_set_border_width (GTK_CONTAINER (child), 10);
9509
9510       vbox = gtk_vbox_new (TRUE,0);
9511       gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
9512       gtk_container_add (GTK_CONTAINER (child), vbox);
9513
9514       hbox = gtk_hbox_new (TRUE,0);
9515       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 5);
9516
9517       button = gtk_check_button_new_with_label ("Fill Tab");
9518       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
9519       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
9520       g_signal_connect (button, "toggled",
9521                         G_CALLBACK (tab_fill), child);
9522
9523       button = gtk_check_button_new_with_label ("Expand Tab");
9524       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
9525       g_signal_connect (button, "toggled",
9526                         G_CALLBACK (tab_expand), child);
9527
9528       button = gtk_check_button_new_with_label ("Pack end");
9529       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
9530       g_signal_connect (button, "toggled",
9531                         G_CALLBACK (tab_pack), child);
9532
9533       button = gtk_button_new_with_label ("Hide Page");
9534       gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 5);
9535       g_signal_connect_swapped (button, "clicked",
9536                                 G_CALLBACK (gtk_widget_hide),
9537                                 child);
9538
9539       gtk_widget_show_all (child);
9540
9541       label_box = gtk_hbox_new (FALSE, 0);
9542       pixwid = gtk_image_new_from_pixbuf (book_closed);
9543       g_object_set_data (G_OBJECT (child), "tab_pixmap", pixwid);
9544                            
9545       gtk_box_pack_start (GTK_BOX (label_box), pixwid, FALSE, TRUE, 0);
9546       gtk_misc_set_padding (GTK_MISC (pixwid), 3, 1);
9547       label = gtk_label_new_with_mnemonic (accel_buffer);
9548       gtk_box_pack_start (GTK_BOX (label_box), label, FALSE, TRUE, 0);
9549       gtk_widget_show_all (label_box);
9550       
9551                                        
9552       menu_box = gtk_hbox_new (FALSE, 0);
9553       pixwid = gtk_image_new_from_pixbuf (book_closed);
9554       g_object_set_data (G_OBJECT (child), "menu_pixmap", pixwid);
9555       
9556       gtk_box_pack_start (GTK_BOX (menu_box), pixwid, FALSE, TRUE, 0);
9557       gtk_misc_set_padding (GTK_MISC (pixwid), 3, 1);
9558       label = gtk_label_new (buffer);
9559       gtk_box_pack_start (GTK_BOX (menu_box), label, FALSE, TRUE, 0);
9560       gtk_widget_show_all (menu_box);
9561
9562       gtk_notebook_append_page_menu (notebook, child, label_box, menu_box);
9563     }
9564 }
9565
9566 static void
9567 rotate_notebook (GtkButton   *button,
9568                  GtkNotebook *notebook)
9569 {
9570   gtk_notebook_set_tab_pos (notebook, (notebook->tab_pos + 1) % 4);
9571 }
9572
9573 static void
9574 show_all_pages (GtkButton   *button,
9575                 GtkNotebook *notebook)
9576 {  
9577   gtk_container_foreach (GTK_CONTAINER (notebook),
9578                          (GtkCallback) gtk_widget_show, NULL);
9579 }
9580
9581 static void
9582 notebook_type_changed (GtkWidget *optionmenu,
9583                        gpointer   data)
9584 {
9585   GtkNotebook *notebook;
9586   gint i, c;
9587
9588   enum {
9589     STANDARD,
9590     NOTABS,
9591     BORDERLESS,
9592     SCROLLABLE
9593   };
9594
9595   notebook = GTK_NOTEBOOK (data);
9596
9597   c = gtk_option_menu_get_history (GTK_OPTION_MENU (optionmenu));
9598
9599   switch (c)
9600     {
9601     case STANDARD:
9602       /* standard notebook */
9603       gtk_notebook_set_show_tabs (notebook, TRUE);
9604       gtk_notebook_set_show_border (notebook, TRUE);
9605       gtk_notebook_set_scrollable (notebook, FALSE);
9606       break;
9607
9608     case NOTABS:
9609       /* notabs notebook */
9610       gtk_notebook_set_show_tabs (notebook, FALSE);
9611       gtk_notebook_set_show_border (notebook, TRUE);
9612       break;
9613
9614     case BORDERLESS:
9615       /* borderless */
9616       gtk_notebook_set_show_tabs (notebook, FALSE);
9617       gtk_notebook_set_show_border (notebook, FALSE);
9618       break;
9619
9620     case SCROLLABLE:  
9621       /* scrollable */
9622       gtk_notebook_set_show_tabs (notebook, TRUE);
9623       gtk_notebook_set_show_border (notebook, TRUE);
9624       gtk_notebook_set_scrollable (notebook, TRUE);
9625       if (g_list_length (notebook->children) == 5)
9626         create_pages (notebook, 6, 15);
9627       
9628       return;
9629       break;
9630     }
9631   
9632   if (g_list_length (notebook->children) == 15)
9633     for (i = 0; i < 10; i++)
9634       gtk_notebook_remove_page (notebook, 5);
9635 }
9636
9637 static void
9638 notebook_popup (GtkToggleButton *button,
9639                 GtkNotebook     *notebook)
9640 {
9641   if (button->active)
9642     gtk_notebook_popup_enable (notebook);
9643   else
9644     gtk_notebook_popup_disable (notebook);
9645 }
9646
9647 static void
9648 notebook_homogeneous (GtkToggleButton *button,
9649                       GtkNotebook     *notebook)
9650 {
9651   g_object_set (notebook, "homogeneous", button->active, NULL);
9652 }
9653
9654 static void
9655 create_notebook (GtkWidget *widget)
9656 {
9657   static GtkWidget *window = NULL;
9658   GtkWidget *box1;
9659   GtkWidget *box2;
9660   GtkWidget *button;
9661   GtkWidget *separator;
9662   GtkWidget *omenu;
9663   GtkWidget *label;
9664
9665   static gchar *items[] =
9666   {
9667     "Standard",
9668     "No tabs",
9669     "Borderless",
9670     "Scrollable"
9671   };
9672   
9673   if (!window)
9674     {
9675       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9676       gtk_window_set_screen (GTK_WINDOW (window),
9677                              gtk_widget_get_screen (widget));
9678
9679       g_signal_connect (window, "destroy",
9680                         G_CALLBACK (gtk_widget_destroyed),
9681                         &window);
9682
9683       gtk_window_set_title (GTK_WINDOW (window), "notebook");
9684       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
9685
9686       box1 = gtk_vbox_new (FALSE, 0);
9687       gtk_container_add (GTK_CONTAINER (window), box1);
9688
9689       sample_notebook = gtk_notebook_new ();
9690       g_signal_connect (sample_notebook, "switch_page",
9691                         G_CALLBACK (page_switch), NULL);
9692       gtk_notebook_set_tab_pos (GTK_NOTEBOOK (sample_notebook), GTK_POS_TOP);
9693       gtk_box_pack_start (GTK_BOX (box1), sample_notebook, TRUE, TRUE, 0);
9694       gtk_container_set_border_width (GTK_CONTAINER (sample_notebook), 10);
9695
9696       gtk_widget_realize (sample_notebook);
9697
9698       if (!book_open)
9699         book_open = gdk_pixbuf_new_from_xpm_data ((const char **)book_open_xpm);
9700                                                   
9701       if (!book_closed)
9702         book_closed = gdk_pixbuf_new_from_xpm_data ((const char **)book_closed_xpm);
9703
9704       create_pages (GTK_NOTEBOOK (sample_notebook), 1, 5);
9705
9706       separator = gtk_hseparator_new ();
9707       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 10);
9708       
9709       box2 = gtk_hbox_new (FALSE, 5);
9710       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
9711       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
9712
9713       button = gtk_check_button_new_with_label ("popup menu");
9714       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, FALSE, 0);
9715       g_signal_connect (button, "clicked",
9716                         G_CALLBACK (notebook_popup),
9717                         sample_notebook);
9718
9719       button = gtk_check_button_new_with_label ("homogeneous tabs");
9720       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, FALSE, 0);
9721       g_signal_connect (button, "clicked",
9722                         G_CALLBACK (notebook_homogeneous),
9723                         sample_notebook);
9724
9725       box2 = gtk_hbox_new (FALSE, 5);
9726       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
9727       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
9728
9729       label = gtk_label_new ("Notebook Style :");
9730       gtk_box_pack_start (GTK_BOX (box2), label, FALSE, TRUE, 0);
9731
9732       omenu = build_option_menu (items, G_N_ELEMENTS (items), 0,
9733                                  notebook_type_changed,
9734                                  sample_notebook);
9735       gtk_box_pack_start (GTK_BOX (box2), omenu, FALSE, TRUE, 0);
9736
9737       button = gtk_button_new_with_label ("Show all Pages");
9738       gtk_box_pack_start (GTK_BOX (box2), button, FALSE, TRUE, 0);
9739       g_signal_connect (button, "clicked",
9740                         G_CALLBACK (show_all_pages), sample_notebook);
9741
9742       box2 = gtk_hbox_new (TRUE, 10);
9743       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
9744       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
9745
9746       button = gtk_button_new_with_label ("prev");
9747       g_signal_connect_swapped (button, "clicked",
9748                                 G_CALLBACK (gtk_notebook_prev_page),
9749                                 sample_notebook);
9750       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
9751
9752       button = gtk_button_new_with_label ("next");
9753       g_signal_connect_swapped (button, "clicked",
9754                                 G_CALLBACK (gtk_notebook_next_page),
9755                                 sample_notebook);
9756       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
9757
9758       button = gtk_button_new_with_label ("rotate");
9759       g_signal_connect (button, "clicked",
9760                         G_CALLBACK (rotate_notebook), sample_notebook);
9761       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
9762
9763       separator = gtk_hseparator_new ();
9764       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
9765
9766       button = gtk_button_new_with_label ("close");
9767       gtk_container_set_border_width (GTK_CONTAINER (button), 5);
9768       g_signal_connect_swapped (button, "clicked",
9769                                 G_CALLBACK (gtk_widget_destroy),
9770                                 window);
9771       gtk_box_pack_start (GTK_BOX (box1), button, FALSE, FALSE, 0);
9772       gtk_widget_set_can_default (button, TRUE);
9773       gtk_widget_grab_default (button);
9774     }
9775
9776   if (!gtk_widget_get_visible (window))
9777     gtk_widget_show_all (window);
9778   else
9779     gtk_widget_destroy (window);
9780 }
9781
9782 /*
9783  * GtkPanes
9784  */
9785
9786 void
9787 toggle_resize (GtkWidget *widget, GtkWidget *child)
9788 {
9789   GtkContainer *container = GTK_CONTAINER (gtk_widget_get_parent (child));
9790   GValue value = { 0, };
9791   g_value_init (&value, G_TYPE_BOOLEAN);
9792   gtk_container_child_get_property (container, child, "resize", &value);
9793   g_value_set_boolean (&value, !g_value_get_boolean (&value));
9794   gtk_container_child_set_property (container, child, "resize", &value);
9795 }
9796
9797 void
9798 toggle_shrink (GtkWidget *widget, GtkWidget *child)
9799 {
9800   GtkContainer *container = GTK_CONTAINER (gtk_widget_get_parent (child));
9801   GValue value = { 0, };
9802   g_value_init (&value, G_TYPE_BOOLEAN);
9803   gtk_container_child_get_property (container, child, "shrink", &value);
9804   g_value_set_boolean (&value, !g_value_get_boolean (&value));
9805   gtk_container_child_set_property (container, child, "shrink", &value);
9806 }
9807
9808 static void
9809 paned_props_clicked (GtkWidget *button,
9810                      GObject   *paned)
9811 {
9812   GtkWidget *window = create_prop_editor (paned, GTK_TYPE_PANED);
9813   
9814   gtk_window_set_title (GTK_WINDOW (window), "Paned Properties");
9815 }
9816
9817 GtkWidget *
9818 create_pane_options (GtkPaned    *paned,
9819                      const gchar *frame_label,
9820                      const gchar *label1,
9821                      const gchar *label2)
9822 {
9823   GtkWidget *frame;
9824   GtkWidget *table;
9825   GtkWidget *label;
9826   GtkWidget *button;
9827   GtkWidget *check_button;
9828   
9829   frame = gtk_frame_new (frame_label);
9830   gtk_container_set_border_width (GTK_CONTAINER (frame), 4);
9831   
9832   table = gtk_table_new (4, 2, 4);
9833   gtk_container_add (GTK_CONTAINER (frame), table);
9834   
9835   label = gtk_label_new (label1);
9836   gtk_table_attach_defaults (GTK_TABLE (table), label,
9837                              0, 1, 0, 1);
9838   
9839   check_button = gtk_check_button_new_with_label ("Resize");
9840   gtk_table_attach_defaults (GTK_TABLE (table), check_button,
9841                              0, 1, 1, 2);
9842   g_signal_connect (check_button, "toggled",
9843                     G_CALLBACK (toggle_resize),
9844                     paned->child1);
9845   
9846   check_button = gtk_check_button_new_with_label ("Shrink");
9847   gtk_table_attach_defaults (GTK_TABLE (table), check_button,
9848                              0, 1, 2, 3);
9849   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button),
9850                                TRUE);
9851   g_signal_connect (check_button, "toggled",
9852                     G_CALLBACK (toggle_shrink),
9853                     paned->child1);
9854   
9855   label = gtk_label_new (label2);
9856   gtk_table_attach_defaults (GTK_TABLE (table), label,
9857                              1, 2, 0, 1);
9858   
9859   check_button = gtk_check_button_new_with_label ("Resize");
9860   gtk_table_attach_defaults (GTK_TABLE (table), check_button,
9861                              1, 2, 1, 2);
9862   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button),
9863                                TRUE);
9864   g_signal_connect (check_button, "toggled",
9865                     G_CALLBACK (toggle_resize),
9866                     paned->child2);
9867   
9868   check_button = gtk_check_button_new_with_label ("Shrink");
9869   gtk_table_attach_defaults (GTK_TABLE (table), check_button,
9870                              1, 2, 2, 3);
9871   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button),
9872                                TRUE);
9873   g_signal_connect (check_button, "toggled",
9874                     G_CALLBACK (toggle_shrink),
9875                     paned->child2);
9876
9877   button = gtk_button_new_with_mnemonic ("_Properties");
9878   gtk_table_attach_defaults (GTK_TABLE (table), button,
9879                              0, 2, 3, 4);
9880   g_signal_connect (button, "clicked",
9881                     G_CALLBACK (paned_props_clicked),
9882                     paned);
9883
9884   return frame;
9885 }
9886
9887 void
9888 create_panes (GtkWidget *widget)
9889 {
9890   static GtkWidget *window = NULL;
9891   GtkWidget *frame;
9892   GtkWidget *hpaned;
9893   GtkWidget *vpaned;
9894   GtkWidget *button;
9895   GtkWidget *vbox;
9896
9897   if (!window)
9898     {
9899       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9900
9901       gtk_window_set_screen (GTK_WINDOW (window),
9902                              gtk_widget_get_screen (widget));
9903       
9904       g_signal_connect (window, "destroy",
9905                         G_CALLBACK (gtk_widget_destroyed),
9906                         &window);
9907
9908       gtk_window_set_title (GTK_WINDOW (window), "Panes");
9909       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
9910
9911       vbox = gtk_vbox_new (FALSE, 0);
9912       gtk_container_add (GTK_CONTAINER (window), vbox);
9913       
9914       vpaned = gtk_vpaned_new ();
9915       gtk_box_pack_start (GTK_BOX (vbox), vpaned, TRUE, TRUE, 0);
9916       gtk_container_set_border_width (GTK_CONTAINER(vpaned), 5);
9917
9918       hpaned = gtk_hpaned_new ();
9919       gtk_paned_add1 (GTK_PANED (vpaned), hpaned);
9920
9921       frame = gtk_frame_new (NULL);
9922       gtk_frame_set_shadow_type (GTK_FRAME(frame), GTK_SHADOW_IN);
9923       gtk_widget_set_size_request (frame, 60, 60);
9924       gtk_paned_add1 (GTK_PANED (hpaned), frame);
9925       
9926       button = gtk_button_new_with_label ("Hi there");
9927       gtk_container_add (GTK_CONTAINER(frame), button);
9928
9929       frame = gtk_frame_new (NULL);
9930       gtk_frame_set_shadow_type (GTK_FRAME(frame), GTK_SHADOW_IN);
9931       gtk_widget_set_size_request (frame, 80, 60);
9932       gtk_paned_add2 (GTK_PANED (hpaned), frame);
9933
9934       frame = gtk_frame_new (NULL);
9935       gtk_frame_set_shadow_type (GTK_FRAME(frame), GTK_SHADOW_IN);
9936       gtk_widget_set_size_request (frame, 60, 80);
9937       gtk_paned_add2 (GTK_PANED (vpaned), frame);
9938
9939       /* Now create toggle buttons to control sizing */
9940
9941       gtk_box_pack_start (GTK_BOX (vbox),
9942                           create_pane_options (GTK_PANED (hpaned),
9943                                                "Horizontal",
9944                                                "Left",
9945                                                "Right"),
9946                           FALSE, FALSE, 0);
9947
9948       gtk_box_pack_start (GTK_BOX (vbox),
9949                           create_pane_options (GTK_PANED (vpaned),
9950                                                "Vertical",
9951                                                "Top",
9952                                                "Bottom"),
9953                           FALSE, FALSE, 0);
9954
9955       gtk_widget_show_all (vbox);
9956     }
9957
9958   if (!gtk_widget_get_visible (window))
9959     gtk_widget_show (window);
9960   else
9961     gtk_widget_destroy (window);
9962 }
9963
9964 /*
9965  * Paned keyboard navigation
9966  */
9967
9968 static GtkWidget*
9969 paned_keyboard_window1 (GtkWidget *widget)
9970 {
9971   GtkWidget *window1;
9972   GtkWidget *hpaned1;
9973   GtkWidget *frame1;
9974   GtkWidget *vbox1;
9975   GtkWidget *button7;
9976   GtkWidget *button8;
9977   GtkWidget *button9;
9978   GtkWidget *vpaned1;
9979   GtkWidget *frame2;
9980   GtkWidget *frame5;
9981   GtkWidget *hbox1;
9982   GtkWidget *button5;
9983   GtkWidget *button6;
9984   GtkWidget *frame3;
9985   GtkWidget *frame4;
9986   GtkWidget *table1;
9987   GtkWidget *button1;
9988   GtkWidget *button2;
9989   GtkWidget *button3;
9990   GtkWidget *button4;
9991
9992   window1 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9993   gtk_window_set_title (GTK_WINDOW (window1), "Basic paned navigation");
9994   gtk_window_set_screen (GTK_WINDOW (window1), 
9995                          gtk_widget_get_screen (widget));
9996
9997   hpaned1 = gtk_hpaned_new ();
9998   gtk_container_add (GTK_CONTAINER (window1), hpaned1);
9999
10000   frame1 = gtk_frame_new (NULL);
10001   gtk_paned_pack1 (GTK_PANED (hpaned1), frame1, FALSE, TRUE);
10002   gtk_frame_set_shadow_type (GTK_FRAME (frame1), GTK_SHADOW_IN);
10003
10004   vbox1 = gtk_vbox_new (FALSE, 0);
10005   gtk_container_add (GTK_CONTAINER (frame1), vbox1);
10006
10007   button7 = gtk_button_new_with_label ("button7");
10008   gtk_box_pack_start (GTK_BOX (vbox1), button7, FALSE, FALSE, 0);
10009
10010   button8 = gtk_button_new_with_label ("button8");
10011   gtk_box_pack_start (GTK_BOX (vbox1), button8, FALSE, FALSE, 0);
10012
10013   button9 = gtk_button_new_with_label ("button9");
10014   gtk_box_pack_start (GTK_BOX (vbox1), button9, FALSE, FALSE, 0);
10015
10016   vpaned1 = gtk_vpaned_new ();
10017   gtk_paned_pack2 (GTK_PANED (hpaned1), vpaned1, TRUE, TRUE);
10018
10019   frame2 = gtk_frame_new (NULL);
10020   gtk_paned_pack1 (GTK_PANED (vpaned1), frame2, FALSE, TRUE);
10021   gtk_frame_set_shadow_type (GTK_FRAME (frame2), GTK_SHADOW_IN);
10022
10023   frame5 = gtk_frame_new (NULL);
10024   gtk_container_add (GTK_CONTAINER (frame2), frame5);
10025
10026   hbox1 = gtk_hbox_new (FALSE, 0);
10027   gtk_container_add (GTK_CONTAINER (frame5), hbox1);
10028
10029   button5 = gtk_button_new_with_label ("button5");
10030   gtk_box_pack_start (GTK_BOX (hbox1), button5, FALSE, FALSE, 0);
10031
10032   button6 = gtk_button_new_with_label ("button6");
10033   gtk_box_pack_start (GTK_BOX (hbox1), button6, FALSE, FALSE, 0);
10034
10035   frame3 = gtk_frame_new (NULL);
10036   gtk_paned_pack2 (GTK_PANED (vpaned1), frame3, TRUE, TRUE);
10037   gtk_frame_set_shadow_type (GTK_FRAME (frame3), GTK_SHADOW_IN);
10038
10039   frame4 = gtk_frame_new ("Buttons");
10040   gtk_container_add (GTK_CONTAINER (frame3), frame4);
10041   gtk_container_set_border_width (GTK_CONTAINER (frame4), 15);
10042
10043   table1 = gtk_table_new (2, 2, FALSE);
10044   gtk_container_add (GTK_CONTAINER (frame4), table1);
10045   gtk_container_set_border_width (GTK_CONTAINER (table1), 11);
10046
10047   button1 = gtk_button_new_with_label ("button1");
10048   gtk_table_attach (GTK_TABLE (table1), button1, 0, 1, 0, 1,
10049                     (GtkAttachOptions) (GTK_FILL),
10050                     (GtkAttachOptions) (0), 0, 0);
10051
10052   button2 = gtk_button_new_with_label ("button2");
10053   gtk_table_attach (GTK_TABLE (table1), button2, 1, 2, 0, 1,
10054                     (GtkAttachOptions) (GTK_FILL),
10055                     (GtkAttachOptions) (0), 0, 0);
10056
10057   button3 = gtk_button_new_with_label ("button3");
10058   gtk_table_attach (GTK_TABLE (table1), button3, 0, 1, 1, 2,
10059                     (GtkAttachOptions) (GTK_FILL),
10060                     (GtkAttachOptions) (0), 0, 0);
10061
10062   button4 = gtk_button_new_with_label ("button4");
10063   gtk_table_attach (GTK_TABLE (table1), button4, 1, 2, 1, 2,
10064                     (GtkAttachOptions) (GTK_FILL),
10065                     (GtkAttachOptions) (0), 0, 0);
10066
10067   return window1;
10068 }
10069
10070 static GtkWidget*
10071 paned_keyboard_window2 (GtkWidget *widget)
10072 {
10073   GtkWidget *window2;
10074   GtkWidget *hpaned2;
10075   GtkWidget *frame6;
10076   GtkWidget *button13;
10077   GtkWidget *hbox2;
10078   GtkWidget *vpaned2;
10079   GtkWidget *frame7;
10080   GtkWidget *button12;
10081   GtkWidget *frame8;
10082   GtkWidget *button11;
10083   GtkWidget *button10;
10084
10085   window2 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
10086   gtk_window_set_title (GTK_WINDOW (window2), "\"button 10\" is not inside the horisontal pane");
10087
10088   gtk_window_set_screen (GTK_WINDOW (window2), 
10089                          gtk_widget_get_screen (widget));
10090
10091   hpaned2 = gtk_hpaned_new ();
10092   gtk_container_add (GTK_CONTAINER (window2), hpaned2);
10093
10094   frame6 = gtk_frame_new (NULL);
10095   gtk_paned_pack1 (GTK_PANED (hpaned2), frame6, FALSE, TRUE);
10096   gtk_frame_set_shadow_type (GTK_FRAME (frame6), GTK_SHADOW_IN);
10097
10098   button13 = gtk_button_new_with_label ("button13");
10099   gtk_container_add (GTK_CONTAINER (frame6), button13);
10100
10101   hbox2 = gtk_hbox_new (FALSE, 0);
10102   gtk_paned_pack2 (GTK_PANED (hpaned2), hbox2, TRUE, TRUE);
10103
10104   vpaned2 = gtk_vpaned_new ();
10105   gtk_box_pack_start (GTK_BOX (hbox2), vpaned2, TRUE, TRUE, 0);
10106
10107   frame7 = gtk_frame_new (NULL);
10108   gtk_paned_pack1 (GTK_PANED (vpaned2), frame7, FALSE, TRUE);
10109   gtk_frame_set_shadow_type (GTK_FRAME (frame7), GTK_SHADOW_IN);
10110
10111   button12 = gtk_button_new_with_label ("button12");
10112   gtk_container_add (GTK_CONTAINER (frame7), button12);
10113
10114   frame8 = gtk_frame_new (NULL);
10115   gtk_paned_pack2 (GTK_PANED (vpaned2), frame8, TRUE, TRUE);
10116   gtk_frame_set_shadow_type (GTK_FRAME (frame8), GTK_SHADOW_IN);
10117
10118   button11 = gtk_button_new_with_label ("button11");
10119   gtk_container_add (GTK_CONTAINER (frame8), button11);
10120
10121   button10 = gtk_button_new_with_label ("button10");
10122   gtk_box_pack_start (GTK_BOX (hbox2), button10, FALSE, FALSE, 0);
10123
10124   return window2;
10125 }
10126
10127 static GtkWidget*
10128 paned_keyboard_window3 (GtkWidget *widget)
10129 {
10130   GtkWidget *window3;
10131   GtkWidget *vbox2;
10132   GtkWidget *label1;
10133   GtkWidget *hpaned3;
10134   GtkWidget *frame9;
10135   GtkWidget *button14;
10136   GtkWidget *hpaned4;
10137   GtkWidget *frame10;
10138   GtkWidget *button15;
10139   GtkWidget *hpaned5;
10140   GtkWidget *frame11;
10141   GtkWidget *button16;
10142   GtkWidget *frame12;
10143   GtkWidget *button17;
10144
10145   window3 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
10146   g_object_set_data (G_OBJECT (window3), "window3", window3);
10147   gtk_window_set_title (GTK_WINDOW (window3), "Nested panes");
10148
10149   gtk_window_set_screen (GTK_WINDOW (window3), 
10150                          gtk_widget_get_screen (widget));
10151   
10152
10153   vbox2 = gtk_vbox_new (FALSE, 0);
10154   gtk_container_add (GTK_CONTAINER (window3), vbox2);
10155
10156   label1 = gtk_label_new ("Three panes nested inside each other");
10157   gtk_box_pack_start (GTK_BOX (vbox2), label1, FALSE, FALSE, 0);
10158
10159   hpaned3 = gtk_hpaned_new ();
10160   gtk_box_pack_start (GTK_BOX (vbox2), hpaned3, TRUE, TRUE, 0);
10161
10162   frame9 = gtk_frame_new (NULL);
10163   gtk_paned_pack1 (GTK_PANED (hpaned3), frame9, FALSE, TRUE);
10164   gtk_frame_set_shadow_type (GTK_FRAME (frame9), GTK_SHADOW_IN);
10165
10166   button14 = gtk_button_new_with_label ("button14");
10167   gtk_container_add (GTK_CONTAINER (frame9), button14);
10168
10169   hpaned4 = gtk_hpaned_new ();
10170   gtk_paned_pack2 (GTK_PANED (hpaned3), hpaned4, TRUE, TRUE);
10171
10172   frame10 = gtk_frame_new (NULL);
10173   gtk_paned_pack1 (GTK_PANED (hpaned4), frame10, FALSE, TRUE);
10174   gtk_frame_set_shadow_type (GTK_FRAME (frame10), GTK_SHADOW_IN);
10175
10176   button15 = gtk_button_new_with_label ("button15");
10177   gtk_container_add (GTK_CONTAINER (frame10), button15);
10178
10179   hpaned5 = gtk_hpaned_new ();
10180   gtk_paned_pack2 (GTK_PANED (hpaned4), hpaned5, TRUE, TRUE);
10181
10182   frame11 = gtk_frame_new (NULL);
10183   gtk_paned_pack1 (GTK_PANED (hpaned5), frame11, FALSE, TRUE);
10184   gtk_frame_set_shadow_type (GTK_FRAME (frame11), GTK_SHADOW_IN);
10185
10186   button16 = gtk_button_new_with_label ("button16");
10187   gtk_container_add (GTK_CONTAINER (frame11), button16);
10188
10189   frame12 = gtk_frame_new (NULL);
10190   gtk_paned_pack2 (GTK_PANED (hpaned5), frame12, TRUE, TRUE);
10191   gtk_frame_set_shadow_type (GTK_FRAME (frame12), GTK_SHADOW_IN);
10192
10193   button17 = gtk_button_new_with_label ("button17");
10194   gtk_container_add (GTK_CONTAINER (frame12), button17);
10195
10196   return window3;
10197 }
10198
10199 static GtkWidget*
10200 paned_keyboard_window4 (GtkWidget *widget)
10201 {
10202   GtkWidget *window4;
10203   GtkWidget *vbox3;
10204   GtkWidget *label2;
10205   GtkWidget *hpaned6;
10206   GtkWidget *vpaned3;
10207   GtkWidget *button19;
10208   GtkWidget *button18;
10209   GtkWidget *hbox3;
10210   GtkWidget *vpaned4;
10211   GtkWidget *button21;
10212   GtkWidget *button20;
10213   GtkWidget *vpaned5;
10214   GtkWidget *button23;
10215   GtkWidget *button22;
10216   GtkWidget *vpaned6;
10217   GtkWidget *button25;
10218   GtkWidget *button24;
10219
10220   window4 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
10221   g_object_set_data (G_OBJECT (window4), "window4", window4);
10222   gtk_window_set_title (GTK_WINDOW (window4), "window4");
10223
10224   gtk_window_set_screen (GTK_WINDOW (window4), 
10225                          gtk_widget_get_screen (widget));
10226
10227   vbox3 = gtk_vbox_new (FALSE, 0);
10228   gtk_container_add (GTK_CONTAINER (window4), vbox3);
10229
10230   label2 = gtk_label_new ("Widget tree:\n\nhpaned \n - vpaned\n - hbox\n    - vpaned\n    - vpaned\n    - vpaned\n");
10231   gtk_box_pack_start (GTK_BOX (vbox3), label2, FALSE, FALSE, 0);
10232   gtk_label_set_justify (GTK_LABEL (label2), GTK_JUSTIFY_LEFT);
10233
10234   hpaned6 = gtk_hpaned_new ();
10235   gtk_box_pack_start (GTK_BOX (vbox3), hpaned6, TRUE, TRUE, 0);
10236
10237   vpaned3 = gtk_vpaned_new ();
10238   gtk_paned_pack1 (GTK_PANED (hpaned6), vpaned3, FALSE, TRUE);
10239
10240   button19 = gtk_button_new_with_label ("button19");
10241   gtk_paned_pack1 (GTK_PANED (vpaned3), button19, FALSE, TRUE);
10242
10243   button18 = gtk_button_new_with_label ("button18");
10244   gtk_paned_pack2 (GTK_PANED (vpaned3), button18, TRUE, TRUE);
10245
10246   hbox3 = gtk_hbox_new (FALSE, 0);
10247   gtk_paned_pack2 (GTK_PANED (hpaned6), hbox3, TRUE, TRUE);
10248
10249   vpaned4 = gtk_vpaned_new ();
10250   gtk_box_pack_start (GTK_BOX (hbox3), vpaned4, TRUE, TRUE, 0);
10251
10252   button21 = gtk_button_new_with_label ("button21");
10253   gtk_paned_pack1 (GTK_PANED (vpaned4), button21, FALSE, TRUE);
10254
10255   button20 = gtk_button_new_with_label ("button20");
10256   gtk_paned_pack2 (GTK_PANED (vpaned4), button20, TRUE, TRUE);
10257
10258   vpaned5 = gtk_vpaned_new ();
10259   gtk_box_pack_start (GTK_BOX (hbox3), vpaned5, TRUE, TRUE, 0);
10260
10261   button23 = gtk_button_new_with_label ("button23");
10262   gtk_paned_pack1 (GTK_PANED (vpaned5), button23, FALSE, TRUE);
10263
10264   button22 = gtk_button_new_with_label ("button22");
10265   gtk_paned_pack2 (GTK_PANED (vpaned5), button22, TRUE, TRUE);
10266
10267   vpaned6 = gtk_vpaned_new ();
10268   gtk_box_pack_start (GTK_BOX (hbox3), vpaned6, TRUE, TRUE, 0);
10269
10270   button25 = gtk_button_new_with_label ("button25");
10271   gtk_paned_pack1 (GTK_PANED (vpaned6), button25, FALSE, TRUE);
10272
10273   button24 = gtk_button_new_with_label ("button24");
10274   gtk_paned_pack2 (GTK_PANED (vpaned6), button24, TRUE, TRUE);
10275
10276   return window4;
10277 }
10278
10279 static void
10280 create_paned_keyboard_navigation (GtkWidget *widget)
10281 {
10282   static GtkWidget *window1 = NULL;
10283   static GtkWidget *window2 = NULL;
10284   static GtkWidget *window3 = NULL;
10285   static GtkWidget *window4 = NULL;
10286
10287   if (window1 && 
10288      (gtk_widget_get_screen (window1) != gtk_widget_get_screen (widget)))
10289     {
10290       gtk_widget_destroy (window1);
10291       gtk_widget_destroy (window2);
10292       gtk_widget_destroy (window3);
10293       gtk_widget_destroy (window4);
10294     }
10295   
10296   if (!window1)
10297     {
10298       window1 = paned_keyboard_window1 (widget);
10299       g_signal_connect (window1, "destroy",
10300                         G_CALLBACK (gtk_widget_destroyed),
10301                         &window1);
10302     }
10303
10304   if (!window2)
10305     {
10306       window2 = paned_keyboard_window2 (widget);
10307       g_signal_connect (window2, "destroy",
10308                         G_CALLBACK (gtk_widget_destroyed),
10309                         &window2);
10310     }
10311
10312   if (!window3)
10313     {
10314       window3 = paned_keyboard_window3 (widget);
10315       g_signal_connect (window3, "destroy",
10316                         G_CALLBACK (gtk_widget_destroyed),
10317                         &window3);
10318     }
10319
10320   if (!window4)
10321     {
10322       window4 = paned_keyboard_window4 (widget);
10323       g_signal_connect (window4, "destroy",
10324                         G_CALLBACK (gtk_widget_destroyed),
10325                         &window4);
10326     }
10327
10328   if (gtk_widget_get_visible (window1))
10329     gtk_widget_destroy (GTK_WIDGET (window1));
10330   else
10331     gtk_widget_show_all (GTK_WIDGET (window1));
10332
10333   if (gtk_widget_get_visible (window2))
10334     gtk_widget_destroy (GTK_WIDGET (window2));
10335   else
10336     gtk_widget_show_all (GTK_WIDGET (window2));
10337
10338   if (gtk_widget_get_visible (window3))
10339     gtk_widget_destroy (GTK_WIDGET (window3));
10340   else
10341     gtk_widget_show_all (GTK_WIDGET (window3));
10342
10343   if (gtk_widget_get_visible (window4))
10344     gtk_widget_destroy (GTK_WIDGET (window4));
10345   else
10346     gtk_widget_show_all (GTK_WIDGET (window4));
10347 }
10348
10349
10350 /*
10351  * Shaped Windows
10352  */
10353
10354 typedef struct _cursoroffset {gint x,y;} CursorOffset;
10355
10356 static void
10357 shape_pressed (GtkWidget *widget, GdkEventButton *event)
10358 {
10359   CursorOffset *p;
10360
10361   /* ignore double and triple click */
10362   if (event->type != GDK_BUTTON_PRESS)
10363     return;
10364
10365   p = g_object_get_data (G_OBJECT (widget), "cursor_offset");
10366   p->x = (int) event->x;
10367   p->y = (int) event->y;
10368
10369   gtk_grab_add (widget);
10370   gdk_pointer_grab (widget->window, TRUE,
10371                     GDK_BUTTON_RELEASE_MASK |
10372                     GDK_BUTTON_MOTION_MASK |
10373                     GDK_POINTER_MOTION_HINT_MASK,
10374                     NULL, NULL, 0);
10375 }
10376
10377 static void
10378 shape_released (GtkWidget *widget)
10379 {
10380   gtk_grab_remove (widget);
10381   gdk_display_pointer_ungrab (gtk_widget_get_display (widget),
10382                               GDK_CURRENT_TIME);
10383 }
10384
10385 static void
10386 shape_motion (GtkWidget      *widget, 
10387               GdkEventMotion *event)
10388 {
10389   gint xp, yp;
10390   CursorOffset * p;
10391   GdkModifierType mask;
10392
10393   p = g_object_get_data (G_OBJECT (widget), "cursor_offset");
10394
10395   /*
10396    * Can't use event->x / event->y here 
10397    * because I need absolute coordinates.
10398    */
10399   gdk_window_get_pointer (NULL, &xp, &yp, &mask);
10400   gtk_widget_set_uposition (widget, xp  - p->x, yp  - p->y);
10401 }
10402
10403 GtkWidget *
10404 shape_create_icon (GdkScreen *screen,
10405                    char      *xpm_file,
10406                    gint       x,
10407                    gint       y,
10408                    gint       px,
10409                    gint       py,
10410                    gint       window_type)
10411 {
10412   GtkWidget *window;
10413   GtkWidget *pixmap;
10414   GtkWidget *fixed;
10415   CursorOffset* icon_pos;
10416   GdkGC* gc;
10417   GdkBitmap *gdk_pixmap_mask;
10418   GdkPixmap *gdk_pixmap;
10419   GtkStyle *style;
10420
10421   style = gtk_widget_get_default_style ();
10422   gc = style->black_gc; 
10423
10424   /*
10425    * GDK_WINDOW_TOPLEVEL works also, giving you a title border
10426    */
10427   window = gtk_window_new (window_type);
10428   gtk_window_set_screen (GTK_WINDOW (window), screen);
10429   
10430   fixed = gtk_fixed_new ();
10431   gtk_widget_set_size_request (fixed, 100, 100);
10432   gtk_container_add (GTK_CONTAINER (window), fixed);
10433   gtk_widget_show (fixed);
10434   
10435   gtk_widget_set_events (window, 
10436                          gtk_widget_get_events (window) |
10437                          GDK_BUTTON_MOTION_MASK |
10438                          GDK_POINTER_MOTION_HINT_MASK |
10439                          GDK_BUTTON_PRESS_MASK);
10440
10441   gtk_widget_realize (window);
10442   gdk_pixmap = gdk_pixmap_create_from_xpm (window->window, &gdk_pixmap_mask, 
10443                                            &style->bg[GTK_STATE_NORMAL],
10444                                            xpm_file);
10445
10446   pixmap = gtk_image_new_from_pixmap (gdk_pixmap, gdk_pixmap_mask);
10447   gtk_fixed_put (GTK_FIXED (fixed), pixmap, px,py);
10448   gtk_widget_show (pixmap);
10449   
10450   gtk_widget_shape_combine_mask (window, gdk_pixmap_mask, px, py);
10451   
10452   g_object_unref (gdk_pixmap_mask);
10453   g_object_unref (gdk_pixmap);
10454
10455   g_signal_connect (window, "button_press_event",
10456                     G_CALLBACK (shape_pressed), NULL);
10457   g_signal_connect (window, "button_release_event",
10458                     G_CALLBACK (shape_released), NULL);
10459   g_signal_connect (window, "motion_notify_event",
10460                     G_CALLBACK (shape_motion), NULL);
10461
10462   icon_pos = g_new (CursorOffset, 1);
10463   g_object_set_data (G_OBJECT (window), "cursor_offset", icon_pos);
10464
10465   gtk_widget_set_uposition (window, x, y);
10466   gtk_widget_show (window);
10467   
10468   return window;
10469 }
10470
10471 void 
10472 create_shapes (GtkWidget *widget)
10473 {
10474   /* Variables used by the Drag/Drop and Shape Window demos */
10475   static GtkWidget *modeller = NULL;
10476   static GtkWidget *sheets = NULL;
10477   static GtkWidget *rings = NULL;
10478   static GtkWidget *with_region = NULL;
10479   GdkScreen *screen = gtk_widget_get_screen (widget);
10480   
10481   if (!(file_exists ("Modeller.xpm") &&
10482         file_exists ("FilesQueue.xpm") &&
10483         file_exists ("3DRings.xpm")))
10484     return;
10485   
10486
10487   if (!modeller)
10488     {
10489       modeller = shape_create_icon (screen, "Modeller.xpm",
10490                                     440, 140, 0,0, GTK_WINDOW_POPUP);
10491
10492       g_signal_connect (modeller, "destroy",
10493                         G_CALLBACK (gtk_widget_destroyed),
10494                         &modeller);
10495     }
10496   else
10497     gtk_widget_destroy (modeller);
10498
10499   if (!sheets)
10500     {
10501       sheets = shape_create_icon (screen, "FilesQueue.xpm",
10502                                   580, 170, 0,0, GTK_WINDOW_POPUP);
10503
10504       g_signal_connect (sheets, "destroy",
10505                         G_CALLBACK (gtk_widget_destroyed),
10506                         &sheets);
10507
10508     }
10509   else
10510     gtk_widget_destroy (sheets);
10511
10512   if (!rings)
10513     {
10514       rings = shape_create_icon (screen, "3DRings.xpm",
10515                                  460, 270, 25,25, GTK_WINDOW_TOPLEVEL);
10516
10517       g_signal_connect (rings, "destroy",
10518                         G_CALLBACK (gtk_widget_destroyed),
10519                         &rings);
10520     }
10521   else
10522     gtk_widget_destroy (rings);
10523
10524   if (!with_region)
10525     {
10526       GdkRegion *region;
10527       gint x, y;
10528       
10529       with_region = shape_create_icon (screen, "3DRings.xpm",
10530                                        460, 270, 25,25, GTK_WINDOW_TOPLEVEL);
10531
10532       gtk_window_set_decorated (GTK_WINDOW (with_region), FALSE);
10533       
10534       g_signal_connect (with_region, "destroy",
10535                         G_CALLBACK (gtk_widget_destroyed),
10536                         &with_region);
10537
10538       /* reset shape from mask to a region */
10539       x = 0;
10540       y = 0;
10541       region = gdk_region_new ();
10542
10543       while (x < 460)
10544         {
10545           while (y < 270)
10546             {
10547               GdkRectangle rect;
10548               rect.x = x;
10549               rect.y = y;
10550               rect.width = 10;
10551               rect.height = 10;
10552
10553               gdk_region_union_with_rect (region, &rect);
10554               
10555               y += 20;
10556             }
10557           y = 0;
10558           x += 20;
10559         }
10560
10561       gdk_window_shape_combine_region (with_region->window,
10562                                        region,
10563                                        0, 0);
10564     }
10565   else
10566     gtk_widget_destroy (with_region);
10567 }
10568
10569 /*
10570  * WM Hints demo
10571  */
10572
10573 void
10574 create_wmhints (GtkWidget *widget)
10575 {
10576   static GtkWidget *window = NULL;
10577   GtkWidget *label;
10578   GtkWidget *separator;
10579   GtkWidget *button;
10580   GtkWidget *box1;
10581   GtkWidget *box2;
10582
10583   GdkBitmap *circles;
10584
10585   if (!window)
10586     {
10587       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
10588
10589       gtk_window_set_screen (GTK_WINDOW (window),
10590                              gtk_widget_get_screen (widget));
10591       
10592       g_signal_connect (window, "destroy",
10593                         G_CALLBACK (gtk_widget_destroyed),
10594                         &window);
10595
10596       gtk_window_set_title (GTK_WINDOW (window), "WM Hints");
10597       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
10598
10599       gtk_widget_realize (window);
10600       
10601       circles = gdk_bitmap_create_from_data (window->window,
10602                                              (gchar *) circles_bits,
10603                                              circles_width,
10604                                              circles_height);
10605       gdk_window_set_icon (window->window, NULL,
10606                            circles, circles);
10607       
10608       gdk_window_set_icon_name (window->window, "WMHints Test Icon");
10609   
10610       gdk_window_set_decorations (window->window, GDK_DECOR_ALL | GDK_DECOR_MENU);
10611       gdk_window_set_functions (window->window, GDK_FUNC_ALL | GDK_FUNC_RESIZE);
10612       
10613       box1 = gtk_vbox_new (FALSE, 0);
10614       gtk_container_add (GTK_CONTAINER (window), box1);
10615       gtk_widget_show (box1);
10616
10617       label = gtk_label_new ("Try iconizing me!");
10618       gtk_widget_set_size_request (label, 150, 50);
10619       gtk_box_pack_start (GTK_BOX (box1), label, TRUE, TRUE, 0);
10620       gtk_widget_show (label);
10621
10622
10623       separator = gtk_hseparator_new ();
10624       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
10625       gtk_widget_show (separator);
10626
10627
10628       box2 = gtk_vbox_new (FALSE, 10);
10629       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
10630       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
10631       gtk_widget_show (box2);
10632
10633
10634       button = gtk_button_new_with_label ("close");
10635
10636       g_signal_connect_swapped (button, "clicked",
10637                                 G_CALLBACK (gtk_widget_destroy),
10638                                 window);
10639
10640       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
10641       gtk_widget_set_can_default (button, TRUE);
10642       gtk_widget_grab_default (button);
10643       gtk_widget_show (button);
10644     }
10645
10646   if (!gtk_widget_get_visible (window))
10647     gtk_widget_show (window);
10648   else
10649     gtk_widget_destroy (window);
10650 }
10651
10652
10653 /*
10654  * Window state tracking
10655  */
10656
10657 static gint
10658 window_state_callback (GtkWidget *widget,
10659                        GdkEventWindowState *event,
10660                        gpointer data)
10661 {
10662   GtkWidget *label = data;
10663   gchar *msg;
10664
10665   msg = g_strconcat (GTK_WINDOW (widget)->title, ": ",
10666                      (event->new_window_state & GDK_WINDOW_STATE_WITHDRAWN) ?
10667                      "withdrawn" : "not withdrawn", ", ",
10668                      (event->new_window_state & GDK_WINDOW_STATE_ICONIFIED) ?
10669                      "iconified" : "not iconified", ", ",
10670                      (event->new_window_state & GDK_WINDOW_STATE_STICKY) ?
10671                      "sticky" : "not sticky", ", ",
10672                      (event->new_window_state & GDK_WINDOW_STATE_MAXIMIZED) ?
10673                      "maximized" : "not maximized", ", ",
10674                      (event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN) ?
10675                      "fullscreen" : "not fullscreen",
10676                      (event->new_window_state & GDK_WINDOW_STATE_ABOVE) ?
10677                      "above" : "not above", ", ",
10678                      (event->new_window_state & GDK_WINDOW_STATE_BELOW) ?
10679                      "below" : "not below", ", ",
10680                      NULL);
10681   
10682   gtk_label_set_text (GTK_LABEL (label), msg);
10683
10684   g_free (msg);
10685
10686   return FALSE;
10687 }
10688
10689 static GtkWidget*
10690 tracking_label (GtkWidget *window)
10691 {
10692   GtkWidget *label;
10693   GtkWidget *hbox;
10694   GtkWidget *button;
10695
10696   hbox = gtk_hbox_new (FALSE, 5);
10697
10698   g_signal_connect_object (hbox,
10699                            "destroy",
10700                            G_CALLBACK (gtk_widget_destroy),
10701                            window,
10702                            G_CONNECT_SWAPPED);
10703   
10704   label = gtk_label_new ("<no window state events received>");
10705   gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
10706   gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
10707   
10708   g_signal_connect (window,
10709                     "window_state_event",
10710                     G_CALLBACK (window_state_callback),
10711                     label);
10712
10713   button = gtk_button_new_with_label ("Deiconify");
10714   g_signal_connect_object (button,
10715                            "clicked",
10716                            G_CALLBACK (gtk_window_deiconify),
10717                            window,
10718                            G_CONNECT_SWAPPED);
10719   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
10720
10721   button = gtk_button_new_with_label ("Iconify");
10722   g_signal_connect_object (button,
10723                            "clicked",
10724                            G_CALLBACK (gtk_window_iconify),
10725                            window,
10726                            G_CONNECT_SWAPPED);
10727   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
10728
10729   button = gtk_button_new_with_label ("Fullscreen");
10730   g_signal_connect_object (button,
10731                            "clicked",
10732                            G_CALLBACK (gtk_window_fullscreen),
10733                            window,
10734                            G_CONNECT_SWAPPED);
10735   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
10736
10737   button = gtk_button_new_with_label ("Unfullscreen");
10738   g_signal_connect_object (button,
10739                            "clicked",
10740                            G_CALLBACK (gtk_window_unfullscreen),
10741                            window,
10742                            G_CONNECT_SWAPPED);
10743   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
10744   
10745   button = gtk_button_new_with_label ("Present");
10746   g_signal_connect_object (button,
10747                            "clicked",
10748                            G_CALLBACK (gtk_window_present),
10749                            window,
10750                            G_CONNECT_SWAPPED);
10751   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
10752
10753   button = gtk_button_new_with_label ("Show");
10754   g_signal_connect_object (button,
10755                            "clicked",
10756                            G_CALLBACK (gtk_widget_show),
10757                            window,
10758                            G_CONNECT_SWAPPED);
10759   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
10760   
10761   gtk_widget_show_all (hbox);
10762   
10763   return hbox;
10764 }
10765
10766 void
10767 keep_window_above (GtkToggleButton *togglebutton, gpointer data)
10768 {
10769   GtkWidget *button = g_object_get_data (G_OBJECT (togglebutton), "radio");
10770
10771   gtk_window_set_keep_above (GTK_WINDOW (data),
10772                              gtk_toggle_button_get_active (togglebutton));
10773
10774   if (gtk_toggle_button_get_active (togglebutton))
10775     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE);
10776 }
10777
10778 void
10779 keep_window_below (GtkToggleButton *togglebutton, gpointer data)
10780 {
10781   GtkWidget *button = g_object_get_data (G_OBJECT (togglebutton), "radio");
10782
10783   gtk_window_set_keep_below (GTK_WINDOW (data),
10784                              gtk_toggle_button_get_active (togglebutton));
10785
10786   if (gtk_toggle_button_get_active (togglebutton))
10787     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE);
10788 }
10789
10790
10791 static GtkWidget*
10792 get_state_controls (GtkWidget *window)
10793 {
10794   GtkWidget *vbox;
10795   GtkWidget *button;
10796   GtkWidget *button_above;
10797   GtkWidget *button_below;
10798
10799   vbox = gtk_vbox_new (FALSE, 0);
10800   
10801   button = gtk_button_new_with_label ("Stick");
10802   g_signal_connect_object (button,
10803                            "clicked",
10804                            G_CALLBACK (gtk_window_stick),
10805                            window,
10806                            G_CONNECT_SWAPPED);
10807   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
10808
10809   button = gtk_button_new_with_label ("Unstick");
10810   g_signal_connect_object (button,
10811                            "clicked",
10812                            G_CALLBACK (gtk_window_unstick),
10813                            window,
10814                            G_CONNECT_SWAPPED);
10815   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
10816   
10817   button = gtk_button_new_with_label ("Maximize");
10818   g_signal_connect_object (button,
10819                            "clicked",
10820                            G_CALLBACK (gtk_window_maximize),
10821                            window,
10822                            G_CONNECT_SWAPPED);
10823   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
10824
10825   button = gtk_button_new_with_label ("Unmaximize");
10826   g_signal_connect_object (button,
10827                            "clicked",
10828                            G_CALLBACK (gtk_window_unmaximize),
10829                            window,
10830                            G_CONNECT_SWAPPED);
10831   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
10832
10833   button = gtk_button_new_with_label ("Iconify");
10834   g_signal_connect_object (button,
10835                            "clicked",
10836                            G_CALLBACK (gtk_window_iconify),
10837                            window,
10838                            G_CONNECT_SWAPPED);
10839   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
10840
10841   button = gtk_button_new_with_label ("Fullscreen");
10842   g_signal_connect_object (button,
10843                            "clicked",
10844                            G_CALLBACK (gtk_window_fullscreen),
10845                            window,
10846                            G_CONNECT_SWAPPED);
10847   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
10848
10849   button = gtk_button_new_with_label ("Unfullscreen");
10850   g_signal_connect_object (button,
10851                            "clicked",
10852                            G_CALLBACK (gtk_window_unfullscreen),
10853                            window,
10854                            G_CONNECT_SWAPPED);
10855   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
10856
10857   button_above = gtk_toggle_button_new_with_label ("Keep above");
10858   g_signal_connect (button_above,
10859                     "toggled",
10860                     G_CALLBACK (keep_window_above),
10861                     window);
10862   gtk_box_pack_start (GTK_BOX (vbox), button_above, FALSE, FALSE, 0);
10863
10864   button_below = gtk_toggle_button_new_with_label ("Keep below");
10865   g_signal_connect (button_below,
10866                     "toggled",
10867                     G_CALLBACK (keep_window_below),
10868                     window);
10869   gtk_box_pack_start (GTK_BOX (vbox), button_below, FALSE, FALSE, 0);
10870
10871   g_object_set_data (G_OBJECT (button_above), "radio", button_below);
10872   g_object_set_data (G_OBJECT (button_below), "radio", button_above);
10873
10874   button = gtk_button_new_with_label ("Hide (withdraw)");
10875   g_signal_connect_object (button,
10876                            "clicked",
10877                            G_CALLBACK (gtk_widget_hide),
10878                            window,
10879                            G_CONNECT_SWAPPED);
10880   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
10881   
10882   gtk_widget_show_all (vbox);
10883
10884   return vbox;
10885 }
10886
10887 void
10888 create_window_states (GtkWidget *widget)
10889 {
10890   static GtkWidget *window = NULL;
10891   GtkWidget *label;
10892   GtkWidget *box1;
10893   GtkWidget *iconified;
10894   GtkWidget *normal;
10895   GtkWidget *controls;
10896
10897   if (!window)
10898     {
10899       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
10900       gtk_window_set_screen (GTK_WINDOW (window),
10901                              gtk_widget_get_screen (widget));
10902
10903       g_signal_connect (window, "destroy",
10904                         G_CALLBACK (gtk_widget_destroyed),
10905                         &window);
10906
10907       gtk_window_set_title (GTK_WINDOW (window), "Window states");
10908       
10909       box1 = gtk_vbox_new (FALSE, 0);
10910       gtk_container_add (GTK_CONTAINER (window), box1);
10911
10912       iconified = gtk_window_new (GTK_WINDOW_TOPLEVEL);
10913
10914       gtk_window_set_screen (GTK_WINDOW (iconified),
10915                              gtk_widget_get_screen (widget));
10916       
10917       g_signal_connect_object (iconified, "destroy",
10918                                G_CALLBACK (gtk_widget_destroy),
10919                                window,
10920                                G_CONNECT_SWAPPED);
10921       gtk_window_iconify (GTK_WINDOW (iconified));
10922       gtk_window_set_title (GTK_WINDOW (iconified), "Iconified initially");
10923       controls = get_state_controls (iconified);
10924       gtk_container_add (GTK_CONTAINER (iconified), controls);
10925       
10926       normal = gtk_window_new (GTK_WINDOW_TOPLEVEL);
10927
10928       gtk_window_set_screen (GTK_WINDOW (normal),
10929                              gtk_widget_get_screen (widget));
10930       
10931       g_signal_connect_object (normal, "destroy",
10932                                G_CALLBACK (gtk_widget_destroy),
10933                                window,
10934                                G_CONNECT_SWAPPED);
10935       
10936       gtk_window_set_title (GTK_WINDOW (normal), "Deiconified initially");
10937       controls = get_state_controls (normal);
10938       gtk_container_add (GTK_CONTAINER (normal), controls);
10939       
10940       label = tracking_label (iconified);
10941       gtk_container_add (GTK_CONTAINER (box1), label);
10942
10943       label = tracking_label (normal);
10944       gtk_container_add (GTK_CONTAINER (box1), label);
10945
10946       gtk_widget_show_all (iconified);
10947       gtk_widget_show_all (normal);
10948       gtk_widget_show_all (box1);
10949     }
10950
10951   if (!gtk_widget_get_visible (window))
10952     gtk_widget_show (window);
10953   else
10954     gtk_widget_destroy (window);
10955 }
10956
10957 /*
10958  * Window sizing
10959  */
10960
10961 static gint
10962 configure_event_callback (GtkWidget *widget,
10963                           GdkEventConfigure *event,
10964                           gpointer data)
10965 {
10966   GtkWidget *label = data;
10967   gchar *msg;
10968   gint x, y;
10969   
10970   gtk_window_get_position (GTK_WINDOW (widget), &x, &y);
10971   
10972   msg = g_strdup_printf ("event: %d,%d  %d x %d\n"
10973                          "position: %d, %d",
10974                          event->x, event->y, event->width, event->height,
10975                          x, y);
10976   
10977   gtk_label_set_text (GTK_LABEL (label), msg);
10978
10979   g_free (msg);
10980
10981   return FALSE;
10982 }
10983
10984 static void
10985 get_ints (GtkWidget *window,
10986           gint      *a,
10987           gint      *b)
10988 {
10989   GtkWidget *spin1;
10990   GtkWidget *spin2;
10991
10992   spin1 = g_object_get_data (G_OBJECT (window), "spin1");
10993   spin2 = g_object_get_data (G_OBJECT (window), "spin2");
10994
10995   *a = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (spin1));
10996   *b = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (spin2));
10997 }
10998
10999 static void
11000 set_size_callback (GtkWidget *widget,
11001                    gpointer   data)
11002 {
11003   gint w, h;
11004   
11005   get_ints (data, &w, &h);
11006
11007   gtk_window_resize (GTK_WINDOW (g_object_get_data (data, "target")), w, h);
11008 }
11009
11010 static void
11011 unset_default_size_callback (GtkWidget *widget,
11012                              gpointer   data)
11013 {
11014   gtk_window_set_default_size (g_object_get_data (data, "target"),
11015                                -1, -1);
11016 }
11017
11018 static void
11019 set_default_size_callback (GtkWidget *widget,
11020                            gpointer   data)
11021 {
11022   gint w, h;
11023   
11024   get_ints (data, &w, &h);
11025
11026   gtk_window_set_default_size (g_object_get_data (data, "target"),
11027                                w, h);
11028 }
11029
11030 static void
11031 unset_size_request_callback (GtkWidget *widget,
11032                              gpointer   data)
11033 {
11034   gtk_widget_set_size_request (g_object_get_data (data, "target"),
11035                                -1, -1);
11036 }
11037
11038 static void
11039 set_size_request_callback (GtkWidget *widget,
11040                            gpointer   data)
11041 {
11042   gint w, h;
11043   
11044   get_ints (data, &w, &h);
11045
11046   gtk_widget_set_size_request (g_object_get_data (data, "target"),
11047                                w, h);
11048 }
11049
11050 static void
11051 set_location_callback (GtkWidget *widget,
11052                        gpointer   data)
11053 {
11054   gint x, y;
11055   
11056   get_ints (data, &x, &y);
11057
11058   gtk_window_move (g_object_get_data (data, "target"), x, y);
11059 }
11060
11061 static void
11062 move_to_position_callback (GtkWidget *widget,
11063                            gpointer   data)
11064 {
11065   gint x, y;
11066   GtkWindow *window;
11067
11068   window = g_object_get_data (data, "target");
11069   
11070   gtk_window_get_position (window, &x, &y);
11071
11072   gtk_window_move (window, x, y);
11073 }
11074
11075 static void
11076 set_geometry_callback (GtkWidget *entry,
11077                        gpointer   data)
11078 {
11079   gchar *text;
11080   GtkWindow *target;
11081
11082   target = GTK_WINDOW (g_object_get_data (G_OBJECT (data), "target"));
11083   
11084   text = gtk_editable_get_chars (GTK_EDITABLE (entry), 0, -1);
11085
11086   if (!gtk_window_parse_geometry (target, text))
11087     g_print ("Bad geometry string '%s'\n", text);
11088
11089   g_free (text);
11090 }
11091
11092 static void
11093 allow_shrink_callback (GtkWidget *widget,
11094                        gpointer   data)
11095 {
11096   g_object_set (g_object_get_data (data, "target"),
11097                 "allow_shrink",
11098                 GTK_TOGGLE_BUTTON (widget)->active,
11099                 NULL);
11100 }
11101
11102 static void
11103 allow_grow_callback (GtkWidget *widget,
11104                      gpointer   data)
11105 {
11106   g_object_set (g_object_get_data (data, "target"),
11107                 "allow_grow",
11108                 GTK_TOGGLE_BUTTON (widget)->active,
11109                 NULL);
11110 }
11111
11112 static void
11113 gravity_selected (GtkWidget *widget,
11114                   gpointer   data)
11115 {
11116   gtk_window_set_gravity (GTK_WINDOW (g_object_get_data (data, "target")),
11117                           gtk_option_menu_get_history (GTK_OPTION_MENU (widget)) + GDK_GRAVITY_NORTH_WEST);
11118 }
11119
11120 static void
11121 pos_selected (GtkWidget *widget,
11122               gpointer   data)
11123 {
11124   gtk_window_set_position (GTK_WINDOW (g_object_get_data (data, "target")),
11125                            gtk_option_menu_get_history (GTK_OPTION_MENU (widget)) + GTK_WIN_POS_NONE);
11126 }
11127
11128 static void
11129 move_gravity_window_to_current_position (GtkWidget *widget,
11130                                          gpointer   data)
11131 {
11132   gint x, y;
11133   GtkWindow *window;
11134
11135   window = GTK_WINDOW (data);    
11136   
11137   gtk_window_get_position (window, &x, &y);
11138
11139   gtk_window_move (window, x, y);
11140 }
11141
11142 static void
11143 get_screen_corner (GtkWindow *window,
11144                    gint      *x,
11145                    gint      *y)
11146 {
11147   int w, h;
11148   GdkScreen * screen = gtk_window_get_screen (window);
11149   
11150   gtk_window_get_size (GTK_WINDOW (window), &w, &h);
11151
11152   switch (gtk_window_get_gravity (window))
11153     {
11154     case GDK_GRAVITY_SOUTH_EAST:
11155       *x = gdk_screen_get_width (screen) - w;
11156       *y = gdk_screen_get_height (screen) - h;
11157       break;
11158
11159     case GDK_GRAVITY_NORTH_EAST:
11160       *x = gdk_screen_get_width (screen) - w;
11161       *y = 0;
11162       break;
11163
11164     case GDK_GRAVITY_SOUTH_WEST:
11165       *x = 0;
11166       *y = gdk_screen_get_height (screen) - h;
11167       break;
11168
11169     case GDK_GRAVITY_NORTH_WEST:
11170       *x = 0;
11171       *y = 0;
11172       break;
11173       
11174     case GDK_GRAVITY_SOUTH:
11175       *x = (gdk_screen_get_width (screen) - w) / 2;
11176       *y = gdk_screen_get_height (screen) - h;
11177       break;
11178
11179     case GDK_GRAVITY_NORTH:
11180       *x = (gdk_screen_get_width (screen) - w) / 2;
11181       *y = 0;
11182       break;
11183
11184     case GDK_GRAVITY_WEST:
11185       *x = 0;
11186       *y = (gdk_screen_get_height (screen) - h) / 2;
11187       break;
11188
11189     case GDK_GRAVITY_EAST:
11190       *x = gdk_screen_get_width (screen) - w;
11191       *y = (gdk_screen_get_height (screen) - h) / 2;
11192       break;
11193
11194     case GDK_GRAVITY_CENTER:
11195       *x = (gdk_screen_get_width (screen) - w) / 2;
11196       *y = (gdk_screen_get_height (screen) - h) / 2;
11197       break;
11198
11199     case GDK_GRAVITY_STATIC:
11200       /* pick some random numbers */
11201       *x = 350;
11202       *y = 350;
11203       break;
11204
11205     default:
11206       g_assert_not_reached ();
11207       break;
11208     }
11209 }
11210
11211 static void
11212 move_gravity_window_to_starting_position (GtkWidget *widget,
11213                                           gpointer   data)
11214 {
11215   gint x, y;
11216   GtkWindow *window;
11217
11218   window = GTK_WINDOW (data);    
11219   
11220   get_screen_corner (window,
11221                      &x, &y);
11222   
11223   gtk_window_move (window, x, y);
11224 }
11225
11226 static GtkWidget*
11227 make_gravity_window (GtkWidget   *destroy_with,
11228                      GdkGravity   gravity,
11229                      const gchar *title)
11230 {
11231   GtkWidget *window;
11232   GtkWidget *button;
11233   GtkWidget *vbox;
11234   int x, y;
11235   
11236   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
11237
11238   gtk_window_set_screen (GTK_WINDOW (window),
11239                          gtk_widget_get_screen (destroy_with));
11240
11241   vbox = gtk_vbox_new (FALSE, 0);
11242   gtk_widget_show (vbox);
11243   
11244   gtk_container_add (GTK_CONTAINER (window), vbox);
11245   gtk_window_set_title (GTK_WINDOW (window), title);
11246   gtk_window_set_gravity (GTK_WINDOW (window), gravity);
11247
11248   g_signal_connect_object (destroy_with,
11249                            "destroy",
11250                            G_CALLBACK (gtk_widget_destroy),
11251                            window,
11252                            G_CONNECT_SWAPPED);
11253
11254   
11255   button = gtk_button_new_with_mnemonic ("_Move to current position");
11256
11257   g_signal_connect (button, "clicked",
11258                     G_CALLBACK (move_gravity_window_to_current_position),
11259                     window);
11260
11261   gtk_container_add (GTK_CONTAINER (vbox), button);
11262   gtk_widget_show (button);
11263
11264   button = gtk_button_new_with_mnemonic ("Move to _starting position");
11265
11266   g_signal_connect (button, "clicked",
11267                     G_CALLBACK (move_gravity_window_to_starting_position),
11268                     window);
11269
11270   gtk_container_add (GTK_CONTAINER (vbox), button);
11271   gtk_widget_show (button);
11272   
11273   /* Pretend this is the result of --geometry.
11274    * DO NOT COPY THIS CODE unless you are setting --geometry results,
11275    * and in that case you probably should just use gtk_window_parse_geometry().
11276    * AGAIN, DO NOT SET GDK_HINT_USER_POS! It violates the ICCCM unless
11277    * you are parsing --geometry or equivalent.
11278    */
11279   gtk_window_set_geometry_hints (GTK_WINDOW (window),
11280                                  NULL, NULL,
11281                                  GDK_HINT_USER_POS);
11282
11283   gtk_window_set_default_size (GTK_WINDOW (window),
11284                                200, 200);
11285
11286   get_screen_corner (GTK_WINDOW (window), &x, &y);
11287   
11288   gtk_window_move (GTK_WINDOW (window),
11289                    x, y);
11290   
11291   return window;
11292 }
11293
11294 static void
11295 do_gravity_test (GtkWidget *widget,
11296                  gpointer   data)
11297 {
11298   GtkWidget *destroy_with = data;
11299   GtkWidget *window;
11300   
11301   /* We put a window at each gravity point on the screen. */
11302   window = make_gravity_window (destroy_with, GDK_GRAVITY_NORTH_WEST,
11303                                 "NorthWest");
11304   gtk_widget_show (window);
11305   
11306   window = make_gravity_window (destroy_with, GDK_GRAVITY_SOUTH_EAST,
11307                                 "SouthEast");
11308   gtk_widget_show (window);
11309
11310   window = make_gravity_window (destroy_with, GDK_GRAVITY_NORTH_EAST,
11311                                 "NorthEast");
11312   gtk_widget_show (window);
11313
11314   window = make_gravity_window (destroy_with, GDK_GRAVITY_SOUTH_WEST,
11315                                 "SouthWest");
11316   gtk_widget_show (window);
11317
11318   window = make_gravity_window (destroy_with, GDK_GRAVITY_SOUTH,
11319                                 "South");
11320   gtk_widget_show (window);
11321
11322   window = make_gravity_window (destroy_with, GDK_GRAVITY_NORTH,
11323                                 "North");
11324   gtk_widget_show (window);
11325
11326   
11327   window = make_gravity_window (destroy_with, GDK_GRAVITY_WEST,
11328                                 "West");
11329   gtk_widget_show (window);
11330
11331     
11332   window = make_gravity_window (destroy_with, GDK_GRAVITY_EAST,
11333                                 "East");
11334   gtk_widget_show (window);
11335
11336   window = make_gravity_window (destroy_with, GDK_GRAVITY_CENTER,
11337                                 "Center");
11338   gtk_widget_show (window);
11339
11340   window = make_gravity_window (destroy_with, GDK_GRAVITY_STATIC,
11341                                 "Static");
11342   gtk_widget_show (window);
11343 }
11344
11345 static GtkWidget*
11346 window_controls (GtkWidget *window)
11347 {
11348   GtkWidget *control_window;
11349   GtkWidget *label;
11350   GtkWidget *vbox;
11351   GtkWidget *button;
11352   GtkWidget *spin;
11353   GtkAdjustment *adj;
11354   GtkWidget *entry;
11355   GtkWidget *om;
11356   GtkWidget *menu;
11357   gint i;
11358   
11359   control_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
11360
11361   gtk_window_set_screen (GTK_WINDOW (control_window),
11362                          gtk_widget_get_screen (window));
11363
11364   gtk_window_set_title (GTK_WINDOW (control_window), "Size controls");
11365   
11366   g_object_set_data (G_OBJECT (control_window),
11367                      "target",
11368                      window);
11369   
11370   g_signal_connect_object (control_window,
11371                            "destroy",
11372                            G_CALLBACK (gtk_widget_destroy),
11373                            window,
11374                            G_CONNECT_SWAPPED);
11375
11376   vbox = gtk_vbox_new (FALSE, 5);
11377   
11378   gtk_container_add (GTK_CONTAINER (control_window), vbox);
11379   
11380   label = gtk_label_new ("<no configure events>");
11381   gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
11382   
11383   g_signal_connect (window,
11384                     "configure_event",
11385                     G_CALLBACK (configure_event_callback),
11386                     label);
11387
11388   adj = (GtkAdjustment *) gtk_adjustment_new (10.0, -2000.0, 2000.0, 1.0,
11389                                               5.0, 0.0);
11390   spin = gtk_spin_button_new (adj, 0, 0);
11391
11392   gtk_box_pack_start (GTK_BOX (vbox), spin, FALSE, FALSE, 0);
11393
11394   g_object_set_data (G_OBJECT (control_window), "spin1", spin);
11395
11396   adj = (GtkAdjustment *) gtk_adjustment_new (10.0, -2000.0, 2000.0, 1.0,
11397                                               5.0, 0.0);
11398   spin = gtk_spin_button_new (adj, 0, 0);
11399
11400   gtk_box_pack_start (GTK_BOX (vbox), spin, FALSE, FALSE, 0);
11401
11402   g_object_set_data (G_OBJECT (control_window), "spin2", spin);
11403
11404   entry = gtk_entry_new ();
11405   gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
11406
11407   g_signal_connect (entry, "changed",
11408                     G_CALLBACK (set_geometry_callback),
11409                     control_window);
11410
11411   button = gtk_button_new_with_label ("Show gravity test windows");
11412   g_signal_connect_swapped (button,
11413                             "clicked",
11414                             G_CALLBACK (do_gravity_test),
11415                             control_window);
11416   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
11417
11418   button = gtk_button_new_with_label ("Reshow with initial size");
11419   g_signal_connect_object (button,
11420                            "clicked",
11421                            G_CALLBACK (gtk_window_reshow_with_initial_size),
11422                            window,
11423                            G_CONNECT_SWAPPED);
11424   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
11425   
11426   button = gtk_button_new_with_label ("Queue resize");
11427   g_signal_connect_object (button,
11428                            "clicked",
11429                            G_CALLBACK (gtk_widget_queue_resize),
11430                            window,
11431                            G_CONNECT_SWAPPED);
11432   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
11433   
11434   button = gtk_button_new_with_label ("Resize");
11435   g_signal_connect (button,
11436                     "clicked",
11437                     G_CALLBACK (set_size_callback),
11438                     control_window);
11439   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
11440
11441   button = gtk_button_new_with_label ("Set default size");
11442   g_signal_connect (button,
11443                     "clicked",
11444                     G_CALLBACK (set_default_size_callback),
11445                     control_window);
11446   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
11447
11448   button = gtk_button_new_with_label ("Unset default size");
11449   g_signal_connect (button,
11450                     "clicked",
11451                     G_CALLBACK (unset_default_size_callback),
11452                     control_window);
11453   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
11454   
11455   button = gtk_button_new_with_label ("Set size request");
11456   g_signal_connect (button,
11457                     "clicked",
11458                     G_CALLBACK (set_size_request_callback),
11459                     control_window);
11460   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
11461
11462   button = gtk_button_new_with_label ("Unset size request");
11463   g_signal_connect (button,
11464                     "clicked",
11465                     G_CALLBACK (unset_size_request_callback),
11466                     control_window);
11467   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
11468   
11469   button = gtk_button_new_with_label ("Move");
11470   g_signal_connect (button,
11471                     "clicked",
11472                     G_CALLBACK (set_location_callback),
11473                     control_window);
11474   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
11475
11476   button = gtk_button_new_with_label ("Move to current position");
11477   g_signal_connect (button,
11478                     "clicked",
11479                     G_CALLBACK (move_to_position_callback),
11480                     control_window);
11481   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
11482   
11483   button = gtk_check_button_new_with_label ("Allow shrink");
11484   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE);
11485   g_signal_connect (button,
11486                     "toggled",
11487                     G_CALLBACK (allow_shrink_callback),
11488                     control_window);
11489   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
11490
11491   button = gtk_check_button_new_with_label ("Allow grow");
11492   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
11493   g_signal_connect (button,
11494                     "toggled",
11495                     G_CALLBACK (allow_grow_callback),
11496                     control_window);
11497   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
11498   
11499   button = gtk_button_new_with_mnemonic ("_Show");
11500   g_signal_connect_object (button,
11501                            "clicked",
11502                            G_CALLBACK (gtk_widget_show),
11503                            window,
11504                            G_CONNECT_SWAPPED);
11505   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
11506
11507   button = gtk_button_new_with_mnemonic ("_Hide");
11508   g_signal_connect_object (button,
11509                            "clicked",
11510                            G_CALLBACK (gtk_widget_hide),
11511                            window,
11512                            G_CONNECT_SWAPPED);
11513   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
11514   
11515   menu = gtk_menu_new ();
11516   
11517   i = 0;
11518   while (i < 10)
11519     {
11520       GtkWidget *mi;
11521       static gchar *names[] = {
11522         "GDK_GRAVITY_NORTH_WEST",
11523         "GDK_GRAVITY_NORTH",
11524         "GDK_GRAVITY_NORTH_EAST",
11525         "GDK_GRAVITY_WEST",
11526         "GDK_GRAVITY_CENTER",
11527         "GDK_GRAVITY_EAST",
11528         "GDK_GRAVITY_SOUTH_WEST",
11529         "GDK_GRAVITY_SOUTH",
11530         "GDK_GRAVITY_SOUTH_EAST",
11531         "GDK_GRAVITY_STATIC",
11532         NULL
11533       };
11534
11535       g_assert (names[i]);
11536       
11537       mi = gtk_menu_item_new_with_label (names[i]);
11538
11539       gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
11540
11541       ++i;
11542     }
11543   
11544   gtk_widget_show_all (menu);
11545   
11546   om = gtk_option_menu_new ();
11547   gtk_option_menu_set_menu (GTK_OPTION_MENU (om), menu);
11548   
11549
11550   g_signal_connect (om,
11551                     "changed",
11552                     G_CALLBACK (gravity_selected),
11553                     control_window);
11554
11555   gtk_box_pack_end (GTK_BOX (vbox), om, FALSE, FALSE, 0);
11556
11557
11558   menu = gtk_menu_new ();
11559   
11560   i = 0;
11561   while (i < 5)
11562     {
11563       GtkWidget *mi;
11564       static gchar *names[] = {
11565         "GTK_WIN_POS_NONE",
11566         "GTK_WIN_POS_CENTER",
11567         "GTK_WIN_POS_MOUSE",
11568         "GTK_WIN_POS_CENTER_ALWAYS",
11569         "GTK_WIN_POS_CENTER_ON_PARENT",
11570         NULL
11571       };
11572
11573       g_assert (names[i]);
11574       
11575       mi = gtk_menu_item_new_with_label (names[i]);
11576
11577       gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
11578
11579       ++i;
11580     }
11581   
11582   gtk_widget_show_all (menu);
11583   
11584   om = gtk_option_menu_new ();
11585   gtk_option_menu_set_menu (GTK_OPTION_MENU (om), menu);
11586   
11587
11588   g_signal_connect (om,
11589                     "changed",
11590                     G_CALLBACK (pos_selected),
11591                     control_window);
11592
11593   gtk_box_pack_end (GTK_BOX (vbox), om, FALSE, FALSE, 0);
11594   
11595   gtk_widget_show_all (vbox);
11596   
11597   return control_window;
11598 }
11599
11600 void
11601 create_window_sizing (GtkWidget *widget)
11602 {
11603   static GtkWidget *window = NULL;
11604   static GtkWidget *target_window = NULL;
11605
11606   if (!target_window)
11607     {
11608       GtkWidget *label;
11609       
11610       target_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
11611       gtk_window_set_screen (GTK_WINDOW (target_window),
11612                              gtk_widget_get_screen (widget));
11613       label = gtk_label_new (NULL);
11614       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");
11615       gtk_container_add (GTK_CONTAINER (target_window), label);
11616       gtk_widget_show (label);
11617       
11618       g_signal_connect (target_window, "destroy",
11619                         G_CALLBACK (gtk_widget_destroyed),
11620                         &target_window);
11621
11622       window = window_controls (target_window);
11623       
11624       g_signal_connect (window, "destroy",
11625                         G_CALLBACK (gtk_widget_destroyed),
11626                         &window);
11627       
11628       gtk_window_set_title (GTK_WINDOW (target_window), "Window to size");
11629     }
11630
11631   /* don't show target window by default, we want to allow testing
11632    * of behavior on first show.
11633    */
11634   
11635   if (!gtk_widget_get_visible (window))
11636     gtk_widget_show (window);
11637   else
11638     gtk_widget_destroy (window);
11639 }
11640
11641 /*
11642  * GtkProgressBar
11643  */
11644
11645 typedef struct _ProgressData {
11646   GtkWidget *window;
11647   GtkWidget *pbar;
11648   GtkWidget *block_spin;
11649   GtkWidget *x_align_spin;
11650   GtkWidget *y_align_spin;
11651   GtkWidget *step_spin;
11652   GtkWidget *act_blocks_spin;
11653   GtkWidget *label;
11654   GtkWidget *omenu1;
11655   GtkWidget *elmenu;
11656   GtkWidget *omenu2;
11657   GtkWidget *entry;
11658   int timer;
11659 } ProgressData;
11660
11661 gint
11662 progress_timeout (gpointer data)
11663 {
11664   gdouble new_val;
11665   GtkAdjustment *adj;
11666
11667   adj = GTK_PROGRESS (data)->adjustment;
11668
11669   new_val = adj->value + 1;
11670   if (new_val > adj->upper)
11671     new_val = adj->lower;
11672
11673   gtk_progress_set_value (GTK_PROGRESS (data), new_val);
11674
11675   return TRUE;
11676 }
11677
11678 static void
11679 destroy_progress (GtkWidget     *widget,
11680                   ProgressData **pdata)
11681 {
11682   gtk_timeout_remove ((*pdata)->timer);
11683   (*pdata)->timer = 0;
11684   (*pdata)->window = NULL;
11685   g_free (*pdata);
11686   *pdata = NULL;
11687 }
11688
11689 static void
11690 progressbar_toggle_orientation (GtkWidget *widget, gpointer data)
11691 {
11692   ProgressData *pdata;
11693   gint i;
11694
11695   pdata = (ProgressData *) data;
11696
11697   if (!gtk_widget_get_mapped (widget))
11698     return;
11699
11700   i = gtk_option_menu_get_history (GTK_OPTION_MENU (widget));
11701
11702   gtk_progress_bar_set_orientation (GTK_PROGRESS_BAR (pdata->pbar),
11703                                     (GtkProgressBarOrientation) i);
11704 }
11705
11706 static void
11707 toggle_show_text (GtkWidget *widget, ProgressData *pdata)
11708 {
11709   gtk_progress_set_show_text (GTK_PROGRESS (pdata->pbar),
11710                               GTK_TOGGLE_BUTTON (widget)->active);
11711   gtk_widget_set_sensitive (pdata->entry, GTK_TOGGLE_BUTTON (widget)->active);
11712   gtk_widget_set_sensitive (pdata->x_align_spin,
11713                             GTK_TOGGLE_BUTTON (widget)->active);
11714   gtk_widget_set_sensitive (pdata->y_align_spin,
11715                             GTK_TOGGLE_BUTTON (widget)->active);
11716 }
11717
11718 static void
11719 progressbar_toggle_ellipsize (GtkWidget *widget,
11720                               gpointer   data)
11721 {
11722   ProgressData *pdata = data;
11723   if (gtk_widget_is_drawable (widget))
11724     {
11725       gint i = gtk_option_menu_get_history (GTK_OPTION_MENU (widget));
11726       gtk_progress_bar_set_ellipsize (GTK_PROGRESS_BAR (pdata->pbar), i);
11727     }
11728 }
11729
11730 static void
11731 progressbar_toggle_bar_style (GtkWidget *widget, gpointer data)
11732 {
11733   ProgressData *pdata;
11734   gint i;
11735
11736   pdata = (ProgressData *) data;
11737
11738   if (!gtk_widget_get_mapped (widget))
11739     return;
11740
11741   i = gtk_option_menu_get_history (GTK_OPTION_MENU (widget));
11742
11743   if (i == 1)
11744     gtk_widget_set_sensitive (pdata->block_spin, TRUE);
11745   else
11746     gtk_widget_set_sensitive (pdata->block_spin, FALSE);
11747   
11748   gtk_progress_bar_set_bar_style (GTK_PROGRESS_BAR (pdata->pbar),
11749                                   (GtkProgressBarStyle) i);
11750 }
11751
11752 static void
11753 progress_value_changed (GtkAdjustment *adj, ProgressData *pdata)
11754 {
11755   char buf[20];
11756
11757   if (GTK_PROGRESS (pdata->pbar)->activity_mode)
11758     sprintf (buf, "???");
11759   else
11760     sprintf (buf, "%.0f%%", 100 *
11761              gtk_progress_get_current_percentage (GTK_PROGRESS (pdata->pbar)));
11762   gtk_label_set_text (GTK_LABEL (pdata->label), buf);
11763 }
11764
11765 static void
11766 adjust_blocks (GtkAdjustment *adj, ProgressData *pdata)
11767 {
11768   gtk_progress_set_percentage (GTK_PROGRESS (pdata->pbar), 0);
11769   gtk_progress_bar_set_discrete_blocks (GTK_PROGRESS_BAR (pdata->pbar),
11770      gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (pdata->block_spin)));
11771 }
11772
11773 static void
11774 adjust_step (GtkAdjustment *adj, ProgressData *pdata)
11775 {
11776   gtk_progress_bar_set_activity_step (GTK_PROGRESS_BAR (pdata->pbar),
11777      gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (pdata->step_spin)));
11778 }
11779
11780 static void
11781 adjust_act_blocks (GtkAdjustment *adj, ProgressData *pdata)
11782 {
11783   gtk_progress_bar_set_activity_blocks (GTK_PROGRESS_BAR (pdata->pbar),
11784                gtk_spin_button_get_value_as_int 
11785                       (GTK_SPIN_BUTTON (pdata->act_blocks_spin)));
11786 }
11787
11788 static void
11789 adjust_align (GtkAdjustment *adj, ProgressData *pdata)
11790 {
11791   gtk_progress_set_text_alignment (GTK_PROGRESS (pdata->pbar),
11792          gtk_spin_button_get_value (GTK_SPIN_BUTTON (pdata->x_align_spin)),
11793          gtk_spin_button_get_value (GTK_SPIN_BUTTON (pdata->y_align_spin)));
11794 }
11795
11796 static void
11797 toggle_activity_mode (GtkWidget *widget, ProgressData *pdata)
11798 {
11799   gtk_progress_set_activity_mode (GTK_PROGRESS (pdata->pbar),
11800                                   GTK_TOGGLE_BUTTON (widget)->active);
11801   gtk_widget_set_sensitive (pdata->step_spin, 
11802                             GTK_TOGGLE_BUTTON (widget)->active);
11803   gtk_widget_set_sensitive (pdata->act_blocks_spin, 
11804                             GTK_TOGGLE_BUTTON (widget)->active);
11805 }
11806
11807 static void
11808 entry_changed (GtkWidget *widget, ProgressData *pdata)
11809 {
11810   gtk_progress_set_format_string (GTK_PROGRESS (pdata->pbar),
11811                           gtk_entry_get_text (GTK_ENTRY (pdata->entry)));
11812 }
11813
11814 void
11815 create_progress_bar (GtkWidget *widget)
11816 {
11817   GtkWidget *button;
11818   GtkWidget *vbox;
11819   GtkWidget *vbox2;
11820   GtkWidget *hbox;
11821   GtkWidget *check;
11822   GtkWidget *frame;
11823   GtkWidget *tab;
11824   GtkWidget *label;
11825   GtkWidget *align;
11826   GtkAdjustment *adj;
11827   static ProgressData *pdata = NULL;
11828
11829   static gchar *items1[] =
11830   {
11831     "Left-Right",
11832     "Right-Left",
11833     "Bottom-Top",
11834     "Top-Bottom"
11835   };
11836
11837   static gchar *items2[] =
11838   {
11839     "Continuous",
11840     "Discrete"
11841   };
11842
11843   static char *ellipsize_items[] = {
11844     "None",     // PANGO_ELLIPSIZE_NONE,
11845     "Start",    // PANGO_ELLIPSIZE_START,
11846     "Middle",   // PANGO_ELLIPSIZE_MIDDLE,
11847     "End",      // PANGO_ELLIPSIZE_END
11848   };
11849   
11850   if (!pdata)
11851     pdata = g_new0 (ProgressData, 1);
11852
11853   if (!pdata->window)
11854     {
11855       pdata->window = gtk_dialog_new ();
11856
11857       gtk_window_set_screen (GTK_WINDOW (pdata->window),
11858                              gtk_widget_get_screen (widget));
11859
11860       gtk_window_set_resizable (GTK_WINDOW (pdata->window), TRUE);
11861
11862       g_signal_connect (pdata->window, "destroy",
11863                         G_CALLBACK (destroy_progress),
11864                         &pdata);
11865
11866       pdata->timer = 0;
11867
11868       gtk_window_set_title (GTK_WINDOW (pdata->window), "GtkProgressBar");
11869       gtk_container_set_border_width (GTK_CONTAINER (pdata->window), 0);
11870
11871       vbox = gtk_vbox_new (FALSE, 5);
11872       gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
11873       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (pdata->window)->vbox), 
11874                           vbox, FALSE, TRUE, 0);
11875
11876       frame = gtk_frame_new ("Progress");
11877       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
11878
11879       vbox2 = gtk_vbox_new (FALSE, 5);
11880       gtk_container_add (GTK_CONTAINER (frame), vbox2);
11881
11882       align = gtk_alignment_new (0.5, 0.5, 0, 0);
11883       gtk_box_pack_start (GTK_BOX (vbox2), align, FALSE, FALSE, 5);
11884
11885       adj = (GtkAdjustment *) gtk_adjustment_new (0, 1, 300, 0, 0, 0);
11886       g_signal_connect (adj, "value_changed",
11887                         G_CALLBACK (progress_value_changed), pdata);
11888
11889       pdata->pbar = g_object_new (GTK_TYPE_PROGRESS_BAR,
11890                                     "adjustment", adj,
11891                                     "ellipsize", PANGO_ELLIPSIZE_MIDDLE,
11892                                     NULL);
11893       gtk_progress_set_format_string (GTK_PROGRESS (pdata->pbar),
11894                                       "%v from [%l,%u] (=%p%%)");
11895       gtk_container_add (GTK_CONTAINER (align), pdata->pbar);
11896       pdata->timer = gtk_timeout_add (100, progress_timeout, pdata->pbar);
11897
11898       align = gtk_alignment_new (0.5, 0.5, 0, 0);
11899       gtk_box_pack_start (GTK_BOX (vbox2), align, FALSE, FALSE, 5);
11900
11901       hbox = gtk_hbox_new (FALSE, 5);
11902       gtk_container_add (GTK_CONTAINER (align), hbox);
11903       label = gtk_label_new ("Label updated by user :"); 
11904       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
11905       pdata->label = gtk_label_new ("");
11906       gtk_box_pack_start (GTK_BOX (hbox), pdata->label, FALSE, TRUE, 0);
11907
11908       frame = gtk_frame_new ("Options");
11909       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
11910
11911       vbox2 = gtk_vbox_new (FALSE, 5);
11912       gtk_container_add (GTK_CONTAINER (frame), vbox2);
11913
11914       tab = gtk_table_new (7, 2, FALSE);
11915       gtk_box_pack_start (GTK_BOX (vbox2), tab, FALSE, TRUE, 0);
11916
11917       label = gtk_label_new ("Orientation :");
11918       gtk_table_attach (GTK_TABLE (tab), label, 0, 1, 0, 1,
11919                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
11920                         5, 5);
11921       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
11922
11923       pdata->omenu1 = build_option_menu (items1, 4, 0,
11924                                          progressbar_toggle_orientation,
11925                                          pdata);
11926       hbox = gtk_hbox_new (FALSE, 0);
11927       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 0, 1,
11928                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
11929                         5, 5);
11930       gtk_box_pack_start (GTK_BOX (hbox), pdata->omenu1, TRUE, TRUE, 0);
11931       
11932       check = gtk_check_button_new_with_label ("Show text");
11933       g_signal_connect (check, "clicked",
11934                         G_CALLBACK (toggle_show_text),
11935                         pdata);
11936       gtk_table_attach (GTK_TABLE (tab), check, 0, 1, 1, 2,
11937                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
11938                         5, 5);
11939
11940       hbox = gtk_hbox_new (FALSE, 0);
11941       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 1, 2,
11942                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
11943                         5, 5);
11944
11945       label = gtk_label_new ("Format : ");
11946       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
11947
11948       pdata->entry = gtk_entry_new ();
11949       g_signal_connect (pdata->entry, "changed",
11950                         G_CALLBACK (entry_changed),
11951                         pdata);
11952       gtk_box_pack_start (GTK_BOX (hbox), pdata->entry, TRUE, TRUE, 0);
11953       gtk_entry_set_text (GTK_ENTRY (pdata->entry), "%v from [%l,%u] (=%p%%)");
11954       gtk_widget_set_size_request (pdata->entry, 100, -1);
11955       gtk_widget_set_sensitive (pdata->entry, FALSE);
11956
11957       label = gtk_label_new ("Text align :");
11958       gtk_table_attach (GTK_TABLE (tab), label, 0, 1, 2, 3,
11959                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
11960                         5, 5);
11961       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
11962
11963       hbox = gtk_hbox_new (FALSE, 0);
11964       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 2, 3,
11965                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
11966                         5, 5);
11967
11968       label = gtk_label_new ("x :");
11969       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 5);
11970       
11971       adj = (GtkAdjustment *) gtk_adjustment_new (0.5, 0, 1, 0.1, 0.1, 0);
11972       pdata->x_align_spin = gtk_spin_button_new (adj, 0, 1);
11973       g_signal_connect (adj, "value_changed",
11974                         G_CALLBACK (adjust_align), pdata);
11975       gtk_box_pack_start (GTK_BOX (hbox), pdata->x_align_spin, FALSE, TRUE, 0);
11976       gtk_widget_set_sensitive (pdata->x_align_spin, FALSE);
11977
11978       label = gtk_label_new ("y :");
11979       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 5);
11980
11981       adj = (GtkAdjustment *) gtk_adjustment_new (0.5, 0, 1, 0.1, 0.1, 0);
11982       pdata->y_align_spin = gtk_spin_button_new (adj, 0, 1);
11983       g_signal_connect (adj, "value_changed",
11984                         G_CALLBACK (adjust_align), pdata);
11985       gtk_box_pack_start (GTK_BOX (hbox), pdata->y_align_spin, FALSE, TRUE, 0);
11986       gtk_widget_set_sensitive (pdata->y_align_spin, FALSE);
11987
11988       label = gtk_label_new ("Ellipsize text :");
11989       gtk_table_attach (GTK_TABLE (tab), label, 0, 1, 10, 11,
11990                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
11991                         5, 5);
11992       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
11993       pdata->elmenu = build_option_menu (ellipsize_items,
11994                                          sizeof (ellipsize_items) / sizeof (ellipsize_items[0]),
11995                                          2, // PANGO_ELLIPSIZE_MIDDLE
11996                                          progressbar_toggle_ellipsize,
11997                                          pdata);
11998       hbox = gtk_hbox_new (FALSE, 0);
11999       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 10, 11,
12000                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
12001                         5, 5);
12002       gtk_box_pack_start (GTK_BOX (hbox), pdata->elmenu, TRUE, TRUE, 0);
12003
12004       label = gtk_label_new ("Bar Style :");
12005       gtk_table_attach (GTK_TABLE (tab), label, 0, 1, 13, 14,
12006                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
12007                         5, 5);
12008       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
12009
12010       pdata->omenu2 = build_option_menu (items2, 2, 0,
12011                                          progressbar_toggle_bar_style,
12012                                          pdata);
12013       hbox = gtk_hbox_new (FALSE, 0);
12014       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 13, 14,
12015                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
12016                         5, 5);
12017       gtk_box_pack_start (GTK_BOX (hbox), pdata->omenu2, TRUE, TRUE, 0);
12018
12019       label = gtk_label_new ("Block count :");
12020       gtk_table_attach (GTK_TABLE (tab), label, 0, 1, 14, 15,
12021                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
12022                         5, 5);
12023       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
12024
12025       hbox = gtk_hbox_new (FALSE, 0);
12026       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 14, 15,
12027                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
12028                         5, 5);
12029       adj = (GtkAdjustment *) gtk_adjustment_new (10, 2, 20, 1, 5, 0);
12030       pdata->block_spin = gtk_spin_button_new (adj, 0, 0);
12031       g_signal_connect (adj, "value_changed",
12032                         G_CALLBACK (adjust_blocks), pdata);
12033       gtk_box_pack_start (GTK_BOX (hbox), pdata->block_spin, FALSE, TRUE, 0);
12034       gtk_widget_set_sensitive (pdata->block_spin, FALSE);
12035
12036       check = gtk_check_button_new_with_label ("Activity mode");
12037       g_signal_connect (check, "clicked",
12038                         G_CALLBACK (toggle_activity_mode), pdata);
12039       gtk_table_attach (GTK_TABLE (tab), check, 0, 1, 15, 16,
12040                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
12041                         5, 5);
12042
12043       hbox = gtk_hbox_new (FALSE, 0);
12044       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 15, 16,
12045                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
12046                         5, 5);
12047       label = gtk_label_new ("Step size : ");
12048       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
12049       adj = (GtkAdjustment *) gtk_adjustment_new (3, 1, 20, 1, 5, 0);
12050       pdata->step_spin = gtk_spin_button_new (adj, 0, 0);
12051       g_signal_connect (adj, "value_changed",
12052                         G_CALLBACK (adjust_step), pdata);
12053       gtk_box_pack_start (GTK_BOX (hbox), pdata->step_spin, FALSE, TRUE, 0);
12054       gtk_widget_set_sensitive (pdata->step_spin, FALSE);
12055
12056       hbox = gtk_hbox_new (FALSE, 0);
12057       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 16, 17,
12058                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
12059                         5, 5);
12060       label = gtk_label_new ("Blocks :     ");
12061       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
12062       adj = (GtkAdjustment *) gtk_adjustment_new (5, 2, 10, 1, 5, 0);
12063       pdata->act_blocks_spin = gtk_spin_button_new (adj, 0, 0);
12064       g_signal_connect (adj, "value_changed",
12065                         G_CALLBACK (adjust_act_blocks), pdata);
12066       gtk_box_pack_start (GTK_BOX (hbox), pdata->act_blocks_spin, FALSE, TRUE,
12067                           0);
12068       gtk_widget_set_sensitive (pdata->act_blocks_spin, FALSE);
12069
12070       button = gtk_button_new_with_label ("close");
12071       g_signal_connect_swapped (button, "clicked",
12072                                 G_CALLBACK (gtk_widget_destroy),
12073                                 pdata->window);
12074       gtk_widget_set_can_default (button, TRUE);
12075       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (pdata->window)->action_area), 
12076                           button, TRUE, TRUE, 0);
12077       gtk_widget_grab_default (button);
12078     }
12079
12080   if (!gtk_widget_get_visible (pdata->window))
12081     gtk_widget_show_all (pdata->window);
12082   else
12083     gtk_widget_destroy (pdata->window);
12084 }
12085
12086 /*
12087  * Properties
12088  */
12089
12090 typedef struct {
12091   int x;
12092   int y;
12093   gboolean found;
12094   gboolean first;
12095   GtkWidget *res_widget;
12096 } FindWidgetData;
12097
12098 static void
12099 find_widget (GtkWidget *widget, FindWidgetData *data)
12100 {
12101   GtkAllocation new_allocation;
12102   gint x_offset = 0;
12103   gint y_offset = 0;
12104
12105   new_allocation = widget->allocation;
12106
12107   if (data->found || !gtk_widget_get_mapped (widget))
12108     return;
12109
12110   /* Note that in the following code, we only count the
12111    * position as being inside a WINDOW widget if it is inside
12112    * widget->window; points that are outside of widget->window
12113    * but within the allocation are not counted. This is consistent
12114    * with the way we highlight drag targets.
12115    */
12116   if (gtk_widget_get_has_window (widget))
12117     {
12118       new_allocation.x = 0;
12119       new_allocation.y = 0;
12120     }
12121   
12122   if (widget->parent && !data->first)
12123     {
12124       GdkWindow *window = widget->window;
12125       while (window != widget->parent->window)
12126         {
12127           gint tx, ty, twidth, theight;
12128           gdk_drawable_get_size (window, &twidth, &theight);
12129
12130           if (new_allocation.x < 0)
12131             {
12132               new_allocation.width += new_allocation.x;
12133               new_allocation.x = 0;
12134             }
12135           if (new_allocation.y < 0)
12136             {
12137               new_allocation.height += new_allocation.y;
12138               new_allocation.y = 0;
12139             }
12140           if (new_allocation.x + new_allocation.width > twidth)
12141             new_allocation.width = twidth - new_allocation.x;
12142           if (new_allocation.y + new_allocation.height > theight)
12143             new_allocation.height = theight - new_allocation.y;
12144
12145           gdk_window_get_position (window, &tx, &ty);
12146           new_allocation.x += tx;
12147           x_offset += tx;
12148           new_allocation.y += ty;
12149           y_offset += ty;
12150           
12151           window = gdk_window_get_parent (window);
12152         }
12153     }
12154
12155   if ((data->x >= new_allocation.x) && (data->y >= new_allocation.y) &&
12156       (data->x < new_allocation.x + new_allocation.width) && 
12157       (data->y < new_allocation.y + new_allocation.height))
12158     {
12159       /* First, check if the drag is in a valid drop site in
12160        * one of our children 
12161        */
12162       if (GTK_IS_CONTAINER (widget))
12163         {
12164           FindWidgetData new_data = *data;
12165           
12166           new_data.x -= x_offset;
12167           new_data.y -= y_offset;
12168           new_data.found = FALSE;
12169           new_data.first = FALSE;
12170           
12171           gtk_container_forall (GTK_CONTAINER (widget),
12172                                 (GtkCallback)find_widget,
12173                                 &new_data);
12174           
12175           data->found = new_data.found;
12176           if (data->found)
12177             data->res_widget = new_data.res_widget;
12178         }
12179
12180       /* If not, and this widget is registered as a drop site, check to
12181        * emit "drag_motion" to check if we are actually in
12182        * a drop site.
12183        */
12184       if (!data->found)
12185         {
12186           data->found = TRUE;
12187           data->res_widget = widget;
12188         }
12189     }
12190 }
12191
12192 static GtkWidget *
12193 find_widget_at_pointer (GdkDisplay *display)
12194 {
12195   GtkWidget *widget = NULL;
12196   GdkWindow *pointer_window;
12197   gint x, y;
12198   FindWidgetData data;
12199  
12200  pointer_window = gdk_display_get_window_at_pointer (display, NULL, NULL);
12201  
12202  if (pointer_window)
12203    {
12204      gpointer widget_ptr;
12205
12206      gdk_window_get_user_data (pointer_window, &widget_ptr);
12207      widget = widget_ptr;
12208    }
12209
12210  if (widget)
12211    {
12212      gdk_window_get_pointer (widget->window,
12213                              &x, &y, NULL);
12214      
12215      data.x = x;
12216      data.y = y;
12217      data.found = FALSE;
12218      data.first = TRUE;
12219
12220      find_widget (widget, &data);
12221      if (data.found)
12222        return data.res_widget;
12223      return widget;
12224    }
12225  return NULL;
12226 }
12227
12228 struct PropertiesData {
12229   GtkWidget **window;
12230   GdkCursor *cursor;
12231   gboolean in_query;
12232   gint handler;
12233 };
12234
12235 static void
12236 destroy_properties (GtkWidget             *widget,
12237                     struct PropertiesData *data)
12238 {
12239   if (data->window)
12240     {
12241       *data->window = NULL;
12242       data->window = NULL;
12243     }
12244
12245   if (data->cursor)
12246     {
12247       gdk_cursor_unref (data->cursor);
12248       data->cursor = NULL;
12249     }
12250
12251   if (data->handler)
12252     {
12253       g_signal_handler_disconnect (widget, data->handler);
12254       data->handler = 0;
12255     }
12256
12257   g_free (data);
12258 }
12259
12260 static gint
12261 property_query_event (GtkWidget        *widget,
12262                       GdkEvent         *event,
12263                       struct PropertiesData *data)
12264 {
12265   GtkWidget *res_widget = NULL;
12266
12267   if (!data->in_query)
12268     return FALSE;
12269   
12270   if (event->type == GDK_BUTTON_RELEASE)
12271     {
12272       gtk_grab_remove (widget);
12273       gdk_display_pointer_ungrab (gtk_widget_get_display (widget),
12274                                   GDK_CURRENT_TIME);
12275       
12276       res_widget = find_widget_at_pointer (gtk_widget_get_display (widget));
12277       if (res_widget)
12278         {
12279           g_object_set_data (G_OBJECT (res_widget), "prop-editor-screen",
12280                              gtk_widget_get_screen (widget));
12281           create_prop_editor (G_OBJECT (res_widget), 0);
12282         }
12283
12284       data->in_query = FALSE;
12285     }
12286   return FALSE;
12287 }
12288
12289
12290 static void
12291 query_properties (GtkButton *button,
12292                   struct PropertiesData *data)
12293 {
12294   gint failure;
12295
12296   g_signal_connect (button, "event",
12297                     G_CALLBACK (property_query_event), data);
12298
12299
12300   if (!data->cursor)
12301     data->cursor = gdk_cursor_new_for_display (gtk_widget_get_display (GTK_WIDGET (button)),
12302                                                GDK_TARGET);
12303   
12304   failure = gdk_pointer_grab (GTK_WIDGET (button)->window,
12305                               TRUE,
12306                               GDK_BUTTON_RELEASE_MASK,
12307                               NULL,
12308                               data->cursor,
12309                               GDK_CURRENT_TIME);
12310
12311   gtk_grab_add (GTK_WIDGET (button));
12312
12313   data->in_query = TRUE;
12314 }
12315
12316 static void
12317 create_properties (GtkWidget *widget)
12318 {
12319   static GtkWidget *window = NULL;
12320   GtkWidget *button;
12321   GtkWidget *vbox;
12322   GtkWidget *label;
12323   struct PropertiesData *data;
12324
12325   data = g_new (struct PropertiesData, 1);
12326   data->window = &window;
12327   data->in_query = FALSE;
12328   data->cursor = NULL;
12329   data->handler = 0;
12330
12331   if (!window)
12332     {
12333       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
12334
12335       gtk_window_set_screen (GTK_WINDOW (window),
12336                              gtk_widget_get_screen (widget));      
12337
12338       data->handler = g_signal_connect (window, "destroy",
12339                                         G_CALLBACK (destroy_properties),
12340                                         data);
12341
12342       gtk_window_set_title (GTK_WINDOW (window), "test properties");
12343       gtk_container_set_border_width (GTK_CONTAINER (window), 10);
12344
12345       vbox = gtk_vbox_new (FALSE, 1);
12346       gtk_container_add (GTK_CONTAINER (window), vbox);
12347             
12348       label = gtk_label_new ("This is just a dumb test to test properties.\nIf you need a generic module, get GLE.");
12349       gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
12350       
12351       button = gtk_button_new_with_label ("Query properties");
12352       gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
12353       g_signal_connect (button, "clicked",
12354                         G_CALLBACK (query_properties),
12355                         data);
12356     }
12357
12358   if (!gtk_widget_get_visible (window))
12359     gtk_widget_show_all (window);
12360   else
12361     gtk_widget_destroy (window);
12362   
12363 }
12364
12365 struct SnapshotData {
12366   GtkWidget *toplevel_button;
12367   GtkWidget **window;
12368   GdkCursor *cursor;
12369   gboolean in_query;
12370   gboolean is_toplevel;
12371   gint handler;
12372 };
12373
12374 static void
12375 destroy_snapshot_data (GtkWidget             *widget,
12376                        struct SnapshotData *data)
12377 {
12378   if (*data->window)
12379     *data->window = NULL;
12380   
12381   if (data->cursor)
12382     {
12383       gdk_cursor_unref (data->cursor);
12384       data->cursor = NULL;
12385     }
12386
12387   if (data->handler)
12388     {
12389       g_signal_handler_disconnect (widget, data->handler);
12390       data->handler = 0;
12391     }
12392
12393   g_free (data);
12394 }
12395
12396 static gint
12397 snapshot_widget_event (GtkWidget               *widget,
12398                        GdkEvent        *event,
12399                        struct SnapshotData *data)
12400 {
12401   GtkWidget *res_widget = NULL;
12402
12403   if (!data->in_query)
12404     return FALSE;
12405   
12406   if (event->type == GDK_BUTTON_RELEASE)
12407     {
12408       gtk_grab_remove (widget);
12409       gdk_display_pointer_ungrab (gtk_widget_get_display (widget),
12410                                   GDK_CURRENT_TIME);
12411       
12412       res_widget = find_widget_at_pointer (gtk_widget_get_display (widget));
12413       if (data->is_toplevel && res_widget)
12414         res_widget = gtk_widget_get_toplevel (res_widget);
12415       if (res_widget)
12416         {
12417           GdkPixmap *pixmap;
12418           GtkWidget *window, *image;
12419
12420           window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
12421           pixmap = gtk_widget_get_snapshot (res_widget, NULL);
12422           gtk_widget_realize (window);
12423           if (gdk_drawable_get_depth (window->window) != gdk_drawable_get_depth (pixmap))
12424             {
12425               /* this branch is needed to convert ARGB -> RGB */
12426               int width, height;
12427               GdkPixbuf *pixbuf;
12428               gdk_drawable_get_size (pixmap, &width, &height);
12429               pixbuf = gdk_pixbuf_get_from_drawable (NULL, pixmap,
12430                                                      gtk_widget_get_colormap (res_widget),
12431                                                      0, 0,
12432                                                      0, 0,
12433                                                      width, height);
12434               image = gtk_image_new_from_pixbuf (pixbuf);
12435               g_object_unref (pixbuf);
12436             }
12437           else
12438             image = gtk_image_new_from_pixmap (pixmap, NULL);
12439           gtk_container_add (GTK_CONTAINER (window), image);
12440           g_object_unref (pixmap);
12441           gtk_widget_show_all (window);
12442         }
12443
12444       data->in_query = FALSE;
12445     }
12446   return FALSE;
12447 }
12448
12449
12450 static void
12451 snapshot_widget (GtkButton *button,
12452                  struct SnapshotData *data)
12453 {
12454   gint failure;
12455
12456   g_signal_connect (button, "event",
12457                     G_CALLBACK (snapshot_widget_event), data);
12458
12459   data->is_toplevel = GTK_WIDGET (button) == data->toplevel_button;
12460   
12461   if (!data->cursor)
12462     data->cursor = gdk_cursor_new_for_display (gtk_widget_get_display (GTK_WIDGET (button)),
12463                                                GDK_TARGET);
12464   
12465   failure = gdk_pointer_grab (GTK_WIDGET (button)->window,
12466                               TRUE,
12467                               GDK_BUTTON_RELEASE_MASK,
12468                               NULL,
12469                               data->cursor,
12470                               GDK_CURRENT_TIME);
12471
12472   gtk_grab_add (GTK_WIDGET (button));
12473
12474   data->in_query = TRUE;
12475 }
12476
12477 static void
12478 create_snapshot (GtkWidget *widget)
12479 {
12480   static GtkWidget *window = NULL;
12481   GtkWidget *button;
12482   GtkWidget *vbox;
12483   struct SnapshotData *data;
12484
12485   data = g_new (struct SnapshotData, 1);
12486   data->window = &window;
12487   data->in_query = FALSE;
12488   data->cursor = NULL;
12489   data->handler = 0;
12490
12491   if (!window)
12492     {
12493       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
12494
12495       gtk_window_set_screen (GTK_WINDOW (window),
12496                              gtk_widget_get_screen (widget));      
12497
12498       data->handler = g_signal_connect (window, "destroy",
12499                                         G_CALLBACK (destroy_snapshot_data),
12500                                         data);
12501
12502       gtk_window_set_title (GTK_WINDOW (window), "test snapshot");
12503       gtk_container_set_border_width (GTK_CONTAINER (window), 10);
12504
12505       vbox = gtk_vbox_new (FALSE, 1);
12506       gtk_container_add (GTK_CONTAINER (window), vbox);
12507             
12508       button = gtk_button_new_with_label ("Snapshot widget");
12509       gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
12510       g_signal_connect (button, "clicked",
12511                         G_CALLBACK (snapshot_widget),
12512                         data);
12513       
12514       button = gtk_button_new_with_label ("Snapshot toplevel");
12515       data->toplevel_button = button;
12516       gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
12517       g_signal_connect (button, "clicked",
12518                         G_CALLBACK (snapshot_widget),
12519                         data);
12520     }
12521
12522   if (!gtk_widget_get_visible (window))
12523     gtk_widget_show_all (window);
12524   else
12525     gtk_widget_destroy (window);
12526   
12527 }
12528
12529
12530
12531 /*
12532  * Color Preview
12533  */
12534
12535 static int color_idle = 0;
12536
12537 gint
12538 color_idle_func (GtkWidget *preview)
12539 {
12540   static int count = 1;
12541   guchar buf[768];
12542   int i, j, k;
12543
12544   for (i = 0; i < 256; i++)
12545     {
12546       for (j = 0, k = 0; j < 256; j++)
12547         {
12548           buf[k+0] = i + count;
12549           buf[k+1] = 0;
12550           buf[k+2] = j + count;
12551           k += 3;
12552         }
12553
12554       gtk_preview_draw_row (GTK_PREVIEW (preview), buf, 0, i, 256);
12555     }
12556
12557   count += 1;
12558
12559   gtk_widget_queue_draw (preview);
12560   gdk_window_process_updates (preview->window, TRUE);
12561
12562   return TRUE;
12563 }
12564
12565 static void
12566 color_preview_destroy (GtkWidget  *widget,
12567                        GtkWidget **window)
12568 {
12569   gtk_idle_remove (color_idle);
12570   color_idle = 0;
12571
12572   *window = NULL;
12573 }
12574
12575 void
12576 create_color_preview (GtkWidget *widget)
12577 {
12578   static GtkWidget *window = NULL;
12579   GtkWidget *preview;
12580   guchar buf[768];
12581   int i, j, k;
12582
12583   if (!window)
12584     {
12585       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
12586       
12587       gtk_window_set_screen (GTK_WINDOW (window),
12588                              gtk_widget_get_screen (widget));
12589
12590       g_signal_connect (window, "destroy",
12591                         G_CALLBACK (color_preview_destroy),
12592                         &window);
12593
12594       gtk_window_set_title (GTK_WINDOW (window), "test");
12595       gtk_container_set_border_width (GTK_CONTAINER (window), 10);
12596
12597       preview = gtk_preview_new (GTK_PREVIEW_COLOR);
12598       gtk_preview_size (GTK_PREVIEW (preview), 256, 256);
12599       gtk_container_add (GTK_CONTAINER (window), preview);
12600
12601       for (i = 0; i < 256; i++)
12602         {
12603           for (j = 0, k = 0; j < 256; j++)
12604             {
12605               buf[k+0] = i;
12606               buf[k+1] = 0;
12607               buf[k+2] = j;
12608               k += 3;
12609             }
12610
12611           gtk_preview_draw_row (GTK_PREVIEW (preview), buf, 0, i, 256);
12612         }
12613
12614       color_idle = gtk_idle_add ((GtkFunction) color_idle_func, preview);
12615     }
12616
12617   if (!gtk_widget_get_visible (window))
12618     gtk_widget_show_all (window);
12619   else
12620     gtk_widget_destroy (window);
12621 }
12622
12623 /*
12624  * Gray Preview
12625  */
12626
12627 static int gray_idle = 0;
12628
12629 gint
12630 gray_idle_func (GtkWidget *preview)
12631 {
12632   static int count = 1;
12633   guchar buf[256];
12634   int i, j;
12635
12636   for (i = 0; i < 256; i++)
12637     {
12638       for (j = 0; j < 256; j++)
12639         buf[j] = i + j + count;
12640
12641       gtk_preview_draw_row (GTK_PREVIEW (preview), buf, 0, i, 256);
12642     }
12643
12644   count += 1;
12645
12646   gtk_widget_draw (preview, NULL);
12647
12648   return TRUE;
12649 }
12650
12651 static void
12652 gray_preview_destroy (GtkWidget  *widget,
12653                       GtkWidget **window)
12654 {
12655   gtk_idle_remove (gray_idle);
12656   gray_idle = 0;
12657
12658   *window = NULL;
12659 }
12660
12661 void
12662 create_gray_preview (GtkWidget *widget)
12663 {
12664   static GtkWidget *window = NULL;
12665   GtkWidget *preview;
12666   guchar buf[256];
12667   int i, j;
12668
12669   if (!window)
12670     {
12671       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
12672
12673       gtk_window_set_screen (GTK_WINDOW (window),
12674                              gtk_widget_get_screen (widget));
12675
12676       g_signal_connect (window, "destroy",
12677                         G_CALLBACK (gray_preview_destroy),
12678                         &window);
12679
12680       gtk_window_set_title (GTK_WINDOW (window), "test");
12681       gtk_container_set_border_width (GTK_CONTAINER (window), 10);
12682
12683       preview = gtk_preview_new (GTK_PREVIEW_GRAYSCALE);
12684       gtk_preview_size (GTK_PREVIEW (preview), 256, 256);
12685       gtk_container_add (GTK_CONTAINER (window), preview);
12686
12687       for (i = 0; i < 256; i++)
12688         {
12689           for (j = 0; j < 256; j++)
12690             buf[j] = i + j;
12691
12692           gtk_preview_draw_row (GTK_PREVIEW (preview), buf, 0, i, 256);
12693         }
12694
12695       gray_idle = gtk_idle_add ((GtkFunction) gray_idle_func, preview);
12696     }
12697
12698   if (!gtk_widget_get_visible (window))
12699     gtk_widget_show_all (window);
12700   else
12701     gtk_widget_destroy (window);
12702 }
12703
12704
12705 /*
12706  * Selection Test
12707  */
12708
12709 void
12710 selection_test_received (GtkWidget *list, GtkSelectionData *data)
12711 {
12712   GdkAtom *atoms;
12713   GtkWidget *list_item;
12714   GList *item_list;
12715   int i, l;
12716
12717   if (data->length < 0)
12718     {
12719       g_print ("Selection retrieval failed\n");
12720       return;
12721     }
12722   if (data->type != GDK_SELECTION_TYPE_ATOM)
12723     {
12724       g_print ("Selection \"TARGETS\" was not returned as atoms!\n");
12725       return;
12726     }
12727
12728   /* Clear out any current list items */
12729
12730   gtk_list_clear_items (GTK_LIST(list), 0, -1);
12731
12732   /* Add new items to list */
12733
12734   atoms = (GdkAtom *)data->data;
12735
12736   item_list = NULL;
12737   l = data->length / sizeof (GdkAtom);
12738   for (i = 0; i < l; i++)
12739     {
12740       char *name;
12741       name = gdk_atom_name (atoms[i]);
12742       if (name != NULL)
12743         {
12744           list_item = gtk_list_item_new_with_label (name);
12745           g_free (name);
12746         }
12747       else
12748         list_item = gtk_list_item_new_with_label ("(bad atom)");
12749
12750       gtk_widget_show (list_item);
12751       item_list = g_list_append (item_list, list_item);
12752     }
12753
12754   gtk_list_append_items (GTK_LIST (list), item_list);
12755
12756   return;
12757 }
12758
12759 void
12760 selection_test_get_targets (GtkWidget *widget, GtkWidget *list)
12761 {
12762   static GdkAtom targets_atom = GDK_NONE;
12763
12764   if (targets_atom == GDK_NONE)
12765     targets_atom = gdk_atom_intern ("TARGETS", FALSE);
12766
12767   gtk_selection_convert (list, GDK_SELECTION_PRIMARY, targets_atom,
12768                          GDK_CURRENT_TIME);
12769 }
12770
12771 void
12772 create_selection_test (GtkWidget *widget)
12773 {
12774   static GtkWidget *window = NULL;
12775   GtkWidget *button;
12776   GtkWidget *vbox;
12777   GtkWidget *scrolled_win;
12778   GtkWidget *list;
12779   GtkWidget *label;
12780
12781   if (!window)
12782     {
12783       window = gtk_dialog_new ();
12784       
12785       gtk_window_set_screen (GTK_WINDOW (window),
12786                              gtk_widget_get_screen (widget));
12787
12788       g_signal_connect (window, "destroy",
12789                         G_CALLBACK (gtk_widget_destroyed),
12790                         &window);
12791
12792       gtk_window_set_title (GTK_WINDOW (window), "Selection Test");
12793       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
12794
12795       /* Create the list */
12796
12797       vbox = gtk_vbox_new (FALSE, 5);
12798       gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
12799       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), vbox,
12800                           TRUE, TRUE, 0);
12801
12802       label = gtk_label_new ("Gets available targets for current selection");
12803       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
12804
12805       scrolled_win = gtk_scrolled_window_new (NULL, NULL);
12806       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
12807                                       GTK_POLICY_AUTOMATIC, 
12808                                       GTK_POLICY_AUTOMATIC);
12809       gtk_box_pack_start (GTK_BOX (vbox), scrolled_win, TRUE, TRUE, 0);
12810       gtk_widget_set_size_request (scrolled_win, 100, 200);
12811
12812       list = gtk_list_new ();
12813       gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_win), list);
12814
12815       g_signal_connect (list, "selection_received",
12816                         G_CALLBACK (selection_test_received), NULL);
12817
12818       /* .. And create some buttons */
12819       button = gtk_button_new_with_label ("Get Targets");
12820       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area),
12821                           button, TRUE, TRUE, 0);
12822
12823       g_signal_connect (button, "clicked",
12824                         G_CALLBACK (selection_test_get_targets), list);
12825
12826       button = gtk_button_new_with_label ("Quit");
12827       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area),
12828                           button, TRUE, TRUE, 0);
12829
12830       g_signal_connect_swapped (button, "clicked",
12831                                 G_CALLBACK (gtk_widget_destroy),
12832                                 window);
12833     }
12834
12835   if (!gtk_widget_get_visible (window))
12836     gtk_widget_show_all (window);
12837   else
12838     gtk_widget_destroy (window);
12839 }
12840
12841 /*
12842  * Gamma Curve
12843  */
12844
12845 void
12846 create_gamma_curve (GtkWidget *widget)
12847 {
12848   static GtkWidget *window = NULL, *curve;
12849   static int count = 0;
12850   gfloat vec[256];
12851   gint max;
12852   gint i;
12853   
12854   if (!window)
12855     {
12856       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
12857       gtk_window_set_screen (GTK_WINDOW (window),
12858                              gtk_widget_get_screen (widget));
12859
12860       gtk_window_set_title (GTK_WINDOW (window), "test");
12861       gtk_container_set_border_width (GTK_CONTAINER (window), 10);
12862
12863       g_signal_connect (window, "destroy",
12864                         G_CALLBACK(gtk_widget_destroyed),
12865                         &window);
12866
12867       curve = gtk_gamma_curve_new ();
12868       gtk_container_add (GTK_CONTAINER (window), curve);
12869       gtk_widget_show (curve);
12870     }
12871
12872   max = 127 + (count % 2)*128;
12873   gtk_curve_set_range (GTK_CURVE (GTK_GAMMA_CURVE (curve)->curve),
12874                        0, max, 0, max);
12875   for (i = 0; i < max; ++i)
12876     vec[i] = (127 / sqrt (max)) * sqrt (i);
12877   gtk_curve_set_vector (GTK_CURVE (GTK_GAMMA_CURVE (curve)->curve),
12878                         max, vec);
12879
12880   if (!gtk_widget_get_visible (window))
12881     gtk_widget_show (window);
12882   else if (count % 4 == 3)
12883     {
12884       gtk_widget_destroy (window);
12885       window = NULL;
12886     }
12887
12888   ++count;
12889 }
12890
12891 /*
12892  * Test scrolling
12893  */
12894
12895 static int scroll_test_pos = 0.0;
12896
12897 static gint
12898 scroll_test_expose (GtkWidget *widget, GdkEventExpose *event,
12899                     GtkAdjustment *adj)
12900 {
12901   gint i,j;
12902   gint imin, imax, jmin, jmax;
12903   
12904   imin = (event->area.x) / 10;
12905   imax = (event->area.x + event->area.width + 9) / 10;
12906
12907   jmin = ((int)adj->value + event->area.y) / 10;
12908   jmax = ((int)adj->value + event->area.y + event->area.height + 9) / 10;
12909
12910   gdk_window_clear_area (widget->window,
12911                          event->area.x, event->area.y,
12912                          event->area.width, event->area.height);
12913
12914   for (i=imin; i<imax; i++)
12915     for (j=jmin; j<jmax; j++)
12916       if ((i+j) % 2)
12917         gdk_draw_rectangle (widget->window, 
12918                             widget->style->black_gc,
12919                             TRUE,
12920                             10*i, 10*j - (int)adj->value, 1+i%10, 1+j%10);
12921
12922   return TRUE;
12923 }
12924
12925 static gint
12926 scroll_test_scroll (GtkWidget *widget, GdkEventScroll *event,
12927                     GtkAdjustment *adj)
12928 {
12929   gdouble new_value = adj->value + ((event->direction == GDK_SCROLL_UP) ?
12930                                     -adj->page_increment / 2:
12931                                     adj->page_increment / 2);
12932   new_value = CLAMP (new_value, adj->lower, adj->upper - adj->page_size);
12933   gtk_adjustment_set_value (adj, new_value);  
12934   
12935   return TRUE;
12936 }
12937
12938 static void
12939 scroll_test_configure (GtkWidget *widget, GdkEventConfigure *event,
12940                        GtkAdjustment *adj)
12941 {
12942   adj->page_increment = 0.9 * widget->allocation.height;
12943   adj->page_size = widget->allocation.height;
12944
12945   g_signal_emit_by_name (adj, "changed");
12946 }
12947
12948 static void
12949 scroll_test_adjustment_changed (GtkAdjustment *adj, GtkWidget *widget)
12950 {
12951   /* gint source_min = (int)adj->value - scroll_test_pos; */
12952   gint dy;
12953
12954   dy = scroll_test_pos - (int)adj->value;
12955   scroll_test_pos = adj->value;
12956
12957   if (!gtk_widget_is_drawable (widget))
12958     return;
12959   gdk_window_scroll (widget->window, 0, dy);
12960   gdk_window_process_updates (widget->window, FALSE);
12961 }
12962
12963
12964 void
12965 create_scroll_test (GtkWidget *widget)
12966 {
12967   static GtkWidget *window = NULL;
12968   GtkWidget *hbox;
12969   GtkWidget *drawing_area;
12970   GtkWidget *scrollbar;
12971   GtkWidget *button;
12972   GtkAdjustment *adj;
12973   GdkGeometry geometry;
12974   GdkWindowHints geometry_mask;
12975
12976   if (!window)
12977     {
12978       window = gtk_dialog_new ();
12979
12980       gtk_window_set_screen (GTK_WINDOW (window),
12981                              gtk_widget_get_screen (widget));
12982
12983       g_signal_connect (window, "destroy",
12984                         G_CALLBACK (gtk_widget_destroyed),
12985                         &window);
12986
12987       gtk_window_set_title (GTK_WINDOW (window), "Scroll Test");
12988       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
12989
12990       hbox = gtk_hbox_new (FALSE, 0);
12991       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), hbox,
12992                           TRUE, TRUE, 0);
12993       gtk_widget_show (hbox);
12994
12995       drawing_area = gtk_drawing_area_new ();
12996       gtk_widget_set_size_request (drawing_area, 200, 200);
12997       gtk_box_pack_start (GTK_BOX (hbox), drawing_area, TRUE, TRUE, 0);
12998       gtk_widget_show (drawing_area);
12999
13000       gtk_widget_set_events (drawing_area, GDK_EXPOSURE_MASK | GDK_SCROLL_MASK);
13001
13002       adj = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 1000.0, 1.0, 180.0, 200.0));
13003       scroll_test_pos = 0.0;
13004
13005       scrollbar = gtk_vscrollbar_new (adj);
13006       gtk_box_pack_start (GTK_BOX (hbox), scrollbar, FALSE, FALSE, 0);
13007       gtk_widget_show (scrollbar);
13008
13009       g_signal_connect (drawing_area, "expose_event",
13010                         G_CALLBACK (scroll_test_expose), adj);
13011       g_signal_connect (drawing_area, "configure_event",
13012                         G_CALLBACK (scroll_test_configure), adj);
13013       g_signal_connect (drawing_area, "scroll_event",
13014                         G_CALLBACK (scroll_test_scroll), adj);
13015       
13016       g_signal_connect (adj, "value_changed",
13017                         G_CALLBACK (scroll_test_adjustment_changed),
13018                         drawing_area);
13019       
13020       /* .. And create some buttons */
13021
13022       button = gtk_button_new_with_label ("Quit");
13023       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area),
13024                           button, TRUE, TRUE, 0);
13025
13026       g_signal_connect_swapped (button, "clicked",
13027                                 G_CALLBACK (gtk_widget_destroy),
13028                                 window);
13029       gtk_widget_show (button);
13030
13031       /* Set up gridded geometry */
13032
13033       geometry_mask = GDK_HINT_MIN_SIZE | 
13034                        GDK_HINT_BASE_SIZE | 
13035                        GDK_HINT_RESIZE_INC;
13036
13037       geometry.min_width = 20;
13038       geometry.min_height = 20;
13039       geometry.base_width = 0;
13040       geometry.base_height = 0;
13041       geometry.width_inc = 10;
13042       geometry.height_inc = 10;
13043       
13044       gtk_window_set_geometry_hints (GTK_WINDOW (window),
13045                                drawing_area, &geometry, geometry_mask);
13046     }
13047
13048   if (!gtk_widget_get_visible (window))
13049     gtk_widget_show (window);
13050   else
13051     gtk_widget_destroy (window);
13052 }
13053
13054 /*
13055  * Timeout Test
13056  */
13057
13058 static int timer = 0;
13059
13060 gint
13061 timeout_test (GtkWidget *label)
13062 {
13063   static int count = 0;
13064   static char buffer[32];
13065
13066   sprintf (buffer, "count: %d", ++count);
13067   gtk_label_set_text (GTK_LABEL (label), buffer);
13068
13069   return TRUE;
13070 }
13071
13072 void
13073 start_timeout_test (GtkWidget *widget,
13074                     GtkWidget *label)
13075 {
13076   if (!timer)
13077     {
13078       timer = gtk_timeout_add (100, (GtkFunction) timeout_test, label);
13079     }
13080 }
13081
13082 void
13083 stop_timeout_test (GtkWidget *widget,
13084                    gpointer   data)
13085 {
13086   if (timer)
13087     {
13088       gtk_timeout_remove (timer);
13089       timer = 0;
13090     }
13091 }
13092
13093 void
13094 destroy_timeout_test (GtkWidget  *widget,
13095                       GtkWidget **window)
13096 {
13097   stop_timeout_test (NULL, NULL);
13098
13099   *window = NULL;
13100 }
13101
13102 void
13103 create_timeout_test (GtkWidget *widget)
13104 {
13105   static GtkWidget *window = NULL;
13106   GtkWidget *button;
13107   GtkWidget *label;
13108
13109   if (!window)
13110     {
13111       window = gtk_dialog_new ();
13112
13113       gtk_window_set_screen (GTK_WINDOW (window),
13114                              gtk_widget_get_screen (widget));
13115
13116       g_signal_connect (window, "destroy",
13117                         G_CALLBACK (destroy_timeout_test),
13118                         &window);
13119
13120       gtk_window_set_title (GTK_WINDOW (window), "Timeout Test");
13121       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
13122
13123       label = gtk_label_new ("count: 0");
13124       gtk_misc_set_padding (GTK_MISC (label), 10, 10);
13125       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
13126                           label, TRUE, TRUE, 0);
13127       gtk_widget_show (label);
13128
13129       button = gtk_button_new_with_label ("close");
13130       g_signal_connect_swapped (button, "clicked",
13131                                 G_CALLBACK (gtk_widget_destroy),
13132                                 window);
13133       gtk_widget_set_can_default (button, TRUE);
13134       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
13135                           button, TRUE, TRUE, 0);
13136       gtk_widget_grab_default (button);
13137       gtk_widget_show (button);
13138
13139       button = gtk_button_new_with_label ("start");
13140       g_signal_connect (button, "clicked",
13141                         G_CALLBACK(start_timeout_test),
13142                         label);
13143       gtk_widget_set_can_default (button, TRUE);
13144       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
13145                           button, TRUE, TRUE, 0);
13146       gtk_widget_show (button);
13147
13148       button = gtk_button_new_with_label ("stop");
13149       g_signal_connect (button, "clicked",
13150                         G_CALLBACK (stop_timeout_test),
13151                         NULL);
13152       gtk_widget_set_can_default (button, TRUE);
13153       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
13154                           button, TRUE, TRUE, 0);
13155       gtk_widget_show (button);
13156     }
13157
13158   if (!gtk_widget_get_visible (window))
13159     gtk_widget_show (window);
13160   else
13161     gtk_widget_destroy (window);
13162 }
13163
13164 /*
13165  * Idle Test
13166  */
13167
13168 static int idle_id = 0;
13169
13170 static gint
13171 idle_test (GtkWidget *label)
13172 {
13173   static int count = 0;
13174   static char buffer[32];
13175
13176   sprintf (buffer, "count: %d", ++count);
13177   gtk_label_set_text (GTK_LABEL (label), buffer);
13178
13179   return TRUE;
13180 }
13181
13182 static void
13183 start_idle_test (GtkWidget *widget,
13184                  GtkWidget *label)
13185 {
13186   if (!idle_id)
13187     {
13188       idle_id = gtk_idle_add ((GtkFunction) idle_test, label);
13189     }
13190 }
13191
13192 static void
13193 stop_idle_test (GtkWidget *widget,
13194                 gpointer   data)
13195 {
13196   if (idle_id)
13197     {
13198       gtk_idle_remove (idle_id);
13199       idle_id = 0;
13200     }
13201 }
13202
13203 static void
13204 destroy_idle_test (GtkWidget  *widget,
13205                    GtkWidget **window)
13206 {
13207   stop_idle_test (NULL, NULL);
13208
13209   *window = NULL;
13210 }
13211
13212 static void
13213 toggle_idle_container (GObject *button,
13214                        GtkContainer *container)
13215 {
13216   gtk_container_set_resize_mode (container, GPOINTER_TO_INT (g_object_get_data (button, "user_data")));
13217 }
13218
13219 static void
13220 create_idle_test (GtkWidget *widget)
13221 {
13222   static GtkWidget *window = NULL;
13223   GtkWidget *button;
13224   GtkWidget *label;
13225   GtkWidget *container;
13226
13227   if (!window)
13228     {
13229       GtkWidget *button2;
13230       GtkWidget *frame;
13231       GtkWidget *box;
13232
13233       window = gtk_dialog_new ();
13234
13235       gtk_window_set_screen (GTK_WINDOW (window),
13236                              gtk_widget_get_screen (widget));
13237
13238       g_signal_connect (window, "destroy",
13239                         G_CALLBACK (destroy_idle_test),
13240                         &window);
13241
13242       gtk_window_set_title (GTK_WINDOW (window), "Idle Test");
13243       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
13244
13245       label = gtk_label_new ("count: 0");
13246       gtk_misc_set_padding (GTK_MISC (label), 10, 10);
13247       gtk_widget_show (label);
13248       
13249       container =
13250         g_object_new (GTK_TYPE_HBOX,
13251                         "visible", TRUE,
13252                         /* "GtkContainer::child", g_object_new (GTK_TYPE_HBOX,
13253                          * "GtkWidget::visible", TRUE,
13254                          */
13255                          "child", label,
13256                         /* NULL), */
13257                         NULL);
13258       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
13259                           container, TRUE, TRUE, 0);
13260
13261       frame =
13262         g_object_new (GTK_TYPE_FRAME,
13263                         "border_width", 5,
13264                         "label", "Label Container",
13265                         "visible", TRUE,
13266                         "parent", GTK_DIALOG (window)->vbox,
13267                         NULL);
13268       box =
13269         g_object_new (GTK_TYPE_VBOX,
13270                         "visible", TRUE,
13271                         "parent", frame,
13272                         NULL);
13273       button =
13274         g_object_connect (g_object_new (GTK_TYPE_RADIO_BUTTON,
13275                                           "label", "Resize-Parent",
13276                                           "user_data", (void*)GTK_RESIZE_PARENT,
13277                                           "visible", TRUE,
13278                                           "parent", box,
13279                                           NULL),
13280                           "signal::clicked", toggle_idle_container, container,
13281                           NULL);
13282       button = g_object_new (GTK_TYPE_RADIO_BUTTON,
13283                                "label", "Resize-Queue",
13284                                "user_data", (void*)GTK_RESIZE_QUEUE,
13285                                "group", button,
13286                                "visible", TRUE,
13287                                "parent", box,
13288                                NULL);
13289       g_object_connect (button,
13290                         "signal::clicked", toggle_idle_container, container,
13291                         NULL);
13292       button2 = g_object_new (GTK_TYPE_RADIO_BUTTON,
13293                                 "label", "Resize-Immediate",
13294                                 "user_data", (void*)GTK_RESIZE_IMMEDIATE,
13295                                 NULL);
13296       g_object_connect (button2,
13297                         "signal::clicked", toggle_idle_container, container,
13298                         NULL);
13299       g_object_set (button2,
13300                     "group", button,
13301                     "visible", TRUE,
13302                     "parent", box,
13303                     NULL);
13304
13305       button = gtk_button_new_with_label ("close");
13306       g_signal_connect_swapped (button, "clicked",
13307                                 G_CALLBACK (gtk_widget_destroy),
13308                                 window);
13309       gtk_widget_set_can_default (button, TRUE);
13310       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
13311                           button, TRUE, TRUE, 0);
13312       gtk_widget_grab_default (button);
13313       gtk_widget_show (button);
13314
13315       button = gtk_button_new_with_label ("start");
13316       g_signal_connect (button, "clicked",
13317                         G_CALLBACK (start_idle_test),
13318                         label);
13319       gtk_widget_set_can_default (button, TRUE);
13320       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
13321                           button, TRUE, TRUE, 0);
13322       gtk_widget_show (button);
13323
13324       button = gtk_button_new_with_label ("stop");
13325       g_signal_connect (button, "clicked",
13326                         G_CALLBACK (stop_idle_test),
13327                         NULL);
13328       gtk_widget_set_can_default (button, TRUE);
13329       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
13330                           button, TRUE, TRUE, 0);
13331       gtk_widget_show (button);
13332     }
13333
13334   if (!gtk_widget_get_visible (window))
13335     gtk_widget_show (window);
13336   else
13337     gtk_widget_destroy (window);
13338 }
13339
13340 /*
13341  * rc file test
13342  */
13343
13344 void
13345 reload_all_rc_files (void)
13346 {
13347   static GdkAtom atom_rcfiles = GDK_NONE;
13348
13349   GdkEvent *send_event = gdk_event_new (GDK_CLIENT_EVENT);
13350   int i;
13351   
13352   if (!atom_rcfiles)
13353     atom_rcfiles = gdk_atom_intern("_GTK_READ_RCFILES", FALSE);
13354
13355   for(i = 0; i < 5; i++)
13356     send_event->client.data.l[i] = 0;
13357   send_event->client.data_format = 32;
13358   send_event->client.message_type = atom_rcfiles;
13359   gdk_event_send_clientmessage_toall (send_event);
13360
13361   gdk_event_free (send_event);
13362 }
13363
13364 void
13365 create_rc_file (GtkWidget *widget)
13366 {
13367   static GtkWidget *window = NULL;
13368   GtkWidget *button;
13369   GtkWidget *frame;
13370   GtkWidget *vbox;
13371   GtkWidget *label;
13372
13373   if (!window)
13374     {
13375       window = gtk_dialog_new ();
13376
13377       gtk_window_set_screen (GTK_WINDOW (window),
13378                              gtk_widget_get_screen (widget));
13379
13380       g_signal_connect (window, "destroy",
13381                         G_CALLBACK (gtk_widget_destroyed),
13382                         &window);
13383
13384       frame = gtk_aspect_frame_new ("Testing RC file prioritization", 0.5, 0.5, 0.0, TRUE);
13385       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), frame, FALSE, FALSE, 0);
13386
13387       vbox = gtk_vbox_new (FALSE, 0);
13388       gtk_container_add (GTK_CONTAINER (frame), vbox);
13389       
13390       label = gtk_label_new ("This label should be red");
13391       gtk_widget_set_name (label, "testgtk-red-label");
13392       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
13393
13394       label = gtk_label_new ("This label should be green");
13395       gtk_widget_set_name (label, "testgtk-green-label");
13396       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
13397
13398       label = gtk_label_new ("This label should be blue");
13399       gtk_widget_set_name (label, "testgtk-blue-label");
13400       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
13401
13402       gtk_window_set_title (GTK_WINDOW (window), "Reload Rc file");
13403       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
13404
13405       button = gtk_button_new_with_label ("Reload");
13406       g_signal_connect (button, "clicked",
13407                         G_CALLBACK (gtk_rc_reparse_all), NULL);
13408       gtk_widget_set_can_default (button, TRUE);
13409       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
13410                           button, TRUE, TRUE, 0);
13411       gtk_widget_grab_default (button);
13412
13413       button = gtk_button_new_with_label ("Reload All");
13414       g_signal_connect (button, "clicked",
13415                         G_CALLBACK (reload_all_rc_files), NULL);
13416       gtk_widget_set_can_default (button, TRUE);
13417       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
13418                           button, TRUE, TRUE, 0);
13419
13420       button = gtk_button_new_with_label ("Close");
13421       g_signal_connect_swapped (button, "clicked",
13422                                 G_CALLBACK (gtk_widget_destroy),
13423                                 window);
13424       gtk_widget_set_can_default (button, TRUE);
13425       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
13426                           button, TRUE, TRUE, 0);
13427     }
13428
13429   if (!gtk_widget_get_visible (window))
13430     gtk_widget_show_all (window);
13431   else
13432     gtk_widget_destroy (window);
13433 }
13434
13435 /*
13436  * Test of recursive mainloop
13437  */
13438
13439 void
13440 mainloop_destroyed (GtkWidget *w, GtkWidget **window)
13441 {
13442   *window = NULL;
13443   gtk_main_quit ();
13444 }
13445
13446 void
13447 create_mainloop (GtkWidget *widget)
13448 {
13449   static GtkWidget *window = NULL;
13450   GtkWidget *label;
13451   GtkWidget *button;
13452
13453   if (!window)
13454     {
13455       window = gtk_dialog_new ();
13456
13457       gtk_window_set_screen (GTK_WINDOW (window),
13458                              gtk_widget_get_screen (widget));
13459
13460       gtk_window_set_title (GTK_WINDOW (window), "Test Main Loop");
13461
13462       g_signal_connect (window, "destroy",
13463                         G_CALLBACK (mainloop_destroyed),
13464                         &window);
13465
13466       label = gtk_label_new ("In recursive main loop...");
13467       gtk_misc_set_padding (GTK_MISC(label), 20, 20);
13468
13469       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), label,
13470                           TRUE, TRUE, 0);
13471       gtk_widget_show (label);
13472
13473       button = gtk_button_new_with_label ("Leave");
13474       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), button, 
13475                           FALSE, TRUE, 0);
13476
13477       g_signal_connect_swapped (button, "clicked",
13478                                 G_CALLBACK (gtk_widget_destroy),
13479                                 window);
13480
13481       gtk_widget_set_can_default (button, TRUE);
13482       gtk_widget_grab_default (button);
13483
13484       gtk_widget_show (button);
13485     }
13486
13487   if (!gtk_widget_get_visible (window))
13488     {
13489       gtk_widget_show (window);
13490
13491       g_print ("create_mainloop: start\n");
13492       gtk_main ();
13493       g_print ("create_mainloop: done\n");
13494     }
13495   else
13496     gtk_widget_destroy (window);
13497 }
13498
13499 gboolean
13500 layout_expose_handler (GtkWidget *widget, GdkEventExpose *event)
13501 {
13502   GtkLayout *layout;
13503
13504   gint i,j;
13505   gint imin, imax, jmin, jmax;
13506
13507   layout = GTK_LAYOUT (widget);
13508
13509   if (event->window != layout->bin_window)
13510     return FALSE;
13511   
13512   imin = (event->area.x) / 10;
13513   imax = (event->area.x + event->area.width + 9) / 10;
13514
13515   jmin = (event->area.y) / 10;
13516   jmax = (event->area.y + event->area.height + 9) / 10;
13517
13518   for (i=imin; i<imax; i++)
13519     for (j=jmin; j<jmax; j++)
13520       if ((i+j) % 2)
13521         gdk_draw_rectangle (layout->bin_window,
13522                             widget->style->black_gc,
13523                             TRUE,
13524                             10*i, 10*j, 
13525                             1+i%10, 1+j%10);
13526   
13527   return FALSE;
13528 }
13529
13530 void create_layout (GtkWidget *widget)
13531 {
13532   static GtkWidget *window = NULL;
13533   GtkWidget *layout;
13534   GtkWidget *scrolledwindow;
13535   GtkWidget *button;
13536
13537   if (!window)
13538     {
13539       gchar buf[16];
13540
13541       gint i, j;
13542       
13543       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
13544       gtk_window_set_screen (GTK_WINDOW (window),
13545                              gtk_widget_get_screen (widget));
13546
13547       g_signal_connect (window, "destroy",
13548                         G_CALLBACK (gtk_widget_destroyed),
13549                         &window);
13550
13551       gtk_window_set_title (GTK_WINDOW (window), "Layout");
13552       gtk_widget_set_size_request (window, 200, 200);
13553
13554       scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
13555       gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolledwindow),
13556                                            GTK_SHADOW_IN);
13557       gtk_scrolled_window_set_placement (GTK_SCROLLED_WINDOW (scrolledwindow),
13558                                          GTK_CORNER_TOP_RIGHT);
13559
13560       gtk_container_add (GTK_CONTAINER (window), scrolledwindow);
13561       
13562       layout = gtk_layout_new (NULL, NULL);
13563       gtk_container_add (GTK_CONTAINER (scrolledwindow), layout);
13564
13565       /* We set step sizes here since GtkLayout does not set
13566        * them itself.
13567        */
13568       GTK_LAYOUT (layout)->hadjustment->step_increment = 10.0;
13569       GTK_LAYOUT (layout)->vadjustment->step_increment = 10.0;
13570       
13571       gtk_widget_set_events (layout, GDK_EXPOSURE_MASK);
13572       g_signal_connect (layout, "expose_event",
13573                         G_CALLBACK (layout_expose_handler), NULL);
13574       
13575       gtk_layout_set_size (GTK_LAYOUT (layout), 1600, 128000);
13576       
13577       for (i=0 ; i < 16 ; i++)
13578         for (j=0 ; j < 16 ; j++)
13579           {
13580             sprintf(buf, "Button %d, %d", i, j);
13581             if ((i + j) % 2)
13582               button = gtk_button_new_with_label (buf);
13583             else
13584               button = gtk_label_new (buf);
13585
13586             gtk_layout_put (GTK_LAYOUT (layout), button,
13587                             j*100, i*100);
13588           }
13589
13590       for (i=16; i < 1280; i++)
13591         {
13592           sprintf(buf, "Button %d, %d", i, 0);
13593           if (i % 2)
13594             button = gtk_button_new_with_label (buf);
13595           else
13596             button = gtk_label_new (buf);
13597
13598           gtk_layout_put (GTK_LAYOUT (layout), button,
13599                           0, i*100);
13600         }
13601     }
13602
13603   if (!gtk_widget_get_visible (window))
13604     gtk_widget_show_all (window);
13605   else
13606     gtk_widget_destroy (window);
13607 }
13608
13609 void
13610 create_styles (GtkWidget *widget)
13611 {
13612   static GtkWidget *window = NULL;
13613   GtkWidget *label;
13614   GtkWidget *button;
13615   GtkWidget *entry;
13616   GtkWidget *vbox;
13617   static GdkColor red =    { 0, 0xffff, 0,      0      };
13618   static GdkColor green =  { 0, 0,      0xffff, 0      };
13619   static GdkColor blue =   { 0, 0,      0,      0xffff };
13620   static GdkColor yellow = { 0, 0xffff, 0xffff, 0      };
13621   static GdkColor cyan =   { 0, 0     , 0xffff, 0xffff };
13622   PangoFontDescription *font_desc;
13623
13624   GtkRcStyle *rc_style;
13625
13626   if (!window)
13627     {
13628       window = gtk_dialog_new ();
13629       gtk_window_set_screen (GTK_WINDOW (window),
13630                              gtk_widget_get_screen (widget));
13631      
13632       g_signal_connect (window, "destroy",
13633                         G_CALLBACK (gtk_widget_destroyed),
13634                         &window);
13635
13636       
13637       button = gtk_button_new_with_label ("Close");
13638       g_signal_connect_swapped (button, "clicked",
13639                                 G_CALLBACK (gtk_widget_destroy),
13640                                 window);
13641       gtk_widget_set_can_default (button, TRUE);
13642       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
13643                           button, TRUE, TRUE, 0);
13644       gtk_widget_show (button);
13645
13646       vbox = gtk_vbox_new (FALSE, 5);
13647       gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
13648       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), vbox, FALSE, FALSE, 0);
13649       
13650       label = gtk_label_new ("Font:");
13651       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
13652       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
13653
13654       font_desc = pango_font_description_from_string ("Helvetica,Sans Oblique 18");
13655
13656       button = gtk_button_new_with_label ("Some Text");
13657       gtk_widget_modify_font (GTK_BIN (button)->child, font_desc);
13658       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
13659
13660       label = gtk_label_new ("Foreground:");
13661       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
13662       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
13663
13664       button = gtk_button_new_with_label ("Some Text");
13665       gtk_widget_modify_fg (GTK_BIN (button)->child, GTK_STATE_NORMAL, &red);
13666       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
13667
13668       label = gtk_label_new ("Background:");
13669       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
13670       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
13671
13672       button = gtk_button_new_with_label ("Some Text");
13673       gtk_widget_modify_bg (button, GTK_STATE_NORMAL, &green);
13674       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
13675
13676       label = gtk_label_new ("Text:");
13677       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
13678       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
13679
13680       entry = gtk_entry_new ();
13681       gtk_entry_set_text (GTK_ENTRY (entry), "Some Text");
13682       gtk_widget_modify_text (entry, GTK_STATE_NORMAL, &blue);
13683       gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
13684
13685       label = gtk_label_new ("Base:");
13686       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
13687       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
13688
13689       entry = gtk_entry_new ();
13690       gtk_entry_set_text (GTK_ENTRY (entry), "Some Text");
13691       gtk_widget_modify_base (entry, GTK_STATE_NORMAL, &yellow);
13692       gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
13693
13694       label = gtk_label_new ("Cursor:");
13695       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
13696       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
13697
13698       entry = gtk_entry_new ();
13699       gtk_entry_set_text (GTK_ENTRY (entry), "Some Text");
13700       gtk_widget_modify_cursor (entry, &red, &red);
13701       gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
13702
13703       label = gtk_label_new ("Multiple:");
13704       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
13705       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
13706
13707       button = gtk_button_new_with_label ("Some Text");
13708
13709       rc_style = gtk_rc_style_new ();
13710
13711       rc_style->font_desc = pango_font_description_copy (font_desc);
13712       rc_style->color_flags[GTK_STATE_NORMAL] = GTK_RC_FG | GTK_RC_BG;
13713       rc_style->color_flags[GTK_STATE_PRELIGHT] = GTK_RC_FG | GTK_RC_BG;
13714       rc_style->color_flags[GTK_STATE_ACTIVE] = GTK_RC_FG | GTK_RC_BG;
13715       rc_style->fg[GTK_STATE_NORMAL] = yellow;
13716       rc_style->bg[GTK_STATE_NORMAL] = blue;
13717       rc_style->fg[GTK_STATE_PRELIGHT] = blue;
13718       rc_style->bg[GTK_STATE_PRELIGHT] = yellow;
13719       rc_style->fg[GTK_STATE_ACTIVE] = red;
13720       rc_style->bg[GTK_STATE_ACTIVE] = cyan;
13721       rc_style->xthickness = 5;
13722       rc_style->ythickness = 5;
13723
13724       gtk_widget_modify_style (button, rc_style);
13725       gtk_widget_modify_style (GTK_BIN (button)->child, rc_style);
13726
13727       g_object_unref (rc_style);
13728       
13729       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
13730     }
13731   
13732   if (!gtk_widget_get_visible (window))
13733     gtk_widget_show_all (window);
13734   else
13735     gtk_widget_destroy (window);
13736 }
13737
13738 /*
13739  * Main Window and Exit
13740  */
13741
13742 void
13743 do_exit (GtkWidget *widget, GtkWidget *window)
13744 {
13745   gtk_widget_destroy (window);
13746   gtk_main_quit ();
13747 }
13748
13749 struct {
13750   char *label;
13751   void (*func) (GtkWidget *widget);
13752   gboolean do_not_benchmark;
13753 } buttons[] =
13754 {
13755   { "alpha window", create_alpha_window },
13756   { "big windows", create_big_windows },
13757   { "button box", create_button_box },
13758   { "buttons", create_buttons },
13759   { "check buttons", create_check_buttons },
13760   { "clist", create_clist},
13761   { "color selection", create_color_selection },
13762   { "composited window", create_composited_window },
13763   { "ctree", create_ctree },
13764   { "cursors", create_cursors },
13765   { "dialog", create_dialog },
13766   { "display & screen", create_display_screen, TRUE },
13767   { "entry", create_entry },
13768   { "event box", create_event_box },
13769   { "event watcher", create_event_watcher },
13770   { "expander", create_expander },
13771   { "file selection", create_file_selection },
13772   { "flipping", create_flipping },
13773   { "focus", create_focus },
13774   { "font selection", create_font_selection },
13775   { "gamma curve", create_gamma_curve, TRUE },
13776   { "gridded geometry", create_gridded_geometry },
13777   { "handle box", create_handle_box },
13778   { "image from drawable", create_get_image },
13779   { "image", create_image },
13780   { "item factory", create_item_factory },
13781   { "key lookup", create_key_lookup },
13782   { "labels", create_labels },
13783   { "layout", create_layout },
13784   { "list", create_list },
13785   { "menus", create_menus },
13786   { "message dialog", create_message_dialog },
13787   { "modal window", create_modal_window, TRUE },
13788   { "notebook", create_notebook },
13789   { "panes", create_panes },
13790   { "paned keyboard", create_paned_keyboard_navigation },
13791   { "pixmap", create_pixmap },
13792   { "preview color", create_color_preview, TRUE },
13793   { "preview gray", create_gray_preview, TRUE },
13794   { "progress bar", create_progress_bar },
13795   { "properties", create_properties },
13796   { "radio buttons", create_radio_buttons },
13797   { "range controls", create_range_controls },
13798   { "rc file", create_rc_file },
13799   { "reparent", create_reparent },
13800   { "resize grips", create_resize_grips },
13801   { "rotated label", create_rotated_label },
13802   { "rotated text", create_rotated_text },
13803   { "rulers", create_rulers },
13804   { "saved position", create_saved_position },
13805   { "scrolled windows", create_scrolled_windows },
13806   { "shapes", create_shapes },
13807   { "size groups", create_size_groups },
13808   { "snapshot", create_snapshot },
13809   { "spinbutton", create_spins },
13810   { "statusbar", create_statusbar },
13811   { "styles", create_styles },
13812   { "test idle", create_idle_test },
13813   { "test mainloop", create_mainloop, TRUE },
13814   { "test scrolling", create_scroll_test },
13815   { "test selection", create_selection_test },
13816   { "test timeout", create_timeout_test },
13817   { "text", create_text },
13818   { "toggle buttons", create_toggle_buttons },
13819   { "toolbar", create_toolbar },
13820   { "tooltips", create_tooltips },
13821   { "tree", create_tree_mode_window},
13822   { "WM hints", create_wmhints },
13823   { "window sizing", create_window_sizing },
13824   { "window states", create_window_states }
13825 };
13826 int nbuttons = sizeof (buttons) / sizeof (buttons[0]);
13827
13828 void
13829 create_main_window (void)
13830 {
13831   GtkWidget *window;
13832   GtkWidget *box1;
13833   GtkWidget *box2;
13834   GtkWidget *scrolled_window;
13835   GtkWidget *button;
13836   GtkWidget *label;
13837   gchar buffer[64];
13838   GtkWidget *separator;
13839   GdkGeometry geometry;
13840   int i;
13841
13842   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
13843   gtk_widget_set_name (window, "main window");
13844   gtk_widget_set_uposition (window, 50, 20);
13845   gtk_window_set_default_size (GTK_WINDOW (window), -1, 400);
13846
13847   geometry.min_width = -1;
13848   geometry.min_height = -1;
13849   geometry.max_width = -1;
13850   geometry.max_height = G_MAXSHORT;
13851   gtk_window_set_geometry_hints (GTK_WINDOW (window), NULL,
13852                                  &geometry,
13853                                  GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE);
13854
13855   g_signal_connect (window, "destroy",
13856                     G_CALLBACK (gtk_main_quit),
13857                     NULL);
13858   g_signal_connect (window, "delete-event",
13859                     G_CALLBACK (gtk_false),
13860                     NULL);
13861
13862   box1 = gtk_vbox_new (FALSE, 0);
13863   gtk_container_add (GTK_CONTAINER (window), box1);
13864
13865   if (gtk_micro_version > 0)
13866     sprintf (buffer,
13867              "Gtk+ v%d.%d.%d",
13868              gtk_major_version,
13869              gtk_minor_version,
13870              gtk_micro_version);
13871   else
13872     sprintf (buffer,
13873              "Gtk+ v%d.%d",
13874              gtk_major_version,
13875              gtk_minor_version);
13876
13877   label = gtk_label_new (buffer);
13878   gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);
13879   gtk_widget_set_name (label, "testgtk-version-label");
13880
13881   scrolled_window = gtk_scrolled_window_new (NULL, NULL);
13882   gtk_container_set_border_width (GTK_CONTAINER (scrolled_window), 10);
13883   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
13884                                   GTK_POLICY_NEVER, 
13885                                   GTK_POLICY_AUTOMATIC);
13886   gtk_box_pack_start (GTK_BOX (box1), scrolled_window, TRUE, TRUE, 0);
13887
13888   box2 = gtk_vbox_new (FALSE, 0);
13889   gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
13890   gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_window), box2);
13891   gtk_container_set_focus_vadjustment (GTK_CONTAINER (box2),
13892                                        gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (scrolled_window)));
13893   gtk_widget_show (box2);
13894
13895   for (i = 0; i < nbuttons; i++)
13896     {
13897       button = gtk_button_new_with_label (buttons[i].label);
13898       if (buttons[i].func)
13899         g_signal_connect (button, 
13900                           "clicked", 
13901                           G_CALLBACK(buttons[i].func),
13902                           NULL);
13903       else
13904         gtk_widget_set_sensitive (button, FALSE);
13905       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
13906     }
13907
13908   separator = gtk_hseparator_new ();
13909   gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
13910
13911   box2 = gtk_vbox_new (FALSE, 10);
13912   gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
13913   gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
13914
13915   button = gtk_button_new_with_mnemonic ("_Close");
13916   g_signal_connect (button, "clicked",
13917                     G_CALLBACK (do_exit),
13918                     window);
13919   gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
13920   gtk_widget_set_can_default (button, TRUE);
13921   gtk_widget_grab_default (button);
13922
13923   gtk_widget_show_all (window);
13924 }
13925
13926 static void
13927 test_init (void)
13928 {
13929   if (g_file_test ("../gdk-pixbuf/libpixbufloader-pnm.la",
13930                    G_FILE_TEST_EXISTS))
13931     {
13932       g_setenv ("GDK_PIXBUF_MODULE_FILE", "../gdk-pixbuf/gdk-pixbuf.loaders", TRUE);
13933       g_setenv ("GTK_IM_MODULE_FILE", "../modules/input/gtk.immodules", TRUE);
13934     }
13935 }
13936
13937 static char *
13938 pad (const char *str, int to)
13939 {
13940   static char buf[256];
13941   int len = strlen (str);
13942   int i;
13943
13944   for (i = 0; i < to; i++)
13945     buf[i] = ' ';
13946
13947   buf[to] = '\0';
13948
13949   memcpy (buf, str, len);
13950
13951   return buf;
13952 }
13953
13954 static void
13955 bench_iteration (GtkWidget *widget, void (* fn) (GtkWidget *widget))
13956 {
13957   fn (widget); /* on */
13958   while (g_main_context_iteration (NULL, FALSE));
13959   fn (widget); /* off */
13960   while (g_main_context_iteration (NULL, FALSE));
13961 }
13962
13963 void
13964 do_real_bench (GtkWidget *widget, void (* fn) (GtkWidget *widget), char *name, int num)
13965 {
13966   GTimeVal tv0, tv1;
13967   double dt_first;
13968   double dt;
13969   int n;
13970   static gboolean printed_headers = FALSE;
13971
13972   if (!printed_headers) {
13973     g_print ("Test                 Iters      First      Other\n");
13974     g_print ("-------------------- ----- ---------- ----------\n");
13975     printed_headers = TRUE;
13976   }
13977
13978   g_get_current_time (&tv0);
13979   bench_iteration (widget, fn); 
13980   g_get_current_time (&tv1);
13981
13982   dt_first = ((double)tv1.tv_sec - tv0.tv_sec) * 1000.0
13983         + (tv1.tv_usec - tv0.tv_usec) / 1000.0;
13984
13985   g_get_current_time (&tv0);
13986   for (n = 0; n < num - 1; n++)
13987     bench_iteration (widget, fn); 
13988   g_get_current_time (&tv1);
13989   dt = ((double)tv1.tv_sec - tv0.tv_sec) * 1000.0
13990         + (tv1.tv_usec - tv0.tv_usec) / 1000.0;
13991
13992   g_print ("%s %5d ", pad (name, 20), num);
13993   if (num > 1)
13994     g_print ("%10.1f %10.1f\n", dt_first, dt/(num-1));
13995   else
13996     g_print ("%10.1f\n", dt_first);
13997 }
13998
13999 void
14000 do_bench (char* what, int num)
14001 {
14002   int i;
14003   GtkWidget *widget;
14004   void (* fn) (GtkWidget *widget);
14005   fn = NULL;
14006   widget = gtk_window_new (GTK_WINDOW_TOPLEVEL);
14007
14008   if (g_ascii_strcasecmp (what, "ALL") == 0)
14009     {
14010       for (i = 0; i < nbuttons; i++)
14011         {
14012           if (!buttons[i].do_not_benchmark)
14013             do_real_bench (widget, buttons[i].func, buttons[i].label, num);
14014         }
14015
14016       return;
14017     }
14018   else
14019     {
14020       for (i = 0; i < nbuttons; i++)
14021         {
14022           if (strcmp (buttons[i].label, what) == 0)
14023             {
14024               fn = buttons[i].func;
14025               break;
14026             }
14027         }
14028       
14029       if (!fn)
14030         g_print ("Can't bench: \"%s\" not found.\n", what);
14031       else
14032         do_real_bench (widget, fn, buttons[i].label, num);
14033     }
14034 }
14035
14036 void 
14037 usage (void)
14038 {
14039   fprintf (stderr, "Usage: testgtk [--bench ALL|<bench>[:<count>]]\n");
14040   exit (1);
14041 }
14042
14043 int
14044 main (int argc, char *argv[])
14045 {
14046   GtkBindingSet *binding_set;
14047   int i;
14048   gboolean done_benchmarks = FALSE;
14049
14050   srand (time (NULL));
14051
14052   test_init ();
14053
14054   /* Check to see if we are being run from the correct
14055    * directory.
14056    */
14057   if (file_exists ("testgtkrc"))
14058     gtk_rc_add_default_file ("testgtkrc");
14059   else if (file_exists ("tests/testgtkrc"))
14060     gtk_rc_add_default_file ("tests/testgtkrc");
14061   else
14062     g_warning ("Couldn't find file \"testgtkrc\".");
14063
14064   g_set_application_name ("GTK+ Test Program");
14065
14066   gtk_init (&argc, &argv);
14067
14068   gtk_accelerator_set_default_mod_mask (GDK_SHIFT_MASK |
14069                                         GDK_CONTROL_MASK |
14070                                         GDK_MOD1_MASK | 
14071                                         GDK_META_MASK |
14072                                         GDK_SUPER_MASK |
14073                                         GDK_HYPER_MASK |
14074                                         GDK_MOD4_MASK);
14075   /*  benchmarking
14076    */
14077   for (i = 1; i < argc; i++)
14078     {
14079       if (strncmp (argv[i], "--bench", strlen("--bench")) == 0)
14080         {
14081           int num = 1;
14082           char *nextarg;
14083           char *what;
14084           char *count;
14085           
14086           nextarg = strchr (argv[i], '=');
14087           if (nextarg)
14088             nextarg++;
14089           else
14090             {
14091               i++;
14092               if (i == argc)
14093                 usage ();
14094               nextarg = argv[i];
14095             }
14096
14097           count = strchr (nextarg, ':');
14098           if (count)
14099             {
14100               what = g_strndup (nextarg, count - nextarg);
14101               count++;
14102               num = atoi (count);
14103               if (num <= 0)
14104                 usage ();
14105             }
14106           else
14107             what = g_strdup (nextarg);
14108
14109           do_bench (what, num ? num : 1);
14110           done_benchmarks = TRUE;
14111         }
14112       else
14113         usage ();
14114     }
14115   if (done_benchmarks)
14116     return 0;
14117
14118   /* bindings test
14119    */
14120   binding_set = gtk_binding_set_by_class (g_type_class_ref (GTK_TYPE_WIDGET));
14121   gtk_binding_entry_add_signal (binding_set,
14122                                 '9', GDK_CONTROL_MASK | GDK_RELEASE_MASK,
14123                                 "debug_msg",
14124                                 1,
14125                                 G_TYPE_STRING, "GtkWidgetClass <ctrl><release>9 test");
14126   
14127   /* We use gtk_rc_parse_string() here so we can make sure it works across theme
14128    * changes
14129    */
14130
14131   gtk_rc_parse_string ("style \"testgtk-version-label\" { "
14132                        "   fg[NORMAL] = \"#ff0000\"\n"
14133                        "   font = \"Sans 18\"\n"
14134                        "}\n"
14135                        "widget \"*.testgtk-version-label\" style \"testgtk-version-label\"");
14136   
14137   create_main_window ();
14138
14139   gtk_main ();
14140
14141   if (1)
14142     {
14143       while (g_main_context_pending (NULL))
14144         g_main_context_iteration (NULL, FALSE);
14145 #if 0
14146       sleep (1);
14147       while (g_main_context_pending (NULL))
14148         g_main_context_iteration (NULL, FALSE);
14149 #endif
14150     }
14151   return 0;
14152 }