]> Pileus Git - ~andy/gtk/blob - tests/testgtk.c
Bug 546285 – Allow GtkEntry to draw progress
[~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 set_direction_recurse (GtkWidget *widget,
8287                        gpointer   data)
8288 {
8289   GtkTextDirection *dir = data;
8290   
8291   gtk_widget_set_direction (widget, *dir);
8292   if (GTK_IS_CONTAINER (widget))
8293     gtk_container_foreach (GTK_CONTAINER (widget),
8294                            set_direction_recurse,
8295                            data);
8296 }
8297
8298 static GtkWidget *
8299 create_forward_back (const char       *title,
8300                      GtkTextDirection  text_dir)
8301 {
8302   GtkWidget *frame = gtk_frame_new (title);
8303   GtkWidget *bbox = gtk_hbutton_box_new ();
8304   GtkWidget *back_button = gtk_button_new_from_stock (GTK_STOCK_GO_BACK);
8305   GtkWidget *forward_button = gtk_button_new_from_stock (GTK_STOCK_GO_FORWARD);
8306
8307   gtk_container_set_border_width (GTK_CONTAINER (bbox), 5);
8308   
8309   gtk_container_add (GTK_CONTAINER (frame), bbox);
8310   gtk_container_add (GTK_CONTAINER (bbox), back_button);
8311   gtk_container_add (GTK_CONTAINER (bbox), forward_button);
8312
8313   set_direction_recurse (frame, &text_dir);
8314
8315   return frame;
8316 }
8317
8318 void
8319 create_flipping (GtkWidget *widget)
8320 {
8321   static GtkWidget *window = NULL;
8322   GtkWidget *check_button, *button;
8323
8324   if (!window)
8325     {
8326       window = gtk_dialog_new ();
8327
8328       gtk_window_set_screen (GTK_WINDOW (window),
8329                              gtk_widget_get_screen (widget));
8330
8331       g_signal_connect (window, "destroy",
8332                         G_CALLBACK (gtk_widget_destroyed),
8333                         &window);
8334
8335       gtk_window_set_title (GTK_WINDOW (window), "Bidirectional Flipping");
8336
8337       check_button = gtk_check_button_new_with_label ("Right-to-left global direction");
8338       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
8339                           check_button, TRUE, TRUE, 0);
8340
8341       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
8342                           create_forward_back ("Default", GTK_TEXT_DIR_NONE),
8343                           TRUE, TRUE, 0);
8344
8345       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
8346                           create_forward_back ("Left-to-Right", GTK_TEXT_DIR_LTR),
8347                           TRUE, TRUE, 0);
8348
8349       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
8350                           create_forward_back ("Right-to-Left", GTK_TEXT_DIR_RTL),
8351                           TRUE, TRUE, 0);
8352
8353       if (gtk_widget_get_default_direction () == GTK_TEXT_DIR_RTL)
8354         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button), TRUE);
8355
8356       g_signal_connect (check_button, "toggled",
8357                         G_CALLBACK (flipping_toggled_cb), NULL);
8358
8359       gtk_container_set_border_width (GTK_CONTAINER (check_button), 10);
8360       
8361       button = gtk_button_new_with_label ("Close");
8362       g_signal_connect_swapped (button, "clicked",
8363                                 G_CALLBACK (gtk_widget_destroy), window);
8364       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
8365                           button, TRUE, TRUE, 0);
8366     }
8367   
8368   if (!GTK_WIDGET_VISIBLE (window))
8369     gtk_widget_show_all (window);
8370   else
8371     gtk_widget_destroy (window);
8372 }
8373
8374 /*
8375  * Focus test
8376  */
8377
8378 static GtkWidget*
8379 make_focus_table (GList **list)
8380 {
8381   GtkWidget *table;
8382   gint i, j;
8383   
8384   table = gtk_table_new (5, 5, FALSE);
8385
8386   i = 0;
8387   j = 0;
8388
8389   while (i < 5)
8390     {
8391       j = 0;
8392       while (j < 5)
8393         {
8394           GtkWidget *widget;
8395           
8396           if ((i + j) % 2)
8397             widget = gtk_entry_new ();
8398           else
8399             widget = gtk_button_new_with_label ("Foo");
8400
8401           *list = g_list_prepend (*list, widget);
8402           
8403           gtk_table_attach (GTK_TABLE (table),
8404                             widget,
8405                             i, i + 1,
8406                             j, j + 1,
8407                             GTK_EXPAND | GTK_FILL,
8408                             GTK_EXPAND | GTK_FILL,
8409                             5, 5);
8410           
8411           ++j;
8412         }
8413
8414       ++i;
8415     }
8416
8417   *list = g_list_reverse (*list);
8418   
8419   return table;
8420 }
8421
8422 static void
8423 create_focus (GtkWidget *widget)
8424 {
8425   static GtkWidget *window = NULL;
8426   
8427   if (!window)
8428     {
8429       GtkWidget *table;
8430       GtkWidget *frame;
8431       GList *list = NULL;
8432       
8433       window = gtk_dialog_new_with_buttons ("Keyboard focus navigation",
8434                                             NULL, 0,
8435                                             GTK_STOCK_CLOSE,
8436                                             GTK_RESPONSE_NONE,
8437                                             NULL);
8438
8439       gtk_window_set_screen (GTK_WINDOW (window),
8440                              gtk_widget_get_screen (widget));
8441
8442       g_signal_connect (window, "destroy",
8443                         G_CALLBACK (gtk_widget_destroyed),
8444                         &window);
8445
8446       g_signal_connect (window, "response",
8447                         G_CALLBACK (gtk_widget_destroy),
8448                         NULL);
8449       
8450       gtk_window_set_title (GTK_WINDOW (window), "Keyboard Focus Navigation");
8451
8452       frame = gtk_frame_new ("Weird tab focus chain");
8453
8454       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
8455                           frame, TRUE, TRUE, 0);
8456       
8457       table = make_focus_table (&list);
8458
8459       gtk_container_add (GTK_CONTAINER (frame), table);
8460
8461       gtk_container_set_focus_chain (GTK_CONTAINER (table),
8462                                      list);
8463
8464       g_list_free (list);
8465       
8466       frame = gtk_frame_new ("Default tab focus chain");
8467
8468       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
8469                           frame, TRUE, TRUE, 0);
8470
8471       list = NULL;
8472       table = make_focus_table (&list);
8473
8474       g_list_free (list);
8475       
8476       gtk_container_add (GTK_CONTAINER (frame), table);      
8477     }
8478   
8479   if (!GTK_WIDGET_VISIBLE (window))
8480     gtk_widget_show_all (window);
8481   else
8482     gtk_widget_destroy (window);
8483 }
8484
8485 /*
8486  * GtkFontSelection
8487  */
8488
8489 void
8490 font_selection_ok (GtkWidget              *w,
8491                    GtkFontSelectionDialog *fs)
8492 {
8493   gchar *s = gtk_font_selection_dialog_get_font_name (fs);
8494
8495   g_print ("%s\n", s);
8496   g_free (s);
8497   gtk_widget_destroy (GTK_WIDGET (fs));
8498 }
8499
8500 void
8501 create_font_selection (GtkWidget *widget)
8502 {
8503   static GtkWidget *window = NULL;
8504
8505   if (!window)
8506     {
8507       GtkWidget *picker;
8508       GtkWidget *hbox;
8509       GtkWidget *label;
8510       
8511       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8512       gtk_window_set_screen (GTK_WINDOW (window),
8513                              gtk_widget_get_screen (widget));
8514
8515       g_signal_connect (window, "destroy",
8516                         G_CALLBACK (gtk_widget_destroyed),
8517                         &window);
8518
8519       gtk_window_set_title (GTK_WINDOW (window), "GtkFontButton");
8520       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
8521
8522       hbox = gtk_hbox_new (FALSE, 8);
8523       gtk_container_set_border_width (GTK_CONTAINER (hbox), 8);
8524       gtk_container_add (GTK_CONTAINER (window), hbox);
8525       
8526       label = gtk_label_new ("Pick a font");
8527       gtk_container_add (GTK_CONTAINER (hbox), label);
8528
8529       picker = gtk_font_button_new ();
8530       gtk_font_button_set_use_font (GTK_FONT_BUTTON (picker), TRUE);
8531       gtk_container_add (GTK_CONTAINER (hbox), picker);
8532     }
8533   
8534   if (!GTK_WIDGET_VISIBLE (window))
8535     gtk_widget_show_all (window);
8536   else
8537     gtk_widget_destroy (window);
8538 }
8539
8540 /*
8541  * GtkDialog
8542  */
8543
8544 static GtkWidget *dialog_window = NULL;
8545
8546 static void
8547 label_toggle (GtkWidget  *widget,
8548               GtkWidget **label)
8549 {
8550   if (!(*label))
8551     {
8552       *label = gtk_label_new ("Dialog Test");
8553       g_signal_connect (*label,
8554                         "destroy",
8555                         G_CALLBACK (gtk_widget_destroyed),
8556                         label);
8557       gtk_misc_set_padding (GTK_MISC (*label), 10, 10);
8558       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog_window)->vbox), 
8559                           *label, TRUE, TRUE, 0);
8560       gtk_widget_show (*label);
8561     }
8562   else
8563     gtk_widget_destroy (*label);
8564 }
8565
8566 #define RESPONSE_TOGGLE_SEPARATOR 1
8567
8568 static void
8569 print_response (GtkWidget *dialog,
8570                 gint       response_id,
8571                 gpointer   data)
8572 {
8573   g_print ("response signal received (%d)\n", response_id);
8574
8575   if (response_id == RESPONSE_TOGGLE_SEPARATOR)
8576     {
8577       gtk_dialog_set_has_separator (GTK_DIALOG (dialog),
8578                                     !gtk_dialog_get_has_separator (GTK_DIALOG (dialog)));
8579     }
8580 }
8581
8582 static void
8583 create_dialog (GtkWidget *widget)
8584 {
8585   static GtkWidget *label;
8586   GtkWidget *button;
8587
8588   if (!dialog_window)
8589     {
8590       /* This is a terrible example; it's much simpler to create
8591        * dialogs than this. Don't use testgtk for example code,
8592        * use gtk-demo ;-)
8593        */
8594       
8595       dialog_window = gtk_dialog_new ();
8596       gtk_window_set_screen (GTK_WINDOW (dialog_window),
8597                              gtk_widget_get_screen (widget));
8598
8599       g_signal_connect (dialog_window,
8600                         "response",
8601                         G_CALLBACK (print_response),
8602                         NULL);
8603       
8604       g_signal_connect (dialog_window, "destroy",
8605                         G_CALLBACK (gtk_widget_destroyed),
8606                         &dialog_window);
8607
8608       gtk_window_set_title (GTK_WINDOW (dialog_window), "GtkDialog");
8609       gtk_container_set_border_width (GTK_CONTAINER (dialog_window), 0);
8610
8611       button = gtk_button_new_with_label ("OK");
8612       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
8613       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog_window)->action_area), 
8614                           button, TRUE, TRUE, 0);
8615       gtk_widget_grab_default (button);
8616       gtk_widget_show (button);
8617
8618       button = gtk_button_new_with_label ("Toggle");
8619       g_signal_connect (button, "clicked",
8620                         G_CALLBACK (label_toggle),
8621                         &label);
8622       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
8623       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog_window)->action_area),
8624                           button, TRUE, TRUE, 0);
8625       gtk_widget_show (button);
8626
8627       label = NULL;
8628       
8629       button = gtk_button_new_with_label ("Separator");
8630
8631       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
8632
8633       gtk_dialog_add_action_widget (GTK_DIALOG (dialog_window),
8634                                     button,
8635                                     RESPONSE_TOGGLE_SEPARATOR);
8636       gtk_widget_show (button);
8637     }
8638
8639   if (!GTK_WIDGET_VISIBLE (dialog_window))
8640     gtk_widget_show (dialog_window);
8641   else
8642     gtk_widget_destroy (dialog_window);
8643 }
8644
8645 /* Display & Screen test 
8646  */
8647
8648 typedef struct 
8649
8650   GtkEntry *entry;
8651   GtkWidget *radio_dpy;
8652   GtkWidget *toplevel; 
8653   GtkWidget *dialog_window;
8654   GList *valid_display_list;
8655 } ScreenDisplaySelection;
8656
8657 static gint
8658 display_name_cmp (gconstpointer a,
8659                   gconstpointer b)
8660 {
8661   return g_ascii_strcasecmp (a,b);
8662 }
8663
8664 static void
8665 screen_display_check (GtkWidget *widget, ScreenDisplaySelection *data)
8666 {
8667   char *display_name;
8668   GdkDisplay *display = gtk_widget_get_display (widget);
8669   GtkWidget *dialog;
8670   GdkScreen *new_screen = NULL;
8671   GdkScreen *current_screen = gtk_widget_get_screen (widget);
8672   
8673   if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (data->radio_dpy)))
8674     {
8675       display_name = g_strdup (gtk_entry_get_text (data->entry));
8676       display = gdk_display_open (display_name);
8677       
8678       if (!display)
8679         {
8680           dialog = gtk_message_dialog_new (GTK_WINDOW (gtk_widget_get_toplevel (widget)),
8681                                            GTK_DIALOG_DESTROY_WITH_PARENT,
8682                                            GTK_MESSAGE_ERROR,
8683                                            GTK_BUTTONS_OK,
8684                                            "The display :\n%s\ncannot be opened",
8685                                            display_name);
8686           gtk_window_set_screen (GTK_WINDOW (dialog), current_screen);
8687           gtk_widget_show (dialog);
8688           g_signal_connect (dialog, "response",
8689                             G_CALLBACK (gtk_widget_destroy),
8690                             NULL);
8691         }
8692       else
8693         {
8694           if (!g_list_find_custom (data->valid_display_list, 
8695                                    display_name,
8696                                    display_name_cmp))
8697             data->valid_display_list = g_list_append (data->valid_display_list,
8698                                                       display_name);
8699           
8700           new_screen = gdk_display_get_default_screen (display);
8701         }
8702     }
8703   else
8704     {
8705       gint number_of_screens = gdk_display_get_n_screens (display);
8706       gint screen_num = gdk_screen_get_number (current_screen);
8707       if ((screen_num +1) < number_of_screens)
8708         new_screen = gdk_display_get_screen (display, screen_num + 1);
8709       else
8710         new_screen = gdk_display_get_screen (display, 0);
8711     }
8712   
8713   if (new_screen) 
8714     {
8715       gtk_window_set_screen (GTK_WINDOW (data->toplevel), new_screen);
8716       gtk_widget_destroy (data->dialog_window);
8717     }
8718 }
8719
8720 void
8721 screen_display_destroy_diag (GtkWidget *widget, GtkWidget *data)
8722 {
8723   gtk_widget_destroy (data);
8724 }
8725
8726 void
8727 create_display_screen (GtkWidget *widget)
8728 {
8729   GtkWidget *table, *frame, *window, *combo_dpy, *vbox;
8730   GtkWidget *radio_dpy, *radio_scr, *applyb, *cancelb;
8731   GtkWidget *bbox;
8732   ScreenDisplaySelection *scr_dpy_data;
8733   GdkScreen *screen = gtk_widget_get_screen (widget);
8734   static GList *valid_display_list = NULL;
8735   
8736   GdkDisplay *display = gdk_screen_get_display (screen);
8737
8738   window = g_object_new (gtk_window_get_type (),
8739                            "screen", screen,
8740                            "user_data", NULL,
8741                            "type", GTK_WINDOW_TOPLEVEL,
8742                            "title",
8743                            "Screen or Display selection",
8744                            "border_width", 10, NULL);
8745   g_signal_connect (window, "destroy", 
8746                     G_CALLBACK (gtk_widget_destroy), NULL);
8747
8748   vbox = gtk_vbox_new (FALSE, 3);
8749   gtk_container_add (GTK_CONTAINER (window), vbox);
8750   
8751   frame = gtk_frame_new ("Select screen or display");
8752   gtk_container_add (GTK_CONTAINER (vbox), frame);
8753   
8754   table = gtk_table_new (2, 2, TRUE);
8755   gtk_table_set_row_spacings (GTK_TABLE (table), 3);
8756   gtk_table_set_col_spacings (GTK_TABLE (table), 3);
8757
8758   gtk_container_add (GTK_CONTAINER (frame), table);
8759
8760   radio_dpy = gtk_radio_button_new_with_label (NULL, "move to another X display");
8761   if (gdk_display_get_n_screens(display) > 1)
8762     radio_scr = gtk_radio_button_new_with_label 
8763     (gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio_dpy)), "move to next screen");
8764   else
8765     {    
8766       radio_scr = gtk_radio_button_new_with_label 
8767         (gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio_dpy)), 
8768          "only one screen on the current display");
8769       gtk_widget_set_sensitive (radio_scr, FALSE);
8770     }
8771   combo_dpy = gtk_combo_new ();
8772   if (!valid_display_list)
8773     valid_display_list = g_list_append (valid_display_list, "diabolo:0.0");
8774     
8775   gtk_combo_set_popdown_strings (GTK_COMBO (combo_dpy), valid_display_list);
8776     
8777   gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (combo_dpy)->entry), 
8778                       "<hostname>:<X Server Num>.<Screen Num>");
8779
8780   gtk_table_attach_defaults (GTK_TABLE (table), radio_dpy, 0, 1, 0, 1);
8781   gtk_table_attach_defaults (GTK_TABLE (table), radio_scr, 0, 1, 1, 2);
8782   gtk_table_attach_defaults (GTK_TABLE (table), combo_dpy, 1, 2, 0, 1);
8783
8784   bbox = gtk_hbutton_box_new ();
8785   applyb = gtk_button_new_from_stock (GTK_STOCK_APPLY);
8786   cancelb = gtk_button_new_from_stock (GTK_STOCK_CANCEL);
8787   
8788   gtk_container_add (GTK_CONTAINER (vbox), bbox);
8789
8790   gtk_container_add (GTK_CONTAINER (bbox), applyb);
8791   gtk_container_add (GTK_CONTAINER (bbox), cancelb);
8792
8793   scr_dpy_data = g_new0 (ScreenDisplaySelection, 1);
8794
8795   scr_dpy_data->entry = GTK_ENTRY (GTK_COMBO (combo_dpy)->entry);
8796   scr_dpy_data->radio_dpy = radio_dpy;
8797   scr_dpy_data->toplevel = gtk_widget_get_toplevel (widget);
8798   scr_dpy_data->dialog_window = window;
8799   scr_dpy_data->valid_display_list = valid_display_list;
8800
8801   g_signal_connect (cancelb, "clicked", 
8802                     G_CALLBACK (screen_display_destroy_diag), window);
8803   g_signal_connect (applyb, "clicked", 
8804                     G_CALLBACK (screen_display_check), scr_dpy_data);
8805   gtk_widget_show_all (window);
8806 }
8807
8808 /* Event Watcher
8809  */
8810 static gboolean event_watcher_enter_id = 0;
8811 static gboolean event_watcher_leave_id = 0;
8812
8813 static gboolean
8814 event_watcher (GSignalInvocationHint *ihint,
8815                guint                  n_param_values,
8816                const GValue          *param_values,
8817                gpointer               data)
8818 {
8819   g_print ("Watch: \"%s\" emitted for %s\n",
8820            g_signal_name (ihint->signal_id),
8821            G_OBJECT_TYPE_NAME (g_value_get_object (param_values + 0)));
8822
8823   return TRUE;
8824 }
8825
8826 static void
8827 event_watcher_down (void)
8828 {
8829   if (event_watcher_enter_id)
8830     {
8831       guint signal_id;
8832
8833       signal_id = g_signal_lookup ("enter_notify_event", GTK_TYPE_WIDGET);
8834       g_signal_remove_emission_hook (signal_id, event_watcher_enter_id);
8835       event_watcher_enter_id = 0;
8836       signal_id = g_signal_lookup ("leave_notify_event", GTK_TYPE_WIDGET);
8837       g_signal_remove_emission_hook (signal_id, event_watcher_leave_id);
8838       event_watcher_leave_id = 0;
8839     }
8840 }
8841
8842 static void
8843 event_watcher_toggle (void)
8844 {
8845   if (event_watcher_enter_id)
8846     event_watcher_down ();
8847   else
8848     {
8849       guint signal_id;
8850
8851       signal_id = g_signal_lookup ("enter_notify_event", GTK_TYPE_WIDGET);
8852       event_watcher_enter_id = g_signal_add_emission_hook (signal_id, 0, event_watcher, NULL, NULL);
8853       signal_id = g_signal_lookup ("leave_notify_event", GTK_TYPE_WIDGET);
8854       event_watcher_leave_id = g_signal_add_emission_hook (signal_id, 0, event_watcher, NULL, NULL);
8855     }
8856 }
8857
8858 static void
8859 create_event_watcher (GtkWidget *widget)
8860 {
8861   GtkWidget *button;
8862
8863   if (!dialog_window)
8864     {
8865       dialog_window = gtk_dialog_new ();
8866       gtk_window_set_screen (GTK_WINDOW (dialog_window),
8867                              gtk_widget_get_screen (widget));
8868
8869       g_signal_connect (dialog_window, "destroy",
8870                         G_CALLBACK (gtk_widget_destroyed),
8871                         &dialog_window);
8872       g_signal_connect (dialog_window, "destroy",
8873                         G_CALLBACK (event_watcher_down),
8874                         NULL);
8875
8876       gtk_window_set_title (GTK_WINDOW (dialog_window), "Event Watcher");
8877       gtk_container_set_border_width (GTK_CONTAINER (dialog_window), 0);
8878       gtk_widget_set_size_request (dialog_window, 200, 110);
8879
8880       button = gtk_toggle_button_new_with_label ("Activate Watch");
8881       g_signal_connect (button, "clicked",
8882                         G_CALLBACK (event_watcher_toggle),
8883                         NULL);
8884       gtk_container_set_border_width (GTK_CONTAINER (button), 10);
8885       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog_window)->vbox), 
8886                           button, TRUE, TRUE, 0);
8887       gtk_widget_show (button);
8888
8889       button = gtk_button_new_with_label ("Close");
8890       g_signal_connect_swapped (button, "clicked",
8891                                 G_CALLBACK (gtk_widget_destroy),
8892                                 dialog_window);
8893       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
8894       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog_window)->action_area),
8895                           button, TRUE, TRUE, 0);
8896       gtk_widget_grab_default (button);
8897       gtk_widget_show (button);
8898     }
8899
8900   if (!GTK_WIDGET_VISIBLE (dialog_window))
8901     gtk_widget_show (dialog_window);
8902   else
8903     gtk_widget_destroy (dialog_window);
8904 }
8905
8906 /*
8907  * GtkRange
8908  */
8909
8910 static gchar*
8911 reformat_value (GtkScale *scale,
8912                 gdouble   value)
8913 {
8914   return g_strdup_printf ("-->%0.*g<--",
8915                           gtk_scale_get_digits (scale), value);
8916 }
8917
8918 static void
8919 create_range_controls (GtkWidget *widget)
8920 {
8921   static GtkWidget *window = NULL;
8922   GtkWidget *box1;
8923   GtkWidget *box2;
8924   GtkWidget *button;
8925   GtkWidget *scrollbar;
8926   GtkWidget *scale;
8927   GtkWidget *separator;
8928   GtkObject *adjustment;
8929   GtkWidget *hbox;
8930
8931   if (!window)
8932     {
8933       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8934
8935       gtk_window_set_screen (GTK_WINDOW (window),
8936                              gtk_widget_get_screen (widget));
8937
8938       g_signal_connect (window, "destroy",
8939                         G_CALLBACK (gtk_widget_destroyed),
8940                         &window);
8941
8942       gtk_window_set_title (GTK_WINDOW (window), "range controls");
8943       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
8944
8945
8946       box1 = gtk_vbox_new (FALSE, 0);
8947       gtk_container_add (GTK_CONTAINER (window), box1);
8948       gtk_widget_show (box1);
8949
8950
8951       box2 = gtk_vbox_new (FALSE, 10);
8952       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
8953       gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
8954       gtk_widget_show (box2);
8955
8956
8957       adjustment = gtk_adjustment_new (0.0, 0.0, 101.0, 0.1, 1.0, 1.0);
8958
8959       scale = gtk_hscale_new (GTK_ADJUSTMENT (adjustment));
8960       gtk_widget_set_size_request (GTK_WIDGET (scale), 150, -1);
8961       gtk_range_set_update_policy (GTK_RANGE (scale), GTK_UPDATE_DELAYED);
8962       gtk_scale_set_digits (GTK_SCALE (scale), 1);
8963       gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE);
8964       gtk_box_pack_start (GTK_BOX (box2), scale, TRUE, TRUE, 0);
8965       gtk_widget_show (scale);
8966
8967       scrollbar = gtk_hscrollbar_new (GTK_ADJUSTMENT (adjustment));
8968       gtk_range_set_update_policy (GTK_RANGE (scrollbar), 
8969                                    GTK_UPDATE_CONTINUOUS);
8970       gtk_box_pack_start (GTK_BOX (box2), scrollbar, TRUE, TRUE, 0);
8971       gtk_widget_show (scrollbar);
8972
8973       scale = gtk_hscale_new (GTK_ADJUSTMENT (adjustment));
8974       gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE);
8975       g_signal_connect (scale,
8976                         "format_value",
8977                         G_CALLBACK (reformat_value),
8978                         NULL);
8979       gtk_box_pack_start (GTK_BOX (box2), scale, TRUE, TRUE, 0);
8980       gtk_widget_show (scale);
8981       
8982       hbox = gtk_hbox_new (FALSE, 0);
8983
8984       scale = gtk_vscale_new (GTK_ADJUSTMENT (adjustment));
8985       gtk_widget_set_size_request (scale, -1, 200);
8986       gtk_scale_set_digits (GTK_SCALE (scale), 2);
8987       gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE);
8988       gtk_box_pack_start (GTK_BOX (hbox), scale, TRUE, TRUE, 0);
8989       gtk_widget_show (scale);
8990
8991       scale = gtk_vscale_new (GTK_ADJUSTMENT (adjustment));
8992       gtk_widget_set_size_request (scale, -1, 200);
8993       gtk_scale_set_digits (GTK_SCALE (scale), 2);
8994       gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE);
8995       gtk_range_set_inverted (GTK_RANGE (scale), TRUE);
8996       gtk_box_pack_start (GTK_BOX (hbox), scale, TRUE, TRUE, 0);
8997       gtk_widget_show (scale);
8998
8999       scale = gtk_vscale_new (GTK_ADJUSTMENT (adjustment));
9000       gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE);
9001       g_signal_connect (scale,
9002                         "format_value",
9003                         G_CALLBACK (reformat_value),
9004                         NULL);
9005       gtk_box_pack_start (GTK_BOX (hbox), scale, TRUE, TRUE, 0);
9006       gtk_widget_show (scale);
9007
9008       
9009       gtk_box_pack_start (GTK_BOX (box2), hbox, TRUE, TRUE, 0);
9010       gtk_widget_show (hbox);
9011       
9012       separator = gtk_hseparator_new ();
9013       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
9014       gtk_widget_show (separator);
9015
9016
9017       box2 = gtk_vbox_new (FALSE, 10);
9018       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
9019       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
9020       gtk_widget_show (box2);
9021
9022
9023       button = gtk_button_new_with_label ("close");
9024       g_signal_connect_swapped (button, "clicked",
9025                                 G_CALLBACK (gtk_widget_destroy),
9026                                 window);
9027       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
9028       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
9029       gtk_widget_grab_default (button);
9030       gtk_widget_show (button);
9031     }
9032
9033   if (!GTK_WIDGET_VISIBLE (window))
9034     gtk_widget_show (window);
9035   else
9036     gtk_widget_destroy (window);
9037 }
9038
9039 /*
9040  * GtkRulers
9041  */
9042
9043 void
9044 create_rulers (GtkWidget *widget)
9045 {
9046   static GtkWidget *window = NULL;
9047   GtkWidget *table;
9048   GtkWidget *ruler;
9049
9050   if (!window)
9051     {
9052       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9053
9054       gtk_window_set_screen (GTK_WINDOW (window),
9055                              gtk_widget_get_screen (widget));
9056
9057       g_object_set (window, "allow_shrink", TRUE, "allow_grow", TRUE, NULL);
9058
9059       g_signal_connect (window, "destroy",
9060                         G_CALLBACK (gtk_widget_destroyed),
9061                         &window);
9062
9063       gtk_window_set_title (GTK_WINDOW (window), "rulers");
9064       gtk_widget_set_size_request (window, 300, 300);
9065       gtk_widget_set_events (window, 
9066                              GDK_POINTER_MOTION_MASK 
9067                              | GDK_POINTER_MOTION_HINT_MASK);
9068       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
9069
9070       table = gtk_table_new (2, 2, FALSE);
9071       gtk_container_add (GTK_CONTAINER (window), table);
9072       gtk_widget_show (table);
9073
9074       ruler = gtk_hruler_new ();
9075       gtk_ruler_set_metric (GTK_RULER (ruler), GTK_CENTIMETERS);
9076       gtk_ruler_set_range (GTK_RULER (ruler), 100, 0, 0, 20);
9077
9078       g_signal_connect_swapped (window, 
9079                                 "motion_notify_event",
9080                                 G_CALLBACK (GTK_WIDGET_GET_CLASS (ruler)->motion_notify_event),
9081                                 ruler);
9082       
9083       gtk_table_attach (GTK_TABLE (table), ruler, 1, 2, 0, 1,
9084                         GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
9085       gtk_widget_show (ruler);
9086
9087
9088       ruler = gtk_vruler_new ();
9089       gtk_ruler_set_range (GTK_RULER (ruler), 5, 15, 0, 20);
9090
9091       g_signal_connect_swapped (window, 
9092                                 "motion_notify_event",
9093                                 G_CALLBACK (GTK_WIDGET_GET_CLASS (ruler)->motion_notify_event),
9094                                 ruler);
9095       
9096       gtk_table_attach (GTK_TABLE (table), ruler, 0, 1, 1, 2,
9097                         GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
9098       gtk_widget_show (ruler);
9099     }
9100
9101   if (!GTK_WIDGET_VISIBLE (window))
9102     gtk_widget_show (window);
9103   else
9104     gtk_widget_destroy (window);
9105 }
9106
9107 static void
9108 text_toggle_editable (GtkWidget *checkbutton,
9109                        GtkWidget *text)
9110 {
9111    gtk_text_set_editable(GTK_TEXT(text),
9112                           GTK_TOGGLE_BUTTON(checkbutton)->active);
9113 }
9114
9115 static void
9116 text_toggle_word_wrap (GtkWidget *checkbutton,
9117                        GtkWidget *text)
9118 {
9119    gtk_text_set_word_wrap(GTK_TEXT(text),
9120                           GTK_TOGGLE_BUTTON(checkbutton)->active);
9121 }
9122
9123 struct {
9124   GdkColor color;
9125   gchar *name;
9126 } text_colors[] = {
9127  { { 0, 0x0000, 0x0000, 0x0000 }, "black" },
9128  { { 0, 0xFFFF, 0xFFFF, 0xFFFF }, "white" },
9129  { { 0, 0xFFFF, 0x0000, 0x0000 }, "red" },
9130  { { 0, 0x0000, 0xFFFF, 0x0000 }, "green" },
9131  { { 0, 0x0000, 0x0000, 0xFFFF }, "blue" }, 
9132  { { 0, 0x0000, 0xFFFF, 0xFFFF }, "cyan" },
9133  { { 0, 0xFFFF, 0x0000, 0xFFFF }, "magenta" },
9134  { { 0, 0xFFFF, 0xFFFF, 0x0000 }, "yellow" }
9135 };
9136
9137 int ntext_colors = sizeof(text_colors) / sizeof(text_colors[0]);
9138
9139 /*
9140  * GtkText
9141  */
9142 void
9143 text_insert_random (GtkWidget *w, GtkText *text)
9144 {
9145   int i;
9146   char c;
9147    for (i=0; i<10; i++)
9148     {
9149       c = 'A' + rand() % ('Z' - 'A');
9150       gtk_text_set_point (text, rand() % gtk_text_get_length (text));
9151       gtk_text_insert (text, NULL, NULL, NULL, &c, 1);
9152     }
9153 }
9154
9155 void
9156 create_text (GtkWidget *widget)
9157 {
9158   int i, j;
9159
9160   static GtkWidget *window = NULL;
9161   GtkWidget *box1;
9162   GtkWidget *box2;
9163   GtkWidget *hbox;
9164   GtkWidget *button;
9165   GtkWidget *check;
9166   GtkWidget *separator;
9167   GtkWidget *scrolled_window;
9168   GtkWidget *text;
9169
9170   FILE *infile;
9171
9172   if (!window)
9173     {
9174       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9175       gtk_window_set_screen (GTK_WINDOW (window),
9176                              gtk_widget_get_screen (widget));
9177
9178       gtk_widget_set_name (window, "text window");
9179       g_object_set (window, "allow_shrink", TRUE, "allow_grow", TRUE, NULL);
9180       gtk_widget_set_size_request (window, 500, 500);
9181
9182       g_signal_connect (window, "destroy",
9183                         G_CALLBACK (gtk_widget_destroyed),
9184                         &window);
9185
9186       gtk_window_set_title (GTK_WINDOW (window), "test");
9187       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
9188
9189
9190       box1 = gtk_vbox_new (FALSE, 0);
9191       gtk_container_add (GTK_CONTAINER (window), box1);
9192       gtk_widget_show (box1);
9193
9194
9195       box2 = gtk_vbox_new (FALSE, 10);
9196       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
9197       gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
9198       gtk_widget_show (box2);
9199
9200
9201       scrolled_window = gtk_scrolled_window_new (NULL, NULL);
9202       gtk_box_pack_start (GTK_BOX (box2), scrolled_window, TRUE, TRUE, 0);
9203       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
9204                                       GTK_POLICY_NEVER,
9205                                       GTK_POLICY_ALWAYS);
9206       gtk_widget_show (scrolled_window);
9207
9208       text = gtk_text_new (NULL, NULL);
9209       gtk_text_set_editable (GTK_TEXT (text), TRUE);
9210       gtk_container_add (GTK_CONTAINER (scrolled_window), text);
9211       gtk_widget_grab_focus (text);
9212       gtk_widget_show (text);
9213
9214
9215       gtk_text_freeze (GTK_TEXT (text));
9216
9217       for (i=0; i<ntext_colors; i++)
9218         {
9219           gtk_text_insert (GTK_TEXT (text), NULL, NULL, NULL, 
9220                            text_colors[i].name, -1);
9221           gtk_text_insert (GTK_TEXT (text), NULL, NULL, NULL, "\t", -1);
9222
9223           for (j=0; j<ntext_colors; j++)
9224             {
9225               gtk_text_insert (GTK_TEXT (text), NULL,
9226                                &text_colors[j].color, &text_colors[i].color,
9227                                "XYZ", -1);
9228             }
9229           gtk_text_insert (GTK_TEXT (text), NULL, NULL, NULL, "\n", -1);
9230         }
9231
9232       infile = fopen("testgtk.c", "r");
9233       
9234       if (infile)
9235         {
9236           char *buffer;
9237           int nbytes_read, nbytes_alloc;
9238           
9239           nbytes_read = 0;
9240           nbytes_alloc = 1024;
9241           buffer = g_new (char, nbytes_alloc);
9242           while (1)
9243             {
9244               int len;
9245               if (nbytes_alloc < nbytes_read + 1024)
9246                 {
9247                   nbytes_alloc *= 2;
9248                   buffer = g_realloc (buffer, nbytes_alloc);
9249                 }
9250               len = fread (buffer + nbytes_read, 1, 1024, infile);
9251               nbytes_read += len;
9252               if (len < 1024)
9253                 break;
9254             }
9255           
9256           gtk_text_insert (GTK_TEXT (text), NULL, NULL,
9257                            NULL, buffer, nbytes_read);
9258           g_free(buffer);
9259           fclose (infile);
9260         }
9261       
9262       gtk_text_thaw (GTK_TEXT (text));
9263
9264       hbox = gtk_hbutton_box_new ();
9265       gtk_box_pack_start (GTK_BOX (box2), hbox, FALSE, FALSE, 0);
9266       gtk_widget_show (hbox);
9267
9268       check = gtk_check_button_new_with_label("Editable");
9269       gtk_box_pack_start (GTK_BOX (hbox), check, FALSE, FALSE, 0);
9270       g_signal_connect (check, "toggled",
9271                         G_CALLBACK (text_toggle_editable), text);
9272       gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), TRUE);
9273       gtk_widget_show (check);
9274
9275       check = gtk_check_button_new_with_label("Wrap Words");
9276       gtk_box_pack_start (GTK_BOX (hbox), check, FALSE, TRUE, 0);
9277       g_signal_connect (check, "toggled",
9278                         G_CALLBACK (text_toggle_word_wrap), text);
9279       gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), FALSE);
9280       gtk_widget_show (check);
9281
9282       separator = gtk_hseparator_new ();
9283       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
9284       gtk_widget_show (separator);
9285
9286
9287       box2 = gtk_vbox_new (FALSE, 10);
9288       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
9289       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
9290       gtk_widget_show (box2);
9291
9292
9293       button = gtk_button_new_with_label ("insert random");
9294       g_signal_connect (button, "clicked",
9295                         G_CALLBACK (text_insert_random),
9296                         text);
9297       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
9298       gtk_widget_show (button);
9299
9300       button = gtk_button_new_with_label ("close");
9301       g_signal_connect_swapped (button, "clicked",
9302                                 G_CALLBACK (gtk_widget_destroy),
9303                                 window);
9304       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
9305       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
9306       gtk_widget_grab_default (button);
9307       gtk_widget_show (button);
9308     }
9309
9310   if (!GTK_WIDGET_VISIBLE (window))
9311     gtk_widget_show (window);
9312   else
9313     gtk_widget_destroy (window);
9314 }
9315
9316 /*
9317  * GtkNotebook
9318  */
9319
9320 GdkPixbuf *book_open;
9321 GdkPixbuf *book_closed;
9322 GtkWidget *sample_notebook;
9323
9324 static void
9325 set_page_image (GtkNotebook *notebook, gint page_num, GdkPixbuf *pixbuf)
9326 {
9327   GtkWidget *page_widget;
9328   GtkWidget *pixwid;
9329
9330   page_widget = gtk_notebook_get_nth_page (notebook, page_num);
9331
9332   pixwid = g_object_get_data (G_OBJECT (page_widget), "tab_pixmap");
9333   gtk_image_set_from_pixbuf (GTK_IMAGE (pixwid), pixbuf);
9334   
9335   pixwid = g_object_get_data (G_OBJECT (page_widget), "menu_pixmap");
9336   gtk_image_set_from_pixbuf (GTK_IMAGE (pixwid), pixbuf);
9337 }
9338
9339 static void
9340 page_switch (GtkWidget *widget, GtkNotebookPage *page, gint page_num)
9341 {
9342   GtkNotebook *notebook = GTK_NOTEBOOK (widget);
9343   gint old_page_num = gtk_notebook_get_current_page (notebook);
9344  
9345   if (page_num == old_page_num)
9346     return;
9347
9348   set_page_image (notebook, page_num, book_open);
9349
9350   if (old_page_num != -1)
9351     set_page_image (notebook, old_page_num, book_closed);
9352 }
9353
9354 static void
9355 tab_fill (GtkToggleButton *button, GtkWidget *child)
9356 {
9357   gboolean expand;
9358   GtkPackType pack_type;
9359
9360   gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (sample_notebook), child,
9361                                         &expand, NULL, &pack_type);
9362   gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (sample_notebook), child,
9363                                       expand, button->active, pack_type);
9364 }
9365
9366 static void
9367 tab_expand (GtkToggleButton *button, GtkWidget *child)
9368 {
9369   gboolean fill;
9370   GtkPackType pack_type;
9371
9372   gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (sample_notebook), child,
9373                                         NULL, &fill, &pack_type);
9374   gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (sample_notebook), child,
9375                                       button->active, fill, pack_type);
9376 }
9377
9378 static void
9379 tab_pack (GtkToggleButton *button, GtkWidget *child)
9380           
9381
9382   gboolean expand;
9383   gboolean fill;
9384
9385   gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (sample_notebook), child,
9386                                         &expand, &fill, NULL);
9387   gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (sample_notebook), child,
9388                                       expand, fill, button->active);
9389 }
9390
9391 static void
9392 create_pages (GtkNotebook *notebook, gint start, gint end)
9393 {
9394   GtkWidget *child = NULL;
9395   GtkWidget *button;
9396   GtkWidget *label;
9397   GtkWidget *hbox;
9398   GtkWidget *vbox;
9399   GtkWidget *label_box;
9400   GtkWidget *menu_box;
9401   GtkWidget *pixwid;
9402   gint i;
9403   char buffer[32];
9404   char accel_buffer[32];
9405
9406   for (i = start; i <= end; i++)
9407     {
9408       sprintf (buffer, "Page %d", i);
9409       sprintf (accel_buffer, "Page _%d", i);
9410
9411       child = gtk_frame_new (buffer);
9412       gtk_container_set_border_width (GTK_CONTAINER (child), 10);
9413
9414       vbox = gtk_vbox_new (TRUE,0);
9415       gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
9416       gtk_container_add (GTK_CONTAINER (child), vbox);
9417
9418       hbox = gtk_hbox_new (TRUE,0);
9419       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 5);
9420
9421       button = gtk_check_button_new_with_label ("Fill Tab");
9422       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
9423       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
9424       g_signal_connect (button, "toggled",
9425                         G_CALLBACK (tab_fill), child);
9426
9427       button = gtk_check_button_new_with_label ("Expand Tab");
9428       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
9429       g_signal_connect (button, "toggled",
9430                         G_CALLBACK (tab_expand), child);
9431
9432       button = gtk_check_button_new_with_label ("Pack end");
9433       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
9434       g_signal_connect (button, "toggled",
9435                         G_CALLBACK (tab_pack), child);
9436
9437       button = gtk_button_new_with_label ("Hide Page");
9438       gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 5);
9439       g_signal_connect_swapped (button, "clicked",
9440                                 G_CALLBACK (gtk_widget_hide),
9441                                 child);
9442
9443       gtk_widget_show_all (child);
9444
9445       label_box = gtk_hbox_new (FALSE, 0);
9446       pixwid = gtk_image_new_from_pixbuf (book_closed);
9447       g_object_set_data (G_OBJECT (child), "tab_pixmap", pixwid);
9448                            
9449       gtk_box_pack_start (GTK_BOX (label_box), pixwid, FALSE, TRUE, 0);
9450       gtk_misc_set_padding (GTK_MISC (pixwid), 3, 1);
9451       label = gtk_label_new_with_mnemonic (accel_buffer);
9452       gtk_box_pack_start (GTK_BOX (label_box), label, FALSE, TRUE, 0);
9453       gtk_widget_show_all (label_box);
9454       
9455                                        
9456       menu_box = gtk_hbox_new (FALSE, 0);
9457       pixwid = gtk_image_new_from_pixbuf (book_closed);
9458       g_object_set_data (G_OBJECT (child), "menu_pixmap", pixwid);
9459       
9460       gtk_box_pack_start (GTK_BOX (menu_box), pixwid, FALSE, TRUE, 0);
9461       gtk_misc_set_padding (GTK_MISC (pixwid), 3, 1);
9462       label = gtk_label_new (buffer);
9463       gtk_box_pack_start (GTK_BOX (menu_box), label, FALSE, TRUE, 0);
9464       gtk_widget_show_all (menu_box);
9465
9466       gtk_notebook_append_page_menu (notebook, child, label_box, menu_box);
9467     }
9468 }
9469
9470 static void
9471 rotate_notebook (GtkButton   *button,
9472                  GtkNotebook *notebook)
9473 {
9474   gtk_notebook_set_tab_pos (notebook, (notebook->tab_pos + 1) % 4);
9475 }
9476
9477 static void
9478 show_all_pages (GtkButton   *button,
9479                 GtkNotebook *notebook)
9480 {  
9481   gtk_container_foreach (GTK_CONTAINER (notebook),
9482                          (GtkCallback) gtk_widget_show, NULL);
9483 }
9484
9485 static void
9486 notebook_type_changed (GtkWidget *optionmenu,
9487                        gpointer   data)
9488 {
9489   GtkNotebook *notebook;
9490   gint i, c;
9491
9492   enum {
9493     STANDARD,
9494     NOTABS,
9495     BORDERLESS,
9496     SCROLLABLE
9497   };
9498
9499   notebook = GTK_NOTEBOOK (data);
9500
9501   c = gtk_option_menu_get_history (GTK_OPTION_MENU (optionmenu));
9502
9503   switch (c)
9504     {
9505     case STANDARD:
9506       /* standard notebook */
9507       gtk_notebook_set_show_tabs (notebook, TRUE);
9508       gtk_notebook_set_show_border (notebook, TRUE);
9509       gtk_notebook_set_scrollable (notebook, FALSE);
9510       break;
9511
9512     case NOTABS:
9513       /* notabs notebook */
9514       gtk_notebook_set_show_tabs (notebook, FALSE);
9515       gtk_notebook_set_show_border (notebook, TRUE);
9516       break;
9517
9518     case BORDERLESS:
9519       /* borderless */
9520       gtk_notebook_set_show_tabs (notebook, FALSE);
9521       gtk_notebook_set_show_border (notebook, FALSE);
9522       break;
9523
9524     case SCROLLABLE:  
9525       /* scrollable */
9526       gtk_notebook_set_show_tabs (notebook, TRUE);
9527       gtk_notebook_set_show_border (notebook, TRUE);
9528       gtk_notebook_set_scrollable (notebook, TRUE);
9529       if (g_list_length (notebook->children) == 5)
9530         create_pages (notebook, 6, 15);
9531       
9532       return;
9533       break;
9534     }
9535   
9536   if (g_list_length (notebook->children) == 15)
9537     for (i = 0; i < 10; i++)
9538       gtk_notebook_remove_page (notebook, 5);
9539 }
9540
9541 static void
9542 notebook_popup (GtkToggleButton *button,
9543                 GtkNotebook     *notebook)
9544 {
9545   if (button->active)
9546     gtk_notebook_popup_enable (notebook);
9547   else
9548     gtk_notebook_popup_disable (notebook);
9549 }
9550
9551 static void
9552 notebook_homogeneous (GtkToggleButton *button,
9553                       GtkNotebook     *notebook)
9554 {
9555   g_object_set (notebook, "homogeneous", button->active, NULL);
9556 }
9557
9558 static void
9559 create_notebook (GtkWidget *widget)
9560 {
9561   static GtkWidget *window = NULL;
9562   GtkWidget *box1;
9563   GtkWidget *box2;
9564   GtkWidget *button;
9565   GtkWidget *separator;
9566   GtkWidget *omenu;
9567   GtkWidget *label;
9568
9569   static gchar *items[] =
9570   {
9571     "Standard",
9572     "No tabs",
9573     "Borderless",
9574     "Scrollable"
9575   };
9576   
9577   if (!window)
9578     {
9579       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9580       gtk_window_set_screen (GTK_WINDOW (window),
9581                              gtk_widget_get_screen (widget));
9582
9583       g_signal_connect (window, "destroy",
9584                         G_CALLBACK (gtk_widget_destroyed),
9585                         &window);
9586
9587       gtk_window_set_title (GTK_WINDOW (window), "notebook");
9588       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
9589
9590       box1 = gtk_vbox_new (FALSE, 0);
9591       gtk_container_add (GTK_CONTAINER (window), box1);
9592
9593       sample_notebook = gtk_notebook_new ();
9594       g_signal_connect (sample_notebook, "switch_page",
9595                         G_CALLBACK (page_switch), NULL);
9596       gtk_notebook_set_tab_pos (GTK_NOTEBOOK (sample_notebook), GTK_POS_TOP);
9597       gtk_box_pack_start (GTK_BOX (box1), sample_notebook, TRUE, TRUE, 0);
9598       gtk_container_set_border_width (GTK_CONTAINER (sample_notebook), 10);
9599
9600       gtk_widget_realize (sample_notebook);
9601
9602       if (!book_open)
9603         book_open = gdk_pixbuf_new_from_xpm_data ((const char **)book_open_xpm);
9604                                                   
9605       if (!book_closed)
9606         book_closed = gdk_pixbuf_new_from_xpm_data ((const char **)book_closed_xpm);
9607
9608       create_pages (GTK_NOTEBOOK (sample_notebook), 1, 5);
9609
9610       separator = gtk_hseparator_new ();
9611       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 10);
9612       
9613       box2 = gtk_hbox_new (FALSE, 5);
9614       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
9615       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
9616
9617       button = gtk_check_button_new_with_label ("popup menu");
9618       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, FALSE, 0);
9619       g_signal_connect (button, "clicked",
9620                         G_CALLBACK (notebook_popup),
9621                         sample_notebook);
9622
9623       button = gtk_check_button_new_with_label ("homogeneous tabs");
9624       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, FALSE, 0);
9625       g_signal_connect (button, "clicked",
9626                         G_CALLBACK (notebook_homogeneous),
9627                         sample_notebook);
9628
9629       box2 = gtk_hbox_new (FALSE, 5);
9630       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
9631       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
9632
9633       label = gtk_label_new ("Notebook Style :");
9634       gtk_box_pack_start (GTK_BOX (box2), label, FALSE, TRUE, 0);
9635
9636       omenu = build_option_menu (items, G_N_ELEMENTS (items), 0,
9637                                  notebook_type_changed,
9638                                  sample_notebook);
9639       gtk_box_pack_start (GTK_BOX (box2), omenu, FALSE, TRUE, 0);
9640
9641       button = gtk_button_new_with_label ("Show all Pages");
9642       gtk_box_pack_start (GTK_BOX (box2), button, FALSE, TRUE, 0);
9643       g_signal_connect (button, "clicked",
9644                         G_CALLBACK (show_all_pages), sample_notebook);
9645
9646       box2 = gtk_hbox_new (TRUE, 10);
9647       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
9648       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
9649
9650       button = gtk_button_new_with_label ("prev");
9651       g_signal_connect_swapped (button, "clicked",
9652                                 G_CALLBACK (gtk_notebook_prev_page),
9653                                 sample_notebook);
9654       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
9655
9656       button = gtk_button_new_with_label ("next");
9657       g_signal_connect_swapped (button, "clicked",
9658                                 G_CALLBACK (gtk_notebook_next_page),
9659                                 sample_notebook);
9660       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
9661
9662       button = gtk_button_new_with_label ("rotate");
9663       g_signal_connect (button, "clicked",
9664                         G_CALLBACK (rotate_notebook), sample_notebook);
9665       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
9666
9667       separator = gtk_hseparator_new ();
9668       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
9669
9670       button = gtk_button_new_with_label ("close");
9671       gtk_container_set_border_width (GTK_CONTAINER (button), 5);
9672       g_signal_connect_swapped (button, "clicked",
9673                                 G_CALLBACK (gtk_widget_destroy),
9674                                 window);
9675       gtk_box_pack_start (GTK_BOX (box1), button, FALSE, FALSE, 0);
9676       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
9677       gtk_widget_grab_default (button);
9678     }
9679
9680   if (!GTK_WIDGET_VISIBLE (window))
9681     gtk_widget_show_all (window);
9682   else
9683     gtk_widget_destroy (window);
9684 }
9685
9686 /*
9687  * GtkPanes
9688  */
9689
9690 void
9691 toggle_resize (GtkWidget *widget, GtkWidget *child)
9692 {
9693   GtkContainer *container = GTK_CONTAINER (gtk_widget_get_parent (child));
9694   GValue value = { 0, };
9695   g_value_init (&value, G_TYPE_BOOLEAN);
9696   gtk_container_child_get_property (container, child, "resize", &value);
9697   g_value_set_boolean (&value, !g_value_get_boolean (&value));
9698   gtk_container_child_set_property (container, child, "resize", &value);
9699 }
9700
9701 void
9702 toggle_shrink (GtkWidget *widget, GtkWidget *child)
9703 {
9704   GtkContainer *container = GTK_CONTAINER (gtk_widget_get_parent (child));
9705   GValue value = { 0, };
9706   g_value_init (&value, G_TYPE_BOOLEAN);
9707   gtk_container_child_get_property (container, child, "shrink", &value);
9708   g_value_set_boolean (&value, !g_value_get_boolean (&value));
9709   gtk_container_child_set_property (container, child, "shrink", &value);
9710 }
9711
9712 static void
9713 paned_props_clicked (GtkWidget *button,
9714                      GObject   *paned)
9715 {
9716   GtkWidget *window = create_prop_editor (paned, GTK_TYPE_PANED);
9717   
9718   gtk_window_set_title (GTK_WINDOW (window), "Paned Properties");
9719 }
9720
9721 GtkWidget *
9722 create_pane_options (GtkPaned    *paned,
9723                      const gchar *frame_label,
9724                      const gchar *label1,
9725                      const gchar *label2)
9726 {
9727   GtkWidget *frame;
9728   GtkWidget *table;
9729   GtkWidget *label;
9730   GtkWidget *button;
9731   GtkWidget *check_button;
9732   
9733   frame = gtk_frame_new (frame_label);
9734   gtk_container_set_border_width (GTK_CONTAINER (frame), 4);
9735   
9736   table = gtk_table_new (4, 2, 4);
9737   gtk_container_add (GTK_CONTAINER (frame), table);
9738   
9739   label = gtk_label_new (label1);
9740   gtk_table_attach_defaults (GTK_TABLE (table), label,
9741                              0, 1, 0, 1);
9742   
9743   check_button = gtk_check_button_new_with_label ("Resize");
9744   gtk_table_attach_defaults (GTK_TABLE (table), check_button,
9745                              0, 1, 1, 2);
9746   g_signal_connect (check_button, "toggled",
9747                     G_CALLBACK (toggle_resize),
9748                     paned->child1);
9749   
9750   check_button = gtk_check_button_new_with_label ("Shrink");
9751   gtk_table_attach_defaults (GTK_TABLE (table), check_button,
9752                              0, 1, 2, 3);
9753   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button),
9754                                TRUE);
9755   g_signal_connect (check_button, "toggled",
9756                     G_CALLBACK (toggle_shrink),
9757                     paned->child1);
9758   
9759   label = gtk_label_new (label2);
9760   gtk_table_attach_defaults (GTK_TABLE (table), label,
9761                              1, 2, 0, 1);
9762   
9763   check_button = gtk_check_button_new_with_label ("Resize");
9764   gtk_table_attach_defaults (GTK_TABLE (table), check_button,
9765                              1, 2, 1, 2);
9766   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button),
9767                                TRUE);
9768   g_signal_connect (check_button, "toggled",
9769                     G_CALLBACK (toggle_resize),
9770                     paned->child2);
9771   
9772   check_button = gtk_check_button_new_with_label ("Shrink");
9773   gtk_table_attach_defaults (GTK_TABLE (table), check_button,
9774                              1, 2, 2, 3);
9775   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button),
9776                                TRUE);
9777   g_signal_connect (check_button, "toggled",
9778                     G_CALLBACK (toggle_shrink),
9779                     paned->child2);
9780
9781   button = gtk_button_new_with_mnemonic ("_Properties");
9782   gtk_table_attach_defaults (GTK_TABLE (table), button,
9783                              0, 2, 3, 4);
9784   g_signal_connect (button, "clicked",
9785                     G_CALLBACK (paned_props_clicked),
9786                     paned);
9787
9788   return frame;
9789 }
9790
9791 void
9792 create_panes (GtkWidget *widget)
9793 {
9794   static GtkWidget *window = NULL;
9795   GtkWidget *frame;
9796   GtkWidget *hpaned;
9797   GtkWidget *vpaned;
9798   GtkWidget *button;
9799   GtkWidget *vbox;
9800
9801   if (!window)
9802     {
9803       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9804
9805       gtk_window_set_screen (GTK_WINDOW (window),
9806                              gtk_widget_get_screen (widget));
9807       
9808       g_signal_connect (window, "destroy",
9809                         G_CALLBACK (gtk_widget_destroyed),
9810                         &window);
9811
9812       gtk_window_set_title (GTK_WINDOW (window), "Panes");
9813       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
9814
9815       vbox = gtk_vbox_new (FALSE, 0);
9816       gtk_container_add (GTK_CONTAINER (window), vbox);
9817       
9818       vpaned = gtk_vpaned_new ();
9819       gtk_box_pack_start (GTK_BOX (vbox), vpaned, TRUE, TRUE, 0);
9820       gtk_container_set_border_width (GTK_CONTAINER(vpaned), 5);
9821
9822       hpaned = gtk_hpaned_new ();
9823       gtk_paned_add1 (GTK_PANED (vpaned), hpaned);
9824
9825       frame = gtk_frame_new (NULL);
9826       gtk_frame_set_shadow_type (GTK_FRAME(frame), GTK_SHADOW_IN);
9827       gtk_widget_set_size_request (frame, 60, 60);
9828       gtk_paned_add1 (GTK_PANED (hpaned), frame);
9829       
9830       button = gtk_button_new_with_label ("Hi there");
9831       gtk_container_add (GTK_CONTAINER(frame), button);
9832
9833       frame = gtk_frame_new (NULL);
9834       gtk_frame_set_shadow_type (GTK_FRAME(frame), GTK_SHADOW_IN);
9835       gtk_widget_set_size_request (frame, 80, 60);
9836       gtk_paned_add2 (GTK_PANED (hpaned), frame);
9837
9838       frame = gtk_frame_new (NULL);
9839       gtk_frame_set_shadow_type (GTK_FRAME(frame), GTK_SHADOW_IN);
9840       gtk_widget_set_size_request (frame, 60, 80);
9841       gtk_paned_add2 (GTK_PANED (vpaned), frame);
9842
9843       /* Now create toggle buttons to control sizing */
9844
9845       gtk_box_pack_start (GTK_BOX (vbox),
9846                           create_pane_options (GTK_PANED (hpaned),
9847                                                "Horizontal",
9848                                                "Left",
9849                                                "Right"),
9850                           FALSE, FALSE, 0);
9851
9852       gtk_box_pack_start (GTK_BOX (vbox),
9853                           create_pane_options (GTK_PANED (vpaned),
9854                                                "Vertical",
9855                                                "Top",
9856                                                "Bottom"),
9857                           FALSE, FALSE, 0);
9858
9859       gtk_widget_show_all (vbox);
9860     }
9861
9862   if (!GTK_WIDGET_VISIBLE (window))
9863     gtk_widget_show (window);
9864   else
9865     gtk_widget_destroy (window);
9866 }
9867
9868 /*
9869  * Paned keyboard navigation
9870  */
9871
9872 static GtkWidget*
9873 paned_keyboard_window1 (GtkWidget *widget)
9874 {
9875   GtkWidget *window1;
9876   GtkWidget *hpaned1;
9877   GtkWidget *frame1;
9878   GtkWidget *vbox1;
9879   GtkWidget *button7;
9880   GtkWidget *button8;
9881   GtkWidget *button9;
9882   GtkWidget *vpaned1;
9883   GtkWidget *frame2;
9884   GtkWidget *frame5;
9885   GtkWidget *hbox1;
9886   GtkWidget *button5;
9887   GtkWidget *button6;
9888   GtkWidget *frame3;
9889   GtkWidget *frame4;
9890   GtkWidget *table1;
9891   GtkWidget *button1;
9892   GtkWidget *button2;
9893   GtkWidget *button3;
9894   GtkWidget *button4;
9895
9896   window1 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9897   gtk_window_set_title (GTK_WINDOW (window1), "Basic paned navigation");
9898   gtk_window_set_screen (GTK_WINDOW (window1), 
9899                          gtk_widget_get_screen (widget));
9900
9901   hpaned1 = gtk_hpaned_new ();
9902   gtk_container_add (GTK_CONTAINER (window1), hpaned1);
9903
9904   frame1 = gtk_frame_new (NULL);
9905   gtk_paned_pack1 (GTK_PANED (hpaned1), frame1, FALSE, TRUE);
9906   gtk_frame_set_shadow_type (GTK_FRAME (frame1), GTK_SHADOW_IN);
9907
9908   vbox1 = gtk_vbox_new (FALSE, 0);
9909   gtk_container_add (GTK_CONTAINER (frame1), vbox1);
9910
9911   button7 = gtk_button_new_with_label ("button7");
9912   gtk_box_pack_start (GTK_BOX (vbox1), button7, FALSE, FALSE, 0);
9913
9914   button8 = gtk_button_new_with_label ("button8");
9915   gtk_box_pack_start (GTK_BOX (vbox1), button8, FALSE, FALSE, 0);
9916
9917   button9 = gtk_button_new_with_label ("button9");
9918   gtk_box_pack_start (GTK_BOX (vbox1), button9, FALSE, FALSE, 0);
9919
9920   vpaned1 = gtk_vpaned_new ();
9921   gtk_paned_pack2 (GTK_PANED (hpaned1), vpaned1, TRUE, TRUE);
9922
9923   frame2 = gtk_frame_new (NULL);
9924   gtk_paned_pack1 (GTK_PANED (vpaned1), frame2, FALSE, TRUE);
9925   gtk_frame_set_shadow_type (GTK_FRAME (frame2), GTK_SHADOW_IN);
9926
9927   frame5 = gtk_frame_new (NULL);
9928   gtk_container_add (GTK_CONTAINER (frame2), frame5);
9929
9930   hbox1 = gtk_hbox_new (FALSE, 0);
9931   gtk_container_add (GTK_CONTAINER (frame5), hbox1);
9932
9933   button5 = gtk_button_new_with_label ("button5");
9934   gtk_box_pack_start (GTK_BOX (hbox1), button5, FALSE, FALSE, 0);
9935
9936   button6 = gtk_button_new_with_label ("button6");
9937   gtk_box_pack_start (GTK_BOX (hbox1), button6, FALSE, FALSE, 0);
9938
9939   frame3 = gtk_frame_new (NULL);
9940   gtk_paned_pack2 (GTK_PANED (vpaned1), frame3, TRUE, TRUE);
9941   gtk_frame_set_shadow_type (GTK_FRAME (frame3), GTK_SHADOW_IN);
9942
9943   frame4 = gtk_frame_new ("Buttons");
9944   gtk_container_add (GTK_CONTAINER (frame3), frame4);
9945   gtk_container_set_border_width (GTK_CONTAINER (frame4), 15);
9946
9947   table1 = gtk_table_new (2, 2, FALSE);
9948   gtk_container_add (GTK_CONTAINER (frame4), table1);
9949   gtk_container_set_border_width (GTK_CONTAINER (table1), 11);
9950
9951   button1 = gtk_button_new_with_label ("button1");
9952   gtk_table_attach (GTK_TABLE (table1), button1, 0, 1, 0, 1,
9953                     (GtkAttachOptions) (GTK_FILL),
9954                     (GtkAttachOptions) (0), 0, 0);
9955
9956   button2 = gtk_button_new_with_label ("button2");
9957   gtk_table_attach (GTK_TABLE (table1), button2, 1, 2, 0, 1,
9958                     (GtkAttachOptions) (GTK_FILL),
9959                     (GtkAttachOptions) (0), 0, 0);
9960
9961   button3 = gtk_button_new_with_label ("button3");
9962   gtk_table_attach (GTK_TABLE (table1), button3, 0, 1, 1, 2,
9963                     (GtkAttachOptions) (GTK_FILL),
9964                     (GtkAttachOptions) (0), 0, 0);
9965
9966   button4 = gtk_button_new_with_label ("button4");
9967   gtk_table_attach (GTK_TABLE (table1), button4, 1, 2, 1, 2,
9968                     (GtkAttachOptions) (GTK_FILL),
9969                     (GtkAttachOptions) (0), 0, 0);
9970
9971   return window1;
9972 }
9973
9974 static GtkWidget*
9975 paned_keyboard_window2 (GtkWidget *widget)
9976 {
9977   GtkWidget *window2;
9978   GtkWidget *hpaned2;
9979   GtkWidget *frame6;
9980   GtkWidget *button13;
9981   GtkWidget *hbox2;
9982   GtkWidget *vpaned2;
9983   GtkWidget *frame7;
9984   GtkWidget *button12;
9985   GtkWidget *frame8;
9986   GtkWidget *button11;
9987   GtkWidget *button10;
9988
9989   window2 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9990   gtk_window_set_title (GTK_WINDOW (window2), "\"button 10\" is not inside the horisontal pane");
9991
9992   gtk_window_set_screen (GTK_WINDOW (window2), 
9993                          gtk_widget_get_screen (widget));
9994
9995   hpaned2 = gtk_hpaned_new ();
9996   gtk_container_add (GTK_CONTAINER (window2), hpaned2);
9997
9998   frame6 = gtk_frame_new (NULL);
9999   gtk_paned_pack1 (GTK_PANED (hpaned2), frame6, FALSE, TRUE);
10000   gtk_frame_set_shadow_type (GTK_FRAME (frame6), GTK_SHADOW_IN);
10001
10002   button13 = gtk_button_new_with_label ("button13");
10003   gtk_container_add (GTK_CONTAINER (frame6), button13);
10004
10005   hbox2 = gtk_hbox_new (FALSE, 0);
10006   gtk_paned_pack2 (GTK_PANED (hpaned2), hbox2, TRUE, TRUE);
10007
10008   vpaned2 = gtk_vpaned_new ();
10009   gtk_box_pack_start (GTK_BOX (hbox2), vpaned2, TRUE, TRUE, 0);
10010
10011   frame7 = gtk_frame_new (NULL);
10012   gtk_paned_pack1 (GTK_PANED (vpaned2), frame7, FALSE, TRUE);
10013   gtk_frame_set_shadow_type (GTK_FRAME (frame7), GTK_SHADOW_IN);
10014
10015   button12 = gtk_button_new_with_label ("button12");
10016   gtk_container_add (GTK_CONTAINER (frame7), button12);
10017
10018   frame8 = gtk_frame_new (NULL);
10019   gtk_paned_pack2 (GTK_PANED (vpaned2), frame8, TRUE, TRUE);
10020   gtk_frame_set_shadow_type (GTK_FRAME (frame8), GTK_SHADOW_IN);
10021
10022   button11 = gtk_button_new_with_label ("button11");
10023   gtk_container_add (GTK_CONTAINER (frame8), button11);
10024
10025   button10 = gtk_button_new_with_label ("button10");
10026   gtk_box_pack_start (GTK_BOX (hbox2), button10, FALSE, FALSE, 0);
10027
10028   return window2;
10029 }
10030
10031 static GtkWidget*
10032 paned_keyboard_window3 (GtkWidget *widget)
10033 {
10034   GtkWidget *window3;
10035   GtkWidget *vbox2;
10036   GtkWidget *label1;
10037   GtkWidget *hpaned3;
10038   GtkWidget *frame9;
10039   GtkWidget *button14;
10040   GtkWidget *hpaned4;
10041   GtkWidget *frame10;
10042   GtkWidget *button15;
10043   GtkWidget *hpaned5;
10044   GtkWidget *frame11;
10045   GtkWidget *button16;
10046   GtkWidget *frame12;
10047   GtkWidget *button17;
10048
10049   window3 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
10050   g_object_set_data (G_OBJECT (window3), "window3", window3);
10051   gtk_window_set_title (GTK_WINDOW (window3), "Nested panes");
10052
10053   gtk_window_set_screen (GTK_WINDOW (window3), 
10054                          gtk_widget_get_screen (widget));
10055   
10056
10057   vbox2 = gtk_vbox_new (FALSE, 0);
10058   gtk_container_add (GTK_CONTAINER (window3), vbox2);
10059
10060   label1 = gtk_label_new ("Three panes nested inside each other");
10061   gtk_box_pack_start (GTK_BOX (vbox2), label1, FALSE, FALSE, 0);
10062
10063   hpaned3 = gtk_hpaned_new ();
10064   gtk_box_pack_start (GTK_BOX (vbox2), hpaned3, TRUE, TRUE, 0);
10065
10066   frame9 = gtk_frame_new (NULL);
10067   gtk_paned_pack1 (GTK_PANED (hpaned3), frame9, FALSE, TRUE);
10068   gtk_frame_set_shadow_type (GTK_FRAME (frame9), GTK_SHADOW_IN);
10069
10070   button14 = gtk_button_new_with_label ("button14");
10071   gtk_container_add (GTK_CONTAINER (frame9), button14);
10072
10073   hpaned4 = gtk_hpaned_new ();
10074   gtk_paned_pack2 (GTK_PANED (hpaned3), hpaned4, TRUE, TRUE);
10075
10076   frame10 = gtk_frame_new (NULL);
10077   gtk_paned_pack1 (GTK_PANED (hpaned4), frame10, FALSE, TRUE);
10078   gtk_frame_set_shadow_type (GTK_FRAME (frame10), GTK_SHADOW_IN);
10079
10080   button15 = gtk_button_new_with_label ("button15");
10081   gtk_container_add (GTK_CONTAINER (frame10), button15);
10082
10083   hpaned5 = gtk_hpaned_new ();
10084   gtk_paned_pack2 (GTK_PANED (hpaned4), hpaned5, TRUE, TRUE);
10085
10086   frame11 = gtk_frame_new (NULL);
10087   gtk_paned_pack1 (GTK_PANED (hpaned5), frame11, FALSE, TRUE);
10088   gtk_frame_set_shadow_type (GTK_FRAME (frame11), GTK_SHADOW_IN);
10089
10090   button16 = gtk_button_new_with_label ("button16");
10091   gtk_container_add (GTK_CONTAINER (frame11), button16);
10092
10093   frame12 = gtk_frame_new (NULL);
10094   gtk_paned_pack2 (GTK_PANED (hpaned5), frame12, TRUE, TRUE);
10095   gtk_frame_set_shadow_type (GTK_FRAME (frame12), GTK_SHADOW_IN);
10096
10097   button17 = gtk_button_new_with_label ("button17");
10098   gtk_container_add (GTK_CONTAINER (frame12), button17);
10099
10100   return window3;
10101 }
10102
10103 static GtkWidget*
10104 paned_keyboard_window4 (GtkWidget *widget)
10105 {
10106   GtkWidget *window4;
10107   GtkWidget *vbox3;
10108   GtkWidget *label2;
10109   GtkWidget *hpaned6;
10110   GtkWidget *vpaned3;
10111   GtkWidget *button19;
10112   GtkWidget *button18;
10113   GtkWidget *hbox3;
10114   GtkWidget *vpaned4;
10115   GtkWidget *button21;
10116   GtkWidget *button20;
10117   GtkWidget *vpaned5;
10118   GtkWidget *button23;
10119   GtkWidget *button22;
10120   GtkWidget *vpaned6;
10121   GtkWidget *button25;
10122   GtkWidget *button24;
10123
10124   window4 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
10125   g_object_set_data (G_OBJECT (window4), "window4", window4);
10126   gtk_window_set_title (GTK_WINDOW (window4), "window4");
10127
10128   gtk_window_set_screen (GTK_WINDOW (window4), 
10129                          gtk_widget_get_screen (widget));
10130
10131   vbox3 = gtk_vbox_new (FALSE, 0);
10132   gtk_container_add (GTK_CONTAINER (window4), vbox3);
10133
10134   label2 = gtk_label_new ("Widget tree:\n\nhpaned \n - vpaned\n - hbox\n    - vpaned\n    - vpaned\n    - vpaned\n");
10135   gtk_box_pack_start (GTK_BOX (vbox3), label2, FALSE, FALSE, 0);
10136   gtk_label_set_justify (GTK_LABEL (label2), GTK_JUSTIFY_LEFT);
10137
10138   hpaned6 = gtk_hpaned_new ();
10139   gtk_box_pack_start (GTK_BOX (vbox3), hpaned6, TRUE, TRUE, 0);
10140
10141   vpaned3 = gtk_vpaned_new ();
10142   gtk_paned_pack1 (GTK_PANED (hpaned6), vpaned3, FALSE, TRUE);
10143
10144   button19 = gtk_button_new_with_label ("button19");
10145   gtk_paned_pack1 (GTK_PANED (vpaned3), button19, FALSE, TRUE);
10146
10147   button18 = gtk_button_new_with_label ("button18");
10148   gtk_paned_pack2 (GTK_PANED (vpaned3), button18, TRUE, TRUE);
10149
10150   hbox3 = gtk_hbox_new (FALSE, 0);
10151   gtk_paned_pack2 (GTK_PANED (hpaned6), hbox3, TRUE, TRUE);
10152
10153   vpaned4 = gtk_vpaned_new ();
10154   gtk_box_pack_start (GTK_BOX (hbox3), vpaned4, TRUE, TRUE, 0);
10155
10156   button21 = gtk_button_new_with_label ("button21");
10157   gtk_paned_pack1 (GTK_PANED (vpaned4), button21, FALSE, TRUE);
10158
10159   button20 = gtk_button_new_with_label ("button20");
10160   gtk_paned_pack2 (GTK_PANED (vpaned4), button20, TRUE, TRUE);
10161
10162   vpaned5 = gtk_vpaned_new ();
10163   gtk_box_pack_start (GTK_BOX (hbox3), vpaned5, TRUE, TRUE, 0);
10164
10165   button23 = gtk_button_new_with_label ("button23");
10166   gtk_paned_pack1 (GTK_PANED (vpaned5), button23, FALSE, TRUE);
10167
10168   button22 = gtk_button_new_with_label ("button22");
10169   gtk_paned_pack2 (GTK_PANED (vpaned5), button22, TRUE, TRUE);
10170
10171   vpaned6 = gtk_vpaned_new ();
10172   gtk_box_pack_start (GTK_BOX (hbox3), vpaned6, TRUE, TRUE, 0);
10173
10174   button25 = gtk_button_new_with_label ("button25");
10175   gtk_paned_pack1 (GTK_PANED (vpaned6), button25, FALSE, TRUE);
10176
10177   button24 = gtk_button_new_with_label ("button24");
10178   gtk_paned_pack2 (GTK_PANED (vpaned6), button24, TRUE, TRUE);
10179
10180   return window4;
10181 }
10182
10183 static void
10184 create_paned_keyboard_navigation (GtkWidget *widget)
10185 {
10186   static GtkWidget *window1 = NULL;
10187   static GtkWidget *window2 = NULL;
10188   static GtkWidget *window3 = NULL;
10189   static GtkWidget *window4 = NULL;
10190
10191   if (window1 && 
10192      (gtk_widget_get_screen (window1) != gtk_widget_get_screen (widget)))
10193     {
10194       gtk_widget_destroy (window1);
10195       gtk_widget_destroy (window2);
10196       gtk_widget_destroy (window3);
10197       gtk_widget_destroy (window4);
10198     }
10199   
10200   if (!window1)
10201     {
10202       window1 = paned_keyboard_window1 (widget);
10203       g_signal_connect (window1, "destroy",
10204                         G_CALLBACK (gtk_widget_destroyed),
10205                         &window1);
10206     }
10207
10208   if (!window2)
10209     {
10210       window2 = paned_keyboard_window2 (widget);
10211       g_signal_connect (window2, "destroy",
10212                         G_CALLBACK (gtk_widget_destroyed),
10213                         &window2);
10214     }
10215
10216   if (!window3)
10217     {
10218       window3 = paned_keyboard_window3 (widget);
10219       g_signal_connect (window3, "destroy",
10220                         G_CALLBACK (gtk_widget_destroyed),
10221                         &window3);
10222     }
10223
10224   if (!window4)
10225     {
10226       window4 = paned_keyboard_window4 (widget);
10227       g_signal_connect (window4, "destroy",
10228                         G_CALLBACK (gtk_widget_destroyed),
10229                         &window4);
10230     }
10231
10232   if (GTK_WIDGET_VISIBLE (window1))
10233     gtk_widget_destroy (GTK_WIDGET (window1));
10234   else
10235     gtk_widget_show_all (GTK_WIDGET (window1));
10236
10237   if (GTK_WIDGET_VISIBLE (window2))
10238     gtk_widget_destroy (GTK_WIDGET (window2));
10239   else
10240     gtk_widget_show_all (GTK_WIDGET (window2));
10241
10242   if (GTK_WIDGET_VISIBLE (window3))
10243     gtk_widget_destroy (GTK_WIDGET (window3));
10244   else
10245     gtk_widget_show_all (GTK_WIDGET (window3));
10246
10247   if (GTK_WIDGET_VISIBLE (window4))
10248     gtk_widget_destroy (GTK_WIDGET (window4));
10249   else
10250     gtk_widget_show_all (GTK_WIDGET (window4));
10251 }
10252
10253
10254 /*
10255  * Shaped Windows
10256  */
10257
10258 typedef struct _cursoroffset {gint x,y;} CursorOffset;
10259
10260 static void
10261 shape_pressed (GtkWidget *widget, GdkEventButton *event)
10262 {
10263   CursorOffset *p;
10264
10265   /* ignore double and triple click */
10266   if (event->type != GDK_BUTTON_PRESS)
10267     return;
10268
10269   p = g_object_get_data (G_OBJECT (widget), "cursor_offset");
10270   p->x = (int) event->x;
10271   p->y = (int) event->y;
10272
10273   gtk_grab_add (widget);
10274   gdk_pointer_grab (widget->window, TRUE,
10275                     GDK_BUTTON_RELEASE_MASK |
10276                     GDK_BUTTON_MOTION_MASK |
10277                     GDK_POINTER_MOTION_HINT_MASK,
10278                     NULL, NULL, 0);
10279 }
10280
10281 static void
10282 shape_released (GtkWidget *widget)
10283 {
10284   gtk_grab_remove (widget);
10285   gdk_display_pointer_ungrab (gtk_widget_get_display (widget),
10286                               GDK_CURRENT_TIME);
10287 }
10288
10289 static void
10290 shape_motion (GtkWidget      *widget, 
10291               GdkEventMotion *event)
10292 {
10293   gint xp, yp;
10294   CursorOffset * p;
10295   GdkModifierType mask;
10296
10297   p = g_object_get_data (G_OBJECT (widget), "cursor_offset");
10298
10299   /*
10300    * Can't use event->x / event->y here 
10301    * because I need absolute coordinates.
10302    */
10303   gdk_window_get_pointer (NULL, &xp, &yp, &mask);
10304   gtk_widget_set_uposition (widget, xp  - p->x, yp  - p->y);
10305 }
10306
10307 GtkWidget *
10308 shape_create_icon (GdkScreen *screen,
10309                    char      *xpm_file,
10310                    gint       x,
10311                    gint       y,
10312                    gint       px,
10313                    gint       py,
10314                    gint       window_type)
10315 {
10316   GtkWidget *window;
10317   GtkWidget *pixmap;
10318   GtkWidget *fixed;
10319   CursorOffset* icon_pos;
10320   GdkGC* gc;
10321   GdkBitmap *gdk_pixmap_mask;
10322   GdkPixmap *gdk_pixmap;
10323   GtkStyle *style;
10324
10325   style = gtk_widget_get_default_style ();
10326   gc = style->black_gc; 
10327
10328   /*
10329    * GDK_WINDOW_TOPLEVEL works also, giving you a title border
10330    */
10331   window = gtk_window_new (window_type);
10332   gtk_window_set_screen (GTK_WINDOW (window), screen);
10333   
10334   fixed = gtk_fixed_new ();
10335   gtk_widget_set_size_request (fixed, 100, 100);
10336   gtk_container_add (GTK_CONTAINER (window), fixed);
10337   gtk_widget_show (fixed);
10338   
10339   gtk_widget_set_events (window, 
10340                          gtk_widget_get_events (window) |
10341                          GDK_BUTTON_MOTION_MASK |
10342                          GDK_POINTER_MOTION_HINT_MASK |
10343                          GDK_BUTTON_PRESS_MASK);
10344
10345   gtk_widget_realize (window);
10346   gdk_pixmap = gdk_pixmap_create_from_xpm (window->window, &gdk_pixmap_mask, 
10347                                            &style->bg[GTK_STATE_NORMAL],
10348                                            xpm_file);
10349
10350   pixmap = gtk_image_new_from_pixmap (gdk_pixmap, gdk_pixmap_mask);
10351   gtk_fixed_put (GTK_FIXED (fixed), pixmap, px,py);
10352   gtk_widget_show (pixmap);
10353   
10354   gtk_widget_shape_combine_mask (window, gdk_pixmap_mask, px, py);
10355   
10356   g_object_unref (gdk_pixmap_mask);
10357   g_object_unref (gdk_pixmap);
10358
10359   g_signal_connect (window, "button_press_event",
10360                     G_CALLBACK (shape_pressed), NULL);
10361   g_signal_connect (window, "button_release_event",
10362                     G_CALLBACK (shape_released), NULL);
10363   g_signal_connect (window, "motion_notify_event",
10364                     G_CALLBACK (shape_motion), NULL);
10365
10366   icon_pos = g_new (CursorOffset, 1);
10367   g_object_set_data (G_OBJECT (window), "cursor_offset", icon_pos);
10368
10369   gtk_widget_set_uposition (window, x, y);
10370   gtk_widget_show (window);
10371   
10372   return window;
10373 }
10374
10375 void 
10376 create_shapes (GtkWidget *widget)
10377 {
10378   /* Variables used by the Drag/Drop and Shape Window demos */
10379   static GtkWidget *modeller = NULL;
10380   static GtkWidget *sheets = NULL;
10381   static GtkWidget *rings = NULL;
10382   static GtkWidget *with_region = NULL;
10383   GdkScreen *screen = gtk_widget_get_screen (widget);
10384   
10385   if (!(file_exists ("Modeller.xpm") &&
10386         file_exists ("FilesQueue.xpm") &&
10387         file_exists ("3DRings.xpm")))
10388     return;
10389   
10390
10391   if (!modeller)
10392     {
10393       modeller = shape_create_icon (screen, "Modeller.xpm",
10394                                     440, 140, 0,0, GTK_WINDOW_POPUP);
10395
10396       g_signal_connect (modeller, "destroy",
10397                         G_CALLBACK (gtk_widget_destroyed),
10398                         &modeller);
10399     }
10400   else
10401     gtk_widget_destroy (modeller);
10402
10403   if (!sheets)
10404     {
10405       sheets = shape_create_icon (screen, "FilesQueue.xpm",
10406                                   580, 170, 0,0, GTK_WINDOW_POPUP);
10407
10408       g_signal_connect (sheets, "destroy",
10409                         G_CALLBACK (gtk_widget_destroyed),
10410                         &sheets);
10411
10412     }
10413   else
10414     gtk_widget_destroy (sheets);
10415
10416   if (!rings)
10417     {
10418       rings = shape_create_icon (screen, "3DRings.xpm",
10419                                  460, 270, 25,25, GTK_WINDOW_TOPLEVEL);
10420
10421       g_signal_connect (rings, "destroy",
10422                         G_CALLBACK (gtk_widget_destroyed),
10423                         &rings);
10424     }
10425   else
10426     gtk_widget_destroy (rings);
10427
10428   if (!with_region)
10429     {
10430       GdkRegion *region;
10431       gint x, y;
10432       
10433       with_region = shape_create_icon (screen, "3DRings.xpm",
10434                                        460, 270, 25,25, GTK_WINDOW_TOPLEVEL);
10435
10436       gtk_window_set_decorated (GTK_WINDOW (with_region), FALSE);
10437       
10438       g_signal_connect (with_region, "destroy",
10439                         G_CALLBACK (gtk_widget_destroyed),
10440                         &with_region);
10441
10442       /* reset shape from mask to a region */
10443       x = 0;
10444       y = 0;
10445       region = gdk_region_new ();
10446
10447       while (x < 460)
10448         {
10449           while (y < 270)
10450             {
10451               GdkRectangle rect;
10452               rect.x = x;
10453               rect.y = y;
10454               rect.width = 10;
10455               rect.height = 10;
10456
10457               gdk_region_union_with_rect (region, &rect);
10458               
10459               y += 20;
10460             }
10461           y = 0;
10462           x += 20;
10463         }
10464
10465       gdk_window_shape_combine_region (with_region->window,
10466                                        region,
10467                                        0, 0);
10468     }
10469   else
10470     gtk_widget_destroy (with_region);
10471 }
10472
10473 /*
10474  * WM Hints demo
10475  */
10476
10477 void
10478 create_wmhints (GtkWidget *widget)
10479 {
10480   static GtkWidget *window = NULL;
10481   GtkWidget *label;
10482   GtkWidget *separator;
10483   GtkWidget *button;
10484   GtkWidget *box1;
10485   GtkWidget *box2;
10486
10487   GdkBitmap *circles;
10488
10489   if (!window)
10490     {
10491       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
10492
10493       gtk_window_set_screen (GTK_WINDOW (window),
10494                              gtk_widget_get_screen (widget));
10495       
10496       g_signal_connect (window, "destroy",
10497                         G_CALLBACK (gtk_widget_destroyed),
10498                         &window);
10499
10500       gtk_window_set_title (GTK_WINDOW (window), "WM Hints");
10501       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
10502
10503       gtk_widget_realize (window);
10504       
10505       circles = gdk_bitmap_create_from_data (window->window,
10506                                              (gchar *) circles_bits,
10507                                              circles_width,
10508                                              circles_height);
10509       gdk_window_set_icon (window->window, NULL,
10510                            circles, circles);
10511       
10512       gdk_window_set_icon_name (window->window, "WMHints Test Icon");
10513   
10514       gdk_window_set_decorations (window->window, GDK_DECOR_ALL | GDK_DECOR_MENU);
10515       gdk_window_set_functions (window->window, GDK_FUNC_ALL | GDK_FUNC_RESIZE);
10516       
10517       box1 = gtk_vbox_new (FALSE, 0);
10518       gtk_container_add (GTK_CONTAINER (window), box1);
10519       gtk_widget_show (box1);
10520
10521       label = gtk_label_new ("Try iconizing me!");
10522       gtk_widget_set_size_request (label, 150, 50);
10523       gtk_box_pack_start (GTK_BOX (box1), label, TRUE, TRUE, 0);
10524       gtk_widget_show (label);
10525
10526
10527       separator = gtk_hseparator_new ();
10528       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
10529       gtk_widget_show (separator);
10530
10531
10532       box2 = gtk_vbox_new (FALSE, 10);
10533       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
10534       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
10535       gtk_widget_show (box2);
10536
10537
10538       button = gtk_button_new_with_label ("close");
10539
10540       g_signal_connect_swapped (button, "clicked",
10541                                 G_CALLBACK (gtk_widget_destroy),
10542                                 window);
10543
10544       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
10545       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
10546       gtk_widget_grab_default (button);
10547       gtk_widget_show (button);
10548     }
10549
10550   if (!GTK_WIDGET_VISIBLE (window))
10551     gtk_widget_show (window);
10552   else
10553     gtk_widget_destroy (window);
10554 }
10555
10556
10557 /*
10558  * Window state tracking
10559  */
10560
10561 static gint
10562 window_state_callback (GtkWidget *widget,
10563                        GdkEventWindowState *event,
10564                        gpointer data)
10565 {
10566   GtkWidget *label = data;
10567   gchar *msg;
10568
10569   msg = g_strconcat (GTK_WINDOW (widget)->title, ": ",
10570                      (event->new_window_state & GDK_WINDOW_STATE_WITHDRAWN) ?
10571                      "withdrawn" : "not withdrawn", ", ",
10572                      (event->new_window_state & GDK_WINDOW_STATE_ICONIFIED) ?
10573                      "iconified" : "not iconified", ", ",
10574                      (event->new_window_state & GDK_WINDOW_STATE_STICKY) ?
10575                      "sticky" : "not sticky", ", ",
10576                      (event->new_window_state & GDK_WINDOW_STATE_MAXIMIZED) ?
10577                      "maximized" : "not maximized", ", ",
10578                      (event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN) ?
10579                      "fullscreen" : "not fullscreen",
10580                      (event->new_window_state & GDK_WINDOW_STATE_ABOVE) ?
10581                      "above" : "not above", ", ",
10582                      (event->new_window_state & GDK_WINDOW_STATE_BELOW) ?
10583                      "below" : "not below", ", ",
10584                      NULL);
10585   
10586   gtk_label_set_text (GTK_LABEL (label), msg);
10587
10588   g_free (msg);
10589
10590   return FALSE;
10591 }
10592
10593 static GtkWidget*
10594 tracking_label (GtkWidget *window)
10595 {
10596   GtkWidget *label;
10597   GtkWidget *hbox;
10598   GtkWidget *button;
10599
10600   hbox = gtk_hbox_new (FALSE, 5);
10601
10602   g_signal_connect_object (hbox,
10603                            "destroy",
10604                            G_CALLBACK (gtk_widget_destroy),
10605                            window,
10606                            G_CONNECT_SWAPPED);
10607   
10608   label = gtk_label_new ("<no window state events received>");
10609   gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
10610   gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
10611   
10612   g_signal_connect (window,
10613                     "window_state_event",
10614                     G_CALLBACK (window_state_callback),
10615                     label);
10616
10617   button = gtk_button_new_with_label ("Deiconify");
10618   g_signal_connect_object (button,
10619                            "clicked",
10620                            G_CALLBACK (gtk_window_deiconify),
10621                            window,
10622                            G_CONNECT_SWAPPED);
10623   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
10624
10625   button = gtk_button_new_with_label ("Iconify");
10626   g_signal_connect_object (button,
10627                            "clicked",
10628                            G_CALLBACK (gtk_window_iconify),
10629                            window,
10630                            G_CONNECT_SWAPPED);
10631   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
10632
10633   button = gtk_button_new_with_label ("Fullscreen");
10634   g_signal_connect_object (button,
10635                            "clicked",
10636                            G_CALLBACK (gtk_window_fullscreen),
10637                            window,
10638                            G_CONNECT_SWAPPED);
10639   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
10640
10641   button = gtk_button_new_with_label ("Unfullscreen");
10642   g_signal_connect_object (button,
10643                            "clicked",
10644                            G_CALLBACK (gtk_window_unfullscreen),
10645                            window,
10646                            G_CONNECT_SWAPPED);
10647   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
10648   
10649   button = gtk_button_new_with_label ("Present");
10650   g_signal_connect_object (button,
10651                            "clicked",
10652                            G_CALLBACK (gtk_window_present),
10653                            window,
10654                            G_CONNECT_SWAPPED);
10655   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
10656
10657   button = gtk_button_new_with_label ("Show");
10658   g_signal_connect_object (button,
10659                            "clicked",
10660                            G_CALLBACK (gtk_widget_show),
10661                            window,
10662                            G_CONNECT_SWAPPED);
10663   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
10664   
10665   gtk_widget_show_all (hbox);
10666   
10667   return hbox;
10668 }
10669
10670 void
10671 keep_window_above (GtkToggleButton *togglebutton, gpointer data)
10672 {
10673   GtkWidget *button = g_object_get_data (G_OBJECT (togglebutton), "radio");
10674
10675   gtk_window_set_keep_above (GTK_WINDOW (data),
10676                              gtk_toggle_button_get_active (togglebutton));
10677
10678   if (gtk_toggle_button_get_active (togglebutton))
10679     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE);
10680 }
10681
10682 void
10683 keep_window_below (GtkToggleButton *togglebutton, gpointer data)
10684 {
10685   GtkWidget *button = g_object_get_data (G_OBJECT (togglebutton), "radio");
10686
10687   gtk_window_set_keep_below (GTK_WINDOW (data),
10688                              gtk_toggle_button_get_active (togglebutton));
10689
10690   if (gtk_toggle_button_get_active (togglebutton))
10691     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE);
10692 }
10693
10694
10695 static GtkWidget*
10696 get_state_controls (GtkWidget *window)
10697 {
10698   GtkWidget *vbox;
10699   GtkWidget *button;
10700   GtkWidget *button_above;
10701   GtkWidget *button_below;
10702
10703   vbox = gtk_vbox_new (FALSE, 0);
10704   
10705   button = gtk_button_new_with_label ("Stick");
10706   g_signal_connect_object (button,
10707                            "clicked",
10708                            G_CALLBACK (gtk_window_stick),
10709                            window,
10710                            G_CONNECT_SWAPPED);
10711   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
10712
10713   button = gtk_button_new_with_label ("Unstick");
10714   g_signal_connect_object (button,
10715                            "clicked",
10716                            G_CALLBACK (gtk_window_unstick),
10717                            window,
10718                            G_CONNECT_SWAPPED);
10719   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
10720   
10721   button = gtk_button_new_with_label ("Maximize");
10722   g_signal_connect_object (button,
10723                            "clicked",
10724                            G_CALLBACK (gtk_window_maximize),
10725                            window,
10726                            G_CONNECT_SWAPPED);
10727   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
10728
10729   button = gtk_button_new_with_label ("Unmaximize");
10730   g_signal_connect_object (button,
10731                            "clicked",
10732                            G_CALLBACK (gtk_window_unmaximize),
10733                            window,
10734                            G_CONNECT_SWAPPED);
10735   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
10736
10737   button = gtk_button_new_with_label ("Iconify");
10738   g_signal_connect_object (button,
10739                            "clicked",
10740                            G_CALLBACK (gtk_window_iconify),
10741                            window,
10742                            G_CONNECT_SWAPPED);
10743   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
10744
10745   button = gtk_button_new_with_label ("Fullscreen");
10746   g_signal_connect_object (button,
10747                            "clicked",
10748                            G_CALLBACK (gtk_window_fullscreen),
10749                            window,
10750                            G_CONNECT_SWAPPED);
10751   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
10752
10753   button = gtk_button_new_with_label ("Unfullscreen");
10754   g_signal_connect_object (button,
10755                            "clicked",
10756                            G_CALLBACK (gtk_window_unfullscreen),
10757                            window,
10758                            G_CONNECT_SWAPPED);
10759   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
10760
10761   button_above = gtk_toggle_button_new_with_label ("Keep above");
10762   g_signal_connect (button_above,
10763                     "toggled",
10764                     G_CALLBACK (keep_window_above),
10765                     window);
10766   gtk_box_pack_start (GTK_BOX (vbox), button_above, FALSE, FALSE, 0);
10767
10768   button_below = gtk_toggle_button_new_with_label ("Keep below");
10769   g_signal_connect (button_below,
10770                     "toggled",
10771                     G_CALLBACK (keep_window_below),
10772                     window);
10773   gtk_box_pack_start (GTK_BOX (vbox), button_below, FALSE, FALSE, 0);
10774
10775   g_object_set_data (G_OBJECT (button_above), "radio", button_below);
10776   g_object_set_data (G_OBJECT (button_below), "radio", button_above);
10777
10778   button = gtk_button_new_with_label ("Hide (withdraw)");
10779   g_signal_connect_object (button,
10780                            "clicked",
10781                            G_CALLBACK (gtk_widget_hide),
10782                            window,
10783                            G_CONNECT_SWAPPED);
10784   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
10785   
10786   gtk_widget_show_all (vbox);
10787
10788   return vbox;
10789 }
10790
10791 void
10792 create_window_states (GtkWidget *widget)
10793 {
10794   static GtkWidget *window = NULL;
10795   GtkWidget *label;
10796   GtkWidget *box1;
10797   GtkWidget *iconified;
10798   GtkWidget *normal;
10799   GtkWidget *controls;
10800
10801   if (!window)
10802     {
10803       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
10804       gtk_window_set_screen (GTK_WINDOW (window),
10805                              gtk_widget_get_screen (widget));
10806
10807       g_signal_connect (window, "destroy",
10808                         G_CALLBACK (gtk_widget_destroyed),
10809                         &window);
10810
10811       gtk_window_set_title (GTK_WINDOW (window), "Window states");
10812       
10813       box1 = gtk_vbox_new (FALSE, 0);
10814       gtk_container_add (GTK_CONTAINER (window), box1);
10815
10816       iconified = gtk_window_new (GTK_WINDOW_TOPLEVEL);
10817
10818       gtk_window_set_screen (GTK_WINDOW (iconified),
10819                              gtk_widget_get_screen (widget));
10820       
10821       g_signal_connect_object (iconified, "destroy",
10822                                G_CALLBACK (gtk_widget_destroy),
10823                                window,
10824                                G_CONNECT_SWAPPED);
10825       gtk_window_iconify (GTK_WINDOW (iconified));
10826       gtk_window_set_title (GTK_WINDOW (iconified), "Iconified initially");
10827       controls = get_state_controls (iconified);
10828       gtk_container_add (GTK_CONTAINER (iconified), controls);
10829       
10830       normal = gtk_window_new (GTK_WINDOW_TOPLEVEL);
10831
10832       gtk_window_set_screen (GTK_WINDOW (normal),
10833                              gtk_widget_get_screen (widget));
10834       
10835       g_signal_connect_object (normal, "destroy",
10836                                G_CALLBACK (gtk_widget_destroy),
10837                                window,
10838                                G_CONNECT_SWAPPED);
10839       
10840       gtk_window_set_title (GTK_WINDOW (normal), "Deiconified initially");
10841       controls = get_state_controls (normal);
10842       gtk_container_add (GTK_CONTAINER (normal), controls);
10843       
10844       label = tracking_label (iconified);
10845       gtk_container_add (GTK_CONTAINER (box1), label);
10846
10847       label = tracking_label (normal);
10848       gtk_container_add (GTK_CONTAINER (box1), label);
10849
10850       gtk_widget_show_all (iconified);
10851       gtk_widget_show_all (normal);
10852       gtk_widget_show_all (box1);
10853     }
10854
10855   if (!GTK_WIDGET_VISIBLE (window))
10856     gtk_widget_show (window);
10857   else
10858     gtk_widget_destroy (window);
10859 }
10860
10861 /*
10862  * Window sizing
10863  */
10864
10865 static gint
10866 configure_event_callback (GtkWidget *widget,
10867                           GdkEventConfigure *event,
10868                           gpointer data)
10869 {
10870   GtkWidget *label = data;
10871   gchar *msg;
10872   gint x, y;
10873   
10874   gtk_window_get_position (GTK_WINDOW (widget), &x, &y);
10875   
10876   msg = g_strdup_printf ("event: %d,%d  %d x %d\n"
10877                          "position: %d, %d",
10878                          event->x, event->y, event->width, event->height,
10879                          x, y);
10880   
10881   gtk_label_set_text (GTK_LABEL (label), msg);
10882
10883   g_free (msg);
10884
10885   return FALSE;
10886 }
10887
10888 static void
10889 get_ints (GtkWidget *window,
10890           gint      *a,
10891           gint      *b)
10892 {
10893   GtkWidget *spin1;
10894   GtkWidget *spin2;
10895
10896   spin1 = g_object_get_data (G_OBJECT (window), "spin1");
10897   spin2 = g_object_get_data (G_OBJECT (window), "spin2");
10898
10899   *a = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (spin1));
10900   *b = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (spin2));
10901 }
10902
10903 static void
10904 set_size_callback (GtkWidget *widget,
10905                    gpointer   data)
10906 {
10907   gint w, h;
10908   
10909   get_ints (data, &w, &h);
10910
10911   gtk_window_resize (GTK_WINDOW (g_object_get_data (data, "target")), w, h);
10912 }
10913
10914 static void
10915 unset_default_size_callback (GtkWidget *widget,
10916                              gpointer   data)
10917 {
10918   gtk_window_set_default_size (g_object_get_data (data, "target"),
10919                                -1, -1);
10920 }
10921
10922 static void
10923 set_default_size_callback (GtkWidget *widget,
10924                            gpointer   data)
10925 {
10926   gint w, h;
10927   
10928   get_ints (data, &w, &h);
10929
10930   gtk_window_set_default_size (g_object_get_data (data, "target"),
10931                                w, h);
10932 }
10933
10934 static void
10935 unset_size_request_callback (GtkWidget *widget,
10936                              gpointer   data)
10937 {
10938   gtk_widget_set_size_request (g_object_get_data (data, "target"),
10939                                -1, -1);
10940 }
10941
10942 static void
10943 set_size_request_callback (GtkWidget *widget,
10944                            gpointer   data)
10945 {
10946   gint w, h;
10947   
10948   get_ints (data, &w, &h);
10949
10950   gtk_widget_set_size_request (g_object_get_data (data, "target"),
10951                                w, h);
10952 }
10953
10954 static void
10955 set_location_callback (GtkWidget *widget,
10956                        gpointer   data)
10957 {
10958   gint x, y;
10959   
10960   get_ints (data, &x, &y);
10961
10962   gtk_window_move (g_object_get_data (data, "target"), x, y);
10963 }
10964
10965 static void
10966 move_to_position_callback (GtkWidget *widget,
10967                            gpointer   data)
10968 {
10969   gint x, y;
10970   GtkWindow *window;
10971
10972   window = g_object_get_data (data, "target");
10973   
10974   gtk_window_get_position (window, &x, &y);
10975
10976   gtk_window_move (window, x, y);
10977 }
10978
10979 static void
10980 set_geometry_callback (GtkWidget *entry,
10981                        gpointer   data)
10982 {
10983   gchar *text;
10984   GtkWindow *target;
10985
10986   target = GTK_WINDOW (g_object_get_data (G_OBJECT (data), "target"));
10987   
10988   text = gtk_editable_get_chars (GTK_EDITABLE (entry), 0, -1);
10989
10990   if (!gtk_window_parse_geometry (target, text))
10991     g_print ("Bad geometry string '%s'\n", text);
10992
10993   g_free (text);
10994 }
10995
10996 static void
10997 allow_shrink_callback (GtkWidget *widget,
10998                        gpointer   data)
10999 {
11000   g_object_set (g_object_get_data (data, "target"),
11001                 "allow_shrink",
11002                 GTK_TOGGLE_BUTTON (widget)->active,
11003                 NULL);
11004 }
11005
11006 static void
11007 allow_grow_callback (GtkWidget *widget,
11008                      gpointer   data)
11009 {
11010   g_object_set (g_object_get_data (data, "target"),
11011                 "allow_grow",
11012                 GTK_TOGGLE_BUTTON (widget)->active,
11013                 NULL);
11014 }
11015
11016 static void
11017 gravity_selected (GtkWidget *widget,
11018                   gpointer   data)
11019 {
11020   gtk_window_set_gravity (GTK_WINDOW (g_object_get_data (data, "target")),
11021                           gtk_option_menu_get_history (GTK_OPTION_MENU (widget)) + GDK_GRAVITY_NORTH_WEST);
11022 }
11023
11024 static void
11025 pos_selected (GtkWidget *widget,
11026               gpointer   data)
11027 {
11028   gtk_window_set_position (GTK_WINDOW (g_object_get_data (data, "target")),
11029                            gtk_option_menu_get_history (GTK_OPTION_MENU (widget)) + GTK_WIN_POS_NONE);
11030 }
11031
11032 static void
11033 move_gravity_window_to_current_position (GtkWidget *widget,
11034                                          gpointer   data)
11035 {
11036   gint x, y;
11037   GtkWindow *window;
11038
11039   window = GTK_WINDOW (data);    
11040   
11041   gtk_window_get_position (window, &x, &y);
11042
11043   gtk_window_move (window, x, y);
11044 }
11045
11046 static void
11047 get_screen_corner (GtkWindow *window,
11048                    gint      *x,
11049                    gint      *y)
11050 {
11051   int w, h;
11052   GdkScreen * screen = gtk_window_get_screen (window);
11053   
11054   gtk_window_get_size (GTK_WINDOW (window), &w, &h);
11055
11056   switch (gtk_window_get_gravity (window))
11057     {
11058     case GDK_GRAVITY_SOUTH_EAST:
11059       *x = gdk_screen_get_width (screen) - w;
11060       *y = gdk_screen_get_height (screen) - h;
11061       break;
11062
11063     case GDK_GRAVITY_NORTH_EAST:
11064       *x = gdk_screen_get_width (screen) - w;
11065       *y = 0;
11066       break;
11067
11068     case GDK_GRAVITY_SOUTH_WEST:
11069       *x = 0;
11070       *y = gdk_screen_get_height (screen) - h;
11071       break;
11072
11073     case GDK_GRAVITY_NORTH_WEST:
11074       *x = 0;
11075       *y = 0;
11076       break;
11077       
11078     case GDK_GRAVITY_SOUTH:
11079       *x = (gdk_screen_get_width (screen) - w) / 2;
11080       *y = gdk_screen_get_height (screen) - h;
11081       break;
11082
11083     case GDK_GRAVITY_NORTH:
11084       *x = (gdk_screen_get_width (screen) - w) / 2;
11085       *y = 0;
11086       break;
11087
11088     case GDK_GRAVITY_WEST:
11089       *x = 0;
11090       *y = (gdk_screen_get_height (screen) - h) / 2;
11091       break;
11092
11093     case GDK_GRAVITY_EAST:
11094       *x = gdk_screen_get_width (screen) - w;
11095       *y = (gdk_screen_get_height (screen) - h) / 2;
11096       break;
11097
11098     case GDK_GRAVITY_CENTER:
11099       *x = (gdk_screen_get_width (screen) - w) / 2;
11100       *y = (gdk_screen_get_height (screen) - h) / 2;
11101       break;
11102
11103     case GDK_GRAVITY_STATIC:
11104       /* pick some random numbers */
11105       *x = 350;
11106       *y = 350;
11107       break;
11108
11109     default:
11110       g_assert_not_reached ();
11111       break;
11112     }
11113 }
11114
11115 static void
11116 move_gravity_window_to_starting_position (GtkWidget *widget,
11117                                           gpointer   data)
11118 {
11119   gint x, y;
11120   GtkWindow *window;
11121
11122   window = GTK_WINDOW (data);    
11123   
11124   get_screen_corner (window,
11125                      &x, &y);
11126   
11127   gtk_window_move (window, x, y);
11128 }
11129
11130 static GtkWidget*
11131 make_gravity_window (GtkWidget   *destroy_with,
11132                      GdkGravity   gravity,
11133                      const gchar *title)
11134 {
11135   GtkWidget *window;
11136   GtkWidget *button;
11137   GtkWidget *vbox;
11138   int x, y;
11139   
11140   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
11141
11142   gtk_window_set_screen (GTK_WINDOW (window),
11143                          gtk_widget_get_screen (destroy_with));
11144
11145   vbox = gtk_vbox_new (FALSE, 0);
11146   gtk_widget_show (vbox);
11147   
11148   gtk_container_add (GTK_CONTAINER (window), vbox);
11149   gtk_window_set_title (GTK_WINDOW (window), title);
11150   gtk_window_set_gravity (GTK_WINDOW (window), gravity);
11151
11152   g_signal_connect_object (destroy_with,
11153                            "destroy",
11154                            G_CALLBACK (gtk_widget_destroy),
11155                            window,
11156                            G_CONNECT_SWAPPED);
11157
11158   
11159   button = gtk_button_new_with_mnemonic ("_Move to current position");
11160
11161   g_signal_connect (button, "clicked",
11162                     G_CALLBACK (move_gravity_window_to_current_position),
11163                     window);
11164
11165   gtk_container_add (GTK_CONTAINER (vbox), button);
11166   gtk_widget_show (button);
11167
11168   button = gtk_button_new_with_mnemonic ("Move to _starting position");
11169
11170   g_signal_connect (button, "clicked",
11171                     G_CALLBACK (move_gravity_window_to_starting_position),
11172                     window);
11173
11174   gtk_container_add (GTK_CONTAINER (vbox), button);
11175   gtk_widget_show (button);
11176   
11177   /* Pretend this is the result of --geometry.
11178    * DO NOT COPY THIS CODE unless you are setting --geometry results,
11179    * and in that case you probably should just use gtk_window_parse_geometry().
11180    * AGAIN, DO NOT SET GDK_HINT_USER_POS! It violates the ICCCM unless
11181    * you are parsing --geometry or equivalent.
11182    */
11183   gtk_window_set_geometry_hints (GTK_WINDOW (window),
11184                                  NULL, NULL,
11185                                  GDK_HINT_USER_POS);
11186
11187   gtk_window_set_default_size (GTK_WINDOW (window),
11188                                200, 200);
11189
11190   get_screen_corner (GTK_WINDOW (window), &x, &y);
11191   
11192   gtk_window_move (GTK_WINDOW (window),
11193                    x, y);
11194   
11195   return window;
11196 }
11197
11198 static void
11199 do_gravity_test (GtkWidget *widget,
11200                  gpointer   data)
11201 {
11202   GtkWidget *destroy_with = data;
11203   GtkWidget *window;
11204   
11205   /* We put a window at each gravity point on the screen. */
11206   window = make_gravity_window (destroy_with, GDK_GRAVITY_NORTH_WEST,
11207                                 "NorthWest");
11208   gtk_widget_show (window);
11209   
11210   window = make_gravity_window (destroy_with, GDK_GRAVITY_SOUTH_EAST,
11211                                 "SouthEast");
11212   gtk_widget_show (window);
11213
11214   window = make_gravity_window (destroy_with, GDK_GRAVITY_NORTH_EAST,
11215                                 "NorthEast");
11216   gtk_widget_show (window);
11217
11218   window = make_gravity_window (destroy_with, GDK_GRAVITY_SOUTH_WEST,
11219                                 "SouthWest");
11220   gtk_widget_show (window);
11221
11222   window = make_gravity_window (destroy_with, GDK_GRAVITY_SOUTH,
11223                                 "South");
11224   gtk_widget_show (window);
11225
11226   window = make_gravity_window (destroy_with, GDK_GRAVITY_NORTH,
11227                                 "North");
11228   gtk_widget_show (window);
11229
11230   
11231   window = make_gravity_window (destroy_with, GDK_GRAVITY_WEST,
11232                                 "West");
11233   gtk_widget_show (window);
11234
11235     
11236   window = make_gravity_window (destroy_with, GDK_GRAVITY_EAST,
11237                                 "East");
11238   gtk_widget_show (window);
11239
11240   window = make_gravity_window (destroy_with, GDK_GRAVITY_CENTER,
11241                                 "Center");
11242   gtk_widget_show (window);
11243
11244   window = make_gravity_window (destroy_with, GDK_GRAVITY_STATIC,
11245                                 "Static");
11246   gtk_widget_show (window);
11247 }
11248
11249 static GtkWidget*
11250 window_controls (GtkWidget *window)
11251 {
11252   GtkWidget *control_window;
11253   GtkWidget *label;
11254   GtkWidget *vbox;
11255   GtkWidget *button;
11256   GtkWidget *spin;
11257   GtkAdjustment *adj;
11258   GtkWidget *entry;
11259   GtkWidget *om;
11260   GtkWidget *menu;
11261   gint i;
11262   
11263   control_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
11264
11265   gtk_window_set_screen (GTK_WINDOW (control_window),
11266                          gtk_widget_get_screen (window));
11267
11268   gtk_window_set_title (GTK_WINDOW (control_window), "Size controls");
11269   
11270   g_object_set_data (G_OBJECT (control_window),
11271                      "target",
11272                      window);
11273   
11274   g_signal_connect_object (control_window,
11275                            "destroy",
11276                            G_CALLBACK (gtk_widget_destroy),
11277                            window,
11278                            G_CONNECT_SWAPPED);
11279
11280   vbox = gtk_vbox_new (FALSE, 5);
11281   
11282   gtk_container_add (GTK_CONTAINER (control_window), vbox);
11283   
11284   label = gtk_label_new ("<no configure events>");
11285   gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
11286   
11287   g_signal_connect (window,
11288                     "configure_event",
11289                     G_CALLBACK (configure_event_callback),
11290                     label);
11291
11292   adj = (GtkAdjustment *) gtk_adjustment_new (10.0, -2000.0, 2000.0, 1.0,
11293                                               5.0, 0.0);
11294   spin = gtk_spin_button_new (adj, 0, 0);
11295
11296   gtk_box_pack_start (GTK_BOX (vbox), spin, FALSE, FALSE, 0);
11297
11298   g_object_set_data (G_OBJECT (control_window), "spin1", spin);
11299
11300   adj = (GtkAdjustment *) gtk_adjustment_new (10.0, -2000.0, 2000.0, 1.0,
11301                                               5.0, 0.0);
11302   spin = gtk_spin_button_new (adj, 0, 0);
11303
11304   gtk_box_pack_start (GTK_BOX (vbox), spin, FALSE, FALSE, 0);
11305
11306   g_object_set_data (G_OBJECT (control_window), "spin2", spin);
11307
11308   entry = gtk_entry_new ();
11309   gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
11310
11311   g_signal_connect (entry, "changed",
11312                     G_CALLBACK (set_geometry_callback),
11313                     control_window);
11314
11315   button = gtk_button_new_with_label ("Show gravity test windows");
11316   g_signal_connect_swapped (button,
11317                             "clicked",
11318                             G_CALLBACK (do_gravity_test),
11319                             control_window);
11320   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
11321
11322   button = gtk_button_new_with_label ("Reshow with initial size");
11323   g_signal_connect_object (button,
11324                            "clicked",
11325                            G_CALLBACK (gtk_window_reshow_with_initial_size),
11326                            window,
11327                            G_CONNECT_SWAPPED);
11328   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
11329   
11330   button = gtk_button_new_with_label ("Queue resize");
11331   g_signal_connect_object (button,
11332                            "clicked",
11333                            G_CALLBACK (gtk_widget_queue_resize),
11334                            window,
11335                            G_CONNECT_SWAPPED);
11336   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
11337   
11338   button = gtk_button_new_with_label ("Resize");
11339   g_signal_connect (button,
11340                     "clicked",
11341                     G_CALLBACK (set_size_callback),
11342                     control_window);
11343   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
11344
11345   button = gtk_button_new_with_label ("Set default size");
11346   g_signal_connect (button,
11347                     "clicked",
11348                     G_CALLBACK (set_default_size_callback),
11349                     control_window);
11350   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
11351
11352   button = gtk_button_new_with_label ("Unset default size");
11353   g_signal_connect (button,
11354                     "clicked",
11355                     G_CALLBACK (unset_default_size_callback),
11356                     control_window);
11357   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
11358   
11359   button = gtk_button_new_with_label ("Set size request");
11360   g_signal_connect (button,
11361                     "clicked",
11362                     G_CALLBACK (set_size_request_callback),
11363                     control_window);
11364   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
11365
11366   button = gtk_button_new_with_label ("Unset size request");
11367   g_signal_connect (button,
11368                     "clicked",
11369                     G_CALLBACK (unset_size_request_callback),
11370                     control_window);
11371   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
11372   
11373   button = gtk_button_new_with_label ("Move");
11374   g_signal_connect (button,
11375                     "clicked",
11376                     G_CALLBACK (set_location_callback),
11377                     control_window);
11378   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
11379
11380   button = gtk_button_new_with_label ("Move to current position");
11381   g_signal_connect (button,
11382                     "clicked",
11383                     G_CALLBACK (move_to_position_callback),
11384                     control_window);
11385   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
11386   
11387   button = gtk_check_button_new_with_label ("Allow shrink");
11388   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE);
11389   g_signal_connect (button,
11390                     "toggled",
11391                     G_CALLBACK (allow_shrink_callback),
11392                     control_window);
11393   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
11394
11395   button = gtk_check_button_new_with_label ("Allow grow");
11396   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
11397   g_signal_connect (button,
11398                     "toggled",
11399                     G_CALLBACK (allow_grow_callback),
11400                     control_window);
11401   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
11402   
11403   button = gtk_button_new_with_mnemonic ("_Show");
11404   g_signal_connect_object (button,
11405                            "clicked",
11406                            G_CALLBACK (gtk_widget_show),
11407                            window,
11408                            G_CONNECT_SWAPPED);
11409   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
11410
11411   button = gtk_button_new_with_mnemonic ("_Hide");
11412   g_signal_connect_object (button,
11413                            "clicked",
11414                            G_CALLBACK (gtk_widget_hide),
11415                            window,
11416                            G_CONNECT_SWAPPED);
11417   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
11418   
11419   menu = gtk_menu_new ();
11420   
11421   i = 0;
11422   while (i < 10)
11423     {
11424       GtkWidget *mi;
11425       static gchar *names[] = {
11426         "GDK_GRAVITY_NORTH_WEST",
11427         "GDK_GRAVITY_NORTH",
11428         "GDK_GRAVITY_NORTH_EAST",
11429         "GDK_GRAVITY_WEST",
11430         "GDK_GRAVITY_CENTER",
11431         "GDK_GRAVITY_EAST",
11432         "GDK_GRAVITY_SOUTH_WEST",
11433         "GDK_GRAVITY_SOUTH",
11434         "GDK_GRAVITY_SOUTH_EAST",
11435         "GDK_GRAVITY_STATIC",
11436         NULL
11437       };
11438
11439       g_assert (names[i]);
11440       
11441       mi = gtk_menu_item_new_with_label (names[i]);
11442
11443       gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
11444
11445       ++i;
11446     }
11447   
11448   gtk_widget_show_all (menu);
11449   
11450   om = gtk_option_menu_new ();
11451   gtk_option_menu_set_menu (GTK_OPTION_MENU (om), menu);
11452   
11453
11454   g_signal_connect (om,
11455                     "changed",
11456                     G_CALLBACK (gravity_selected),
11457                     control_window);
11458
11459   gtk_box_pack_end (GTK_BOX (vbox), om, FALSE, FALSE, 0);
11460
11461
11462   menu = gtk_menu_new ();
11463   
11464   i = 0;
11465   while (i < 5)
11466     {
11467       GtkWidget *mi;
11468       static gchar *names[] = {
11469         "GTK_WIN_POS_NONE",
11470         "GTK_WIN_POS_CENTER",
11471         "GTK_WIN_POS_MOUSE",
11472         "GTK_WIN_POS_CENTER_ALWAYS",
11473         "GTK_WIN_POS_CENTER_ON_PARENT",
11474         NULL
11475       };
11476
11477       g_assert (names[i]);
11478       
11479       mi = gtk_menu_item_new_with_label (names[i]);
11480
11481       gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
11482
11483       ++i;
11484     }
11485   
11486   gtk_widget_show_all (menu);
11487   
11488   om = gtk_option_menu_new ();
11489   gtk_option_menu_set_menu (GTK_OPTION_MENU (om), menu);
11490   
11491
11492   g_signal_connect (om,
11493                     "changed",
11494                     G_CALLBACK (pos_selected),
11495                     control_window);
11496
11497   gtk_box_pack_end (GTK_BOX (vbox), om, FALSE, FALSE, 0);
11498   
11499   gtk_widget_show_all (vbox);
11500   
11501   return control_window;
11502 }
11503
11504 void
11505 create_window_sizing (GtkWidget *widget)
11506 {
11507   static GtkWidget *window = NULL;
11508   static GtkWidget *target_window = NULL;
11509
11510   if (!target_window)
11511     {
11512       GtkWidget *label;
11513       
11514       target_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
11515       gtk_window_set_screen (GTK_WINDOW (target_window),
11516                              gtk_widget_get_screen (widget));
11517       label = gtk_label_new (NULL);
11518       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");
11519       gtk_container_add (GTK_CONTAINER (target_window), label);
11520       gtk_widget_show (label);
11521       
11522       g_signal_connect (target_window, "destroy",
11523                         G_CALLBACK (gtk_widget_destroyed),
11524                         &target_window);
11525
11526       window = window_controls (target_window);
11527       
11528       g_signal_connect (window, "destroy",
11529                         G_CALLBACK (gtk_widget_destroyed),
11530                         &window);
11531       
11532       gtk_window_set_title (GTK_WINDOW (target_window), "Window to size");
11533     }
11534
11535   /* don't show target window by default, we want to allow testing
11536    * of behavior on first show.
11537    */
11538   
11539   if (!GTK_WIDGET_VISIBLE (window))
11540     gtk_widget_show (window);
11541   else
11542     gtk_widget_destroy (window);
11543 }
11544
11545 /*
11546  * GtkProgressBar
11547  */
11548
11549 typedef struct _ProgressData {
11550   GtkWidget *window;
11551   GtkWidget *pbar;
11552   GtkWidget *block_spin;
11553   GtkWidget *x_align_spin;
11554   GtkWidget *y_align_spin;
11555   GtkWidget *step_spin;
11556   GtkWidget *act_blocks_spin;
11557   GtkWidget *label;
11558   GtkWidget *omenu1;
11559   GtkWidget *elmenu;
11560   GtkWidget *omenu2;
11561   GtkWidget *entry;
11562   int timer;
11563 } ProgressData;
11564
11565 gint
11566 progress_timeout (gpointer data)
11567 {
11568   gdouble new_val;
11569   GtkAdjustment *adj;
11570
11571   adj = GTK_PROGRESS (data)->adjustment;
11572
11573   new_val = adj->value + 1;
11574   if (new_val > adj->upper)
11575     new_val = adj->lower;
11576
11577   gtk_progress_set_value (GTK_PROGRESS (data), new_val);
11578
11579   return TRUE;
11580 }
11581
11582 static void
11583 destroy_progress (GtkWidget     *widget,
11584                   ProgressData **pdata)
11585 {
11586   gtk_timeout_remove ((*pdata)->timer);
11587   (*pdata)->timer = 0;
11588   (*pdata)->window = NULL;
11589   g_free (*pdata);
11590   *pdata = NULL;
11591 }
11592
11593 static void
11594 progressbar_toggle_orientation (GtkWidget *widget, gpointer data)
11595 {
11596   ProgressData *pdata;
11597   gint i;
11598
11599   pdata = (ProgressData *) data;
11600
11601   if (!GTK_WIDGET_MAPPED (widget))
11602     return;
11603
11604   i = gtk_option_menu_get_history (GTK_OPTION_MENU (widget));
11605
11606   gtk_progress_bar_set_orientation (GTK_PROGRESS_BAR (pdata->pbar),
11607                                     (GtkProgressBarOrientation) i);
11608 }
11609
11610 static void
11611 toggle_show_text (GtkWidget *widget, ProgressData *pdata)
11612 {
11613   gtk_progress_set_show_text (GTK_PROGRESS (pdata->pbar),
11614                               GTK_TOGGLE_BUTTON (widget)->active);
11615   gtk_widget_set_sensitive (pdata->entry, GTK_TOGGLE_BUTTON (widget)->active);
11616   gtk_widget_set_sensitive (pdata->x_align_spin,
11617                             GTK_TOGGLE_BUTTON (widget)->active);
11618   gtk_widget_set_sensitive (pdata->y_align_spin,
11619                             GTK_TOGGLE_BUTTON (widget)->active);
11620 }
11621
11622 static void
11623 progressbar_toggle_ellipsize (GtkWidget *widget,
11624                               gpointer   data)
11625 {
11626   ProgressData *pdata = data;
11627   if (GTK_WIDGET_DRAWABLE (widget))
11628     {
11629       gint i = gtk_option_menu_get_history (GTK_OPTION_MENU (widget));
11630       gtk_progress_bar_set_ellipsize (GTK_PROGRESS_BAR (pdata->pbar), i);
11631     }
11632 }
11633
11634 static void
11635 progressbar_toggle_bar_style (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   if (i == 1)
11648     gtk_widget_set_sensitive (pdata->block_spin, TRUE);
11649   else
11650     gtk_widget_set_sensitive (pdata->block_spin, FALSE);
11651   
11652   gtk_progress_bar_set_bar_style (GTK_PROGRESS_BAR (pdata->pbar),
11653                                   (GtkProgressBarStyle) i);
11654 }
11655
11656 static void
11657 progress_value_changed (GtkAdjustment *adj, ProgressData *pdata)
11658 {
11659   char buf[20];
11660
11661   if (GTK_PROGRESS (pdata->pbar)->activity_mode)
11662     sprintf (buf, "???");
11663   else
11664     sprintf (buf, "%.0f%%", 100 *
11665              gtk_progress_get_current_percentage (GTK_PROGRESS (pdata->pbar)));
11666   gtk_label_set_text (GTK_LABEL (pdata->label), buf);
11667 }
11668
11669 static void
11670 adjust_blocks (GtkAdjustment *adj, ProgressData *pdata)
11671 {
11672   gtk_progress_set_percentage (GTK_PROGRESS (pdata->pbar), 0);
11673   gtk_progress_bar_set_discrete_blocks (GTK_PROGRESS_BAR (pdata->pbar),
11674      gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (pdata->block_spin)));
11675 }
11676
11677 static void
11678 adjust_step (GtkAdjustment *adj, ProgressData *pdata)
11679 {
11680   gtk_progress_bar_set_activity_step (GTK_PROGRESS_BAR (pdata->pbar),
11681      gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (pdata->step_spin)));
11682 }
11683
11684 static void
11685 adjust_act_blocks (GtkAdjustment *adj, ProgressData *pdata)
11686 {
11687   gtk_progress_bar_set_activity_blocks (GTK_PROGRESS_BAR (pdata->pbar),
11688                gtk_spin_button_get_value_as_int 
11689                       (GTK_SPIN_BUTTON (pdata->act_blocks_spin)));
11690 }
11691
11692 static void
11693 adjust_align (GtkAdjustment *adj, ProgressData *pdata)
11694 {
11695   gtk_progress_set_text_alignment (GTK_PROGRESS (pdata->pbar),
11696          gtk_spin_button_get_value (GTK_SPIN_BUTTON (pdata->x_align_spin)),
11697          gtk_spin_button_get_value (GTK_SPIN_BUTTON (pdata->y_align_spin)));
11698 }
11699
11700 static void
11701 toggle_activity_mode (GtkWidget *widget, ProgressData *pdata)
11702 {
11703   gtk_progress_set_activity_mode (GTK_PROGRESS (pdata->pbar),
11704                                   GTK_TOGGLE_BUTTON (widget)->active);
11705   gtk_widget_set_sensitive (pdata->step_spin, 
11706                             GTK_TOGGLE_BUTTON (widget)->active);
11707   gtk_widget_set_sensitive (pdata->act_blocks_spin, 
11708                             GTK_TOGGLE_BUTTON (widget)->active);
11709 }
11710
11711 static void
11712 entry_changed (GtkWidget *widget, ProgressData *pdata)
11713 {
11714   gtk_progress_set_format_string (GTK_PROGRESS (pdata->pbar),
11715                           gtk_entry_get_text (GTK_ENTRY (pdata->entry)));
11716 }
11717
11718 void
11719 create_progress_bar (GtkWidget *widget)
11720 {
11721   GtkWidget *button;
11722   GtkWidget *vbox;
11723   GtkWidget *vbox2;
11724   GtkWidget *hbox;
11725   GtkWidget *check;
11726   GtkWidget *frame;
11727   GtkWidget *tab;
11728   GtkWidget *label;
11729   GtkWidget *align;
11730   GtkAdjustment *adj;
11731   static ProgressData *pdata = NULL;
11732
11733   static gchar *items1[] =
11734   {
11735     "Left-Right",
11736     "Right-Left",
11737     "Bottom-Top",
11738     "Top-Bottom"
11739   };
11740
11741   static gchar *items2[] =
11742   {
11743     "Continuous",
11744     "Discrete"
11745   };
11746
11747   static char *ellipsize_items[] = {
11748     "None",     // PANGO_ELLIPSIZE_NONE,
11749     "Start",    // PANGO_ELLIPSIZE_START,
11750     "Middle",   // PANGO_ELLIPSIZE_MIDDLE,
11751     "End",      // PANGO_ELLIPSIZE_END
11752   };
11753   
11754   if (!pdata)
11755     pdata = g_new0 (ProgressData, 1);
11756
11757   if (!pdata->window)
11758     {
11759       pdata->window = gtk_dialog_new ();
11760
11761       gtk_window_set_screen (GTK_WINDOW (pdata->window),
11762                              gtk_widget_get_screen (widget));
11763
11764       gtk_window_set_resizable (GTK_WINDOW (pdata->window), TRUE);
11765
11766       g_signal_connect (pdata->window, "destroy",
11767                         G_CALLBACK (destroy_progress),
11768                         &pdata);
11769
11770       pdata->timer = 0;
11771
11772       gtk_window_set_title (GTK_WINDOW (pdata->window), "GtkProgressBar");
11773       gtk_container_set_border_width (GTK_CONTAINER (pdata->window), 0);
11774
11775       vbox = gtk_vbox_new (FALSE, 5);
11776       gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
11777       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (pdata->window)->vbox), 
11778                           vbox, FALSE, TRUE, 0);
11779
11780       frame = gtk_frame_new ("Progress");
11781       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
11782
11783       vbox2 = gtk_vbox_new (FALSE, 5);
11784       gtk_container_add (GTK_CONTAINER (frame), vbox2);
11785
11786       align = gtk_alignment_new (0.5, 0.5, 0, 0);
11787       gtk_box_pack_start (GTK_BOX (vbox2), align, FALSE, FALSE, 5);
11788
11789       adj = (GtkAdjustment *) gtk_adjustment_new (0, 1, 300, 0, 0, 0);
11790       g_signal_connect (adj, "value_changed",
11791                         G_CALLBACK (progress_value_changed), pdata);
11792
11793       pdata->pbar = g_object_new (GTK_TYPE_PROGRESS_BAR,
11794                                     "adjustment", adj,
11795                                     "ellipsize", PANGO_ELLIPSIZE_MIDDLE,
11796                                     NULL);
11797       gtk_progress_set_format_string (GTK_PROGRESS (pdata->pbar),
11798                                       "%v from [%l,%u] (=%p%%)");
11799       gtk_container_add (GTK_CONTAINER (align), pdata->pbar);
11800       pdata->timer = gtk_timeout_add (100, progress_timeout, pdata->pbar);
11801
11802       align = gtk_alignment_new (0.5, 0.5, 0, 0);
11803       gtk_box_pack_start (GTK_BOX (vbox2), align, FALSE, FALSE, 5);
11804
11805       hbox = gtk_hbox_new (FALSE, 5);
11806       gtk_container_add (GTK_CONTAINER (align), hbox);
11807       label = gtk_label_new ("Label updated by user :"); 
11808       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
11809       pdata->label = gtk_label_new ("");
11810       gtk_box_pack_start (GTK_BOX (hbox), pdata->label, FALSE, TRUE, 0);
11811
11812       frame = gtk_frame_new ("Options");
11813       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
11814
11815       vbox2 = gtk_vbox_new (FALSE, 5);
11816       gtk_container_add (GTK_CONTAINER (frame), vbox2);
11817
11818       tab = gtk_table_new (7, 2, FALSE);
11819       gtk_box_pack_start (GTK_BOX (vbox2), tab, FALSE, TRUE, 0);
11820
11821       label = gtk_label_new ("Orientation :");
11822       gtk_table_attach (GTK_TABLE (tab), label, 0, 1, 0, 1,
11823                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
11824                         5, 5);
11825       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
11826
11827       pdata->omenu1 = build_option_menu (items1, 4, 0,
11828                                          progressbar_toggle_orientation,
11829                                          pdata);
11830       hbox = gtk_hbox_new (FALSE, 0);
11831       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 0, 1,
11832                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
11833                         5, 5);
11834       gtk_box_pack_start (GTK_BOX (hbox), pdata->omenu1, TRUE, TRUE, 0);
11835       
11836       check = gtk_check_button_new_with_label ("Show text");
11837       g_signal_connect (check, "clicked",
11838                         G_CALLBACK (toggle_show_text),
11839                         pdata);
11840       gtk_table_attach (GTK_TABLE (tab), check, 0, 1, 1, 2,
11841                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
11842                         5, 5);
11843
11844       hbox = gtk_hbox_new (FALSE, 0);
11845       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 1, 2,
11846                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
11847                         5, 5);
11848
11849       label = gtk_label_new ("Format : ");
11850       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
11851
11852       pdata->entry = gtk_entry_new ();
11853       g_signal_connect (pdata->entry, "changed",
11854                         G_CALLBACK (entry_changed),
11855                         pdata);
11856       gtk_box_pack_start (GTK_BOX (hbox), pdata->entry, TRUE, TRUE, 0);
11857       gtk_entry_set_text (GTK_ENTRY (pdata->entry), "%v from [%l,%u] (=%p%%)");
11858       gtk_widget_set_size_request (pdata->entry, 100, -1);
11859       gtk_widget_set_sensitive (pdata->entry, FALSE);
11860
11861       label = gtk_label_new ("Text align :");
11862       gtk_table_attach (GTK_TABLE (tab), label, 0, 1, 2, 3,
11863                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
11864                         5, 5);
11865       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
11866
11867       hbox = gtk_hbox_new (FALSE, 0);
11868       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 2, 3,
11869                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
11870                         5, 5);
11871
11872       label = gtk_label_new ("x :");
11873       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 5);
11874       
11875       adj = (GtkAdjustment *) gtk_adjustment_new (0.5, 0, 1, 0.1, 0.1, 0);
11876       pdata->x_align_spin = gtk_spin_button_new (adj, 0, 1);
11877       g_signal_connect (adj, "value_changed",
11878                         G_CALLBACK (adjust_align), pdata);
11879       gtk_box_pack_start (GTK_BOX (hbox), pdata->x_align_spin, FALSE, TRUE, 0);
11880       gtk_widget_set_sensitive (pdata->x_align_spin, FALSE);
11881
11882       label = gtk_label_new ("y :");
11883       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 5);
11884
11885       adj = (GtkAdjustment *) gtk_adjustment_new (0.5, 0, 1, 0.1, 0.1, 0);
11886       pdata->y_align_spin = gtk_spin_button_new (adj, 0, 1);
11887       g_signal_connect (adj, "value_changed",
11888                         G_CALLBACK (adjust_align), pdata);
11889       gtk_box_pack_start (GTK_BOX (hbox), pdata->y_align_spin, FALSE, TRUE, 0);
11890       gtk_widget_set_sensitive (pdata->y_align_spin, FALSE);
11891
11892       label = gtk_label_new ("Ellipsize text :");
11893       gtk_table_attach (GTK_TABLE (tab), label, 0, 1, 10, 11,
11894                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
11895                         5, 5);
11896       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
11897       pdata->elmenu = build_option_menu (ellipsize_items,
11898                                          sizeof (ellipsize_items) / sizeof (ellipsize_items[0]),
11899                                          2, // PANGO_ELLIPSIZE_MIDDLE
11900                                          progressbar_toggle_ellipsize,
11901                                          pdata);
11902       hbox = gtk_hbox_new (FALSE, 0);
11903       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 10, 11,
11904                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
11905                         5, 5);
11906       gtk_box_pack_start (GTK_BOX (hbox), pdata->elmenu, TRUE, TRUE, 0);
11907
11908       label = gtk_label_new ("Bar Style :");
11909       gtk_table_attach (GTK_TABLE (tab), label, 0, 1, 13, 14,
11910                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
11911                         5, 5);
11912       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
11913
11914       pdata->omenu2 = build_option_menu (items2, 2, 0,
11915                                          progressbar_toggle_bar_style,
11916                                          pdata);
11917       hbox = gtk_hbox_new (FALSE, 0);
11918       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 13, 14,
11919                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
11920                         5, 5);
11921       gtk_box_pack_start (GTK_BOX (hbox), pdata->omenu2, TRUE, TRUE, 0);
11922
11923       label = gtk_label_new ("Block count :");
11924       gtk_table_attach (GTK_TABLE (tab), label, 0, 1, 14, 15,
11925                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
11926                         5, 5);
11927       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
11928
11929       hbox = gtk_hbox_new (FALSE, 0);
11930       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 14, 15,
11931                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
11932                         5, 5);
11933       adj = (GtkAdjustment *) gtk_adjustment_new (10, 2, 20, 1, 5, 0);
11934       pdata->block_spin = gtk_spin_button_new (adj, 0, 0);
11935       g_signal_connect (adj, "value_changed",
11936                         G_CALLBACK (adjust_blocks), pdata);
11937       gtk_box_pack_start (GTK_BOX (hbox), pdata->block_spin, FALSE, TRUE, 0);
11938       gtk_widget_set_sensitive (pdata->block_spin, FALSE);
11939
11940       check = gtk_check_button_new_with_label ("Activity mode");
11941       g_signal_connect (check, "clicked",
11942                         G_CALLBACK (toggle_activity_mode), pdata);
11943       gtk_table_attach (GTK_TABLE (tab), check, 0, 1, 15, 16,
11944                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
11945                         5, 5);
11946
11947       hbox = gtk_hbox_new (FALSE, 0);
11948       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 15, 16,
11949                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
11950                         5, 5);
11951       label = gtk_label_new ("Step size : ");
11952       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
11953       adj = (GtkAdjustment *) gtk_adjustment_new (3, 1, 20, 1, 5, 0);
11954       pdata->step_spin = gtk_spin_button_new (adj, 0, 0);
11955       g_signal_connect (adj, "value_changed",
11956                         G_CALLBACK (adjust_step), pdata);
11957       gtk_box_pack_start (GTK_BOX (hbox), pdata->step_spin, FALSE, TRUE, 0);
11958       gtk_widget_set_sensitive (pdata->step_spin, FALSE);
11959
11960       hbox = gtk_hbox_new (FALSE, 0);
11961       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 16, 17,
11962                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
11963                         5, 5);
11964       label = gtk_label_new ("Blocks :     ");
11965       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
11966       adj = (GtkAdjustment *) gtk_adjustment_new (5, 2, 10, 1, 5, 0);
11967       pdata->act_blocks_spin = gtk_spin_button_new (adj, 0, 0);
11968       g_signal_connect (adj, "value_changed",
11969                         G_CALLBACK (adjust_act_blocks), pdata);
11970       gtk_box_pack_start (GTK_BOX (hbox), pdata->act_blocks_spin, FALSE, TRUE,
11971                           0);
11972       gtk_widget_set_sensitive (pdata->act_blocks_spin, FALSE);
11973
11974       button = gtk_button_new_with_label ("close");
11975       g_signal_connect_swapped (button, "clicked",
11976                                 G_CALLBACK (gtk_widget_destroy),
11977                                 pdata->window);
11978       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
11979       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (pdata->window)->action_area), 
11980                           button, TRUE, TRUE, 0);
11981       gtk_widget_grab_default (button);
11982     }
11983
11984   if (!GTK_WIDGET_VISIBLE (pdata->window))
11985     gtk_widget_show_all (pdata->window);
11986   else
11987     gtk_widget_destroy (pdata->window);
11988 }
11989
11990 /*
11991  * Properties
11992  */
11993
11994 typedef struct {
11995   int x;
11996   int y;
11997   gboolean found;
11998   gboolean first;
11999   GtkWidget *res_widget;
12000 } FindWidgetData;
12001
12002 static void
12003 find_widget (GtkWidget *widget, FindWidgetData *data)
12004 {
12005   GtkAllocation new_allocation;
12006   gint x_offset = 0;
12007   gint y_offset = 0;
12008
12009   new_allocation = widget->allocation;
12010
12011   if (data->found || !GTK_WIDGET_MAPPED (widget))
12012     return;
12013
12014   /* Note that in the following code, we only count the
12015    * position as being inside a WINDOW widget if it is inside
12016    * widget->window; points that are outside of widget->window
12017    * but within the allocation are not counted. This is consistent
12018    * with the way we highlight drag targets.
12019    */
12020   if (!GTK_WIDGET_NO_WINDOW (widget))
12021     {
12022       new_allocation.x = 0;
12023       new_allocation.y = 0;
12024     }
12025   
12026   if (widget->parent && !data->first)
12027     {
12028       GdkWindow *window = widget->window;
12029       while (window != widget->parent->window)
12030         {
12031           gint tx, ty, twidth, theight;
12032           gdk_drawable_get_size (window, &twidth, &theight);
12033
12034           if (new_allocation.x < 0)
12035             {
12036               new_allocation.width += new_allocation.x;
12037               new_allocation.x = 0;
12038             }
12039           if (new_allocation.y < 0)
12040             {
12041               new_allocation.height += new_allocation.y;
12042               new_allocation.y = 0;
12043             }
12044           if (new_allocation.x + new_allocation.width > twidth)
12045             new_allocation.width = twidth - new_allocation.x;
12046           if (new_allocation.y + new_allocation.height > theight)
12047             new_allocation.height = theight - new_allocation.y;
12048
12049           gdk_window_get_position (window, &tx, &ty);
12050           new_allocation.x += tx;
12051           x_offset += tx;
12052           new_allocation.y += ty;
12053           y_offset += ty;
12054           
12055           window = gdk_window_get_parent (window);
12056         }
12057     }
12058
12059   if ((data->x >= new_allocation.x) && (data->y >= new_allocation.y) &&
12060       (data->x < new_allocation.x + new_allocation.width) && 
12061       (data->y < new_allocation.y + new_allocation.height))
12062     {
12063       /* First, check if the drag is in a valid drop site in
12064        * one of our children 
12065        */
12066       if (GTK_IS_CONTAINER (widget))
12067         {
12068           FindWidgetData new_data = *data;
12069           
12070           new_data.x -= x_offset;
12071           new_data.y -= y_offset;
12072           new_data.found = FALSE;
12073           new_data.first = FALSE;
12074           
12075           gtk_container_forall (GTK_CONTAINER (widget),
12076                                 (GtkCallback)find_widget,
12077                                 &new_data);
12078           
12079           data->found = new_data.found;
12080           if (data->found)
12081             data->res_widget = new_data.res_widget;
12082         }
12083
12084       /* If not, and this widget is registered as a drop site, check to
12085        * emit "drag_motion" to check if we are actually in
12086        * a drop site.
12087        */
12088       if (!data->found)
12089         {
12090           data->found = TRUE;
12091           data->res_widget = widget;
12092         }
12093     }
12094 }
12095
12096 static GtkWidget *
12097 find_widget_at_pointer (GdkDisplay *display)
12098 {
12099   GtkWidget *widget = NULL;
12100   GdkWindow *pointer_window;
12101   gint x, y;
12102   FindWidgetData data;
12103  
12104  pointer_window = gdk_display_get_window_at_pointer (display, NULL, NULL);
12105  
12106  if (pointer_window)
12107    {
12108      gpointer widget_ptr;
12109
12110      gdk_window_get_user_data (pointer_window, &widget_ptr);
12111      widget = widget_ptr;
12112    }
12113
12114  if (widget)
12115    {
12116      gdk_window_get_pointer (widget->window,
12117                              &x, &y, NULL);
12118      
12119      data.x = x;
12120      data.y = y;
12121      data.found = FALSE;
12122      data.first = TRUE;
12123
12124      find_widget (widget, &data);
12125      if (data.found)
12126        return data.res_widget;
12127      return widget;
12128    }
12129  return NULL;
12130 }
12131
12132 struct PropertiesData {
12133   GtkWidget **window;
12134   GdkCursor *cursor;
12135   gboolean in_query;
12136   gint handler;
12137 };
12138
12139 static void
12140 destroy_properties (GtkWidget             *widget,
12141                     struct PropertiesData *data)
12142 {
12143   if (data->window)
12144     {
12145       *data->window = NULL;
12146       data->window = NULL;
12147     }
12148
12149   if (data->cursor)
12150     {
12151       gdk_cursor_unref (data->cursor);
12152       data->cursor = NULL;
12153     }
12154
12155   if (data->handler)
12156     {
12157       g_signal_handler_disconnect (widget, data->handler);
12158       data->handler = 0;
12159     }
12160
12161   g_free (data);
12162 }
12163
12164 static gint
12165 property_query_event (GtkWidget        *widget,
12166                       GdkEvent         *event,
12167                       struct PropertiesData *data)
12168 {
12169   GtkWidget *res_widget = NULL;
12170
12171   if (!data->in_query)
12172     return FALSE;
12173   
12174   if (event->type == GDK_BUTTON_RELEASE)
12175     {
12176       gtk_grab_remove (widget);
12177       gdk_display_pointer_ungrab (gtk_widget_get_display (widget),
12178                                   GDK_CURRENT_TIME);
12179       
12180       res_widget = find_widget_at_pointer (gtk_widget_get_display (widget));
12181       if (res_widget)
12182         {
12183           g_object_set_data (G_OBJECT (res_widget), "prop-editor-screen",
12184                              gtk_widget_get_screen (widget));
12185           create_prop_editor (G_OBJECT (res_widget), 0);
12186         }
12187
12188       data->in_query = FALSE;
12189     }
12190   return FALSE;
12191 }
12192
12193
12194 static void
12195 query_properties (GtkButton *button,
12196                   struct PropertiesData *data)
12197 {
12198   gint failure;
12199
12200   g_signal_connect (button, "event",
12201                     G_CALLBACK (property_query_event), data);
12202
12203
12204   if (!data->cursor)
12205     data->cursor = gdk_cursor_new_for_display (gtk_widget_get_display (GTK_WIDGET (button)),
12206                                                GDK_TARGET);
12207   
12208   failure = gdk_pointer_grab (GTK_WIDGET (button)->window,
12209                               TRUE,
12210                               GDK_BUTTON_RELEASE_MASK,
12211                               NULL,
12212                               data->cursor,
12213                               GDK_CURRENT_TIME);
12214
12215   gtk_grab_add (GTK_WIDGET (button));
12216
12217   data->in_query = TRUE;
12218 }
12219
12220 static void
12221 create_properties (GtkWidget *widget)
12222 {
12223   static GtkWidget *window = NULL;
12224   GtkWidget *button;
12225   GtkWidget *vbox;
12226   GtkWidget *label;
12227   struct PropertiesData *data;
12228
12229   data = g_new (struct PropertiesData, 1);
12230   data->window = &window;
12231   data->in_query = FALSE;
12232   data->cursor = NULL;
12233   data->handler = 0;
12234
12235   if (!window)
12236     {
12237       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
12238
12239       gtk_window_set_screen (GTK_WINDOW (window),
12240                              gtk_widget_get_screen (widget));      
12241
12242       data->handler = g_signal_connect (window, "destroy",
12243                                         G_CALLBACK (destroy_properties),
12244                                         data);
12245
12246       gtk_window_set_title (GTK_WINDOW (window), "test properties");
12247       gtk_container_set_border_width (GTK_CONTAINER (window), 10);
12248
12249       vbox = gtk_vbox_new (FALSE, 1);
12250       gtk_container_add (GTK_CONTAINER (window), vbox);
12251             
12252       label = gtk_label_new ("This is just a dumb test to test properties.\nIf you need a generic module, get GLE.");
12253       gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
12254       
12255       button = gtk_button_new_with_label ("Query properties");
12256       gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
12257       g_signal_connect (button, "clicked",
12258                         G_CALLBACK (query_properties),
12259                         data);
12260     }
12261
12262   if (!GTK_WIDGET_VISIBLE (window))
12263     gtk_widget_show_all (window);
12264   else
12265     gtk_widget_destroy (window);
12266   
12267 }
12268
12269 struct SnapshotData {
12270   GtkWidget *toplevel_button;
12271   GtkWidget **window;
12272   GdkCursor *cursor;
12273   gboolean in_query;
12274   gboolean is_toplevel;
12275   gint handler;
12276 };
12277
12278 static void
12279 destroy_snapshot_data (GtkWidget             *widget,
12280                        struct SnapshotData *data)
12281 {
12282   if (*data->window)
12283     *data->window = NULL;
12284   
12285   if (data->cursor)
12286     {
12287       gdk_cursor_unref (data->cursor);
12288       data->cursor = NULL;
12289     }
12290
12291   if (data->handler)
12292     {
12293       g_signal_handler_disconnect (widget, data->handler);
12294       data->handler = 0;
12295     }
12296
12297   g_free (data);
12298 }
12299
12300 static gint
12301 snapshot_widget_event (GtkWidget               *widget,
12302                        GdkEvent        *event,
12303                        struct SnapshotData *data)
12304 {
12305   GtkWidget *res_widget = NULL;
12306
12307   if (!data->in_query)
12308     return FALSE;
12309   
12310   if (event->type == GDK_BUTTON_RELEASE)
12311     {
12312       gtk_grab_remove (widget);
12313       gdk_display_pointer_ungrab (gtk_widget_get_display (widget),
12314                                   GDK_CURRENT_TIME);
12315       
12316       res_widget = find_widget_at_pointer (gtk_widget_get_display (widget));
12317       if (data->is_toplevel && res_widget)
12318         res_widget = gtk_widget_get_toplevel (res_widget);
12319       if (res_widget)
12320         {
12321           GdkPixmap *pixmap;
12322           GtkWidget *window, *image;
12323
12324           window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
12325           pixmap = gtk_widget_get_snapshot (res_widget, NULL);
12326           gtk_widget_realize (window);
12327           if (gdk_drawable_get_depth (window->window) != gdk_drawable_get_depth (pixmap))
12328             {
12329               /* this branch is needed to convert ARGB -> RGB */
12330               int width, height;
12331               GdkPixbuf *pixbuf;
12332               gdk_drawable_get_size (pixmap, &width, &height);
12333               pixbuf = gdk_pixbuf_get_from_drawable (NULL, pixmap,
12334                                                      gtk_widget_get_colormap (res_widget),
12335                                                      0, 0,
12336                                                      0, 0,
12337                                                      width, height);
12338               image = gtk_image_new_from_pixbuf (pixbuf);
12339               g_object_unref (pixbuf);
12340             }
12341           else
12342             image = gtk_image_new_from_pixmap (pixmap, NULL);
12343           gtk_container_add (GTK_CONTAINER (window), image);
12344           g_object_unref (pixmap);
12345           gtk_widget_show_all (window);
12346         }
12347
12348       data->in_query = FALSE;
12349     }
12350   return FALSE;
12351 }
12352
12353
12354 static void
12355 snapshot_widget (GtkButton *button,
12356                  struct SnapshotData *data)
12357 {
12358   gint failure;
12359
12360   g_signal_connect (button, "event",
12361                     G_CALLBACK (snapshot_widget_event), data);
12362
12363   data->is_toplevel = GTK_WIDGET (button) == data->toplevel_button;
12364   
12365   if (!data->cursor)
12366     data->cursor = gdk_cursor_new_for_display (gtk_widget_get_display (GTK_WIDGET (button)),
12367                                                GDK_TARGET);
12368   
12369   failure = gdk_pointer_grab (GTK_WIDGET (button)->window,
12370                               TRUE,
12371                               GDK_BUTTON_RELEASE_MASK,
12372                               NULL,
12373                               data->cursor,
12374                               GDK_CURRENT_TIME);
12375
12376   gtk_grab_add (GTK_WIDGET (button));
12377
12378   data->in_query = TRUE;
12379 }
12380
12381 static void
12382 create_snapshot (GtkWidget *widget)
12383 {
12384   static GtkWidget *window = NULL;
12385   GtkWidget *button;
12386   GtkWidget *vbox;
12387   struct SnapshotData *data;
12388
12389   data = g_new (struct SnapshotData, 1);
12390   data->window = &window;
12391   data->in_query = FALSE;
12392   data->cursor = NULL;
12393   data->handler = 0;
12394
12395   if (!window)
12396     {
12397       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
12398
12399       gtk_window_set_screen (GTK_WINDOW (window),
12400                              gtk_widget_get_screen (widget));      
12401
12402       data->handler = g_signal_connect (window, "destroy",
12403                                         G_CALLBACK (destroy_snapshot_data),
12404                                         data);
12405
12406       gtk_window_set_title (GTK_WINDOW (window), "test snapshot");
12407       gtk_container_set_border_width (GTK_CONTAINER (window), 10);
12408
12409       vbox = gtk_vbox_new (FALSE, 1);
12410       gtk_container_add (GTK_CONTAINER (window), vbox);
12411             
12412       button = gtk_button_new_with_label ("Snapshot widget");
12413       gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
12414       g_signal_connect (button, "clicked",
12415                         G_CALLBACK (snapshot_widget),
12416                         data);
12417       
12418       button = gtk_button_new_with_label ("Snapshot toplevel");
12419       data->toplevel_button = button;
12420       gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
12421       g_signal_connect (button, "clicked",
12422                         G_CALLBACK (snapshot_widget),
12423                         data);
12424     }
12425
12426   if (!GTK_WIDGET_VISIBLE (window))
12427     gtk_widget_show_all (window);
12428   else
12429     gtk_widget_destroy (window);
12430   
12431 }
12432
12433
12434
12435 /*
12436  * Color Preview
12437  */
12438
12439 static int color_idle = 0;
12440
12441 gint
12442 color_idle_func (GtkWidget *preview)
12443 {
12444   static int count = 1;
12445   guchar buf[768];
12446   int i, j, k;
12447
12448   for (i = 0; i < 256; i++)
12449     {
12450       for (j = 0, k = 0; j < 256; j++)
12451         {
12452           buf[k+0] = i + count;
12453           buf[k+1] = 0;
12454           buf[k+2] = j + count;
12455           k += 3;
12456         }
12457
12458       gtk_preview_draw_row (GTK_PREVIEW (preview), buf, 0, i, 256);
12459     }
12460
12461   count += 1;
12462
12463   gtk_widget_queue_draw (preview);
12464   gdk_window_process_updates (preview->window, TRUE);
12465
12466   return TRUE;
12467 }
12468
12469 static void
12470 color_preview_destroy (GtkWidget  *widget,
12471                        GtkWidget **window)
12472 {
12473   gtk_idle_remove (color_idle);
12474   color_idle = 0;
12475
12476   *window = NULL;
12477 }
12478
12479 void
12480 create_color_preview (GtkWidget *widget)
12481 {
12482   static GtkWidget *window = NULL;
12483   GtkWidget *preview;
12484   guchar buf[768];
12485   int i, j, k;
12486
12487   if (!window)
12488     {
12489       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
12490       
12491       gtk_window_set_screen (GTK_WINDOW (window),
12492                              gtk_widget_get_screen (widget));
12493
12494       g_signal_connect (window, "destroy",
12495                         G_CALLBACK (color_preview_destroy),
12496                         &window);
12497
12498       gtk_window_set_title (GTK_WINDOW (window), "test");
12499       gtk_container_set_border_width (GTK_CONTAINER (window), 10);
12500
12501       preview = gtk_preview_new (GTK_PREVIEW_COLOR);
12502       gtk_preview_size (GTK_PREVIEW (preview), 256, 256);
12503       gtk_container_add (GTK_CONTAINER (window), preview);
12504
12505       for (i = 0; i < 256; i++)
12506         {
12507           for (j = 0, k = 0; j < 256; j++)
12508             {
12509               buf[k+0] = i;
12510               buf[k+1] = 0;
12511               buf[k+2] = j;
12512               k += 3;
12513             }
12514
12515           gtk_preview_draw_row (GTK_PREVIEW (preview), buf, 0, i, 256);
12516         }
12517
12518       color_idle = gtk_idle_add ((GtkFunction) color_idle_func, preview);
12519     }
12520
12521   if (!GTK_WIDGET_VISIBLE (window))
12522     gtk_widget_show_all (window);
12523   else
12524     gtk_widget_destroy (window);
12525 }
12526
12527 /*
12528  * Gray Preview
12529  */
12530
12531 static int gray_idle = 0;
12532
12533 gint
12534 gray_idle_func (GtkWidget *preview)
12535 {
12536   static int count = 1;
12537   guchar buf[256];
12538   int i, j;
12539
12540   for (i = 0; i < 256; i++)
12541     {
12542       for (j = 0; j < 256; j++)
12543         buf[j] = i + j + count;
12544
12545       gtk_preview_draw_row (GTK_PREVIEW (preview), buf, 0, i, 256);
12546     }
12547
12548   count += 1;
12549
12550   gtk_widget_draw (preview, NULL);
12551
12552   return TRUE;
12553 }
12554
12555 static void
12556 gray_preview_destroy (GtkWidget  *widget,
12557                       GtkWidget **window)
12558 {
12559   gtk_idle_remove (gray_idle);
12560   gray_idle = 0;
12561
12562   *window = NULL;
12563 }
12564
12565 void
12566 create_gray_preview (GtkWidget *widget)
12567 {
12568   static GtkWidget *window = NULL;
12569   GtkWidget *preview;
12570   guchar buf[256];
12571   int i, j;
12572
12573   if (!window)
12574     {
12575       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
12576
12577       gtk_window_set_screen (GTK_WINDOW (window),
12578                              gtk_widget_get_screen (widget));
12579
12580       g_signal_connect (window, "destroy",
12581                         G_CALLBACK (gray_preview_destroy),
12582                         &window);
12583
12584       gtk_window_set_title (GTK_WINDOW (window), "test");
12585       gtk_container_set_border_width (GTK_CONTAINER (window), 10);
12586
12587       preview = gtk_preview_new (GTK_PREVIEW_GRAYSCALE);
12588       gtk_preview_size (GTK_PREVIEW (preview), 256, 256);
12589       gtk_container_add (GTK_CONTAINER (window), preview);
12590
12591       for (i = 0; i < 256; i++)
12592         {
12593           for (j = 0; j < 256; j++)
12594             buf[j] = i + j;
12595
12596           gtk_preview_draw_row (GTK_PREVIEW (preview), buf, 0, i, 256);
12597         }
12598
12599       gray_idle = gtk_idle_add ((GtkFunction) gray_idle_func, preview);
12600     }
12601
12602   if (!GTK_WIDGET_VISIBLE (window))
12603     gtk_widget_show_all (window);
12604   else
12605     gtk_widget_destroy (window);
12606 }
12607
12608
12609 /*
12610  * Selection Test
12611  */
12612
12613 void
12614 selection_test_received (GtkWidget *list, GtkSelectionData *data)
12615 {
12616   GdkAtom *atoms;
12617   GtkWidget *list_item;
12618   GList *item_list;
12619   int i, l;
12620
12621   if (data->length < 0)
12622     {
12623       g_print ("Selection retrieval failed\n");
12624       return;
12625     }
12626   if (data->type != GDK_SELECTION_TYPE_ATOM)
12627     {
12628       g_print ("Selection \"TARGETS\" was not returned as atoms!\n");
12629       return;
12630     }
12631
12632   /* Clear out any current list items */
12633
12634   gtk_list_clear_items (GTK_LIST(list), 0, -1);
12635
12636   /* Add new items to list */
12637
12638   atoms = (GdkAtom *)data->data;
12639
12640   item_list = NULL;
12641   l = data->length / sizeof (GdkAtom);
12642   for (i = 0; i < l; i++)
12643     {
12644       char *name;
12645       name = gdk_atom_name (atoms[i]);
12646       if (name != NULL)
12647         {
12648           list_item = gtk_list_item_new_with_label (name);
12649           g_free (name);
12650         }
12651       else
12652         list_item = gtk_list_item_new_with_label ("(bad atom)");
12653
12654       gtk_widget_show (list_item);
12655       item_list = g_list_append (item_list, list_item);
12656     }
12657
12658   gtk_list_append_items (GTK_LIST (list), item_list);
12659
12660   return;
12661 }
12662
12663 void
12664 selection_test_get_targets (GtkWidget *widget, GtkWidget *list)
12665 {
12666   static GdkAtom targets_atom = GDK_NONE;
12667
12668   if (targets_atom == GDK_NONE)
12669     targets_atom = gdk_atom_intern ("TARGETS", FALSE);
12670
12671   gtk_selection_convert (list, GDK_SELECTION_PRIMARY, targets_atom,
12672                          GDK_CURRENT_TIME);
12673 }
12674
12675 void
12676 create_selection_test (GtkWidget *widget)
12677 {
12678   static GtkWidget *window = NULL;
12679   GtkWidget *button;
12680   GtkWidget *vbox;
12681   GtkWidget *scrolled_win;
12682   GtkWidget *list;
12683   GtkWidget *label;
12684
12685   if (!window)
12686     {
12687       window = gtk_dialog_new ();
12688       
12689       gtk_window_set_screen (GTK_WINDOW (window),
12690                              gtk_widget_get_screen (widget));
12691
12692       g_signal_connect (window, "destroy",
12693                         G_CALLBACK (gtk_widget_destroyed),
12694                         &window);
12695
12696       gtk_window_set_title (GTK_WINDOW (window), "Selection Test");
12697       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
12698
12699       /* Create the list */
12700
12701       vbox = gtk_vbox_new (FALSE, 5);
12702       gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
12703       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), vbox,
12704                           TRUE, TRUE, 0);
12705
12706       label = gtk_label_new ("Gets available targets for current selection");
12707       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
12708
12709       scrolled_win = gtk_scrolled_window_new (NULL, NULL);
12710       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
12711                                       GTK_POLICY_AUTOMATIC, 
12712                                       GTK_POLICY_AUTOMATIC);
12713       gtk_box_pack_start (GTK_BOX (vbox), scrolled_win, TRUE, TRUE, 0);
12714       gtk_widget_set_size_request (scrolled_win, 100, 200);
12715
12716       list = gtk_list_new ();
12717       gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_win), list);
12718
12719       g_signal_connect (list, "selection_received",
12720                         G_CALLBACK (selection_test_received), NULL);
12721
12722       /* .. And create some buttons */
12723       button = gtk_button_new_with_label ("Get Targets");
12724       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area),
12725                           button, TRUE, TRUE, 0);
12726
12727       g_signal_connect (button, "clicked",
12728                         G_CALLBACK (selection_test_get_targets), list);
12729
12730       button = gtk_button_new_with_label ("Quit");
12731       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area),
12732                           button, TRUE, TRUE, 0);
12733
12734       g_signal_connect_swapped (button, "clicked",
12735                                 G_CALLBACK (gtk_widget_destroy),
12736                                 window);
12737     }
12738
12739   if (!GTK_WIDGET_VISIBLE (window))
12740     gtk_widget_show_all (window);
12741   else
12742     gtk_widget_destroy (window);
12743 }
12744
12745 /*
12746  * Gamma Curve
12747  */
12748
12749 void
12750 create_gamma_curve (GtkWidget *widget)
12751 {
12752   static GtkWidget *window = NULL, *curve;
12753   static int count = 0;
12754   gfloat vec[256];
12755   gint max;
12756   gint i;
12757   
12758   if (!window)
12759     {
12760       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
12761       gtk_window_set_screen (GTK_WINDOW (window),
12762                              gtk_widget_get_screen (widget));
12763
12764       gtk_window_set_title (GTK_WINDOW (window), "test");
12765       gtk_container_set_border_width (GTK_CONTAINER (window), 10);
12766
12767       g_signal_connect (window, "destroy",
12768                         G_CALLBACK(gtk_widget_destroyed),
12769                         &window);
12770
12771       curve = gtk_gamma_curve_new ();
12772       gtk_container_add (GTK_CONTAINER (window), curve);
12773       gtk_widget_show (curve);
12774     }
12775
12776   max = 127 + (count % 2)*128;
12777   gtk_curve_set_range (GTK_CURVE (GTK_GAMMA_CURVE (curve)->curve),
12778                        0, max, 0, max);
12779   for (i = 0; i < max; ++i)
12780     vec[i] = (127 / sqrt (max)) * sqrt (i);
12781   gtk_curve_set_vector (GTK_CURVE (GTK_GAMMA_CURVE (curve)->curve),
12782                         max, vec);
12783
12784   if (!GTK_WIDGET_VISIBLE (window))
12785     gtk_widget_show (window);
12786   else if (count % 4 == 3)
12787     {
12788       gtk_widget_destroy (window);
12789       window = NULL;
12790     }
12791
12792   ++count;
12793 }
12794
12795 /*
12796  * Test scrolling
12797  */
12798
12799 static int scroll_test_pos = 0.0;
12800
12801 static gint
12802 scroll_test_expose (GtkWidget *widget, GdkEventExpose *event,
12803                     GtkAdjustment *adj)
12804 {
12805   gint i,j;
12806   gint imin, imax, jmin, jmax;
12807   
12808   imin = (event->area.x) / 10;
12809   imax = (event->area.x + event->area.width + 9) / 10;
12810
12811   jmin = ((int)adj->value + event->area.y) / 10;
12812   jmax = ((int)adj->value + event->area.y + event->area.height + 9) / 10;
12813
12814   gdk_window_clear_area (widget->window,
12815                          event->area.x, event->area.y,
12816                          event->area.width, event->area.height);
12817
12818   for (i=imin; i<imax; i++)
12819     for (j=jmin; j<jmax; j++)
12820       if ((i+j) % 2)
12821         gdk_draw_rectangle (widget->window, 
12822                             widget->style->black_gc,
12823                             TRUE,
12824                             10*i, 10*j - (int)adj->value, 1+i%10, 1+j%10);
12825
12826   return TRUE;
12827 }
12828
12829 static gint
12830 scroll_test_scroll (GtkWidget *widget, GdkEventScroll *event,
12831                     GtkAdjustment *adj)
12832 {
12833   gdouble new_value = adj->value + ((event->direction == GDK_SCROLL_UP) ?
12834                                     -adj->page_increment / 2:
12835                                     adj->page_increment / 2);
12836   new_value = CLAMP (new_value, adj->lower, adj->upper - adj->page_size);
12837   gtk_adjustment_set_value (adj, new_value);  
12838   
12839   return TRUE;
12840 }
12841
12842 static void
12843 scroll_test_configure (GtkWidget *widget, GdkEventConfigure *event,
12844                        GtkAdjustment *adj)
12845 {
12846   adj->page_increment = 0.9 * widget->allocation.height;
12847   adj->page_size = widget->allocation.height;
12848
12849   g_signal_emit_by_name (adj, "changed");
12850 }
12851
12852 static void
12853 scroll_test_adjustment_changed (GtkAdjustment *adj, GtkWidget *widget)
12854 {
12855   /* gint source_min = (int)adj->value - scroll_test_pos; */
12856   gint dy;
12857
12858   dy = scroll_test_pos - (int)adj->value;
12859   scroll_test_pos = adj->value;
12860
12861   if (!GTK_WIDGET_DRAWABLE (widget))
12862     return;
12863   gdk_window_scroll (widget->window, 0, dy);
12864   gdk_window_process_updates (widget->window, FALSE);
12865 }
12866
12867
12868 void
12869 create_scroll_test (GtkWidget *widget)
12870 {
12871   static GtkWidget *window = NULL;
12872   GtkWidget *hbox;
12873   GtkWidget *drawing_area;
12874   GtkWidget *scrollbar;
12875   GtkWidget *button;
12876   GtkAdjustment *adj;
12877   GdkGeometry geometry;
12878   GdkWindowHints geometry_mask;
12879
12880   if (!window)
12881     {
12882       window = gtk_dialog_new ();
12883
12884       gtk_window_set_screen (GTK_WINDOW (window),
12885                              gtk_widget_get_screen (widget));
12886
12887       g_signal_connect (window, "destroy",
12888                         G_CALLBACK (gtk_widget_destroyed),
12889                         &window);
12890
12891       gtk_window_set_title (GTK_WINDOW (window), "Scroll Test");
12892       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
12893
12894       hbox = gtk_hbox_new (FALSE, 0);
12895       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), hbox,
12896                           TRUE, TRUE, 0);
12897       gtk_widget_show (hbox);
12898
12899       drawing_area = gtk_drawing_area_new ();
12900       gtk_widget_set_size_request (drawing_area, 200, 200);
12901       gtk_box_pack_start (GTK_BOX (hbox), drawing_area, TRUE, TRUE, 0);
12902       gtk_widget_show (drawing_area);
12903
12904       gtk_widget_set_events (drawing_area, GDK_EXPOSURE_MASK | GDK_SCROLL_MASK);
12905
12906       adj = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 1000.0, 1.0, 180.0, 200.0));
12907       scroll_test_pos = 0.0;
12908
12909       scrollbar = gtk_vscrollbar_new (adj);
12910       gtk_box_pack_start (GTK_BOX (hbox), scrollbar, FALSE, FALSE, 0);
12911       gtk_widget_show (scrollbar);
12912
12913       g_signal_connect (drawing_area, "expose_event",
12914                         G_CALLBACK (scroll_test_expose), adj);
12915       g_signal_connect (drawing_area, "configure_event",
12916                         G_CALLBACK (scroll_test_configure), adj);
12917       g_signal_connect (drawing_area, "scroll_event",
12918                         G_CALLBACK (scroll_test_scroll), adj);
12919       
12920       g_signal_connect (adj, "value_changed",
12921                         G_CALLBACK (scroll_test_adjustment_changed),
12922                         drawing_area);
12923       
12924       /* .. And create some buttons */
12925
12926       button = gtk_button_new_with_label ("Quit");
12927       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area),
12928                           button, TRUE, TRUE, 0);
12929
12930       g_signal_connect_swapped (button, "clicked",
12931                                 G_CALLBACK (gtk_widget_destroy),
12932                                 window);
12933       gtk_widget_show (button);
12934
12935       /* Set up gridded geometry */
12936
12937       geometry_mask = GDK_HINT_MIN_SIZE | 
12938                        GDK_HINT_BASE_SIZE | 
12939                        GDK_HINT_RESIZE_INC;
12940
12941       geometry.min_width = 20;
12942       geometry.min_height = 20;
12943       geometry.base_width = 0;
12944       geometry.base_height = 0;
12945       geometry.width_inc = 10;
12946       geometry.height_inc = 10;
12947       
12948       gtk_window_set_geometry_hints (GTK_WINDOW (window),
12949                                drawing_area, &geometry, geometry_mask);
12950     }
12951
12952   if (!GTK_WIDGET_VISIBLE (window))
12953     gtk_widget_show (window);
12954   else
12955     gtk_widget_destroy (window);
12956 }
12957
12958 /*
12959  * Timeout Test
12960  */
12961
12962 static int timer = 0;
12963
12964 gint
12965 timeout_test (GtkWidget *label)
12966 {
12967   static int count = 0;
12968   static char buffer[32];
12969
12970   sprintf (buffer, "count: %d", ++count);
12971   gtk_label_set_text (GTK_LABEL (label), buffer);
12972
12973   return TRUE;
12974 }
12975
12976 void
12977 start_timeout_test (GtkWidget *widget,
12978                     GtkWidget *label)
12979 {
12980   if (!timer)
12981     {
12982       timer = gtk_timeout_add (100, (GtkFunction) timeout_test, label);
12983     }
12984 }
12985
12986 void
12987 stop_timeout_test (GtkWidget *widget,
12988                    gpointer   data)
12989 {
12990   if (timer)
12991     {
12992       gtk_timeout_remove (timer);
12993       timer = 0;
12994     }
12995 }
12996
12997 void
12998 destroy_timeout_test (GtkWidget  *widget,
12999                       GtkWidget **window)
13000 {
13001   stop_timeout_test (NULL, NULL);
13002
13003   *window = NULL;
13004 }
13005
13006 void
13007 create_timeout_test (GtkWidget *widget)
13008 {
13009   static GtkWidget *window = NULL;
13010   GtkWidget *button;
13011   GtkWidget *label;
13012
13013   if (!window)
13014     {
13015       window = gtk_dialog_new ();
13016
13017       gtk_window_set_screen (GTK_WINDOW (window),
13018                              gtk_widget_get_screen (widget));
13019
13020       g_signal_connect (window, "destroy",
13021                         G_CALLBACK (destroy_timeout_test),
13022                         &window);
13023
13024       gtk_window_set_title (GTK_WINDOW (window), "Timeout Test");
13025       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
13026
13027       label = gtk_label_new ("count: 0");
13028       gtk_misc_set_padding (GTK_MISC (label), 10, 10);
13029       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
13030                           label, TRUE, TRUE, 0);
13031       gtk_widget_show (label);
13032
13033       button = gtk_button_new_with_label ("close");
13034       g_signal_connect_swapped (button, "clicked",
13035                                 G_CALLBACK (gtk_widget_destroy),
13036                                 window);
13037       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
13038       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
13039                           button, TRUE, TRUE, 0);
13040       gtk_widget_grab_default (button);
13041       gtk_widget_show (button);
13042
13043       button = gtk_button_new_with_label ("start");
13044       g_signal_connect (button, "clicked",
13045                         G_CALLBACK(start_timeout_test),
13046                         label);
13047       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
13048       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
13049                           button, TRUE, TRUE, 0);
13050       gtk_widget_show (button);
13051
13052       button = gtk_button_new_with_label ("stop");
13053       g_signal_connect (button, "clicked",
13054                         G_CALLBACK (stop_timeout_test),
13055                         NULL);
13056       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
13057       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
13058                           button, TRUE, TRUE, 0);
13059       gtk_widget_show (button);
13060     }
13061
13062   if (!GTK_WIDGET_VISIBLE (window))
13063     gtk_widget_show (window);
13064   else
13065     gtk_widget_destroy (window);
13066 }
13067
13068 /*
13069  * Idle Test
13070  */
13071
13072 static int idle_id = 0;
13073
13074 static gint
13075 idle_test (GtkWidget *label)
13076 {
13077   static int count = 0;
13078   static char buffer[32];
13079
13080   sprintf (buffer, "count: %d", ++count);
13081   gtk_label_set_text (GTK_LABEL (label), buffer);
13082
13083   return TRUE;
13084 }
13085
13086 static void
13087 start_idle_test (GtkWidget *widget,
13088                  GtkWidget *label)
13089 {
13090   if (!idle_id)
13091     {
13092       idle_id = gtk_idle_add ((GtkFunction) idle_test, label);
13093     }
13094 }
13095
13096 static void
13097 stop_idle_test (GtkWidget *widget,
13098                 gpointer   data)
13099 {
13100   if (idle_id)
13101     {
13102       gtk_idle_remove (idle_id);
13103       idle_id = 0;
13104     }
13105 }
13106
13107 static void
13108 destroy_idle_test (GtkWidget  *widget,
13109                    GtkWidget **window)
13110 {
13111   stop_idle_test (NULL, NULL);
13112
13113   *window = NULL;
13114 }
13115
13116 static void
13117 toggle_idle_container (GObject *button,
13118                        GtkContainer *container)
13119 {
13120   gtk_container_set_resize_mode (container, GPOINTER_TO_INT (g_object_get_data (button, "user_data")));
13121 }
13122
13123 static void
13124 create_idle_test (GtkWidget *widget)
13125 {
13126   static GtkWidget *window = NULL;
13127   GtkWidget *button;
13128   GtkWidget *label;
13129   GtkWidget *container;
13130
13131   if (!window)
13132     {
13133       GtkWidget *button2;
13134       GtkWidget *frame;
13135       GtkWidget *box;
13136
13137       window = gtk_dialog_new ();
13138
13139       gtk_window_set_screen (GTK_WINDOW (window),
13140                              gtk_widget_get_screen (widget));
13141
13142       g_signal_connect (window, "destroy",
13143                         G_CALLBACK (destroy_idle_test),
13144                         &window);
13145
13146       gtk_window_set_title (GTK_WINDOW (window), "Idle Test");
13147       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
13148
13149       label = gtk_label_new ("count: 0");
13150       gtk_misc_set_padding (GTK_MISC (label), 10, 10);
13151       gtk_widget_show (label);
13152       
13153       container =
13154         g_object_new (GTK_TYPE_HBOX,
13155                         "visible", TRUE,
13156                         /* "GtkContainer::child", g_object_new (GTK_TYPE_HBOX,
13157                          * "GtkWidget::visible", TRUE,
13158                          */
13159                          "child", label,
13160                         /* NULL), */
13161                         NULL);
13162       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
13163                           container, TRUE, TRUE, 0);
13164
13165       frame =
13166         g_object_new (GTK_TYPE_FRAME,
13167                         "border_width", 5,
13168                         "label", "Label Container",
13169                         "visible", TRUE,
13170                         "parent", GTK_DIALOG (window)->vbox,
13171                         NULL);
13172       box =
13173         g_object_new (GTK_TYPE_VBOX,
13174                         "visible", TRUE,
13175                         "parent", frame,
13176                         NULL);
13177       button =
13178         g_object_connect (g_object_new (GTK_TYPE_RADIO_BUTTON,
13179                                           "label", "Resize-Parent",
13180                                           "user_data", (void*)GTK_RESIZE_PARENT,
13181                                           "visible", TRUE,
13182                                           "parent", box,
13183                                           NULL),
13184                           "signal::clicked", toggle_idle_container, container,
13185                           NULL);
13186       button = g_object_new (GTK_TYPE_RADIO_BUTTON,
13187                                "label", "Resize-Queue",
13188                                "user_data", (void*)GTK_RESIZE_QUEUE,
13189                                "group", button,
13190                                "visible", TRUE,
13191                                "parent", box,
13192                                NULL);
13193       g_object_connect (button,
13194                         "signal::clicked", toggle_idle_container, container,
13195                         NULL);
13196       button2 = g_object_new (GTK_TYPE_RADIO_BUTTON,
13197                                 "label", "Resize-Immediate",
13198                                 "user_data", (void*)GTK_RESIZE_IMMEDIATE,
13199                                 NULL);
13200       g_object_connect (button2,
13201                         "signal::clicked", toggle_idle_container, container,
13202                         NULL);
13203       g_object_set (button2,
13204                     "group", button,
13205                     "visible", TRUE,
13206                     "parent", box,
13207                     NULL);
13208
13209       button = gtk_button_new_with_label ("close");
13210       g_signal_connect_swapped (button, "clicked",
13211                                 G_CALLBACK (gtk_widget_destroy),
13212                                 window);
13213       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
13214       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
13215                           button, TRUE, TRUE, 0);
13216       gtk_widget_grab_default (button);
13217       gtk_widget_show (button);
13218
13219       button = gtk_button_new_with_label ("start");
13220       g_signal_connect (button, "clicked",
13221                         G_CALLBACK (start_idle_test),
13222                         label);
13223       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
13224       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
13225                           button, TRUE, TRUE, 0);
13226       gtk_widget_show (button);
13227
13228       button = gtk_button_new_with_label ("stop");
13229       g_signal_connect (button, "clicked",
13230                         G_CALLBACK (stop_idle_test),
13231                         NULL);
13232       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
13233       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
13234                           button, TRUE, TRUE, 0);
13235       gtk_widget_show (button);
13236     }
13237
13238   if (!GTK_WIDGET_VISIBLE (window))
13239     gtk_widget_show (window);
13240   else
13241     gtk_widget_destroy (window);
13242 }
13243
13244 /*
13245  * rc file test
13246  */
13247
13248 void
13249 reload_all_rc_files (void)
13250 {
13251   static GdkAtom atom_rcfiles = GDK_NONE;
13252
13253   GdkEvent *send_event = gdk_event_new (GDK_CLIENT_EVENT);
13254   int i;
13255   
13256   if (!atom_rcfiles)
13257     atom_rcfiles = gdk_atom_intern("_GTK_READ_RCFILES", FALSE);
13258
13259   for(i = 0; i < 5; i++)
13260     send_event->client.data.l[i] = 0;
13261   send_event->client.data_format = 32;
13262   send_event->client.message_type = atom_rcfiles;
13263   gdk_event_send_clientmessage_toall (send_event);
13264
13265   gdk_event_free (send_event);
13266 }
13267
13268 void
13269 create_rc_file (GtkWidget *widget)
13270 {
13271   static GtkWidget *window = NULL;
13272   GtkWidget *button;
13273   GtkWidget *frame;
13274   GtkWidget *vbox;
13275   GtkWidget *label;
13276
13277   if (!window)
13278     {
13279       window = gtk_dialog_new ();
13280
13281       gtk_window_set_screen (GTK_WINDOW (window),
13282                              gtk_widget_get_screen (widget));
13283
13284       g_signal_connect (window, "destroy",
13285                         G_CALLBACK (gtk_widget_destroyed),
13286                         &window);
13287
13288       frame = gtk_aspect_frame_new ("Testing RC file prioritization", 0.5, 0.5, 0.0, TRUE);
13289       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), frame, FALSE, FALSE, 0);
13290
13291       vbox = gtk_vbox_new (FALSE, 0);
13292       gtk_container_add (GTK_CONTAINER (frame), vbox);
13293       
13294       label = gtk_label_new ("This label should be red");
13295       gtk_widget_set_name (label, "testgtk-red-label");
13296       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
13297
13298       label = gtk_label_new ("This label should be green");
13299       gtk_widget_set_name (label, "testgtk-green-label");
13300       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
13301
13302       label = gtk_label_new ("This label should be blue");
13303       gtk_widget_set_name (label, "testgtk-blue-label");
13304       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
13305
13306       gtk_window_set_title (GTK_WINDOW (window), "Reload Rc file");
13307       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
13308
13309       button = gtk_button_new_with_label ("Reload");
13310       g_signal_connect (button, "clicked",
13311                         G_CALLBACK (gtk_rc_reparse_all), NULL);
13312       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
13313       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
13314                           button, TRUE, TRUE, 0);
13315       gtk_widget_grab_default (button);
13316
13317       button = gtk_button_new_with_label ("Reload All");
13318       g_signal_connect (button, "clicked",
13319                         G_CALLBACK (reload_all_rc_files), NULL);
13320       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
13321       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
13322                           button, TRUE, TRUE, 0);
13323
13324       button = gtk_button_new_with_label ("Close");
13325       g_signal_connect_swapped (button, "clicked",
13326                                 G_CALLBACK (gtk_widget_destroy),
13327                                 window);
13328       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
13329       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
13330                           button, TRUE, TRUE, 0);
13331     }
13332
13333   if (!GTK_WIDGET_VISIBLE (window))
13334     gtk_widget_show_all (window);
13335   else
13336     gtk_widget_destroy (window);
13337 }
13338
13339 /*
13340  * Test of recursive mainloop
13341  */
13342
13343 void
13344 mainloop_destroyed (GtkWidget *w, GtkWidget **window)
13345 {
13346   *window = NULL;
13347   gtk_main_quit ();
13348 }
13349
13350 void
13351 create_mainloop (GtkWidget *widget)
13352 {
13353   static GtkWidget *window = NULL;
13354   GtkWidget *label;
13355   GtkWidget *button;
13356
13357   if (!window)
13358     {
13359       window = gtk_dialog_new ();
13360
13361       gtk_window_set_screen (GTK_WINDOW (window),
13362                              gtk_widget_get_screen (widget));
13363
13364       gtk_window_set_title (GTK_WINDOW (window), "Test Main Loop");
13365
13366       g_signal_connect (window, "destroy",
13367                         G_CALLBACK (mainloop_destroyed),
13368                         &window);
13369
13370       label = gtk_label_new ("In recursive main loop...");
13371       gtk_misc_set_padding (GTK_MISC(label), 20, 20);
13372
13373       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), label,
13374                           TRUE, TRUE, 0);
13375       gtk_widget_show (label);
13376
13377       button = gtk_button_new_with_label ("Leave");
13378       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), button, 
13379                           FALSE, TRUE, 0);
13380
13381       g_signal_connect_swapped (button, "clicked",
13382                                 G_CALLBACK (gtk_widget_destroy),
13383                                 window);
13384
13385       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
13386       gtk_widget_grab_default (button);
13387
13388       gtk_widget_show (button);
13389     }
13390
13391   if (!GTK_WIDGET_VISIBLE (window))
13392     {
13393       gtk_widget_show (window);
13394
13395       g_print ("create_mainloop: start\n");
13396       gtk_main ();
13397       g_print ("create_mainloop: done\n");
13398     }
13399   else
13400     gtk_widget_destroy (window);
13401 }
13402
13403 gboolean
13404 layout_expose_handler (GtkWidget *widget, GdkEventExpose *event)
13405 {
13406   GtkLayout *layout;
13407
13408   gint i,j;
13409   gint imin, imax, jmin, jmax;
13410
13411   layout = GTK_LAYOUT (widget);
13412
13413   if (event->window != layout->bin_window)
13414     return FALSE;
13415   
13416   imin = (event->area.x) / 10;
13417   imax = (event->area.x + event->area.width + 9) / 10;
13418
13419   jmin = (event->area.y) / 10;
13420   jmax = (event->area.y + event->area.height + 9) / 10;
13421
13422   for (i=imin; i<imax; i++)
13423     for (j=jmin; j<jmax; j++)
13424       if ((i+j) % 2)
13425         gdk_draw_rectangle (layout->bin_window,
13426                             widget->style->black_gc,
13427                             TRUE,
13428                             10*i, 10*j, 
13429                             1+i%10, 1+j%10);
13430   
13431   return FALSE;
13432 }
13433
13434 void create_layout (GtkWidget *widget)
13435 {
13436   static GtkWidget *window = NULL;
13437   GtkWidget *layout;
13438   GtkWidget *scrolledwindow;
13439   GtkWidget *button;
13440
13441   if (!window)
13442     {
13443       gchar buf[16];
13444
13445       gint i, j;
13446       
13447       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
13448       gtk_window_set_screen (GTK_WINDOW (window),
13449                              gtk_widget_get_screen (widget));
13450
13451       g_signal_connect (window, "destroy",
13452                         G_CALLBACK (gtk_widget_destroyed),
13453                         &window);
13454
13455       gtk_window_set_title (GTK_WINDOW (window), "Layout");
13456       gtk_widget_set_size_request (window, 200, 200);
13457
13458       scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
13459       gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolledwindow),
13460                                            GTK_SHADOW_IN);
13461       gtk_scrolled_window_set_placement (GTK_SCROLLED_WINDOW (scrolledwindow),
13462                                          GTK_CORNER_TOP_RIGHT);
13463
13464       gtk_container_add (GTK_CONTAINER (window), scrolledwindow);
13465       
13466       layout = gtk_layout_new (NULL, NULL);
13467       gtk_container_add (GTK_CONTAINER (scrolledwindow), layout);
13468
13469       /* We set step sizes here since GtkLayout does not set
13470        * them itself.
13471        */
13472       GTK_LAYOUT (layout)->hadjustment->step_increment = 10.0;
13473       GTK_LAYOUT (layout)->vadjustment->step_increment = 10.0;
13474       
13475       gtk_widget_set_events (layout, GDK_EXPOSURE_MASK);
13476       g_signal_connect (layout, "expose_event",
13477                         G_CALLBACK (layout_expose_handler), NULL);
13478       
13479       gtk_layout_set_size (GTK_LAYOUT (layout), 1600, 128000);
13480       
13481       for (i=0 ; i < 16 ; i++)
13482         for (j=0 ; j < 16 ; j++)
13483           {
13484             sprintf(buf, "Button %d, %d", i, j);
13485             if ((i + j) % 2)
13486               button = gtk_button_new_with_label (buf);
13487             else
13488               button = gtk_label_new (buf);
13489
13490             gtk_layout_put (GTK_LAYOUT (layout), button,
13491                             j*100, i*100);
13492           }
13493
13494       for (i=16; i < 1280; i++)
13495         {
13496           sprintf(buf, "Button %d, %d", i, 0);
13497           if (i % 2)
13498             button = gtk_button_new_with_label (buf);
13499           else
13500             button = gtk_label_new (buf);
13501
13502           gtk_layout_put (GTK_LAYOUT (layout), button,
13503                           0, i*100);
13504         }
13505     }
13506
13507   if (!GTK_WIDGET_VISIBLE (window))
13508     gtk_widget_show_all (window);
13509   else
13510     gtk_widget_destroy (window);
13511 }
13512
13513 void
13514 create_styles (GtkWidget *widget)
13515 {
13516   static GtkWidget *window = NULL;
13517   GtkWidget *label;
13518   GtkWidget *button;
13519   GtkWidget *entry;
13520   GtkWidget *vbox;
13521   static GdkColor red =    { 0, 0xffff, 0,      0      };
13522   static GdkColor green =  { 0, 0,      0xffff, 0      };
13523   static GdkColor blue =   { 0, 0,      0,      0xffff };
13524   static GdkColor yellow = { 0, 0xffff, 0xffff, 0      };
13525   static GdkColor cyan =   { 0, 0     , 0xffff, 0xffff };
13526   PangoFontDescription *font_desc;
13527
13528   GtkRcStyle *rc_style;
13529
13530   if (!window)
13531     {
13532       window = gtk_dialog_new ();
13533       gtk_window_set_screen (GTK_WINDOW (window),
13534                              gtk_widget_get_screen (widget));
13535      
13536       g_signal_connect (window, "destroy",
13537                         G_CALLBACK (gtk_widget_destroyed),
13538                         &window);
13539
13540       
13541       button = gtk_button_new_with_label ("Close");
13542       g_signal_connect_swapped (button, "clicked",
13543                                 G_CALLBACK (gtk_widget_destroy),
13544                                 window);
13545       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
13546       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
13547                           button, TRUE, TRUE, 0);
13548       gtk_widget_show (button);
13549
13550       vbox = gtk_vbox_new (FALSE, 5);
13551       gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
13552       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), vbox, FALSE, FALSE, 0);
13553       
13554       label = gtk_label_new ("Font:");
13555       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
13556       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
13557
13558       font_desc = pango_font_description_from_string ("Helvetica,Sans Oblique 18");
13559
13560       button = gtk_button_new_with_label ("Some Text");
13561       gtk_widget_modify_font (GTK_BIN (button)->child, font_desc);
13562       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
13563
13564       label = gtk_label_new ("Foreground:");
13565       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
13566       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
13567
13568       button = gtk_button_new_with_label ("Some Text");
13569       gtk_widget_modify_fg (GTK_BIN (button)->child, GTK_STATE_NORMAL, &red);
13570       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
13571
13572       label = gtk_label_new ("Background:");
13573       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
13574       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
13575
13576       button = gtk_button_new_with_label ("Some Text");
13577       gtk_widget_modify_bg (button, GTK_STATE_NORMAL, &green);
13578       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
13579
13580       label = gtk_label_new ("Text:");
13581       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
13582       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
13583
13584       entry = gtk_entry_new ();
13585       gtk_entry_set_text (GTK_ENTRY (entry), "Some Text");
13586       gtk_widget_modify_text (entry, GTK_STATE_NORMAL, &blue);
13587       gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
13588
13589       label = gtk_label_new ("Base:");
13590       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
13591       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
13592
13593       entry = gtk_entry_new ();
13594       gtk_entry_set_text (GTK_ENTRY (entry), "Some Text");
13595       gtk_widget_modify_base (entry, GTK_STATE_NORMAL, &yellow);
13596       gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
13597
13598       label = gtk_label_new ("Cursor:");
13599       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
13600       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
13601
13602       entry = gtk_entry_new ();
13603       gtk_entry_set_text (GTK_ENTRY (entry), "Some Text");
13604       gtk_widget_modify_cursor (entry, &red, &red);
13605       gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
13606
13607       label = gtk_label_new ("Multiple:");
13608       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
13609       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
13610
13611       button = gtk_button_new_with_label ("Some Text");
13612
13613       rc_style = gtk_rc_style_new ();
13614
13615       rc_style->font_desc = pango_font_description_copy (font_desc);
13616       rc_style->color_flags[GTK_STATE_NORMAL] = GTK_RC_FG | GTK_RC_BG;
13617       rc_style->color_flags[GTK_STATE_PRELIGHT] = GTK_RC_FG | GTK_RC_BG;
13618       rc_style->color_flags[GTK_STATE_ACTIVE] = GTK_RC_FG | GTK_RC_BG;
13619       rc_style->fg[GTK_STATE_NORMAL] = yellow;
13620       rc_style->bg[GTK_STATE_NORMAL] = blue;
13621       rc_style->fg[GTK_STATE_PRELIGHT] = blue;
13622       rc_style->bg[GTK_STATE_PRELIGHT] = yellow;
13623       rc_style->fg[GTK_STATE_ACTIVE] = red;
13624       rc_style->bg[GTK_STATE_ACTIVE] = cyan;
13625       rc_style->xthickness = 5;
13626       rc_style->ythickness = 5;
13627
13628       gtk_widget_modify_style (button, rc_style);
13629       gtk_widget_modify_style (GTK_BIN (button)->child, rc_style);
13630
13631       g_object_unref (rc_style);
13632       
13633       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
13634     }
13635   
13636   if (!GTK_WIDGET_VISIBLE (window))
13637     gtk_widget_show_all (window);
13638   else
13639     gtk_widget_destroy (window);
13640 }
13641
13642 /*
13643  * Main Window and Exit
13644  */
13645
13646 void
13647 do_exit (GtkWidget *widget, GtkWidget *window)
13648 {
13649   gtk_widget_destroy (window);
13650   gtk_main_quit ();
13651 }
13652
13653 struct {
13654   char *label;
13655   void (*func) (GtkWidget *widget);
13656   gboolean do_not_benchmark;
13657 } buttons[] =
13658 {
13659   { "alpha window", create_alpha_window },
13660 #ifdef G_OS_WIN32
13661   /* dog slow on NT, no working at all on 9x */
13662   { "big windows", create_big_windows, TRUE },
13663 #else
13664   { "big windows", create_big_windows },
13665 #endif
13666   { "button box", create_button_box },
13667   { "buttons", create_buttons },
13668   { "check buttons", create_check_buttons },
13669   { "clist", create_clist},
13670   { "color selection", create_color_selection },
13671   { "composited window", create_composited_window },
13672   { "ctree", create_ctree },
13673   { "cursors", create_cursors },
13674   { "dialog", create_dialog, TRUE },
13675   { "display & screen", create_display_screen, TRUE },
13676   { "entry", create_entry },
13677   { "event box", create_event_box },
13678   { "event watcher", create_event_watcher },
13679   { "expander", create_expander },
13680   { "file selection", create_file_selection },
13681   { "flipping", create_flipping },
13682   { "focus", create_focus },
13683   { "font selection", create_font_selection },
13684   { "gamma curve", create_gamma_curve, TRUE },
13685   { "gridded geometry", create_gridded_geometry },
13686   { "handle box", create_handle_box },
13687   { "image from drawable", create_get_image },
13688   { "image", create_image },
13689   { "item factory", create_item_factory },
13690   { "key lookup", create_key_lookup },
13691   { "labels", create_labels },
13692   { "layout", create_layout },
13693   { "list", create_list },
13694   { "menus", create_menus },
13695   { "message dialog", create_message_dialog },
13696   { "modal window", create_modal_window, TRUE },
13697   { "notebook", create_notebook },
13698   { "panes", create_panes },
13699   { "paned keyboard", create_paned_keyboard_navigation },
13700   { "pixmap", create_pixmap },
13701   { "preview color", create_color_preview, TRUE },
13702   { "preview gray", create_gray_preview, TRUE },
13703   { "progress bar", create_progress_bar },
13704   { "properties", create_properties },
13705   { "radio buttons", create_radio_buttons },
13706   { "range controls", create_range_controls },
13707   { "rc file", create_rc_file },
13708   { "reparent", create_reparent },
13709   { "resize grips", create_resize_grips },
13710   { "rotated label", create_rotated_label },
13711   { "rotated text", create_rotated_text },
13712   { "rulers", create_rulers },
13713   { "saved position", create_saved_position },
13714   { "scrolled windows", create_scrolled_windows },
13715   { "shapes", create_shapes },
13716   { "size groups", create_size_groups },
13717   { "snapshot", create_snapshot },
13718   { "spinbutton", create_spins },
13719   { "statusbar", create_statusbar },
13720   { "styles", create_styles },
13721   { "test idle", create_idle_test },
13722   { "test mainloop", create_mainloop, TRUE },
13723   { "test scrolling", create_scroll_test },
13724   { "test selection", create_selection_test },
13725   { "test timeout", create_timeout_test },
13726   { "text", create_text },
13727   { "toggle buttons", create_toggle_buttons },
13728   { "toolbar", create_toolbar },
13729   { "tooltips", create_tooltips },
13730   { "tree", create_tree_mode_window},
13731   { "WM hints", create_wmhints },
13732   { "window sizing", create_window_sizing },
13733   { "window states", create_window_states }
13734 };
13735 int nbuttons = sizeof (buttons) / sizeof (buttons[0]);
13736
13737 void
13738 create_main_window (void)
13739 {
13740   GtkWidget *window;
13741   GtkWidget *box1;
13742   GtkWidget *box2;
13743   GtkWidget *scrolled_window;
13744   GtkWidget *button;
13745   GtkWidget *label;
13746   gchar buffer[64];
13747   GtkWidget *separator;
13748   GdkGeometry geometry;
13749   int i;
13750
13751   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
13752   gtk_widget_set_name (window, "main window");
13753   gtk_widget_set_uposition (window, 50, 20);
13754   gtk_window_set_default_size (GTK_WINDOW (window), -1, 400);
13755
13756   geometry.min_width = -1;
13757   geometry.min_height = -1;
13758   geometry.max_width = -1;
13759   geometry.max_height = G_MAXSHORT;
13760   gtk_window_set_geometry_hints (GTK_WINDOW (window), NULL,
13761                                  &geometry,
13762                                  GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE);
13763
13764   g_signal_connect (window, "destroy",
13765                     G_CALLBACK (gtk_main_quit),
13766                     NULL);
13767   g_signal_connect (window, "delete-event",
13768                     G_CALLBACK (gtk_false),
13769                     NULL);
13770
13771   box1 = gtk_vbox_new (FALSE, 0);
13772   gtk_container_add (GTK_CONTAINER (window), box1);
13773
13774   if (gtk_micro_version > 0)
13775     sprintf (buffer,
13776              "Gtk+ v%d.%d.%d",
13777              gtk_major_version,
13778              gtk_minor_version,
13779              gtk_micro_version);
13780   else
13781     sprintf (buffer,
13782              "Gtk+ v%d.%d",
13783              gtk_major_version,
13784              gtk_minor_version);
13785
13786   label = gtk_label_new (buffer);
13787   gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);
13788   gtk_widget_set_name (label, "testgtk-version-label");
13789
13790   scrolled_window = gtk_scrolled_window_new (NULL, NULL);
13791   gtk_container_set_border_width (GTK_CONTAINER (scrolled_window), 10);
13792   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
13793                                   GTK_POLICY_NEVER, 
13794                                   GTK_POLICY_AUTOMATIC);
13795   gtk_box_pack_start (GTK_BOX (box1), scrolled_window, TRUE, TRUE, 0);
13796
13797   box2 = gtk_vbox_new (FALSE, 0);
13798   gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
13799   gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_window), box2);
13800   gtk_container_set_focus_vadjustment (GTK_CONTAINER (box2),
13801                                        gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (scrolled_window)));
13802   gtk_widget_show (box2);
13803
13804   for (i = 0; i < nbuttons; i++)
13805     {
13806       button = gtk_button_new_with_label (buttons[i].label);
13807       if (buttons[i].func)
13808         g_signal_connect (button, 
13809                           "clicked", 
13810                           G_CALLBACK(buttons[i].func),
13811                           NULL);
13812       else
13813         gtk_widget_set_sensitive (button, FALSE);
13814       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
13815     }
13816
13817   separator = gtk_hseparator_new ();
13818   gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
13819
13820   box2 = gtk_vbox_new (FALSE, 10);
13821   gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
13822   gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
13823
13824   button = gtk_button_new_with_mnemonic ("_Close");
13825   g_signal_connect (button, "clicked",
13826                     G_CALLBACK (do_exit),
13827                     window);
13828   gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
13829   GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
13830   gtk_widget_grab_default (button);
13831
13832   gtk_widget_show_all (window);
13833 }
13834
13835 static void
13836 test_init (void)
13837 {
13838   if (g_file_test ("../gdk-pixbuf/libpixbufloader-pnm.la",
13839                    G_FILE_TEST_EXISTS))
13840     {
13841       g_setenv ("GDK_PIXBUF_MODULE_FILE", "../gdk-pixbuf/gdk-pixbuf.loaders", TRUE);
13842       g_setenv ("GTK_IM_MODULE_FILE", "../modules/input/gtk.immodules", TRUE);
13843     }
13844 }
13845
13846 static char *
13847 pad (const char *str, int to)
13848 {
13849   static char buf[256];
13850   int len = strlen (str);
13851   int i;
13852
13853   for (i = 0; i < to; i++)
13854     buf[i] = ' ';
13855
13856   buf[to] = '\0';
13857
13858   memcpy (buf, str, len);
13859
13860   return buf;
13861 }
13862
13863 static void
13864 bench_iteration (GtkWidget *widget, void (* fn) (GtkWidget *widget))
13865 {
13866   fn (widget); /* on */
13867   while (g_main_context_iteration (NULL, FALSE));
13868   fn (widget); /* off */
13869   while (g_main_context_iteration (NULL, FALSE));
13870 }
13871
13872 void
13873 do_real_bench (GtkWidget *widget, void (* fn) (GtkWidget *widget), char *name, int num)
13874 {
13875   GTimeVal tv0, tv1;
13876   double dt_first;
13877   double dt;
13878   int n;
13879   static gboolean printed_headers = FALSE;
13880
13881   if (!printed_headers) {
13882     g_print ("Test                 Iters      First      Other\n");
13883     g_print ("-------------------- ----- ---------- ----------\n");
13884     printed_headers = TRUE;
13885   }
13886
13887   g_get_current_time (&tv0);
13888   bench_iteration (widget, fn); 
13889   g_get_current_time (&tv1);
13890
13891   dt_first = ((double)tv1.tv_sec - tv0.tv_sec) * 1000.0
13892         + (tv1.tv_usec - tv0.tv_usec) / 1000.0;
13893
13894   g_get_current_time (&tv0);
13895   for (n = 0; n < num - 1; n++)
13896     bench_iteration (widget, fn); 
13897   g_get_current_time (&tv1);
13898   dt = ((double)tv1.tv_sec - tv0.tv_sec) * 1000.0
13899         + (tv1.tv_usec - tv0.tv_usec) / 1000.0;
13900
13901   g_print ("%s %5d ", pad (name, 20), num);
13902   if (num > 1)
13903     g_print ("%10.1f %10.1f\n", dt_first, dt/(num-1));
13904   else
13905     g_print ("%10.1f\n", dt_first);
13906 }
13907
13908 void
13909 do_bench (char* what, int num)
13910 {
13911   int i;
13912   GtkWidget *widget;
13913   void (* fn) (GtkWidget *widget);
13914   fn = NULL;
13915   widget = gtk_window_new (GTK_WINDOW_TOPLEVEL);
13916
13917   if (g_ascii_strcasecmp (what, "ALL") == 0)
13918     {
13919       for (i = 0; i < nbuttons; i++)
13920         {
13921           if (!buttons[i].do_not_benchmark)
13922             do_real_bench (widget, buttons[i].func, buttons[i].label, num);
13923         }
13924
13925       return;
13926     }
13927   else
13928     {
13929       for (i = 0; i < nbuttons; i++)
13930         {
13931           if (strcmp (buttons[i].label, what) == 0)
13932             {
13933               fn = buttons[i].func;
13934               break;
13935             }
13936         }
13937       
13938       if (!fn)
13939         g_print ("Can't bench: \"%s\" not found.\n", what);
13940       else
13941         do_real_bench (widget, fn, buttons[i].label, num);
13942     }
13943 }
13944
13945 void 
13946 usage (void)
13947 {
13948   fprintf (stderr, "Usage: testgtk [--bench ALL|<bench>[:<count>]]\n");
13949   exit (1);
13950 }
13951
13952 int
13953 main (int argc, char *argv[])
13954 {
13955   GtkBindingSet *binding_set;
13956   int i;
13957   gboolean done_benchmarks = FALSE;
13958
13959   srand (time (NULL));
13960
13961   test_init ();
13962
13963   /* Check to see if we are being run from the correct
13964    * directory.
13965    */
13966   if (file_exists ("testgtkrc"))
13967     gtk_rc_add_default_file ("testgtkrc");
13968   else if (file_exists ("tests/testgtkrc"))
13969     gtk_rc_add_default_file ("tests/testgtkrc");
13970   else
13971     g_warning ("Couldn't find file \"testgtkrc\".");
13972
13973   g_set_application_name ("GTK+ Test Program");
13974
13975   gtk_init (&argc, &argv);
13976
13977   gtk_accelerator_set_default_mod_mask (GDK_SHIFT_MASK |
13978                                         GDK_CONTROL_MASK |
13979                                         GDK_MOD1_MASK | 
13980                                         GDK_META_MASK |
13981                                         GDK_SUPER_MASK |
13982                                         GDK_HYPER_MASK |
13983                                         GDK_MOD4_MASK);
13984   /*  benchmarking
13985    */
13986   for (i = 1; i < argc; i++)
13987     {
13988       if (strncmp (argv[i], "--bench", strlen("--bench")) == 0)
13989         {
13990           int num = 1;
13991           char *nextarg;
13992           char *what;
13993           char *count;
13994           
13995           nextarg = strchr (argv[i], '=');
13996           if (nextarg)
13997             nextarg++;
13998           else
13999             {
14000               i++;
14001               if (i == argc)
14002                 usage ();
14003               nextarg = argv[i];
14004             }
14005
14006           count = strchr (nextarg, ':');
14007           if (count)
14008             {
14009               what = g_strndup (nextarg, count - nextarg);
14010               count++;
14011               num = atoi (count);
14012               if (num <= 0)
14013                 usage ();
14014             }
14015           else
14016             what = g_strdup (nextarg);
14017
14018           do_bench (what, num ? num : 1);
14019           done_benchmarks = TRUE;
14020         }
14021       else
14022         usage ();
14023     }
14024   if (done_benchmarks)
14025     return 0;
14026
14027   /* bindings test
14028    */
14029   binding_set = gtk_binding_set_by_class (g_type_class_ref (GTK_TYPE_WIDGET));
14030   gtk_binding_entry_add_signal (binding_set,
14031                                 '9', GDK_CONTROL_MASK | GDK_RELEASE_MASK,
14032                                 "debug_msg",
14033                                 1,
14034                                 G_TYPE_STRING, "GtkWidgetClass <ctrl><release>9 test");
14035   
14036   /* We use gtk_rc_parse_string() here so we can make sure it works across theme
14037    * changes
14038    */
14039
14040   gtk_rc_parse_string ("style \"testgtk-version-label\" { "
14041                        "   fg[NORMAL] = \"#ff0000\"\n"
14042                        "   font = \"Sans 18\"\n"
14043                        "}\n"
14044                        "widget \"*.testgtk-version-label\" style \"testgtk-version-label\"");
14045   
14046   create_main_window ();
14047
14048   gtk_main ();
14049
14050   if (1)
14051     {
14052       while (g_main_context_pending (NULL))
14053         g_main_context_iteration (NULL, FALSE);
14054 #if 0
14055       sleep (1);
14056       while (g_main_context_pending (NULL))
14057         g_main_context_iteration (NULL, FALSE);
14058 #endif
14059     }
14060   return 0;
14061 }