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