]> Pileus Git - ~andy/gtk/blob - tests/testgtk.c
add some orientation flipping code to the "flipping" test.
[~andy/gtk] / tests / testgtk.c
1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /*
21  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
22  * file for a list of people on the GTK+ Team.  See the ChangeLog
23  * files for a list of changes.  These files are distributed with
24  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
25  */
26
27 #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_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_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_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_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_FLAGS (button[9], GTK_CAN_DEFAULT);
913       gtk_widget_grab_default (button[9]);
914     }
915
916   if (!GTK_WIDGET_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_FLAGS (button, GTK_CAN_DEFAULT);
981       gtk_widget_grab_default (button);
982     }
983
984   if (!GTK_WIDGET_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_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_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_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_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_FLAGS (button, GTK_CAN_DEFAULT);
1796       gtk_widget_grab_default (button);
1797     }
1798
1799   if (!GTK_WIDGET_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_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_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 void create_labels (GtkWidget *widget)
2965 {
2966   static GtkWidget *window = NULL;
2967   GtkWidget *hbox;
2968   GtkWidget *vbox;
2969   GtkWidget *frame;
2970   GtkWidget *label;
2971   GtkWidget *button;
2972
2973   if (!window)
2974     {
2975       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
2976
2977       gtk_window_set_screen (GTK_WINDOW (window),
2978                              gtk_widget_get_screen (widget));
2979
2980       g_signal_connect (window, "destroy",
2981                         G_CALLBACK (gtk_widget_destroyed),
2982                         &window);
2983
2984       gtk_window_set_title (GTK_WINDOW (window), "Label");
2985
2986       vbox = gtk_vbox_new (FALSE, 5);
2987       
2988       hbox = gtk_hbox_new (FALSE, 5);
2989       gtk_container_add (GTK_CONTAINER (window), vbox);
2990
2991       gtk_box_pack_end (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
2992
2993       button = create_sensitivity_control (hbox);
2994
2995       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
2996
2997       button = create_selectable_control (hbox);
2998
2999       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
3000       
3001       vbox = gtk_vbox_new (FALSE, 5);
3002       
3003       gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
3004       gtk_container_set_border_width (GTK_CONTAINER (window), 5);
3005
3006       frame = gtk_frame_new ("Normal Label");
3007       label = gtk_label_new ("This is a Normal label");
3008       gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_START);
3009       gtk_container_add (GTK_CONTAINER (frame), label);
3010       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3011
3012       frame = gtk_frame_new ("Multi-line Label");
3013       label = gtk_label_new ("This is a Multi-line label.\nSecond line\nThird line");
3014       gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_END);
3015       gtk_container_add (GTK_CONTAINER (frame), label);
3016       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3017
3018       frame = gtk_frame_new ("Left Justified Label");
3019       label = gtk_label_new ("This is a Left-Justified\nMulti-line label.\nThird      line");
3020       gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_MIDDLE);
3021       gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
3022       gtk_container_add (GTK_CONTAINER (frame), label);
3023       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3024
3025       frame = gtk_frame_new ("Right Justified Label");
3026       gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_START);
3027       label = gtk_label_new ("This is a Right-Justified\nMulti-line label.\nFourth line, (j/k)");
3028       gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_RIGHT);
3029       gtk_container_add (GTK_CONTAINER (frame), label);
3030       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3031
3032       frame = gtk_frame_new ("Internationalized Label");
3033       label = gtk_label_new (NULL);
3034       gtk_label_set_markup (GTK_LABEL (label),
3035                             "French (Fran\303\247ais) Bonjour, Salut\n"
3036                             "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"
3037                             "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"
3038                             "Chinese (Simplified) <span lang=\"zh-cn\">\345\205\203\346\260\224 \345\274\200\345\217\221</span>\n"
3039                             "Chinese (Traditional) <span lang=\"zh-tw\">\345\205\203\346\260\243        \351\226\213\347\231\274</span>\n"
3040                             "Japanese <span lang=\"ja\">\345\205\203\346\260\227        \351\226\213\347\231\272</span>");
3041       gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
3042       gtk_container_add (GTK_CONTAINER (frame), label);
3043       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3044
3045       frame = gtk_frame_new ("Bidirection Label");
3046       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"
3047                              "\342\200\217Hebrew        \327\251\327\234\327\225\327\235");
3048       gtk_container_add (GTK_CONTAINER (frame), label);
3049       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3050
3051       vbox = gtk_vbox_new (FALSE, 5);
3052       gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
3053       frame = gtk_frame_new ("Line wrapped label");
3054       label = gtk_label_new ("This is an example of a line-wrapped label.  It should not be taking "\
3055                              "up the entire             "/* big space to test spacing */\
3056                              "width allocated to it, but automatically wraps the words to fit.  "\
3057                              "The time has come, for all good men, to come to the aid of their party.  "\
3058                              "The sixth sheik's six sheep's sick.\n"\
3059                              "     It supports multiple paragraphs correctly, and  correctly   adds "\
3060                              "many          extra  spaces. ");
3061
3062       gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
3063       gtk_container_add (GTK_CONTAINER (frame), label);
3064       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3065
3066       frame = gtk_frame_new ("Filled, wrapped label");
3067       label = gtk_label_new ("This is an example of a line-wrapped, filled label.  It should be taking "\
3068                              "up the entire              width allocated to it.  Here is a seneance to prove "\
3069                              "my point.  Here is another sentence. "\
3070                              "Here comes the sun, do de do de do.\n"\
3071                              "    This is a new paragraph.\n"\
3072                              "    This is another newer, longer, better paragraph.  It is coming to an end, "\
3073                              "unfortunately.");
3074       gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_FILL);
3075       gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
3076       gtk_container_add (GTK_CONTAINER (frame), label);
3077       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3078
3079       frame = gtk_frame_new ("Underlined label");
3080       label = gtk_label_new ("This label is underlined!\n"
3081                              "This one is underlined (\343\201\223\343\202\223\343\201\253\343\201\241\343\201\257) in quite a funky fashion");
3082       gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
3083       gtk_label_set_pattern (GTK_LABEL (label), "_________________________ _ _________ _ _____ _ __ __  ___ ____ _____");
3084       gtk_container_add (GTK_CONTAINER (frame), label);
3085       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3086
3087       frame = gtk_frame_new ("Markup label");
3088       label = gtk_label_new (NULL);
3089
3090       /* There's also a gtk_label_set_markup() without accel if you
3091        * don't have an accelerator key
3092        */
3093       gtk_label_set_markup_with_mnemonic (GTK_LABEL (label),
3094                                           "This <span foreground=\"blue\" background=\"orange\">label</span> has "
3095                                           "<b>markup</b> _such as "
3096                                           "<big><i>Big Italics</i></big>\n"
3097                                           "<tt>Monospace font</tt>\n"
3098                                           "<u>Underline!</u>\n"
3099                                           "foo\n"
3100                                           "<span foreground=\"green\" background=\"red\">Ugly colors</span>\n"
3101                                           "and nothing on this line,\n"
3102                                           "or this.\n"
3103                                           "or this either\n"
3104                                           "or even on this one\n"
3105                                           "la <big>la <big>la <big>la <big>la</big></big></big></big>\n"
3106                                           "but this _word is <span foreground=\"purple\"><big>purple</big></span>\n"
3107                                           "<span underline=\"double\">We like <sup>superscript</sup> and <sub>subscript</sub> too</span>");
3108
3109       g_assert (gtk_label_get_mnemonic_keyval (GTK_LABEL (label)) == GDK_s);
3110       
3111       gtk_container_add (GTK_CONTAINER (frame), label);
3112       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3113     }
3114   
3115   if (!GTK_WIDGET_VISIBLE (window))
3116     gtk_widget_show_all (window);
3117   else
3118     gtk_widget_destroy (window);
3119 }
3120
3121 static void
3122 on_angle_scale_changed (GtkRange *range,
3123                         GtkLabel *label)
3124 {
3125   gtk_label_set_angle (GTK_LABEL (label), gtk_range_get_value (range));
3126 }
3127
3128 static void
3129 create_rotated_label (GtkWidget *widget)
3130 {
3131   static GtkWidget *window = NULL;
3132   GtkWidget *vbox;
3133   GtkWidget *hscale;
3134   GtkWidget *label;  
3135   GtkWidget *scale_label;  
3136   GtkWidget *scale_hbox;  
3137
3138   if (!window)
3139     {
3140       window = gtk_dialog_new_with_buttons ("Rotated Label",
3141                                             GTK_WINDOW (gtk_widget_get_toplevel (widget)), 0,
3142                                             GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
3143                                             NULL);
3144
3145       gtk_window_set_resizable (GTK_WINDOW (window), TRUE);
3146
3147       gtk_window_set_screen (GTK_WINDOW (window),
3148                              gtk_widget_get_screen (widget));
3149
3150       g_signal_connect (window, "response",
3151                         G_CALLBACK (gtk_object_destroy), NULL);
3152       g_signal_connect (window, "destroy",
3153                         G_CALLBACK (gtk_widget_destroyed), &window);
3154
3155       vbox = gtk_vbox_new (FALSE, 5);
3156       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), vbox, TRUE, TRUE, 0);
3157       gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
3158
3159       label = gtk_label_new (NULL);
3160       gtk_label_set_markup (GTK_LABEL (label), "Hello World\n<i>Rotate</i> <span underline='single' foreground='blue'>me</span>");
3161       gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
3162
3163       scale_hbox = gtk_hbox_new (FALSE, 0);
3164       gtk_box_pack_start (GTK_BOX (vbox), scale_hbox, FALSE, FALSE, 0);
3165       
3166       scale_label = gtk_label_new (NULL);
3167       gtk_label_set_markup (GTK_LABEL (scale_label), "<i>Angle: </i>");
3168       gtk_box_pack_start (GTK_BOX (scale_hbox), scale_label, FALSE, FALSE, 0);
3169
3170       hscale = gtk_hscale_new_with_range (0, 360, 5);
3171       g_signal_connect (hscale, "value-changed",
3172                         G_CALLBACK (on_angle_scale_changed), label);
3173       
3174       gtk_range_set_value (GTK_RANGE (hscale), 45);
3175       gtk_widget_set_usize (hscale, 200, -1);
3176       gtk_box_pack_start (GTK_BOX (scale_hbox), hscale, TRUE, TRUE, 0);
3177     }
3178   
3179   if (!GTK_WIDGET_VISIBLE (window))
3180     gtk_widget_show_all (window);
3181   else
3182     gtk_widget_destroy (window);
3183 }
3184
3185 #define DEFAULT_TEXT_RADIUS 200
3186
3187 static void
3188 on_rotated_text_unrealize (GtkWidget *widget)
3189 {
3190   g_object_set_data (G_OBJECT (widget), "text-gc", NULL);
3191 }
3192
3193 static gboolean
3194 on_rotated_text_expose (GtkWidget      *widget,
3195                         GdkEventExpose *event,
3196                         GdkPixbuf      *tile_pixbuf)
3197 {
3198   static const gchar *words[] = { "The", "grand", "old", "Duke", "of", "York",
3199                                   "had", "10,000", "men" };
3200   PangoRenderer *renderer;
3201   GdkGC *gc;
3202   int n_words;
3203   int i;
3204   double radius;
3205   PangoMatrix matrix = PANGO_MATRIX_INIT;
3206   PangoLayout *layout;
3207   PangoContext *context;
3208   PangoFontDescription *desc;
3209
3210   gc = g_object_get_data (G_OBJECT (widget), "text-gc");
3211   if (!gc)
3212     {
3213       static GdkColor black = { 0, 0, 0, 0 };
3214       
3215       gc = gdk_gc_new (widget->window);
3216       gdk_gc_set_rgb_fg_color (gc, &black);
3217       
3218       if (tile_pixbuf)
3219         {
3220           GdkPixmap *tile;
3221           
3222           gint width = gdk_pixbuf_get_width (tile_pixbuf);
3223           gint height = gdk_pixbuf_get_height (tile_pixbuf);
3224           
3225           tile = gdk_pixmap_new (widget->window, width, height, -1);
3226           gdk_draw_pixbuf (tile, gc, tile_pixbuf,
3227                            0, 0, 0, 0, width, height,
3228                            GDK_RGB_DITHER_NORMAL, 0, 0);
3229
3230           gdk_gc_set_tile (gc, tile);
3231           gdk_gc_set_fill (gc, GDK_TILED);
3232
3233           g_object_unref (tile);
3234         }
3235
3236       g_object_set_data_full (G_OBJECT (widget), "text-gc", gc, (GDestroyNotify)g_object_unref);
3237     }
3238
3239   renderer = gdk_pango_renderer_get_default (gtk_widget_get_screen (widget));
3240   gdk_pango_renderer_set_drawable (GDK_PANGO_RENDERER (renderer), widget->window);
3241   gdk_pango_renderer_set_gc (GDK_PANGO_RENDERER (renderer), gc);
3242
3243   radius = MIN (widget->allocation.width, widget->allocation.height) / 2.;
3244
3245   pango_matrix_translate (&matrix,
3246                           radius + (widget->allocation.width - 2 * radius) / 2,
3247                           radius + (widget->allocation.height - 2 * radius) / 2);
3248   pango_matrix_scale (&matrix, radius / DEFAULT_TEXT_RADIUS, radius / DEFAULT_TEXT_RADIUS);
3249
3250   context = gtk_widget_get_pango_context (widget);
3251   layout = pango_layout_new (context);
3252   desc = pango_font_description_from_string ("Sans Bold 30");
3253   pango_layout_set_font_description (layout, desc);
3254   pango_font_description_free (desc);
3255     
3256   n_words = G_N_ELEMENTS (words);
3257   for (i = 0; i < n_words; i++)
3258     {
3259       PangoMatrix rotated_matrix = matrix;
3260       int width, height;
3261       
3262       pango_matrix_rotate (&rotated_matrix, - (360. * i) / n_words);
3263
3264       pango_context_set_matrix (context, &rotated_matrix);
3265       pango_layout_context_changed (layout);
3266       pango_layout_set_text (layout, words[i], -1);
3267       
3268       pango_layout_get_size (layout, &width, &height);
3269
3270       pango_renderer_draw_layout (renderer, layout,
3271                                   - width / 2, - DEFAULT_TEXT_RADIUS * PANGO_SCALE);
3272     }
3273
3274   gdk_pango_renderer_set_drawable (GDK_PANGO_RENDERER (renderer), NULL);
3275   gdk_pango_renderer_set_gc (GDK_PANGO_RENDERER (renderer), NULL);
3276   
3277   g_object_unref (layout);
3278
3279   return FALSE;
3280 }
3281
3282 static void
3283 create_rotated_text (GtkWidget *widget)
3284 {
3285   static GtkWidget *window = NULL;
3286
3287   if (!window)
3288     {
3289       const GdkColor white = { 0, 0xffff, 0xffff, 0xffff };
3290       GtkRequisition requisition;
3291       GtkWidget *drawing_area;
3292       GdkPixbuf *tile_pixbuf;
3293
3294       window = gtk_dialog_new_with_buttons ("Rotated Text",
3295                                             GTK_WINDOW (gtk_widget_get_toplevel (widget)), 0,
3296                                             GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
3297                                             NULL);
3298
3299       gtk_window_set_resizable (GTK_WINDOW (window), TRUE);
3300
3301       gtk_window_set_screen (GTK_WINDOW (window),
3302                              gtk_widget_get_screen (widget));
3303
3304       g_signal_connect (window, "response",
3305                         G_CALLBACK (gtk_object_destroy), NULL);
3306       g_signal_connect (window, "destroy",
3307                         G_CALLBACK (gtk_widget_destroyed), &window);
3308
3309       drawing_area = gtk_drawing_area_new ();
3310       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), drawing_area, TRUE, TRUE, 0);
3311       gtk_widget_modify_bg (drawing_area, GTK_STATE_NORMAL, &white);
3312
3313       tile_pixbuf = gdk_pixbuf_new_from_file ("marble.xpm", NULL);
3314       
3315       g_signal_connect (drawing_area, "expose-event",
3316                         G_CALLBACK (on_rotated_text_expose), tile_pixbuf);
3317       g_signal_connect (drawing_area, "unrealize",
3318                         G_CALLBACK (on_rotated_text_unrealize), NULL);
3319
3320       gtk_widget_show_all (GTK_BIN (window)->child);
3321       
3322       gtk_widget_set_size_request (drawing_area, DEFAULT_TEXT_RADIUS * 2, DEFAULT_TEXT_RADIUS * 2);
3323       gtk_widget_size_request (window, &requisition);
3324       gtk_widget_set_size_request (drawing_area, -1, -1);
3325       gtk_window_resize (GTK_WINDOW (window), requisition.width, requisition.height);
3326     }
3327   
3328   if (!GTK_WIDGET_VISIBLE (window))
3329     gtk_widget_show (window);
3330   else
3331     gtk_widget_destroy (window);
3332 }
3333
3334 /*
3335  * Reparent demo
3336  */
3337
3338 static void
3339 reparent_label (GtkWidget *widget,
3340                 GtkWidget *new_parent)
3341 {
3342   GtkWidget *label;
3343
3344   label = g_object_get_data (G_OBJECT (widget), "user_data");
3345
3346   gtk_widget_reparent (label, new_parent);
3347 }
3348
3349 static void
3350 set_parent_signal (GtkWidget *child,
3351                    GtkWidget *old_parent,
3352                    gpointer   func_data)
3353 {
3354   g_message ("set_parent for \"%s\": new parent: \"%s\", old parent: \"%s\", data: %d\n",
3355              g_type_name (G_OBJECT_TYPE (child)),
3356              child->parent ? g_type_name (G_OBJECT_TYPE (child->parent)) : "NULL",
3357              old_parent ? g_type_name (G_OBJECT_TYPE (old_parent)) : "NULL",
3358              GPOINTER_TO_INT (func_data));
3359 }
3360
3361 static void
3362 create_reparent (GtkWidget *widget)
3363 {
3364   static GtkWidget *window = NULL;
3365   GtkWidget *box1;
3366   GtkWidget *box2;
3367   GtkWidget *box3;
3368   GtkWidget *frame;
3369   GtkWidget *button;
3370   GtkWidget *label;
3371   GtkWidget *separator;
3372   GtkWidget *event_box;
3373
3374   if (!window)
3375     {
3376       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3377
3378       gtk_window_set_screen (GTK_WINDOW (window),
3379                              gtk_widget_get_screen (widget));
3380
3381       g_signal_connect (window, "destroy",
3382                         G_CALLBACK (gtk_widget_destroyed),
3383                         &window);
3384
3385       gtk_window_set_title (GTK_WINDOW (window), "reparent");
3386       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
3387
3388       box1 = gtk_vbox_new (FALSE, 0);
3389       gtk_container_add (GTK_CONTAINER (window), box1);
3390
3391       box2 = gtk_hbox_new (FALSE, 5);
3392       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
3393       gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
3394
3395       label = gtk_label_new ("Hello World");
3396
3397       frame = gtk_frame_new ("Frame 1");
3398       gtk_box_pack_start (GTK_BOX (box2), frame, TRUE, TRUE, 0);
3399
3400       box3 = gtk_vbox_new (FALSE, 5);
3401       gtk_container_set_border_width (GTK_CONTAINER (box3), 5);
3402       gtk_container_add (GTK_CONTAINER (frame), box3);
3403
3404       button = gtk_button_new_with_label ("switch");
3405       g_object_set_data (G_OBJECT (button), "user_data", label);
3406       gtk_box_pack_start (GTK_BOX (box3), button, FALSE, TRUE, 0);
3407
3408       event_box = gtk_event_box_new ();
3409       gtk_box_pack_start (GTK_BOX (box3), event_box, FALSE, TRUE, 0);
3410       gtk_container_add (GTK_CONTAINER (event_box), label);
3411                          
3412       g_signal_connect (button, "clicked",
3413                         G_CALLBACK (reparent_label),
3414                         event_box);
3415       
3416       g_signal_connect (label, "parent_set",
3417                         G_CALLBACK (set_parent_signal),
3418                         GINT_TO_POINTER (42));
3419
3420       frame = gtk_frame_new ("Frame 2");
3421       gtk_box_pack_start (GTK_BOX (box2), frame, TRUE, TRUE, 0);
3422
3423       box3 = gtk_vbox_new (FALSE, 5);
3424       gtk_container_set_border_width (GTK_CONTAINER (box3), 5);
3425       gtk_container_add (GTK_CONTAINER (frame), box3);
3426
3427       button = gtk_button_new_with_label ("switch");
3428       g_object_set_data (G_OBJECT (button), "user_data", label);
3429       gtk_box_pack_start (GTK_BOX (box3), button, FALSE, TRUE, 0);
3430       
3431       event_box = gtk_event_box_new ();
3432       gtk_box_pack_start (GTK_BOX (box3), event_box, FALSE, TRUE, 0);
3433
3434       g_signal_connect (button, "clicked",
3435                         G_CALLBACK (reparent_label),
3436                         event_box);
3437
3438       separator = gtk_hseparator_new ();
3439       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
3440
3441       box2 = gtk_vbox_new (FALSE, 10);
3442       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
3443       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
3444
3445       button = gtk_button_new_with_label ("close");
3446       g_signal_connect_swapped (button, "clicked",
3447                                 G_CALLBACK (gtk_widget_destroy), window);
3448       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
3449       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
3450       gtk_widget_grab_default (button);
3451     }
3452
3453   if (!GTK_WIDGET_VISIBLE (window))
3454     gtk_widget_show_all (window);
3455   else
3456     gtk_widget_destroy (window);
3457 }
3458
3459 /*
3460  * Resize Grips
3461  */
3462 static gboolean
3463 grippy_button_press (GtkWidget *area, GdkEventButton *event, GdkWindowEdge edge)
3464 {
3465   if (event->type == GDK_BUTTON_PRESS) 
3466     {
3467       if (event->button == 1)
3468         gtk_window_begin_resize_drag (GTK_WINDOW (gtk_widget_get_toplevel (area)), edge,
3469                                       event->button, event->x_root, event->y_root,
3470                                       event->time);
3471       else if (event->button == 2)
3472         gtk_window_begin_move_drag (GTK_WINDOW (gtk_widget_get_toplevel (area)), 
3473                                     event->button, event->x_root, event->y_root,
3474                                     event->time);
3475     }
3476   return TRUE;
3477 }
3478
3479 static gboolean
3480 grippy_expose (GtkWidget *area, GdkEventExpose *event, GdkWindowEdge edge)
3481 {
3482   gtk_paint_resize_grip (area->style,
3483                          area->window,
3484                          GTK_WIDGET_STATE (area),
3485                          &event->area,
3486                          area,
3487                          "statusbar",
3488                          edge,
3489                          0, 0,
3490                          area->allocation.width,
3491                          area->allocation.height);
3492
3493   return TRUE;
3494 }
3495
3496 static void
3497 create_resize_grips (GtkWidget *widget)
3498 {
3499   static GtkWidget *window = NULL;
3500   GtkWidget *area;
3501   GtkWidget *hbox, *vbox;
3502   if (!window)
3503     {
3504       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3505
3506       gtk_window_set_screen (GTK_WINDOW (window),
3507                              gtk_widget_get_screen (widget));
3508
3509       gtk_window_set_title (GTK_WINDOW (window), "resize grips");
3510       
3511       g_signal_connect (window, "destroy",
3512                         G_CALLBACK (gtk_widget_destroyed),
3513                         &window);
3514
3515       vbox = gtk_vbox_new (FALSE, 0);
3516       gtk_container_add (GTK_CONTAINER (window), vbox);
3517       
3518       hbox = gtk_hbox_new (FALSE, 0);
3519       gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);
3520
3521       /* North west */
3522       area = gtk_drawing_area_new ();
3523       gtk_widget_add_events (area, GDK_BUTTON_PRESS_MASK);
3524       gtk_box_pack_start (GTK_BOX (hbox), area, TRUE, TRUE, 0);
3525       g_signal_connect (area, "expose_event", G_CALLBACK (grippy_expose),
3526                         GINT_TO_POINTER (GDK_WINDOW_EDGE_NORTH_WEST));
3527       g_signal_connect (area, "button_press_event", G_CALLBACK (grippy_button_press),
3528                         GINT_TO_POINTER (GDK_WINDOW_EDGE_NORTH_WEST));
3529       
3530       /* North */
3531       area = gtk_drawing_area_new ();
3532       gtk_widget_add_events (area, GDK_BUTTON_PRESS_MASK);
3533       gtk_box_pack_start (GTK_BOX (hbox), area, TRUE, TRUE, 0);
3534       g_signal_connect (area, "expose_event", G_CALLBACK (grippy_expose),
3535                         GINT_TO_POINTER (GDK_WINDOW_EDGE_NORTH));
3536       g_signal_connect (area, "button_press_event", G_CALLBACK (grippy_button_press),
3537                         GINT_TO_POINTER (GDK_WINDOW_EDGE_NORTH));
3538
3539       /* North east */
3540       area = gtk_drawing_area_new ();
3541       gtk_widget_add_events (area, GDK_BUTTON_PRESS_MASK);
3542       gtk_box_pack_start (GTK_BOX (hbox), area, TRUE, TRUE, 0);
3543       g_signal_connect (area, "expose_event", G_CALLBACK (grippy_expose),
3544                         GINT_TO_POINTER (GDK_WINDOW_EDGE_NORTH_EAST));
3545       g_signal_connect (area, "button_press_event", G_CALLBACK (grippy_button_press),
3546                         GINT_TO_POINTER (GDK_WINDOW_EDGE_NORTH_EAST));
3547
3548       hbox = gtk_hbox_new (FALSE, 0);
3549       gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);
3550
3551       /* West */
3552       area = gtk_drawing_area_new ();
3553       gtk_widget_add_events (area, GDK_BUTTON_PRESS_MASK);
3554       gtk_box_pack_start (GTK_BOX (hbox), area, TRUE, TRUE, 0);
3555       g_signal_connect (area, "expose_event", G_CALLBACK (grippy_expose),
3556                         GINT_TO_POINTER (GDK_WINDOW_EDGE_WEST));
3557       g_signal_connect (area, "button_press_event", G_CALLBACK (grippy_button_press),
3558                         GINT_TO_POINTER (GDK_WINDOW_EDGE_WEST));
3559
3560       /* Middle */
3561       area = gtk_drawing_area_new ();
3562       gtk_box_pack_start (GTK_BOX (hbox), area, TRUE, TRUE, 0);
3563
3564       /* East */
3565       area = gtk_drawing_area_new ();
3566       gtk_widget_add_events (area, GDK_BUTTON_PRESS_MASK);
3567       gtk_box_pack_start (GTK_BOX (hbox), area, TRUE, TRUE, 0);
3568       g_signal_connect (area, "expose_event", G_CALLBACK (grippy_expose),
3569                         GINT_TO_POINTER (GDK_WINDOW_EDGE_EAST));
3570       g_signal_connect (area, "button_press_event", G_CALLBACK (grippy_button_press),
3571                         GINT_TO_POINTER (GDK_WINDOW_EDGE_EAST));
3572
3573
3574       hbox = gtk_hbox_new (FALSE, 0);
3575       gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);
3576
3577       /* South west */
3578       area = gtk_drawing_area_new ();
3579       gtk_widget_add_events (area, GDK_BUTTON_PRESS_MASK);
3580       gtk_box_pack_start (GTK_BOX (hbox), area, TRUE, TRUE, 0);
3581       g_signal_connect (area, "expose_event", G_CALLBACK (grippy_expose),
3582                         GINT_TO_POINTER (GDK_WINDOW_EDGE_SOUTH_WEST));
3583       g_signal_connect (area, "button_press_event", G_CALLBACK (grippy_button_press),
3584                         GINT_TO_POINTER (GDK_WINDOW_EDGE_SOUTH_WEST));
3585       /* South */
3586       area = gtk_drawing_area_new ();
3587       gtk_widget_add_events (area, GDK_BUTTON_PRESS_MASK);
3588       gtk_box_pack_start (GTK_BOX (hbox), area, TRUE, TRUE, 0);
3589       g_signal_connect (area, "expose_event", G_CALLBACK (grippy_expose),
3590                         GINT_TO_POINTER (GDK_WINDOW_EDGE_SOUTH));
3591       g_signal_connect (area, "button_press_event", G_CALLBACK (grippy_button_press),
3592                         GINT_TO_POINTER (GDK_WINDOW_EDGE_SOUTH));
3593       
3594       /* South east */
3595       area = gtk_drawing_area_new ();
3596       gtk_widget_add_events (area, GDK_BUTTON_PRESS_MASK);
3597       gtk_box_pack_start (GTK_BOX (hbox), area, TRUE, TRUE, 0);
3598       g_signal_connect (area, "expose_event", G_CALLBACK (grippy_expose),
3599                         GINT_TO_POINTER (GDK_WINDOW_EDGE_SOUTH_EAST));
3600       g_signal_connect (area, "button_press_event", G_CALLBACK (grippy_button_press),
3601                         GINT_TO_POINTER (GDK_WINDOW_EDGE_SOUTH_EAST));
3602     }
3603
3604   if (!GTK_WIDGET_VISIBLE (window))
3605     gtk_widget_show_all (window);
3606   else
3607     gtk_widget_destroy (window);
3608 }
3609
3610 /*
3611  * Saved Position
3612  */
3613 gint upositionx = 0;
3614 gint upositiony = 0;
3615
3616 static gint
3617 uposition_configure (GtkWidget *window)
3618 {
3619   GtkLabel *lx;
3620   GtkLabel *ly;
3621   gchar buffer[64];
3622
3623   lx = g_object_get_data (G_OBJECT (window), "x");
3624   ly = g_object_get_data (G_OBJECT (window), "y");
3625
3626   gdk_window_get_root_origin (window->window, &upositionx, &upositiony);
3627   sprintf (buffer, "%d", upositionx);
3628   gtk_label_set_text (lx, buffer);
3629   sprintf (buffer, "%d", upositiony);
3630   gtk_label_set_text (ly, buffer);
3631
3632   return FALSE;
3633 }
3634
3635 static void
3636 uposition_stop_configure (GtkToggleButton *toggle,
3637                           GtkObject       *window)
3638 {
3639   if (toggle->active)
3640     g_signal_handlers_block_by_func (window, G_CALLBACK (uposition_configure), NULL);
3641   else
3642     g_signal_handlers_unblock_by_func (window, G_CALLBACK (uposition_configure), NULL);
3643 }
3644
3645 static void
3646 create_saved_position (GtkWidget *widget)
3647 {
3648   static GtkWidget *window = NULL;
3649
3650   if (!window)
3651     {
3652       GtkWidget *hbox;
3653       GtkWidget *main_vbox;
3654       GtkWidget *vbox;
3655       GtkWidget *x_label;
3656       GtkWidget *y_label;
3657       GtkWidget *button;
3658       GtkWidget *label;
3659       GtkWidget *any;
3660
3661       window = g_object_connect (g_object_new (GTK_TYPE_WINDOW,
3662                                                  "type", GTK_WINDOW_TOPLEVEL,
3663                                                  "title", "Saved Position",
3664                                                  NULL),
3665                                  "signal::configure_event", uposition_configure, NULL,
3666                                  NULL);
3667
3668       gtk_window_move (GTK_WINDOW (window), upositionx, upositiony);
3669
3670       gtk_window_set_screen (GTK_WINDOW (window),
3671                              gtk_widget_get_screen (widget));
3672       
3673
3674       g_signal_connect (window, "destroy",
3675                         G_CALLBACK (gtk_widget_destroyed),
3676                         &window);
3677
3678       main_vbox = gtk_vbox_new (FALSE, 5);
3679       gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 0);
3680       gtk_container_add (GTK_CONTAINER (window), main_vbox);
3681
3682       vbox =
3683         g_object_new (gtk_vbox_get_type (),
3684                         "GtkBox::homogeneous", FALSE,
3685                         "GtkBox::spacing", 5,
3686                         "GtkContainer::border_width", 10,
3687                         "GtkWidget::parent", main_vbox,
3688                         "GtkWidget::visible", TRUE,
3689                         "child", g_object_connect (g_object_new (GTK_TYPE_TOGGLE_BUTTON,
3690                                                                    "label", "Stop Events",
3691                                                                    "active", FALSE,
3692                                                                    "visible", TRUE,
3693                                                                    NULL),
3694                                                    "signal::clicked", uposition_stop_configure, window,
3695                                                    NULL),
3696                         NULL);
3697
3698       hbox = gtk_hbox_new (FALSE, 0);
3699       gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
3700       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
3701
3702       label = gtk_label_new ("X Origin : ");
3703       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
3704       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
3705
3706       x_label = gtk_label_new ("");
3707       gtk_box_pack_start (GTK_BOX (hbox), x_label, TRUE, TRUE, 0);
3708       g_object_set_data (G_OBJECT (window), "x", x_label);
3709
3710       hbox = gtk_hbox_new (FALSE, 0);
3711       gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
3712       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
3713
3714       label = gtk_label_new ("Y Origin : ");
3715       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
3716       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
3717
3718       y_label = gtk_label_new ("");
3719       gtk_box_pack_start (GTK_BOX (hbox), y_label, TRUE, TRUE, 0);
3720       g_object_set_data (G_OBJECT (window), "y", y_label);
3721
3722       any =
3723         g_object_new (gtk_hseparator_get_type (),
3724                         "GtkWidget::visible", TRUE,
3725                         NULL);
3726       gtk_box_pack_start (GTK_BOX (main_vbox), any, FALSE, TRUE, 0);
3727
3728       hbox = gtk_hbox_new (FALSE, 0);
3729       gtk_container_set_border_width (GTK_CONTAINER (hbox), 10);
3730       gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, TRUE, 0);
3731
3732       button = gtk_button_new_with_label ("Close");
3733       g_signal_connect_swapped (button, "clicked",
3734                                 G_CALLBACK (gtk_widget_destroy),
3735                                 window);
3736       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
3737       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
3738       gtk_widget_grab_default (button);
3739       
3740       gtk_widget_show_all (window);
3741     }
3742   else
3743     gtk_widget_destroy (window);
3744 }
3745
3746 /*
3747  * GtkPixmap
3748  */
3749
3750 static void
3751 create_pixmap (GtkWidget *widget)
3752 {
3753   static GtkWidget *window = NULL;
3754   GtkWidget *box1;
3755   GtkWidget *box2;
3756   GtkWidget *box3;
3757   GtkWidget *button;
3758   GtkWidget *label;
3759   GtkWidget *separator;
3760   GtkWidget *pixmapwid;
3761
3762   if (!window)
3763     {
3764       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3765
3766       gtk_window_set_screen (GTK_WINDOW (window),
3767                              gtk_widget_get_screen (widget));
3768
3769       g_signal_connect (window, "destroy",
3770                         G_CALLBACK (gtk_widget_destroyed),
3771                         &window);
3772
3773       gtk_window_set_title (GTK_WINDOW (window), "GtkPixmap");
3774       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
3775       gtk_widget_realize(window);
3776
3777       box1 = gtk_vbox_new (FALSE, 0);
3778       gtk_container_add (GTK_CONTAINER (window), box1);
3779
3780       box2 = gtk_vbox_new (FALSE, 10);
3781       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
3782       gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
3783
3784       button = gtk_button_new ();
3785       gtk_box_pack_start (GTK_BOX (box2), button, FALSE, FALSE, 0);
3786
3787       pixmapwid = new_pixmap ("test.xpm", window->window, NULL);
3788
3789       label = gtk_label_new ("Pixmap\ntest");
3790       box3 = gtk_hbox_new (FALSE, 0);
3791       gtk_container_set_border_width (GTK_CONTAINER (box3), 2);
3792       gtk_container_add (GTK_CONTAINER (box3), pixmapwid);
3793       gtk_container_add (GTK_CONTAINER (box3), label);
3794       gtk_container_add (GTK_CONTAINER (button), box3);
3795
3796       button = gtk_button_new ();
3797       gtk_box_pack_start (GTK_BOX (box2), button, FALSE, FALSE, 0);
3798       
3799       pixmapwid = new_pixmap ("test.xpm", window->window, NULL);
3800
3801       label = gtk_label_new ("Pixmap\ntest");
3802       box3 = gtk_hbox_new (FALSE, 0);
3803       gtk_container_set_border_width (GTK_CONTAINER (box3), 2);
3804       gtk_container_add (GTK_CONTAINER (box3), pixmapwid);
3805       gtk_container_add (GTK_CONTAINER (box3), label);
3806       gtk_container_add (GTK_CONTAINER (button), box3);
3807
3808       gtk_widget_set_sensitive (button, FALSE);
3809       
3810       separator = gtk_hseparator_new ();
3811       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
3812
3813       box2 = gtk_vbox_new (FALSE, 10);
3814       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
3815       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
3816
3817       button = gtk_button_new_with_label ("close");
3818       g_signal_connect_swapped (button, "clicked",
3819                                 G_CALLBACK (gtk_widget_destroy),
3820                                 window);
3821       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
3822       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
3823       gtk_widget_grab_default (button);
3824     }
3825
3826   if (!GTK_WIDGET_VISIBLE (window))
3827     gtk_widget_show_all (window);
3828   else
3829     gtk_widget_destroy (window);
3830 }
3831
3832 static void
3833 tips_query_widget_entered (GtkTipsQuery   *tips_query,
3834                            GtkWidget      *widget,
3835                            const gchar    *tip_text,
3836                            const gchar    *tip_private,
3837                            GtkWidget      *toggle)
3838 {
3839   if (GTK_TOGGLE_BUTTON (toggle)->active)
3840     {
3841       gtk_label_set_text (GTK_LABEL (tips_query), tip_text ? "There is a Tip!" : "There is no Tip!");
3842       /* don't let GtkTipsQuery reset its label */
3843       g_signal_stop_emission_by_name (tips_query, "widget_entered");
3844     }
3845 }
3846
3847 static gint
3848 tips_query_widget_selected (GtkWidget      *tips_query,
3849                             GtkWidget      *widget,
3850                             const gchar    *tip_text,
3851                             const gchar    *tip_private,
3852                             GdkEventButton *event,
3853                             gpointer        func_data)
3854 {
3855   if (widget)
3856     g_print ("Help \"%s\" requested for <%s>\n",
3857              tip_private ? tip_private : "None",
3858              g_type_name (G_OBJECT_TYPE (widget)));
3859   return TRUE;
3860 }
3861
3862 static void
3863 create_tooltips (GtkWidget *widget)
3864 {
3865   static GtkWidget *window = NULL;
3866   GtkWidget *box1;
3867   GtkWidget *box2;
3868   GtkWidget *box3;
3869   GtkWidget *button;
3870   GtkWidget *toggle;
3871   GtkWidget *frame;
3872   GtkWidget *tips_query;
3873   GtkWidget *separator;
3874   GtkTooltips *tooltips;
3875
3876   if (!window)
3877     {
3878       window =
3879         g_object_new (gtk_window_get_type (),
3880                         "GtkWindow::type", GTK_WINDOW_TOPLEVEL,
3881                         "GtkContainer::border_width", 0,
3882                         "GtkWindow::title", "Tooltips",
3883                         "GtkWindow::allow_shrink", TRUE,
3884                         "GtkWindow::allow_grow", FALSE,
3885                         NULL);
3886
3887       gtk_window_set_screen (GTK_WINDOW (window),
3888                              gtk_widget_get_screen (widget));
3889
3890       g_signal_connect (window, "destroy",
3891                         G_CALLBACK (destroy_tooltips),
3892                         &window);
3893
3894       tooltips=gtk_tooltips_new();
3895       g_object_ref (tooltips);
3896       gtk_object_sink (GTK_OBJECT (tooltips));
3897       g_object_set_data (G_OBJECT (window), "tooltips", tooltips);
3898       
3899       box1 = gtk_vbox_new (FALSE, 0);
3900       gtk_container_add (GTK_CONTAINER (window), box1);
3901
3902       box2 = gtk_vbox_new (FALSE, 10);
3903       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
3904       gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
3905
3906       button = gtk_toggle_button_new_with_label ("button1");
3907       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
3908
3909       gtk_tooltips_set_tip (tooltips,
3910                             button,
3911                             "This is button 1",
3912                             "ContextHelp/buttons/1");
3913
3914       button = gtk_toggle_button_new_with_label ("button2");
3915       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
3916
3917       gtk_tooltips_set_tip (tooltips,
3918                             button,
3919                             "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.",
3920                             "ContextHelp/buttons/2_long");
3921
3922       toggle = gtk_toggle_button_new_with_label ("Override TipsQuery Label");
3923       gtk_box_pack_start (GTK_BOX (box2), toggle, TRUE, TRUE, 0);
3924
3925       gtk_tooltips_set_tip (tooltips,
3926                             toggle,
3927                             "Toggle TipsQuery view.",
3928                             "Hi msw! ;)");
3929
3930       box3 =
3931         g_object_new (gtk_vbox_get_type (),
3932                         "homogeneous", FALSE,
3933                         "spacing", 5,
3934                         "border_width", 5,
3935                         "visible", TRUE,
3936                         NULL);
3937
3938       tips_query = gtk_tips_query_new ();
3939
3940       button =
3941         g_object_new (gtk_button_get_type (),
3942                         "label", "[?]",
3943                         "visible", TRUE,
3944                         "parent", box3,
3945                         NULL);
3946       g_object_connect (button,
3947                         "swapped_signal::clicked", gtk_tips_query_start_query, tips_query,
3948                         NULL);
3949       gtk_box_set_child_packing (GTK_BOX (box3), button, FALSE, FALSE, 0, GTK_PACK_START);
3950       gtk_tooltips_set_tip (tooltips,
3951                             button,
3952                             "Start the Tooltips Inspector",
3953                             "ContextHelp/buttons/?");
3954       
3955       
3956       g_object_set (g_object_connect (tips_query,
3957                                       "signal::widget_entered", tips_query_widget_entered, toggle,
3958                                       "signal::widget_selected", tips_query_widget_selected, NULL,
3959                                       NULL),
3960                     "visible", TRUE,
3961                     "parent", box3,
3962                     "caller", button,
3963                     NULL);
3964       
3965       frame = g_object_new (gtk_frame_get_type (),
3966                               "label", "ToolTips Inspector",
3967                               "label_xalign", (double) 0.5,
3968                               "border_width", 0,
3969                               "visible", TRUE,
3970                               "parent", box2,
3971                               "child", box3,
3972                               NULL);
3973       gtk_box_set_child_packing (GTK_BOX (box2), frame, TRUE, TRUE, 10, GTK_PACK_START);
3974
3975       separator = gtk_hseparator_new ();
3976       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
3977
3978       box2 = gtk_vbox_new (FALSE, 10);
3979       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
3980       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
3981
3982       button = gtk_button_new_with_label ("close");
3983       g_signal_connect_swapped (button, "clicked",
3984                                 G_CALLBACK (gtk_widget_destroy),
3985                                 window);
3986       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
3987       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
3988       gtk_widget_grab_default (button);
3989
3990       gtk_tooltips_set_tip (tooltips, button, "Push this button to close window", "ContextHelp/buttons/Close");
3991     }
3992
3993   if (!GTK_WIDGET_VISIBLE (window))
3994     gtk_widget_show_all (window);
3995   else
3996     gtk_widget_destroy (window);
3997 }
3998
3999 /*
4000  * GtkImage
4001  */
4002
4003 static void
4004 pack_image (GtkWidget *box,
4005             const gchar *text,
4006             GtkWidget *image)
4007 {
4008   gtk_box_pack_start (GTK_BOX (box),
4009                       gtk_label_new (text),
4010                       FALSE, FALSE, 0);
4011
4012   gtk_box_pack_start (GTK_BOX (box),
4013                       image,
4014                       TRUE, TRUE, 0);  
4015 }
4016
4017 static void
4018 create_image (GtkWidget *widget)
4019 {
4020   static GtkWidget *window = NULL;
4021
4022   if (window == NULL)
4023     {
4024       GtkWidget *vbox;
4025       GdkPixmap *pixmap;
4026       GdkBitmap *mask;
4027         
4028       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
4029       
4030       gtk_window_set_screen (GTK_WINDOW (window),
4031                              gtk_widget_get_screen (widget));
4032
4033       /* this is bogus for testing drawing when allocation < request,
4034        * don't copy into real code
4035        */
4036       g_object_set (window, "allow_shrink", TRUE, "allow_grow", TRUE, NULL);
4037       
4038       g_signal_connect (window, "destroy",
4039                         G_CALLBACK (gtk_widget_destroyed),
4040                         &window);
4041
4042       vbox = gtk_vbox_new (FALSE, 5);
4043
4044       gtk_container_add (GTK_CONTAINER (window), vbox);
4045
4046       pack_image (vbox, "Stock Warning Dialog",
4047                   gtk_image_new_from_stock (GTK_STOCK_DIALOG_WARNING,
4048                                             GTK_ICON_SIZE_DIALOG));
4049
4050       pixmap = gdk_pixmap_colormap_create_from_xpm_d (NULL,
4051                                                       gtk_widget_get_colormap (window),
4052                                                       &mask,
4053                                                       NULL,
4054                                                       openfile);
4055       
4056       pack_image (vbox, "Pixmap",
4057                   gtk_image_new_from_pixmap (pixmap, mask));
4058     }
4059
4060   if (!GTK_WIDGET_VISIBLE (window))
4061     gtk_widget_show_all (window);
4062   else
4063     gtk_widget_destroy (window);
4064 }
4065      
4066 /*
4067  * Menu demo
4068  */
4069
4070 static GtkWidget*
4071 create_menu (GdkScreen *screen, gint depth, gint length, gboolean tearoff)
4072 {
4073   GtkWidget *menu;
4074   GtkWidget *menuitem;
4075   GtkWidget *image;
4076   GSList *group;
4077   char buf[32];
4078   int i, j;
4079
4080   if (depth < 1)
4081     return NULL;
4082
4083   menu = gtk_menu_new ();
4084   gtk_menu_set_screen (GTK_MENU (menu), screen);
4085
4086   group = NULL;
4087
4088   if (tearoff)
4089     {
4090       menuitem = gtk_tearoff_menu_item_new ();
4091       gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
4092       gtk_widget_show (menuitem);
4093     }
4094
4095   image = gtk_image_new_from_stock (GTK_STOCK_OPEN,
4096                                     GTK_ICON_SIZE_MENU);
4097   gtk_widget_show (image);
4098   menuitem = gtk_image_menu_item_new_with_label ("Image item");
4099   gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), image);
4100   gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
4101   gtk_widget_show (menuitem);
4102   
4103   for (i = 0, j = 1; i < length; i++, j++)
4104     {
4105       sprintf (buf, "item %2d - %d", depth, j);
4106
4107       menuitem = gtk_radio_menu_item_new_with_label (group, buf);
4108       group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (menuitem));
4109
4110 #if 0
4111       if (depth % 2)
4112         gtk_check_menu_item_set_show_toggle (GTK_CHECK_MENU_ITEM (menuitem), TRUE);
4113 #endif
4114
4115       gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
4116       gtk_widget_show (menuitem);
4117       if (i == 3)
4118         gtk_widget_set_sensitive (menuitem, FALSE);
4119
4120       if (i == 5)
4121         gtk_check_menu_item_set_inconsistent (GTK_CHECK_MENU_ITEM (menuitem),
4122                                               TRUE);
4123
4124       if (i < 5)
4125         gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), 
4126                                    create_menu (screen, depth - 1, 5,  TRUE));
4127     }
4128
4129   return menu;
4130 }
4131
4132 static GtkWidget*
4133 create_table_menu (GdkScreen *screen, gint cols, gint rows, gboolean tearoff)
4134 {
4135   GtkWidget *menu;
4136   GtkWidget *menuitem;
4137   GtkWidget *submenu;
4138   GtkWidget *image;
4139   char buf[32];
4140   int i, j;
4141
4142   menu = gtk_menu_new ();
4143   gtk_menu_set_screen (GTK_MENU (menu), screen);
4144
4145   j = 0;
4146   if (tearoff)
4147     {
4148       menuitem = gtk_tearoff_menu_item_new ();
4149       gtk_menu_attach (GTK_MENU (menu), menuitem, 0, cols, j, j + 1);
4150       gtk_widget_show (menuitem);
4151       j++;
4152     }
4153   
4154   menuitem = gtk_menu_item_new_with_label ("items");
4155   gtk_menu_attach (GTK_MENU (menu), menuitem, 0, cols, j, j + 1);
4156
4157   submenu = gtk_menu_new ();
4158   gtk_menu_set_screen (GTK_MENU (submenu), screen);
4159   gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), submenu);
4160   gtk_widget_show (menuitem);
4161   j++;
4162
4163   /* now fill the items submenu */
4164   image = gtk_image_new_from_stock (GTK_STOCK_HELP,
4165                                     GTK_ICON_SIZE_MENU);
4166   gtk_widget_show (image);
4167   menuitem = gtk_image_menu_item_new_with_label ("Image");
4168   gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), image);
4169   gtk_menu_attach (GTK_MENU (submenu), menuitem, 0, 1, 0, 1);
4170   gtk_widget_show (menuitem);
4171
4172   menuitem = gtk_menu_item_new_with_label ("x");
4173   gtk_menu_attach (GTK_MENU (submenu), menuitem, 1, 2, 0, 1);
4174   gtk_widget_show (menuitem);
4175
4176   menuitem = gtk_menu_item_new_with_label ("x");
4177   gtk_menu_attach (GTK_MENU (submenu), menuitem, 0, 1, 1, 2);
4178   gtk_widget_show (menuitem);
4179   
4180   image = gtk_image_new_from_stock (GTK_STOCK_HELP,
4181                                     GTK_ICON_SIZE_MENU);
4182   gtk_widget_show (image);
4183   menuitem = gtk_image_menu_item_new_with_label ("Image");
4184   gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), image);
4185   gtk_menu_attach (GTK_MENU (submenu), menuitem, 1, 2, 1, 2);
4186   gtk_widget_show (menuitem);
4187
4188   menuitem = gtk_radio_menu_item_new_with_label (NULL, "Radio");
4189   gtk_menu_attach (GTK_MENU (submenu), menuitem, 0, 1, 2, 3);
4190   gtk_widget_show (menuitem);
4191
4192   menuitem = gtk_menu_item_new_with_label ("x");
4193   gtk_menu_attach (GTK_MENU (submenu), menuitem, 1, 2, 2, 3);
4194   gtk_widget_show (menuitem);
4195
4196   menuitem = gtk_menu_item_new_with_label ("x");
4197   gtk_menu_attach (GTK_MENU (submenu), menuitem, 0, 1, 3, 4);
4198   gtk_widget_show (menuitem);
4199   
4200   menuitem = gtk_radio_menu_item_new_with_label (NULL, "Radio");
4201   gtk_menu_attach (GTK_MENU (submenu), menuitem, 1, 2, 3, 4);
4202   gtk_widget_show (menuitem);
4203
4204   menuitem = gtk_check_menu_item_new_with_label ("Check");
4205   gtk_menu_attach (GTK_MENU (submenu), menuitem, 0, 1, 4, 5);
4206   gtk_widget_show (menuitem);
4207
4208   menuitem = gtk_menu_item_new_with_label ("x");
4209   gtk_menu_attach (GTK_MENU (submenu), menuitem, 1, 2, 4, 5);
4210   gtk_widget_show (menuitem);
4211
4212   menuitem = gtk_menu_item_new_with_label ("x");
4213   gtk_menu_attach (GTK_MENU (submenu), menuitem, 0, 1, 5, 6);
4214   gtk_widget_show (menuitem);
4215   
4216   menuitem = gtk_check_menu_item_new_with_label ("Check");
4217   gtk_menu_attach (GTK_MENU (submenu), menuitem, 1, 2, 5, 6);
4218   gtk_widget_show (menuitem);
4219
4220   menuitem = gtk_menu_item_new_with_label ("1. Inserted normally (8)");
4221   gtk_widget_show (menuitem);
4222   gtk_menu_shell_insert (GTK_MENU_SHELL (submenu), menuitem, 8);
4223
4224   menuitem = gtk_menu_item_new_with_label ("2. Inserted normally (2)");
4225   gtk_widget_show (menuitem);
4226   gtk_menu_shell_insert (GTK_MENU_SHELL (submenu), menuitem, 2);
4227
4228   menuitem = gtk_menu_item_new_with_label ("3. Inserted normally (0)");
4229   gtk_widget_show (menuitem);
4230   gtk_menu_shell_insert (GTK_MENU_SHELL (submenu), menuitem, 0);
4231
4232   menuitem = gtk_menu_item_new_with_label ("4. Inserted normally (-1)");
4233   gtk_widget_show (menuitem);
4234   gtk_menu_shell_insert (GTK_MENU_SHELL (submenu), menuitem, -1);
4235   
4236   /* end of items submenu */
4237
4238   menuitem = gtk_menu_item_new_with_label ("spanning");
4239   gtk_menu_attach (GTK_MENU (menu), menuitem, 0, cols, j, j + 1);
4240
4241   submenu = gtk_menu_new ();
4242   gtk_menu_set_screen (GTK_MENU (submenu), screen);
4243   gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), submenu);
4244   gtk_widget_show (menuitem);
4245   j++;
4246
4247   /* now fill the spanning submenu */
4248   menuitem = gtk_menu_item_new_with_label ("a");
4249   gtk_menu_attach (GTK_MENU (submenu), menuitem, 0, 2, 0, 1);
4250   gtk_widget_show (menuitem);
4251
4252   menuitem = gtk_menu_item_new_with_label ("b");
4253   gtk_menu_attach (GTK_MENU (submenu), menuitem, 2, 3, 0, 2);
4254   gtk_widget_show (menuitem);
4255
4256   menuitem = gtk_menu_item_new_with_label ("c");
4257   gtk_menu_attach (GTK_MENU (submenu), menuitem, 0, 1, 1, 3);
4258   gtk_widget_show (menuitem);
4259
4260   menuitem = gtk_menu_item_new_with_label ("d");
4261   gtk_menu_attach (GTK_MENU (submenu), menuitem, 1, 2, 1, 2);
4262   gtk_widget_show (menuitem);
4263
4264   menuitem = gtk_menu_item_new_with_label ("e");
4265   gtk_menu_attach (GTK_MENU (submenu), menuitem, 1, 3, 2, 3);
4266   gtk_widget_show (menuitem);
4267   /* end of spanning submenu */
4268   
4269   menuitem = gtk_menu_item_new_with_label ("left");
4270   gtk_menu_attach (GTK_MENU (menu), menuitem, 0, 1, j, j + 1);
4271   submenu = gtk_menu_new ();
4272   gtk_menu_set_screen (GTK_MENU (submenu), screen);
4273   gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), submenu);
4274   gtk_widget_show (menuitem);
4275
4276   menuitem = gtk_menu_item_new_with_label ("Empty");
4277   gtk_menu_attach (GTK_MENU (submenu), menuitem, 0, 1, 0, 1);
4278   submenu = gtk_menu_new ();
4279   gtk_menu_set_screen (GTK_MENU (submenu), screen);
4280   gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), submenu);
4281   gtk_widget_show (menuitem);
4282
4283   menuitem = gtk_menu_item_new_with_label ("right");
4284   gtk_menu_attach (GTK_MENU (menu), menuitem, 1, 2, j, j + 1);
4285   submenu = gtk_menu_new ();
4286   gtk_menu_set_screen (GTK_MENU (submenu), screen);
4287   gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), submenu);
4288   gtk_widget_show (menuitem);
4289
4290   menuitem = gtk_menu_item_new_with_label ("Empty");
4291   gtk_menu_attach (GTK_MENU (submenu), menuitem, 0, 1, 0, 1);
4292   gtk_widget_show (menuitem);
4293
4294   j++;
4295
4296   for (; j < rows; j++)
4297       for (i = 0; i < cols; i++)
4298       {
4299         sprintf (buf, "(%d %d)", i, j);
4300         menuitem = gtk_menu_item_new_with_label (buf);
4301         gtk_menu_attach (GTK_MENU (menu), menuitem, i, i + 1, j, j + 1);
4302         gtk_widget_show (menuitem);
4303       }
4304   
4305   menuitem = gtk_menu_item_new_with_label ("1. Inserted normally (8)");
4306   gtk_menu_shell_insert (GTK_MENU_SHELL (menu), menuitem, 8);
4307   gtk_widget_show (menuitem);
4308   menuitem = gtk_menu_item_new_with_label ("2. Inserted normally (2)");
4309   gtk_menu_shell_insert (GTK_MENU_SHELL (menu), menuitem, 2);
4310   gtk_widget_show (menuitem);
4311   menuitem = gtk_menu_item_new_with_label ("3. Inserted normally (0)");
4312   gtk_menu_shell_insert (GTK_MENU_SHELL (menu), menuitem, 0);
4313   gtk_widget_show (menuitem);
4314   menuitem = gtk_menu_item_new_with_label ("4. Inserted normally (-1)");
4315   gtk_menu_shell_insert (GTK_MENU_SHELL (menu), menuitem, -1);
4316   gtk_widget_show (menuitem);
4317   
4318   return menu;
4319 }
4320
4321 static void
4322 create_menus (GtkWidget *widget)
4323 {
4324   static GtkWidget *window = NULL;
4325   GtkWidget *box1;
4326   GtkWidget *box2;
4327   GtkWidget *button;
4328   GtkWidget *optionmenu;
4329   GtkWidget *separator;
4330   
4331   if (!window)
4332     {
4333       GtkWidget *menubar;
4334       GtkWidget *menu;
4335       GtkWidget *menuitem;
4336       GtkAccelGroup *accel_group;
4337       GtkWidget *image;
4338       GdkScreen *screen = gtk_widget_get_screen (widget);
4339       
4340       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
4341
4342       gtk_window_set_screen (GTK_WINDOW (window), screen);
4343       
4344       g_signal_connect (window, "destroy",
4345                         G_CALLBACK (gtk_widget_destroyed),
4346                         &window);
4347       g_signal_connect (window, "delete-event",
4348                         G_CALLBACK (gtk_true),
4349                         NULL);
4350       
4351       accel_group = gtk_accel_group_new ();
4352       gtk_window_add_accel_group (GTK_WINDOW (window), accel_group);
4353
4354       gtk_window_set_title (GTK_WINDOW (window), "menus");
4355       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
4356       
4357       
4358       box1 = gtk_vbox_new (FALSE, 0);
4359       gtk_container_add (GTK_CONTAINER (window), box1);
4360       gtk_widget_show (box1);
4361       
4362       menubar = gtk_menu_bar_new ();
4363       gtk_box_pack_start (GTK_BOX (box1), menubar, FALSE, TRUE, 0);
4364       gtk_widget_show (menubar);
4365       
4366       menu = create_menu (screen, 2, 50, TRUE);
4367       
4368       menuitem = gtk_menu_item_new_with_label ("test\nline2");
4369       gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), menu);
4370       gtk_menu_shell_append (GTK_MENU_SHELL (menubar), menuitem);
4371       gtk_widget_show (menuitem);
4372
4373       menu = create_table_menu (screen, 2, 50, TRUE);
4374       
4375       menuitem = gtk_menu_item_new_with_label ("table");
4376       gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), menu);
4377       gtk_menu_shell_append (GTK_MENU_SHELL (menubar), menuitem);
4378       gtk_widget_show (menuitem);
4379       
4380       menuitem = gtk_menu_item_new_with_label ("foo");
4381       gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), create_menu (screen, 3, 5, TRUE));
4382       gtk_menu_shell_append (GTK_MENU_SHELL (menubar), menuitem);
4383       gtk_widget_show (menuitem);
4384
4385       image = gtk_image_new_from_stock (GTK_STOCK_HELP,
4386                                         GTK_ICON_SIZE_MENU);
4387       gtk_widget_show (image);
4388       menuitem = gtk_image_menu_item_new_with_label ("Help");
4389       gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), image);
4390       gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), create_menu (screen, 4, 5, TRUE));
4391       gtk_menu_item_set_right_justified (GTK_MENU_ITEM (menuitem), TRUE);
4392       gtk_menu_shell_append (GTK_MENU_SHELL (menubar), menuitem);
4393       gtk_widget_show (menuitem);
4394       
4395       menubar = gtk_menu_bar_new ();
4396       gtk_box_pack_start (GTK_BOX (box1), menubar, FALSE, TRUE, 0);
4397       gtk_widget_show (menubar);
4398       
4399       menu = create_menu (screen, 2, 10, TRUE);
4400       
4401       menuitem = gtk_menu_item_new_with_label ("Second menu bar");
4402       gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), menu);
4403       gtk_menu_shell_append (GTK_MENU_SHELL (menubar), menuitem);
4404       gtk_widget_show (menuitem);
4405       
4406       box2 = gtk_vbox_new (FALSE, 10);
4407       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
4408       gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
4409       gtk_widget_show (box2);
4410       
4411       menu = create_menu (screen, 1, 5, FALSE);
4412       gtk_menu_set_accel_group (GTK_MENU (menu), accel_group);
4413
4414       menuitem = gtk_image_menu_item_new_from_stock (GTK_STOCK_NEW, accel_group);
4415       gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
4416       gtk_widget_show (menuitem);
4417       
4418       menuitem = gtk_check_menu_item_new_with_label ("Accelerate Me");
4419       gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
4420       gtk_widget_show (menuitem);
4421       gtk_widget_add_accelerator (menuitem,
4422                                   "activate",
4423                                   accel_group,
4424                                   GDK_F1,
4425                                   0,
4426                                   GTK_ACCEL_VISIBLE);
4427       menuitem = gtk_check_menu_item_new_with_label ("Accelerator Locked");
4428       gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
4429       gtk_widget_show (menuitem);
4430       gtk_widget_add_accelerator (menuitem,
4431                                   "activate",
4432                                   accel_group,
4433                                   GDK_F2,
4434                                   0,
4435                                   GTK_ACCEL_VISIBLE | GTK_ACCEL_LOCKED);
4436       menuitem = gtk_check_menu_item_new_with_label ("Accelerators Frozen");
4437       gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
4438       gtk_widget_show (menuitem);
4439       gtk_widget_add_accelerator (menuitem,
4440                                   "activate",
4441                                   accel_group,
4442                                   GDK_F2,
4443                                   0,
4444                                   GTK_ACCEL_VISIBLE);
4445       gtk_widget_add_accelerator (menuitem,
4446                                   "activate",
4447                                   accel_group,
4448                                   GDK_F3,
4449                                   0,
4450                                   GTK_ACCEL_VISIBLE);
4451       
4452       optionmenu = gtk_option_menu_new ();
4453       gtk_option_menu_set_menu (GTK_OPTION_MENU (optionmenu), menu);
4454       gtk_option_menu_set_history (GTK_OPTION_MENU (optionmenu), 3);
4455       gtk_box_pack_start (GTK_BOX (box2), optionmenu, TRUE, TRUE, 0);
4456       gtk_widget_show (optionmenu);
4457
4458       separator = gtk_hseparator_new ();
4459       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
4460       gtk_widget_show (separator);
4461
4462       box2 = gtk_vbox_new (FALSE, 10);
4463       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
4464       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
4465       gtk_widget_show (box2);
4466
4467       button = gtk_button_new_with_label ("close");
4468       g_signal_connect_swapped (button, "clicked",
4469                                 G_CALLBACK (gtk_widget_destroy),
4470                                 window);
4471       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
4472       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
4473       gtk_widget_grab_default (button);
4474       gtk_widget_show (button);
4475     }
4476
4477   if (!GTK_WIDGET_VISIBLE (window))
4478     gtk_widget_show (window);
4479   else
4480     gtk_widget_destroy (window);
4481 }
4482
4483 static void
4484 gtk_ifactory_cb (gpointer             callback_data,
4485                  guint                callback_action,
4486                  GtkWidget           *widget)
4487 {
4488   g_message ("ItemFactory: activated \"%s\"", gtk_item_factory_path_from_widget (widget));
4489 }
4490
4491 /* GdkPixbuf RGBA C-Source image dump */
4492
4493 static const guint8 apple[] = 
4494 { ""
4495   /* Pixbuf magic (0x47646b50) */
4496   "GdkP"
4497   /* length: header (24) + pixel_data (2304) */
4498   "\0\0\11\30"
4499   /* pixdata_type (0x1010002) */
4500   "\1\1\0\2"
4501   /* rowstride (96) */
4502   "\0\0\0`"
4503   /* width (24) */
4504   "\0\0\0\30"
4505   /* height (24) */
4506   "\0\0\0\30"
4507   /* pixel_data: */
4508   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
4509   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
4510   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
4511   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
4512   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
4513   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
4514   "\0\0\0\0\0\0\0\0\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"
4515   "\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"
4516   "\0\0\0\0\0\0\0\0\0\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"
4517   "[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"
4518   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
4519   "\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"
4520   "\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"
4521   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
4522   "\0\0\0\0\0\0`l\\\20iw_\356y\211h\373x\207g\364~\216i\364u\204e\366gt"
4523   "_\374^jX\241A;-_\0\0\0~\0\0\0\0SM4)SM21B9&\22\320\270\204\1\320\270\204"
4524   "\0\0\0\0\0\0\0\0\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"
4525   "]\212r\200c\366v\205f\371jx_\323_kY\232_kZH^jY\26]iW\211@G9\272:6%j\220"
4526   "\211]\320\221\211`\377\212\203Z\377~xP\377mkE\331]^;|/0\37\21\0\0\0\0"
4527   "\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["
4528   "eT<\216\200Z\203\227\211_\354\234\217c\377\232\217b\362\232\220c\337"
4529   "\243\233k\377\252\241p\377\250\236p\377\241\225h\377\231\214_\377\210"
4530   "\202U\377srI\377[]:\355KO0U\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0i"
4531   "v^\200`lY\211^jY\"\0\0\0\0\221\204\\\273\250\233r\377\302\267\224\377"
4532   "\311\300\237\377\272\256\204\377\271\256\177\377\271\257\200\377\267"
4533   "\260\177\377\260\251x\377\250\236l\377\242\225e\377\226\213]\377~zP\377"
4534   "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"
4535   "\0\213\203[v\253\240t\377\334\326\301\377\344\340\317\377\321\312\253"
4536   "\377\303\271\217\377\300\270\213\377\277\267\210\377\272\264\203\377"
4537   "\261\255z\377\250\242n\377\243\232h\377\232\220`\377\210\202V\377nnE"
4538   "\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"
4539   "\234\222e\362\304\274\232\377\337\333\306\377\332\325\273\377\311\302"
4540   "\232\377\312\303\236\377\301\273\216\377\300\271\212\377\270\264\200"
4541   "\377\256\253v\377\246\243n\377\236\232h\377\230\220`\377\213\203V\377"
4542   "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"
4543   "\203Zl\242\234l\377\321\315\260\377\331\324\271\377\320\313\251\377\307"
4544   "\301\232\377\303\276\224\377\300\272\214\377\274\267\206\377\264\260"
4545   "|\377\253\251s\377\244\243n\377\232\230e\377\223\216^\377\207\200U\377"
4546   "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"
4547   "\210\204Y\240\245\237o\377\316\310\253\377\310\303\237\377\304\300\230"
4548   "\377\303\277\225\377\277\272\216\377\274\270\210\377\266\263\200\377"
4549   "\256\254v\377\247\246p\377\237\236j\377\227\226d\377\215\212[\377\203"
4550   "\177T\377qsH\377X]8\377FN.\377DK-\200\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
4551   "\0\0\0\0\207\204X\257\244\240o\377\300\275\231\377\301\275\226\377\274"
4552   "\270\213\377\274\270\214\377\267\264\205\377\264\262\200\377\260\256"
4553   "z\377\251\251s\377\243\244n\377\231\232g\377\220\222`\377\210\211Y\377"
4554   "|}Q\377hlC\377PU3\377CK,\377DL/Y\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
4555   "\0\0\205\204X\220\232\230h\377\261\260\204\377\266\264\212\377\261\260"
4556   "\201\377\263\260\200\377\260\257}\377\256\256x\377\253\254t\377\244\246"
4557   "o\377\233\236i\377\221\224b\377\211\214\\\377\202\204V\377txM\377]b>"
4558   "\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>"
4559   "\215\215_\377\237\237r\377\247\247x\377\247\247t\377\252\252w\377\252"
4560   "\252u\377\252\253t\377\243\246o\377\235\240j\377\223\230c\377\213\217"
4561   "]\377\201\206V\377x}P\377gkD\377RY5\377BI,\377AI,\262\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\202\205W\312\216\220`\377\230"
4563   "\232g\377\234\236i\377\236\241l\377\241\244n\377\240\244m\377\232\237"
4564   "i\377\223\230c\377\212\221]\377\200\210W\377v|P\377jnG\377Za>\377HP2"
4565   "\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"
4566   "\0wzQ6\177\201U\371\206\211Z\377\216\222`\377\220\225a\377\220\225b\377"
4567   "\220\226a\377\213\221_\377\204\213Z\377{\203R\377ryN\377iqH\377^fA\377"
4568   "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"
4569   "\0\0\0\0\0\0\0\0\0\0\0\0ptJTw|Q\371z\177R\377}\202T\377|\203T\377z\200"
4570   "R\377v|O\377pwL\377jpF\377dlB\377`hB\377Yb@\377LT6\377<C*\377\11\12\6"
4571   "\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"
4572   "\0\0\0\0\0\0\0\0\0\0\\`=UgnE\370hnG\377gmE\377djB\377]d>\377[c<\377Y"
4573   "b<\377Zc>\377V_>\377OW8\377BK/\377\16\20\12\377\0\0\0\377\0\0\0\377\0"
4574   "\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"
4575   "\0\1\0\0\0\40\22\24\15\260@D+\377W`;\377OV5\377.3\36\377.3\37\377IP0"
4576   "\377RZ7\377PZ8\3776=&\377\14\15\10\377\0\0\0\377\0\0\0\377\0\0\0\377"
4577   "\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"
4578   "\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"
4579   "\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"
4580   "\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"
4581   "\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"
4582   "\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"
4583   "\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"
4584   "\0\0\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"
4585   "\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"
4586   "\0\0\5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"};
4587
4588
4589 static void
4590 dump_accels (gpointer             callback_data,
4591              guint                callback_action,
4592              GtkWidget           *widget)
4593 {
4594   gtk_accel_map_save_fd (1 /* stdout */);
4595 }
4596     
4597 static GtkItemFactoryEntry menu_items[] =
4598 {
4599   { "/_File",                  NULL,         NULL,                  0, "<Branch>" },
4600   { "/File/tearoff1",          NULL,         gtk_ifactory_cb,       0, "<Tearoff>" },
4601   { "/File/_New",              NULL,         gtk_ifactory_cb,       0, "<StockItem>", GTK_STOCK_NEW },
4602   { "/File/_Open",             NULL,         gtk_ifactory_cb,       0, "<StockItem>", GTK_STOCK_OPEN },
4603   { "/File/_Save",             NULL,         gtk_ifactory_cb,       0, "<StockItem>", GTK_STOCK_SAVE },
4604   { "/File/Save _As...",       "<control>A", gtk_ifactory_cb,       0, "<StockItem>", GTK_STOCK_SAVE },
4605   { "/File/_Dump \"_Accels\"",  NULL,        dump_accels,           0 },
4606   { "/File/\\/Test__Escaping/And\\/\n\tWei\\\\rdly",
4607                                 NULL,        gtk_ifactory_cb,       0 },
4608   { "/File/sep1",        NULL,               gtk_ifactory_cb,       0, "<Separator>" },
4609   { "/File/_Quit",       NULL,               gtk_ifactory_cb,       0, "<StockItem>", GTK_STOCK_QUIT },
4610
4611   { "/_Preferences",                    NULL, 0,               0, "<Branch>" },
4612   { "/_Preferences/_Color",             NULL, 0,               0, "<Branch>" },
4613   { "/_Preferences/Color/_Red",         NULL, gtk_ifactory_cb, 0, "<RadioItem>" },
4614   { "/_Preferences/Color/_Green",       NULL, gtk_ifactory_cb, 0, "/Preferences/Color/Red" },
4615   { "/_Preferences/Color/_Blue",        NULL, gtk_ifactory_cb, 0, "/Preferences/Color/Red" },
4616   { "/_Preferences/_Shape",             NULL, 0,               0, "<Branch>" },
4617   { "/_Preferences/Shape/_Square",      NULL, gtk_ifactory_cb, 0, "<RadioItem>" },
4618   { "/_Preferences/Shape/_Rectangle",   NULL, gtk_ifactory_cb, 0, "/Preferences/Shape/Square" },
4619   { "/_Preferences/Shape/_Oval",        NULL, gtk_ifactory_cb, 0, "/Preferences/Shape/Rectangle" },
4620   { "/_Preferences/Shape/_Rectangle",   NULL, gtk_ifactory_cb, 0, "/Preferences/Shape/Square" },
4621   { "/_Preferences/Shape/_Oval",        NULL, gtk_ifactory_cb, 0, "/Preferences/Shape/Rectangle" },
4622   { "/_Preferences/Shape/_Image",       NULL, gtk_ifactory_cb, 0, "<ImageItem>", apple },
4623   { "/_Preferences/Coffee",                  NULL, gtk_ifactory_cb, 0, "<CheckItem>" },
4624   { "/_Preferences/Toast",                   NULL, gtk_ifactory_cb, 0, "<CheckItem>" },
4625   { "/_Preferences/Marshmallow Froot Loops", NULL, gtk_ifactory_cb, 0, "<CheckItem>" },
4626
4627   /* For testing deletion of menus */
4628   { "/_Preferences/Should_NotAppear",          NULL, 0,               0, "<Branch>" },
4629   { "/Preferences/ShouldNotAppear/SubItem1",   NULL, gtk_ifactory_cb, 0 },
4630   { "/Preferences/ShouldNotAppear/SubItem2",   NULL, gtk_ifactory_cb, 0 },
4631
4632   { "/_Help",            NULL,         0,                     0, "<LastBranch>" },
4633   { "/Help/_Help",       NULL,         gtk_ifactory_cb,       0, "<StockItem>", GTK_STOCK_HELP},
4634   { "/Help/_About",      NULL,         gtk_ifactory_cb,       0 },
4635 };
4636
4637
4638 static int nmenu_items = sizeof (menu_items) / sizeof (menu_items[0]);
4639
4640 static void
4641 create_item_factory (GtkWidget *widget)
4642 {
4643   static GtkWidget *window = NULL;
4644   
4645   if (!window)
4646     {
4647       GtkWidget *box1;
4648       GtkWidget *box2;
4649       GtkWidget *separator;
4650       GtkWidget *label;
4651       GtkWidget *button;
4652       GtkAccelGroup *accel_group;
4653       GtkItemFactory *item_factory;
4654       GtkTooltips *tooltips;
4655       
4656       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
4657       
4658       gtk_window_set_screen (GTK_WINDOW (window),
4659                              gtk_widget_get_screen (widget));
4660       
4661       g_signal_connect (window, "destroy",
4662                         G_CALLBACK(gtk_widget_destroyed),
4663                         &window);
4664       g_signal_connect (window, "delete-event",
4665                         G_CALLBACK (gtk_true),
4666                         NULL);
4667       
4668       accel_group = gtk_accel_group_new ();
4669       item_factory = gtk_item_factory_new (GTK_TYPE_MENU_BAR, "<main>", accel_group);
4670       g_object_set_data_full (G_OBJECT (window),
4671                               "<main>",
4672                               item_factory,
4673                               g_object_unref);
4674       gtk_window_add_accel_group (GTK_WINDOW (window), accel_group);
4675       gtk_window_set_title (GTK_WINDOW (window), "Item Factory");
4676       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
4677       gtk_item_factory_create_items (item_factory, nmenu_items, menu_items, NULL);
4678
4679       /* preselect /Preferences/Shape/Oval over the other radios
4680        */
4681       gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_item_factory_get_item (item_factory,
4682                                                                                       "/Preferences/Shape/Oval")),
4683                                       TRUE);
4684
4685       /* preselect /Preferences/Coffee
4686        */
4687       gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_item_factory_get_item (item_factory,
4688                                                                                       "/Preferences/Coffee")),
4689                                       TRUE);
4690
4691       /* preselect /Preferences/Marshmallow Froot Loops and set it insensitive
4692        */
4693       gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_item_factory_get_item (item_factory,
4694                                                                                       "/Preferences/Marshmallow Froot Loops")),
4695                                       TRUE);
4696       gtk_widget_set_sensitive (GTK_WIDGET (gtk_item_factory_get_item (item_factory,
4697                                                                        "/Preferences/Marshmallow Froot Loops")),
4698                                 FALSE);
4699        
4700       /* Test how tooltips (ugh) work on menu items
4701        */
4702       tooltips = gtk_tooltips_new ();
4703       g_object_ref (tooltips);
4704       gtk_object_sink (GTK_OBJECT (tooltips));
4705       g_object_set_data_full (G_OBJECT (window), "testgtk-tooltips",
4706                               tooltips, (GDestroyNotify)g_object_unref);
4707       
4708       gtk_tooltips_set_tip (tooltips, gtk_item_factory_get_item (item_factory, "/File/New"),
4709                             "Create a new file", NULL);
4710       gtk_tooltips_set_tip (tooltips, gtk_item_factory_get_item (item_factory, "/File/Open"),
4711                             "Open a file", NULL);
4712       gtk_tooltips_set_tip (tooltips, gtk_item_factory_get_item (item_factory, "/File/Save"),
4713                             "Safe file", NULL);
4714       gtk_tooltips_set_tip (tooltips, gtk_item_factory_get_item (item_factory, "/Preferences/Color"),
4715                             "Modify color", NULL);
4716
4717       box1 = gtk_vbox_new (FALSE, 0);
4718       gtk_container_add (GTK_CONTAINER (window), box1);
4719       
4720       gtk_box_pack_start (GTK_BOX (box1),
4721                           gtk_item_factory_get_widget (item_factory, "<main>"),
4722                           FALSE, FALSE, 0);
4723
4724       label = gtk_label_new ("Type\n<alt>\nto start");
4725       gtk_widget_set_size_request (label, 200, 200);
4726       gtk_misc_set_alignment (GTK_MISC (label), 0.5, 0.5);
4727       gtk_box_pack_start (GTK_BOX (box1), label, TRUE, TRUE, 0);
4728
4729
4730       separator = gtk_hseparator_new ();
4731       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
4732
4733
4734       box2 = gtk_vbox_new (FALSE, 10);
4735       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
4736       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
4737
4738       button = gtk_button_new_with_label ("close");
4739       g_signal_connect_swapped (button, "clicked",
4740                                 G_CALLBACK (gtk_widget_destroy),
4741                                 window);
4742       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
4743       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
4744       gtk_widget_grab_default (button);
4745
4746       gtk_item_factory_delete_item (item_factory, "/Preferences/ShouldNotAppear");
4747       
4748       gtk_widget_show_all (window);
4749     }
4750   else
4751     gtk_widget_destroy (window);
4752 }
4753
4754 static GtkWidget *
4755 accel_button_new (GtkAccelGroup *accel_group,
4756                   const gchar   *text,
4757                   const gchar   *accel)
4758 {
4759   guint keyval;
4760   GdkModifierType modifiers;
4761   GtkWidget *button;
4762   GtkWidget *label;
4763
4764   gtk_accelerator_parse (accel, &keyval, &modifiers);
4765   g_assert (keyval);
4766
4767   button = gtk_button_new ();
4768   gtk_widget_add_accelerator (button, "activate", accel_group,
4769                               keyval, modifiers, GTK_ACCEL_VISIBLE | GTK_ACCEL_LOCKED);
4770
4771   label = gtk_accel_label_new (text);
4772   gtk_accel_label_set_accel_widget (GTK_ACCEL_LABEL (label), button);
4773   gtk_widget_show (label);
4774   
4775   gtk_container_add (GTK_CONTAINER (button), label);
4776
4777   return button;
4778 }
4779
4780 static void
4781 create_key_lookup (GtkWidget *widget)
4782 {
4783   static GtkWidget *window = NULL;
4784   gpointer window_ptr;
4785
4786   if (!window)
4787     {
4788       GtkAccelGroup *accel_group = gtk_accel_group_new ();
4789       GtkWidget *button;
4790       
4791       window = gtk_dialog_new_with_buttons ("Key Lookup", NULL, 0,
4792                                             GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
4793                                             NULL);
4794
4795       gtk_window_set_screen (GTK_WINDOW (window),
4796                              gtk_widget_get_screen (widget));
4797
4798       /* We have to expand it so the accel labels will draw their labels
4799        */
4800       gtk_window_set_default_size (GTK_WINDOW (window), 300, -1);
4801       
4802       gtk_window_add_accel_group (GTK_WINDOW (window), accel_group);
4803       
4804       button = gtk_button_new_with_mnemonic ("Button 1 (_a)");
4805       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
4806       button = gtk_button_new_with_mnemonic ("Button 2 (_A)");
4807       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
4808       button = gtk_button_new_with_mnemonic ("Button 3 (_\321\204)");
4809       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
4810       button = gtk_button_new_with_mnemonic ("Button 4 (_\320\244)");
4811       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
4812       button = gtk_button_new_with_mnemonic ("Button 6 (_b)");
4813       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
4814       button = accel_button_new (accel_group, "Button 7", "<Alt><Shift>b");
4815       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
4816       button = accel_button_new (accel_group, "Button 8", "<Alt>d");
4817       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
4818       button = accel_button_new (accel_group, "Button 9", "<Alt>Cyrillic_ve");
4819       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
4820       button = gtk_button_new_with_mnemonic ("Button 10 (_1)");
4821       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
4822       button = gtk_button_new_with_mnemonic ("Button 11 (_!)");
4823       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
4824       button = accel_button_new (accel_group, "Button 12", "<Super>a");
4825       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
4826       button = accel_button_new (accel_group, "Button 13", "<Hyper>a");
4827       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
4828       button = accel_button_new (accel_group, "Button 14", "<Meta>a");
4829       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
4830       button = accel_button_new (accel_group, "Button 15", "<Shift><Mod4>b");
4831       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
4832
4833       window_ptr = &window;
4834       g_object_add_weak_pointer (G_OBJECT (window), window_ptr);
4835       g_signal_connect (window, "response", G_CALLBACK (gtk_object_destroy), NULL);
4836
4837       gtk_widget_show_all (window);
4838     }
4839   else
4840     gtk_widget_destroy (window);
4841 }
4842
4843
4844 /*
4845  create_modal_window
4846  */
4847
4848 static gboolean
4849 cmw_destroy_cb(GtkWidget *widget)
4850 {
4851   /* This is needed to get out of gtk_main */
4852   gtk_main_quit ();
4853
4854   return FALSE;
4855 }
4856
4857 static void
4858 cmw_color (GtkWidget *widget, GtkWidget *parent)
4859 {
4860     GtkWidget *csd;
4861
4862     csd = gtk_color_selection_dialog_new ("This is a modal color selection dialog");
4863
4864     gtk_window_set_screen (GTK_WINDOW (csd), gtk_widget_get_screen (parent));
4865
4866     gtk_color_selection_set_has_palette (GTK_COLOR_SELECTION (GTK_COLOR_SELECTION_DIALOG (csd)->colorsel),
4867                                          TRUE);
4868     
4869     /* Set as modal */
4870     gtk_window_set_modal (GTK_WINDOW(csd),TRUE);
4871
4872     /* And mark it as a transient dialog */
4873     gtk_window_set_transient_for (GTK_WINDOW (csd), GTK_WINDOW (parent));
4874     
4875     g_signal_connect (csd, "destroy",
4876                       G_CALLBACK (cmw_destroy_cb), NULL);
4877
4878     g_signal_connect_swapped (GTK_COLOR_SELECTION_DIALOG (csd)->ok_button,
4879                              "clicked", G_CALLBACK (gtk_widget_destroy), csd);
4880     g_signal_connect_swapped (GTK_COLOR_SELECTION_DIALOG (csd)->cancel_button,
4881                              "clicked", G_CALLBACK (gtk_widget_destroy), csd);
4882     
4883     /* wait until destroy calls gtk_main_quit */
4884     gtk_widget_show (csd);    
4885     gtk_main ();
4886 }
4887
4888 static void
4889 cmw_file (GtkWidget *widget, GtkWidget *parent)
4890 {
4891     GtkWidget *fs;
4892
4893     fs = gtk_file_selection_new("This is a modal file selection dialog");
4894
4895     gtk_window_set_screen (GTK_WINDOW (fs), gtk_widget_get_screen (parent));
4896
4897     /* Set as modal */
4898     gtk_window_set_modal (GTK_WINDOW(fs),TRUE);
4899
4900     /* And mark it as a transient dialog */
4901     gtk_window_set_transient_for (GTK_WINDOW (fs), GTK_WINDOW (parent));
4902
4903     g_signal_connect (fs, "destroy",
4904                       G_CALLBACK (cmw_destroy_cb), NULL);
4905
4906     g_signal_connect_swapped (GTK_FILE_SELECTION (fs)->ok_button,
4907                               "clicked", G_CALLBACK (gtk_widget_destroy), fs);
4908     g_signal_connect_swapped (GTK_FILE_SELECTION (fs)->cancel_button,
4909                               "clicked", G_CALLBACK (gtk_widget_destroy), fs);
4910     
4911     /* wait until destroy calls gtk_main_quit */
4912     gtk_widget_show (fs);
4913     
4914     gtk_main();
4915 }
4916
4917
4918 static void
4919 create_modal_window (GtkWidget *widget)
4920 {
4921   GtkWidget *window = NULL;
4922   GtkWidget *box1,*box2;
4923   GtkWidget *frame1;
4924   GtkWidget *btnColor,*btnFile,*btnClose;
4925
4926   /* Create modal window (Here you can use any window descendent )*/
4927   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
4928   gtk_window_set_screen (GTK_WINDOW (window),
4929                          gtk_widget_get_screen (widget));
4930
4931   gtk_window_set_title (GTK_WINDOW(window),"This window is modal");
4932
4933   /* Set window as modal */
4934   gtk_window_set_modal (GTK_WINDOW(window),TRUE);
4935
4936   /* Create widgets */
4937   box1 = gtk_vbox_new (FALSE,5);
4938   frame1 = gtk_frame_new ("Standard dialogs in modal form");
4939   box2 = gtk_vbox_new (TRUE,5);
4940   btnColor = gtk_button_new_with_label ("Color");
4941   btnFile = gtk_button_new_with_label ("File Selection");
4942   btnClose = gtk_button_new_with_label ("Close");
4943
4944   /* Init widgets */
4945   gtk_container_set_border_width (GTK_CONTAINER (box1), 3);
4946   gtk_container_set_border_width (GTK_CONTAINER (box2), 3);
4947     
4948   /* Pack widgets */
4949   gtk_container_add (GTK_CONTAINER (window), box1);
4950   gtk_box_pack_start (GTK_BOX (box1), frame1, TRUE, TRUE, 4);
4951   gtk_container_add (GTK_CONTAINER (frame1), box2);
4952   gtk_box_pack_start (GTK_BOX (box2), btnColor, FALSE, FALSE, 4);
4953   gtk_box_pack_start (GTK_BOX (box2), btnFile, FALSE, FALSE, 4);
4954   gtk_box_pack_start (GTK_BOX (box1), gtk_hseparator_new (), FALSE, FALSE, 4);
4955   gtk_box_pack_start (GTK_BOX (box1), btnClose, FALSE, FALSE, 4);
4956    
4957   /* connect signals */
4958   g_signal_connect_swapped (btnClose, "clicked",
4959                             G_CALLBACK (gtk_widget_destroy), window);
4960
4961   g_signal_connect (window, "destroy",
4962                     G_CALLBACK (cmw_destroy_cb), NULL);
4963   
4964   g_signal_connect (btnColor, "clicked",
4965                     G_CALLBACK (cmw_color), window);
4966   g_signal_connect (btnFile, "clicked",
4967                     G_CALLBACK (cmw_file), window);
4968
4969   /* Show widgets */
4970   gtk_widget_show_all (window);
4971
4972   /* wait until dialog get destroyed */
4973   gtk_main();
4974 }
4975
4976 /*
4977  * GtkMessageDialog
4978  */
4979
4980 static void
4981 make_message_dialog (GdkScreen *screen,
4982                      GtkWidget **dialog,
4983                      GtkMessageType  type,
4984                      GtkButtonsType  buttons,
4985                      guint           default_response)
4986 {
4987   if (*dialog)
4988     {
4989       gtk_widget_destroy (*dialog);
4990
4991       return;
4992     }
4993
4994   *dialog = gtk_message_dialog_new (NULL, 0, type, buttons,
4995                                     "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.)");
4996
4997   gtk_window_set_screen (GTK_WINDOW (*dialog), screen);
4998
4999   g_signal_connect_swapped (*dialog,
5000                             "response",
5001                             G_CALLBACK (gtk_widget_destroy),
5002                             *dialog);
5003   
5004   g_signal_connect (*dialog,
5005                     "destroy",
5006                     G_CALLBACK (gtk_widget_destroyed),
5007                     dialog);
5008
5009   gtk_dialog_set_default_response (GTK_DIALOG (*dialog), default_response);
5010
5011   gtk_widget_show (*dialog);
5012 }
5013
5014 static void
5015 create_message_dialog (GtkWidget *widget)
5016 {
5017   static GtkWidget *info = NULL;
5018   static GtkWidget *warning = NULL;
5019   static GtkWidget *error = NULL;
5020   static GtkWidget *question = NULL;
5021   GdkScreen *screen = gtk_widget_get_screen (widget);
5022
5023   make_message_dialog (screen, &info, GTK_MESSAGE_INFO, GTK_BUTTONS_OK, GTK_RESPONSE_OK);
5024   make_message_dialog (screen, &warning, GTK_MESSAGE_WARNING, GTK_BUTTONS_CLOSE, GTK_RESPONSE_CLOSE);
5025   make_message_dialog (screen, &error, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK_CANCEL, GTK_RESPONSE_OK);
5026   make_message_dialog (screen, &question, GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO, GTK_RESPONSE_NO);
5027 }
5028
5029 /*
5030  * GtkScrolledWindow
5031  */
5032
5033 static GtkWidget *sw_parent = NULL;
5034 static GtkWidget *sw_float_parent;
5035 static guint sw_destroyed_handler = 0;
5036
5037 static gboolean
5038 scrolled_windows_delete_cb (GtkWidget *widget, GdkEventAny *event, GtkWidget *scrollwin)
5039 {
5040   gtk_widget_reparent (scrollwin, sw_parent);
5041   
5042   g_signal_handler_disconnect (sw_parent, sw_destroyed_handler);
5043   sw_float_parent = NULL;
5044   sw_parent = NULL;
5045   sw_destroyed_handler = 0;
5046
5047   return FALSE;
5048 }
5049
5050 static void
5051 scrolled_windows_destroy_cb (GtkWidget *widget, GtkWidget *scrollwin)
5052 {
5053   gtk_widget_destroy (sw_float_parent);
5054
5055   sw_float_parent = NULL;
5056   sw_parent = NULL;
5057   sw_destroyed_handler = 0;
5058 }
5059
5060 static void
5061 scrolled_windows_remove (GtkWidget *widget, GtkWidget *scrollwin)
5062 {
5063   if (sw_parent)
5064     {
5065       gtk_widget_reparent (scrollwin, sw_parent);
5066       gtk_widget_destroy (sw_float_parent);
5067
5068       g_signal_handler_disconnect (sw_parent, sw_destroyed_handler);
5069       sw_float_parent = NULL;
5070       sw_parent = NULL;
5071       sw_destroyed_handler = 0;
5072     }
5073   else
5074     {
5075       sw_parent = scrollwin->parent;
5076       sw_float_parent = gtk_window_new (GTK_WINDOW_TOPLEVEL);
5077       gtk_window_set_screen (GTK_WINDOW (sw_float_parent),
5078                              gtk_widget_get_screen (widget));
5079       
5080       gtk_window_set_default_size (GTK_WINDOW (sw_float_parent), 200, 200);
5081       
5082       gtk_widget_reparent (scrollwin, sw_float_parent);
5083       gtk_widget_show (sw_float_parent);
5084
5085       sw_destroyed_handler =
5086         g_signal_connect (sw_parent, "destroy",
5087                           G_CALLBACK (scrolled_windows_destroy_cb), scrollwin);
5088       g_signal_connect (sw_float_parent, "delete_event",
5089                         G_CALLBACK (scrolled_windows_delete_cb), scrollwin);
5090     }
5091 }
5092
5093 static void
5094 create_scrolled_windows (GtkWidget *widget)
5095 {
5096   static GtkWidget *window;
5097   GtkWidget *scrolled_window;
5098   GtkWidget *table;
5099   GtkWidget *button;
5100   char buffer[32];
5101   int i, j;
5102
5103   if (!window)
5104     {
5105       window = gtk_dialog_new ();
5106
5107       gtk_window_set_screen (GTK_WINDOW (window),
5108                              gtk_widget_get_screen (widget));
5109
5110       g_signal_connect (window, "destroy",
5111                         G_CALLBACK (gtk_widget_destroyed),
5112                         &window);
5113
5114       gtk_window_set_title (GTK_WINDOW (window), "dialog");
5115       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
5116
5117
5118       scrolled_window = gtk_scrolled_window_new (NULL, NULL);
5119       gtk_container_set_border_width (GTK_CONTAINER (scrolled_window), 10);
5120       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
5121                                       GTK_POLICY_AUTOMATIC,
5122                                       GTK_POLICY_AUTOMATIC);
5123       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
5124                           scrolled_window, TRUE, TRUE, 0);
5125       gtk_widget_show (scrolled_window);
5126
5127       table = gtk_table_new (20, 20, FALSE);
5128       gtk_table_set_row_spacings (GTK_TABLE (table), 10);
5129       gtk_table_set_col_spacings (GTK_TABLE (table), 10);
5130       gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_window), table);
5131       gtk_container_set_focus_hadjustment (GTK_CONTAINER (table),
5132                                            gtk_scrolled_window_get_hadjustment (GTK_SCROLLED_WINDOW (scrolled_window)));
5133       gtk_container_set_focus_vadjustment (GTK_CONTAINER (table),
5134                                            gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (scrolled_window)));
5135       gtk_widget_show (table);
5136
5137       for (i = 0; i < 20; i++)
5138         for (j = 0; j < 20; j++)
5139           {
5140             sprintf (buffer, "button (%d,%d)\n", i, j);
5141             button = gtk_toggle_button_new_with_label (buffer);
5142             gtk_table_attach_defaults (GTK_TABLE (table), button,
5143                                        i, i+1, j, j+1);
5144             gtk_widget_show (button);
5145           }
5146
5147
5148       button = gtk_button_new_with_label ("Close");
5149       g_signal_connect_swapped (button, "clicked",
5150                                 G_CALLBACK (gtk_widget_destroy),
5151                                 window);
5152       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
5153       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
5154                           button, TRUE, TRUE, 0);
5155       gtk_widget_grab_default (button);
5156       gtk_widget_show (button);
5157
5158       button = gtk_button_new_with_label ("Reparent Out");
5159       g_signal_connect (button, "clicked",
5160                         G_CALLBACK (scrolled_windows_remove),
5161                         scrolled_window);
5162       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
5163       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
5164                           button, TRUE, TRUE, 0);
5165       gtk_widget_grab_default (button);
5166       gtk_widget_show (button);
5167
5168       gtk_window_set_default_size (GTK_WINDOW (window), 300, 300);
5169     }
5170
5171   if (!GTK_WIDGET_VISIBLE (window))
5172     gtk_widget_show (window);
5173   else
5174     gtk_widget_destroy (window);
5175 }
5176
5177 /*
5178  * GtkEntry
5179  */
5180
5181 static void
5182 entry_toggle_frame (GtkWidget *checkbutton,
5183                     GtkWidget *entry)
5184 {
5185    gtk_entry_set_has_frame (GTK_ENTRY(entry),
5186                             GTK_TOGGLE_BUTTON(checkbutton)->active);
5187 }
5188
5189 static void
5190 entry_toggle_sensitive (GtkWidget *checkbutton,
5191                         GtkWidget *entry)
5192 {
5193    gtk_widget_set_sensitive (entry, GTK_TOGGLE_BUTTON(checkbutton)->active);
5194 }
5195
5196 static gboolean
5197 entry_progress_timeout (gpointer data)
5198 {
5199   if (GPOINTER_TO_INT (g_object_get_data (G_OBJECT (data), "progress-pulse")))
5200     {
5201       gtk_entry_progress_pulse (GTK_ENTRY (data));
5202     }
5203   else
5204     {
5205       gdouble fraction;
5206
5207       fraction = gtk_entry_get_progress_fraction (GTK_ENTRY (data));
5208
5209       fraction += 0.05;
5210       if (fraction > 1.0001)
5211         fraction = 0.0;
5212
5213       gtk_entry_set_progress_fraction (GTK_ENTRY (data), fraction);
5214     }
5215
5216   return TRUE;
5217 }
5218
5219 static void
5220 entry_remove_timeout (gpointer data)
5221 {
5222   g_source_remove (GPOINTER_TO_UINT (data));
5223 }
5224
5225 static void
5226 entry_toggle_progress (GtkWidget *checkbutton,
5227                        GtkWidget *entry)
5228 {
5229   if (GTK_TOGGLE_BUTTON (checkbutton)->active)
5230     {
5231       guint timeout = gdk_threads_add_timeout (100,
5232                                                entry_progress_timeout,
5233                                                entry);
5234       g_object_set_data_full (G_OBJECT (entry), "timeout-id",
5235                               GUINT_TO_POINTER (timeout),
5236                               entry_remove_timeout);
5237     }
5238   else
5239     {
5240       g_object_set_data (G_OBJECT (entry), "timeout-id",
5241                          GUINT_TO_POINTER (0));
5242
5243       gtk_entry_set_progress_fraction (GTK_ENTRY (entry), 0.0);
5244     }
5245 }
5246
5247 static void
5248 entry_toggle_pulse (GtkWidget *checkbutton,
5249                     GtkWidget *entry)
5250 {
5251   g_object_set_data (G_OBJECT (entry), "progress-pulse",
5252                      GINT_TO_POINTER (GTK_TOGGLE_BUTTON (checkbutton)->active));
5253 }
5254
5255 static void
5256 entry_props_clicked (GtkWidget *button,
5257                      GObject   *entry)
5258 {
5259   GtkWidget *window = create_prop_editor (entry, 0);
5260
5261   gtk_window_set_title (GTK_WINDOW (window), "Entry Properties");
5262 }
5263
5264 static void
5265 create_entry (GtkWidget *widget)
5266 {
5267   static GtkWidget *window = NULL;
5268   GtkWidget *box1;
5269   GtkWidget *box2;
5270   GtkWidget *hbox;
5271   GtkWidget *has_frame_check;
5272   GtkWidget *sensitive_check;
5273   GtkWidget *progress_check;
5274   GtkWidget *entry, *cb;
5275   GtkWidget *button;
5276   GtkWidget *separator;
5277   GList *cbitems = NULL;
5278
5279   if (!window)
5280     {
5281       cbitems = g_list_append(cbitems, "item0");
5282       cbitems = g_list_append(cbitems, "item1 item1");
5283       cbitems = g_list_append(cbitems, "item2 item2 item2");
5284       cbitems = g_list_append(cbitems, "item3 item3 item3 item3");
5285       cbitems = g_list_append(cbitems, "item4 item4 item4 item4 item4");
5286       cbitems = g_list_append(cbitems, "item5 item5 item5 item5 item5 item5");
5287       cbitems = g_list_append(cbitems, "item6 item6 item6 item6 item6");
5288       cbitems = g_list_append(cbitems, "item7 item7 item7 item7");
5289       cbitems = g_list_append(cbitems, "item8 item8 item8");
5290       cbitems = g_list_append(cbitems, "item9 item9");
5291
5292       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
5293       gtk_window_set_screen (GTK_WINDOW (window),
5294                              gtk_widget_get_screen (widget));
5295
5296       g_signal_connect (window, "destroy",
5297                         G_CALLBACK (gtk_widget_destroyed),
5298                         &window);
5299
5300       gtk_window_set_title (GTK_WINDOW (window), "entry");
5301       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
5302
5303
5304       box1 = gtk_vbox_new (FALSE, 0);
5305       gtk_container_add (GTK_CONTAINER (window), box1);
5306
5307
5308       box2 = gtk_vbox_new (FALSE, 10);
5309       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
5310       gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
5311
5312       hbox = gtk_hbox_new (FALSE, 5);
5313       gtk_box_pack_start (GTK_BOX (box2), hbox, TRUE, TRUE, 0);
5314       
5315       entry = gtk_entry_new ();
5316       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");
5317       gtk_editable_select_region (GTK_EDITABLE (entry), 0, 5);
5318       gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0);
5319
5320       button = gtk_button_new_with_mnemonic ("_Props");
5321       gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
5322       g_signal_connect (button, "clicked",
5323                         G_CALLBACK (entry_props_clicked),
5324                         entry);
5325
5326       cb = gtk_combo_new ();
5327       gtk_combo_set_popdown_strings (GTK_COMBO (cb), cbitems);
5328       gtk_entry_set_text (GTK_ENTRY (GTK_COMBO(cb)->entry), "hello world \n\n\n foo");
5329       gtk_editable_select_region (GTK_EDITABLE (GTK_COMBO(cb)->entry),
5330                                   0, -1);
5331       gtk_box_pack_start (GTK_BOX (box2), cb, TRUE, TRUE, 0);
5332
5333       sensitive_check = gtk_check_button_new_with_label("Sensitive");
5334       gtk_box_pack_start (GTK_BOX (box2), sensitive_check, FALSE, TRUE, 0);
5335       g_signal_connect (sensitive_check, "toggled",
5336                         G_CALLBACK (entry_toggle_sensitive), entry);
5337       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sensitive_check), TRUE);
5338
5339       has_frame_check = gtk_check_button_new_with_label("Has Frame");
5340       gtk_box_pack_start (GTK_BOX (box2), has_frame_check, FALSE, TRUE, 0);
5341       g_signal_connect (has_frame_check, "toggled",
5342                         G_CALLBACK (entry_toggle_frame), entry);
5343       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (has_frame_check), TRUE);
5344
5345       progress_check = gtk_check_button_new_with_label("Show Progress");
5346       gtk_box_pack_start (GTK_BOX (box2), progress_check, FALSE, TRUE, 0);
5347       g_signal_connect (progress_check, "toggled",
5348                         G_CALLBACK (entry_toggle_progress), entry);
5349
5350       progress_check = gtk_check_button_new_with_label("Pulse Progress");
5351       gtk_box_pack_start (GTK_BOX (box2), progress_check, FALSE, TRUE, 0);
5352       g_signal_connect (progress_check, "toggled",
5353                         G_CALLBACK (entry_toggle_pulse), entry);
5354
5355       separator = gtk_hseparator_new ();
5356       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
5357
5358       box2 = gtk_vbox_new (FALSE, 10);
5359       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
5360       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
5361
5362       button = gtk_button_new_with_label ("close");
5363       g_signal_connect_swapped (button, "clicked",
5364                                 G_CALLBACK (gtk_widget_destroy),
5365                                 window);
5366       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
5367       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
5368       gtk_widget_grab_default (button);
5369     }
5370
5371   if (!GTK_WIDGET_VISIBLE (window))
5372     gtk_widget_show_all (window);
5373   else
5374     gtk_widget_destroy (window);
5375 }
5376
5377 static void
5378 create_expander (GtkWidget *widget)
5379 {
5380   GtkWidget *box1;
5381   GtkWidget *expander;
5382   GtkWidget *hidden;
5383   static GtkWidget *window = NULL;
5384
5385   if (!window)
5386     {
5387       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
5388       gtk_window_set_screen (GTK_WINDOW (window),
5389                              gtk_widget_get_screen (widget));
5390       
5391       g_signal_connect (window, "destroy",
5392                         G_CALLBACK (gtk_widget_destroyed),
5393                         &window);
5394       
5395       gtk_window_set_title (GTK_WINDOW (window), "expander");
5396       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
5397       
5398       box1 = gtk_vbox_new (FALSE, 0);
5399       gtk_container_add (GTK_CONTAINER (window), box1);
5400       
5401       expander = gtk_expander_new ("The Hidden");
5402       
5403       gtk_box_pack_start (GTK_BOX (box1), expander, TRUE, TRUE, 0);
5404       
5405       hidden = gtk_label_new ("Revealed!");
5406       
5407       gtk_container_add (GTK_CONTAINER (expander), hidden);
5408     }
5409   
5410   if (!GTK_WIDGET_VISIBLE (window))
5411     gtk_widget_show_all (window);
5412   else
5413     gtk_widget_destroy (window);
5414 }
5415
5416
5417 /* GtkEventBox */
5418
5419
5420 static void
5421 event_box_label_pressed (GtkWidget        *widget,
5422                          GdkEventButton   *event,
5423                          gpointer user_data)
5424 {
5425   g_print ("clicked on event box\n");
5426 }
5427
5428 static void
5429 event_box_button_clicked (GtkWidget *widget,
5430                           GtkWidget *button,
5431                           gpointer user_data)
5432 {
5433   g_print ("pushed button\n");
5434 }
5435
5436 static void
5437 event_box_toggle_visible_window (GtkWidget *checkbutton,
5438                                  GtkEventBox *event_box)
5439 {
5440   gtk_event_box_set_visible_window (event_box,
5441                                     GTK_TOGGLE_BUTTON(checkbutton)->active);
5442 }
5443
5444 static void
5445 event_box_toggle_above_child (GtkWidget *checkbutton,
5446                               GtkEventBox *event_box)
5447 {
5448   gtk_event_box_set_above_child (event_box,
5449                                  GTK_TOGGLE_BUTTON(checkbutton)->active);
5450 }
5451
5452 static void
5453 create_event_box (GtkWidget *widget)
5454 {
5455   static GtkWidget *window = NULL;
5456   GtkWidget *box1;
5457   GtkWidget *box2;
5458   GtkWidget *hbox;
5459   GtkWidget *vbox;
5460   GtkWidget *button;
5461   GtkWidget *separator;
5462   GtkWidget *event_box;
5463   GtkWidget *label;
5464   GtkWidget *visible_window_check;
5465   GtkWidget *above_child_check;
5466   GdkColor color;
5467
5468   if (!window)
5469     {
5470       color.red = 0;
5471       color.blue = 65535;
5472       color.green = 0;
5473       
5474       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
5475       gtk_window_set_screen (GTK_WINDOW (window),
5476                              gtk_widget_get_screen (widget));
5477
5478       g_signal_connect (window, "destroy",
5479                         G_CALLBACK (gtk_widget_destroyed),
5480                         &window);
5481
5482       gtk_window_set_title (GTK_WINDOW (window), "event box");
5483       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
5484
5485       box1 = gtk_vbox_new (FALSE, 0);
5486       gtk_container_add (GTK_CONTAINER (window), box1);
5487       gtk_widget_modify_bg (window, GTK_STATE_NORMAL, &color);
5488
5489       hbox = gtk_hbox_new (FALSE, 0);
5490       gtk_box_pack_start (GTK_BOX (box1), hbox, TRUE, FALSE, 0);
5491       
5492       event_box = gtk_event_box_new ();
5493       gtk_box_pack_start (GTK_BOX (hbox), event_box, TRUE, FALSE, 0);
5494
5495       vbox = gtk_vbox_new (FALSE, 0);
5496       gtk_container_add (GTK_CONTAINER (event_box), vbox);
5497       g_signal_connect (event_box, "button_press_event",
5498                         G_CALLBACK (event_box_label_pressed),
5499                         NULL);
5500       
5501       label = gtk_label_new ("Click on this label");
5502       gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, FALSE, 0);
5503
5504       button = gtk_button_new_with_label ("button in eventbox");
5505       gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, FALSE, 0);
5506       g_signal_connect (button, "clicked",
5507                         G_CALLBACK (event_box_button_clicked),
5508                         NULL);
5509       
5510
5511       visible_window_check = gtk_check_button_new_with_label("Visible Window");
5512       gtk_box_pack_start (GTK_BOX (box1), visible_window_check, FALSE, TRUE, 0);
5513       g_signal_connect (visible_window_check, "toggled",
5514                         G_CALLBACK (event_box_toggle_visible_window), event_box);
5515       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (visible_window_check), FALSE);
5516       
5517       above_child_check = gtk_check_button_new_with_label("Above Child");
5518       gtk_box_pack_start (GTK_BOX (box1), above_child_check, FALSE, TRUE, 0);
5519       g_signal_connect (above_child_check, "toggled",
5520                         G_CALLBACK (event_box_toggle_above_child), event_box);
5521       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (above_child_check), FALSE);
5522       
5523       separator = gtk_hseparator_new ();
5524       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
5525
5526       box2 = gtk_vbox_new (FALSE, 10);
5527       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
5528       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
5529
5530       button = gtk_button_new_with_label ("close");
5531       g_signal_connect_swapped (button, "clicked",
5532                                 G_CALLBACK (gtk_widget_destroy),
5533                                 window);
5534       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
5535       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
5536       gtk_widget_grab_default (button);
5537     }
5538
5539   if (!GTK_WIDGET_VISIBLE (window))
5540     gtk_widget_show_all (window);
5541   else
5542     gtk_widget_destroy (window);
5543 }
5544
5545
5546 /*
5547  * GtkSizeGroup
5548  */
5549
5550 #define SIZE_GROUP_INITIAL_SIZE 50
5551
5552 static void
5553 size_group_hsize_changed (GtkSpinButton *spin_button,
5554                           GtkWidget     *button)
5555 {
5556   gtk_widget_set_size_request (GTK_BIN (button)->child,
5557                                gtk_spin_button_get_value_as_int (spin_button),
5558                                -1);
5559 }
5560
5561 static void
5562 size_group_vsize_changed (GtkSpinButton *spin_button,
5563                           GtkWidget     *button)
5564 {
5565   gtk_widget_set_size_request (GTK_BIN (button)->child,
5566                                -1,
5567                                gtk_spin_button_get_value_as_int (spin_button));
5568 }
5569
5570 static GtkWidget *
5571 create_size_group_window (GdkScreen    *screen,
5572                           GtkSizeGroup *master_size_group)
5573 {
5574   GtkWidget *window;
5575   GtkWidget *table;
5576   GtkWidget *main_button;
5577   GtkWidget *button;
5578   GtkWidget *spin_button;
5579   GtkWidget *hbox;
5580   GtkSizeGroup *hgroup1;
5581   GtkSizeGroup *hgroup2;
5582   GtkSizeGroup *vgroup1;
5583   GtkSizeGroup *vgroup2;
5584
5585   window = gtk_dialog_new_with_buttons ("GtkSizeGroup",
5586                                         NULL, 0,
5587                                         GTK_STOCK_CLOSE,
5588                                         GTK_RESPONSE_NONE,
5589                                         NULL);
5590
5591   gtk_window_set_screen (GTK_WINDOW (window), screen);
5592
5593   gtk_window_set_resizable (GTK_WINDOW (window), TRUE);
5594
5595   g_signal_connect (window, "response",
5596                     G_CALLBACK (gtk_widget_destroy),
5597                     NULL);
5598
5599   table = gtk_table_new (2, 2, FALSE);
5600   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), table, TRUE, TRUE, 0);
5601
5602   gtk_table_set_row_spacings (GTK_TABLE (table), 5);
5603   gtk_table_set_col_spacings (GTK_TABLE (table), 5);
5604   gtk_container_set_border_width (GTK_CONTAINER (table), 5);
5605   gtk_widget_set_size_request (table, 250, 250);
5606
5607   hgroup1 = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
5608   hgroup2 = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
5609   vgroup1 = gtk_size_group_new (GTK_SIZE_GROUP_VERTICAL);
5610   vgroup2 = gtk_size_group_new (GTK_SIZE_GROUP_VERTICAL);
5611
5612   main_button = gtk_button_new_with_label ("X");
5613   
5614   gtk_table_attach (GTK_TABLE (table), main_button,
5615                     0, 1,       0, 1,
5616                     GTK_EXPAND, GTK_EXPAND,
5617                     0,          0);
5618   gtk_size_group_add_widget (master_size_group, main_button);
5619   gtk_size_group_add_widget (hgroup1, main_button);
5620   gtk_size_group_add_widget (vgroup1, main_button);
5621   gtk_widget_set_size_request (GTK_BIN (main_button)->child,
5622                                SIZE_GROUP_INITIAL_SIZE,
5623                                SIZE_GROUP_INITIAL_SIZE);
5624
5625   button = gtk_button_new ();
5626   gtk_table_attach (GTK_TABLE (table), button,
5627                     1, 2,       0, 1,
5628                     GTK_EXPAND, GTK_EXPAND,
5629                     0,          0);
5630   gtk_size_group_add_widget (vgroup1, button);
5631   gtk_size_group_add_widget (vgroup2, button);
5632
5633   button = gtk_button_new ();
5634   gtk_table_attach (GTK_TABLE (table), button,
5635                     0, 1,       1, 2,
5636                     GTK_EXPAND, GTK_EXPAND,
5637                     0,          0);
5638   gtk_size_group_add_widget (hgroup1, button);
5639   gtk_size_group_add_widget (hgroup2, button);
5640
5641   button = gtk_button_new ();
5642   gtk_table_attach (GTK_TABLE (table), button,
5643                     1, 2,       1, 2,
5644                     GTK_EXPAND, GTK_EXPAND,
5645                     0,          0);
5646   gtk_size_group_add_widget (hgroup2, button);
5647   gtk_size_group_add_widget (vgroup2, button);
5648
5649   g_object_unref (hgroup1);
5650   g_object_unref (hgroup2);
5651   g_object_unref (vgroup1);
5652   g_object_unref (vgroup2);
5653   
5654   hbox = gtk_hbox_new (FALSE, 5);
5655   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), hbox, FALSE, FALSE, 0);
5656   
5657   spin_button = gtk_spin_button_new_with_range (1, 100, 1);
5658   gtk_spin_button_set_value (GTK_SPIN_BUTTON (spin_button), SIZE_GROUP_INITIAL_SIZE);
5659   gtk_box_pack_start (GTK_BOX (hbox), spin_button, TRUE, TRUE, 0);
5660   g_signal_connect (spin_button, "value_changed",
5661                     G_CALLBACK (size_group_hsize_changed), main_button);
5662
5663   spin_button = gtk_spin_button_new_with_range (1, 100, 1);
5664   gtk_spin_button_set_value (GTK_SPIN_BUTTON (spin_button), SIZE_GROUP_INITIAL_SIZE);
5665   gtk_box_pack_start (GTK_BOX (hbox), spin_button, TRUE, TRUE, 0);
5666   g_signal_connect (spin_button, "value_changed",
5667                     G_CALLBACK (size_group_vsize_changed), main_button);
5668
5669   return window;
5670 }
5671
5672 static void
5673 create_size_groups (GtkWidget *widget)
5674 {
5675   static GtkWidget *window1 = NULL;
5676   static GtkWidget *window2 = NULL;
5677   static GtkSizeGroup *master_size_group;
5678
5679   if (!master_size_group)
5680     master_size_group = gtk_size_group_new (GTK_SIZE_GROUP_BOTH);
5681
5682   if (!window1)
5683     {
5684       window1 = create_size_group_window (gtk_widget_get_screen (widget),
5685                                           master_size_group);
5686
5687       g_signal_connect (window1, "destroy",
5688                         G_CALLBACK (gtk_widget_destroyed),
5689                         &window1);
5690     }
5691
5692   if (!window2)
5693     {
5694       window2 = create_size_group_window (gtk_widget_get_screen (widget),
5695                                           master_size_group);
5696
5697       g_signal_connect (window2, "destroy",
5698                         G_CALLBACK (gtk_widget_destroyed),
5699                         &window2);
5700     }
5701
5702   if (GTK_WIDGET_VISIBLE (window1) && GTK_WIDGET_VISIBLE (window2))
5703     {
5704       gtk_widget_destroy (window1);
5705       gtk_widget_destroy (window2);
5706     }
5707   else
5708     {
5709       if (!GTK_WIDGET_VISIBLE (window1))
5710         gtk_widget_show_all (window1);
5711       if (!GTK_WIDGET_VISIBLE (window2))
5712         gtk_widget_show_all (window2);
5713     }
5714 }
5715
5716 /*
5717  * GtkSpinButton
5718  */
5719
5720 static GtkWidget *spinner1;
5721
5722 static void
5723 toggle_snap (GtkWidget *widget, GtkSpinButton *spin)
5724 {
5725   gtk_spin_button_set_snap_to_ticks (spin, GTK_TOGGLE_BUTTON (widget)->active);
5726 }
5727
5728 static void
5729 toggle_numeric (GtkWidget *widget, GtkSpinButton *spin)
5730 {
5731   gtk_spin_button_set_numeric (spin, GTK_TOGGLE_BUTTON (widget)->active);
5732 }
5733
5734 static void
5735 change_digits (GtkWidget *widget, GtkSpinButton *spin)
5736 {
5737   gtk_spin_button_set_digits (GTK_SPIN_BUTTON (spinner1),
5738                               gtk_spin_button_get_value_as_int (spin));
5739 }
5740
5741 static void
5742 get_value (GtkWidget *widget, gpointer data)
5743 {
5744   gchar buf[32];
5745   GtkLabel *label;
5746   GtkSpinButton *spin;
5747
5748   spin = GTK_SPIN_BUTTON (spinner1);
5749   label = GTK_LABEL (g_object_get_data (G_OBJECT (widget), "user_data"));
5750   if (GPOINTER_TO_INT (data) == 1)
5751     sprintf (buf, "%d", gtk_spin_button_get_value_as_int (spin));
5752   else
5753     sprintf (buf, "%0.*f", spin->digits, gtk_spin_button_get_value (spin));
5754   gtk_label_set_text (label, buf);
5755 }
5756
5757 static void
5758 get_spin_value (GtkWidget *widget, gpointer data)
5759 {
5760   gchar *buffer;
5761   GtkLabel *label;
5762   GtkSpinButton *spin;
5763
5764   spin = GTK_SPIN_BUTTON (widget);
5765   label = GTK_LABEL (data);
5766
5767   buffer = g_strdup_printf ("%0.*f", spin->digits,
5768                             gtk_spin_button_get_value (spin));
5769   gtk_label_set_text (label, buffer);
5770
5771   g_free (buffer);
5772 }
5773
5774 static gint
5775 spin_button_time_output_func (GtkSpinButton *spin_button)
5776 {
5777   static gchar buf[6];
5778   gdouble hours;
5779   gdouble minutes;
5780
5781   hours = spin_button->adjustment->value / 60.0;
5782   minutes = (fabs(floor (hours) - hours) < 1e-5) ? 0.0 : 30;
5783   sprintf (buf, "%02.0f:%02.0f", floor (hours), minutes);
5784   if (strcmp (buf, gtk_entry_get_text (GTK_ENTRY (spin_button))))
5785     gtk_entry_set_text (GTK_ENTRY (spin_button), buf);
5786   return TRUE;
5787 }
5788
5789 static gint
5790 spin_button_month_input_func (GtkSpinButton *spin_button,
5791                               gdouble       *new_val)
5792 {
5793   gint i;
5794   static gchar *month[12] = { "January", "February", "March", "April",
5795                               "May", "June", "July", "August",
5796                               "September", "October", "November", "December" };
5797   gchar *tmp1, *tmp2;
5798   gboolean found = FALSE;
5799
5800   for (i = 1; i <= 12; i++)
5801     {
5802       tmp1 = g_ascii_strup (month[i - 1], -1);
5803       tmp2 = g_ascii_strup (gtk_entry_get_text (GTK_ENTRY (spin_button)), -1);
5804       if (strstr (tmp1, tmp2) == tmp1)
5805         found = TRUE;
5806       g_free (tmp1);
5807       g_free (tmp2);
5808       if (found)
5809         break;
5810     }
5811   if (!found)
5812     {
5813       *new_val = 0.0;
5814       return GTK_INPUT_ERROR;
5815     }
5816   *new_val = (gdouble) i;
5817   return TRUE;
5818 }
5819
5820 static gint
5821 spin_button_month_output_func (GtkSpinButton *spin_button)
5822 {
5823   gint i;
5824   static gchar *month[12] = { "January", "February", "March", "April",
5825                               "May", "June", "July", "August", "September",
5826                               "October", "November", "December" };
5827
5828   for (i = 1; i <= 12; i++)
5829     if (fabs (spin_button->adjustment->value - (double)i) < 1e-5)
5830       {
5831         if (strcmp (month[i-1], gtk_entry_get_text (GTK_ENTRY (spin_button))))
5832           gtk_entry_set_text (GTK_ENTRY (spin_button), month[i-1]);
5833       }
5834   return TRUE;
5835 }
5836
5837 static gint
5838 spin_button_hex_input_func (GtkSpinButton *spin_button,
5839                             gdouble       *new_val)
5840 {
5841   const gchar *buf;
5842   gchar *err;
5843   gdouble res;
5844
5845   buf = gtk_entry_get_text (GTK_ENTRY (spin_button));
5846   res = strtol(buf, &err, 16);
5847   *new_val = res;
5848   if (*err)
5849     return GTK_INPUT_ERROR;
5850   else
5851     return TRUE;
5852 }
5853
5854 static gint
5855 spin_button_hex_output_func (GtkSpinButton *spin_button)
5856 {
5857   static gchar buf[7];
5858   gint val;
5859
5860   val = (gint) spin_button->adjustment->value;
5861   if (fabs (val) < 1e-5)
5862     sprintf (buf, "0x00");
5863   else
5864     sprintf (buf, "0x%.2X", val);
5865   if (strcmp (buf, gtk_entry_get_text (GTK_ENTRY (spin_button))))
5866     gtk_entry_set_text (GTK_ENTRY (spin_button), buf);
5867   return TRUE;
5868 }
5869
5870 static void
5871 create_spins (GtkWidget *widget)
5872 {
5873   static GtkWidget *window = NULL;
5874   GtkWidget *frame;
5875   GtkWidget *hbox;
5876   GtkWidget *main_vbox;
5877   GtkWidget *vbox;
5878   GtkWidget *vbox2;
5879   GtkWidget *spinner2;
5880   GtkWidget *spinner;
5881   GtkWidget *button;
5882   GtkWidget *label;
5883   GtkWidget *val_label;
5884   GtkAdjustment *adj;
5885
5886   if (!window)
5887     {
5888       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
5889       gtk_window_set_screen (GTK_WINDOW (window),
5890                              gtk_widget_get_screen (widget));
5891       
5892       g_signal_connect (window, "destroy",
5893                         G_CALLBACK (gtk_widget_destroyed),
5894                         &window);
5895       
5896       gtk_window_set_title (GTK_WINDOW (window), "GtkSpinButton");
5897       
5898       main_vbox = gtk_vbox_new (FALSE, 5);
5899       gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 10);
5900       gtk_container_add (GTK_CONTAINER (window), main_vbox);
5901       
5902       frame = gtk_frame_new ("Not accelerated");
5903       gtk_box_pack_start (GTK_BOX (main_vbox), frame, TRUE, TRUE, 0);
5904       
5905       vbox = gtk_vbox_new (FALSE, 0);
5906       gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
5907       gtk_container_add (GTK_CONTAINER (frame), vbox);
5908       
5909       /* Time, month, hex spinners */
5910       
5911       hbox = gtk_hbox_new (FALSE, 0);
5912       gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 5);
5913       
5914       vbox2 = gtk_vbox_new (FALSE, 0);
5915       gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 5);
5916       
5917       label = gtk_label_new ("Time :");
5918       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
5919       gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
5920       
5921       adj = (GtkAdjustment *) gtk_adjustment_new (0, 0, 1410, 30, 60, 0);
5922       spinner = gtk_spin_button_new (adj, 0, 0);
5923       gtk_editable_set_editable (GTK_EDITABLE (spinner), FALSE);
5924       g_signal_connect (spinner,
5925                         "output",
5926                         G_CALLBACK (spin_button_time_output_func),
5927                         NULL);
5928       gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner), TRUE);
5929       gtk_entry_set_width_chars (GTK_ENTRY (spinner), 5);
5930       gtk_box_pack_start (GTK_BOX (vbox2), spinner, FALSE, TRUE, 0);
5931
5932       vbox2 = gtk_vbox_new (FALSE, 0);
5933       gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 5);
5934       
5935       label = gtk_label_new ("Month :");
5936       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
5937       gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
5938       
5939       adj = (GtkAdjustment *) gtk_adjustment_new (1.0, 1.0, 12.0, 1.0,
5940                                                   5.0, 0.0);
5941       spinner = gtk_spin_button_new (adj, 0, 0);
5942       gtk_spin_button_set_update_policy (GTK_SPIN_BUTTON (spinner),
5943                                          GTK_UPDATE_IF_VALID);
5944       g_signal_connect (spinner,
5945                         "input",
5946                         G_CALLBACK (spin_button_month_input_func),
5947                         NULL);
5948       g_signal_connect (spinner,
5949                         "output",
5950                         G_CALLBACK (spin_button_month_output_func),
5951                         NULL);
5952       gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner), TRUE);
5953       gtk_entry_set_width_chars (GTK_ENTRY (spinner), 9);
5954       gtk_box_pack_start (GTK_BOX (vbox2), spinner, FALSE, TRUE, 0);
5955       
5956       vbox2 = gtk_vbox_new (FALSE, 0);
5957       gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 5);
5958
5959       label = gtk_label_new ("Hex :");
5960       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
5961       gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
5962
5963       adj = (GtkAdjustment *) gtk_adjustment_new (0, 0, 255, 1, 16, 0);
5964       spinner = gtk_spin_button_new (adj, 0, 0);
5965       gtk_editable_set_editable (GTK_EDITABLE (spinner), TRUE);
5966       g_signal_connect (spinner,
5967                         "input",
5968                         G_CALLBACK (spin_button_hex_input_func),
5969                         NULL);
5970       g_signal_connect (spinner,
5971                         "output",
5972                         G_CALLBACK (spin_button_hex_output_func),
5973                         NULL);
5974       gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner), TRUE);
5975       gtk_entry_set_width_chars (GTK_ENTRY (spinner), 4);
5976       gtk_box_pack_start (GTK_BOX (vbox2), spinner, FALSE, TRUE, 0);
5977
5978       frame = gtk_frame_new ("Accelerated");
5979       gtk_box_pack_start (GTK_BOX (main_vbox), frame, TRUE, TRUE, 0);
5980   
5981       vbox = gtk_vbox_new (FALSE, 0);
5982       gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
5983       gtk_container_add (GTK_CONTAINER (frame), vbox);
5984       
5985       hbox = gtk_hbox_new (FALSE, 0);
5986       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 5);
5987       
5988       vbox2 = gtk_vbox_new (FALSE, 0);
5989       gtk_box_pack_start (GTK_BOX (hbox), vbox2, FALSE, FALSE, 5);
5990       
5991       label = gtk_label_new ("Value :");
5992       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
5993       gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
5994
5995       adj = (GtkAdjustment *) gtk_adjustment_new (0.0, -10000.0, 10000.0,
5996                                                   0.5, 100.0, 0.0);
5997       spinner1 = gtk_spin_button_new (adj, 1.0, 2);
5998       gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner1), TRUE);
5999       gtk_box_pack_start (GTK_BOX (vbox2), spinner1, FALSE, TRUE, 0);
6000
6001       vbox2 = gtk_vbox_new (FALSE, 0);
6002       gtk_box_pack_start (GTK_BOX (hbox), vbox2, FALSE, FALSE, 5);
6003
6004       label = gtk_label_new ("Digits :");
6005       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
6006       gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
6007
6008       adj = (GtkAdjustment *) gtk_adjustment_new (2, 1, 15, 1, 1, 0);
6009       spinner2 = gtk_spin_button_new (adj, 0.0, 0);
6010       g_signal_connect (adj, "value_changed",
6011                         G_CALLBACK (change_digits),
6012                         spinner2);
6013       gtk_box_pack_start (GTK_BOX (vbox2), spinner2, FALSE, TRUE, 0);
6014
6015       hbox = gtk_hbox_new (FALSE, 0);
6016       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 5);
6017
6018       button = gtk_check_button_new_with_label ("Snap to 0.5-ticks");
6019       g_signal_connect (button, "clicked",
6020                         G_CALLBACK (toggle_snap),
6021                         spinner1);
6022       gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
6023       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
6024
6025       button = gtk_check_button_new_with_label ("Numeric only input mode");
6026       g_signal_connect (button, "clicked",
6027                         G_CALLBACK (toggle_numeric),
6028                         spinner1);
6029       gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
6030       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
6031
6032       val_label = gtk_label_new ("");
6033
6034       hbox = gtk_hbox_new (FALSE, 0);
6035       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 5);
6036
6037       button = gtk_button_new_with_label ("Value as Int");
6038       g_object_set_data (G_OBJECT (button), "user_data", val_label);
6039       g_signal_connect (button, "clicked",
6040                         G_CALLBACK (get_value),
6041                         GINT_TO_POINTER (1));
6042       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
6043
6044       button = gtk_button_new_with_label ("Value as Float");
6045       g_object_set_data (G_OBJECT (button), "user_data", val_label);
6046       g_signal_connect (button, "clicked",
6047                         G_CALLBACK (get_value),
6048                         GINT_TO_POINTER (2));
6049       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
6050
6051       gtk_box_pack_start (GTK_BOX (vbox), val_label, TRUE, TRUE, 0);
6052       gtk_label_set_text (GTK_LABEL (val_label), "0");
6053
6054       frame = gtk_frame_new ("Using Convenience Constructor");
6055       gtk_box_pack_start (GTK_BOX (main_vbox), frame, TRUE, TRUE, 0);
6056   
6057       hbox = gtk_hbox_new (FALSE, 0);
6058       gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
6059       gtk_container_add (GTK_CONTAINER (frame), hbox);
6060       
6061       val_label = gtk_label_new ("0.0");
6062
6063       spinner = gtk_spin_button_new_with_range (0.0, 10.0, 0.009);
6064       gtk_spin_button_set_value (GTK_SPIN_BUTTON (spinner), 0.0);
6065       g_signal_connect (spinner, "value_changed",
6066                         G_CALLBACK (get_spin_value), val_label);
6067       gtk_box_pack_start (GTK_BOX (hbox), spinner, TRUE, TRUE, 5);
6068       gtk_box_pack_start (GTK_BOX (hbox), val_label, TRUE, TRUE, 5);
6069
6070       hbox = gtk_hbox_new (FALSE, 0);
6071       gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, TRUE, 0);
6072   
6073       button = gtk_button_new_with_label ("Close");
6074       g_signal_connect_swapped (button, "clicked",
6075                                 G_CALLBACK (gtk_widget_destroy),
6076                                 window);
6077       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
6078     }
6079
6080   if (!GTK_WIDGET_VISIBLE (window))
6081     gtk_widget_show_all (window);
6082   else
6083     gtk_widget_destroy (window);
6084 }
6085
6086
6087 /*
6088  * Cursors
6089  */
6090
6091 static gint
6092 cursor_expose_event (GtkWidget *widget,
6093                      GdkEvent  *event,
6094                      gpointer   user_data)
6095 {
6096   GtkDrawingArea *darea;
6097   GdkDrawable *drawable;
6098   GdkGC *black_gc;
6099   GdkGC *gray_gc;
6100   GdkGC *white_gc;
6101   guint max_width;
6102   guint max_height;
6103
6104   g_return_val_if_fail (widget != NULL, TRUE);
6105   g_return_val_if_fail (GTK_IS_DRAWING_AREA (widget), TRUE);
6106
6107   darea = GTK_DRAWING_AREA (widget);
6108   drawable = widget->window;
6109   white_gc = widget->style->white_gc;
6110   gray_gc = widget->style->bg_gc[GTK_STATE_NORMAL];
6111   black_gc = widget->style->black_gc;
6112   max_width = widget->allocation.width;
6113   max_height = widget->allocation.height;
6114
6115   gdk_draw_rectangle (drawable, white_gc,
6116                       TRUE,
6117                       0,
6118                       0,
6119                       max_width,
6120                       max_height / 2);
6121
6122   gdk_draw_rectangle (drawable, black_gc,
6123                       TRUE,
6124                       0,
6125                       max_height / 2,
6126                       max_width,
6127                       max_height / 2);
6128
6129   gdk_draw_rectangle (drawable, gray_gc,
6130                       TRUE,
6131                       max_width / 3,
6132                       max_height / 3,
6133                       max_width / 3,
6134                       max_height / 3);
6135
6136   return TRUE;
6137 }
6138
6139 static void
6140 set_cursor (GtkWidget *spinner,
6141             GtkWidget *widget)
6142 {
6143   guint c;
6144   GdkCursor *cursor;
6145   GtkWidget *label;
6146   GEnumClass *class;
6147   GEnumValue *vals;
6148
6149   c = CLAMP (gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (spinner)), 0, 152);
6150   c &= 0xfe;
6151
6152   label = g_object_get_data (G_OBJECT (spinner), "user_data");
6153   
6154   class = g_type_class_ref (GDK_TYPE_CURSOR_TYPE);
6155   vals = class->values;
6156
6157   while (vals && vals->value != c)
6158     vals++;
6159   if (vals)
6160     gtk_label_set_text (GTK_LABEL (label), vals->value_nick);
6161   else
6162     gtk_label_set_text (GTK_LABEL (label), "<unknown>");
6163
6164   g_type_class_unref (class);
6165
6166   cursor = gdk_cursor_new_for_display (gtk_widget_get_display (widget), c);
6167   gdk_window_set_cursor (widget->window, cursor);
6168   gdk_cursor_unref (cursor);
6169 }
6170
6171 static gint
6172 cursor_event (GtkWidget          *widget,
6173               GdkEvent           *event,
6174               GtkSpinButton      *spinner)
6175 {
6176   if ((event->type == GDK_BUTTON_PRESS) &&
6177       ((event->button.button == 1) ||
6178        (event->button.button == 3)))
6179     {
6180       gtk_spin_button_spin (spinner, event->button.button == 1 ?
6181                             GTK_SPIN_STEP_FORWARD : GTK_SPIN_STEP_BACKWARD, 0);
6182       return TRUE;
6183     }
6184
6185   return FALSE;
6186 }
6187
6188 #ifdef GDK_WINDOWING_X11
6189 #include "x11/gdkx.h"
6190
6191 static void
6192 change_cursor_theme (GtkWidget *widget,
6193                      gpointer   data)
6194 {
6195   const gchar *theme;
6196   gint size;
6197   GList *children;
6198
6199   children = gtk_container_get_children (GTK_CONTAINER (data));
6200
6201   theme = gtk_entry_get_text (GTK_ENTRY (children->next->data));
6202   size = (gint) gtk_spin_button_get_value (GTK_SPIN_BUTTON (children->next->next->data));
6203
6204   g_list_free (children);
6205
6206   gdk_x11_display_set_cursor_theme (gtk_widget_get_display (widget),
6207                                     theme, size);
6208 }
6209 #endif
6210
6211
6212 static void
6213 create_cursors (GtkWidget *widget)
6214 {
6215   static GtkWidget *window = NULL;
6216   GtkWidget *frame;
6217   GtkWidget *hbox;
6218   GtkWidget *main_vbox;
6219   GtkWidget *vbox;
6220   GtkWidget *darea;
6221   GtkWidget *spinner;
6222   GtkWidget *button;
6223   GtkWidget *label;
6224   GtkWidget *any;
6225   GtkAdjustment *adj;
6226   GtkWidget *entry;
6227   GtkWidget *size;  
6228
6229   if (!window)
6230     {
6231       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6232       gtk_window_set_screen (GTK_WINDOW (window), 
6233                              gtk_widget_get_screen (widget));
6234       
6235       g_signal_connect (window, "destroy",
6236                         G_CALLBACK (gtk_widget_destroyed),
6237                         &window);
6238       
6239       gtk_window_set_title (GTK_WINDOW (window), "Cursors");
6240       
6241       main_vbox = gtk_vbox_new (FALSE, 5);
6242       gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 0);
6243       gtk_container_add (GTK_CONTAINER (window), main_vbox);
6244
6245       vbox =
6246         g_object_new (gtk_vbox_get_type (),
6247                         "GtkBox::homogeneous", FALSE,
6248                         "GtkBox::spacing", 5,
6249                         "GtkContainer::border_width", 10,
6250                         "GtkWidget::parent", main_vbox,
6251                         "GtkWidget::visible", TRUE,
6252                         NULL);
6253
6254 #ifdef GDK_WINDOWING_X11
6255       hbox = gtk_hbox_new (FALSE, 0);
6256       gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
6257       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
6258
6259       label = gtk_label_new ("Cursor Theme : ");
6260       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
6261       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
6262
6263       entry = gtk_entry_new ();
6264       gtk_entry_set_text (GTK_ENTRY (entry), "default");
6265       gtk_box_pack_start (GTK_BOX (hbox), entry, FALSE, TRUE, 0);
6266
6267       size = gtk_spin_button_new_with_range (1.0, 64.0, 1.0);
6268       gtk_spin_button_set_value (GTK_SPIN_BUTTON (size), 24.0);
6269       gtk_box_pack_start (GTK_BOX (hbox), size, TRUE, TRUE, 0);
6270       
6271       g_signal_connect (entry, "changed", 
6272                         G_CALLBACK (change_cursor_theme), hbox);
6273       g_signal_connect (size, "changed", 
6274                         G_CALLBACK (change_cursor_theme), hbox);
6275 #endif
6276
6277       hbox = gtk_hbox_new (FALSE, 0);
6278       gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
6279       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
6280
6281       label = gtk_label_new ("Cursor Value : ");
6282       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
6283       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
6284       
6285       adj = (GtkAdjustment *) gtk_adjustment_new (0,
6286                                                   0, 152,
6287                                                   2,
6288                                                   10, 0);
6289       spinner = gtk_spin_button_new (adj, 0, 0);
6290       gtk_box_pack_start (GTK_BOX (hbox), spinner, TRUE, TRUE, 0);
6291
6292       frame =
6293         g_object_new (gtk_frame_get_type (),
6294                         "GtkFrame::shadow", GTK_SHADOW_ETCHED_IN,
6295                         "GtkFrame::label_xalign", 0.5,
6296                         "GtkFrame::label", "Cursor Area",
6297                         "GtkContainer::border_width", 10,
6298                         "GtkWidget::parent", vbox,
6299                         "GtkWidget::visible", TRUE,
6300                         NULL);
6301
6302       darea = gtk_drawing_area_new ();
6303       gtk_widget_set_size_request (darea, 80, 80);
6304       gtk_container_add (GTK_CONTAINER (frame), darea);
6305       g_signal_connect (darea,
6306                         "expose_event",
6307                         G_CALLBACK (cursor_expose_event),
6308                         NULL);
6309       gtk_widget_set_events (darea, GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK);
6310       g_signal_connect (darea,
6311                         "button_press_event",
6312                         G_CALLBACK (cursor_event),
6313                         spinner);
6314       gtk_widget_show (darea);
6315
6316       g_signal_connect (spinner, "changed",
6317                         G_CALLBACK (set_cursor),
6318                         darea);
6319
6320       label = g_object_new (GTK_TYPE_LABEL,
6321                               "visible", TRUE,
6322                               "label", "XXX",
6323                               "parent", vbox,
6324                               NULL);
6325       gtk_container_child_set (GTK_CONTAINER (vbox), label,
6326                                "expand", FALSE,
6327                                NULL);
6328       g_object_set_data (G_OBJECT (spinner), "user_data", label);
6329
6330       any =
6331         g_object_new (gtk_hseparator_get_type (),
6332                         "GtkWidget::visible", TRUE,
6333                         NULL);
6334       gtk_box_pack_start (GTK_BOX (main_vbox), any, FALSE, TRUE, 0);
6335   
6336       hbox = gtk_hbox_new (FALSE, 0);
6337       gtk_container_set_border_width (GTK_CONTAINER (hbox), 10);
6338       gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, TRUE, 0);
6339
6340       button = gtk_button_new_with_label ("Close");
6341       g_signal_connect_swapped (button, "clicked",
6342                                 G_CALLBACK (gtk_widget_destroy),
6343                                 window);
6344       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
6345
6346       gtk_widget_show_all (window);
6347
6348       set_cursor (spinner, darea);
6349     }
6350   else
6351     gtk_widget_destroy (window);
6352 }
6353
6354 /*
6355  * GtkList
6356  */
6357
6358 static void
6359 list_add (GtkWidget *widget,
6360           GtkWidget *list)
6361 {
6362   static int i = 1;
6363   gchar buffer[64];
6364   GtkWidget *list_item;
6365   GtkContainer *container;
6366
6367   container = GTK_CONTAINER (list);
6368
6369   sprintf (buffer, "added item %d", i++);
6370   list_item = gtk_list_item_new_with_label (buffer);
6371   gtk_widget_show (list_item);
6372
6373   gtk_container_add (container, list_item);
6374 }
6375
6376 static void
6377 list_remove (GtkWidget *widget,
6378              GtkList   *list)
6379 {
6380   GList *clear_list = NULL;
6381   GList *sel_row = NULL;
6382   GList *work = NULL;
6383
6384   if (list->selection_mode == GTK_SELECTION_EXTENDED)
6385     {
6386       GtkWidget *item;
6387
6388       item = GTK_CONTAINER (list)->focus_child;
6389       if (!item && list->selection)
6390         item = list->selection->data;
6391
6392       if (item)
6393         {
6394           work = g_list_find (list->children, item);
6395           for (sel_row = work; sel_row; sel_row = sel_row->next)
6396             if (GTK_WIDGET (sel_row->data)->state != GTK_STATE_SELECTED)
6397               break;
6398
6399           if (!sel_row)
6400             {
6401               for (sel_row = work; sel_row; sel_row = sel_row->prev)
6402                 if (GTK_WIDGET (sel_row->data)->state != GTK_STATE_SELECTED)
6403                   break;
6404             }
6405         }
6406     }
6407
6408   for (work = list->selection; work; work = work->next)
6409     clear_list = g_list_prepend (clear_list, work->data);
6410
6411   clear_list = g_list_reverse (clear_list);
6412   gtk_list_remove_items (GTK_LIST (list), clear_list);
6413   g_list_free (clear_list);
6414
6415   if (list->selection_mode == GTK_SELECTION_EXTENDED && sel_row)
6416     gtk_list_select_child (list, GTK_WIDGET(sel_row->data));
6417 }
6418
6419 static void
6420 list_clear (GtkWidget *widget,
6421             GtkWidget *list)
6422 {
6423   gtk_list_clear_items (GTK_LIST (list), 0, -1);
6424 }
6425
6426 static gchar *selection_mode_items[] =
6427 {
6428   "Single",
6429   "Browse",
6430   "Multiple"
6431 };
6432
6433 static const GtkSelectionMode selection_modes[] = {
6434   GTK_SELECTION_SINGLE,
6435   GTK_SELECTION_BROWSE,
6436   GTK_SELECTION_MULTIPLE
6437 };
6438
6439 static GtkWidget *list_omenu;
6440
6441 static void 
6442 list_toggle_sel_mode (GtkWidget *widget, gpointer data)
6443 {
6444   GtkList *list;
6445   gint i;
6446
6447   list = GTK_LIST (data);
6448
6449   if (!GTK_WIDGET_MAPPED (widget))
6450     return;
6451
6452   i = gtk_option_menu_get_history (GTK_OPTION_MENU (widget));
6453
6454   gtk_list_set_selection_mode (list, selection_modes[i]);
6455 }
6456
6457 static void
6458 create_list (GtkWidget *widget)
6459 {
6460   static GtkWidget *window = NULL;
6461
6462   if (!window)
6463     {
6464       GtkWidget *cbox;
6465       GtkWidget *vbox;
6466       GtkWidget *hbox;
6467       GtkWidget *label;
6468       GtkWidget *scrolled_win;
6469       GtkWidget *list;
6470       GtkWidget *button;
6471       GtkWidget *separator;
6472       FILE *infile;
6473
6474       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6475
6476       gtk_window_set_screen (GTK_WINDOW (window),
6477                              gtk_widget_get_screen (widget));
6478
6479       g_signal_connect (window, "destroy",
6480                         G_CALLBACK (gtk_widget_destroyed),
6481                         &window);
6482
6483       gtk_window_set_title (GTK_WINDOW (window), "list");
6484       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
6485
6486       vbox = gtk_vbox_new (FALSE, 0);
6487       gtk_container_add (GTK_CONTAINER (window), vbox);
6488
6489       scrolled_win = gtk_scrolled_window_new (NULL, NULL);
6490       gtk_container_set_border_width (GTK_CONTAINER (scrolled_win), 5);
6491       gtk_widget_set_size_request (scrolled_win, -1, 300);
6492       gtk_box_pack_start (GTK_BOX (vbox), scrolled_win, TRUE, TRUE, 0);
6493       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
6494                                       GTK_POLICY_AUTOMATIC,
6495                                       GTK_POLICY_AUTOMATIC);
6496
6497       list = gtk_list_new ();
6498       gtk_list_set_selection_mode (GTK_LIST (list), GTK_SELECTION_SINGLE);
6499       gtk_scrolled_window_add_with_viewport
6500         (GTK_SCROLLED_WINDOW (scrolled_win), list);
6501       gtk_container_set_focus_vadjustment
6502         (GTK_CONTAINER (list),
6503          gtk_scrolled_window_get_vadjustment
6504          (GTK_SCROLLED_WINDOW (scrolled_win)));
6505       gtk_container_set_focus_hadjustment
6506         (GTK_CONTAINER (list),
6507          gtk_scrolled_window_get_hadjustment
6508          (GTK_SCROLLED_WINDOW (scrolled_win)));
6509
6510       if ((infile = fopen("../gtk/gtkenums.h", "r")))
6511         {
6512           char buffer[256];
6513           char *pos;
6514           GtkWidget *item;
6515
6516           while (fgets (buffer, 256, infile))
6517             {
6518               if ((pos = strchr (buffer, '\n')))
6519                 *pos = 0;
6520               item = gtk_list_item_new_with_label (buffer);
6521               gtk_container_add (GTK_CONTAINER (list), item);
6522             }
6523           
6524           fclose (infile);
6525         }
6526
6527
6528       hbox = gtk_hbox_new (TRUE, 5);
6529       gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
6530       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
6531
6532       button = gtk_button_new_with_label ("Insert Row");
6533       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
6534       g_signal_connect (button, "clicked",
6535                         G_CALLBACK (list_add),
6536                         list);
6537
6538       button = gtk_button_new_with_label ("Clear List");
6539       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
6540       g_signal_connect (button, "clicked",
6541                         G_CALLBACK (list_clear),
6542                         list);
6543
6544       button = gtk_button_new_with_label ("Remove Selection");
6545       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
6546       g_signal_connect (button, "clicked",
6547                         G_CALLBACK (list_remove),
6548                         list);
6549
6550       cbox = gtk_hbox_new (FALSE, 0);
6551       gtk_box_pack_start (GTK_BOX (vbox), cbox, FALSE, TRUE, 0);
6552
6553       hbox = gtk_hbox_new (FALSE, 5);
6554       gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
6555       gtk_box_pack_start (GTK_BOX (cbox), hbox, TRUE, FALSE, 0);
6556
6557       label = gtk_label_new ("Selection Mode :");
6558       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
6559
6560       list_omenu = build_option_menu (selection_mode_items, 3, 3, 
6561                                       list_toggle_sel_mode,
6562                                       list);
6563       gtk_box_pack_start (GTK_BOX (hbox), list_omenu, FALSE, TRUE, 0);
6564
6565       separator = gtk_hseparator_new ();
6566       gtk_box_pack_start (GTK_BOX (vbox), separator, FALSE, TRUE, 0);
6567
6568       cbox = gtk_hbox_new (FALSE, 0);
6569       gtk_box_pack_start (GTK_BOX (vbox), cbox, FALSE, TRUE, 0);
6570
6571       button = gtk_button_new_with_label ("close");
6572       gtk_container_set_border_width (GTK_CONTAINER (button), 10);
6573       gtk_box_pack_start (GTK_BOX (cbox), button, TRUE, TRUE, 0);
6574       g_signal_connect_swapped (button, "clicked",
6575                                 G_CALLBACK (gtk_widget_destroy),
6576                                 window);
6577
6578       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
6579       gtk_widget_grab_default (button);
6580     }
6581
6582   if (!GTK_WIDGET_VISIBLE (window))
6583     gtk_widget_show_all (window);
6584   else
6585     gtk_widget_destroy (window);
6586 }
6587
6588 /*
6589  * GtkCList
6590  */
6591
6592 static char * book_open_xpm[] = {
6593 "16 16 4 1",
6594 "       c None s None",
6595 ".      c black",
6596 "X      c #808080",
6597 "o      c white",
6598 "                ",
6599 "  ..            ",
6600 " .Xo.    ...    ",
6601 " .Xoo. ..oo.    ",
6602 " .Xooo.Xooo...  ",
6603 " .Xooo.oooo.X.  ",
6604 " .Xooo.Xooo.X.  ",
6605 " .Xooo.oooo.X.  ",
6606 " .Xooo.Xooo.X.  ",
6607 " .Xooo.oooo.X.  ",
6608 "  .Xoo.Xoo..X.  ",
6609 "   .Xo.o..ooX.  ",
6610 "    .X..XXXXX.  ",
6611 "    ..X.......  ",
6612 "     ..         ",
6613 "                "};
6614
6615 static char * book_closed_xpm[] = {
6616 "16 16 6 1",
6617 "       c None s None",
6618 ".      c black",
6619 "X      c red",
6620 "o      c yellow",
6621 "O      c #808080",
6622 "#      c white",
6623 "                ",
6624 "       ..       ",
6625 "     ..XX.      ",
6626 "   ..XXXXX.     ",
6627 " ..XXXXXXXX.    ",
6628 ".ooXXXXXXXXX.   ",
6629 "..ooXXXXXXXXX.  ",
6630 ".X.ooXXXXXXXXX. ",
6631 ".XX.ooXXXXXX..  ",
6632 " .XX.ooXXX..#O  ",
6633 "  .XX.oo..##OO. ",
6634 "   .XX..##OO..  ",
6635 "    .X.#OO..    ",
6636 "     ..O..      ",
6637 "      ..        ",
6638 "                "};
6639
6640 static char * mini_page_xpm[] = {
6641 "16 16 4 1",
6642 "       c None s None",
6643 ".      c black",
6644 "X      c white",
6645 "o      c #808080",
6646 "                ",
6647 "   .......      ",
6648 "   .XXXXX..     ",
6649 "   .XoooX.X.    ",
6650 "   .XXXXX....   ",
6651 "   .XooooXoo.o  ",
6652 "   .XXXXXXXX.o  ",
6653 "   .XooooooX.o  ",
6654 "   .XXXXXXXX.o  ",
6655 "   .XooooooX.o  ",
6656 "   .XXXXXXXX.o  ",
6657 "   .XooooooX.o  ",
6658 "   .XXXXXXXX.o  ",
6659 "   ..........o  ",
6660 "    oooooooooo  ",
6661 "                "};
6662
6663 static char * gtk_mini_xpm[] = {
6664 "15 20 17 1",
6665 "       c None",
6666 ".      c #14121F",
6667 "+      c #278828",
6668 "@      c #9B3334",
6669 "#      c #284C72",
6670 "$      c #24692A",
6671 "%      c #69282E",
6672 "&      c #37C539",
6673 "*      c #1D2F4D",
6674 "=      c #6D7076",
6675 "-      c #7D8482",
6676 ";      c #E24A49",
6677 ">      c #515357",
6678 ",      c #9B9C9B",
6679 "'      c #2FA232",
6680 ")      c #3CE23D",
6681 "!      c #3B6CCB",
6682 "               ",
6683 "      ***>     ",
6684 "    >.*!!!*    ",
6685 "   ***....#*=  ",
6686 "  *!*.!!!**!!# ",
6687 " .!!#*!#*!!!!# ",
6688 " @%#!.##.*!!$& ",
6689 " @;%*!*.#!#')) ",
6690 " @;;@%!!*$&)'' ",
6691 " @%.%@%$'&)$+' ",
6692 " @;...@$'*'*)+ ",
6693 " @;%..@$+*.')$ ",
6694 " @;%%;;$+..$)# ",
6695 " @;%%;@$$$'.$# ",
6696 " %;@@;;$$+))&* ",
6697 "  %;;;@+$&)&*  ",
6698 "   %;;@'))+>   ",
6699 "    %;@'&#     ",
6700 "     >%$$      ",
6701 "      >=       "};
6702
6703 #define TESTGTK_CLIST_COLUMNS 12
6704 static gint clist_rows = 0;
6705 static GtkWidget *clist_omenu;
6706
6707 static void
6708 add1000_clist (GtkWidget *widget, gpointer data)
6709 {
6710   gint i, row;
6711   char text[TESTGTK_CLIST_COLUMNS][50];
6712   char *texts[TESTGTK_CLIST_COLUMNS];
6713   GdkBitmap *mask;
6714   GdkPixmap *pixmap;
6715   GtkCList  *clist;
6716
6717   clist = GTK_CLIST (data);
6718
6719   pixmap = gdk_pixmap_create_from_xpm_d (clist->clist_window,
6720                                          &mask, 
6721                                          &GTK_WIDGET (data)->style->white,
6722                                          gtk_mini_xpm);
6723
6724   for (i = 0; i < TESTGTK_CLIST_COLUMNS; i++)
6725     {
6726       texts[i] = text[i];
6727       sprintf (text[i], "Column %d", i);
6728     }
6729   
6730   texts[3] = NULL;
6731   sprintf (text[1], "Right");
6732   sprintf (text[2], "Center");
6733   
6734   gtk_clist_freeze (GTK_CLIST (data));
6735   for (i = 0; i < 1000; i++)
6736     {
6737       sprintf (text[0], "CListRow %d", rand() % 10000);
6738       row = gtk_clist_append (clist, texts);
6739       gtk_clist_set_pixtext (clist, row, 3, "gtk+", 5, pixmap, mask);
6740     }
6741
6742   gtk_clist_thaw (GTK_CLIST (data));
6743
6744   g_object_unref (pixmap);
6745   g_object_unref (mask);
6746 }
6747
6748 static void
6749 add10000_clist (GtkWidget *widget, gpointer data)
6750 {
6751   gint i;
6752   char text[TESTGTK_CLIST_COLUMNS][50];
6753   char *texts[TESTGTK_CLIST_COLUMNS];
6754
6755   for (i = 0; i < TESTGTK_CLIST_COLUMNS; i++)
6756     {
6757       texts[i] = text[i];
6758       sprintf (text[i], "Column %d", i);
6759     }
6760   
6761   sprintf (text[1], "Right");
6762   sprintf (text[2], "Center");
6763   
6764   gtk_clist_freeze (GTK_CLIST (data));
6765   for (i = 0; i < 10000; i++)
6766     {
6767       sprintf (text[0], "CListRow %d", rand() % 10000);
6768       gtk_clist_append (GTK_CLIST (data), texts);
6769     }
6770   gtk_clist_thaw (GTK_CLIST (data));
6771 }
6772
6773 void
6774 clear_clist (GtkWidget *widget, gpointer data)
6775 {
6776   gtk_clist_clear (GTK_CLIST (data));
6777   clist_rows = 0;
6778 }
6779
6780 void clist_remove_selection (GtkWidget *widget, GtkCList *clist)
6781 {
6782   gtk_clist_freeze (clist);
6783
6784   while (clist->selection)
6785     {
6786       gint row;
6787
6788       clist_rows--;
6789       row = GPOINTER_TO_INT (clist->selection->data);
6790
6791       gtk_clist_remove (clist, row);
6792
6793       if (clist->selection_mode == GTK_SELECTION_BROWSE)
6794         break;
6795     }
6796
6797   if (clist->selection_mode == GTK_SELECTION_EXTENDED && !clist->selection &&
6798       clist->focus_row >= 0)
6799     gtk_clist_select_row (clist, clist->focus_row, -1);
6800
6801   gtk_clist_thaw (clist);
6802 }
6803
6804 void toggle_title_buttons (GtkWidget *widget, GtkCList *clist)
6805 {
6806   if (GTK_TOGGLE_BUTTON (widget)->active)
6807     gtk_clist_column_titles_show (clist);
6808   else
6809     gtk_clist_column_titles_hide (clist);
6810 }
6811
6812 void toggle_reorderable (GtkWidget *widget, GtkCList *clist)
6813 {
6814   gtk_clist_set_reorderable (clist, GTK_TOGGLE_BUTTON (widget)->active);
6815 }
6816
6817 static void
6818 insert_row_clist (GtkWidget *widget, gpointer data)
6819 {
6820   static char *text[] =
6821   {
6822     "This", "is an", "inserted", "row.",
6823     "This", "is an", "inserted", "row.",
6824     "This", "is an", "inserted", "row."
6825   };
6826
6827   static GtkStyle *style1 = NULL;
6828   static GtkStyle *style2 = NULL;
6829   static GtkStyle *style3 = NULL;
6830   gint row;
6831   
6832   if (GTK_CLIST (data)->focus_row >= 0)
6833     row = gtk_clist_insert (GTK_CLIST (data), GTK_CLIST (data)->focus_row,
6834                             text);
6835   else
6836     row = gtk_clist_prepend (GTK_CLIST (data), text);
6837
6838   if (!style1)
6839     {
6840       GdkColor col1 = { 0, 0, 56000, 0};
6841       GdkColor col2 = { 0, 32000, 0, 56000};
6842
6843       style1 = gtk_style_copy (GTK_WIDGET (data)->style);
6844       style1->base[GTK_STATE_NORMAL] = col1;
6845       style1->base[GTK_STATE_SELECTED] = col2;
6846
6847       style2 = gtk_style_copy (GTK_WIDGET (data)->style);
6848       style2->fg[GTK_STATE_NORMAL] = col1;
6849       style2->fg[GTK_STATE_SELECTED] = col2;
6850
6851       style3 = gtk_style_copy (GTK_WIDGET (data)->style);
6852       style3->fg[GTK_STATE_NORMAL] = col1;
6853       style3->base[GTK_STATE_NORMAL] = col2;
6854       pango_font_description_free (style3->font_desc);
6855       style3->font_desc = pango_font_description_from_string ("courier 12");
6856     }
6857
6858   gtk_clist_set_cell_style (GTK_CLIST (data), row, 3, style1);
6859   gtk_clist_set_cell_style (GTK_CLIST (data), row, 4, style2);
6860   gtk_clist_set_cell_style (GTK_CLIST (data), row, 0, style3);
6861
6862   clist_rows++;
6863 }
6864
6865 static void
6866 clist_warning_test (GtkWidget *button,
6867                     GtkWidget *clist)
6868 {
6869   GtkWidget *child;
6870   static gboolean add_remove = FALSE;
6871
6872   add_remove = !add_remove;
6873
6874   child = gtk_label_new ("Test");
6875   g_object_ref (child);
6876   gtk_object_sink (GTK_OBJECT (child));
6877
6878   if (add_remove)
6879     gtk_container_add (GTK_CONTAINER (clist), child);
6880   else
6881     {
6882       child->parent = clist;
6883       gtk_container_remove (GTK_CONTAINER (clist), child);
6884       child->parent = NULL;
6885     }
6886
6887   gtk_widget_destroy (child);
6888   g_object_unref (child);
6889 }
6890
6891 static void
6892 undo_selection (GtkWidget *button, GtkCList *clist)
6893 {
6894   gtk_clist_undo_selection (clist);
6895 }
6896
6897 static void 
6898 clist_toggle_sel_mode (GtkWidget *widget, gpointer data)
6899 {
6900   GtkCList *clist;
6901   gint i;
6902
6903   clist = GTK_CLIST (data);
6904
6905   if (!GTK_WIDGET_MAPPED (widget))
6906     return;
6907
6908   i = gtk_option_menu_get_history (GTK_OPTION_MENU (widget));
6909
6910   gtk_clist_set_selection_mode (clist, selection_modes[i]);
6911 }
6912
6913 static void 
6914 clist_click_column (GtkCList *clist, gint column, gpointer data)
6915 {
6916   if (column == 4)
6917     gtk_clist_set_column_visibility (clist, column, FALSE);
6918   else if (column == clist->sort_column)
6919     {
6920       if (clist->sort_type == GTK_SORT_ASCENDING)
6921         clist->sort_type = GTK_SORT_DESCENDING;
6922       else
6923         clist->sort_type = GTK_SORT_ASCENDING;
6924     }
6925   else
6926     gtk_clist_set_sort_column (clist, column);
6927
6928   gtk_clist_sort (clist);
6929 }
6930
6931 static void
6932 create_clist (GtkWidget *widget)
6933 {
6934   gint i;
6935   static GtkWidget *window = NULL;
6936
6937   static char *titles[] =
6938   {
6939     "auto resize", "not resizeable", "max width 100", "min width 50",
6940     "hide column", "Title 5", "Title 6", "Title 7",
6941     "Title 8",  "Title 9",  "Title 10", "Title 11"
6942   };
6943
6944   char text[TESTGTK_CLIST_COLUMNS][50];
6945   char *texts[TESTGTK_CLIST_COLUMNS];
6946
6947   GtkWidget *vbox;
6948   GtkWidget *hbox;
6949   GtkWidget *clist;
6950   GtkWidget *button;
6951   GtkWidget *separator;
6952   GtkWidget *scrolled_win;
6953   GtkWidget *check;
6954
6955   GtkWidget *undo_button;
6956   GtkWidget *label;
6957
6958   GtkStyle *style;
6959   GdkColor red_col = { 0, 56000, 0, 0};
6960   GdkColor light_green_col = { 0, 0, 56000, 32000};
6961
6962   if (!window)
6963     {
6964       clist_rows = 0;
6965       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6966       gtk_window_set_screen (GTK_WINDOW (window), 
6967                              gtk_widget_get_screen (widget));
6968
6969       g_signal_connect (window, "destroy",
6970                         G_CALLBACK (gtk_widget_destroyed), &window);
6971
6972       gtk_window_set_title (GTK_WINDOW (window), "clist");
6973       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
6974
6975       vbox = gtk_vbox_new (FALSE, 0);
6976       gtk_container_add (GTK_CONTAINER (window), vbox);
6977
6978       scrolled_win = gtk_scrolled_window_new (NULL, NULL);
6979       gtk_container_set_border_width (GTK_CONTAINER (scrolled_win), 5);
6980       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
6981                                       GTK_POLICY_AUTOMATIC, 
6982                                       GTK_POLICY_AUTOMATIC);
6983
6984       /* create GtkCList here so we have a pointer to throw at the 
6985        * button callbacks -- more is done with it later */
6986       clist = gtk_clist_new_with_titles (TESTGTK_CLIST_COLUMNS, titles);
6987       gtk_container_add (GTK_CONTAINER (scrolled_win), clist);
6988       g_signal_connect (clist, "click_column",
6989                         G_CALLBACK (clist_click_column), NULL);
6990
6991       /* control buttons */
6992       hbox = gtk_hbox_new (FALSE, 5);
6993       gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
6994       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
6995
6996       button = gtk_button_new_with_label ("Insert Row");
6997       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
6998       g_signal_connect (button, "clicked",
6999                         G_CALLBACK (insert_row_clist), clist);
7000
7001       button = gtk_button_new_with_label ("Add 1,000 Rows With Pixmaps");
7002       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
7003       g_signal_connect (button, "clicked",
7004                         G_CALLBACK (add1000_clist), clist);
7005
7006       button = gtk_button_new_with_label ("Add 10,000 Rows");
7007       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
7008       g_signal_connect (button, "clicked",
7009                         G_CALLBACK (add10000_clist), clist);
7010
7011       /* second layer of buttons */
7012       hbox = gtk_hbox_new (FALSE, 5);
7013       gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
7014       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
7015
7016       button = gtk_button_new_with_label ("Clear List");
7017       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
7018       g_signal_connect (button, "clicked",
7019                         G_CALLBACK (clear_clist), clist);
7020
7021       button = gtk_button_new_with_label ("Remove Selection");
7022       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
7023       g_signal_connect (button, "clicked",
7024                         G_CALLBACK (clist_remove_selection), clist);
7025
7026       undo_button = gtk_button_new_with_label ("Undo Selection");
7027       gtk_box_pack_start (GTK_BOX (hbox), undo_button, TRUE, TRUE, 0);
7028       g_signal_connect (undo_button, "clicked",
7029                         G_CALLBACK (undo_selection), clist);
7030
7031       button = gtk_button_new_with_label ("Warning Test");
7032       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
7033       g_signal_connect (button, "clicked",
7034                         G_CALLBACK (clist_warning_test), clist);
7035
7036       /* third layer of buttons */
7037       hbox = gtk_hbox_new (FALSE, 5);
7038       gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
7039       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
7040
7041       check = gtk_check_button_new_with_label ("Show Title Buttons");
7042       gtk_box_pack_start (GTK_BOX (hbox), check, FALSE, TRUE, 0);
7043       g_signal_connect (check, "clicked",
7044                         G_CALLBACK (toggle_title_buttons), clist);
7045       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check), TRUE);
7046
7047       check = gtk_check_button_new_with_label ("Reorderable");
7048       gtk_box_pack_start (GTK_BOX (hbox), check, FALSE, TRUE, 0);
7049       g_signal_connect (check, "clicked",
7050                         G_CALLBACK (toggle_reorderable), clist);
7051       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check), TRUE);
7052
7053       label = gtk_label_new ("Selection Mode :");
7054       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
7055
7056       clist_omenu = build_option_menu (selection_mode_items, 3, 3, 
7057                                        clist_toggle_sel_mode,
7058                                        clist);
7059       gtk_box_pack_start (GTK_BOX (hbox), clist_omenu, FALSE, TRUE, 0);
7060
7061       /* 
7062        * the rest of the clist configuration
7063        */
7064
7065       gtk_box_pack_start (GTK_BOX (vbox), scrolled_win, TRUE, TRUE, 0);
7066       gtk_clist_set_row_height (GTK_CLIST (clist), 18);
7067       gtk_widget_set_size_request (clist, -1, 300);
7068
7069       for (i = 1; i < TESTGTK_CLIST_COLUMNS; i++)
7070         gtk_clist_set_column_width (GTK_CLIST (clist), i, 80);
7071
7072       gtk_clist_set_column_auto_resize (GTK_CLIST (clist), 0, TRUE);
7073       gtk_clist_set_column_resizeable (GTK_CLIST (clist), 1, FALSE);
7074       gtk_clist_set_column_max_width (GTK_CLIST (clist), 2, 100);
7075       gtk_clist_set_column_min_width (GTK_CLIST (clist), 3, 50);
7076       gtk_clist_set_selection_mode (GTK_CLIST (clist), GTK_SELECTION_EXTENDED);
7077       gtk_clist_set_column_justification (GTK_CLIST (clist), 1,
7078                                           GTK_JUSTIFY_RIGHT);
7079       gtk_clist_set_column_justification (GTK_CLIST (clist), 2,
7080                                           GTK_JUSTIFY_CENTER);
7081       
7082       for (i = 0; i < TESTGTK_CLIST_COLUMNS; i++)
7083         {
7084           texts[i] = text[i];
7085           sprintf (text[i], "Column %d", i);
7086         }
7087
7088       sprintf (text[1], "Right");
7089       sprintf (text[2], "Center");
7090
7091       style = gtk_style_new ();
7092       style->fg[GTK_STATE_NORMAL] = red_col;
7093       style->base[GTK_STATE_NORMAL] = light_green_col;
7094
7095       pango_font_description_set_size (style->font_desc, 14 * PANGO_SCALE);
7096       pango_font_description_set_weight (style->font_desc, PANGO_WEIGHT_BOLD);
7097
7098       for (i = 0; i < 10; i++)
7099         {
7100           sprintf (text[0], "CListRow %d", clist_rows++);
7101           gtk_clist_append (GTK_CLIST (clist), texts);
7102
7103           switch (i % 4)
7104             {
7105             case 2:
7106               gtk_clist_set_row_style (GTK_CLIST (clist), i, style);
7107               break;
7108             default:
7109               gtk_clist_set_cell_style (GTK_CLIST (clist), i, i % 4, style);
7110               break;
7111             }
7112         }
7113
7114       g_object_unref (style);
7115       
7116       separator = gtk_hseparator_new ();
7117       gtk_box_pack_start (GTK_BOX (vbox), separator, FALSE, TRUE, 0);
7118
7119       hbox = gtk_hbox_new (FALSE, 0);
7120       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
7121
7122       button = gtk_button_new_with_label ("close");
7123       gtk_container_set_border_width (GTK_CONTAINER (button), 10);
7124       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
7125       g_signal_connect_swapped (button, "clicked",
7126                                 G_CALLBACK (gtk_widget_destroy),
7127                                 window);
7128
7129       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
7130       gtk_widget_grab_default (button);
7131     }
7132
7133   if (!GTK_WIDGET_VISIBLE (window))
7134     gtk_widget_show_all (window);
7135   else
7136     {
7137       clist_rows = 0;
7138       gtk_widget_destroy (window);
7139     }
7140 }
7141
7142 /*
7143  * GtkCTree
7144  */
7145
7146 typedef struct 
7147 {
7148   GdkPixmap *pixmap1;
7149   GdkPixmap *pixmap2;
7150   GdkPixmap *pixmap3;
7151   GdkBitmap *mask1;
7152   GdkBitmap *mask2;
7153   GdkBitmap *mask3;
7154 } CTreePixmaps;
7155
7156 static gint books = 0;
7157 static gint pages = 0;
7158
7159 static GtkWidget *book_label;
7160 static GtkWidget *page_label;
7161 static GtkWidget *sel_label;
7162 static GtkWidget *vis_label;
7163 static GtkWidget *omenu1;
7164 static GtkWidget *omenu2;
7165 static GtkWidget *omenu3;
7166 static GtkWidget *omenu4;
7167 static GtkWidget *spin1;
7168 static GtkWidget *spin2;
7169 static GtkWidget *spin3;
7170 static gint line_style;
7171
7172
7173 static CTreePixmaps *
7174 get_ctree_pixmaps (GtkCTree *ctree)
7175 {
7176   GdkScreen *screen = gtk_widget_get_screen (GTK_WIDGET (ctree));
7177   CTreePixmaps *pixmaps = g_object_get_data (G_OBJECT (screen), "ctree-pixmaps");
7178
7179   if (!pixmaps)
7180     {
7181       GdkColormap *colormap = gdk_screen_get_rgb_colormap (screen);
7182       pixmaps = g_new (CTreePixmaps, 1);
7183       
7184       pixmaps->pixmap1 = gdk_pixmap_colormap_create_from_xpm_d (NULL, colormap,
7185                                                                 &pixmaps->mask1, 
7186                                                                 NULL, book_closed_xpm);
7187       pixmaps->pixmap2 = gdk_pixmap_colormap_create_from_xpm_d (NULL, colormap,
7188                                                                 &pixmaps->mask2, 
7189                                                                 NULL, book_open_xpm);
7190       pixmaps->pixmap3 = gdk_pixmap_colormap_create_from_xpm_d (NULL, colormap,
7191                                                                 &pixmaps->mask3,
7192                                                                 NULL, mini_page_xpm);
7193       
7194       g_object_set_data (G_OBJECT (screen), "ctree-pixmaps", pixmaps);
7195     }
7196
7197   return pixmaps;
7198 }
7199
7200 void after_press (GtkCTree *ctree, gpointer data)
7201 {
7202   char buf[80];
7203
7204   sprintf (buf, "%d", g_list_length (GTK_CLIST (ctree)->selection));
7205   gtk_label_set_text (GTK_LABEL (sel_label), buf);
7206
7207   sprintf (buf, "%d", g_list_length (GTK_CLIST (ctree)->row_list));
7208   gtk_label_set_text (GTK_LABEL (vis_label), buf);
7209
7210   sprintf (buf, "%d", books);
7211   gtk_label_set_text (GTK_LABEL (book_label), buf);
7212
7213   sprintf (buf, "%d", pages);
7214   gtk_label_set_text (GTK_LABEL (page_label), buf);
7215 }
7216
7217 void after_move (GtkCTree *ctree, GtkCTreeNode *child, GtkCTreeNode *parent, 
7218                  GtkCTreeNode *sibling, gpointer data)
7219 {
7220   char *source;
7221   char *target1;
7222   char *target2;
7223
7224   gtk_ctree_get_node_info (ctree, child, &source, 
7225                            NULL, NULL, NULL, NULL, NULL, NULL, NULL);
7226   if (parent)
7227     gtk_ctree_get_node_info (ctree, parent, &target1, 
7228                              NULL, NULL, NULL, NULL, NULL, NULL, NULL);
7229   if (sibling)
7230     gtk_ctree_get_node_info (ctree, sibling, &target2, 
7231                              NULL, NULL, NULL, NULL, NULL, NULL, NULL);
7232
7233   g_print ("Moving \"%s\" to \"%s\" with sibling \"%s\".\n", source,
7234            (parent) ? target1 : "nil", (sibling) ? target2 : "nil");
7235 }
7236
7237 void count_items (GtkCTree *ctree, GtkCTreeNode *list)
7238 {
7239   if (GTK_CTREE_ROW (list)->is_leaf)
7240     pages--;
7241   else
7242     books--;
7243 }
7244
7245 void expand_all (GtkWidget *widget, GtkCTree *ctree)
7246 {
7247   gtk_ctree_expand_recursive (ctree, NULL);
7248   after_press (ctree, NULL);
7249 }
7250
7251 void collapse_all (GtkWidget *widget, GtkCTree *ctree)
7252 {
7253   gtk_ctree_collapse_recursive (ctree, NULL);
7254   after_press (ctree, NULL);
7255 }
7256
7257 void select_all (GtkWidget *widget, GtkCTree *ctree)
7258 {
7259   gtk_ctree_select_recursive (ctree, NULL);
7260   after_press (ctree, NULL);
7261 }
7262
7263 void change_style (GtkWidget *widget, GtkCTree *ctree)
7264 {
7265   static GtkStyle *style1 = NULL;
7266   static GtkStyle *style2 = NULL;
7267
7268   GtkCTreeNode *node;
7269   GdkColor green_col = { 0, 0, 56000, 0};
7270   GdkColor purple_col = { 0, 32000, 0, 56000};
7271
7272   if (GTK_CLIST (ctree)->focus_row >= 0)
7273     node = GTK_CTREE_NODE
7274       (g_list_nth (GTK_CLIST (ctree)->row_list,GTK_CLIST (ctree)->focus_row));
7275   else
7276     node = GTK_CTREE_NODE (GTK_CLIST (ctree)->row_list);
7277
7278   if (!node)
7279     return;
7280
7281   if (!style1)
7282     {
7283       style1 = gtk_style_new ();
7284       style1->base[GTK_STATE_NORMAL] = green_col;
7285       style1->fg[GTK_STATE_SELECTED] = purple_col;
7286
7287       style2 = gtk_style_new ();
7288       style2->base[GTK_STATE_SELECTED] = purple_col;
7289       style2->fg[GTK_STATE_NORMAL] = green_col;
7290       style2->base[GTK_STATE_NORMAL] = purple_col;
7291       pango_font_description_free (style2->font_desc);
7292       style2->font_desc = pango_font_description_from_string ("courier 30");
7293     }
7294
7295   gtk_ctree_node_set_cell_style (ctree, node, 1, style1);
7296   gtk_ctree_node_set_cell_style (ctree, node, 0, style2);
7297
7298   if (GTK_CTREE_ROW (node)->children)
7299     gtk_ctree_node_set_row_style (ctree, GTK_CTREE_ROW (node)->children,
7300                                   style2);
7301 }
7302
7303 void unselect_all (GtkWidget *widget, GtkCTree *ctree)
7304 {
7305   gtk_ctree_unselect_recursive (ctree, NULL);
7306   after_press (ctree, NULL);
7307 }
7308
7309 void remove_selection (GtkWidget *widget, GtkCTree *ctree)
7310 {
7311   GtkCList *clist;
7312   GtkCTreeNode *node;
7313
7314   clist = GTK_CLIST (ctree);
7315
7316   gtk_clist_freeze (clist);
7317
7318   while (clist->selection)
7319     {
7320       node = clist->selection->data;
7321
7322       if (GTK_CTREE_ROW (node)->is_leaf)
7323         pages--;
7324       else
7325         gtk_ctree_post_recursive (ctree, node,
7326                                   (GtkCTreeFunc) count_items, NULL);
7327
7328       gtk_ctree_remove_node (ctree, node);
7329
7330       if (clist->selection_mode == GTK_SELECTION_BROWSE)
7331         break;
7332     }
7333
7334   if (clist->selection_mode == GTK_SELECTION_EXTENDED && !clist->selection &&
7335       clist->focus_row >= 0)
7336     {
7337       node = gtk_ctree_node_nth (ctree, clist->focus_row);
7338
7339       if (node)
7340         gtk_ctree_select (ctree, node);
7341     }
7342     
7343   gtk_clist_thaw (clist);
7344   after_press (ctree, NULL);
7345 }
7346
7347 struct _ExportStruct {
7348   gchar *tree;
7349   gchar *info;
7350   gboolean is_leaf;
7351 };
7352
7353 typedef struct _ExportStruct ExportStruct;
7354
7355 gboolean
7356 gnode2ctree (GtkCTree   *ctree,
7357              guint       depth,
7358              GNode        *gnode,
7359              GtkCTreeNode *cnode,
7360              gpointer    data)
7361 {
7362   ExportStruct *es;
7363   GdkPixmap *pixmap_closed;
7364   GdkBitmap *mask_closed;
7365   GdkPixmap *pixmap_opened;
7366   GdkBitmap *mask_opened;
7367   CTreePixmaps *pixmaps;
7368
7369   if (!cnode || !gnode || (!(es = gnode->data)))
7370     return FALSE;
7371
7372   pixmaps = get_ctree_pixmaps (ctree);
7373
7374   if (es->is_leaf)
7375     {
7376       pixmap_closed = pixmaps->pixmap3;
7377       mask_closed = pixmaps->mask3;
7378       pixmap_opened = NULL;
7379       mask_opened = NULL;
7380     }
7381   else
7382     {
7383       pixmap_closed = pixmaps->pixmap1;
7384       mask_closed = pixmaps->mask1;
7385       pixmap_opened = pixmaps->pixmap2;
7386       mask_opened = pixmaps->mask2;
7387     }
7388
7389   gtk_ctree_set_node_info (ctree, cnode, es->tree, 2, pixmap_closed,
7390                            mask_closed, pixmap_opened, mask_opened,
7391                            es->is_leaf, (depth < 3));
7392   gtk_ctree_node_set_text (ctree, cnode, 1, es->info);
7393   g_free (es);
7394   gnode->data = NULL;
7395
7396   return TRUE;
7397 }
7398
7399 gboolean
7400 ctree2gnode (GtkCTree   *ctree,
7401              guint       depth,
7402              GNode        *gnode,
7403              GtkCTreeNode *cnode,
7404              gpointer    data)
7405 {
7406   ExportStruct *es;
7407
7408   if (!cnode || !gnode)
7409     return FALSE;
7410   
7411   es = g_new (ExportStruct, 1);
7412   gnode->data = es;
7413   es->is_leaf = GTK_CTREE_ROW (cnode)->is_leaf;
7414   es->tree = GTK_CELL_PIXTEXT (GTK_CTREE_ROW (cnode)->row.cell[0])->text;
7415   es->info = GTK_CELL_PIXTEXT (GTK_CTREE_ROW (cnode)->row.cell[1])->text;
7416   return TRUE;
7417 }
7418
7419 void export_ctree (GtkWidget *widget, GtkCTree *ctree)
7420 {
7421   char *title[] = { "Tree" , "Info" };
7422   static GtkWidget *export_window = NULL;
7423   static GtkCTree *export_ctree;
7424   GtkWidget *vbox;
7425   GtkWidget *scrolled_win;
7426   GtkWidget *button;
7427   GtkWidget *sep;
7428   GNode *gnode;
7429   GtkCTreeNode *node;
7430
7431   if (!export_window)
7432     {
7433       export_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7434
7435       gtk_window_set_screen (GTK_WINDOW (export_window),
7436                              gtk_widget_get_screen (widget));
7437   
7438       g_signal_connect (export_window, "destroy",
7439                         G_CALLBACK (gtk_widget_destroyed),
7440                         &export_window);
7441
7442       gtk_window_set_title (GTK_WINDOW (export_window), "exported ctree");
7443       gtk_container_set_border_width (GTK_CONTAINER (export_window), 5);
7444
7445       vbox = gtk_vbox_new (FALSE, 0);
7446       gtk_container_add (GTK_CONTAINER (export_window), vbox);
7447       
7448       button = gtk_button_new_with_label ("Close");
7449       gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, TRUE, 0);
7450
7451       g_signal_connect_swapped (button, "clicked",
7452                                 G_CALLBACK (gtk_widget_destroy),
7453                                 export_window);
7454
7455       sep = gtk_hseparator_new ();
7456       gtk_box_pack_end (GTK_BOX (vbox), sep, FALSE, TRUE, 10);
7457
7458       export_ctree = GTK_CTREE (gtk_ctree_new_with_titles (2, 0, title));
7459       gtk_ctree_set_line_style (export_ctree, GTK_CTREE_LINES_DOTTED);
7460
7461       scrolled_win = gtk_scrolled_window_new (NULL, NULL);
7462       gtk_container_add (GTK_CONTAINER (scrolled_win),
7463                          GTK_WIDGET (export_ctree));
7464       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
7465                                       GTK_POLICY_AUTOMATIC,
7466                                       GTK_POLICY_AUTOMATIC);
7467       gtk_box_pack_start (GTK_BOX (vbox), scrolled_win, TRUE, TRUE, 0);
7468       gtk_clist_set_selection_mode (GTK_CLIST (export_ctree),
7469                                     GTK_SELECTION_EXTENDED);
7470       gtk_clist_set_column_width (GTK_CLIST (export_ctree), 0, 200);
7471       gtk_clist_set_column_width (GTK_CLIST (export_ctree), 1, 200);
7472       gtk_widget_set_size_request (GTK_WIDGET (export_ctree), 300, 200);
7473     }
7474
7475   if (!GTK_WIDGET_VISIBLE (export_window))
7476     gtk_widget_show_all (export_window);
7477       
7478   gtk_clist_clear (GTK_CLIST (export_ctree));
7479
7480   node = GTK_CTREE_NODE (g_list_nth (GTK_CLIST (ctree)->row_list,
7481                                      GTK_CLIST (ctree)->focus_row));
7482   if (!node)
7483     return;
7484
7485   gnode = gtk_ctree_export_to_gnode (ctree, NULL, NULL, node,
7486                                      ctree2gnode, NULL);
7487   if (gnode)
7488     {
7489       gtk_ctree_insert_gnode (export_ctree, NULL, NULL, gnode,
7490                               gnode2ctree, NULL);
7491       g_node_destroy (gnode);
7492     }
7493 }
7494
7495 void change_indent (GtkWidget *widget, GtkCTree *ctree)
7496 {
7497   gtk_ctree_set_indent (ctree, GTK_ADJUSTMENT (widget)->value);
7498 }
7499
7500 void change_spacing (GtkWidget *widget, GtkCTree *ctree)
7501 {
7502   gtk_ctree_set_spacing (ctree, GTK_ADJUSTMENT (widget)->value);
7503 }
7504
7505 void change_row_height (GtkWidget *widget, GtkCList *clist)
7506 {
7507   gtk_clist_set_row_height (clist, GTK_ADJUSTMENT (widget)->value);
7508 }
7509
7510 void set_background (GtkCTree *ctree, GtkCTreeNode *node, gpointer data)
7511 {
7512   GtkStyle *style = NULL;
7513   
7514   if (!node)
7515     return;
7516   
7517   if (ctree->line_style != GTK_CTREE_LINES_TABBED)
7518     {
7519       if (!GTK_CTREE_ROW (node)->is_leaf)
7520         style = GTK_CTREE_ROW (node)->row.data;
7521       else if (GTK_CTREE_ROW (node)->parent)
7522         style = GTK_CTREE_ROW (GTK_CTREE_ROW (node)->parent)->row.data;
7523     }
7524
7525   gtk_ctree_node_set_row_style (ctree, node, style);
7526 }
7527
7528 void 
7529 ctree_toggle_line_style (GtkWidget *widget, gpointer data)
7530 {
7531   GtkCTree *ctree;
7532   gint i;
7533
7534   ctree = GTK_CTREE (data);
7535
7536   if (!GTK_WIDGET_MAPPED (widget))
7537     return;
7538
7539   i = gtk_option_menu_get_history (GTK_OPTION_MENU (widget));
7540
7541   if ((ctree->line_style == GTK_CTREE_LINES_TABBED && 
7542        ((GtkCTreeLineStyle) i) != GTK_CTREE_LINES_TABBED) ||
7543       (ctree->line_style != GTK_CTREE_LINES_TABBED && 
7544        ((GtkCTreeLineStyle) i) == GTK_CTREE_LINES_TABBED))
7545     gtk_ctree_pre_recursive (ctree, NULL, set_background, NULL);
7546   gtk_ctree_set_line_style (ctree, i);
7547   line_style = i;
7548 }
7549
7550 void 
7551 ctree_toggle_expander_style (GtkWidget *widget, gpointer data)
7552 {
7553   GtkCTree *ctree;
7554   gint i;
7555
7556   ctree = GTK_CTREE (data);
7557
7558   if (!GTK_WIDGET_MAPPED (widget))
7559     return;
7560   
7561   i = gtk_option_menu_get_history (GTK_OPTION_MENU (widget));
7562   
7563   gtk_ctree_set_expander_style (ctree, (GtkCTreeExpanderStyle) i);
7564 }
7565
7566 void 
7567 ctree_toggle_justify (GtkWidget *widget, gpointer data)
7568 {
7569   GtkCTree *ctree;
7570   gint i;
7571
7572   ctree = GTK_CTREE (data);
7573
7574   if (!GTK_WIDGET_MAPPED (widget))
7575     return;
7576
7577   i = gtk_option_menu_get_history (GTK_OPTION_MENU (widget));
7578
7579   gtk_clist_set_column_justification (GTK_CLIST (ctree), ctree->tree_column, 
7580                                       (GtkJustification) i);
7581 }
7582
7583 void 
7584 ctree_toggle_sel_mode (GtkWidget *widget, gpointer data)
7585 {
7586   GtkCTree *ctree;
7587   gint i;
7588
7589   ctree = GTK_CTREE (data);
7590
7591   if (!GTK_WIDGET_MAPPED (widget))
7592     return;
7593
7594   i = gtk_option_menu_get_history (GTK_OPTION_MENU (widget));
7595
7596   gtk_clist_set_selection_mode (GTK_CLIST (ctree), selection_modes[i]);
7597   after_press (ctree, NULL);
7598 }
7599     
7600 void build_recursive (GtkCTree *ctree, gint cur_depth, gint depth, 
7601                       gint num_books, gint num_pages, GtkCTreeNode *parent)
7602 {
7603   gchar *text[2];
7604   gchar buf1[60];
7605   gchar buf2[60];
7606   GtkCTreeNode *sibling;
7607   CTreePixmaps *pixmaps;
7608   gint i;
7609
7610   text[0] = buf1;
7611   text[1] = buf2;
7612   sibling = NULL;
7613
7614   pixmaps = get_ctree_pixmaps (ctree);
7615
7616   for (i = num_pages + num_books; i > num_books; i--)
7617     {
7618       pages++;
7619       sprintf (buf1, "Page %02d", (gint) rand() % 100);
7620       sprintf (buf2, "Item %d-%d", cur_depth, i);
7621       sibling = gtk_ctree_insert_node (ctree, parent, sibling, text, 5,
7622                                        pixmaps->pixmap3, pixmaps->mask3, NULL, NULL,
7623                                        TRUE, FALSE);
7624
7625       if (parent && ctree->line_style == GTK_CTREE_LINES_TABBED)
7626         gtk_ctree_node_set_row_style (ctree, sibling,
7627                                       GTK_CTREE_ROW (parent)->row.style);
7628     }
7629
7630   if (cur_depth == depth)
7631     return;
7632
7633   for (i = num_books; i > 0; i--)
7634     {
7635       GtkStyle *style;
7636
7637       books++;
7638       sprintf (buf1, "Book %02d", (gint) rand() % 100);
7639       sprintf (buf2, "Item %d-%d", cur_depth, i);
7640       sibling = gtk_ctree_insert_node (ctree, parent, sibling, text, 5,
7641                                        pixmaps->pixmap1, pixmaps->mask1, pixmaps->pixmap2, pixmaps->mask2,
7642                                        FALSE, FALSE);
7643
7644       style = gtk_style_new ();
7645       switch (cur_depth % 3)
7646         {
7647         case 0:
7648           style->base[GTK_STATE_NORMAL].red   = 10000 * (cur_depth % 6);
7649           style->base[GTK_STATE_NORMAL].green = 0;
7650           style->base[GTK_STATE_NORMAL].blue  = 65535 - ((i * 10000) % 65535);
7651           break;
7652         case 1:
7653           style->base[GTK_STATE_NORMAL].red   = 10000 * (cur_depth % 6);
7654           style->base[GTK_STATE_NORMAL].green = 65535 - ((i * 10000) % 65535);
7655           style->base[GTK_STATE_NORMAL].blue  = 0;
7656           break;
7657         default:
7658           style->base[GTK_STATE_NORMAL].red   = 65535 - ((i * 10000) % 65535);
7659           style->base[GTK_STATE_NORMAL].green = 0;
7660           style->base[GTK_STATE_NORMAL].blue  = 10000 * (cur_depth % 6);
7661           break;
7662         }
7663       gtk_ctree_node_set_row_data_full (ctree, sibling, style,
7664                                         (GDestroyNotify) g_object_unref);
7665
7666       if (ctree->line_style == GTK_CTREE_LINES_TABBED)
7667         gtk_ctree_node_set_row_style (ctree, sibling, style);
7668
7669       build_recursive (ctree, cur_depth + 1, depth, num_books, num_pages,
7670                        sibling);
7671     }
7672 }
7673
7674 void rebuild_tree (GtkWidget *widget, GtkCTree *ctree)
7675 {
7676   gchar *text [2];
7677   gchar label1[] = "Root";
7678   gchar label2[] = "";
7679   GtkCTreeNode *parent;
7680   GtkStyle *style;
7681   guint b, d, p, n;
7682   CTreePixmaps *pixmaps;
7683
7684   pixmaps = get_ctree_pixmaps (ctree);
7685
7686   text[0] = label1;
7687   text[1] = label2;
7688   
7689   d = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (spin1)); 
7690   b = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (spin2));
7691   p = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (spin3));
7692
7693   n = ((pow (b, d) - 1) / (b - 1)) * (p + 1);
7694
7695   if (n > 100000)
7696     {
7697       g_print ("%d total items? Try less\n",n);
7698       return;
7699     }
7700
7701   gtk_clist_freeze (GTK_CLIST (ctree));
7702   gtk_clist_clear (GTK_CLIST (ctree));
7703
7704   books = 1;
7705   pages = 0;
7706
7707   parent = gtk_ctree_insert_node (ctree, NULL, NULL, text, 5, pixmaps->pixmap1,
7708                                   pixmaps->mask1, pixmaps->pixmap2, pixmaps->mask2, FALSE, TRUE);
7709
7710   style = gtk_style_new ();
7711   style->base[GTK_STATE_NORMAL].red   = 0;
7712   style->base[GTK_STATE_NORMAL].green = 45000;
7713   style->base[GTK_STATE_NORMAL].blue  = 55000;
7714   gtk_ctree_node_set_row_data_full (ctree, parent, style,
7715                                     (GDestroyNotify) g_object_unref);
7716
7717   if (ctree->line_style == GTK_CTREE_LINES_TABBED)
7718     gtk_ctree_node_set_row_style (ctree, parent, style);
7719
7720   build_recursive (ctree, 1, d, b, p, parent);
7721   gtk_clist_thaw (GTK_CLIST (ctree));
7722   after_press (ctree, NULL);
7723 }
7724
7725 static void 
7726 ctree_click_column (GtkCTree *ctree, gint column, gpointer data)
7727 {
7728   GtkCList *clist;
7729
7730   clist = GTK_CLIST (ctree);
7731
7732   if (column == clist->sort_column)
7733     {
7734       if (clist->sort_type == GTK_SORT_ASCENDING)
7735         clist->sort_type = GTK_SORT_DESCENDING;
7736       else
7737         clist->sort_type = GTK_SORT_ASCENDING;
7738     }
7739   else
7740     gtk_clist_set_sort_column (clist, column);
7741
7742   gtk_ctree_sort_recursive (ctree, NULL);
7743 }
7744
7745 void create_ctree (GtkWidget *widget)
7746 {
7747   static GtkWidget *window = NULL;
7748   GtkTooltips *tooltips;
7749   GtkCTree *ctree;
7750   GtkWidget *scrolled_win;
7751   GtkWidget *vbox;
7752   GtkWidget *bbox;
7753   GtkWidget *mbox;
7754   GtkWidget *hbox;
7755   GtkWidget *hbox2;
7756   GtkWidget *frame;
7757   GtkWidget *label;
7758   GtkWidget *button;
7759   GtkWidget *check;
7760   GtkAdjustment *adj;
7761   GtkWidget *spinner;
7762
7763   char *title[] = { "Tree" , "Info" };
7764   char buf[80];
7765
7766   static gchar *items1[] =
7767   {
7768     "No lines",
7769     "Solid",
7770     "Dotted",
7771     "Tabbed"
7772   };
7773
7774   static gchar *items2[] =
7775   {
7776     "None",
7777     "Square",
7778     "Triangle",
7779     "Circular"
7780   };
7781
7782   static gchar *items3[] =
7783   {
7784     "Left",
7785     "Right"
7786   };
7787   
7788   if (!window)
7789     {
7790       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7791       gtk_window_set_screen (GTK_WINDOW (window), 
7792                              gtk_widget_get_screen (widget));
7793
7794       g_signal_connect (window, "destroy",
7795                         G_CALLBACK (gtk_widget_destroyed),
7796                         &window);
7797
7798       gtk_window_set_title (GTK_WINDOW (window), "GtkCTree");
7799       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
7800
7801       tooltips = gtk_tooltips_new ();
7802       g_object_ref (tooltips);
7803       gtk_object_sink (GTK_OBJECT (tooltips));
7804
7805       g_object_set_data_full (G_OBJECT (window), "tooltips", tooltips,
7806                               g_object_unref);
7807
7808       vbox = gtk_vbox_new (FALSE, 0);
7809       gtk_container_add (GTK_CONTAINER (window), vbox);
7810
7811       hbox = gtk_hbox_new (FALSE, 5);
7812       gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
7813       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
7814       
7815       label = gtk_label_new ("Depth :");
7816       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
7817       
7818       adj = (GtkAdjustment *) gtk_adjustment_new (4, 1, 10, 1, 5, 0);
7819       spin1 = gtk_spin_button_new (adj, 0, 0);
7820       gtk_box_pack_start (GTK_BOX (hbox), spin1, FALSE, TRUE, 5);
7821   
7822       label = gtk_label_new ("Books :");
7823       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
7824       
7825       adj = (GtkAdjustment *) gtk_adjustment_new (3, 1, 20, 1, 5, 0);
7826       spin2 = gtk_spin_button_new (adj, 0, 0);
7827       gtk_box_pack_start (GTK_BOX (hbox), spin2, FALSE, TRUE, 5);
7828
7829       label = gtk_label_new ("Pages :");
7830       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
7831       
7832       adj = (GtkAdjustment *) gtk_adjustment_new (5, 1, 20, 1, 5, 0);
7833       spin3 = gtk_spin_button_new (adj, 0, 0);
7834       gtk_box_pack_start (GTK_BOX (hbox), spin3, FALSE, TRUE, 5);
7835
7836       button = gtk_button_new_with_label ("Close");
7837       gtk_box_pack_end (GTK_BOX (hbox), button, TRUE, TRUE, 0);
7838
7839       g_signal_connect_swapped (button, "clicked",
7840                                 G_CALLBACK (gtk_widget_destroy),
7841                                 window);
7842
7843       button = gtk_button_new_with_label ("Rebuild Tree");
7844       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
7845
7846       scrolled_win = gtk_scrolled_window_new (NULL, NULL);
7847       gtk_container_set_border_width (GTK_CONTAINER (scrolled_win), 5);
7848       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
7849                                       GTK_POLICY_AUTOMATIC,
7850                                       GTK_POLICY_ALWAYS);
7851       gtk_box_pack_start (GTK_BOX (vbox), scrolled_win, TRUE, TRUE, 0);
7852
7853       ctree = GTK_CTREE (gtk_ctree_new_with_titles (2, 0, title));
7854       gtk_container_add (GTK_CONTAINER (scrolled_win), GTK_WIDGET (ctree));
7855
7856       gtk_clist_set_column_auto_resize (GTK_CLIST (ctree), 0, TRUE);
7857       gtk_clist_set_column_width (GTK_CLIST (ctree), 1, 200);
7858       gtk_clist_set_selection_mode (GTK_CLIST (ctree), GTK_SELECTION_EXTENDED);
7859       gtk_ctree_set_line_style (ctree, GTK_CTREE_LINES_DOTTED);
7860       line_style = GTK_CTREE_LINES_DOTTED;
7861
7862       g_signal_connect (button, "clicked",
7863                         G_CALLBACK (rebuild_tree), ctree);
7864       g_signal_connect (ctree, "click_column",
7865                         G_CALLBACK (ctree_click_column), NULL);
7866
7867       g_signal_connect_after (ctree, "button_press_event",
7868                               G_CALLBACK (after_press), NULL);
7869       g_signal_connect_after (ctree, "button_release_event",
7870                               G_CALLBACK (after_press), NULL);
7871       g_signal_connect_after (ctree, "tree_move",
7872                               G_CALLBACK (after_move), NULL);
7873       g_signal_connect_after (ctree, "end_selection",
7874                               G_CALLBACK (after_press), NULL);
7875       g_signal_connect_after (ctree, "toggle_focus_row",
7876                               G_CALLBACK (after_press), NULL);
7877       g_signal_connect_after (ctree, "select_all",
7878                               G_CALLBACK (after_press), NULL);
7879       g_signal_connect_after (ctree, "unselect_all",
7880                               G_CALLBACK (after_press), NULL);
7881       g_signal_connect_after (ctree, "scroll_vertical",
7882                               G_CALLBACK (after_press), NULL);
7883
7884       bbox = gtk_hbox_new (FALSE, 5);
7885       gtk_container_set_border_width (GTK_CONTAINER (bbox), 5);
7886       gtk_box_pack_start (GTK_BOX (vbox), bbox, FALSE, TRUE, 0);
7887
7888       mbox = gtk_vbox_new (TRUE, 5);
7889       gtk_box_pack_start (GTK_BOX (bbox), mbox, FALSE, TRUE, 0);
7890
7891       label = gtk_label_new ("Row Height :");
7892       gtk_box_pack_start (GTK_BOX (mbox), label, FALSE, FALSE, 0);
7893
7894       label = gtk_label_new ("Indent :");
7895       gtk_box_pack_start (GTK_BOX (mbox), label, FALSE, FALSE, 0);
7896
7897       label = gtk_label_new ("Spacing :");
7898       gtk_box_pack_start (GTK_BOX (mbox), label, FALSE, FALSE, 0);
7899
7900       mbox = gtk_vbox_new (TRUE, 5);
7901       gtk_box_pack_start (GTK_BOX (bbox), mbox, FALSE, TRUE, 0);
7902
7903       adj = (GtkAdjustment *) gtk_adjustment_new (20, 12, 100, 1, 10, 0);
7904       spinner = gtk_spin_button_new (adj, 0, 0);
7905       gtk_box_pack_start (GTK_BOX (mbox), spinner, FALSE, FALSE, 5);
7906       gtk_tooltips_set_tip (tooltips, spinner,
7907                             "Row height of list items", NULL);
7908       g_signal_connect (adj, "value_changed",
7909                         G_CALLBACK (change_row_height), ctree);
7910       gtk_clist_set_row_height ( GTK_CLIST (ctree), adj->value);
7911
7912       adj = (GtkAdjustment *) gtk_adjustment_new (20, 0, 60, 1, 10, 0);
7913       spinner = gtk_spin_button_new (adj, 0, 0);
7914       gtk_box_pack_start (GTK_BOX (mbox), spinner, FALSE, FALSE, 5);
7915       gtk_tooltips_set_tip (tooltips, spinner, "Tree Indentation.", NULL);
7916       g_signal_connect (adj, "value_changed",
7917                         G_CALLBACK (change_indent), ctree);
7918
7919       adj = (GtkAdjustment *) gtk_adjustment_new (5, 0, 60, 1, 10, 0);
7920       spinner = gtk_spin_button_new (adj, 0, 0);
7921       gtk_box_pack_start (GTK_BOX (mbox), spinner, FALSE, FALSE, 5);
7922       gtk_tooltips_set_tip (tooltips, spinner, "Tree Spacing.", NULL);
7923       g_signal_connect (adj, "value_changed",
7924                         G_CALLBACK (change_spacing), ctree);
7925
7926       mbox = gtk_vbox_new (TRUE, 5);
7927       gtk_box_pack_start (GTK_BOX (bbox), mbox, FALSE, TRUE, 0);
7928
7929       hbox = gtk_hbox_new (FALSE, 5);
7930       gtk_box_pack_start (GTK_BOX (mbox), hbox, FALSE, FALSE, 0);
7931
7932       button = gtk_button_new_with_label ("Expand All");
7933       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
7934       g_signal_connect (button, "clicked",
7935                         G_CALLBACK (expand_all), ctree);
7936
7937       button = gtk_button_new_with_label ("Collapse All");
7938       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
7939       g_signal_connect (button, "clicked",
7940                         G_CALLBACK (collapse_all), ctree);
7941
7942       button = gtk_button_new_with_label ("Change Style");
7943       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
7944       g_signal_connect (button, "clicked",
7945                         G_CALLBACK (change_style), ctree);
7946
7947       button = gtk_button_new_with_label ("Export Tree");
7948       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
7949       g_signal_connect (button, "clicked",
7950                         G_CALLBACK (export_ctree), ctree);
7951
7952       hbox = gtk_hbox_new (FALSE, 5);
7953       gtk_box_pack_start (GTK_BOX (mbox), hbox, FALSE, FALSE, 0);
7954
7955       button = gtk_button_new_with_label ("Select All");
7956       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
7957       g_signal_connect (button, "clicked",
7958                         G_CALLBACK (select_all), ctree);
7959
7960       button = gtk_button_new_with_label ("Unselect All");
7961       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
7962       g_signal_connect (button, "clicked",
7963                         G_CALLBACK (unselect_all), ctree);
7964
7965       button = gtk_button_new_with_label ("Remove Selection");
7966       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
7967       g_signal_connect (button, "clicked",
7968                         G_CALLBACK (remove_selection), ctree);
7969
7970       check = gtk_check_button_new_with_label ("Reorderable");
7971       gtk_box_pack_start (GTK_BOX (hbox), check, FALSE, TRUE, 0);
7972       gtk_tooltips_set_tip (tooltips, check,
7973                             "Tree items can be reordered by dragging.", NULL);
7974       g_signal_connect (check, "clicked",
7975                         G_CALLBACK (toggle_reorderable), ctree);
7976       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check), TRUE);
7977
7978       hbox = gtk_hbox_new (TRUE, 5);
7979       gtk_box_pack_start (GTK_BOX (mbox), hbox, FALSE, FALSE, 0);
7980
7981       omenu1 = build_option_menu (items1, 4, 2, 
7982                                   ctree_toggle_line_style,
7983                                   ctree);
7984       gtk_box_pack_start (GTK_BOX (hbox), omenu1, FALSE, TRUE, 0);
7985       gtk_tooltips_set_tip (tooltips, omenu1, "The tree's line style.", NULL);
7986
7987       omenu2 = build_option_menu (items2, 4, 1, 
7988                                   ctree_toggle_expander_style,
7989                                   ctree);
7990       gtk_box_pack_start (GTK_BOX (hbox), omenu2, FALSE, TRUE, 0);
7991       gtk_tooltips_set_tip (tooltips, omenu2, "The tree's expander style.",
7992                             NULL);
7993
7994       omenu3 = build_option_menu (items3, 2, 0, 
7995                                   ctree_toggle_justify, ctree);
7996       gtk_box_pack_start (GTK_BOX (hbox), omenu3, FALSE, TRUE, 0);
7997       gtk_tooltips_set_tip (tooltips, omenu3, "The tree's justification.",
7998                             NULL);
7999
8000       omenu4 = build_option_menu (selection_mode_items, 3, 3, 
8001                                   ctree_toggle_sel_mode, ctree);
8002       gtk_box_pack_start (GTK_BOX (hbox), omenu4, FALSE, TRUE, 0);
8003       gtk_tooltips_set_tip (tooltips, omenu4, "The list's selection mode.",
8004                             NULL);
8005
8006       gtk_widget_realize (window);
8007       
8008       gtk_widget_set_size_request (GTK_WIDGET (ctree), -1, 300);
8009
8010       frame = gtk_frame_new (NULL);
8011       gtk_container_set_border_width (GTK_CONTAINER (frame), 0);
8012       gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT);
8013       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
8014
8015       hbox = gtk_hbox_new (TRUE, 2);
8016       gtk_container_set_border_width (GTK_CONTAINER (hbox), 2);
8017       gtk_container_add (GTK_CONTAINER (frame), hbox);
8018
8019       frame = gtk_frame_new (NULL);
8020       gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
8021       gtk_box_pack_start (GTK_BOX (hbox), frame, FALSE, TRUE, 0);
8022
8023       hbox2 = gtk_hbox_new (FALSE, 0);
8024       gtk_container_set_border_width (GTK_CONTAINER (hbox2), 2);
8025       gtk_container_add (GTK_CONTAINER (frame), hbox2);
8026
8027       label = gtk_label_new ("Books :");
8028       gtk_box_pack_start (GTK_BOX (hbox2), label, FALSE, TRUE, 0);
8029
8030       sprintf (buf, "%d", books);
8031       book_label = gtk_label_new (buf);
8032       gtk_box_pack_end (GTK_BOX (hbox2), book_label, FALSE, TRUE, 5);
8033
8034       frame = gtk_frame_new (NULL);
8035       gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
8036       gtk_box_pack_start (GTK_BOX (hbox), frame, FALSE, TRUE, 0);
8037
8038       hbox2 = gtk_hbox_new (FALSE, 0);
8039       gtk_container_set_border_width (GTK_CONTAINER (hbox2), 2);
8040       gtk_container_add (GTK_CONTAINER (frame), hbox2);
8041
8042       label = gtk_label_new ("Pages :");
8043       gtk_box_pack_start (GTK_BOX (hbox2), label, FALSE, TRUE, 0);
8044
8045       sprintf (buf, "%d", pages);
8046       page_label = gtk_label_new (buf);
8047       gtk_box_pack_end (GTK_BOX (hbox2), page_label, FALSE, TRUE, 5);
8048
8049       frame = gtk_frame_new (NULL);
8050       gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
8051       gtk_box_pack_start (GTK_BOX (hbox), frame, FALSE, TRUE, 0);
8052
8053       hbox2 = gtk_hbox_new (FALSE, 0);
8054       gtk_container_set_border_width (GTK_CONTAINER (hbox2), 2);
8055       gtk_container_add (GTK_CONTAINER (frame), hbox2);
8056
8057       label = gtk_label_new ("Selected :");
8058       gtk_box_pack_start (GTK_BOX (hbox2), label, FALSE, TRUE, 0);
8059
8060       sprintf (buf, "%d", g_list_length (GTK_CLIST (ctree)->selection));
8061       sel_label = gtk_label_new (buf);
8062       gtk_box_pack_end (GTK_BOX (hbox2), sel_label, FALSE, TRUE, 5);
8063
8064       frame = gtk_frame_new (NULL);
8065       gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
8066       gtk_box_pack_start (GTK_BOX (hbox), frame, FALSE, TRUE, 0);
8067
8068       hbox2 = gtk_hbox_new (FALSE, 0);
8069       gtk_container_set_border_width (GTK_CONTAINER (hbox2), 2);
8070       gtk_container_add (GTK_CONTAINER (frame), hbox2);
8071
8072       label = gtk_label_new ("Visible :");
8073       gtk_box_pack_start (GTK_BOX (hbox2), label, FALSE, TRUE, 0);
8074
8075       sprintf (buf, "%d", g_list_length (GTK_CLIST (ctree)->row_list));
8076       vis_label = gtk_label_new (buf);
8077       gtk_box_pack_end (GTK_BOX (hbox2), vis_label, FALSE, TRUE, 5);
8078
8079       rebuild_tree (NULL, ctree);
8080     }
8081
8082   if (!GTK_WIDGET_VISIBLE (window))
8083     gtk_widget_show_all (window);
8084   else
8085     gtk_widget_destroy (window);
8086 }
8087
8088 /*
8089  * GtkColorSelection
8090  */
8091
8092 void
8093 color_selection_ok (GtkWidget               *w,
8094                     GtkColorSelectionDialog *cs)
8095 {
8096   GtkColorSelection *colorsel;
8097   gdouble color[4];
8098
8099   colorsel=GTK_COLOR_SELECTION(cs->colorsel);
8100
8101   gtk_color_selection_get_color(colorsel,color);
8102   gtk_color_selection_set_color(colorsel,color);
8103 }
8104
8105 void
8106 color_selection_changed (GtkWidget *w,
8107                          GtkColorSelectionDialog *cs)
8108 {
8109   GtkColorSelection *colorsel;
8110   gdouble color[4];
8111
8112   colorsel=GTK_COLOR_SELECTION(cs->colorsel);
8113   gtk_color_selection_get_color(colorsel,color);
8114 }
8115
8116 #if 0 /* unused */
8117 static void
8118 opacity_toggled_cb (GtkWidget *w,
8119                     GtkColorSelectionDialog *cs)
8120 {
8121   GtkColorSelection *colorsel;
8122
8123   colorsel = GTK_COLOR_SELECTION (cs->colorsel);
8124   gtk_color_selection_set_has_opacity_control (colorsel,
8125                                                gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w)));
8126 }
8127
8128 static void
8129 palette_toggled_cb (GtkWidget *w,
8130                     GtkColorSelectionDialog *cs)
8131 {
8132   GtkColorSelection *colorsel;
8133
8134   colorsel = GTK_COLOR_SELECTION (cs->colorsel);
8135   gtk_color_selection_set_has_palette (colorsel,
8136                                        gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w)));
8137 }
8138 #endif
8139
8140 void
8141 create_color_selection (GtkWidget *widget)
8142 {
8143   static GtkWidget *window = NULL;
8144
8145   if (!window)
8146     {
8147       GtkWidget *picker;
8148       GtkWidget *hbox;
8149       GtkWidget *label;
8150       
8151       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8152       gtk_window_set_screen (GTK_WINDOW (window), 
8153                              gtk_widget_get_screen (widget));
8154                              
8155       g_signal_connect (window, "destroy",
8156                         G_CALLBACK (gtk_widget_destroyed),
8157                         &window);
8158
8159       gtk_window_set_title (GTK_WINDOW (window), "GtkColorButton");
8160       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
8161
8162       hbox = gtk_hbox_new (FALSE, 8);
8163       gtk_container_set_border_width (GTK_CONTAINER (hbox), 8);
8164       gtk_container_add (GTK_CONTAINER (window), hbox);
8165       
8166       label = gtk_label_new ("Pick a color");
8167       gtk_container_add (GTK_CONTAINER (hbox), label);
8168
8169       picker = gtk_color_button_new ();
8170       gtk_color_button_set_use_alpha (GTK_COLOR_BUTTON (picker), TRUE);
8171       gtk_container_add (GTK_CONTAINER (hbox), picker);
8172     }
8173
8174   if (!GTK_WIDGET_VISIBLE (window))
8175     gtk_widget_show_all (window);
8176   else
8177     gtk_widget_destroy (window);
8178 }
8179
8180 /*
8181  * GtkFileSelection
8182  */
8183
8184 void
8185 show_fileops (GtkWidget        *widget,
8186               GtkFileSelection *fs)
8187 {
8188   gboolean show_ops;
8189
8190   show_ops = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
8191
8192   if (show_ops)
8193     gtk_file_selection_show_fileop_buttons (fs);
8194   else
8195     gtk_file_selection_hide_fileop_buttons (fs);
8196 }
8197
8198 void
8199 select_multiple (GtkWidget        *widget,
8200                  GtkFileSelection *fs)
8201 {
8202   gboolean select_multiple;
8203
8204   select_multiple = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
8205   gtk_file_selection_set_select_multiple (fs, select_multiple);
8206 }
8207
8208 void
8209 file_selection_ok (GtkFileSelection *fs)
8210 {
8211   int i;
8212   gchar **selections;
8213
8214   selections = gtk_file_selection_get_selections (fs);
8215
8216   for (i = 0; selections[i] != NULL; i++)
8217     g_print ("%s\n", selections[i]);
8218
8219   g_strfreev (selections);
8220
8221   gtk_widget_destroy (GTK_WIDGET (fs));
8222 }
8223
8224 void
8225 create_file_selection (GtkWidget *widget)
8226 {
8227   static GtkWidget *window = NULL;
8228   GtkWidget *button;
8229
8230   if (!window)
8231     {
8232       window = gtk_file_selection_new ("file selection dialog");
8233       gtk_window_set_screen (GTK_WINDOW (window),
8234                              gtk_widget_get_screen (widget));
8235
8236       gtk_file_selection_hide_fileop_buttons (GTK_FILE_SELECTION (window));
8237
8238       gtk_window_set_position (GTK_WINDOW (window), GTK_WIN_POS_MOUSE);
8239
8240       g_signal_connect (window, "destroy",
8241                         G_CALLBACK (gtk_widget_destroyed),
8242                         &window);
8243
8244       g_signal_connect_swapped (GTK_FILE_SELECTION (window)->ok_button,
8245                                 "clicked",
8246                                 G_CALLBACK (file_selection_ok),
8247                                 window);
8248       g_signal_connect_swapped (GTK_FILE_SELECTION (window)->cancel_button,
8249                                 "clicked",
8250                                 G_CALLBACK (gtk_widget_destroy),
8251                                 window);
8252       
8253       button = gtk_check_button_new_with_label ("Show Fileops");
8254       g_signal_connect (button, "toggled",
8255                         G_CALLBACK (show_fileops),
8256                         window);
8257       gtk_box_pack_start (GTK_BOX (GTK_FILE_SELECTION (window)->action_area), 
8258                           button, FALSE, FALSE, 0);
8259       gtk_widget_show (button);
8260
8261       button = gtk_check_button_new_with_label ("Select Multiple");
8262       g_signal_connect (button, "clicked",
8263                         G_CALLBACK (select_multiple),
8264                         window);
8265       gtk_box_pack_start (GTK_BOX (GTK_FILE_SELECTION (window)->action_area), 
8266                           button, FALSE, FALSE, 0);
8267       gtk_widget_show (button);
8268     }
8269   
8270   if (!GTK_WIDGET_VISIBLE (window))
8271     gtk_widget_show (window);
8272   else
8273     gtk_widget_destroy (window);
8274 }
8275
8276 void
8277 flipping_toggled_cb (GtkWidget *widget, gpointer data)
8278 {
8279   int state = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
8280   int new_direction = state ? GTK_TEXT_DIR_RTL : GTK_TEXT_DIR_LTR;
8281
8282   gtk_widget_set_default_direction (new_direction);
8283 }
8284
8285 static void
8286 orientable_toggle_orientation (GtkOrientable *orientable)
8287 {
8288   GtkOrientation orientation;
8289
8290   orientation = gtk_orientable_get_orientation (orientable);
8291   gtk_orientable_set_orientation (orientable,
8292                                   orientation == GTK_ORIENTATION_HORIZONTAL ?
8293                                   GTK_ORIENTATION_VERTICAL :
8294                                   GTK_ORIENTATION_HORIZONTAL);
8295
8296   if (GTK_IS_CONTAINER (orientable))
8297     {
8298       GList *children;
8299       GList *child;
8300
8301       children = gtk_container_get_children (GTK_CONTAINER (orientable));
8302
8303       for (child = children; child; child = child->next)
8304         {
8305           if (GTK_IS_ORIENTABLE (child->data))
8306             orientable_toggle_orientation (child->data);
8307         }
8308
8309       g_list_free (children);
8310     }
8311 }
8312
8313 void
8314 flipping_orientation_toggled_cb (GtkWidget *widget, gpointer data)
8315 {
8316   orientable_toggle_orientation (GTK_ORIENTABLE (GTK_DIALOG (gtk_widget_get_toplevel (widget))->vbox));
8317 }
8318
8319 static void
8320 set_direction_recurse (GtkWidget *widget,
8321                        gpointer   data)
8322 {
8323   GtkTextDirection *dir = data;
8324   
8325   gtk_widget_set_direction (widget, *dir);
8326   if (GTK_IS_CONTAINER (widget))
8327     gtk_container_foreach (GTK_CONTAINER (widget),
8328                            set_direction_recurse,
8329                            data);
8330 }
8331
8332 static GtkWidget *
8333 create_forward_back (const char       *title,
8334                      GtkTextDirection  text_dir)
8335 {
8336   GtkWidget *frame = gtk_frame_new (title);
8337   GtkWidget *bbox = gtk_hbutton_box_new ();
8338   GtkWidget *back_button = gtk_button_new_from_stock (GTK_STOCK_GO_BACK);
8339   GtkWidget *forward_button = gtk_button_new_from_stock (GTK_STOCK_GO_FORWARD);
8340
8341   gtk_container_set_border_width (GTK_CONTAINER (bbox), 5);
8342   
8343   gtk_container_add (GTK_CONTAINER (frame), bbox);
8344   gtk_container_add (GTK_CONTAINER (bbox), back_button);
8345   gtk_container_add (GTK_CONTAINER (bbox), forward_button);
8346
8347   set_direction_recurse (frame, &text_dir);
8348
8349   return frame;
8350 }
8351
8352 void
8353 create_flipping (GtkWidget *widget)
8354 {
8355   static GtkWidget *window = NULL;
8356   GtkWidget *check_button, *button;
8357
8358   if (!window)
8359     {
8360       window = gtk_dialog_new ();
8361
8362       gtk_window_set_screen (GTK_WINDOW (window),
8363                              gtk_widget_get_screen (widget));
8364
8365       g_signal_connect (window, "destroy",
8366                         G_CALLBACK (gtk_widget_destroyed),
8367                         &window);
8368
8369       gtk_window_set_title (GTK_WINDOW (window), "Bidirectional Flipping");
8370
8371       check_button = gtk_check_button_new_with_label ("Right-to-left global direction");
8372       gtk_container_set_border_width (GTK_CONTAINER (check_button), 10);
8373       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox),
8374                           check_button, TRUE, TRUE, 0);
8375
8376       if (gtk_widget_get_default_direction () == GTK_TEXT_DIR_RTL)
8377         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button), TRUE);
8378
8379       g_signal_connect (check_button, "toggled",
8380                         G_CALLBACK (flipping_toggled_cb), NULL);
8381
8382       check_button = gtk_check_button_new_with_label ("Toggle orientation of all boxes");
8383       gtk_container_set_border_width (GTK_CONTAINER (check_button), 10);
8384       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
8385                           check_button, TRUE, TRUE, 0);
8386
8387       g_signal_connect (check_button, "toggled",
8388                         G_CALLBACK (flipping_orientation_toggled_cb), NULL);
8389
8390       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
8391                           create_forward_back ("Default", GTK_TEXT_DIR_NONE),
8392                           TRUE, TRUE, 0);
8393
8394       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
8395                           create_forward_back ("Left-to-Right", GTK_TEXT_DIR_LTR),
8396                           TRUE, TRUE, 0);
8397
8398       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
8399                           create_forward_back ("Right-to-Left", GTK_TEXT_DIR_RTL),
8400                           TRUE, TRUE, 0);
8401
8402       button = gtk_button_new_with_label ("Close");
8403       g_signal_connect_swapped (button, "clicked",
8404                                 G_CALLBACK (gtk_widget_destroy), window);
8405       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
8406                           button, TRUE, TRUE, 0);
8407     }
8408   
8409   if (!GTK_WIDGET_VISIBLE (window))
8410     gtk_widget_show_all (window);
8411   else
8412     gtk_widget_destroy (window);
8413 }
8414
8415 /*
8416  * Focus test
8417  */
8418
8419 static GtkWidget*
8420 make_focus_table (GList **list)
8421 {
8422   GtkWidget *table;
8423   gint i, j;
8424   
8425   table = gtk_table_new (5, 5, FALSE);
8426
8427   i = 0;
8428   j = 0;
8429
8430   while (i < 5)
8431     {
8432       j = 0;
8433       while (j < 5)
8434         {
8435           GtkWidget *widget;
8436           
8437           if ((i + j) % 2)
8438             widget = gtk_entry_new ();
8439           else
8440             widget = gtk_button_new_with_label ("Foo");
8441
8442           *list = g_list_prepend (*list, widget);
8443           
8444           gtk_table_attach (GTK_TABLE (table),
8445                             widget,
8446                             i, i + 1,
8447                             j, j + 1,
8448                             GTK_EXPAND | GTK_FILL,
8449                             GTK_EXPAND | GTK_FILL,
8450                             5, 5);
8451           
8452           ++j;
8453         }
8454
8455       ++i;
8456     }
8457
8458   *list = g_list_reverse (*list);
8459   
8460   return table;
8461 }
8462
8463 static void
8464 create_focus (GtkWidget *widget)
8465 {
8466   static GtkWidget *window = NULL;
8467   
8468   if (!window)
8469     {
8470       GtkWidget *table;
8471       GtkWidget *frame;
8472       GList *list = NULL;
8473       
8474       window = gtk_dialog_new_with_buttons ("Keyboard focus navigation",
8475                                             NULL, 0,
8476                                             GTK_STOCK_CLOSE,
8477                                             GTK_RESPONSE_NONE,
8478                                             NULL);
8479
8480       gtk_window_set_screen (GTK_WINDOW (window),
8481                              gtk_widget_get_screen (widget));
8482
8483       g_signal_connect (window, "destroy",
8484                         G_CALLBACK (gtk_widget_destroyed),
8485                         &window);
8486
8487       g_signal_connect (window, "response",
8488                         G_CALLBACK (gtk_widget_destroy),
8489                         NULL);
8490       
8491       gtk_window_set_title (GTK_WINDOW (window), "Keyboard Focus Navigation");
8492
8493       frame = gtk_frame_new ("Weird tab focus chain");
8494
8495       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
8496                           frame, TRUE, TRUE, 0);
8497       
8498       table = make_focus_table (&list);
8499
8500       gtk_container_add (GTK_CONTAINER (frame), table);
8501
8502       gtk_container_set_focus_chain (GTK_CONTAINER (table),
8503                                      list);
8504
8505       g_list_free (list);
8506       
8507       frame = gtk_frame_new ("Default tab focus chain");
8508
8509       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
8510                           frame, TRUE, TRUE, 0);
8511
8512       list = NULL;
8513       table = make_focus_table (&list);
8514
8515       g_list_free (list);
8516       
8517       gtk_container_add (GTK_CONTAINER (frame), table);      
8518     }
8519   
8520   if (!GTK_WIDGET_VISIBLE (window))
8521     gtk_widget_show_all (window);
8522   else
8523     gtk_widget_destroy (window);
8524 }
8525
8526 /*
8527  * GtkFontSelection
8528  */
8529
8530 void
8531 font_selection_ok (GtkWidget              *w,
8532                    GtkFontSelectionDialog *fs)
8533 {
8534   gchar *s = gtk_font_selection_dialog_get_font_name (fs);
8535
8536   g_print ("%s\n", s);
8537   g_free (s);
8538   gtk_widget_destroy (GTK_WIDGET (fs));
8539 }
8540
8541 void
8542 create_font_selection (GtkWidget *widget)
8543 {
8544   static GtkWidget *window = NULL;
8545
8546   if (!window)
8547     {
8548       GtkWidget *picker;
8549       GtkWidget *hbox;
8550       GtkWidget *label;
8551       
8552       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8553       gtk_window_set_screen (GTK_WINDOW (window),
8554                              gtk_widget_get_screen (widget));
8555
8556       g_signal_connect (window, "destroy",
8557                         G_CALLBACK (gtk_widget_destroyed),
8558                         &window);
8559
8560       gtk_window_set_title (GTK_WINDOW (window), "GtkFontButton");
8561       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
8562
8563       hbox = gtk_hbox_new (FALSE, 8);
8564       gtk_container_set_border_width (GTK_CONTAINER (hbox), 8);
8565       gtk_container_add (GTK_CONTAINER (window), hbox);
8566       
8567       label = gtk_label_new ("Pick a font");
8568       gtk_container_add (GTK_CONTAINER (hbox), label);
8569
8570       picker = gtk_font_button_new ();
8571       gtk_font_button_set_use_font (GTK_FONT_BUTTON (picker), TRUE);
8572       gtk_container_add (GTK_CONTAINER (hbox), picker);
8573     }
8574   
8575   if (!GTK_WIDGET_VISIBLE (window))
8576     gtk_widget_show_all (window);
8577   else
8578     gtk_widget_destroy (window);
8579 }
8580
8581 /*
8582  * GtkDialog
8583  */
8584
8585 static GtkWidget *dialog_window = NULL;
8586
8587 static void
8588 label_toggle (GtkWidget  *widget,
8589               GtkWidget **label)
8590 {
8591   if (!(*label))
8592     {
8593       *label = gtk_label_new ("Dialog Test");
8594       g_signal_connect (*label,
8595                         "destroy",
8596                         G_CALLBACK (gtk_widget_destroyed),
8597                         label);
8598       gtk_misc_set_padding (GTK_MISC (*label), 10, 10);
8599       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog_window)->vbox), 
8600                           *label, TRUE, TRUE, 0);
8601       gtk_widget_show (*label);
8602     }
8603   else
8604     gtk_widget_destroy (*label);
8605 }
8606
8607 #define RESPONSE_TOGGLE_SEPARATOR 1
8608
8609 static void
8610 print_response (GtkWidget *dialog,
8611                 gint       response_id,
8612                 gpointer   data)
8613 {
8614   g_print ("response signal received (%d)\n", response_id);
8615
8616   if (response_id == RESPONSE_TOGGLE_SEPARATOR)
8617     {
8618       gtk_dialog_set_has_separator (GTK_DIALOG (dialog),
8619                                     !gtk_dialog_get_has_separator (GTK_DIALOG (dialog)));
8620     }
8621 }
8622
8623 static void
8624 create_dialog (GtkWidget *widget)
8625 {
8626   static GtkWidget *label;
8627   GtkWidget *button;
8628
8629   if (!dialog_window)
8630     {
8631       /* This is a terrible example; it's much simpler to create
8632        * dialogs than this. Don't use testgtk for example code,
8633        * use gtk-demo ;-)
8634        */
8635       
8636       dialog_window = gtk_dialog_new ();
8637       gtk_window_set_screen (GTK_WINDOW (dialog_window),
8638                              gtk_widget_get_screen (widget));
8639
8640       g_signal_connect (dialog_window,
8641                         "response",
8642                         G_CALLBACK (print_response),
8643                         NULL);
8644       
8645       g_signal_connect (dialog_window, "destroy",
8646                         G_CALLBACK (gtk_widget_destroyed),
8647                         &dialog_window);
8648
8649       gtk_window_set_title (GTK_WINDOW (dialog_window), "GtkDialog");
8650       gtk_container_set_border_width (GTK_CONTAINER (dialog_window), 0);
8651
8652       button = gtk_button_new_with_label ("OK");
8653       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
8654       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog_window)->action_area), 
8655                           button, TRUE, TRUE, 0);
8656       gtk_widget_grab_default (button);
8657       gtk_widget_show (button);
8658
8659       button = gtk_button_new_with_label ("Toggle");
8660       g_signal_connect (button, "clicked",
8661                         G_CALLBACK (label_toggle),
8662                         &label);
8663       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
8664       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog_window)->action_area),
8665                           button, TRUE, TRUE, 0);
8666       gtk_widget_show (button);
8667
8668       label = NULL;
8669       
8670       button = gtk_button_new_with_label ("Separator");
8671
8672       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
8673
8674       gtk_dialog_add_action_widget (GTK_DIALOG (dialog_window),
8675                                     button,
8676                                     RESPONSE_TOGGLE_SEPARATOR);
8677       gtk_widget_show (button);
8678     }
8679
8680   if (!GTK_WIDGET_VISIBLE (dialog_window))
8681     gtk_widget_show (dialog_window);
8682   else
8683     gtk_widget_destroy (dialog_window);
8684 }
8685
8686 /* Display & Screen test 
8687  */
8688
8689 typedef struct 
8690
8691   GtkEntry *entry;
8692   GtkWidget *radio_dpy;
8693   GtkWidget *toplevel; 
8694   GtkWidget *dialog_window;
8695   GList *valid_display_list;
8696 } ScreenDisplaySelection;
8697
8698 static gint
8699 display_name_cmp (gconstpointer a,
8700                   gconstpointer b)
8701 {
8702   return g_ascii_strcasecmp (a,b);
8703 }
8704
8705 static void
8706 screen_display_check (GtkWidget *widget, ScreenDisplaySelection *data)
8707 {
8708   char *display_name;
8709   GdkDisplay *display = gtk_widget_get_display (widget);
8710   GtkWidget *dialog;
8711   GdkScreen *new_screen = NULL;
8712   GdkScreen *current_screen = gtk_widget_get_screen (widget);
8713   
8714   if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (data->radio_dpy)))
8715     {
8716       display_name = g_strdup (gtk_entry_get_text (data->entry));
8717       display = gdk_display_open (display_name);
8718       
8719       if (!display)
8720         {
8721           dialog = gtk_message_dialog_new (GTK_WINDOW (gtk_widget_get_toplevel (widget)),
8722                                            GTK_DIALOG_DESTROY_WITH_PARENT,
8723                                            GTK_MESSAGE_ERROR,
8724                                            GTK_BUTTONS_OK,
8725                                            "The display :\n%s\ncannot be opened",
8726                                            display_name);
8727           gtk_window_set_screen (GTK_WINDOW (dialog), current_screen);
8728           gtk_widget_show (dialog);
8729           g_signal_connect (dialog, "response",
8730                             G_CALLBACK (gtk_widget_destroy),
8731                             NULL);
8732         }
8733       else
8734         {
8735           if (!g_list_find_custom (data->valid_display_list, 
8736                                    display_name,
8737                                    display_name_cmp))
8738             data->valid_display_list = g_list_append (data->valid_display_list,
8739                                                       display_name);
8740           
8741           new_screen = gdk_display_get_default_screen (display);
8742         }
8743     }
8744   else
8745     {
8746       gint number_of_screens = gdk_display_get_n_screens (display);
8747       gint screen_num = gdk_screen_get_number (current_screen);
8748       if ((screen_num +1) < number_of_screens)
8749         new_screen = gdk_display_get_screen (display, screen_num + 1);
8750       else
8751         new_screen = gdk_display_get_screen (display, 0);
8752     }
8753   
8754   if (new_screen) 
8755     {
8756       gtk_window_set_screen (GTK_WINDOW (data->toplevel), new_screen);
8757       gtk_widget_destroy (data->dialog_window);
8758     }
8759 }
8760
8761 void
8762 screen_display_destroy_diag (GtkWidget *widget, GtkWidget *data)
8763 {
8764   gtk_widget_destroy (data);
8765 }
8766
8767 void
8768 create_display_screen (GtkWidget *widget)
8769 {
8770   GtkWidget *table, *frame, *window, *combo_dpy, *vbox;
8771   GtkWidget *radio_dpy, *radio_scr, *applyb, *cancelb;
8772   GtkWidget *bbox;
8773   ScreenDisplaySelection *scr_dpy_data;
8774   GdkScreen *screen = gtk_widget_get_screen (widget);
8775   static GList *valid_display_list = NULL;
8776   
8777   GdkDisplay *display = gdk_screen_get_display (screen);
8778
8779   window = g_object_new (gtk_window_get_type (),
8780                            "screen", screen,
8781                            "user_data", NULL,
8782                            "type", GTK_WINDOW_TOPLEVEL,
8783                            "title",
8784                            "Screen or Display selection",
8785                            "border_width", 10, NULL);
8786   g_signal_connect (window, "destroy", 
8787                     G_CALLBACK (gtk_widget_destroy), NULL);
8788
8789   vbox = gtk_vbox_new (FALSE, 3);
8790   gtk_container_add (GTK_CONTAINER (window), vbox);
8791   
8792   frame = gtk_frame_new ("Select screen or display");
8793   gtk_container_add (GTK_CONTAINER (vbox), frame);
8794   
8795   table = gtk_table_new (2, 2, TRUE);
8796   gtk_table_set_row_spacings (GTK_TABLE (table), 3);
8797   gtk_table_set_col_spacings (GTK_TABLE (table), 3);
8798
8799   gtk_container_add (GTK_CONTAINER (frame), table);
8800
8801   radio_dpy = gtk_radio_button_new_with_label (NULL, "move to another X display");
8802   if (gdk_display_get_n_screens(display) > 1)
8803     radio_scr = gtk_radio_button_new_with_label 
8804     (gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio_dpy)), "move to next screen");
8805   else
8806     {    
8807       radio_scr = gtk_radio_button_new_with_label 
8808         (gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio_dpy)), 
8809          "only one screen on the current display");
8810       gtk_widget_set_sensitive (radio_scr, FALSE);
8811     }
8812   combo_dpy = gtk_combo_new ();
8813   if (!valid_display_list)
8814     valid_display_list = g_list_append (valid_display_list, "diabolo:0.0");
8815     
8816   gtk_combo_set_popdown_strings (GTK_COMBO (combo_dpy), valid_display_list);
8817     
8818   gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (combo_dpy)->entry), 
8819                       "<hostname>:<X Server Num>.<Screen Num>");
8820
8821   gtk_table_attach_defaults (GTK_TABLE (table), radio_dpy, 0, 1, 0, 1);
8822   gtk_table_attach_defaults (GTK_TABLE (table), radio_scr, 0, 1, 1, 2);
8823   gtk_table_attach_defaults (GTK_TABLE (table), combo_dpy, 1, 2, 0, 1);
8824
8825   bbox = gtk_hbutton_box_new ();
8826   applyb = gtk_button_new_from_stock (GTK_STOCK_APPLY);
8827   cancelb = gtk_button_new_from_stock (GTK_STOCK_CANCEL);
8828   
8829   gtk_container_add (GTK_CONTAINER (vbox), bbox);
8830
8831   gtk_container_add (GTK_CONTAINER (bbox), applyb);
8832   gtk_container_add (GTK_CONTAINER (bbox), cancelb);
8833
8834   scr_dpy_data = g_new0 (ScreenDisplaySelection, 1);
8835
8836   scr_dpy_data->entry = GTK_ENTRY (GTK_COMBO (combo_dpy)->entry);
8837   scr_dpy_data->radio_dpy = radio_dpy;
8838   scr_dpy_data->toplevel = gtk_widget_get_toplevel (widget);
8839   scr_dpy_data->dialog_window = window;
8840   scr_dpy_data->valid_display_list = valid_display_list;
8841
8842   g_signal_connect (cancelb, "clicked", 
8843                     G_CALLBACK (screen_display_destroy_diag), window);
8844   g_signal_connect (applyb, "clicked", 
8845                     G_CALLBACK (screen_display_check), scr_dpy_data);
8846   gtk_widget_show_all (window);
8847 }
8848
8849 /* Event Watcher
8850  */
8851 static gboolean event_watcher_enter_id = 0;
8852 static gboolean event_watcher_leave_id = 0;
8853
8854 static gboolean
8855 event_watcher (GSignalInvocationHint *ihint,
8856                guint                  n_param_values,
8857                const GValue          *param_values,
8858                gpointer               data)
8859 {
8860   g_print ("Watch: \"%s\" emitted for %s\n",
8861            g_signal_name (ihint->signal_id),
8862            G_OBJECT_TYPE_NAME (g_value_get_object (param_values + 0)));
8863
8864   return TRUE;
8865 }
8866
8867 static void
8868 event_watcher_down (void)
8869 {
8870   if (event_watcher_enter_id)
8871     {
8872       guint signal_id;
8873
8874       signal_id = g_signal_lookup ("enter_notify_event", GTK_TYPE_WIDGET);
8875       g_signal_remove_emission_hook (signal_id, event_watcher_enter_id);
8876       event_watcher_enter_id = 0;
8877       signal_id = g_signal_lookup ("leave_notify_event", GTK_TYPE_WIDGET);
8878       g_signal_remove_emission_hook (signal_id, event_watcher_leave_id);
8879       event_watcher_leave_id = 0;
8880     }
8881 }
8882
8883 static void
8884 event_watcher_toggle (void)
8885 {
8886   if (event_watcher_enter_id)
8887     event_watcher_down ();
8888   else
8889     {
8890       guint signal_id;
8891
8892       signal_id = g_signal_lookup ("enter_notify_event", GTK_TYPE_WIDGET);
8893       event_watcher_enter_id = g_signal_add_emission_hook (signal_id, 0, event_watcher, NULL, NULL);
8894       signal_id = g_signal_lookup ("leave_notify_event", GTK_TYPE_WIDGET);
8895       event_watcher_leave_id = g_signal_add_emission_hook (signal_id, 0, event_watcher, NULL, NULL);
8896     }
8897 }
8898
8899 static void
8900 create_event_watcher (GtkWidget *widget)
8901 {
8902   GtkWidget *button;
8903
8904   if (!dialog_window)
8905     {
8906       dialog_window = gtk_dialog_new ();
8907       gtk_window_set_screen (GTK_WINDOW (dialog_window),
8908                              gtk_widget_get_screen (widget));
8909
8910       g_signal_connect (dialog_window, "destroy",
8911                         G_CALLBACK (gtk_widget_destroyed),
8912                         &dialog_window);
8913       g_signal_connect (dialog_window, "destroy",
8914                         G_CALLBACK (event_watcher_down),
8915                         NULL);
8916
8917       gtk_window_set_title (GTK_WINDOW (dialog_window), "Event Watcher");
8918       gtk_container_set_border_width (GTK_CONTAINER (dialog_window), 0);
8919       gtk_widget_set_size_request (dialog_window, 200, 110);
8920
8921       button = gtk_toggle_button_new_with_label ("Activate Watch");
8922       g_signal_connect (button, "clicked",
8923                         G_CALLBACK (event_watcher_toggle),
8924                         NULL);
8925       gtk_container_set_border_width (GTK_CONTAINER (button), 10);
8926       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog_window)->vbox), 
8927                           button, TRUE, TRUE, 0);
8928       gtk_widget_show (button);
8929
8930       button = gtk_button_new_with_label ("Close");
8931       g_signal_connect_swapped (button, "clicked",
8932                                 G_CALLBACK (gtk_widget_destroy),
8933                                 dialog_window);
8934       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
8935       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog_window)->action_area),
8936                           button, TRUE, TRUE, 0);
8937       gtk_widget_grab_default (button);
8938       gtk_widget_show (button);
8939     }
8940
8941   if (!GTK_WIDGET_VISIBLE (dialog_window))
8942     gtk_widget_show (dialog_window);
8943   else
8944     gtk_widget_destroy (dialog_window);
8945 }
8946
8947 /*
8948  * GtkRange
8949  */
8950
8951 static gchar*
8952 reformat_value (GtkScale *scale,
8953                 gdouble   value)
8954 {
8955   return g_strdup_printf ("-->%0.*g<--",
8956                           gtk_scale_get_digits (scale), value);
8957 }
8958
8959 static void
8960 create_range_controls (GtkWidget *widget)
8961 {
8962   static GtkWidget *window = NULL;
8963   GtkWidget *box1;
8964   GtkWidget *box2;
8965   GtkWidget *button;
8966   GtkWidget *scrollbar;
8967   GtkWidget *scale;
8968   GtkWidget *separator;
8969   GtkObject *adjustment;
8970   GtkWidget *hbox;
8971
8972   if (!window)
8973     {
8974       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8975
8976       gtk_window_set_screen (GTK_WINDOW (window),
8977                              gtk_widget_get_screen (widget));
8978
8979       g_signal_connect (window, "destroy",
8980                         G_CALLBACK (gtk_widget_destroyed),
8981                         &window);
8982
8983       gtk_window_set_title (GTK_WINDOW (window), "range controls");
8984       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
8985
8986
8987       box1 = gtk_vbox_new (FALSE, 0);
8988       gtk_container_add (GTK_CONTAINER (window), box1);
8989       gtk_widget_show (box1);
8990
8991
8992       box2 = gtk_vbox_new (FALSE, 10);
8993       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
8994       gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
8995       gtk_widget_show (box2);
8996
8997
8998       adjustment = gtk_adjustment_new (0.0, 0.0, 101.0, 0.1, 1.0, 1.0);
8999
9000       scale = gtk_hscale_new (GTK_ADJUSTMENT (adjustment));
9001       gtk_widget_set_size_request (GTK_WIDGET (scale), 150, -1);
9002       gtk_range_set_update_policy (GTK_RANGE (scale), GTK_UPDATE_DELAYED);
9003       gtk_scale_set_digits (GTK_SCALE (scale), 1);
9004       gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE);
9005       gtk_box_pack_start (GTK_BOX (box2), scale, TRUE, TRUE, 0);
9006       gtk_widget_show (scale);
9007
9008       scrollbar = gtk_hscrollbar_new (GTK_ADJUSTMENT (adjustment));
9009       gtk_range_set_update_policy (GTK_RANGE (scrollbar), 
9010                                    GTK_UPDATE_CONTINUOUS);
9011       gtk_box_pack_start (GTK_BOX (box2), scrollbar, TRUE, TRUE, 0);
9012       gtk_widget_show (scrollbar);
9013
9014       scale = gtk_hscale_new (GTK_ADJUSTMENT (adjustment));
9015       gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE);
9016       g_signal_connect (scale,
9017                         "format_value",
9018                         G_CALLBACK (reformat_value),
9019                         NULL);
9020       gtk_box_pack_start (GTK_BOX (box2), scale, TRUE, TRUE, 0);
9021       gtk_widget_show (scale);
9022       
9023       hbox = gtk_hbox_new (FALSE, 0);
9024
9025       scale = gtk_vscale_new (GTK_ADJUSTMENT (adjustment));
9026       gtk_widget_set_size_request (scale, -1, 200);
9027       gtk_scale_set_digits (GTK_SCALE (scale), 2);
9028       gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE);
9029       gtk_box_pack_start (GTK_BOX (hbox), scale, TRUE, TRUE, 0);
9030       gtk_widget_show (scale);
9031
9032       scale = gtk_vscale_new (GTK_ADJUSTMENT (adjustment));
9033       gtk_widget_set_size_request (scale, -1, 200);
9034       gtk_scale_set_digits (GTK_SCALE (scale), 2);
9035       gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE);
9036       gtk_range_set_inverted (GTK_RANGE (scale), TRUE);
9037       gtk_box_pack_start (GTK_BOX (hbox), scale, TRUE, TRUE, 0);
9038       gtk_widget_show (scale);
9039
9040       scale = gtk_vscale_new (GTK_ADJUSTMENT (adjustment));
9041       gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE);
9042       g_signal_connect (scale,
9043                         "format_value",
9044                         G_CALLBACK (reformat_value),
9045                         NULL);
9046       gtk_box_pack_start (GTK_BOX (hbox), scale, TRUE, TRUE, 0);
9047       gtk_widget_show (scale);
9048
9049       
9050       gtk_box_pack_start (GTK_BOX (box2), hbox, TRUE, TRUE, 0);
9051       gtk_widget_show (hbox);
9052       
9053       separator = gtk_hseparator_new ();
9054       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
9055       gtk_widget_show (separator);
9056
9057
9058       box2 = gtk_vbox_new (FALSE, 10);
9059       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
9060       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
9061       gtk_widget_show (box2);
9062
9063
9064       button = gtk_button_new_with_label ("close");
9065       g_signal_connect_swapped (button, "clicked",
9066                                 G_CALLBACK (gtk_widget_destroy),
9067                                 window);
9068       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
9069       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
9070       gtk_widget_grab_default (button);
9071       gtk_widget_show (button);
9072     }
9073
9074   if (!GTK_WIDGET_VISIBLE (window))
9075     gtk_widget_show (window);
9076   else
9077     gtk_widget_destroy (window);
9078 }
9079
9080 /*
9081  * GtkRulers
9082  */
9083
9084 void
9085 create_rulers (GtkWidget *widget)
9086 {
9087   static GtkWidget *window = NULL;
9088   GtkWidget *table;
9089   GtkWidget *ruler;
9090
9091   if (!window)
9092     {
9093       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9094
9095       gtk_window_set_screen (GTK_WINDOW (window),
9096                              gtk_widget_get_screen (widget));
9097
9098       g_object_set (window, "allow_shrink", TRUE, "allow_grow", TRUE, NULL);
9099
9100       g_signal_connect (window, "destroy",
9101                         G_CALLBACK (gtk_widget_destroyed),
9102                         &window);
9103
9104       gtk_window_set_title (GTK_WINDOW (window), "rulers");
9105       gtk_widget_set_size_request (window, 300, 300);
9106       gtk_widget_set_events (window, 
9107                              GDK_POINTER_MOTION_MASK 
9108                              | GDK_POINTER_MOTION_HINT_MASK);
9109       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
9110
9111       table = gtk_table_new (2, 2, FALSE);
9112       gtk_container_add (GTK_CONTAINER (window), table);
9113       gtk_widget_show (table);
9114
9115       ruler = gtk_hruler_new ();
9116       gtk_ruler_set_metric (GTK_RULER (ruler), GTK_CENTIMETERS);
9117       gtk_ruler_set_range (GTK_RULER (ruler), 100, 0, 0, 20);
9118
9119       g_signal_connect_swapped (window, 
9120                                 "motion_notify_event",
9121                                 G_CALLBACK (GTK_WIDGET_GET_CLASS (ruler)->motion_notify_event),
9122                                 ruler);
9123       
9124       gtk_table_attach (GTK_TABLE (table), ruler, 1, 2, 0, 1,
9125                         GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
9126       gtk_widget_show (ruler);
9127
9128
9129       ruler = gtk_vruler_new ();
9130       gtk_ruler_set_range (GTK_RULER (ruler), 5, 15, 0, 20);
9131
9132       g_signal_connect_swapped (window, 
9133                                 "motion_notify_event",
9134                                 G_CALLBACK (GTK_WIDGET_GET_CLASS (ruler)->motion_notify_event),
9135                                 ruler);
9136       
9137       gtk_table_attach (GTK_TABLE (table), ruler, 0, 1, 1, 2,
9138                         GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
9139       gtk_widget_show (ruler);
9140     }
9141
9142   if (!GTK_WIDGET_VISIBLE (window))
9143     gtk_widget_show (window);
9144   else
9145     gtk_widget_destroy (window);
9146 }
9147
9148 static void
9149 text_toggle_editable (GtkWidget *checkbutton,
9150                        GtkWidget *text)
9151 {
9152    gtk_text_set_editable(GTK_TEXT(text),
9153                           GTK_TOGGLE_BUTTON(checkbutton)->active);
9154 }
9155
9156 static void
9157 text_toggle_word_wrap (GtkWidget *checkbutton,
9158                        GtkWidget *text)
9159 {
9160    gtk_text_set_word_wrap(GTK_TEXT(text),
9161                           GTK_TOGGLE_BUTTON(checkbutton)->active);
9162 }
9163
9164 struct {
9165   GdkColor color;
9166   gchar *name;
9167 } text_colors[] = {
9168  { { 0, 0x0000, 0x0000, 0x0000 }, "black" },
9169  { { 0, 0xFFFF, 0xFFFF, 0xFFFF }, "white" },
9170  { { 0, 0xFFFF, 0x0000, 0x0000 }, "red" },
9171  { { 0, 0x0000, 0xFFFF, 0x0000 }, "green" },
9172  { { 0, 0x0000, 0x0000, 0xFFFF }, "blue" }, 
9173  { { 0, 0x0000, 0xFFFF, 0xFFFF }, "cyan" },
9174  { { 0, 0xFFFF, 0x0000, 0xFFFF }, "magenta" },
9175  { { 0, 0xFFFF, 0xFFFF, 0x0000 }, "yellow" }
9176 };
9177
9178 int ntext_colors = sizeof(text_colors) / sizeof(text_colors[0]);
9179
9180 /*
9181  * GtkText
9182  */
9183 void
9184 text_insert_random (GtkWidget *w, GtkText *text)
9185 {
9186   int i;
9187   char c;
9188    for (i=0; i<10; i++)
9189     {
9190       c = 'A' + rand() % ('Z' - 'A');
9191       gtk_text_set_point (text, rand() % gtk_text_get_length (text));
9192       gtk_text_insert (text, NULL, NULL, NULL, &c, 1);
9193     }
9194 }
9195
9196 void
9197 create_text (GtkWidget *widget)
9198 {
9199   int i, j;
9200
9201   static GtkWidget *window = NULL;
9202   GtkWidget *box1;
9203   GtkWidget *box2;
9204   GtkWidget *hbox;
9205   GtkWidget *button;
9206   GtkWidget *check;
9207   GtkWidget *separator;
9208   GtkWidget *scrolled_window;
9209   GtkWidget *text;
9210
9211   FILE *infile;
9212
9213   if (!window)
9214     {
9215       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9216       gtk_window_set_screen (GTK_WINDOW (window),
9217                              gtk_widget_get_screen (widget));
9218
9219       gtk_widget_set_name (window, "text window");
9220       g_object_set (window, "allow_shrink", TRUE, "allow_grow", TRUE, NULL);
9221       gtk_widget_set_size_request (window, 500, 500);
9222
9223       g_signal_connect (window, "destroy",
9224                         G_CALLBACK (gtk_widget_destroyed),
9225                         &window);
9226
9227       gtk_window_set_title (GTK_WINDOW (window), "test");
9228       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
9229
9230
9231       box1 = gtk_vbox_new (FALSE, 0);
9232       gtk_container_add (GTK_CONTAINER (window), box1);
9233       gtk_widget_show (box1);
9234
9235
9236       box2 = gtk_vbox_new (FALSE, 10);
9237       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
9238       gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
9239       gtk_widget_show (box2);
9240
9241
9242       scrolled_window = gtk_scrolled_window_new (NULL, NULL);
9243       gtk_box_pack_start (GTK_BOX (box2), scrolled_window, TRUE, TRUE, 0);
9244       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
9245                                       GTK_POLICY_NEVER,
9246                                       GTK_POLICY_ALWAYS);
9247       gtk_widget_show (scrolled_window);
9248
9249       text = gtk_text_new (NULL, NULL);
9250       gtk_text_set_editable (GTK_TEXT (text), TRUE);
9251       gtk_container_add (GTK_CONTAINER (scrolled_window), text);
9252       gtk_widget_grab_focus (text);
9253       gtk_widget_show (text);
9254
9255
9256       gtk_text_freeze (GTK_TEXT (text));
9257
9258       for (i=0; i<ntext_colors; i++)
9259         {
9260           gtk_text_insert (GTK_TEXT (text), NULL, NULL, NULL, 
9261                            text_colors[i].name, -1);
9262           gtk_text_insert (GTK_TEXT (text), NULL, NULL, NULL, "\t", -1);
9263
9264           for (j=0; j<ntext_colors; j++)
9265             {
9266               gtk_text_insert (GTK_TEXT (text), NULL,
9267                                &text_colors[j].color, &text_colors[i].color,
9268                                "XYZ", -1);
9269             }
9270           gtk_text_insert (GTK_TEXT (text), NULL, NULL, NULL, "\n", -1);
9271         }
9272
9273       infile = fopen("testgtk.c", "r");
9274       
9275       if (infile)
9276         {
9277           char *buffer;
9278           int nbytes_read, nbytes_alloc;
9279           
9280           nbytes_read = 0;
9281           nbytes_alloc = 1024;
9282           buffer = g_new (char, nbytes_alloc);
9283           while (1)
9284             {
9285               int len;
9286               if (nbytes_alloc < nbytes_read + 1024)
9287                 {
9288                   nbytes_alloc *= 2;
9289                   buffer = g_realloc (buffer, nbytes_alloc);
9290                 }
9291               len = fread (buffer + nbytes_read, 1, 1024, infile);
9292               nbytes_read += len;
9293               if (len < 1024)
9294                 break;
9295             }
9296           
9297           gtk_text_insert (GTK_TEXT (text), NULL, NULL,
9298                            NULL, buffer, nbytes_read);
9299           g_free(buffer);
9300           fclose (infile);
9301         }
9302       
9303       gtk_text_thaw (GTK_TEXT (text));
9304
9305       hbox = gtk_hbutton_box_new ();
9306       gtk_box_pack_start (GTK_BOX (box2), hbox, FALSE, FALSE, 0);
9307       gtk_widget_show (hbox);
9308
9309       check = gtk_check_button_new_with_label("Editable");
9310       gtk_box_pack_start (GTK_BOX (hbox), check, FALSE, FALSE, 0);
9311       g_signal_connect (check, "toggled",
9312                         G_CALLBACK (text_toggle_editable), text);
9313       gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), TRUE);
9314       gtk_widget_show (check);
9315
9316       check = gtk_check_button_new_with_label("Wrap Words");
9317       gtk_box_pack_start (GTK_BOX (hbox), check, FALSE, TRUE, 0);
9318       g_signal_connect (check, "toggled",
9319                         G_CALLBACK (text_toggle_word_wrap), text);
9320       gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), FALSE);
9321       gtk_widget_show (check);
9322
9323       separator = gtk_hseparator_new ();
9324       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
9325       gtk_widget_show (separator);
9326
9327
9328       box2 = gtk_vbox_new (FALSE, 10);
9329       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
9330       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
9331       gtk_widget_show (box2);
9332
9333
9334       button = gtk_button_new_with_label ("insert random");
9335       g_signal_connect (button, "clicked",
9336                         G_CALLBACK (text_insert_random),
9337                         text);
9338       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
9339       gtk_widget_show (button);
9340
9341       button = gtk_button_new_with_label ("close");
9342       g_signal_connect_swapped (button, "clicked",
9343                                 G_CALLBACK (gtk_widget_destroy),
9344                                 window);
9345       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
9346       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
9347       gtk_widget_grab_default (button);
9348       gtk_widget_show (button);
9349     }
9350
9351   if (!GTK_WIDGET_VISIBLE (window))
9352     gtk_widget_show (window);
9353   else
9354     gtk_widget_destroy (window);
9355 }
9356
9357 /*
9358  * GtkNotebook
9359  */
9360
9361 GdkPixbuf *book_open;
9362 GdkPixbuf *book_closed;
9363 GtkWidget *sample_notebook;
9364
9365 static void
9366 set_page_image (GtkNotebook *notebook, gint page_num, GdkPixbuf *pixbuf)
9367 {
9368   GtkWidget *page_widget;
9369   GtkWidget *pixwid;
9370
9371   page_widget = gtk_notebook_get_nth_page (notebook, page_num);
9372
9373   pixwid = g_object_get_data (G_OBJECT (page_widget), "tab_pixmap");
9374   gtk_image_set_from_pixbuf (GTK_IMAGE (pixwid), pixbuf);
9375   
9376   pixwid = g_object_get_data (G_OBJECT (page_widget), "menu_pixmap");
9377   gtk_image_set_from_pixbuf (GTK_IMAGE (pixwid), pixbuf);
9378 }
9379
9380 static void
9381 page_switch (GtkWidget *widget, GtkNotebookPage *page, gint page_num)
9382 {
9383   GtkNotebook *notebook = GTK_NOTEBOOK (widget);
9384   gint old_page_num = gtk_notebook_get_current_page (notebook);
9385  
9386   if (page_num == old_page_num)
9387     return;
9388
9389   set_page_image (notebook, page_num, book_open);
9390
9391   if (old_page_num != -1)
9392     set_page_image (notebook, old_page_num, book_closed);
9393 }
9394
9395 static void
9396 tab_fill (GtkToggleButton *button, GtkWidget *child)
9397 {
9398   gboolean expand;
9399   GtkPackType pack_type;
9400
9401   gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (sample_notebook), child,
9402                                         &expand, NULL, &pack_type);
9403   gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (sample_notebook), child,
9404                                       expand, button->active, pack_type);
9405 }
9406
9407 static void
9408 tab_expand (GtkToggleButton *button, GtkWidget *child)
9409 {
9410   gboolean fill;
9411   GtkPackType pack_type;
9412
9413   gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (sample_notebook), child,
9414                                         NULL, &fill, &pack_type);
9415   gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (sample_notebook), child,
9416                                       button->active, fill, pack_type);
9417 }
9418
9419 static void
9420 tab_pack (GtkToggleButton *button, GtkWidget *child)
9421           
9422
9423   gboolean expand;
9424   gboolean fill;
9425
9426   gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (sample_notebook), child,
9427                                         &expand, &fill, NULL);
9428   gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (sample_notebook), child,
9429                                       expand, fill, button->active);
9430 }
9431
9432 static void
9433 create_pages (GtkNotebook *notebook, gint start, gint end)
9434 {
9435   GtkWidget *child = NULL;
9436   GtkWidget *button;
9437   GtkWidget *label;
9438   GtkWidget *hbox;
9439   GtkWidget *vbox;
9440   GtkWidget *label_box;
9441   GtkWidget *menu_box;
9442   GtkWidget *pixwid;
9443   gint i;
9444   char buffer[32];
9445   char accel_buffer[32];
9446
9447   for (i = start; i <= end; i++)
9448     {
9449       sprintf (buffer, "Page %d", i);
9450       sprintf (accel_buffer, "Page _%d", i);
9451
9452       child = gtk_frame_new (buffer);
9453       gtk_container_set_border_width (GTK_CONTAINER (child), 10);
9454
9455       vbox = gtk_vbox_new (TRUE,0);
9456       gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
9457       gtk_container_add (GTK_CONTAINER (child), vbox);
9458
9459       hbox = gtk_hbox_new (TRUE,0);
9460       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 5);
9461
9462       button = gtk_check_button_new_with_label ("Fill Tab");
9463       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
9464       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
9465       g_signal_connect (button, "toggled",
9466                         G_CALLBACK (tab_fill), child);
9467
9468       button = gtk_check_button_new_with_label ("Expand Tab");
9469       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
9470       g_signal_connect (button, "toggled",
9471                         G_CALLBACK (tab_expand), child);
9472
9473       button = gtk_check_button_new_with_label ("Pack end");
9474       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
9475       g_signal_connect (button, "toggled",
9476                         G_CALLBACK (tab_pack), child);
9477
9478       button = gtk_button_new_with_label ("Hide Page");
9479       gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 5);
9480       g_signal_connect_swapped (button, "clicked",
9481                                 G_CALLBACK (gtk_widget_hide),
9482                                 child);
9483
9484       gtk_widget_show_all (child);
9485
9486       label_box = gtk_hbox_new (FALSE, 0);
9487       pixwid = gtk_image_new_from_pixbuf (book_closed);
9488       g_object_set_data (G_OBJECT (child), "tab_pixmap", pixwid);
9489                            
9490       gtk_box_pack_start (GTK_BOX (label_box), pixwid, FALSE, TRUE, 0);
9491       gtk_misc_set_padding (GTK_MISC (pixwid), 3, 1);
9492       label = gtk_label_new_with_mnemonic (accel_buffer);
9493       gtk_box_pack_start (GTK_BOX (label_box), label, FALSE, TRUE, 0);
9494       gtk_widget_show_all (label_box);
9495       
9496                                        
9497       menu_box = gtk_hbox_new (FALSE, 0);
9498       pixwid = gtk_image_new_from_pixbuf (book_closed);
9499       g_object_set_data (G_OBJECT (child), "menu_pixmap", pixwid);
9500       
9501       gtk_box_pack_start (GTK_BOX (menu_box), pixwid, FALSE, TRUE, 0);
9502       gtk_misc_set_padding (GTK_MISC (pixwid), 3, 1);
9503       label = gtk_label_new (buffer);
9504       gtk_box_pack_start (GTK_BOX (menu_box), label, FALSE, TRUE, 0);
9505       gtk_widget_show_all (menu_box);
9506
9507       gtk_notebook_append_page_menu (notebook, child, label_box, menu_box);
9508     }
9509 }
9510
9511 static void
9512 rotate_notebook (GtkButton   *button,
9513                  GtkNotebook *notebook)
9514 {
9515   gtk_notebook_set_tab_pos (notebook, (notebook->tab_pos + 1) % 4);
9516 }
9517
9518 static void
9519 show_all_pages (GtkButton   *button,
9520                 GtkNotebook *notebook)
9521 {  
9522   gtk_container_foreach (GTK_CONTAINER (notebook),
9523                          (GtkCallback) gtk_widget_show, NULL);
9524 }
9525
9526 static void
9527 notebook_type_changed (GtkWidget *optionmenu,
9528                        gpointer   data)
9529 {
9530   GtkNotebook *notebook;
9531   gint i, c;
9532
9533   enum {
9534     STANDARD,
9535     NOTABS,
9536     BORDERLESS,
9537     SCROLLABLE
9538   };
9539
9540   notebook = GTK_NOTEBOOK (data);
9541
9542   c = gtk_option_menu_get_history (GTK_OPTION_MENU (optionmenu));
9543
9544   switch (c)
9545     {
9546     case STANDARD:
9547       /* standard notebook */
9548       gtk_notebook_set_show_tabs (notebook, TRUE);
9549       gtk_notebook_set_show_border (notebook, TRUE);
9550       gtk_notebook_set_scrollable (notebook, FALSE);
9551       break;
9552
9553     case NOTABS:
9554       /* notabs notebook */
9555       gtk_notebook_set_show_tabs (notebook, FALSE);
9556       gtk_notebook_set_show_border (notebook, TRUE);
9557       break;
9558
9559     case BORDERLESS:
9560       /* borderless */
9561       gtk_notebook_set_show_tabs (notebook, FALSE);
9562       gtk_notebook_set_show_border (notebook, FALSE);
9563       break;
9564
9565     case SCROLLABLE:  
9566       /* scrollable */
9567       gtk_notebook_set_show_tabs (notebook, TRUE);
9568       gtk_notebook_set_show_border (notebook, TRUE);
9569       gtk_notebook_set_scrollable (notebook, TRUE);
9570       if (g_list_length (notebook->children) == 5)
9571         create_pages (notebook, 6, 15);
9572       
9573       return;
9574       break;
9575     }
9576   
9577   if (g_list_length (notebook->children) == 15)
9578     for (i = 0; i < 10; i++)
9579       gtk_notebook_remove_page (notebook, 5);
9580 }
9581
9582 static void
9583 notebook_popup (GtkToggleButton *button,
9584                 GtkNotebook     *notebook)
9585 {
9586   if (button->active)
9587     gtk_notebook_popup_enable (notebook);
9588   else
9589     gtk_notebook_popup_disable (notebook);
9590 }
9591
9592 static void
9593 notebook_homogeneous (GtkToggleButton *button,
9594                       GtkNotebook     *notebook)
9595 {
9596   g_object_set (notebook, "homogeneous", button->active, NULL);
9597 }
9598
9599 static void
9600 create_notebook (GtkWidget *widget)
9601 {
9602   static GtkWidget *window = NULL;
9603   GtkWidget *box1;
9604   GtkWidget *box2;
9605   GtkWidget *button;
9606   GtkWidget *separator;
9607   GtkWidget *omenu;
9608   GtkWidget *label;
9609
9610   static gchar *items[] =
9611   {
9612     "Standard",
9613     "No tabs",
9614     "Borderless",
9615     "Scrollable"
9616   };
9617   
9618   if (!window)
9619     {
9620       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9621       gtk_window_set_screen (GTK_WINDOW (window),
9622                              gtk_widget_get_screen (widget));
9623
9624       g_signal_connect (window, "destroy",
9625                         G_CALLBACK (gtk_widget_destroyed),
9626                         &window);
9627
9628       gtk_window_set_title (GTK_WINDOW (window), "notebook");
9629       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
9630
9631       box1 = gtk_vbox_new (FALSE, 0);
9632       gtk_container_add (GTK_CONTAINER (window), box1);
9633
9634       sample_notebook = gtk_notebook_new ();
9635       g_signal_connect (sample_notebook, "switch_page",
9636                         G_CALLBACK (page_switch), NULL);
9637       gtk_notebook_set_tab_pos (GTK_NOTEBOOK (sample_notebook), GTK_POS_TOP);
9638       gtk_box_pack_start (GTK_BOX (box1), sample_notebook, TRUE, TRUE, 0);
9639       gtk_container_set_border_width (GTK_CONTAINER (sample_notebook), 10);
9640
9641       gtk_widget_realize (sample_notebook);
9642
9643       if (!book_open)
9644         book_open = gdk_pixbuf_new_from_xpm_data ((const char **)book_open_xpm);
9645                                                   
9646       if (!book_closed)
9647         book_closed = gdk_pixbuf_new_from_xpm_data ((const char **)book_closed_xpm);
9648
9649       create_pages (GTK_NOTEBOOK (sample_notebook), 1, 5);
9650
9651       separator = gtk_hseparator_new ();
9652       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 10);
9653       
9654       box2 = gtk_hbox_new (FALSE, 5);
9655       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
9656       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
9657
9658       button = gtk_check_button_new_with_label ("popup menu");
9659       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, FALSE, 0);
9660       g_signal_connect (button, "clicked",
9661                         G_CALLBACK (notebook_popup),
9662                         sample_notebook);
9663
9664       button = gtk_check_button_new_with_label ("homogeneous tabs");
9665       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, FALSE, 0);
9666       g_signal_connect (button, "clicked",
9667                         G_CALLBACK (notebook_homogeneous),
9668                         sample_notebook);
9669
9670       box2 = gtk_hbox_new (FALSE, 5);
9671       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
9672       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
9673
9674       label = gtk_label_new ("Notebook Style :");
9675       gtk_box_pack_start (GTK_BOX (box2), label, FALSE, TRUE, 0);
9676
9677       omenu = build_option_menu (items, G_N_ELEMENTS (items), 0,
9678                                  notebook_type_changed,
9679                                  sample_notebook);
9680       gtk_box_pack_start (GTK_BOX (box2), omenu, FALSE, TRUE, 0);
9681
9682       button = gtk_button_new_with_label ("Show all Pages");
9683       gtk_box_pack_start (GTK_BOX (box2), button, FALSE, TRUE, 0);
9684       g_signal_connect (button, "clicked",
9685                         G_CALLBACK (show_all_pages), sample_notebook);
9686
9687       box2 = gtk_hbox_new (TRUE, 10);
9688       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
9689       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
9690
9691       button = gtk_button_new_with_label ("prev");
9692       g_signal_connect_swapped (button, "clicked",
9693                                 G_CALLBACK (gtk_notebook_prev_page),
9694                                 sample_notebook);
9695       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
9696
9697       button = gtk_button_new_with_label ("next");
9698       g_signal_connect_swapped (button, "clicked",
9699                                 G_CALLBACK (gtk_notebook_next_page),
9700                                 sample_notebook);
9701       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
9702
9703       button = gtk_button_new_with_label ("rotate");
9704       g_signal_connect (button, "clicked",
9705                         G_CALLBACK (rotate_notebook), sample_notebook);
9706       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
9707
9708       separator = gtk_hseparator_new ();
9709       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
9710
9711       button = gtk_button_new_with_label ("close");
9712       gtk_container_set_border_width (GTK_CONTAINER (button), 5);
9713       g_signal_connect_swapped (button, "clicked",
9714                                 G_CALLBACK (gtk_widget_destroy),
9715                                 window);
9716       gtk_box_pack_start (GTK_BOX (box1), button, FALSE, FALSE, 0);
9717       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
9718       gtk_widget_grab_default (button);
9719     }
9720
9721   if (!GTK_WIDGET_VISIBLE (window))
9722     gtk_widget_show_all (window);
9723   else
9724     gtk_widget_destroy (window);
9725 }
9726
9727 /*
9728  * GtkPanes
9729  */
9730
9731 void
9732 toggle_resize (GtkWidget *widget, GtkWidget *child)
9733 {
9734   GtkContainer *container = GTK_CONTAINER (gtk_widget_get_parent (child));
9735   GValue value = { 0, };
9736   g_value_init (&value, G_TYPE_BOOLEAN);
9737   gtk_container_child_get_property (container, child, "resize", &value);
9738   g_value_set_boolean (&value, !g_value_get_boolean (&value));
9739   gtk_container_child_set_property (container, child, "resize", &value);
9740 }
9741
9742 void
9743 toggle_shrink (GtkWidget *widget, GtkWidget *child)
9744 {
9745   GtkContainer *container = GTK_CONTAINER (gtk_widget_get_parent (child));
9746   GValue value = { 0, };
9747   g_value_init (&value, G_TYPE_BOOLEAN);
9748   gtk_container_child_get_property (container, child, "shrink", &value);
9749   g_value_set_boolean (&value, !g_value_get_boolean (&value));
9750   gtk_container_child_set_property (container, child, "shrink", &value);
9751 }
9752
9753 static void
9754 paned_props_clicked (GtkWidget *button,
9755                      GObject   *paned)
9756 {
9757   GtkWidget *window = create_prop_editor (paned, GTK_TYPE_PANED);
9758   
9759   gtk_window_set_title (GTK_WINDOW (window), "Paned Properties");
9760 }
9761
9762 GtkWidget *
9763 create_pane_options (GtkPaned    *paned,
9764                      const gchar *frame_label,
9765                      const gchar *label1,
9766                      const gchar *label2)
9767 {
9768   GtkWidget *frame;
9769   GtkWidget *table;
9770   GtkWidget *label;
9771   GtkWidget *button;
9772   GtkWidget *check_button;
9773   
9774   frame = gtk_frame_new (frame_label);
9775   gtk_container_set_border_width (GTK_CONTAINER (frame), 4);
9776   
9777   table = gtk_table_new (4, 2, 4);
9778   gtk_container_add (GTK_CONTAINER (frame), table);
9779   
9780   label = gtk_label_new (label1);
9781   gtk_table_attach_defaults (GTK_TABLE (table), label,
9782                              0, 1, 0, 1);
9783   
9784   check_button = gtk_check_button_new_with_label ("Resize");
9785   gtk_table_attach_defaults (GTK_TABLE (table), check_button,
9786                              0, 1, 1, 2);
9787   g_signal_connect (check_button, "toggled",
9788                     G_CALLBACK (toggle_resize),
9789                     paned->child1);
9790   
9791   check_button = gtk_check_button_new_with_label ("Shrink");
9792   gtk_table_attach_defaults (GTK_TABLE (table), check_button,
9793                              0, 1, 2, 3);
9794   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button),
9795                                TRUE);
9796   g_signal_connect (check_button, "toggled",
9797                     G_CALLBACK (toggle_shrink),
9798                     paned->child1);
9799   
9800   label = gtk_label_new (label2);
9801   gtk_table_attach_defaults (GTK_TABLE (table), label,
9802                              1, 2, 0, 1);
9803   
9804   check_button = gtk_check_button_new_with_label ("Resize");
9805   gtk_table_attach_defaults (GTK_TABLE (table), check_button,
9806                              1, 2, 1, 2);
9807   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button),
9808                                TRUE);
9809   g_signal_connect (check_button, "toggled",
9810                     G_CALLBACK (toggle_resize),
9811                     paned->child2);
9812   
9813   check_button = gtk_check_button_new_with_label ("Shrink");
9814   gtk_table_attach_defaults (GTK_TABLE (table), check_button,
9815                              1, 2, 2, 3);
9816   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button),
9817                                TRUE);
9818   g_signal_connect (check_button, "toggled",
9819                     G_CALLBACK (toggle_shrink),
9820                     paned->child2);
9821
9822   button = gtk_button_new_with_mnemonic ("_Properties");
9823   gtk_table_attach_defaults (GTK_TABLE (table), button,
9824                              0, 2, 3, 4);
9825   g_signal_connect (button, "clicked",
9826                     G_CALLBACK (paned_props_clicked),
9827                     paned);
9828
9829   return frame;
9830 }
9831
9832 void
9833 create_panes (GtkWidget *widget)
9834 {
9835   static GtkWidget *window = NULL;
9836   GtkWidget *frame;
9837   GtkWidget *hpaned;
9838   GtkWidget *vpaned;
9839   GtkWidget *button;
9840   GtkWidget *vbox;
9841
9842   if (!window)
9843     {
9844       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9845
9846       gtk_window_set_screen (GTK_WINDOW (window),
9847                              gtk_widget_get_screen (widget));
9848       
9849       g_signal_connect (window, "destroy",
9850                         G_CALLBACK (gtk_widget_destroyed),
9851                         &window);
9852
9853       gtk_window_set_title (GTK_WINDOW (window), "Panes");
9854       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
9855
9856       vbox = gtk_vbox_new (FALSE, 0);
9857       gtk_container_add (GTK_CONTAINER (window), vbox);
9858       
9859       vpaned = gtk_vpaned_new ();
9860       gtk_box_pack_start (GTK_BOX (vbox), vpaned, TRUE, TRUE, 0);
9861       gtk_container_set_border_width (GTK_CONTAINER(vpaned), 5);
9862
9863       hpaned = gtk_hpaned_new ();
9864       gtk_paned_add1 (GTK_PANED (vpaned), hpaned);
9865
9866       frame = gtk_frame_new (NULL);
9867       gtk_frame_set_shadow_type (GTK_FRAME(frame), GTK_SHADOW_IN);
9868       gtk_widget_set_size_request (frame, 60, 60);
9869       gtk_paned_add1 (GTK_PANED (hpaned), frame);
9870       
9871       button = gtk_button_new_with_label ("Hi there");
9872       gtk_container_add (GTK_CONTAINER(frame), button);
9873
9874       frame = gtk_frame_new (NULL);
9875       gtk_frame_set_shadow_type (GTK_FRAME(frame), GTK_SHADOW_IN);
9876       gtk_widget_set_size_request (frame, 80, 60);
9877       gtk_paned_add2 (GTK_PANED (hpaned), frame);
9878
9879       frame = gtk_frame_new (NULL);
9880       gtk_frame_set_shadow_type (GTK_FRAME(frame), GTK_SHADOW_IN);
9881       gtk_widget_set_size_request (frame, 60, 80);
9882       gtk_paned_add2 (GTK_PANED (vpaned), frame);
9883
9884       /* Now create toggle buttons to control sizing */
9885
9886       gtk_box_pack_start (GTK_BOX (vbox),
9887                           create_pane_options (GTK_PANED (hpaned),
9888                                                "Horizontal",
9889                                                "Left",
9890                                                "Right"),
9891                           FALSE, FALSE, 0);
9892
9893       gtk_box_pack_start (GTK_BOX (vbox),
9894                           create_pane_options (GTK_PANED (vpaned),
9895                                                "Vertical",
9896                                                "Top",
9897                                                "Bottom"),
9898                           FALSE, FALSE, 0);
9899
9900       gtk_widget_show_all (vbox);
9901     }
9902
9903   if (!GTK_WIDGET_VISIBLE (window))
9904     gtk_widget_show (window);
9905   else
9906     gtk_widget_destroy (window);
9907 }
9908
9909 /*
9910  * Paned keyboard navigation
9911  */
9912
9913 static GtkWidget*
9914 paned_keyboard_window1 (GtkWidget *widget)
9915 {
9916   GtkWidget *window1;
9917   GtkWidget *hpaned1;
9918   GtkWidget *frame1;
9919   GtkWidget *vbox1;
9920   GtkWidget *button7;
9921   GtkWidget *button8;
9922   GtkWidget *button9;
9923   GtkWidget *vpaned1;
9924   GtkWidget *frame2;
9925   GtkWidget *frame5;
9926   GtkWidget *hbox1;
9927   GtkWidget *button5;
9928   GtkWidget *button6;
9929   GtkWidget *frame3;
9930   GtkWidget *frame4;
9931   GtkWidget *table1;
9932   GtkWidget *button1;
9933   GtkWidget *button2;
9934   GtkWidget *button3;
9935   GtkWidget *button4;
9936
9937   window1 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9938   gtk_window_set_title (GTK_WINDOW (window1), "Basic paned navigation");
9939   gtk_window_set_screen (GTK_WINDOW (window1), 
9940                          gtk_widget_get_screen (widget));
9941
9942   hpaned1 = gtk_hpaned_new ();
9943   gtk_container_add (GTK_CONTAINER (window1), hpaned1);
9944
9945   frame1 = gtk_frame_new (NULL);
9946   gtk_paned_pack1 (GTK_PANED (hpaned1), frame1, FALSE, TRUE);
9947   gtk_frame_set_shadow_type (GTK_FRAME (frame1), GTK_SHADOW_IN);
9948
9949   vbox1 = gtk_vbox_new (FALSE, 0);
9950   gtk_container_add (GTK_CONTAINER (frame1), vbox1);
9951
9952   button7 = gtk_button_new_with_label ("button7");
9953   gtk_box_pack_start (GTK_BOX (vbox1), button7, FALSE, FALSE, 0);
9954
9955   button8 = gtk_button_new_with_label ("button8");
9956   gtk_box_pack_start (GTK_BOX (vbox1), button8, FALSE, FALSE, 0);
9957
9958   button9 = gtk_button_new_with_label ("button9");
9959   gtk_box_pack_start (GTK_BOX (vbox1), button9, FALSE, FALSE, 0);
9960
9961   vpaned1 = gtk_vpaned_new ();
9962   gtk_paned_pack2 (GTK_PANED (hpaned1), vpaned1, TRUE, TRUE);
9963
9964   frame2 = gtk_frame_new (NULL);
9965   gtk_paned_pack1 (GTK_PANED (vpaned1), frame2, FALSE, TRUE);
9966   gtk_frame_set_shadow_type (GTK_FRAME (frame2), GTK_SHADOW_IN);
9967
9968   frame5 = gtk_frame_new (NULL);
9969   gtk_container_add (GTK_CONTAINER (frame2), frame5);
9970
9971   hbox1 = gtk_hbox_new (FALSE, 0);
9972   gtk_container_add (GTK_CONTAINER (frame5), hbox1);
9973
9974   button5 = gtk_button_new_with_label ("button5");
9975   gtk_box_pack_start (GTK_BOX (hbox1), button5, FALSE, FALSE, 0);
9976
9977   button6 = gtk_button_new_with_label ("button6");
9978   gtk_box_pack_start (GTK_BOX (hbox1), button6, FALSE, FALSE, 0);
9979
9980   frame3 = gtk_frame_new (NULL);
9981   gtk_paned_pack2 (GTK_PANED (vpaned1), frame3, TRUE, TRUE);
9982   gtk_frame_set_shadow_type (GTK_FRAME (frame3), GTK_SHADOW_IN);
9983
9984   frame4 = gtk_frame_new ("Buttons");
9985   gtk_container_add (GTK_CONTAINER (frame3), frame4);
9986   gtk_container_set_border_width (GTK_CONTAINER (frame4), 15);
9987
9988   table1 = gtk_table_new (2, 2, FALSE);
9989   gtk_container_add (GTK_CONTAINER (frame4), table1);
9990   gtk_container_set_border_width (GTK_CONTAINER (table1), 11);
9991
9992   button1 = gtk_button_new_with_label ("button1");
9993   gtk_table_attach (GTK_TABLE (table1), button1, 0, 1, 0, 1,
9994                     (GtkAttachOptions) (GTK_FILL),
9995                     (GtkAttachOptions) (0), 0, 0);
9996
9997   button2 = gtk_button_new_with_label ("button2");
9998   gtk_table_attach (GTK_TABLE (table1), button2, 1, 2, 0, 1,
9999                     (GtkAttachOptions) (GTK_FILL),
10000                     (GtkAttachOptions) (0), 0, 0);
10001
10002   button3 = gtk_button_new_with_label ("button3");
10003   gtk_table_attach (GTK_TABLE (table1), button3, 0, 1, 1, 2,
10004                     (GtkAttachOptions) (GTK_FILL),
10005                     (GtkAttachOptions) (0), 0, 0);
10006
10007   button4 = gtk_button_new_with_label ("button4");
10008   gtk_table_attach (GTK_TABLE (table1), button4, 1, 2, 1, 2,
10009                     (GtkAttachOptions) (GTK_FILL),
10010                     (GtkAttachOptions) (0), 0, 0);
10011
10012   return window1;
10013 }
10014
10015 static GtkWidget*
10016 paned_keyboard_window2 (GtkWidget *widget)
10017 {
10018   GtkWidget *window2;
10019   GtkWidget *hpaned2;
10020   GtkWidget *frame6;
10021   GtkWidget *button13;
10022   GtkWidget *hbox2;
10023   GtkWidget *vpaned2;
10024   GtkWidget *frame7;
10025   GtkWidget *button12;
10026   GtkWidget *frame8;
10027   GtkWidget *button11;
10028   GtkWidget *button10;
10029
10030   window2 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
10031   gtk_window_set_title (GTK_WINDOW (window2), "\"button 10\" is not inside the horisontal pane");
10032
10033   gtk_window_set_screen (GTK_WINDOW (window2), 
10034                          gtk_widget_get_screen (widget));
10035
10036   hpaned2 = gtk_hpaned_new ();
10037   gtk_container_add (GTK_CONTAINER (window2), hpaned2);
10038
10039   frame6 = gtk_frame_new (NULL);
10040   gtk_paned_pack1 (GTK_PANED (hpaned2), frame6, FALSE, TRUE);
10041   gtk_frame_set_shadow_type (GTK_FRAME (frame6), GTK_SHADOW_IN);
10042
10043   button13 = gtk_button_new_with_label ("button13");
10044   gtk_container_add (GTK_CONTAINER (frame6), button13);
10045
10046   hbox2 = gtk_hbox_new (FALSE, 0);
10047   gtk_paned_pack2 (GTK_PANED (hpaned2), hbox2, TRUE, TRUE);
10048
10049   vpaned2 = gtk_vpaned_new ();
10050   gtk_box_pack_start (GTK_BOX (hbox2), vpaned2, TRUE, TRUE, 0);
10051
10052   frame7 = gtk_frame_new (NULL);
10053   gtk_paned_pack1 (GTK_PANED (vpaned2), frame7, FALSE, TRUE);
10054   gtk_frame_set_shadow_type (GTK_FRAME (frame7), GTK_SHADOW_IN);
10055
10056   button12 = gtk_button_new_with_label ("button12");
10057   gtk_container_add (GTK_CONTAINER (frame7), button12);
10058
10059   frame8 = gtk_frame_new (NULL);
10060   gtk_paned_pack2 (GTK_PANED (vpaned2), frame8, TRUE, TRUE);
10061   gtk_frame_set_shadow_type (GTK_FRAME (frame8), GTK_SHADOW_IN);
10062
10063   button11 = gtk_button_new_with_label ("button11");
10064   gtk_container_add (GTK_CONTAINER (frame8), button11);
10065
10066   button10 = gtk_button_new_with_label ("button10");
10067   gtk_box_pack_start (GTK_BOX (hbox2), button10, FALSE, FALSE, 0);
10068
10069   return window2;
10070 }
10071
10072 static GtkWidget*
10073 paned_keyboard_window3 (GtkWidget *widget)
10074 {
10075   GtkWidget *window3;
10076   GtkWidget *vbox2;
10077   GtkWidget *label1;
10078   GtkWidget *hpaned3;
10079   GtkWidget *frame9;
10080   GtkWidget *button14;
10081   GtkWidget *hpaned4;
10082   GtkWidget *frame10;
10083   GtkWidget *button15;
10084   GtkWidget *hpaned5;
10085   GtkWidget *frame11;
10086   GtkWidget *button16;
10087   GtkWidget *frame12;
10088   GtkWidget *button17;
10089
10090   window3 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
10091   g_object_set_data (G_OBJECT (window3), "window3", window3);
10092   gtk_window_set_title (GTK_WINDOW (window3), "Nested panes");
10093
10094   gtk_window_set_screen (GTK_WINDOW (window3), 
10095                          gtk_widget_get_screen (widget));
10096   
10097
10098   vbox2 = gtk_vbox_new (FALSE, 0);
10099   gtk_container_add (GTK_CONTAINER (window3), vbox2);
10100
10101   label1 = gtk_label_new ("Three panes nested inside each other");
10102   gtk_box_pack_start (GTK_BOX (vbox2), label1, FALSE, FALSE, 0);
10103
10104   hpaned3 = gtk_hpaned_new ();
10105   gtk_box_pack_start (GTK_BOX (vbox2), hpaned3, TRUE, TRUE, 0);
10106
10107   frame9 = gtk_frame_new (NULL);
10108   gtk_paned_pack1 (GTK_PANED (hpaned3), frame9, FALSE, TRUE);
10109   gtk_frame_set_shadow_type (GTK_FRAME (frame9), GTK_SHADOW_IN);
10110
10111   button14 = gtk_button_new_with_label ("button14");
10112   gtk_container_add (GTK_CONTAINER (frame9), button14);
10113
10114   hpaned4 = gtk_hpaned_new ();
10115   gtk_paned_pack2 (GTK_PANED (hpaned3), hpaned4, TRUE, TRUE);
10116
10117   frame10 = gtk_frame_new (NULL);
10118   gtk_paned_pack1 (GTK_PANED (hpaned4), frame10, FALSE, TRUE);
10119   gtk_frame_set_shadow_type (GTK_FRAME (frame10), GTK_SHADOW_IN);
10120
10121   button15 = gtk_button_new_with_label ("button15");
10122   gtk_container_add (GTK_CONTAINER (frame10), button15);
10123
10124   hpaned5 = gtk_hpaned_new ();
10125   gtk_paned_pack2 (GTK_PANED (hpaned4), hpaned5, TRUE, TRUE);
10126
10127   frame11 = gtk_frame_new (NULL);
10128   gtk_paned_pack1 (GTK_PANED (hpaned5), frame11, FALSE, TRUE);
10129   gtk_frame_set_shadow_type (GTK_FRAME (frame11), GTK_SHADOW_IN);
10130
10131   button16 = gtk_button_new_with_label ("button16");
10132   gtk_container_add (GTK_CONTAINER (frame11), button16);
10133
10134   frame12 = gtk_frame_new (NULL);
10135   gtk_paned_pack2 (GTK_PANED (hpaned5), frame12, TRUE, TRUE);
10136   gtk_frame_set_shadow_type (GTK_FRAME (frame12), GTK_SHADOW_IN);
10137
10138   button17 = gtk_button_new_with_label ("button17");
10139   gtk_container_add (GTK_CONTAINER (frame12), button17);
10140
10141   return window3;
10142 }
10143
10144 static GtkWidget*
10145 paned_keyboard_window4 (GtkWidget *widget)
10146 {
10147   GtkWidget *window4;
10148   GtkWidget *vbox3;
10149   GtkWidget *label2;
10150   GtkWidget *hpaned6;
10151   GtkWidget *vpaned3;
10152   GtkWidget *button19;
10153   GtkWidget *button18;
10154   GtkWidget *hbox3;
10155   GtkWidget *vpaned4;
10156   GtkWidget *button21;
10157   GtkWidget *button20;
10158   GtkWidget *vpaned5;
10159   GtkWidget *button23;
10160   GtkWidget *button22;
10161   GtkWidget *vpaned6;
10162   GtkWidget *button25;
10163   GtkWidget *button24;
10164
10165   window4 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
10166   g_object_set_data (G_OBJECT (window4), "window4", window4);
10167   gtk_window_set_title (GTK_WINDOW (window4), "window4");
10168
10169   gtk_window_set_screen (GTK_WINDOW (window4), 
10170                          gtk_widget_get_screen (widget));
10171
10172   vbox3 = gtk_vbox_new (FALSE, 0);
10173   gtk_container_add (GTK_CONTAINER (window4), vbox3);
10174
10175   label2 = gtk_label_new ("Widget tree:\n\nhpaned \n - vpaned\n - hbox\n    - vpaned\n    - vpaned\n    - vpaned\n");
10176   gtk_box_pack_start (GTK_BOX (vbox3), label2, FALSE, FALSE, 0);
10177   gtk_label_set_justify (GTK_LABEL (label2), GTK_JUSTIFY_LEFT);
10178
10179   hpaned6 = gtk_hpaned_new ();
10180   gtk_box_pack_start (GTK_BOX (vbox3), hpaned6, TRUE, TRUE, 0);
10181
10182   vpaned3 = gtk_vpaned_new ();
10183   gtk_paned_pack1 (GTK_PANED (hpaned6), vpaned3, FALSE, TRUE);
10184
10185   button19 = gtk_button_new_with_label ("button19");
10186   gtk_paned_pack1 (GTK_PANED (vpaned3), button19, FALSE, TRUE);
10187
10188   button18 = gtk_button_new_with_label ("button18");
10189   gtk_paned_pack2 (GTK_PANED (vpaned3), button18, TRUE, TRUE);
10190
10191   hbox3 = gtk_hbox_new (FALSE, 0);
10192   gtk_paned_pack2 (GTK_PANED (hpaned6), hbox3, TRUE, TRUE);
10193
10194   vpaned4 = gtk_vpaned_new ();
10195   gtk_box_pack_start (GTK_BOX (hbox3), vpaned4, TRUE, TRUE, 0);
10196
10197   button21 = gtk_button_new_with_label ("button21");
10198   gtk_paned_pack1 (GTK_PANED (vpaned4), button21, FALSE, TRUE);
10199
10200   button20 = gtk_button_new_with_label ("button20");
10201   gtk_paned_pack2 (GTK_PANED (vpaned4), button20, TRUE, TRUE);
10202
10203   vpaned5 = gtk_vpaned_new ();
10204   gtk_box_pack_start (GTK_BOX (hbox3), vpaned5, TRUE, TRUE, 0);
10205
10206   button23 = gtk_button_new_with_label ("button23");
10207   gtk_paned_pack1 (GTK_PANED (vpaned5), button23, FALSE, TRUE);
10208
10209   button22 = gtk_button_new_with_label ("button22");
10210   gtk_paned_pack2 (GTK_PANED (vpaned5), button22, TRUE, TRUE);
10211
10212   vpaned6 = gtk_vpaned_new ();
10213   gtk_box_pack_start (GTK_BOX (hbox3), vpaned6, TRUE, TRUE, 0);
10214
10215   button25 = gtk_button_new_with_label ("button25");
10216   gtk_paned_pack1 (GTK_PANED (vpaned6), button25, FALSE, TRUE);
10217
10218   button24 = gtk_button_new_with_label ("button24");
10219   gtk_paned_pack2 (GTK_PANED (vpaned6), button24, TRUE, TRUE);
10220
10221   return window4;
10222 }
10223
10224 static void
10225 create_paned_keyboard_navigation (GtkWidget *widget)
10226 {
10227   static GtkWidget *window1 = NULL;
10228   static GtkWidget *window2 = NULL;
10229   static GtkWidget *window3 = NULL;
10230   static GtkWidget *window4 = NULL;
10231
10232   if (window1 && 
10233      (gtk_widget_get_screen (window1) != gtk_widget_get_screen (widget)))
10234     {
10235       gtk_widget_destroy (window1);
10236       gtk_widget_destroy (window2);
10237       gtk_widget_destroy (window3);
10238       gtk_widget_destroy (window4);
10239     }
10240   
10241   if (!window1)
10242     {
10243       window1 = paned_keyboard_window1 (widget);
10244       g_signal_connect (window1, "destroy",
10245                         G_CALLBACK (gtk_widget_destroyed),
10246                         &window1);
10247     }
10248
10249   if (!window2)
10250     {
10251       window2 = paned_keyboard_window2 (widget);
10252       g_signal_connect (window2, "destroy",
10253                         G_CALLBACK (gtk_widget_destroyed),
10254                         &window2);
10255     }
10256
10257   if (!window3)
10258     {
10259       window3 = paned_keyboard_window3 (widget);
10260       g_signal_connect (window3, "destroy",
10261                         G_CALLBACK (gtk_widget_destroyed),
10262                         &window3);
10263     }
10264
10265   if (!window4)
10266     {
10267       window4 = paned_keyboard_window4 (widget);
10268       g_signal_connect (window4, "destroy",
10269                         G_CALLBACK (gtk_widget_destroyed),
10270                         &window4);
10271     }
10272
10273   if (GTK_WIDGET_VISIBLE (window1))
10274     gtk_widget_destroy (GTK_WIDGET (window1));
10275   else
10276     gtk_widget_show_all (GTK_WIDGET (window1));
10277
10278   if (GTK_WIDGET_VISIBLE (window2))
10279     gtk_widget_destroy (GTK_WIDGET (window2));
10280   else
10281     gtk_widget_show_all (GTK_WIDGET (window2));
10282
10283   if (GTK_WIDGET_VISIBLE (window3))
10284     gtk_widget_destroy (GTK_WIDGET (window3));
10285   else
10286     gtk_widget_show_all (GTK_WIDGET (window3));
10287
10288   if (GTK_WIDGET_VISIBLE (window4))
10289     gtk_widget_destroy (GTK_WIDGET (window4));
10290   else
10291     gtk_widget_show_all (GTK_WIDGET (window4));
10292 }
10293
10294
10295 /*
10296  * Shaped Windows
10297  */
10298
10299 typedef struct _cursoroffset {gint x,y;} CursorOffset;
10300
10301 static void
10302 shape_pressed (GtkWidget *widget, GdkEventButton *event)
10303 {
10304   CursorOffset *p;
10305
10306   /* ignore double and triple click */
10307   if (event->type != GDK_BUTTON_PRESS)
10308     return;
10309
10310   p = g_object_get_data (G_OBJECT (widget), "cursor_offset");
10311   p->x = (int) event->x;
10312   p->y = (int) event->y;
10313
10314   gtk_grab_add (widget);
10315   gdk_pointer_grab (widget->window, TRUE,
10316                     GDK_BUTTON_RELEASE_MASK |
10317                     GDK_BUTTON_MOTION_MASK |
10318                     GDK_POINTER_MOTION_HINT_MASK,
10319                     NULL, NULL, 0);
10320 }
10321
10322 static void
10323 shape_released (GtkWidget *widget)
10324 {
10325   gtk_grab_remove (widget);
10326   gdk_display_pointer_ungrab (gtk_widget_get_display (widget),
10327                               GDK_CURRENT_TIME);
10328 }
10329
10330 static void
10331 shape_motion (GtkWidget      *widget, 
10332               GdkEventMotion *event)
10333 {
10334   gint xp, yp;
10335   CursorOffset * p;
10336   GdkModifierType mask;
10337
10338   p = g_object_get_data (G_OBJECT (widget), "cursor_offset");
10339
10340   /*
10341    * Can't use event->x / event->y here 
10342    * because I need absolute coordinates.
10343    */
10344   gdk_window_get_pointer (NULL, &xp, &yp, &mask);
10345   gtk_widget_set_uposition (widget, xp  - p->x, yp  - p->y);
10346 }
10347
10348 GtkWidget *
10349 shape_create_icon (GdkScreen *screen,
10350                    char      *xpm_file,
10351                    gint       x,
10352                    gint       y,
10353                    gint       px,
10354                    gint       py,
10355                    gint       window_type)
10356 {
10357   GtkWidget *window;
10358   GtkWidget *pixmap;
10359   GtkWidget *fixed;
10360   CursorOffset* icon_pos;
10361   GdkGC* gc;
10362   GdkBitmap *gdk_pixmap_mask;
10363   GdkPixmap *gdk_pixmap;
10364   GtkStyle *style;
10365
10366   style = gtk_widget_get_default_style ();
10367   gc = style->black_gc; 
10368
10369   /*
10370    * GDK_WINDOW_TOPLEVEL works also, giving you a title border
10371    */
10372   window = gtk_window_new (window_type);
10373   gtk_window_set_screen (GTK_WINDOW (window), screen);
10374   
10375   fixed = gtk_fixed_new ();
10376   gtk_widget_set_size_request (fixed, 100, 100);
10377   gtk_container_add (GTK_CONTAINER (window), fixed);
10378   gtk_widget_show (fixed);
10379   
10380   gtk_widget_set_events (window, 
10381                          gtk_widget_get_events (window) |
10382                          GDK_BUTTON_MOTION_MASK |
10383                          GDK_POINTER_MOTION_HINT_MASK |
10384                          GDK_BUTTON_PRESS_MASK);
10385
10386   gtk_widget_realize (window);
10387   gdk_pixmap = gdk_pixmap_create_from_xpm (window->window, &gdk_pixmap_mask, 
10388                                            &style->bg[GTK_STATE_NORMAL],
10389                                            xpm_file);
10390
10391   pixmap = gtk_image_new_from_pixmap (gdk_pixmap, gdk_pixmap_mask);
10392   gtk_fixed_put (GTK_FIXED (fixed), pixmap, px,py);
10393   gtk_widget_show (pixmap);
10394   
10395   gtk_widget_shape_combine_mask (window, gdk_pixmap_mask, px, py);
10396   
10397   g_object_unref (gdk_pixmap_mask);
10398   g_object_unref (gdk_pixmap);
10399
10400   g_signal_connect (window, "button_press_event",
10401                     G_CALLBACK (shape_pressed), NULL);
10402   g_signal_connect (window, "button_release_event",
10403                     G_CALLBACK (shape_released), NULL);
10404   g_signal_connect (window, "motion_notify_event",
10405                     G_CALLBACK (shape_motion), NULL);
10406
10407   icon_pos = g_new (CursorOffset, 1);
10408   g_object_set_data (G_OBJECT (window), "cursor_offset", icon_pos);
10409
10410   gtk_widget_set_uposition (window, x, y);
10411   gtk_widget_show (window);
10412   
10413   return window;
10414 }
10415
10416 void 
10417 create_shapes (GtkWidget *widget)
10418 {
10419   /* Variables used by the Drag/Drop and Shape Window demos */
10420   static GtkWidget *modeller = NULL;
10421   static GtkWidget *sheets = NULL;
10422   static GtkWidget *rings = NULL;
10423   static GtkWidget *with_region = NULL;
10424   GdkScreen *screen = gtk_widget_get_screen (widget);
10425   
10426   if (!(file_exists ("Modeller.xpm") &&
10427         file_exists ("FilesQueue.xpm") &&
10428         file_exists ("3DRings.xpm")))
10429     return;
10430   
10431
10432   if (!modeller)
10433     {
10434       modeller = shape_create_icon (screen, "Modeller.xpm",
10435                                     440, 140, 0,0, GTK_WINDOW_POPUP);
10436
10437       g_signal_connect (modeller, "destroy",
10438                         G_CALLBACK (gtk_widget_destroyed),
10439                         &modeller);
10440     }
10441   else
10442     gtk_widget_destroy (modeller);
10443
10444   if (!sheets)
10445     {
10446       sheets = shape_create_icon (screen, "FilesQueue.xpm",
10447                                   580, 170, 0,0, GTK_WINDOW_POPUP);
10448
10449       g_signal_connect (sheets, "destroy",
10450                         G_CALLBACK (gtk_widget_destroyed),
10451                         &sheets);
10452
10453     }
10454   else
10455     gtk_widget_destroy (sheets);
10456
10457   if (!rings)
10458     {
10459       rings = shape_create_icon (screen, "3DRings.xpm",
10460                                  460, 270, 25,25, GTK_WINDOW_TOPLEVEL);
10461
10462       g_signal_connect (rings, "destroy",
10463                         G_CALLBACK (gtk_widget_destroyed),
10464                         &rings);
10465     }
10466   else
10467     gtk_widget_destroy (rings);
10468
10469   if (!with_region)
10470     {
10471       GdkRegion *region;
10472       gint x, y;
10473       
10474       with_region = shape_create_icon (screen, "3DRings.xpm",
10475                                        460, 270, 25,25, GTK_WINDOW_TOPLEVEL);
10476
10477       gtk_window_set_decorated (GTK_WINDOW (with_region), FALSE);
10478       
10479       g_signal_connect (with_region, "destroy",
10480                         G_CALLBACK (gtk_widget_destroyed),
10481                         &with_region);
10482
10483       /* reset shape from mask to a region */
10484       x = 0;
10485       y = 0;
10486       region = gdk_region_new ();
10487
10488       while (x < 460)
10489         {
10490           while (y < 270)
10491             {
10492               GdkRectangle rect;
10493               rect.x = x;
10494               rect.y = y;
10495               rect.width = 10;
10496               rect.height = 10;
10497
10498               gdk_region_union_with_rect (region, &rect);
10499               
10500               y += 20;
10501             }
10502           y = 0;
10503           x += 20;
10504         }
10505
10506       gdk_window_shape_combine_region (with_region->window,
10507                                        region,
10508                                        0, 0);
10509     }
10510   else
10511     gtk_widget_destroy (with_region);
10512 }
10513
10514 /*
10515  * WM Hints demo
10516  */
10517
10518 void
10519 create_wmhints (GtkWidget *widget)
10520 {
10521   static GtkWidget *window = NULL;
10522   GtkWidget *label;
10523   GtkWidget *separator;
10524   GtkWidget *button;
10525   GtkWidget *box1;
10526   GtkWidget *box2;
10527
10528   GdkBitmap *circles;
10529
10530   if (!window)
10531     {
10532       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
10533
10534       gtk_window_set_screen (GTK_WINDOW (window),
10535                              gtk_widget_get_screen (widget));
10536       
10537       g_signal_connect (window, "destroy",
10538                         G_CALLBACK (gtk_widget_destroyed),
10539                         &window);
10540
10541       gtk_window_set_title (GTK_WINDOW (window), "WM Hints");
10542       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
10543
10544       gtk_widget_realize (window);
10545       
10546       circles = gdk_bitmap_create_from_data (window->window,
10547                                              (gchar *) circles_bits,
10548                                              circles_width,
10549                                              circles_height);
10550       gdk_window_set_icon (window->window, NULL,
10551                            circles, circles);
10552       
10553       gdk_window_set_icon_name (window->window, "WMHints Test Icon");
10554   
10555       gdk_window_set_decorations (window->window, GDK_DECOR_ALL | GDK_DECOR_MENU);
10556       gdk_window_set_functions (window->window, GDK_FUNC_ALL | GDK_FUNC_RESIZE);
10557       
10558       box1 = gtk_vbox_new (FALSE, 0);
10559       gtk_container_add (GTK_CONTAINER (window), box1);
10560       gtk_widget_show (box1);
10561
10562       label = gtk_label_new ("Try iconizing me!");
10563       gtk_widget_set_size_request (label, 150, 50);
10564       gtk_box_pack_start (GTK_BOX (box1), label, TRUE, TRUE, 0);
10565       gtk_widget_show (label);
10566
10567
10568       separator = gtk_hseparator_new ();
10569       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
10570       gtk_widget_show (separator);
10571
10572
10573       box2 = gtk_vbox_new (FALSE, 10);
10574       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
10575       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
10576       gtk_widget_show (box2);
10577
10578
10579       button = gtk_button_new_with_label ("close");
10580
10581       g_signal_connect_swapped (button, "clicked",
10582                                 G_CALLBACK (gtk_widget_destroy),
10583                                 window);
10584
10585       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
10586       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
10587       gtk_widget_grab_default (button);
10588       gtk_widget_show (button);
10589     }
10590
10591   if (!GTK_WIDGET_VISIBLE (window))
10592     gtk_widget_show (window);
10593   else
10594     gtk_widget_destroy (window);
10595 }
10596
10597
10598 /*
10599  * Window state tracking
10600  */
10601
10602 static gint
10603 window_state_callback (GtkWidget *widget,
10604                        GdkEventWindowState *event,
10605                        gpointer data)
10606 {
10607   GtkWidget *label = data;
10608   gchar *msg;
10609
10610   msg = g_strconcat (GTK_WINDOW (widget)->title, ": ",
10611                      (event->new_window_state & GDK_WINDOW_STATE_WITHDRAWN) ?
10612                      "withdrawn" : "not withdrawn", ", ",
10613                      (event->new_window_state & GDK_WINDOW_STATE_ICONIFIED) ?
10614                      "iconified" : "not iconified", ", ",
10615                      (event->new_window_state & GDK_WINDOW_STATE_STICKY) ?
10616                      "sticky" : "not sticky", ", ",
10617                      (event->new_window_state & GDK_WINDOW_STATE_MAXIMIZED) ?
10618                      "maximized" : "not maximized", ", ",
10619                      (event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN) ?
10620                      "fullscreen" : "not fullscreen",
10621                      (event->new_window_state & GDK_WINDOW_STATE_ABOVE) ?
10622                      "above" : "not above", ", ",
10623                      (event->new_window_state & GDK_WINDOW_STATE_BELOW) ?
10624                      "below" : "not below", ", ",
10625                      NULL);
10626   
10627   gtk_label_set_text (GTK_LABEL (label), msg);
10628
10629   g_free (msg);
10630
10631   return FALSE;
10632 }
10633
10634 static GtkWidget*
10635 tracking_label (GtkWidget *window)
10636 {
10637   GtkWidget *label;
10638   GtkWidget *hbox;
10639   GtkWidget *button;
10640
10641   hbox = gtk_hbox_new (FALSE, 5);
10642
10643   g_signal_connect_object (hbox,
10644                            "destroy",
10645                            G_CALLBACK (gtk_widget_destroy),
10646                            window,
10647                            G_CONNECT_SWAPPED);
10648   
10649   label = gtk_label_new ("<no window state events received>");
10650   gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
10651   gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
10652   
10653   g_signal_connect (window,
10654                     "window_state_event",
10655                     G_CALLBACK (window_state_callback),
10656                     label);
10657
10658   button = gtk_button_new_with_label ("Deiconify");
10659   g_signal_connect_object (button,
10660                            "clicked",
10661                            G_CALLBACK (gtk_window_deiconify),
10662                            window,
10663                            G_CONNECT_SWAPPED);
10664   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
10665
10666   button = gtk_button_new_with_label ("Iconify");
10667   g_signal_connect_object (button,
10668                            "clicked",
10669                            G_CALLBACK (gtk_window_iconify),
10670                            window,
10671                            G_CONNECT_SWAPPED);
10672   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
10673
10674   button = gtk_button_new_with_label ("Fullscreen");
10675   g_signal_connect_object (button,
10676                            "clicked",
10677                            G_CALLBACK (gtk_window_fullscreen),
10678                            window,
10679                            G_CONNECT_SWAPPED);
10680   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
10681
10682   button = gtk_button_new_with_label ("Unfullscreen");
10683   g_signal_connect_object (button,
10684                            "clicked",
10685                            G_CALLBACK (gtk_window_unfullscreen),
10686                            window,
10687                            G_CONNECT_SWAPPED);
10688   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
10689   
10690   button = gtk_button_new_with_label ("Present");
10691   g_signal_connect_object (button,
10692                            "clicked",
10693                            G_CALLBACK (gtk_window_present),
10694                            window,
10695                            G_CONNECT_SWAPPED);
10696   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
10697
10698   button = gtk_button_new_with_label ("Show");
10699   g_signal_connect_object (button,
10700                            "clicked",
10701                            G_CALLBACK (gtk_widget_show),
10702                            window,
10703                            G_CONNECT_SWAPPED);
10704   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
10705   
10706   gtk_widget_show_all (hbox);
10707   
10708   return hbox;
10709 }
10710
10711 void
10712 keep_window_above (GtkToggleButton *togglebutton, gpointer data)
10713 {
10714   GtkWidget *button = g_object_get_data (G_OBJECT (togglebutton), "radio");
10715
10716   gtk_window_set_keep_above (GTK_WINDOW (data),
10717                              gtk_toggle_button_get_active (togglebutton));
10718
10719   if (gtk_toggle_button_get_active (togglebutton))
10720     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE);
10721 }
10722
10723 void
10724 keep_window_below (GtkToggleButton *togglebutton, gpointer data)
10725 {
10726   GtkWidget *button = g_object_get_data (G_OBJECT (togglebutton), "radio");
10727
10728   gtk_window_set_keep_below (GTK_WINDOW (data),
10729                              gtk_toggle_button_get_active (togglebutton));
10730
10731   if (gtk_toggle_button_get_active (togglebutton))
10732     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE);
10733 }
10734
10735
10736 static GtkWidget*
10737 get_state_controls (GtkWidget *window)
10738 {
10739   GtkWidget *vbox;
10740   GtkWidget *button;
10741   GtkWidget *button_above;
10742   GtkWidget *button_below;
10743
10744   vbox = gtk_vbox_new (FALSE, 0);
10745   
10746   button = gtk_button_new_with_label ("Stick");
10747   g_signal_connect_object (button,
10748                            "clicked",
10749                            G_CALLBACK (gtk_window_stick),
10750                            window,
10751                            G_CONNECT_SWAPPED);
10752   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
10753
10754   button = gtk_button_new_with_label ("Unstick");
10755   g_signal_connect_object (button,
10756                            "clicked",
10757                            G_CALLBACK (gtk_window_unstick),
10758                            window,
10759                            G_CONNECT_SWAPPED);
10760   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
10761   
10762   button = gtk_button_new_with_label ("Maximize");
10763   g_signal_connect_object (button,
10764                            "clicked",
10765                            G_CALLBACK (gtk_window_maximize),
10766                            window,
10767                            G_CONNECT_SWAPPED);
10768   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
10769
10770   button = gtk_button_new_with_label ("Unmaximize");
10771   g_signal_connect_object (button,
10772                            "clicked",
10773                            G_CALLBACK (gtk_window_unmaximize),
10774                            window,
10775                            G_CONNECT_SWAPPED);
10776   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
10777
10778   button = gtk_button_new_with_label ("Iconify");
10779   g_signal_connect_object (button,
10780                            "clicked",
10781                            G_CALLBACK (gtk_window_iconify),
10782                            window,
10783                            G_CONNECT_SWAPPED);
10784   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
10785
10786   button = gtk_button_new_with_label ("Fullscreen");
10787   g_signal_connect_object (button,
10788                            "clicked",
10789                            G_CALLBACK (gtk_window_fullscreen),
10790                            window,
10791                            G_CONNECT_SWAPPED);
10792   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
10793
10794   button = gtk_button_new_with_label ("Unfullscreen");
10795   g_signal_connect_object (button,
10796                            "clicked",
10797                            G_CALLBACK (gtk_window_unfullscreen),
10798                            window,
10799                            G_CONNECT_SWAPPED);
10800   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
10801
10802   button_above = gtk_toggle_button_new_with_label ("Keep above");
10803   g_signal_connect (button_above,
10804                     "toggled",
10805                     G_CALLBACK (keep_window_above),
10806                     window);
10807   gtk_box_pack_start (GTK_BOX (vbox), button_above, FALSE, FALSE, 0);
10808
10809   button_below = gtk_toggle_button_new_with_label ("Keep below");
10810   g_signal_connect (button_below,
10811                     "toggled",
10812                     G_CALLBACK (keep_window_below),
10813                     window);
10814   gtk_box_pack_start (GTK_BOX (vbox), button_below, FALSE, FALSE, 0);
10815
10816   g_object_set_data (G_OBJECT (button_above), "radio", button_below);
10817   g_object_set_data (G_OBJECT (button_below), "radio", button_above);
10818
10819   button = gtk_button_new_with_label ("Hide (withdraw)");
10820   g_signal_connect_object (button,
10821                            "clicked",
10822                            G_CALLBACK (gtk_widget_hide),
10823                            window,
10824                            G_CONNECT_SWAPPED);
10825   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
10826   
10827   gtk_widget_show_all (vbox);
10828
10829   return vbox;
10830 }
10831
10832 void
10833 create_window_states (GtkWidget *widget)
10834 {
10835   static GtkWidget *window = NULL;
10836   GtkWidget *label;
10837   GtkWidget *box1;
10838   GtkWidget *iconified;
10839   GtkWidget *normal;
10840   GtkWidget *controls;
10841
10842   if (!window)
10843     {
10844       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
10845       gtk_window_set_screen (GTK_WINDOW (window),
10846                              gtk_widget_get_screen (widget));
10847
10848       g_signal_connect (window, "destroy",
10849                         G_CALLBACK (gtk_widget_destroyed),
10850                         &window);
10851
10852       gtk_window_set_title (GTK_WINDOW (window), "Window states");
10853       
10854       box1 = gtk_vbox_new (FALSE, 0);
10855       gtk_container_add (GTK_CONTAINER (window), box1);
10856
10857       iconified = gtk_window_new (GTK_WINDOW_TOPLEVEL);
10858
10859       gtk_window_set_screen (GTK_WINDOW (iconified),
10860                              gtk_widget_get_screen (widget));
10861       
10862       g_signal_connect_object (iconified, "destroy",
10863                                G_CALLBACK (gtk_widget_destroy),
10864                                window,
10865                                G_CONNECT_SWAPPED);
10866       gtk_window_iconify (GTK_WINDOW (iconified));
10867       gtk_window_set_title (GTK_WINDOW (iconified), "Iconified initially");
10868       controls = get_state_controls (iconified);
10869       gtk_container_add (GTK_CONTAINER (iconified), controls);
10870       
10871       normal = gtk_window_new (GTK_WINDOW_TOPLEVEL);
10872
10873       gtk_window_set_screen (GTK_WINDOW (normal),
10874                              gtk_widget_get_screen (widget));
10875       
10876       g_signal_connect_object (normal, "destroy",
10877                                G_CALLBACK (gtk_widget_destroy),
10878                                window,
10879                                G_CONNECT_SWAPPED);
10880       
10881       gtk_window_set_title (GTK_WINDOW (normal), "Deiconified initially");
10882       controls = get_state_controls (normal);
10883       gtk_container_add (GTK_CONTAINER (normal), controls);
10884       
10885       label = tracking_label (iconified);
10886       gtk_container_add (GTK_CONTAINER (box1), label);
10887
10888       label = tracking_label (normal);
10889       gtk_container_add (GTK_CONTAINER (box1), label);
10890
10891       gtk_widget_show_all (iconified);
10892       gtk_widget_show_all (normal);
10893       gtk_widget_show_all (box1);
10894     }
10895
10896   if (!GTK_WIDGET_VISIBLE (window))
10897     gtk_widget_show (window);
10898   else
10899     gtk_widget_destroy (window);
10900 }
10901
10902 /*
10903  * Window sizing
10904  */
10905
10906 static gint
10907 configure_event_callback (GtkWidget *widget,
10908                           GdkEventConfigure *event,
10909                           gpointer data)
10910 {
10911   GtkWidget *label = data;
10912   gchar *msg;
10913   gint x, y;
10914   
10915   gtk_window_get_position (GTK_WINDOW (widget), &x, &y);
10916   
10917   msg = g_strdup_printf ("event: %d,%d  %d x %d\n"
10918                          "position: %d, %d",
10919                          event->x, event->y, event->width, event->height,
10920                          x, y);
10921   
10922   gtk_label_set_text (GTK_LABEL (label), msg);
10923
10924   g_free (msg);
10925
10926   return FALSE;
10927 }
10928
10929 static void
10930 get_ints (GtkWidget *window,
10931           gint      *a,
10932           gint      *b)
10933 {
10934   GtkWidget *spin1;
10935   GtkWidget *spin2;
10936
10937   spin1 = g_object_get_data (G_OBJECT (window), "spin1");
10938   spin2 = g_object_get_data (G_OBJECT (window), "spin2");
10939
10940   *a = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (spin1));
10941   *b = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (spin2));
10942 }
10943
10944 static void
10945 set_size_callback (GtkWidget *widget,
10946                    gpointer   data)
10947 {
10948   gint w, h;
10949   
10950   get_ints (data, &w, &h);
10951
10952   gtk_window_resize (GTK_WINDOW (g_object_get_data (data, "target")), w, h);
10953 }
10954
10955 static void
10956 unset_default_size_callback (GtkWidget *widget,
10957                              gpointer   data)
10958 {
10959   gtk_window_set_default_size (g_object_get_data (data, "target"),
10960                                -1, -1);
10961 }
10962
10963 static void
10964 set_default_size_callback (GtkWidget *widget,
10965                            gpointer   data)
10966 {
10967   gint w, h;
10968   
10969   get_ints (data, &w, &h);
10970
10971   gtk_window_set_default_size (g_object_get_data (data, "target"),
10972                                w, h);
10973 }
10974
10975 static void
10976 unset_size_request_callback (GtkWidget *widget,
10977                              gpointer   data)
10978 {
10979   gtk_widget_set_size_request (g_object_get_data (data, "target"),
10980                                -1, -1);
10981 }
10982
10983 static void
10984 set_size_request_callback (GtkWidget *widget,
10985                            gpointer   data)
10986 {
10987   gint w, h;
10988   
10989   get_ints (data, &w, &h);
10990
10991   gtk_widget_set_size_request (g_object_get_data (data, "target"),
10992                                w, h);
10993 }
10994
10995 static void
10996 set_location_callback (GtkWidget *widget,
10997                        gpointer   data)
10998 {
10999   gint x, y;
11000   
11001   get_ints (data, &x, &y);
11002
11003   gtk_window_move (g_object_get_data (data, "target"), x, y);
11004 }
11005
11006 static void
11007 move_to_position_callback (GtkWidget *widget,
11008                            gpointer   data)
11009 {
11010   gint x, y;
11011   GtkWindow *window;
11012
11013   window = g_object_get_data (data, "target");
11014   
11015   gtk_window_get_position (window, &x, &y);
11016
11017   gtk_window_move (window, x, y);
11018 }
11019
11020 static void
11021 set_geometry_callback (GtkWidget *entry,
11022                        gpointer   data)
11023 {
11024   gchar *text;
11025   GtkWindow *target;
11026
11027   target = GTK_WINDOW (g_object_get_data (G_OBJECT (data), "target"));
11028   
11029   text = gtk_editable_get_chars (GTK_EDITABLE (entry), 0, -1);
11030
11031   if (!gtk_window_parse_geometry (target, text))
11032     g_print ("Bad geometry string '%s'\n", text);
11033
11034   g_free (text);
11035 }
11036
11037 static void
11038 allow_shrink_callback (GtkWidget *widget,
11039                        gpointer   data)
11040 {
11041   g_object_set (g_object_get_data (data, "target"),
11042                 "allow_shrink",
11043                 GTK_TOGGLE_BUTTON (widget)->active,
11044                 NULL);
11045 }
11046
11047 static void
11048 allow_grow_callback (GtkWidget *widget,
11049                      gpointer   data)
11050 {
11051   g_object_set (g_object_get_data (data, "target"),
11052                 "allow_grow",
11053                 GTK_TOGGLE_BUTTON (widget)->active,
11054                 NULL);
11055 }
11056
11057 static void
11058 gravity_selected (GtkWidget *widget,
11059                   gpointer   data)
11060 {
11061   gtk_window_set_gravity (GTK_WINDOW (g_object_get_data (data, "target")),
11062                           gtk_option_menu_get_history (GTK_OPTION_MENU (widget)) + GDK_GRAVITY_NORTH_WEST);
11063 }
11064
11065 static void
11066 pos_selected (GtkWidget *widget,
11067               gpointer   data)
11068 {
11069   gtk_window_set_position (GTK_WINDOW (g_object_get_data (data, "target")),
11070                            gtk_option_menu_get_history (GTK_OPTION_MENU (widget)) + GTK_WIN_POS_NONE);
11071 }
11072
11073 static void
11074 move_gravity_window_to_current_position (GtkWidget *widget,
11075                                          gpointer   data)
11076 {
11077   gint x, y;
11078   GtkWindow *window;
11079
11080   window = GTK_WINDOW (data);    
11081   
11082   gtk_window_get_position (window, &x, &y);
11083
11084   gtk_window_move (window, x, y);
11085 }
11086
11087 static void
11088 get_screen_corner (GtkWindow *window,
11089                    gint      *x,
11090                    gint      *y)
11091 {
11092   int w, h;
11093   GdkScreen * screen = gtk_window_get_screen (window);
11094   
11095   gtk_window_get_size (GTK_WINDOW (window), &w, &h);
11096
11097   switch (gtk_window_get_gravity (window))
11098     {
11099     case GDK_GRAVITY_SOUTH_EAST:
11100       *x = gdk_screen_get_width (screen) - w;
11101       *y = gdk_screen_get_height (screen) - h;
11102       break;
11103
11104     case GDK_GRAVITY_NORTH_EAST:
11105       *x = gdk_screen_get_width (screen) - w;
11106       *y = 0;
11107       break;
11108
11109     case GDK_GRAVITY_SOUTH_WEST:
11110       *x = 0;
11111       *y = gdk_screen_get_height (screen) - h;
11112       break;
11113
11114     case GDK_GRAVITY_NORTH_WEST:
11115       *x = 0;
11116       *y = 0;
11117       break;
11118       
11119     case GDK_GRAVITY_SOUTH:
11120       *x = (gdk_screen_get_width (screen) - w) / 2;
11121       *y = gdk_screen_get_height (screen) - h;
11122       break;
11123
11124     case GDK_GRAVITY_NORTH:
11125       *x = (gdk_screen_get_width (screen) - w) / 2;
11126       *y = 0;
11127       break;
11128
11129     case GDK_GRAVITY_WEST:
11130       *x = 0;
11131       *y = (gdk_screen_get_height (screen) - h) / 2;
11132       break;
11133
11134     case GDK_GRAVITY_EAST:
11135       *x = gdk_screen_get_width (screen) - w;
11136       *y = (gdk_screen_get_height (screen) - h) / 2;
11137       break;
11138
11139     case GDK_GRAVITY_CENTER:
11140       *x = (gdk_screen_get_width (screen) - w) / 2;
11141       *y = (gdk_screen_get_height (screen) - h) / 2;
11142       break;
11143
11144     case GDK_GRAVITY_STATIC:
11145       /* pick some random numbers */
11146       *x = 350;
11147       *y = 350;
11148       break;
11149
11150     default:
11151       g_assert_not_reached ();
11152       break;
11153     }
11154 }
11155
11156 static void
11157 move_gravity_window_to_starting_position (GtkWidget *widget,
11158                                           gpointer   data)
11159 {
11160   gint x, y;
11161   GtkWindow *window;
11162
11163   window = GTK_WINDOW (data);    
11164   
11165   get_screen_corner (window,
11166                      &x, &y);
11167   
11168   gtk_window_move (window, x, y);
11169 }
11170
11171 static GtkWidget*
11172 make_gravity_window (GtkWidget   *destroy_with,
11173                      GdkGravity   gravity,
11174                      const gchar *title)
11175 {
11176   GtkWidget *window;
11177   GtkWidget *button;
11178   GtkWidget *vbox;
11179   int x, y;
11180   
11181   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
11182
11183   gtk_window_set_screen (GTK_WINDOW (window),
11184                          gtk_widget_get_screen (destroy_with));
11185
11186   vbox = gtk_vbox_new (FALSE, 0);
11187   gtk_widget_show (vbox);
11188   
11189   gtk_container_add (GTK_CONTAINER (window), vbox);
11190   gtk_window_set_title (GTK_WINDOW (window), title);
11191   gtk_window_set_gravity (GTK_WINDOW (window), gravity);
11192
11193   g_signal_connect_object (destroy_with,
11194                            "destroy",
11195                            G_CALLBACK (gtk_widget_destroy),
11196                            window,
11197                            G_CONNECT_SWAPPED);
11198
11199   
11200   button = gtk_button_new_with_mnemonic ("_Move to current position");
11201
11202   g_signal_connect (button, "clicked",
11203                     G_CALLBACK (move_gravity_window_to_current_position),
11204                     window);
11205
11206   gtk_container_add (GTK_CONTAINER (vbox), button);
11207   gtk_widget_show (button);
11208
11209   button = gtk_button_new_with_mnemonic ("Move to _starting position");
11210
11211   g_signal_connect (button, "clicked",
11212                     G_CALLBACK (move_gravity_window_to_starting_position),
11213                     window);
11214
11215   gtk_container_add (GTK_CONTAINER (vbox), button);
11216   gtk_widget_show (button);
11217   
11218   /* Pretend this is the result of --geometry.
11219    * DO NOT COPY THIS CODE unless you are setting --geometry results,
11220    * and in that case you probably should just use gtk_window_parse_geometry().
11221    * AGAIN, DO NOT SET GDK_HINT_USER_POS! It violates the ICCCM unless
11222    * you are parsing --geometry or equivalent.
11223    */
11224   gtk_window_set_geometry_hints (GTK_WINDOW (window),
11225                                  NULL, NULL,
11226                                  GDK_HINT_USER_POS);
11227
11228   gtk_window_set_default_size (GTK_WINDOW (window),
11229                                200, 200);
11230
11231   get_screen_corner (GTK_WINDOW (window), &x, &y);
11232   
11233   gtk_window_move (GTK_WINDOW (window),
11234                    x, y);
11235   
11236   return window;
11237 }
11238
11239 static void
11240 do_gravity_test (GtkWidget *widget,
11241                  gpointer   data)
11242 {
11243   GtkWidget *destroy_with = data;
11244   GtkWidget *window;
11245   
11246   /* We put a window at each gravity point on the screen. */
11247   window = make_gravity_window (destroy_with, GDK_GRAVITY_NORTH_WEST,
11248                                 "NorthWest");
11249   gtk_widget_show (window);
11250   
11251   window = make_gravity_window (destroy_with, GDK_GRAVITY_SOUTH_EAST,
11252                                 "SouthEast");
11253   gtk_widget_show (window);
11254
11255   window = make_gravity_window (destroy_with, GDK_GRAVITY_NORTH_EAST,
11256                                 "NorthEast");
11257   gtk_widget_show (window);
11258
11259   window = make_gravity_window (destroy_with, GDK_GRAVITY_SOUTH_WEST,
11260                                 "SouthWest");
11261   gtk_widget_show (window);
11262
11263   window = make_gravity_window (destroy_with, GDK_GRAVITY_SOUTH,
11264                                 "South");
11265   gtk_widget_show (window);
11266
11267   window = make_gravity_window (destroy_with, GDK_GRAVITY_NORTH,
11268                                 "North");
11269   gtk_widget_show (window);
11270
11271   
11272   window = make_gravity_window (destroy_with, GDK_GRAVITY_WEST,
11273                                 "West");
11274   gtk_widget_show (window);
11275
11276     
11277   window = make_gravity_window (destroy_with, GDK_GRAVITY_EAST,
11278                                 "East");
11279   gtk_widget_show (window);
11280
11281   window = make_gravity_window (destroy_with, GDK_GRAVITY_CENTER,
11282                                 "Center");
11283   gtk_widget_show (window);
11284
11285   window = make_gravity_window (destroy_with, GDK_GRAVITY_STATIC,
11286                                 "Static");
11287   gtk_widget_show (window);
11288 }
11289
11290 static GtkWidget*
11291 window_controls (GtkWidget *window)
11292 {
11293   GtkWidget *control_window;
11294   GtkWidget *label;
11295   GtkWidget *vbox;
11296   GtkWidget *button;
11297   GtkWidget *spin;
11298   GtkAdjustment *adj;
11299   GtkWidget *entry;
11300   GtkWidget *om;
11301   GtkWidget *menu;
11302   gint i;
11303   
11304   control_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
11305
11306   gtk_window_set_screen (GTK_WINDOW (control_window),
11307                          gtk_widget_get_screen (window));
11308
11309   gtk_window_set_title (GTK_WINDOW (control_window), "Size controls");
11310   
11311   g_object_set_data (G_OBJECT (control_window),
11312                      "target",
11313                      window);
11314   
11315   g_signal_connect_object (control_window,
11316                            "destroy",
11317                            G_CALLBACK (gtk_widget_destroy),
11318                            window,
11319                            G_CONNECT_SWAPPED);
11320
11321   vbox = gtk_vbox_new (FALSE, 5);
11322   
11323   gtk_container_add (GTK_CONTAINER (control_window), vbox);
11324   
11325   label = gtk_label_new ("<no configure events>");
11326   gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
11327   
11328   g_signal_connect (window,
11329                     "configure_event",
11330                     G_CALLBACK (configure_event_callback),
11331                     label);
11332
11333   adj = (GtkAdjustment *) gtk_adjustment_new (10.0, -2000.0, 2000.0, 1.0,
11334                                               5.0, 0.0);
11335   spin = gtk_spin_button_new (adj, 0, 0);
11336
11337   gtk_box_pack_start (GTK_BOX (vbox), spin, FALSE, FALSE, 0);
11338
11339   g_object_set_data (G_OBJECT (control_window), "spin1", spin);
11340
11341   adj = (GtkAdjustment *) gtk_adjustment_new (10.0, -2000.0, 2000.0, 1.0,
11342                                               5.0, 0.0);
11343   spin = gtk_spin_button_new (adj, 0, 0);
11344
11345   gtk_box_pack_start (GTK_BOX (vbox), spin, FALSE, FALSE, 0);
11346
11347   g_object_set_data (G_OBJECT (control_window), "spin2", spin);
11348
11349   entry = gtk_entry_new ();
11350   gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
11351
11352   g_signal_connect (entry, "changed",
11353                     G_CALLBACK (set_geometry_callback),
11354                     control_window);
11355
11356   button = gtk_button_new_with_label ("Show gravity test windows");
11357   g_signal_connect_swapped (button,
11358                             "clicked",
11359                             G_CALLBACK (do_gravity_test),
11360                             control_window);
11361   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
11362
11363   button = gtk_button_new_with_label ("Reshow with initial size");
11364   g_signal_connect_object (button,
11365                            "clicked",
11366                            G_CALLBACK (gtk_window_reshow_with_initial_size),
11367                            window,
11368                            G_CONNECT_SWAPPED);
11369   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
11370   
11371   button = gtk_button_new_with_label ("Queue resize");
11372   g_signal_connect_object (button,
11373                            "clicked",
11374                            G_CALLBACK (gtk_widget_queue_resize),
11375                            window,
11376                            G_CONNECT_SWAPPED);
11377   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
11378   
11379   button = gtk_button_new_with_label ("Resize");
11380   g_signal_connect (button,
11381                     "clicked",
11382                     G_CALLBACK (set_size_callback),
11383                     control_window);
11384   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
11385
11386   button = gtk_button_new_with_label ("Set default size");
11387   g_signal_connect (button,
11388                     "clicked",
11389                     G_CALLBACK (set_default_size_callback),
11390                     control_window);
11391   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
11392
11393   button = gtk_button_new_with_label ("Unset default size");
11394   g_signal_connect (button,
11395                     "clicked",
11396                     G_CALLBACK (unset_default_size_callback),
11397                     control_window);
11398   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
11399   
11400   button = gtk_button_new_with_label ("Set size request");
11401   g_signal_connect (button,
11402                     "clicked",
11403                     G_CALLBACK (set_size_request_callback),
11404                     control_window);
11405   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
11406
11407   button = gtk_button_new_with_label ("Unset size request");
11408   g_signal_connect (button,
11409                     "clicked",
11410                     G_CALLBACK (unset_size_request_callback),
11411                     control_window);
11412   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
11413   
11414   button = gtk_button_new_with_label ("Move");
11415   g_signal_connect (button,
11416                     "clicked",
11417                     G_CALLBACK (set_location_callback),
11418                     control_window);
11419   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
11420
11421   button = gtk_button_new_with_label ("Move to current position");
11422   g_signal_connect (button,
11423                     "clicked",
11424                     G_CALLBACK (move_to_position_callback),
11425                     control_window);
11426   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
11427   
11428   button = gtk_check_button_new_with_label ("Allow shrink");
11429   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE);
11430   g_signal_connect (button,
11431                     "toggled",
11432                     G_CALLBACK (allow_shrink_callback),
11433                     control_window);
11434   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
11435
11436   button = gtk_check_button_new_with_label ("Allow grow");
11437   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
11438   g_signal_connect (button,
11439                     "toggled",
11440                     G_CALLBACK (allow_grow_callback),
11441                     control_window);
11442   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
11443   
11444   button = gtk_button_new_with_mnemonic ("_Show");
11445   g_signal_connect_object (button,
11446                            "clicked",
11447                            G_CALLBACK (gtk_widget_show),
11448                            window,
11449                            G_CONNECT_SWAPPED);
11450   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
11451
11452   button = gtk_button_new_with_mnemonic ("_Hide");
11453   g_signal_connect_object (button,
11454                            "clicked",
11455                            G_CALLBACK (gtk_widget_hide),
11456                            window,
11457                            G_CONNECT_SWAPPED);
11458   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
11459   
11460   menu = gtk_menu_new ();
11461   
11462   i = 0;
11463   while (i < 10)
11464     {
11465       GtkWidget *mi;
11466       static gchar *names[] = {
11467         "GDK_GRAVITY_NORTH_WEST",
11468         "GDK_GRAVITY_NORTH",
11469         "GDK_GRAVITY_NORTH_EAST",
11470         "GDK_GRAVITY_WEST",
11471         "GDK_GRAVITY_CENTER",
11472         "GDK_GRAVITY_EAST",
11473         "GDK_GRAVITY_SOUTH_WEST",
11474         "GDK_GRAVITY_SOUTH",
11475         "GDK_GRAVITY_SOUTH_EAST",
11476         "GDK_GRAVITY_STATIC",
11477         NULL
11478       };
11479
11480       g_assert (names[i]);
11481       
11482       mi = gtk_menu_item_new_with_label (names[i]);
11483
11484       gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
11485
11486       ++i;
11487     }
11488   
11489   gtk_widget_show_all (menu);
11490   
11491   om = gtk_option_menu_new ();
11492   gtk_option_menu_set_menu (GTK_OPTION_MENU (om), menu);
11493   
11494
11495   g_signal_connect (om,
11496                     "changed",
11497                     G_CALLBACK (gravity_selected),
11498                     control_window);
11499
11500   gtk_box_pack_end (GTK_BOX (vbox), om, FALSE, FALSE, 0);
11501
11502
11503   menu = gtk_menu_new ();
11504   
11505   i = 0;
11506   while (i < 5)
11507     {
11508       GtkWidget *mi;
11509       static gchar *names[] = {
11510         "GTK_WIN_POS_NONE",
11511         "GTK_WIN_POS_CENTER",
11512         "GTK_WIN_POS_MOUSE",
11513         "GTK_WIN_POS_CENTER_ALWAYS",
11514         "GTK_WIN_POS_CENTER_ON_PARENT",
11515         NULL
11516       };
11517
11518       g_assert (names[i]);
11519       
11520       mi = gtk_menu_item_new_with_label (names[i]);
11521
11522       gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
11523
11524       ++i;
11525     }
11526   
11527   gtk_widget_show_all (menu);
11528   
11529   om = gtk_option_menu_new ();
11530   gtk_option_menu_set_menu (GTK_OPTION_MENU (om), menu);
11531   
11532
11533   g_signal_connect (om,
11534                     "changed",
11535                     G_CALLBACK (pos_selected),
11536                     control_window);
11537
11538   gtk_box_pack_end (GTK_BOX (vbox), om, FALSE, FALSE, 0);
11539   
11540   gtk_widget_show_all (vbox);
11541   
11542   return control_window;
11543 }
11544
11545 void
11546 create_window_sizing (GtkWidget *widget)
11547 {
11548   static GtkWidget *window = NULL;
11549   static GtkWidget *target_window = NULL;
11550
11551   if (!target_window)
11552     {
11553       GtkWidget *label;
11554       
11555       target_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
11556       gtk_window_set_screen (GTK_WINDOW (target_window),
11557                              gtk_widget_get_screen (widget));
11558       label = gtk_label_new (NULL);
11559       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");
11560       gtk_container_add (GTK_CONTAINER (target_window), label);
11561       gtk_widget_show (label);
11562       
11563       g_signal_connect (target_window, "destroy",
11564                         G_CALLBACK (gtk_widget_destroyed),
11565                         &target_window);
11566
11567       window = window_controls (target_window);
11568       
11569       g_signal_connect (window, "destroy",
11570                         G_CALLBACK (gtk_widget_destroyed),
11571                         &window);
11572       
11573       gtk_window_set_title (GTK_WINDOW (target_window), "Window to size");
11574     }
11575
11576   /* don't show target window by default, we want to allow testing
11577    * of behavior on first show.
11578    */
11579   
11580   if (!GTK_WIDGET_VISIBLE (window))
11581     gtk_widget_show (window);
11582   else
11583     gtk_widget_destroy (window);
11584 }
11585
11586 /*
11587  * GtkProgressBar
11588  */
11589
11590 typedef struct _ProgressData {
11591   GtkWidget *window;
11592   GtkWidget *pbar;
11593   GtkWidget *block_spin;
11594   GtkWidget *x_align_spin;
11595   GtkWidget *y_align_spin;
11596   GtkWidget *step_spin;
11597   GtkWidget *act_blocks_spin;
11598   GtkWidget *label;
11599   GtkWidget *omenu1;
11600   GtkWidget *elmenu;
11601   GtkWidget *omenu2;
11602   GtkWidget *entry;
11603   int timer;
11604 } ProgressData;
11605
11606 gint
11607 progress_timeout (gpointer data)
11608 {
11609   gdouble new_val;
11610   GtkAdjustment *adj;
11611
11612   adj = GTK_PROGRESS (data)->adjustment;
11613
11614   new_val = adj->value + 1;
11615   if (new_val > adj->upper)
11616     new_val = adj->lower;
11617
11618   gtk_progress_set_value (GTK_PROGRESS (data), new_val);
11619
11620   return TRUE;
11621 }
11622
11623 static void
11624 destroy_progress (GtkWidget     *widget,
11625                   ProgressData **pdata)
11626 {
11627   gtk_timeout_remove ((*pdata)->timer);
11628   (*pdata)->timer = 0;
11629   (*pdata)->window = NULL;
11630   g_free (*pdata);
11631   *pdata = NULL;
11632 }
11633
11634 static void
11635 progressbar_toggle_orientation (GtkWidget *widget, gpointer data)
11636 {
11637   ProgressData *pdata;
11638   gint i;
11639
11640   pdata = (ProgressData *) data;
11641
11642   if (!GTK_WIDGET_MAPPED (widget))
11643     return;
11644
11645   i = gtk_option_menu_get_history (GTK_OPTION_MENU (widget));
11646
11647   gtk_progress_bar_set_orientation (GTK_PROGRESS_BAR (pdata->pbar),
11648                                     (GtkProgressBarOrientation) i);
11649 }
11650
11651 static void
11652 toggle_show_text (GtkWidget *widget, ProgressData *pdata)
11653 {
11654   gtk_progress_set_show_text (GTK_PROGRESS (pdata->pbar),
11655                               GTK_TOGGLE_BUTTON (widget)->active);
11656   gtk_widget_set_sensitive (pdata->entry, GTK_TOGGLE_BUTTON (widget)->active);
11657   gtk_widget_set_sensitive (pdata->x_align_spin,
11658                             GTK_TOGGLE_BUTTON (widget)->active);
11659   gtk_widget_set_sensitive (pdata->y_align_spin,
11660                             GTK_TOGGLE_BUTTON (widget)->active);
11661 }
11662
11663 static void
11664 progressbar_toggle_ellipsize (GtkWidget *widget,
11665                               gpointer   data)
11666 {
11667   ProgressData *pdata = data;
11668   if (GTK_WIDGET_DRAWABLE (widget))
11669     {
11670       gint i = gtk_option_menu_get_history (GTK_OPTION_MENU (widget));
11671       gtk_progress_bar_set_ellipsize (GTK_PROGRESS_BAR (pdata->pbar), i);
11672     }
11673 }
11674
11675 static void
11676 progressbar_toggle_bar_style (GtkWidget *widget, gpointer data)
11677 {
11678   ProgressData *pdata;
11679   gint i;
11680
11681   pdata = (ProgressData *) data;
11682
11683   if (!GTK_WIDGET_MAPPED (widget))
11684     return;
11685
11686   i = gtk_option_menu_get_history (GTK_OPTION_MENU (widget));
11687
11688   if (i == 1)
11689     gtk_widget_set_sensitive (pdata->block_spin, TRUE);
11690   else
11691     gtk_widget_set_sensitive (pdata->block_spin, FALSE);
11692   
11693   gtk_progress_bar_set_bar_style (GTK_PROGRESS_BAR (pdata->pbar),
11694                                   (GtkProgressBarStyle) i);
11695 }
11696
11697 static void
11698 progress_value_changed (GtkAdjustment *adj, ProgressData *pdata)
11699 {
11700   char buf[20];
11701
11702   if (GTK_PROGRESS (pdata->pbar)->activity_mode)
11703     sprintf (buf, "???");
11704   else
11705     sprintf (buf, "%.0f%%", 100 *
11706              gtk_progress_get_current_percentage (GTK_PROGRESS (pdata->pbar)));
11707   gtk_label_set_text (GTK_LABEL (pdata->label), buf);
11708 }
11709
11710 static void
11711 adjust_blocks (GtkAdjustment *adj, ProgressData *pdata)
11712 {
11713   gtk_progress_set_percentage (GTK_PROGRESS (pdata->pbar), 0);
11714   gtk_progress_bar_set_discrete_blocks (GTK_PROGRESS_BAR (pdata->pbar),
11715      gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (pdata->block_spin)));
11716 }
11717
11718 static void
11719 adjust_step (GtkAdjustment *adj, ProgressData *pdata)
11720 {
11721   gtk_progress_bar_set_activity_step (GTK_PROGRESS_BAR (pdata->pbar),
11722      gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (pdata->step_spin)));
11723 }
11724
11725 static void
11726 adjust_act_blocks (GtkAdjustment *adj, ProgressData *pdata)
11727 {
11728   gtk_progress_bar_set_activity_blocks (GTK_PROGRESS_BAR (pdata->pbar),
11729                gtk_spin_button_get_value_as_int 
11730                       (GTK_SPIN_BUTTON (pdata->act_blocks_spin)));
11731 }
11732
11733 static void
11734 adjust_align (GtkAdjustment *adj, ProgressData *pdata)
11735 {
11736   gtk_progress_set_text_alignment (GTK_PROGRESS (pdata->pbar),
11737          gtk_spin_button_get_value (GTK_SPIN_BUTTON (pdata->x_align_spin)),
11738          gtk_spin_button_get_value (GTK_SPIN_BUTTON (pdata->y_align_spin)));
11739 }
11740
11741 static void
11742 toggle_activity_mode (GtkWidget *widget, ProgressData *pdata)
11743 {
11744   gtk_progress_set_activity_mode (GTK_PROGRESS (pdata->pbar),
11745                                   GTK_TOGGLE_BUTTON (widget)->active);
11746   gtk_widget_set_sensitive (pdata->step_spin, 
11747                             GTK_TOGGLE_BUTTON (widget)->active);
11748   gtk_widget_set_sensitive (pdata->act_blocks_spin, 
11749                             GTK_TOGGLE_BUTTON (widget)->active);
11750 }
11751
11752 static void
11753 entry_changed (GtkWidget *widget, ProgressData *pdata)
11754 {
11755   gtk_progress_set_format_string (GTK_PROGRESS (pdata->pbar),
11756                           gtk_entry_get_text (GTK_ENTRY (pdata->entry)));
11757 }
11758
11759 void
11760 create_progress_bar (GtkWidget *widget)
11761 {
11762   GtkWidget *button;
11763   GtkWidget *vbox;
11764   GtkWidget *vbox2;
11765   GtkWidget *hbox;
11766   GtkWidget *check;
11767   GtkWidget *frame;
11768   GtkWidget *tab;
11769   GtkWidget *label;
11770   GtkWidget *align;
11771   GtkAdjustment *adj;
11772   static ProgressData *pdata = NULL;
11773
11774   static gchar *items1[] =
11775   {
11776     "Left-Right",
11777     "Right-Left",
11778     "Bottom-Top",
11779     "Top-Bottom"
11780   };
11781
11782   static gchar *items2[] =
11783   {
11784     "Continuous",
11785     "Discrete"
11786   };
11787
11788   static char *ellipsize_items[] = {
11789     "None",     // PANGO_ELLIPSIZE_NONE,
11790     "Start",    // PANGO_ELLIPSIZE_START,
11791     "Middle",   // PANGO_ELLIPSIZE_MIDDLE,
11792     "End",      // PANGO_ELLIPSIZE_END
11793   };
11794   
11795   if (!pdata)
11796     pdata = g_new0 (ProgressData, 1);
11797
11798   if (!pdata->window)
11799     {
11800       pdata->window = gtk_dialog_new ();
11801
11802       gtk_window_set_screen (GTK_WINDOW (pdata->window),
11803                              gtk_widget_get_screen (widget));
11804
11805       gtk_window_set_resizable (GTK_WINDOW (pdata->window), TRUE);
11806
11807       g_signal_connect (pdata->window, "destroy",
11808                         G_CALLBACK (destroy_progress),
11809                         &pdata);
11810
11811       pdata->timer = 0;
11812
11813       gtk_window_set_title (GTK_WINDOW (pdata->window), "GtkProgressBar");
11814       gtk_container_set_border_width (GTK_CONTAINER (pdata->window), 0);
11815
11816       vbox = gtk_vbox_new (FALSE, 5);
11817       gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
11818       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (pdata->window)->vbox), 
11819                           vbox, FALSE, TRUE, 0);
11820
11821       frame = gtk_frame_new ("Progress");
11822       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
11823
11824       vbox2 = gtk_vbox_new (FALSE, 5);
11825       gtk_container_add (GTK_CONTAINER (frame), vbox2);
11826
11827       align = gtk_alignment_new (0.5, 0.5, 0, 0);
11828       gtk_box_pack_start (GTK_BOX (vbox2), align, FALSE, FALSE, 5);
11829
11830       adj = (GtkAdjustment *) gtk_adjustment_new (0, 1, 300, 0, 0, 0);
11831       g_signal_connect (adj, "value_changed",
11832                         G_CALLBACK (progress_value_changed), pdata);
11833
11834       pdata->pbar = g_object_new (GTK_TYPE_PROGRESS_BAR,
11835                                     "adjustment", adj,
11836                                     "ellipsize", PANGO_ELLIPSIZE_MIDDLE,
11837                                     NULL);
11838       gtk_progress_set_format_string (GTK_PROGRESS (pdata->pbar),
11839                                       "%v from [%l,%u] (=%p%%)");
11840       gtk_container_add (GTK_CONTAINER (align), pdata->pbar);
11841       pdata->timer = gtk_timeout_add (100, progress_timeout, pdata->pbar);
11842
11843       align = gtk_alignment_new (0.5, 0.5, 0, 0);
11844       gtk_box_pack_start (GTK_BOX (vbox2), align, FALSE, FALSE, 5);
11845
11846       hbox = gtk_hbox_new (FALSE, 5);
11847       gtk_container_add (GTK_CONTAINER (align), hbox);
11848       label = gtk_label_new ("Label updated by user :"); 
11849       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
11850       pdata->label = gtk_label_new ("");
11851       gtk_box_pack_start (GTK_BOX (hbox), pdata->label, FALSE, TRUE, 0);
11852
11853       frame = gtk_frame_new ("Options");
11854       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
11855
11856       vbox2 = gtk_vbox_new (FALSE, 5);
11857       gtk_container_add (GTK_CONTAINER (frame), vbox2);
11858
11859       tab = gtk_table_new (7, 2, FALSE);
11860       gtk_box_pack_start (GTK_BOX (vbox2), tab, FALSE, TRUE, 0);
11861
11862       label = gtk_label_new ("Orientation :");
11863       gtk_table_attach (GTK_TABLE (tab), label, 0, 1, 0, 1,
11864                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
11865                         5, 5);
11866       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
11867
11868       pdata->omenu1 = build_option_menu (items1, 4, 0,
11869                                          progressbar_toggle_orientation,
11870                                          pdata);
11871       hbox = gtk_hbox_new (FALSE, 0);
11872       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 0, 1,
11873                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
11874                         5, 5);
11875       gtk_box_pack_start (GTK_BOX (hbox), pdata->omenu1, TRUE, TRUE, 0);
11876       
11877       check = gtk_check_button_new_with_label ("Show text");
11878       g_signal_connect (check, "clicked",
11879                         G_CALLBACK (toggle_show_text),
11880                         pdata);
11881       gtk_table_attach (GTK_TABLE (tab), check, 0, 1, 1, 2,
11882                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
11883                         5, 5);
11884
11885       hbox = gtk_hbox_new (FALSE, 0);
11886       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 1, 2,
11887                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
11888                         5, 5);
11889
11890       label = gtk_label_new ("Format : ");
11891       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
11892
11893       pdata->entry = gtk_entry_new ();
11894       g_signal_connect (pdata->entry, "changed",
11895                         G_CALLBACK (entry_changed),
11896                         pdata);
11897       gtk_box_pack_start (GTK_BOX (hbox), pdata->entry, TRUE, TRUE, 0);
11898       gtk_entry_set_text (GTK_ENTRY (pdata->entry), "%v from [%l,%u] (=%p%%)");
11899       gtk_widget_set_size_request (pdata->entry, 100, -1);
11900       gtk_widget_set_sensitive (pdata->entry, FALSE);
11901
11902       label = gtk_label_new ("Text align :");
11903       gtk_table_attach (GTK_TABLE (tab), label, 0, 1, 2, 3,
11904                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
11905                         5, 5);
11906       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
11907
11908       hbox = gtk_hbox_new (FALSE, 0);
11909       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 2, 3,
11910                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
11911                         5, 5);
11912
11913       label = gtk_label_new ("x :");
11914       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 5);
11915       
11916       adj = (GtkAdjustment *) gtk_adjustment_new (0.5, 0, 1, 0.1, 0.1, 0);
11917       pdata->x_align_spin = gtk_spin_button_new (adj, 0, 1);
11918       g_signal_connect (adj, "value_changed",
11919                         G_CALLBACK (adjust_align), pdata);
11920       gtk_box_pack_start (GTK_BOX (hbox), pdata->x_align_spin, FALSE, TRUE, 0);
11921       gtk_widget_set_sensitive (pdata->x_align_spin, FALSE);
11922
11923       label = gtk_label_new ("y :");
11924       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 5);
11925
11926       adj = (GtkAdjustment *) gtk_adjustment_new (0.5, 0, 1, 0.1, 0.1, 0);
11927       pdata->y_align_spin = gtk_spin_button_new (adj, 0, 1);
11928       g_signal_connect (adj, "value_changed",
11929                         G_CALLBACK (adjust_align), pdata);
11930       gtk_box_pack_start (GTK_BOX (hbox), pdata->y_align_spin, FALSE, TRUE, 0);
11931       gtk_widget_set_sensitive (pdata->y_align_spin, FALSE);
11932
11933       label = gtk_label_new ("Ellipsize text :");
11934       gtk_table_attach (GTK_TABLE (tab), label, 0, 1, 10, 11,
11935                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
11936                         5, 5);
11937       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
11938       pdata->elmenu = build_option_menu (ellipsize_items,
11939                                          sizeof (ellipsize_items) / sizeof (ellipsize_items[0]),
11940                                          2, // PANGO_ELLIPSIZE_MIDDLE
11941                                          progressbar_toggle_ellipsize,
11942                                          pdata);
11943       hbox = gtk_hbox_new (FALSE, 0);
11944       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 10, 11,
11945                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
11946                         5, 5);
11947       gtk_box_pack_start (GTK_BOX (hbox), pdata->elmenu, TRUE, TRUE, 0);
11948
11949       label = gtk_label_new ("Bar Style :");
11950       gtk_table_attach (GTK_TABLE (tab), label, 0, 1, 13, 14,
11951                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
11952                         5, 5);
11953       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
11954
11955       pdata->omenu2 = build_option_menu (items2, 2, 0,
11956                                          progressbar_toggle_bar_style,
11957                                          pdata);
11958       hbox = gtk_hbox_new (FALSE, 0);
11959       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 13, 14,
11960                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
11961                         5, 5);
11962       gtk_box_pack_start (GTK_BOX (hbox), pdata->omenu2, TRUE, TRUE, 0);
11963
11964       label = gtk_label_new ("Block count :");
11965       gtk_table_attach (GTK_TABLE (tab), label, 0, 1, 14, 15,
11966                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
11967                         5, 5);
11968       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
11969
11970       hbox = gtk_hbox_new (FALSE, 0);
11971       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 14, 15,
11972                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
11973                         5, 5);
11974       adj = (GtkAdjustment *) gtk_adjustment_new (10, 2, 20, 1, 5, 0);
11975       pdata->block_spin = gtk_spin_button_new (adj, 0, 0);
11976       g_signal_connect (adj, "value_changed",
11977                         G_CALLBACK (adjust_blocks), pdata);
11978       gtk_box_pack_start (GTK_BOX (hbox), pdata->block_spin, FALSE, TRUE, 0);
11979       gtk_widget_set_sensitive (pdata->block_spin, FALSE);
11980
11981       check = gtk_check_button_new_with_label ("Activity mode");
11982       g_signal_connect (check, "clicked",
11983                         G_CALLBACK (toggle_activity_mode), pdata);
11984       gtk_table_attach (GTK_TABLE (tab), check, 0, 1, 15, 16,
11985                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
11986                         5, 5);
11987
11988       hbox = gtk_hbox_new (FALSE, 0);
11989       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 15, 16,
11990                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
11991                         5, 5);
11992       label = gtk_label_new ("Step size : ");
11993       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
11994       adj = (GtkAdjustment *) gtk_adjustment_new (3, 1, 20, 1, 5, 0);
11995       pdata->step_spin = gtk_spin_button_new (adj, 0, 0);
11996       g_signal_connect (adj, "value_changed",
11997                         G_CALLBACK (adjust_step), pdata);
11998       gtk_box_pack_start (GTK_BOX (hbox), pdata->step_spin, FALSE, TRUE, 0);
11999       gtk_widget_set_sensitive (pdata->step_spin, FALSE);
12000
12001       hbox = gtk_hbox_new (FALSE, 0);
12002       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 16, 17,
12003                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
12004                         5, 5);
12005       label = gtk_label_new ("Blocks :     ");
12006       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
12007       adj = (GtkAdjustment *) gtk_adjustment_new (5, 2, 10, 1, 5, 0);
12008       pdata->act_blocks_spin = gtk_spin_button_new (adj, 0, 0);
12009       g_signal_connect (adj, "value_changed",
12010                         G_CALLBACK (adjust_act_blocks), pdata);
12011       gtk_box_pack_start (GTK_BOX (hbox), pdata->act_blocks_spin, FALSE, TRUE,
12012                           0);
12013       gtk_widget_set_sensitive (pdata->act_blocks_spin, FALSE);
12014
12015       button = gtk_button_new_with_label ("close");
12016       g_signal_connect_swapped (button, "clicked",
12017                                 G_CALLBACK (gtk_widget_destroy),
12018                                 pdata->window);
12019       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
12020       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (pdata->window)->action_area), 
12021                           button, TRUE, TRUE, 0);
12022       gtk_widget_grab_default (button);
12023     }
12024
12025   if (!GTK_WIDGET_VISIBLE (pdata->window))
12026     gtk_widget_show_all (pdata->window);
12027   else
12028     gtk_widget_destroy (pdata->window);
12029 }
12030
12031 /*
12032  * Properties
12033  */
12034
12035 typedef struct {
12036   int x;
12037   int y;
12038   gboolean found;
12039   gboolean first;
12040   GtkWidget *res_widget;
12041 } FindWidgetData;
12042
12043 static void
12044 find_widget (GtkWidget *widget, FindWidgetData *data)
12045 {
12046   GtkAllocation new_allocation;
12047   gint x_offset = 0;
12048   gint y_offset = 0;
12049
12050   new_allocation = widget->allocation;
12051
12052   if (data->found || !GTK_WIDGET_MAPPED (widget))
12053     return;
12054
12055   /* Note that in the following code, we only count the
12056    * position as being inside a WINDOW widget if it is inside
12057    * widget->window; points that are outside of widget->window
12058    * but within the allocation are not counted. This is consistent
12059    * with the way we highlight drag targets.
12060    */
12061   if (!GTK_WIDGET_NO_WINDOW (widget))
12062     {
12063       new_allocation.x = 0;
12064       new_allocation.y = 0;
12065     }
12066   
12067   if (widget->parent && !data->first)
12068     {
12069       GdkWindow *window = widget->window;
12070       while (window != widget->parent->window)
12071         {
12072           gint tx, ty, twidth, theight;
12073           gdk_drawable_get_size (window, &twidth, &theight);
12074
12075           if (new_allocation.x < 0)
12076             {
12077               new_allocation.width += new_allocation.x;
12078               new_allocation.x = 0;
12079             }
12080           if (new_allocation.y < 0)
12081             {
12082               new_allocation.height += new_allocation.y;
12083               new_allocation.y = 0;
12084             }
12085           if (new_allocation.x + new_allocation.width > twidth)
12086             new_allocation.width = twidth - new_allocation.x;
12087           if (new_allocation.y + new_allocation.height > theight)
12088             new_allocation.height = theight - new_allocation.y;
12089
12090           gdk_window_get_position (window, &tx, &ty);
12091           new_allocation.x += tx;
12092           x_offset += tx;
12093           new_allocation.y += ty;
12094           y_offset += ty;
12095           
12096           window = gdk_window_get_parent (window);
12097         }
12098     }
12099
12100   if ((data->x >= new_allocation.x) && (data->y >= new_allocation.y) &&
12101       (data->x < new_allocation.x + new_allocation.width) && 
12102       (data->y < new_allocation.y + new_allocation.height))
12103     {
12104       /* First, check if the drag is in a valid drop site in
12105        * one of our children 
12106        */
12107       if (GTK_IS_CONTAINER (widget))
12108         {
12109           FindWidgetData new_data = *data;
12110           
12111           new_data.x -= x_offset;
12112           new_data.y -= y_offset;
12113           new_data.found = FALSE;
12114           new_data.first = FALSE;
12115           
12116           gtk_container_forall (GTK_CONTAINER (widget),
12117                                 (GtkCallback)find_widget,
12118                                 &new_data);
12119           
12120           data->found = new_data.found;
12121           if (data->found)
12122             data->res_widget = new_data.res_widget;
12123         }
12124
12125       /* If not, and this widget is registered as a drop site, check to
12126        * emit "drag_motion" to check if we are actually in
12127        * a drop site.
12128        */
12129       if (!data->found)
12130         {
12131           data->found = TRUE;
12132           data->res_widget = widget;
12133         }
12134     }
12135 }
12136
12137 static GtkWidget *
12138 find_widget_at_pointer (GdkDisplay *display)
12139 {
12140   GtkWidget *widget = NULL;
12141   GdkWindow *pointer_window;
12142   gint x, y;
12143   FindWidgetData data;
12144  
12145  pointer_window = gdk_display_get_window_at_pointer (display, NULL, NULL);
12146  
12147  if (pointer_window)
12148    {
12149      gpointer widget_ptr;
12150
12151      gdk_window_get_user_data (pointer_window, &widget_ptr);
12152      widget = widget_ptr;
12153    }
12154
12155  if (widget)
12156    {
12157      gdk_window_get_pointer (widget->window,
12158                              &x, &y, NULL);
12159      
12160      data.x = x;
12161      data.y = y;
12162      data.found = FALSE;
12163      data.first = TRUE;
12164
12165      find_widget (widget, &data);
12166      if (data.found)
12167        return data.res_widget;
12168      return widget;
12169    }
12170  return NULL;
12171 }
12172
12173 struct PropertiesData {
12174   GtkWidget **window;
12175   GdkCursor *cursor;
12176   gboolean in_query;
12177   gint handler;
12178 };
12179
12180 static void
12181 destroy_properties (GtkWidget             *widget,
12182                     struct PropertiesData *data)
12183 {
12184   if (data->window)
12185     {
12186       *data->window = NULL;
12187       data->window = NULL;
12188     }
12189
12190   if (data->cursor)
12191     {
12192       gdk_cursor_unref (data->cursor);
12193       data->cursor = NULL;
12194     }
12195
12196   if (data->handler)
12197     {
12198       g_signal_handler_disconnect (widget, data->handler);
12199       data->handler = 0;
12200     }
12201
12202   g_free (data);
12203 }
12204
12205 static gint
12206 property_query_event (GtkWidget        *widget,
12207                       GdkEvent         *event,
12208                       struct PropertiesData *data)
12209 {
12210   GtkWidget *res_widget = NULL;
12211
12212   if (!data->in_query)
12213     return FALSE;
12214   
12215   if (event->type == GDK_BUTTON_RELEASE)
12216     {
12217       gtk_grab_remove (widget);
12218       gdk_display_pointer_ungrab (gtk_widget_get_display (widget),
12219                                   GDK_CURRENT_TIME);
12220       
12221       res_widget = find_widget_at_pointer (gtk_widget_get_display (widget));
12222       if (res_widget)
12223         {
12224           g_object_set_data (G_OBJECT (res_widget), "prop-editor-screen",
12225                              gtk_widget_get_screen (widget));
12226           create_prop_editor (G_OBJECT (res_widget), 0);
12227         }
12228
12229       data->in_query = FALSE;
12230     }
12231   return FALSE;
12232 }
12233
12234
12235 static void
12236 query_properties (GtkButton *button,
12237                   struct PropertiesData *data)
12238 {
12239   gint failure;
12240
12241   g_signal_connect (button, "event",
12242                     G_CALLBACK (property_query_event), data);
12243
12244
12245   if (!data->cursor)
12246     data->cursor = gdk_cursor_new_for_display (gtk_widget_get_display (GTK_WIDGET (button)),
12247                                                GDK_TARGET);
12248   
12249   failure = gdk_pointer_grab (GTK_WIDGET (button)->window,
12250                               TRUE,
12251                               GDK_BUTTON_RELEASE_MASK,
12252                               NULL,
12253                               data->cursor,
12254                               GDK_CURRENT_TIME);
12255
12256   gtk_grab_add (GTK_WIDGET (button));
12257
12258   data->in_query = TRUE;
12259 }
12260
12261 static void
12262 create_properties (GtkWidget *widget)
12263 {
12264   static GtkWidget *window = NULL;
12265   GtkWidget *button;
12266   GtkWidget *vbox;
12267   GtkWidget *label;
12268   struct PropertiesData *data;
12269
12270   data = g_new (struct PropertiesData, 1);
12271   data->window = &window;
12272   data->in_query = FALSE;
12273   data->cursor = NULL;
12274   data->handler = 0;
12275
12276   if (!window)
12277     {
12278       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
12279
12280       gtk_window_set_screen (GTK_WINDOW (window),
12281                              gtk_widget_get_screen (widget));      
12282
12283       data->handler = g_signal_connect (window, "destroy",
12284                                         G_CALLBACK (destroy_properties),
12285                                         data);
12286
12287       gtk_window_set_title (GTK_WINDOW (window), "test properties");
12288       gtk_container_set_border_width (GTK_CONTAINER (window), 10);
12289
12290       vbox = gtk_vbox_new (FALSE, 1);
12291       gtk_container_add (GTK_CONTAINER (window), vbox);
12292             
12293       label = gtk_label_new ("This is just a dumb test to test properties.\nIf you need a generic module, get GLE.");
12294       gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
12295       
12296       button = gtk_button_new_with_label ("Query properties");
12297       gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
12298       g_signal_connect (button, "clicked",
12299                         G_CALLBACK (query_properties),
12300                         data);
12301     }
12302
12303   if (!GTK_WIDGET_VISIBLE (window))
12304     gtk_widget_show_all (window);
12305   else
12306     gtk_widget_destroy (window);
12307   
12308 }
12309
12310 struct SnapshotData {
12311   GtkWidget *toplevel_button;
12312   GtkWidget **window;
12313   GdkCursor *cursor;
12314   gboolean in_query;
12315   gboolean is_toplevel;
12316   gint handler;
12317 };
12318
12319 static void
12320 destroy_snapshot_data (GtkWidget             *widget,
12321                        struct SnapshotData *data)
12322 {
12323   if (*data->window)
12324     *data->window = NULL;
12325   
12326   if (data->cursor)
12327     {
12328       gdk_cursor_unref (data->cursor);
12329       data->cursor = NULL;
12330     }
12331
12332   if (data->handler)
12333     {
12334       g_signal_handler_disconnect (widget, data->handler);
12335       data->handler = 0;
12336     }
12337
12338   g_free (data);
12339 }
12340
12341 static gint
12342 snapshot_widget_event (GtkWidget               *widget,
12343                        GdkEvent        *event,
12344                        struct SnapshotData *data)
12345 {
12346   GtkWidget *res_widget = NULL;
12347
12348   if (!data->in_query)
12349     return FALSE;
12350   
12351   if (event->type == GDK_BUTTON_RELEASE)
12352     {
12353       gtk_grab_remove (widget);
12354       gdk_display_pointer_ungrab (gtk_widget_get_display (widget),
12355                                   GDK_CURRENT_TIME);
12356       
12357       res_widget = find_widget_at_pointer (gtk_widget_get_display (widget));
12358       if (data->is_toplevel && res_widget)
12359         res_widget = gtk_widget_get_toplevel (res_widget);
12360       if (res_widget)
12361         {
12362           GdkPixmap *pixmap;
12363           GtkWidget *window, *image;
12364
12365           window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
12366           pixmap = gtk_widget_get_snapshot (res_widget, NULL);
12367           gtk_widget_realize (window);
12368           if (gdk_drawable_get_depth (window->window) != gdk_drawable_get_depth (pixmap))
12369             {
12370               /* this branch is needed to convert ARGB -> RGB */
12371               int width, height;
12372               GdkPixbuf *pixbuf;
12373               gdk_drawable_get_size (pixmap, &width, &height);
12374               pixbuf = gdk_pixbuf_get_from_drawable (NULL, pixmap,
12375                                                      gtk_widget_get_colormap (res_widget),
12376                                                      0, 0,
12377                                                      0, 0,
12378                                                      width, height);
12379               image = gtk_image_new_from_pixbuf (pixbuf);
12380               g_object_unref (pixbuf);
12381             }
12382           else
12383             image = gtk_image_new_from_pixmap (pixmap, NULL);
12384           gtk_container_add (GTK_CONTAINER (window), image);
12385           g_object_unref (pixmap);
12386           gtk_widget_show_all (window);
12387         }
12388
12389       data->in_query = FALSE;
12390     }
12391   return FALSE;
12392 }
12393
12394
12395 static void
12396 snapshot_widget (GtkButton *button,
12397                  struct SnapshotData *data)
12398 {
12399   gint failure;
12400
12401   g_signal_connect (button, "event",
12402                     G_CALLBACK (snapshot_widget_event), data);
12403
12404   data->is_toplevel = GTK_WIDGET (button) == data->toplevel_button;
12405   
12406   if (!data->cursor)
12407     data->cursor = gdk_cursor_new_for_display (gtk_widget_get_display (GTK_WIDGET (button)),
12408                                                GDK_TARGET);
12409   
12410   failure = gdk_pointer_grab (GTK_WIDGET (button)->window,
12411                               TRUE,
12412                               GDK_BUTTON_RELEASE_MASK,
12413                               NULL,
12414                               data->cursor,
12415                               GDK_CURRENT_TIME);
12416
12417   gtk_grab_add (GTK_WIDGET (button));
12418
12419   data->in_query = TRUE;
12420 }
12421
12422 static void
12423 create_snapshot (GtkWidget *widget)
12424 {
12425   static GtkWidget *window = NULL;
12426   GtkWidget *button;
12427   GtkWidget *vbox;
12428   struct SnapshotData *data;
12429
12430   data = g_new (struct SnapshotData, 1);
12431   data->window = &window;
12432   data->in_query = FALSE;
12433   data->cursor = NULL;
12434   data->handler = 0;
12435
12436   if (!window)
12437     {
12438       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
12439
12440       gtk_window_set_screen (GTK_WINDOW (window),
12441                              gtk_widget_get_screen (widget));      
12442
12443       data->handler = g_signal_connect (window, "destroy",
12444                                         G_CALLBACK (destroy_snapshot_data),
12445                                         data);
12446
12447       gtk_window_set_title (GTK_WINDOW (window), "test snapshot");
12448       gtk_container_set_border_width (GTK_CONTAINER (window), 10);
12449
12450       vbox = gtk_vbox_new (FALSE, 1);
12451       gtk_container_add (GTK_CONTAINER (window), vbox);
12452             
12453       button = gtk_button_new_with_label ("Snapshot widget");
12454       gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
12455       g_signal_connect (button, "clicked",
12456                         G_CALLBACK (snapshot_widget),
12457                         data);
12458       
12459       button = gtk_button_new_with_label ("Snapshot toplevel");
12460       data->toplevel_button = button;
12461       gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
12462       g_signal_connect (button, "clicked",
12463                         G_CALLBACK (snapshot_widget),
12464                         data);
12465     }
12466
12467   if (!GTK_WIDGET_VISIBLE (window))
12468     gtk_widget_show_all (window);
12469   else
12470     gtk_widget_destroy (window);
12471   
12472 }
12473
12474
12475
12476 /*
12477  * Color Preview
12478  */
12479
12480 static int color_idle = 0;
12481
12482 gint
12483 color_idle_func (GtkWidget *preview)
12484 {
12485   static int count = 1;
12486   guchar buf[768];
12487   int i, j, k;
12488
12489   for (i = 0; i < 256; i++)
12490     {
12491       for (j = 0, k = 0; j < 256; j++)
12492         {
12493           buf[k+0] = i + count;
12494           buf[k+1] = 0;
12495           buf[k+2] = j + count;
12496           k += 3;
12497         }
12498
12499       gtk_preview_draw_row (GTK_PREVIEW (preview), buf, 0, i, 256);
12500     }
12501
12502   count += 1;
12503
12504   gtk_widget_queue_draw (preview);
12505   gdk_window_process_updates (preview->window, TRUE);
12506
12507   return TRUE;
12508 }
12509
12510 static void
12511 color_preview_destroy (GtkWidget  *widget,
12512                        GtkWidget **window)
12513 {
12514   gtk_idle_remove (color_idle);
12515   color_idle = 0;
12516
12517   *window = NULL;
12518 }
12519
12520 void
12521 create_color_preview (GtkWidget *widget)
12522 {
12523   static GtkWidget *window = NULL;
12524   GtkWidget *preview;
12525   guchar buf[768];
12526   int i, j, k;
12527
12528   if (!window)
12529     {
12530       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
12531       
12532       gtk_window_set_screen (GTK_WINDOW (window),
12533                              gtk_widget_get_screen (widget));
12534
12535       g_signal_connect (window, "destroy",
12536                         G_CALLBACK (color_preview_destroy),
12537                         &window);
12538
12539       gtk_window_set_title (GTK_WINDOW (window), "test");
12540       gtk_container_set_border_width (GTK_CONTAINER (window), 10);
12541
12542       preview = gtk_preview_new (GTK_PREVIEW_COLOR);
12543       gtk_preview_size (GTK_PREVIEW (preview), 256, 256);
12544       gtk_container_add (GTK_CONTAINER (window), preview);
12545
12546       for (i = 0; i < 256; i++)
12547         {
12548           for (j = 0, k = 0; j < 256; j++)
12549             {
12550               buf[k+0] = i;
12551               buf[k+1] = 0;
12552               buf[k+2] = j;
12553               k += 3;
12554             }
12555
12556           gtk_preview_draw_row (GTK_PREVIEW (preview), buf, 0, i, 256);
12557         }
12558
12559       color_idle = gtk_idle_add ((GtkFunction) color_idle_func, preview);
12560     }
12561
12562   if (!GTK_WIDGET_VISIBLE (window))
12563     gtk_widget_show_all (window);
12564   else
12565     gtk_widget_destroy (window);
12566 }
12567
12568 /*
12569  * Gray Preview
12570  */
12571
12572 static int gray_idle = 0;
12573
12574 gint
12575 gray_idle_func (GtkWidget *preview)
12576 {
12577   static int count = 1;
12578   guchar buf[256];
12579   int i, j;
12580
12581   for (i = 0; i < 256; i++)
12582     {
12583       for (j = 0; j < 256; j++)
12584         buf[j] = i + j + count;
12585
12586       gtk_preview_draw_row (GTK_PREVIEW (preview), buf, 0, i, 256);
12587     }
12588
12589   count += 1;
12590
12591   gtk_widget_draw (preview, NULL);
12592
12593   return TRUE;
12594 }
12595
12596 static void
12597 gray_preview_destroy (GtkWidget  *widget,
12598                       GtkWidget **window)
12599 {
12600   gtk_idle_remove (gray_idle);
12601   gray_idle = 0;
12602
12603   *window = NULL;
12604 }
12605
12606 void
12607 create_gray_preview (GtkWidget *widget)
12608 {
12609   static GtkWidget *window = NULL;
12610   GtkWidget *preview;
12611   guchar buf[256];
12612   int i, j;
12613
12614   if (!window)
12615     {
12616       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
12617
12618       gtk_window_set_screen (GTK_WINDOW (window),
12619                              gtk_widget_get_screen (widget));
12620
12621       g_signal_connect (window, "destroy",
12622                         G_CALLBACK (gray_preview_destroy),
12623                         &window);
12624
12625       gtk_window_set_title (GTK_WINDOW (window), "test");
12626       gtk_container_set_border_width (GTK_CONTAINER (window), 10);
12627
12628       preview = gtk_preview_new (GTK_PREVIEW_GRAYSCALE);
12629       gtk_preview_size (GTK_PREVIEW (preview), 256, 256);
12630       gtk_container_add (GTK_CONTAINER (window), preview);
12631
12632       for (i = 0; i < 256; i++)
12633         {
12634           for (j = 0; j < 256; j++)
12635             buf[j] = i + j;
12636
12637           gtk_preview_draw_row (GTK_PREVIEW (preview), buf, 0, i, 256);
12638         }
12639
12640       gray_idle = gtk_idle_add ((GtkFunction) gray_idle_func, preview);
12641     }
12642
12643   if (!GTK_WIDGET_VISIBLE (window))
12644     gtk_widget_show_all (window);
12645   else
12646     gtk_widget_destroy (window);
12647 }
12648
12649
12650 /*
12651  * Selection Test
12652  */
12653
12654 void
12655 selection_test_received (GtkWidget *list, GtkSelectionData *data)
12656 {
12657   GdkAtom *atoms;
12658   GtkWidget *list_item;
12659   GList *item_list;
12660   int i, l;
12661
12662   if (data->length < 0)
12663     {
12664       g_print ("Selection retrieval failed\n");
12665       return;
12666     }
12667   if (data->type != GDK_SELECTION_TYPE_ATOM)
12668     {
12669       g_print ("Selection \"TARGETS\" was not returned as atoms!\n");
12670       return;
12671     }
12672
12673   /* Clear out any current list items */
12674
12675   gtk_list_clear_items (GTK_LIST(list), 0, -1);
12676
12677   /* Add new items to list */
12678
12679   atoms = (GdkAtom *)data->data;
12680
12681   item_list = NULL;
12682   l = data->length / sizeof (GdkAtom);
12683   for (i = 0; i < l; i++)
12684     {
12685       char *name;
12686       name = gdk_atom_name (atoms[i]);
12687       if (name != NULL)
12688         {
12689           list_item = gtk_list_item_new_with_label (name);
12690           g_free (name);
12691         }
12692       else
12693         list_item = gtk_list_item_new_with_label ("(bad atom)");
12694
12695       gtk_widget_show (list_item);
12696       item_list = g_list_append (item_list, list_item);
12697     }
12698
12699   gtk_list_append_items (GTK_LIST (list), item_list);
12700
12701   return;
12702 }
12703
12704 void
12705 selection_test_get_targets (GtkWidget *widget, GtkWidget *list)
12706 {
12707   static GdkAtom targets_atom = GDK_NONE;
12708
12709   if (targets_atom == GDK_NONE)
12710     targets_atom = gdk_atom_intern ("TARGETS", FALSE);
12711
12712   gtk_selection_convert (list, GDK_SELECTION_PRIMARY, targets_atom,
12713                          GDK_CURRENT_TIME);
12714 }
12715
12716 void
12717 create_selection_test (GtkWidget *widget)
12718 {
12719   static GtkWidget *window = NULL;
12720   GtkWidget *button;
12721   GtkWidget *vbox;
12722   GtkWidget *scrolled_win;
12723   GtkWidget *list;
12724   GtkWidget *label;
12725
12726   if (!window)
12727     {
12728       window = gtk_dialog_new ();
12729       
12730       gtk_window_set_screen (GTK_WINDOW (window),
12731                              gtk_widget_get_screen (widget));
12732
12733       g_signal_connect (window, "destroy",
12734                         G_CALLBACK (gtk_widget_destroyed),
12735                         &window);
12736
12737       gtk_window_set_title (GTK_WINDOW (window), "Selection Test");
12738       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
12739
12740       /* Create the list */
12741
12742       vbox = gtk_vbox_new (FALSE, 5);
12743       gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
12744       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), vbox,
12745                           TRUE, TRUE, 0);
12746
12747       label = gtk_label_new ("Gets available targets for current selection");
12748       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
12749
12750       scrolled_win = gtk_scrolled_window_new (NULL, NULL);
12751       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
12752                                       GTK_POLICY_AUTOMATIC, 
12753                                       GTK_POLICY_AUTOMATIC);
12754       gtk_box_pack_start (GTK_BOX (vbox), scrolled_win, TRUE, TRUE, 0);
12755       gtk_widget_set_size_request (scrolled_win, 100, 200);
12756
12757       list = gtk_list_new ();
12758       gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_win), list);
12759
12760       g_signal_connect (list, "selection_received",
12761                         G_CALLBACK (selection_test_received), NULL);
12762
12763       /* .. And create some buttons */
12764       button = gtk_button_new_with_label ("Get Targets");
12765       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area),
12766                           button, TRUE, TRUE, 0);
12767
12768       g_signal_connect (button, "clicked",
12769                         G_CALLBACK (selection_test_get_targets), list);
12770
12771       button = gtk_button_new_with_label ("Quit");
12772       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area),
12773                           button, TRUE, TRUE, 0);
12774
12775       g_signal_connect_swapped (button, "clicked",
12776                                 G_CALLBACK (gtk_widget_destroy),
12777                                 window);
12778     }
12779
12780   if (!GTK_WIDGET_VISIBLE (window))
12781     gtk_widget_show_all (window);
12782   else
12783     gtk_widget_destroy (window);
12784 }
12785
12786 /*
12787  * Gamma Curve
12788  */
12789
12790 void
12791 create_gamma_curve (GtkWidget *widget)
12792 {
12793   static GtkWidget *window = NULL, *curve;
12794   static int count = 0;
12795   gfloat vec[256];
12796   gint max;
12797   gint i;
12798   
12799   if (!window)
12800     {
12801       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
12802       gtk_window_set_screen (GTK_WINDOW (window),
12803                              gtk_widget_get_screen (widget));
12804
12805       gtk_window_set_title (GTK_WINDOW (window), "test");
12806       gtk_container_set_border_width (GTK_CONTAINER (window), 10);
12807
12808       g_signal_connect (window, "destroy",
12809                         G_CALLBACK(gtk_widget_destroyed),
12810                         &window);
12811
12812       curve = gtk_gamma_curve_new ();
12813       gtk_container_add (GTK_CONTAINER (window), curve);
12814       gtk_widget_show (curve);
12815     }
12816
12817   max = 127 + (count % 2)*128;
12818   gtk_curve_set_range (GTK_CURVE (GTK_GAMMA_CURVE (curve)->curve),
12819                        0, max, 0, max);
12820   for (i = 0; i < max; ++i)
12821     vec[i] = (127 / sqrt (max)) * sqrt (i);
12822   gtk_curve_set_vector (GTK_CURVE (GTK_GAMMA_CURVE (curve)->curve),
12823                         max, vec);
12824
12825   if (!GTK_WIDGET_VISIBLE (window))
12826     gtk_widget_show (window);
12827   else if (count % 4 == 3)
12828     {
12829       gtk_widget_destroy (window);
12830       window = NULL;
12831     }
12832
12833   ++count;
12834 }
12835
12836 /*
12837  * Test scrolling
12838  */
12839
12840 static int scroll_test_pos = 0.0;
12841
12842 static gint
12843 scroll_test_expose (GtkWidget *widget, GdkEventExpose *event,
12844                     GtkAdjustment *adj)
12845 {
12846   gint i,j;
12847   gint imin, imax, jmin, jmax;
12848   
12849   imin = (event->area.x) / 10;
12850   imax = (event->area.x + event->area.width + 9) / 10;
12851
12852   jmin = ((int)adj->value + event->area.y) / 10;
12853   jmax = ((int)adj->value + event->area.y + event->area.height + 9) / 10;
12854
12855   gdk_window_clear_area (widget->window,
12856                          event->area.x, event->area.y,
12857                          event->area.width, event->area.height);
12858
12859   for (i=imin; i<imax; i++)
12860     for (j=jmin; j<jmax; j++)
12861       if ((i+j) % 2)
12862         gdk_draw_rectangle (widget->window, 
12863                             widget->style->black_gc,
12864                             TRUE,
12865                             10*i, 10*j - (int)adj->value, 1+i%10, 1+j%10);
12866
12867   return TRUE;
12868 }
12869
12870 static gint
12871 scroll_test_scroll (GtkWidget *widget, GdkEventScroll *event,
12872                     GtkAdjustment *adj)
12873 {
12874   gdouble new_value = adj->value + ((event->direction == GDK_SCROLL_UP) ?
12875                                     -adj->page_increment / 2:
12876                                     adj->page_increment / 2);
12877   new_value = CLAMP (new_value, adj->lower, adj->upper - adj->page_size);
12878   gtk_adjustment_set_value (adj, new_value);  
12879   
12880   return TRUE;
12881 }
12882
12883 static void
12884 scroll_test_configure (GtkWidget *widget, GdkEventConfigure *event,
12885                        GtkAdjustment *adj)
12886 {
12887   adj->page_increment = 0.9 * widget->allocation.height;
12888   adj->page_size = widget->allocation.height;
12889
12890   g_signal_emit_by_name (adj, "changed");
12891 }
12892
12893 static void
12894 scroll_test_adjustment_changed (GtkAdjustment *adj, GtkWidget *widget)
12895 {
12896   /* gint source_min = (int)adj->value - scroll_test_pos; */
12897   gint dy;
12898
12899   dy = scroll_test_pos - (int)adj->value;
12900   scroll_test_pos = adj->value;
12901
12902   if (!GTK_WIDGET_DRAWABLE (widget))
12903     return;
12904   gdk_window_scroll (widget->window, 0, dy);
12905   gdk_window_process_updates (widget->window, FALSE);
12906 }
12907
12908
12909 void
12910 create_scroll_test (GtkWidget *widget)
12911 {
12912   static GtkWidget *window = NULL;
12913   GtkWidget *hbox;
12914   GtkWidget *drawing_area;
12915   GtkWidget *scrollbar;
12916   GtkWidget *button;
12917   GtkAdjustment *adj;
12918   GdkGeometry geometry;
12919   GdkWindowHints geometry_mask;
12920
12921   if (!window)
12922     {
12923       window = gtk_dialog_new ();
12924
12925       gtk_window_set_screen (GTK_WINDOW (window),
12926                              gtk_widget_get_screen (widget));
12927
12928       g_signal_connect (window, "destroy",
12929                         G_CALLBACK (gtk_widget_destroyed),
12930                         &window);
12931
12932       gtk_window_set_title (GTK_WINDOW (window), "Scroll Test");
12933       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
12934
12935       hbox = gtk_hbox_new (FALSE, 0);
12936       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), hbox,
12937                           TRUE, TRUE, 0);
12938       gtk_widget_show (hbox);
12939
12940       drawing_area = gtk_drawing_area_new ();
12941       gtk_widget_set_size_request (drawing_area, 200, 200);
12942       gtk_box_pack_start (GTK_BOX (hbox), drawing_area, TRUE, TRUE, 0);
12943       gtk_widget_show (drawing_area);
12944
12945       gtk_widget_set_events (drawing_area, GDK_EXPOSURE_MASK | GDK_SCROLL_MASK);
12946
12947       adj = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 1000.0, 1.0, 180.0, 200.0));
12948       scroll_test_pos = 0.0;
12949
12950       scrollbar = gtk_vscrollbar_new (adj);
12951       gtk_box_pack_start (GTK_BOX (hbox), scrollbar, FALSE, FALSE, 0);
12952       gtk_widget_show (scrollbar);
12953
12954       g_signal_connect (drawing_area, "expose_event",
12955                         G_CALLBACK (scroll_test_expose), adj);
12956       g_signal_connect (drawing_area, "configure_event",
12957                         G_CALLBACK (scroll_test_configure), adj);
12958       g_signal_connect (drawing_area, "scroll_event",
12959                         G_CALLBACK (scroll_test_scroll), adj);
12960       
12961       g_signal_connect (adj, "value_changed",
12962                         G_CALLBACK (scroll_test_adjustment_changed),
12963                         drawing_area);
12964       
12965       /* .. And create some buttons */
12966
12967       button = gtk_button_new_with_label ("Quit");
12968       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area),
12969                           button, TRUE, TRUE, 0);
12970
12971       g_signal_connect_swapped (button, "clicked",
12972                                 G_CALLBACK (gtk_widget_destroy),
12973                                 window);
12974       gtk_widget_show (button);
12975
12976       /* Set up gridded geometry */
12977
12978       geometry_mask = GDK_HINT_MIN_SIZE | 
12979                        GDK_HINT_BASE_SIZE | 
12980                        GDK_HINT_RESIZE_INC;
12981
12982       geometry.min_width = 20;
12983       geometry.min_height = 20;
12984       geometry.base_width = 0;
12985       geometry.base_height = 0;
12986       geometry.width_inc = 10;
12987       geometry.height_inc = 10;
12988       
12989       gtk_window_set_geometry_hints (GTK_WINDOW (window),
12990                                drawing_area, &geometry, geometry_mask);
12991     }
12992
12993   if (!GTK_WIDGET_VISIBLE (window))
12994     gtk_widget_show (window);
12995   else
12996     gtk_widget_destroy (window);
12997 }
12998
12999 /*
13000  * Timeout Test
13001  */
13002
13003 static int timer = 0;
13004
13005 gint
13006 timeout_test (GtkWidget *label)
13007 {
13008   static int count = 0;
13009   static char buffer[32];
13010
13011   sprintf (buffer, "count: %d", ++count);
13012   gtk_label_set_text (GTK_LABEL (label), buffer);
13013
13014   return TRUE;
13015 }
13016
13017 void
13018 start_timeout_test (GtkWidget *widget,
13019                     GtkWidget *label)
13020 {
13021   if (!timer)
13022     {
13023       timer = gtk_timeout_add (100, (GtkFunction) timeout_test, label);
13024     }
13025 }
13026
13027 void
13028 stop_timeout_test (GtkWidget *widget,
13029                    gpointer   data)
13030 {
13031   if (timer)
13032     {
13033       gtk_timeout_remove (timer);
13034       timer = 0;
13035     }
13036 }
13037
13038 void
13039 destroy_timeout_test (GtkWidget  *widget,
13040                       GtkWidget **window)
13041 {
13042   stop_timeout_test (NULL, NULL);
13043
13044   *window = NULL;
13045 }
13046
13047 void
13048 create_timeout_test (GtkWidget *widget)
13049 {
13050   static GtkWidget *window = NULL;
13051   GtkWidget *button;
13052   GtkWidget *label;
13053
13054   if (!window)
13055     {
13056       window = gtk_dialog_new ();
13057
13058       gtk_window_set_screen (GTK_WINDOW (window),
13059                              gtk_widget_get_screen (widget));
13060
13061       g_signal_connect (window, "destroy",
13062                         G_CALLBACK (destroy_timeout_test),
13063                         &window);
13064
13065       gtk_window_set_title (GTK_WINDOW (window), "Timeout Test");
13066       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
13067
13068       label = gtk_label_new ("count: 0");
13069       gtk_misc_set_padding (GTK_MISC (label), 10, 10);
13070       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
13071                           label, TRUE, TRUE, 0);
13072       gtk_widget_show (label);
13073
13074       button = gtk_button_new_with_label ("close");
13075       g_signal_connect_swapped (button, "clicked",
13076                                 G_CALLBACK (gtk_widget_destroy),
13077                                 window);
13078       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
13079       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
13080                           button, TRUE, TRUE, 0);
13081       gtk_widget_grab_default (button);
13082       gtk_widget_show (button);
13083
13084       button = gtk_button_new_with_label ("start");
13085       g_signal_connect (button, "clicked",
13086                         G_CALLBACK(start_timeout_test),
13087                         label);
13088       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
13089       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
13090                           button, TRUE, TRUE, 0);
13091       gtk_widget_show (button);
13092
13093       button = gtk_button_new_with_label ("stop");
13094       g_signal_connect (button, "clicked",
13095                         G_CALLBACK (stop_timeout_test),
13096                         NULL);
13097       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
13098       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
13099                           button, TRUE, TRUE, 0);
13100       gtk_widget_show (button);
13101     }
13102
13103   if (!GTK_WIDGET_VISIBLE (window))
13104     gtk_widget_show (window);
13105   else
13106     gtk_widget_destroy (window);
13107 }
13108
13109 /*
13110  * Idle Test
13111  */
13112
13113 static int idle_id = 0;
13114
13115 static gint
13116 idle_test (GtkWidget *label)
13117 {
13118   static int count = 0;
13119   static char buffer[32];
13120
13121   sprintf (buffer, "count: %d", ++count);
13122   gtk_label_set_text (GTK_LABEL (label), buffer);
13123
13124   return TRUE;
13125 }
13126
13127 static void
13128 start_idle_test (GtkWidget *widget,
13129                  GtkWidget *label)
13130 {
13131   if (!idle_id)
13132     {
13133       idle_id = gtk_idle_add ((GtkFunction) idle_test, label);
13134     }
13135 }
13136
13137 static void
13138 stop_idle_test (GtkWidget *widget,
13139                 gpointer   data)
13140 {
13141   if (idle_id)
13142     {
13143       gtk_idle_remove (idle_id);
13144       idle_id = 0;
13145     }
13146 }
13147
13148 static void
13149 destroy_idle_test (GtkWidget  *widget,
13150                    GtkWidget **window)
13151 {
13152   stop_idle_test (NULL, NULL);
13153
13154   *window = NULL;
13155 }
13156
13157 static void
13158 toggle_idle_container (GObject *button,
13159                        GtkContainer *container)
13160 {
13161   gtk_container_set_resize_mode (container, GPOINTER_TO_INT (g_object_get_data (button, "user_data")));
13162 }
13163
13164 static void
13165 create_idle_test (GtkWidget *widget)
13166 {
13167   static GtkWidget *window = NULL;
13168   GtkWidget *button;
13169   GtkWidget *label;
13170   GtkWidget *container;
13171
13172   if (!window)
13173     {
13174       GtkWidget *button2;
13175       GtkWidget *frame;
13176       GtkWidget *box;
13177
13178       window = gtk_dialog_new ();
13179
13180       gtk_window_set_screen (GTK_WINDOW (window),
13181                              gtk_widget_get_screen (widget));
13182
13183       g_signal_connect (window, "destroy",
13184                         G_CALLBACK (destroy_idle_test),
13185                         &window);
13186
13187       gtk_window_set_title (GTK_WINDOW (window), "Idle Test");
13188       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
13189
13190       label = gtk_label_new ("count: 0");
13191       gtk_misc_set_padding (GTK_MISC (label), 10, 10);
13192       gtk_widget_show (label);
13193       
13194       container =
13195         g_object_new (GTK_TYPE_HBOX,
13196                         "visible", TRUE,
13197                         /* "GtkContainer::child", g_object_new (GTK_TYPE_HBOX,
13198                          * "GtkWidget::visible", TRUE,
13199                          */
13200                          "child", label,
13201                         /* NULL), */
13202                         NULL);
13203       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
13204                           container, TRUE, TRUE, 0);
13205
13206       frame =
13207         g_object_new (GTK_TYPE_FRAME,
13208                         "border_width", 5,
13209                         "label", "Label Container",
13210                         "visible", TRUE,
13211                         "parent", GTK_DIALOG (window)->vbox,
13212                         NULL);
13213       box =
13214         g_object_new (GTK_TYPE_VBOX,
13215                         "visible", TRUE,
13216                         "parent", frame,
13217                         NULL);
13218       button =
13219         g_object_connect (g_object_new (GTK_TYPE_RADIO_BUTTON,
13220                                           "label", "Resize-Parent",
13221                                           "user_data", (void*)GTK_RESIZE_PARENT,
13222                                           "visible", TRUE,
13223                                           "parent", box,
13224                                           NULL),
13225                           "signal::clicked", toggle_idle_container, container,
13226                           NULL);
13227       button = g_object_new (GTK_TYPE_RADIO_BUTTON,
13228                                "label", "Resize-Queue",
13229                                "user_data", (void*)GTK_RESIZE_QUEUE,
13230                                "group", button,
13231                                "visible", TRUE,
13232                                "parent", box,
13233                                NULL);
13234       g_object_connect (button,
13235                         "signal::clicked", toggle_idle_container, container,
13236                         NULL);
13237       button2 = g_object_new (GTK_TYPE_RADIO_BUTTON,
13238                                 "label", "Resize-Immediate",
13239                                 "user_data", (void*)GTK_RESIZE_IMMEDIATE,
13240                                 NULL);
13241       g_object_connect (button2,
13242                         "signal::clicked", toggle_idle_container, container,
13243                         NULL);
13244       g_object_set (button2,
13245                     "group", button,
13246                     "visible", TRUE,
13247                     "parent", box,
13248                     NULL);
13249
13250       button = gtk_button_new_with_label ("close");
13251       g_signal_connect_swapped (button, "clicked",
13252                                 G_CALLBACK (gtk_widget_destroy),
13253                                 window);
13254       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
13255       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
13256                           button, TRUE, TRUE, 0);
13257       gtk_widget_grab_default (button);
13258       gtk_widget_show (button);
13259
13260       button = gtk_button_new_with_label ("start");
13261       g_signal_connect (button, "clicked",
13262                         G_CALLBACK (start_idle_test),
13263                         label);
13264       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
13265       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
13266                           button, TRUE, TRUE, 0);
13267       gtk_widget_show (button);
13268
13269       button = gtk_button_new_with_label ("stop");
13270       g_signal_connect (button, "clicked",
13271                         G_CALLBACK (stop_idle_test),
13272                         NULL);
13273       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
13274       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
13275                           button, TRUE, TRUE, 0);
13276       gtk_widget_show (button);
13277     }
13278
13279   if (!GTK_WIDGET_VISIBLE (window))
13280     gtk_widget_show (window);
13281   else
13282     gtk_widget_destroy (window);
13283 }
13284
13285 /*
13286  * rc file test
13287  */
13288
13289 void
13290 reload_all_rc_files (void)
13291 {
13292   static GdkAtom atom_rcfiles = GDK_NONE;
13293
13294   GdkEvent *send_event = gdk_event_new (GDK_CLIENT_EVENT);
13295   int i;
13296   
13297   if (!atom_rcfiles)
13298     atom_rcfiles = gdk_atom_intern("_GTK_READ_RCFILES", FALSE);
13299
13300   for(i = 0; i < 5; i++)
13301     send_event->client.data.l[i] = 0;
13302   send_event->client.data_format = 32;
13303   send_event->client.message_type = atom_rcfiles;
13304   gdk_event_send_clientmessage_toall (send_event);
13305
13306   gdk_event_free (send_event);
13307 }
13308
13309 void
13310 create_rc_file (GtkWidget *widget)
13311 {
13312   static GtkWidget *window = NULL;
13313   GtkWidget *button;
13314   GtkWidget *frame;
13315   GtkWidget *vbox;
13316   GtkWidget *label;
13317
13318   if (!window)
13319     {
13320       window = gtk_dialog_new ();
13321
13322       gtk_window_set_screen (GTK_WINDOW (window),
13323                              gtk_widget_get_screen (widget));
13324
13325       g_signal_connect (window, "destroy",
13326                         G_CALLBACK (gtk_widget_destroyed),
13327                         &window);
13328
13329       frame = gtk_aspect_frame_new ("Testing RC file prioritization", 0.5, 0.5, 0.0, TRUE);
13330       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), frame, FALSE, FALSE, 0);
13331
13332       vbox = gtk_vbox_new (FALSE, 0);
13333       gtk_container_add (GTK_CONTAINER (frame), vbox);
13334       
13335       label = gtk_label_new ("This label should be red");
13336       gtk_widget_set_name (label, "testgtk-red-label");
13337       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
13338
13339       label = gtk_label_new ("This label should be green");
13340       gtk_widget_set_name (label, "testgtk-green-label");
13341       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
13342
13343       label = gtk_label_new ("This label should be blue");
13344       gtk_widget_set_name (label, "testgtk-blue-label");
13345       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
13346
13347       gtk_window_set_title (GTK_WINDOW (window), "Reload Rc file");
13348       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
13349
13350       button = gtk_button_new_with_label ("Reload");
13351       g_signal_connect (button, "clicked",
13352                         G_CALLBACK (gtk_rc_reparse_all), NULL);
13353       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
13354       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
13355                           button, TRUE, TRUE, 0);
13356       gtk_widget_grab_default (button);
13357
13358       button = gtk_button_new_with_label ("Reload All");
13359       g_signal_connect (button, "clicked",
13360                         G_CALLBACK (reload_all_rc_files), NULL);
13361       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
13362       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
13363                           button, TRUE, TRUE, 0);
13364
13365       button = gtk_button_new_with_label ("Close");
13366       g_signal_connect_swapped (button, "clicked",
13367                                 G_CALLBACK (gtk_widget_destroy),
13368                                 window);
13369       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
13370       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
13371                           button, TRUE, TRUE, 0);
13372     }
13373
13374   if (!GTK_WIDGET_VISIBLE (window))
13375     gtk_widget_show_all (window);
13376   else
13377     gtk_widget_destroy (window);
13378 }
13379
13380 /*
13381  * Test of recursive mainloop
13382  */
13383
13384 void
13385 mainloop_destroyed (GtkWidget *w, GtkWidget **window)
13386 {
13387   *window = NULL;
13388   gtk_main_quit ();
13389 }
13390
13391 void
13392 create_mainloop (GtkWidget *widget)
13393 {
13394   static GtkWidget *window = NULL;
13395   GtkWidget *label;
13396   GtkWidget *button;
13397
13398   if (!window)
13399     {
13400       window = gtk_dialog_new ();
13401
13402       gtk_window_set_screen (GTK_WINDOW (window),
13403                              gtk_widget_get_screen (widget));
13404
13405       gtk_window_set_title (GTK_WINDOW (window), "Test Main Loop");
13406
13407       g_signal_connect (window, "destroy",
13408                         G_CALLBACK (mainloop_destroyed),
13409                         &window);
13410
13411       label = gtk_label_new ("In recursive main loop...");
13412       gtk_misc_set_padding (GTK_MISC(label), 20, 20);
13413
13414       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), label,
13415                           TRUE, TRUE, 0);
13416       gtk_widget_show (label);
13417
13418       button = gtk_button_new_with_label ("Leave");
13419       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), button, 
13420                           FALSE, TRUE, 0);
13421
13422       g_signal_connect_swapped (button, "clicked",
13423                                 G_CALLBACK (gtk_widget_destroy),
13424                                 window);
13425
13426       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
13427       gtk_widget_grab_default (button);
13428
13429       gtk_widget_show (button);
13430     }
13431
13432   if (!GTK_WIDGET_VISIBLE (window))
13433     {
13434       gtk_widget_show (window);
13435
13436       g_print ("create_mainloop: start\n");
13437       gtk_main ();
13438       g_print ("create_mainloop: done\n");
13439     }
13440   else
13441     gtk_widget_destroy (window);
13442 }
13443
13444 gboolean
13445 layout_expose_handler (GtkWidget *widget, GdkEventExpose *event)
13446 {
13447   GtkLayout *layout;
13448
13449   gint i,j;
13450   gint imin, imax, jmin, jmax;
13451
13452   layout = GTK_LAYOUT (widget);
13453
13454   if (event->window != layout->bin_window)
13455     return FALSE;
13456   
13457   imin = (event->area.x) / 10;
13458   imax = (event->area.x + event->area.width + 9) / 10;
13459
13460   jmin = (event->area.y) / 10;
13461   jmax = (event->area.y + event->area.height + 9) / 10;
13462
13463   for (i=imin; i<imax; i++)
13464     for (j=jmin; j<jmax; j++)
13465       if ((i+j) % 2)
13466         gdk_draw_rectangle (layout->bin_window,
13467                             widget->style->black_gc,
13468                             TRUE,
13469                             10*i, 10*j, 
13470                             1+i%10, 1+j%10);
13471   
13472   return FALSE;
13473 }
13474
13475 void create_layout (GtkWidget *widget)
13476 {
13477   static GtkWidget *window = NULL;
13478   GtkWidget *layout;
13479   GtkWidget *scrolledwindow;
13480   GtkWidget *button;
13481
13482   if (!window)
13483     {
13484       gchar buf[16];
13485
13486       gint i, j;
13487       
13488       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
13489       gtk_window_set_screen (GTK_WINDOW (window),
13490                              gtk_widget_get_screen (widget));
13491
13492       g_signal_connect (window, "destroy",
13493                         G_CALLBACK (gtk_widget_destroyed),
13494                         &window);
13495
13496       gtk_window_set_title (GTK_WINDOW (window), "Layout");
13497       gtk_widget_set_size_request (window, 200, 200);
13498
13499       scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
13500       gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolledwindow),
13501                                            GTK_SHADOW_IN);
13502       gtk_scrolled_window_set_placement (GTK_SCROLLED_WINDOW (scrolledwindow),
13503                                          GTK_CORNER_TOP_RIGHT);
13504
13505       gtk_container_add (GTK_CONTAINER (window), scrolledwindow);
13506       
13507       layout = gtk_layout_new (NULL, NULL);
13508       gtk_container_add (GTK_CONTAINER (scrolledwindow), layout);
13509
13510       /* We set step sizes here since GtkLayout does not set
13511        * them itself.
13512        */
13513       GTK_LAYOUT (layout)->hadjustment->step_increment = 10.0;
13514       GTK_LAYOUT (layout)->vadjustment->step_increment = 10.0;
13515       
13516       gtk_widget_set_events (layout, GDK_EXPOSURE_MASK);
13517       g_signal_connect (layout, "expose_event",
13518                         G_CALLBACK (layout_expose_handler), NULL);
13519       
13520       gtk_layout_set_size (GTK_LAYOUT (layout), 1600, 128000);
13521       
13522       for (i=0 ; i < 16 ; i++)
13523         for (j=0 ; j < 16 ; j++)
13524           {
13525             sprintf(buf, "Button %d, %d", i, j);
13526             if ((i + j) % 2)
13527               button = gtk_button_new_with_label (buf);
13528             else
13529               button = gtk_label_new (buf);
13530
13531             gtk_layout_put (GTK_LAYOUT (layout), button,
13532                             j*100, i*100);
13533           }
13534
13535       for (i=16; i < 1280; i++)
13536         {
13537           sprintf(buf, "Button %d, %d", i, 0);
13538           if (i % 2)
13539             button = gtk_button_new_with_label (buf);
13540           else
13541             button = gtk_label_new (buf);
13542
13543           gtk_layout_put (GTK_LAYOUT (layout), button,
13544                           0, i*100);
13545         }
13546     }
13547
13548   if (!GTK_WIDGET_VISIBLE (window))
13549     gtk_widget_show_all (window);
13550   else
13551     gtk_widget_destroy (window);
13552 }
13553
13554 void
13555 create_styles (GtkWidget *widget)
13556 {
13557   static GtkWidget *window = NULL;
13558   GtkWidget *label;
13559   GtkWidget *button;
13560   GtkWidget *entry;
13561   GtkWidget *vbox;
13562   static GdkColor red =    { 0, 0xffff, 0,      0      };
13563   static GdkColor green =  { 0, 0,      0xffff, 0      };
13564   static GdkColor blue =   { 0, 0,      0,      0xffff };
13565   static GdkColor yellow = { 0, 0xffff, 0xffff, 0      };
13566   static GdkColor cyan =   { 0, 0     , 0xffff, 0xffff };
13567   PangoFontDescription *font_desc;
13568
13569   GtkRcStyle *rc_style;
13570
13571   if (!window)
13572     {
13573       window = gtk_dialog_new ();
13574       gtk_window_set_screen (GTK_WINDOW (window),
13575                              gtk_widget_get_screen (widget));
13576      
13577       g_signal_connect (window, "destroy",
13578                         G_CALLBACK (gtk_widget_destroyed),
13579                         &window);
13580
13581       
13582       button = gtk_button_new_with_label ("Close");
13583       g_signal_connect_swapped (button, "clicked",
13584                                 G_CALLBACK (gtk_widget_destroy),
13585                                 window);
13586       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
13587       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
13588                           button, TRUE, TRUE, 0);
13589       gtk_widget_show (button);
13590
13591       vbox = gtk_vbox_new (FALSE, 5);
13592       gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
13593       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), vbox, FALSE, FALSE, 0);
13594       
13595       label = gtk_label_new ("Font:");
13596       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
13597       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
13598
13599       font_desc = pango_font_description_from_string ("Helvetica,Sans Oblique 18");
13600
13601       button = gtk_button_new_with_label ("Some Text");
13602       gtk_widget_modify_font (GTK_BIN (button)->child, font_desc);
13603       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
13604
13605       label = gtk_label_new ("Foreground:");
13606       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
13607       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
13608
13609       button = gtk_button_new_with_label ("Some Text");
13610       gtk_widget_modify_fg (GTK_BIN (button)->child, GTK_STATE_NORMAL, &red);
13611       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
13612
13613       label = gtk_label_new ("Background:");
13614       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
13615       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
13616
13617       button = gtk_button_new_with_label ("Some Text");
13618       gtk_widget_modify_bg (button, GTK_STATE_NORMAL, &green);
13619       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
13620
13621       label = gtk_label_new ("Text:");
13622       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
13623       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
13624
13625       entry = gtk_entry_new ();
13626       gtk_entry_set_text (GTK_ENTRY (entry), "Some Text");
13627       gtk_widget_modify_text (entry, GTK_STATE_NORMAL, &blue);
13628       gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
13629
13630       label = gtk_label_new ("Base:");
13631       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
13632       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
13633
13634       entry = gtk_entry_new ();
13635       gtk_entry_set_text (GTK_ENTRY (entry), "Some Text");
13636       gtk_widget_modify_base (entry, GTK_STATE_NORMAL, &yellow);
13637       gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
13638
13639       label = gtk_label_new ("Cursor:");
13640       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
13641       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
13642
13643       entry = gtk_entry_new ();
13644       gtk_entry_set_text (GTK_ENTRY (entry), "Some Text");
13645       gtk_widget_modify_cursor (entry, &red, &red);
13646       gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
13647
13648       label = gtk_label_new ("Multiple:");
13649       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
13650       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
13651
13652       button = gtk_button_new_with_label ("Some Text");
13653
13654       rc_style = gtk_rc_style_new ();
13655
13656       rc_style->font_desc = pango_font_description_copy (font_desc);
13657       rc_style->color_flags[GTK_STATE_NORMAL] = GTK_RC_FG | GTK_RC_BG;
13658       rc_style->color_flags[GTK_STATE_PRELIGHT] = GTK_RC_FG | GTK_RC_BG;
13659       rc_style->color_flags[GTK_STATE_ACTIVE] = GTK_RC_FG | GTK_RC_BG;
13660       rc_style->fg[GTK_STATE_NORMAL] = yellow;
13661       rc_style->bg[GTK_STATE_NORMAL] = blue;
13662       rc_style->fg[GTK_STATE_PRELIGHT] = blue;
13663       rc_style->bg[GTK_STATE_PRELIGHT] = yellow;
13664       rc_style->fg[GTK_STATE_ACTIVE] = red;
13665       rc_style->bg[GTK_STATE_ACTIVE] = cyan;
13666       rc_style->xthickness = 5;
13667       rc_style->ythickness = 5;
13668
13669       gtk_widget_modify_style (button, rc_style);
13670       gtk_widget_modify_style (GTK_BIN (button)->child, rc_style);
13671
13672       g_object_unref (rc_style);
13673       
13674       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
13675     }
13676   
13677   if (!GTK_WIDGET_VISIBLE (window))
13678     gtk_widget_show_all (window);
13679   else
13680     gtk_widget_destroy (window);
13681 }
13682
13683 /*
13684  * Main Window and Exit
13685  */
13686
13687 void
13688 do_exit (GtkWidget *widget, GtkWidget *window)
13689 {
13690   gtk_widget_destroy (window);
13691   gtk_main_quit ();
13692 }
13693
13694 struct {
13695   char *label;
13696   void (*func) (GtkWidget *widget);
13697   gboolean do_not_benchmark;
13698 } buttons[] =
13699 {
13700   { "alpha window", create_alpha_window },
13701 #ifdef G_OS_WIN32
13702   /* dog slow on NT, no working at all on 9x */
13703   { "big windows", create_big_windows, TRUE },
13704 #else
13705   { "big windows", create_big_windows },
13706 #endif
13707   { "button box", create_button_box },
13708   { "buttons", create_buttons },
13709   { "check buttons", create_check_buttons },
13710   { "clist", create_clist},
13711   { "color selection", create_color_selection },
13712   { "composited window", create_composited_window },
13713   { "ctree", create_ctree },
13714   { "cursors", create_cursors },
13715   { "dialog", create_dialog, TRUE },
13716   { "display & screen", create_display_screen, TRUE },
13717   { "entry", create_entry },
13718   { "event box", create_event_box },
13719   { "event watcher", create_event_watcher },
13720   { "expander", create_expander },
13721   { "file selection", create_file_selection },
13722   { "flipping", create_flipping },
13723   { "focus", create_focus },
13724   { "font selection", create_font_selection },
13725   { "gamma curve", create_gamma_curve, TRUE },
13726   { "gridded geometry", create_gridded_geometry },
13727   { "handle box", create_handle_box },
13728   { "image from drawable", create_get_image },
13729   { "image", create_image },
13730   { "item factory", create_item_factory },
13731   { "key lookup", create_key_lookup },
13732   { "labels", create_labels },
13733   { "layout", create_layout },
13734   { "list", create_list },
13735   { "menus", create_menus },
13736   { "message dialog", create_message_dialog },
13737   { "modal window", create_modal_window, TRUE },
13738   { "notebook", create_notebook },
13739   { "panes", create_panes },
13740   { "paned keyboard", create_paned_keyboard_navigation },
13741   { "pixmap", create_pixmap },
13742   { "preview color", create_color_preview, TRUE },
13743   { "preview gray", create_gray_preview, TRUE },
13744   { "progress bar", create_progress_bar },
13745   { "properties", create_properties },
13746   { "radio buttons", create_radio_buttons },
13747   { "range controls", create_range_controls },
13748   { "rc file", create_rc_file },
13749   { "reparent", create_reparent },
13750   { "resize grips", create_resize_grips },
13751   { "rotated label", create_rotated_label },
13752   { "rotated text", create_rotated_text },
13753   { "rulers", create_rulers },
13754   { "saved position", create_saved_position },
13755   { "scrolled windows", create_scrolled_windows },
13756   { "shapes", create_shapes },
13757   { "size groups", create_size_groups },
13758   { "snapshot", create_snapshot },
13759   { "spinbutton", create_spins },
13760   { "statusbar", create_statusbar },
13761   { "styles", create_styles },
13762   { "test idle", create_idle_test },
13763   { "test mainloop", create_mainloop, TRUE },
13764   { "test scrolling", create_scroll_test },
13765   { "test selection", create_selection_test },
13766   { "test timeout", create_timeout_test },
13767   { "text", create_text },
13768   { "toggle buttons", create_toggle_buttons },
13769   { "toolbar", create_toolbar },
13770   { "tooltips", create_tooltips },
13771   { "tree", create_tree_mode_window},
13772   { "WM hints", create_wmhints },
13773   { "window sizing", create_window_sizing },
13774   { "window states", create_window_states }
13775 };
13776 int nbuttons = sizeof (buttons) / sizeof (buttons[0]);
13777
13778 void
13779 create_main_window (void)
13780 {
13781   GtkWidget *window;
13782   GtkWidget *box1;
13783   GtkWidget *box2;
13784   GtkWidget *scrolled_window;
13785   GtkWidget *button;
13786   GtkWidget *label;
13787   gchar buffer[64];
13788   GtkWidget *separator;
13789   GdkGeometry geometry;
13790   int i;
13791
13792   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
13793   gtk_widget_set_name (window, "main window");
13794   gtk_widget_set_uposition (window, 50, 20);
13795   gtk_window_set_default_size (GTK_WINDOW (window), -1, 400);
13796
13797   geometry.min_width = -1;
13798   geometry.min_height = -1;
13799   geometry.max_width = -1;
13800   geometry.max_height = G_MAXSHORT;
13801   gtk_window_set_geometry_hints (GTK_WINDOW (window), NULL,
13802                                  &geometry,
13803                                  GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE);
13804
13805   g_signal_connect (window, "destroy",
13806                     G_CALLBACK (gtk_main_quit),
13807                     NULL);
13808   g_signal_connect (window, "delete-event",
13809                     G_CALLBACK (gtk_false),
13810                     NULL);
13811
13812   box1 = gtk_vbox_new (FALSE, 0);
13813   gtk_container_add (GTK_CONTAINER (window), box1);
13814
13815   if (gtk_micro_version > 0)
13816     sprintf (buffer,
13817              "Gtk+ v%d.%d.%d",
13818              gtk_major_version,
13819              gtk_minor_version,
13820              gtk_micro_version);
13821   else
13822     sprintf (buffer,
13823              "Gtk+ v%d.%d",
13824              gtk_major_version,
13825              gtk_minor_version);
13826
13827   label = gtk_label_new (buffer);
13828   gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);
13829   gtk_widget_set_name (label, "testgtk-version-label");
13830
13831   scrolled_window = gtk_scrolled_window_new (NULL, NULL);
13832   gtk_container_set_border_width (GTK_CONTAINER (scrolled_window), 10);
13833   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
13834                                   GTK_POLICY_NEVER, 
13835                                   GTK_POLICY_AUTOMATIC);
13836   gtk_box_pack_start (GTK_BOX (box1), scrolled_window, TRUE, TRUE, 0);
13837
13838   box2 = gtk_vbox_new (FALSE, 0);
13839   gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
13840   gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_window), box2);
13841   gtk_container_set_focus_vadjustment (GTK_CONTAINER (box2),
13842                                        gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (scrolled_window)));
13843   gtk_widget_show (box2);
13844
13845   for (i = 0; i < nbuttons; i++)
13846     {
13847       button = gtk_button_new_with_label (buttons[i].label);
13848       if (buttons[i].func)
13849         g_signal_connect (button, 
13850                           "clicked", 
13851                           G_CALLBACK(buttons[i].func),
13852                           NULL);
13853       else
13854         gtk_widget_set_sensitive (button, FALSE);
13855       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
13856     }
13857
13858   separator = gtk_hseparator_new ();
13859   gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
13860
13861   box2 = gtk_vbox_new (FALSE, 10);
13862   gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
13863   gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
13864
13865   button = gtk_button_new_with_mnemonic ("_Close");
13866   g_signal_connect (button, "clicked",
13867                     G_CALLBACK (do_exit),
13868                     window);
13869   gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
13870   GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
13871   gtk_widget_grab_default (button);
13872
13873   gtk_widget_show_all (window);
13874 }
13875
13876 static void
13877 test_init (void)
13878 {
13879   if (g_file_test ("../gdk-pixbuf/libpixbufloader-pnm.la",
13880                    G_FILE_TEST_EXISTS))
13881     {
13882       g_setenv ("GDK_PIXBUF_MODULE_FILE", "../gdk-pixbuf/gdk-pixbuf.loaders", TRUE);
13883       g_setenv ("GTK_IM_MODULE_FILE", "../modules/input/gtk.immodules", TRUE);
13884     }
13885 }
13886
13887 static char *
13888 pad (const char *str, int to)
13889 {
13890   static char buf[256];
13891   int len = strlen (str);
13892   int i;
13893
13894   for (i = 0; i < to; i++)
13895     buf[i] = ' ';
13896
13897   buf[to] = '\0';
13898
13899   memcpy (buf, str, len);
13900
13901   return buf;
13902 }
13903
13904 static void
13905 bench_iteration (GtkWidget *widget, void (* fn) (GtkWidget *widget))
13906 {
13907   fn (widget); /* on */
13908   while (g_main_context_iteration (NULL, FALSE));
13909   fn (widget); /* off */
13910   while (g_main_context_iteration (NULL, FALSE));
13911 }
13912
13913 void
13914 do_real_bench (GtkWidget *widget, void (* fn) (GtkWidget *widget), char *name, int num)
13915 {
13916   GTimeVal tv0, tv1;
13917   double dt_first;
13918   double dt;
13919   int n;
13920   static gboolean printed_headers = FALSE;
13921
13922   if (!printed_headers) {
13923     g_print ("Test                 Iters      First      Other\n");
13924     g_print ("-------------------- ----- ---------- ----------\n");
13925     printed_headers = TRUE;
13926   }
13927
13928   g_get_current_time (&tv0);
13929   bench_iteration (widget, fn); 
13930   g_get_current_time (&tv1);
13931
13932   dt_first = ((double)tv1.tv_sec - tv0.tv_sec) * 1000.0
13933         + (tv1.tv_usec - tv0.tv_usec) / 1000.0;
13934
13935   g_get_current_time (&tv0);
13936   for (n = 0; n < num - 1; n++)
13937     bench_iteration (widget, fn); 
13938   g_get_current_time (&tv1);
13939   dt = ((double)tv1.tv_sec - tv0.tv_sec) * 1000.0
13940         + (tv1.tv_usec - tv0.tv_usec) / 1000.0;
13941
13942   g_print ("%s %5d ", pad (name, 20), num);
13943   if (num > 1)
13944     g_print ("%10.1f %10.1f\n", dt_first, dt/(num-1));
13945   else
13946     g_print ("%10.1f\n", dt_first);
13947 }
13948
13949 void
13950 do_bench (char* what, int num)
13951 {
13952   int i;
13953   GtkWidget *widget;
13954   void (* fn) (GtkWidget *widget);
13955   fn = NULL;
13956   widget = gtk_window_new (GTK_WINDOW_TOPLEVEL);
13957
13958   if (g_ascii_strcasecmp (what, "ALL") == 0)
13959     {
13960       for (i = 0; i < nbuttons; i++)
13961         {
13962           if (!buttons[i].do_not_benchmark)
13963             do_real_bench (widget, buttons[i].func, buttons[i].label, num);
13964         }
13965
13966       return;
13967     }
13968   else
13969     {
13970       for (i = 0; i < nbuttons; i++)
13971         {
13972           if (strcmp (buttons[i].label, what) == 0)
13973             {
13974               fn = buttons[i].func;
13975               break;
13976             }
13977         }
13978       
13979       if (!fn)
13980         g_print ("Can't bench: \"%s\" not found.\n", what);
13981       else
13982         do_real_bench (widget, fn, buttons[i].label, num);
13983     }
13984 }
13985
13986 void 
13987 usage (void)
13988 {
13989   fprintf (stderr, "Usage: testgtk [--bench ALL|<bench>[:<count>]]\n");
13990   exit (1);
13991 }
13992
13993 int
13994 main (int argc, char *argv[])
13995 {
13996   GtkBindingSet *binding_set;
13997   int i;
13998   gboolean done_benchmarks = FALSE;
13999
14000   srand (time (NULL));
14001
14002   test_init ();
14003
14004   /* Check to see if we are being run from the correct
14005    * directory.
14006    */
14007   if (file_exists ("testgtkrc"))
14008     gtk_rc_add_default_file ("testgtkrc");
14009   else if (file_exists ("tests/testgtkrc"))
14010     gtk_rc_add_default_file ("tests/testgtkrc");
14011   else
14012     g_warning ("Couldn't find file \"testgtkrc\".");
14013
14014   g_set_application_name ("GTK+ Test Program");
14015
14016   gtk_init (&argc, &argv);
14017
14018   gtk_accelerator_set_default_mod_mask (GDK_SHIFT_MASK |
14019                                         GDK_CONTROL_MASK |
14020                                         GDK_MOD1_MASK | 
14021                                         GDK_META_MASK |
14022                                         GDK_SUPER_MASK |
14023                                         GDK_HYPER_MASK |
14024                                         GDK_MOD4_MASK);
14025   /*  benchmarking
14026    */
14027   for (i = 1; i < argc; i++)
14028     {
14029       if (strncmp (argv[i], "--bench", strlen("--bench")) == 0)
14030         {
14031           int num = 1;
14032           char *nextarg;
14033           char *what;
14034           char *count;
14035           
14036           nextarg = strchr (argv[i], '=');
14037           if (nextarg)
14038             nextarg++;
14039           else
14040             {
14041               i++;
14042               if (i == argc)
14043                 usage ();
14044               nextarg = argv[i];
14045             }
14046
14047           count = strchr (nextarg, ':');
14048           if (count)
14049             {
14050               what = g_strndup (nextarg, count - nextarg);
14051               count++;
14052               num = atoi (count);
14053               if (num <= 0)
14054                 usage ();
14055             }
14056           else
14057             what = g_strdup (nextarg);
14058
14059           do_bench (what, num ? num : 1);
14060           done_benchmarks = TRUE;
14061         }
14062       else
14063         usage ();
14064     }
14065   if (done_benchmarks)
14066     return 0;
14067
14068   /* bindings test
14069    */
14070   binding_set = gtk_binding_set_by_class (g_type_class_ref (GTK_TYPE_WIDGET));
14071   gtk_binding_entry_add_signal (binding_set,
14072                                 '9', GDK_CONTROL_MASK | GDK_RELEASE_MASK,
14073                                 "debug_msg",
14074                                 1,
14075                                 G_TYPE_STRING, "GtkWidgetClass <ctrl><release>9 test");
14076   
14077   /* We use gtk_rc_parse_string() here so we can make sure it works across theme
14078    * changes
14079    */
14080
14081   gtk_rc_parse_string ("style \"testgtk-version-label\" { "
14082                        "   fg[NORMAL] = \"#ff0000\"\n"
14083                        "   font = \"Sans 18\"\n"
14084                        "}\n"
14085                        "widget \"*.testgtk-version-label\" style \"testgtk-version-label\"");
14086   
14087   create_main_window ();
14088
14089   gtk_main ();
14090
14091   if (1)
14092     {
14093       while (g_main_context_pending (NULL))
14094         g_main_context_iteration (NULL, FALSE);
14095 #if 0
14096       sleep (1);
14097       while (g_main_context_pending (NULL))
14098         g_main_context_iteration (NULL, FALSE);
14099 #endif
14100     }
14101   return 0;
14102 }