]> Pileus Git - ~andy/gtk/blob - tests/testgtk.c
Practically everything changed.
[~andy/gtk] / tests / testgtk.c
1 /* GTK - The GTK+ Toolkit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /*
21  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
22  * file for a list of people on the GTK+ Team.  See the ChangeLog
23  * files for a list of changes.  These files are distributed with
24  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
25  */
26
27 #undef GTK_DISABLE_DEPRECATED
28
29 #include "config.h"
30
31 #undef  G_LOG_DOMAIN
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <sys/stat.h>
37 #include <math.h>
38 #include <time.h>
39 #ifdef HAVE_UNISTD_H
40 #include <unistd.h>
41 #endif
42
43 #define GTK_ENABLE_BROKEN
44 #include "gtk/gtk.h"
45 #include "gdk/gdk.h"
46 #include "gdk/gdkkeysyms.h"
47
48 #ifdef G_OS_WIN32
49 #define sleep(n) _sleep(n)
50 #endif
51
52 #include "prop-editor.h"
53
54 #include "circles.xbm"
55 #include "test.xpm"
56
57 gboolean
58 file_exists (const char *filename)
59 {
60   struct stat statbuf;
61
62   return stat (filename, &statbuf) == 0;
63 }
64
65 GtkWidget *
66 shape_create_icon (GdkScreen *screen,
67                    char      *xpm_file,
68                    gint       x,
69                    gint       y,
70                    gint       px,
71                    gint       py,
72                    gint       window_type);
73
74 static GtkWidget *
75 build_option_menu (gchar           *items[],
76                    gint             num_items,
77                    gint             history,
78                    void           (*func) (GtkWidget *widget, gpointer data),
79                    gpointer         data);
80
81 /* macro, structure and variables used by tree window demos */
82 #define DEFAULT_NUMBER_OF_ITEM  3
83 #define DEFAULT_RECURSION_LEVEL 3
84
85 struct {
86   GSList* selection_mode_group;
87   GtkWidget* single_button;
88   GtkWidget* browse_button;
89   GtkWidget* multiple_button;
90   GtkWidget* draw_line_button;
91   GtkWidget* view_line_button;
92   GtkWidget* no_root_item_button;
93   GtkWidget* nb_item_spinner;
94   GtkWidget* recursion_spinner;
95 } sTreeSampleSelection;
96
97 typedef struct sTreeButtons {
98   guint nb_item_add;
99   GtkWidget* add_button;
100   GtkWidget* remove_button;
101   GtkWidget* subtree_button;
102 } sTreeButtons;
103 /* end of tree section */
104
105 static GtkWidget *
106 build_option_menu (gchar           *items[],
107                    gint             num_items,
108                    gint             history,
109                    void           (*func)(GtkWidget *widget, gpointer data),
110                    gpointer         data)
111 {
112   GtkWidget *omenu;
113   GtkWidget *menu;
114   GtkWidget *menu_item;
115   GSList *group;
116   gint i;
117
118   omenu = gtk_option_menu_new ();
119   g_signal_connect (omenu, "changed",
120                     G_CALLBACK (func), data);
121       
122   menu = gtk_menu_new ();
123   group = NULL;
124   
125   for (i = 0; i < num_items; i++)
126     {
127       menu_item = gtk_radio_menu_item_new_with_label (group, items[i]);
128       group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (menu_item));
129       gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
130       if (i == history)
131         gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menu_item), TRUE);
132       gtk_widget_show (menu_item);
133     }
134
135   gtk_option_menu_set_menu (GTK_OPTION_MENU (omenu), menu);
136   gtk_option_menu_set_history (GTK_OPTION_MENU (omenu), history);
137   
138   return omenu;
139 }
140
141 static void
142 destroy_tooltips (GtkWidget *widget, GtkWindow **window)
143 {
144   GtkTooltips *tt = g_object_get_data (G_OBJECT (*window), "tooltips");
145   g_object_unref (tt);
146   *window = NULL;
147 }
148
149
150 /*
151  * Windows with an alpha channel
152  */
153
154
155 static gboolean
156 on_alpha_window_expose (GtkWidget      *widget,
157                         GdkEventExpose *expose)
158 {
159   cairo_t *cr;
160   cairo_pattern_t *pattern;
161   int radius;
162
163   cr = gdk_cairo_create (widget->window);
164
165   radius = MIN (widget->allocation.width, widget->allocation.height) / 2;
166   pattern = cairo_pattern_create_radial (widget->allocation.width / 2,
167                                          widget->allocation.height / 2,
168                                          0.0,
169                                          widget->allocation.width / 2,
170                                          widget->allocation.height / 2,
171                                          radius * 1.33);
172
173   if (gdk_screen_get_rgba_colormap (gtk_widget_get_screen (widget)) &&
174       gtk_widget_is_composited (widget))
175     cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 0.0); /* transparent */
176   else
177     cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); /* opaque white */
178     
179   cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
180   cairo_paint (cr);
181   
182   cairo_pattern_add_color_stop_rgba (pattern, 0.0,
183                                      1.0, 0.75, 0.0, 1.0); /* solid orange */
184   cairo_pattern_add_color_stop_rgba (pattern, 1.0,
185                                      1.0, 0.75, 0.0, 0.0); /* transparent orange */
186
187   cairo_set_source (cr, pattern);
188   cairo_pattern_destroy (pattern);
189   
190   cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
191   cairo_paint (cr);
192
193   cairo_destroy (cr);
194
195   return FALSE;
196 }
197
198 static GtkWidget *
199 build_alpha_widgets (void)
200 {
201   GtkWidget *table;
202   GtkWidget *radio_button;
203   GtkWidget *hbox;
204   GtkWidget *label;
205   GtkWidget *entry;
206
207   table = gtk_table_new (1, 1, FALSE);
208
209   radio_button = gtk_radio_button_new_with_label (NULL, "Red");
210   gtk_table_attach (GTK_TABLE (table),
211                     radio_button,
212                     0, 1,                  0, 1,
213                     GTK_EXPAND | GTK_FILL, 0,
214                     0,                     0);
215
216   radio_button = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (radio_button), "Green");
217   gtk_table_attach (GTK_TABLE (table),
218                     radio_button,
219                     0, 1,                  1, 2,
220                     GTK_EXPAND | GTK_FILL, 0,
221                     0,                     0);
222
223   radio_button = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (radio_button), "Blue"),
224   gtk_table_attach (GTK_TABLE (table),
225                     radio_button,
226                     0, 1,                  2, 3,
227                     GTK_EXPAND | GTK_FILL, 0,
228                     0,                     0);
229
230   gtk_table_attach (GTK_TABLE (table),
231                     gtk_check_button_new_with_label ("Sedentary"),
232                     1, 2,                  0, 1,
233                     GTK_EXPAND | GTK_FILL, 0,
234                     0,                     0);
235   gtk_table_attach (GTK_TABLE (table),
236                     gtk_check_button_new_with_label ("Nocturnal"),
237                     1, 2,                  1, 2,
238                     GTK_EXPAND | GTK_FILL, 0,
239                     0,                     0);
240   gtk_table_attach (GTK_TABLE (table),
241                     gtk_check_button_new_with_label ("Compulsive"),
242                     1, 2,                  2, 3,
243                     GTK_EXPAND | GTK_FILL, 0,
244                     0,                     0);
245
246   radio_button = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (radio_button), "Green");
247   gtk_table_attach (GTK_TABLE (table),
248                     radio_button,
249                     0, 1,                  1, 2,
250                     GTK_EXPAND | GTK_FILL, 0,
251                     0,                     0);
252
253   radio_button = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (radio_button), "Blue"),
254   gtk_table_attach (GTK_TABLE (table),
255                     radio_button,
256                     0, 1,                  2, 3,
257                     GTK_EXPAND | GTK_FILL, 0,
258                     0,                     0);
259   
260   hbox = gtk_hbox_new (FALSE, 0);
261   label = gtk_label_new (NULL);
262   gtk_label_set_markup (GTK_LABEL (label), "<i>Entry: </i>");
263   gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
264   entry = gtk_entry_new ();
265   gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0);
266   gtk_table_attach (GTK_TABLE (table),
267                     hbox,
268                     0, 1,                  3, 4,
269                     GTK_EXPAND | GTK_FILL, 0,
270                     0,                     0);
271   
272   return table;
273 }
274
275 static gboolean
276 on_alpha_drawing_expose (GtkWidget      *widget,
277                          GdkEventExpose *expose)
278 {
279   int x = widget->allocation.x;
280   int y = widget->allocation.y;
281   int width = widget->allocation.width;
282   int height = widget->allocation.height;
283   GdkPixbuf *pixbuf;
284   guchar *buffer;
285   guchar *p;
286   int i, j;
287
288   buffer = g_malloc (64 * 64 * 4);
289   
290   gdk_draw_rectangle (widget->window, widget->style->black_gc, FALSE,
291                       x,         y,
292                       width - 1, height - 1);
293
294   p = buffer;
295   for (i = 0; i < 64; i++) {
296     for (j = 0; j < 64; j++) {
297       *(p++) = i * 4 + 3;
298       *(p++) = 0;
299       *(p++) = j + 4 + 3;
300       *(p++) = MIN (255, ((32 - i) * (32 - i) + (32 - j) * (32 - j)) / 8);
301     }
302   }
303   p++;
304
305   gdk_draw_rgb_32_image (widget->window, widget->style->black_gc,
306                          x + 18, y + (height - 64) /2,
307                          64, 64, GDK_RGB_DITHER_NORMAL, buffer, 64 * 4);
308
309   pixbuf = gdk_pixbuf_new_from_data (buffer, GDK_COLORSPACE_RGB, TRUE,
310                                      8, 64, 64, 4 * 64, NULL, NULL);
311
312   gdk_draw_pixbuf (widget->window, widget->style->black_gc, pixbuf,
313                    0, 0, x + width - 18 - 64, y + (height - 64) /2,
314                    64, 64, GDK_RGB_DITHER_NORMAL, 0, 0);
315
316   g_object_unref (pixbuf);
317
318   g_free (buffer);
319   
320   return FALSE;
321 }
322
323 static GtkWidget *
324 build_alpha_drawing ()
325 {
326   GtkWidget *hbox;
327
328   hbox = gtk_hbox_new (FALSE, 0);
329   gtk_widget_set_size_request (hbox, 100, 100);
330
331   g_signal_connect (hbox, "expose-event",
332                     G_CALLBACK (on_alpha_drawing_expose), NULL);
333
334   return hbox;
335 }
336
337 static void
338 on_alpha_screen_changed (GtkWidget *widget,
339                          GdkScreen *old_screen,
340                          GtkWidget *label)
341 {
342   GdkScreen *screen = gtk_widget_get_screen (widget);
343   GdkColormap *colormap = gdk_screen_get_rgba_colormap (screen);
344
345   if (!colormap)
346     {
347       colormap = gdk_screen_get_rgb_colormap (screen);
348       gtk_label_set_markup (GTK_LABEL (label), "<b>Screen doesn't support alpha</b>");
349     }
350   else
351     {
352       gtk_label_set_markup (GTK_LABEL (label), "<b>Screen supports alpha</b>");
353     }
354
355   gtk_widget_set_colormap (widget, colormap);
356 }
357
358 static void
359 on_composited_changed (GtkWidget *window,
360                       GtkLabel *label)
361 {
362   gboolean is_composited = gtk_widget_is_composited (window);
363
364   if (is_composited)
365     gtk_label_set_text (label, "Composited");
366   else
367     gtk_label_set_text (label, "Not composited");
368 }
369
370 void
371 create_alpha_window (GtkWidget *widget)
372 {
373   static GtkWidget *window;
374
375   if (!window)
376     {
377       GtkWidget *vbox;
378       GtkWidget *label;
379       
380       window = gtk_dialog_new_with_buttons ("Alpha Window",
381                                             GTK_WINDOW (gtk_widget_get_toplevel (widget)), 0,
382                                             GTK_STOCK_CLOSE, 0,
383                                             NULL);
384
385       gtk_widget_set_app_paintable (window, TRUE);
386       g_signal_connect (window, "expose-event",
387                         G_CALLBACK (on_alpha_window_expose), NULL);
388       
389       vbox = gtk_vbox_new (FALSE, 8);
390       gtk_container_set_border_width (GTK_CONTAINER (vbox), 12);
391       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), vbox,
392                           TRUE, TRUE, 0);
393
394       label = gtk_label_new (NULL);
395       gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
396       on_alpha_screen_changed (window, NULL, label);
397       g_signal_connect (window, "screen-changed",
398                         G_CALLBACK (on_alpha_screen_changed), label);
399       
400       label = gtk_label_new (NULL);
401       gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
402       on_composited_changed (window, GTK_LABEL (label));
403       g_signal_connect (window, "composited_changed", G_CALLBACK (on_composited_changed), label);
404       
405       gtk_box_pack_start (GTK_BOX (vbox), build_alpha_widgets (), TRUE, TRUE, 0);
406       gtk_box_pack_start (GTK_BOX (vbox), build_alpha_drawing (), TRUE, TRUE, 0);
407
408       g_signal_connect (window, "destroy",
409                         G_CALLBACK (gtk_widget_destroyed),
410                         &window);
411       
412       g_signal_connect (window, "response",
413                         G_CALLBACK (gtk_widget_destroy),
414                         NULL); 
415     }
416
417   if (!GTK_WIDGET_VISIBLE (window))
418     gtk_widget_show_all (window);
419   else
420     gtk_widget_destroy (window);
421 }
422
423 /*
424  * Composited non-toplevel window
425  */
426
427 /* The expose event handler for the event box.
428  *
429  * This function simply draws a transparency onto a widget on the area
430  * for which it receives expose events.  This is intended to give the
431  * event box a "transparent" background.
432  *
433  * In order for this to work properly, the widget must have an RGBA
434  * colourmap.  The widget should also be set as app-paintable since it
435  * doesn't make sense for GTK to draw a background if we are drawing it
436  * (and because GTK might actually replace our transparency with its
437  * default background colour).
438  */
439 static gboolean
440 transparent_expose (GtkWidget *widget,
441                     GdkEventExpose *event)
442 {
443   cairo_t *cr;
444
445   cr = gdk_cairo_create (widget->window);
446   cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
447   gdk_cairo_region (cr, event->region);
448   cairo_fill (cr);
449   cairo_destroy (cr);
450
451   return FALSE;
452 }
453
454 /* The expose event handler for the window.
455  *
456  * This function performs the actual compositing of the event box onto
457  * the already-existing background of the window at 50% normal opacity.
458  *
459  * In this case we do not want app-paintable to be set on the widget
460  * since we want it to draw its own (red) background.  Because of this,
461  * however, we must ensure that we use g_signal_register_after so that
462  * this handler is called after the red has been drawn.  If it was
463  * called before then GTK would just blindly paint over our work.
464  */
465 static gboolean
466 window_expose_event (GtkWidget *widget,
467                      GdkEventExpose *event)
468 {
469   GdkRegion *region;
470   GtkWidget *child;
471   cairo_t *cr;
472
473   /* get our child (in this case, the event box) */ 
474   child = gtk_bin_get_child (GTK_BIN (widget));
475
476   /* create a cairo context to draw to the window */
477   cr = gdk_cairo_create (widget->window);
478
479   /* the source data is the (composited) event box */
480   gdk_cairo_set_source_pixmap (cr, child->window,
481                                child->allocation.x,
482                                child->allocation.y);
483
484   /* draw no more than our expose event intersects our child */
485   region = gdk_region_rectangle (&child->allocation);
486   gdk_region_intersect (region, event->region);
487   gdk_cairo_region (cr, region);
488   cairo_clip (cr);
489
490   /* composite, with a 50% opacity */
491   cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
492   cairo_paint_with_alpha (cr, 0.5);
493
494   /* we're done */
495   cairo_destroy (cr);
496
497   return FALSE;
498 }
499
500 void
501 create_composited_window (GtkWidget *widget)
502 {
503   static GtkWidget *window;
504
505   if (!window)
506     {
507       GtkWidget *event, *button;
508       GdkScreen *screen;
509       GdkColormap *rgba;
510       GdkColor red;
511
512       /* make the widgets */
513       button = gtk_button_new_with_label ("A Button");
514       event = gtk_event_box_new ();
515       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
516
517       g_signal_connect (window, "destroy",
518                         G_CALLBACK (gtk_widget_destroyed),
519                         &window);
520
521       /* put a red background on the window */
522       gdk_color_parse ("red", &red);
523       gtk_widget_modify_bg (window, GTK_STATE_NORMAL, &red);
524
525       /* set the colourmap for the event box.
526        * must be done before the event box is realised.
527        */
528       screen = gtk_widget_get_screen (event);
529       rgba = gdk_screen_get_rgba_colormap (screen);
530       gtk_widget_set_colormap (event, rgba);
531
532       /* set our event box to have a fully-transparent background
533        * drawn on it.  currently there is no way to simply tell gtk
534        * that "transparency" is the background colour for a widget.
535        */
536       gtk_widget_set_app_paintable (GTK_WIDGET (event), TRUE);
537       g_signal_connect (event, "expose-event",
538                         G_CALLBACK (transparent_expose), NULL);
539
540       /* put them inside one another */
541       gtk_container_set_border_width (GTK_CONTAINER (window), 10);
542       gtk_container_add (GTK_CONTAINER (window), event);
543       gtk_container_add (GTK_CONTAINER (event), button);
544
545       /* realise and show everything */
546       gtk_widget_realize (button);
547
548       /* set the event box GdkWindow to be composited.
549        * obviously must be performed after event box is realised.
550        */
551       gdk_window_set_composited (event->window, TRUE);
552
553       /* set up the compositing handler.
554        * note that we do _after so that the normal (red) background is drawn
555        * by gtk before our compositing occurs.
556        */
557       g_signal_connect_after (window, "expose-event",
558                               G_CALLBACK (window_expose_event), NULL);
559     }
560
561   if (!GTK_WIDGET_VISIBLE (window))
562     gtk_widget_show_all (window);
563   else
564     gtk_widget_destroy (window);
565 }
566
567 /*
568  * Big windows and guffaw scrolling
569  */
570
571 static gboolean
572 pattern_expose (GtkWidget      *widget,
573                 GdkEventExpose *event,
574                 gpointer        data)
575 {
576   GdkColor *color;
577   GdkWindow *window = event->window;
578
579   color = g_object_get_data (G_OBJECT (window), "pattern-color");
580   if (color)
581     {
582       GdkGC *tmp_gc = gdk_gc_new (window);
583       gdk_gc_set_rgb_fg_color (tmp_gc, color);
584
585       gdk_draw_rectangle (window, tmp_gc, TRUE,
586                           event->area.x, event->area.y,
587                           event->area.width, event->area.height);
588
589       g_object_unref (tmp_gc);
590     }
591
592   return FALSE;
593 }
594
595 static void
596 pattern_set_bg (GtkWidget   *widget,
597                 GdkWindow   *child,
598                 gint         level)
599 {
600   static const GdkColor colors[] = {
601     { 0, 0x4444, 0x4444, 0xffff },
602     { 0, 0x8888, 0x8888, 0xffff },
603     { 0, 0xaaaa, 0xaaaa, 0xffff }
604   };
605     
606   g_object_set_data (G_OBJECT (child), "pattern-color", (gpointer) &colors[level]);
607   gdk_window_set_user_data (child, widget);
608 }
609
610 static void
611 create_pattern (GtkWidget   *widget,
612                 GdkWindow   *parent,
613                 gint         level,
614                 gint         width,
615                 gint         height)
616 {
617   gint h = 1;
618   gint i = 0;
619     
620   GdkWindow *child;
621
622   while (2 * h <= height)
623     {
624       gint w = 1;
625       gint j = 0;
626       
627       while (2 * w <= width)
628         {
629           if ((i + j) % 2 == 0)
630             {
631               gint x = w  - 1;
632               gint y = h - 1;
633               
634               GdkWindowAttr attributes;
635
636               attributes.window_type = GDK_WINDOW_CHILD;
637               attributes.x = x;
638               attributes.y = y;
639               attributes.width = w;
640               attributes.height = h;
641               attributes.wclass = GDK_INPUT_OUTPUT;
642               attributes.event_mask = GDK_EXPOSURE_MASK;
643               attributes.visual = gtk_widget_get_visual (widget);
644               attributes.colormap = gtk_widget_get_colormap (widget);
645               
646               child = gdk_window_new (parent, &attributes,
647                                       GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP);
648
649               pattern_set_bg (widget, child, level);
650
651               if (level < 2)
652                 create_pattern (widget, child, level + 1, w, h);
653
654               gdk_window_show (child);
655             }
656           j++;
657           w *= 2;
658         }
659       i++;
660       h *= 2;
661     }
662 }
663
664 #define PATTERN_SIZE (1 << 18)
665
666 static void
667 pattern_hadj_changed (GtkAdjustment *adj,
668                       GtkWidget     *darea)
669 {
670   gint *old_value = g_object_get_data (G_OBJECT (adj), "old-value");
671   gint new_value = adj->value;
672
673   if (GTK_WIDGET_REALIZED (darea))
674     {
675       gdk_window_scroll (darea->window, *old_value - new_value, 0);
676       *old_value = new_value;
677     }
678 }
679
680 static void
681 pattern_vadj_changed (GtkAdjustment *adj,
682                       GtkWidget *darea)
683 {
684   gint *old_value = g_object_get_data (G_OBJECT (adj), "old-value");
685   gint new_value = adj->value;
686
687   if (GTK_WIDGET_REALIZED (darea))
688     {
689       gdk_window_scroll (darea->window, 0, *old_value - new_value);
690       *old_value = new_value;
691     }
692 }
693
694 static void
695 pattern_realize (GtkWidget *widget,
696                  gpointer   data)
697 {
698   pattern_set_bg (widget, widget->window, 0);
699   create_pattern (widget, widget->window, 1, PATTERN_SIZE, PATTERN_SIZE);
700 }
701
702 static void 
703 create_big_windows (GtkWidget *widget)
704 {
705   static GtkWidget *window = NULL;
706   GtkWidget *darea, *table, *scrollbar;
707   GtkWidget *eventbox;
708   GtkAdjustment *hadj;
709   GtkAdjustment *vadj;
710   static gint current_x;
711   static gint current_y;
712  
713   if (!window)
714     {
715       current_x = 0;
716       current_y = 0;
717       
718       window = gtk_dialog_new_with_buttons ("Big Windows",
719                                             NULL, 0,
720                                             GTK_STOCK_CLOSE,
721                                             GTK_RESPONSE_NONE,
722                                             NULL);
723  
724       gtk_window_set_screen (GTK_WINDOW (window),
725                              gtk_widget_get_screen (widget));
726
727       gtk_window_set_default_size (GTK_WINDOW (window), 200, 300);
728
729       g_signal_connect (window, "destroy",
730                         G_CALLBACK (gtk_widget_destroyed),
731                         &window);
732
733       g_signal_connect (window, "response",
734                         G_CALLBACK (gtk_widget_destroy),
735                         NULL);
736
737       table = gtk_table_new (2, 2, FALSE);
738       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox),
739                           table, TRUE, TRUE, 0);
740
741       darea = gtk_drawing_area_new ();
742
743       hadj = (GtkAdjustment *)gtk_adjustment_new (0, 0, PATTERN_SIZE, 10, 100, 100);
744       g_signal_connect (hadj, "value_changed",
745                         G_CALLBACK (pattern_hadj_changed), darea);
746       g_object_set_data (G_OBJECT (hadj), "old-value", &current_x);
747       
748       vadj = (GtkAdjustment *)gtk_adjustment_new (0, 0, PATTERN_SIZE, 10, 100, 100);
749       g_signal_connect (vadj, "value_changed",
750                         G_CALLBACK (pattern_vadj_changed), darea);
751       g_object_set_data (G_OBJECT (vadj), "old-value", &current_y);
752       
753       g_signal_connect (darea, "realize",
754                         G_CALLBACK (pattern_realize),
755                         NULL);
756       g_signal_connect (darea, "expose_event",
757                         G_CALLBACK (pattern_expose),
758                         NULL);
759
760       eventbox = gtk_event_box_new ();
761       gtk_table_attach (GTK_TABLE (table), eventbox,
762                         0, 1,                  0, 1,
763                         GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND,
764                         0,                     0);
765
766       gtk_container_add (GTK_CONTAINER (eventbox), darea);
767
768       scrollbar = gtk_hscrollbar_new (hadj);
769       gtk_table_attach (GTK_TABLE (table), scrollbar,
770                         0, 1,                  1, 2,
771                         GTK_FILL | GTK_EXPAND, GTK_FILL,
772                         0,                     0);
773
774       scrollbar = gtk_vscrollbar_new (vadj);
775       gtk_table_attach (GTK_TABLE (table), scrollbar,
776                         1, 2,                  0, 1,
777                         GTK_FILL,              GTK_EXPAND | GTK_FILL,
778                         0,                     0);
779
780     }
781
782   if (!GTK_WIDGET_VISIBLE (window))
783     gtk_widget_show_all (window);
784   else
785     gtk_widget_hide (window);
786 }
787
788 /*
789  * GtkButton
790  */
791
792 static void
793 button_window (GtkWidget *widget,
794                GtkWidget *button)
795 {
796   if (!GTK_WIDGET_VISIBLE (button))
797     gtk_widget_show (button);
798   else
799     gtk_widget_hide (button);
800 }
801
802 static void
803 create_buttons (GtkWidget *widget)
804 {
805   static GtkWidget *window = NULL;
806   GtkWidget *box1;
807   GtkWidget *box2;
808   GtkWidget *table;
809   GtkWidget *button[10];
810   GtkWidget *separator;
811
812   if (!window)
813     {
814       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
815       gtk_window_set_screen (GTK_WINDOW (window),
816                              gtk_widget_get_screen (widget));
817
818       g_signal_connect (window, "destroy",
819                         G_CALLBACK (gtk_widget_destroyed),
820                         &window);
821
822       gtk_window_set_title (GTK_WINDOW (window), "GtkButton");
823       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
824
825       box1 = gtk_vbox_new (FALSE, 0);
826       gtk_container_add (GTK_CONTAINER (window), box1);
827
828       table = gtk_table_new (3, 3, FALSE);
829       gtk_table_set_row_spacings (GTK_TABLE (table), 5);
830       gtk_table_set_col_spacings (GTK_TABLE (table), 5);
831       gtk_container_set_border_width (GTK_CONTAINER (table), 10);
832       gtk_box_pack_start (GTK_BOX (box1), table, TRUE, TRUE, 0);
833
834       button[0] = gtk_button_new_with_label ("button1");
835       button[1] = gtk_button_new_with_mnemonic ("_button2");
836       button[2] = gtk_button_new_with_mnemonic ("_button3");
837       button[3] = gtk_button_new_from_stock (GTK_STOCK_OK);
838       button[4] = gtk_button_new_with_label ("button5");
839       button[5] = gtk_button_new_with_label ("button6");
840       button[6] = gtk_button_new_with_label ("button7");
841       button[7] = gtk_button_new_from_stock (GTK_STOCK_CLOSE);
842       button[8] = gtk_button_new_with_label ("button9");
843       
844       g_signal_connect (button[0], "clicked",
845                         G_CALLBACK (button_window),
846                         button[1]);
847
848       gtk_table_attach (GTK_TABLE (table), button[0], 0, 1, 0, 1,
849                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
850
851       g_signal_connect (button[1], "clicked",
852                         G_CALLBACK (button_window),
853                         button[2]);
854
855       gtk_table_attach (GTK_TABLE (table), button[1], 1, 2, 1, 2,
856                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
857
858       g_signal_connect (button[2], "clicked",
859                         G_CALLBACK (button_window),
860                         button[3]);
861       gtk_table_attach (GTK_TABLE (table), button[2], 2, 3, 2, 3,
862                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
863
864       g_signal_connect (button[3], "clicked",
865                         G_CALLBACK (button_window),
866                         button[4]);
867       gtk_table_attach (GTK_TABLE (table), button[3], 0, 1, 2, 3,
868                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
869
870       g_signal_connect (button[4], "clicked",
871                         G_CALLBACK (button_window),
872                         button[5]);
873       gtk_table_attach (GTK_TABLE (table), button[4], 2, 3, 0, 1,
874                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
875
876       g_signal_connect (button[5], "clicked",
877                         G_CALLBACK (button_window),
878                         button[6]);
879       gtk_table_attach (GTK_TABLE (table), button[5], 1, 2, 2, 3,
880                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
881
882       g_signal_connect (button[6], "clicked",
883                         G_CALLBACK (button_window),
884                         button[7]);
885       gtk_table_attach (GTK_TABLE (table), button[6], 1, 2, 0, 1,
886                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
887
888       g_signal_connect (button[7], "clicked",
889                         G_CALLBACK (button_window),
890                         button[8]);
891       gtk_table_attach (GTK_TABLE (table), button[7], 2, 3, 1, 2,
892                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
893
894       g_signal_connect (button[8], "clicked",
895                         G_CALLBACK (button_window),
896                         button[0]);
897       gtk_table_attach (GTK_TABLE (table), button[8], 0, 1, 1, 2,
898                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
899
900       separator = gtk_hseparator_new ();
901       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
902
903       box2 = gtk_vbox_new (FALSE, 10);
904       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
905       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
906
907       button[9] = gtk_button_new_with_label ("close");
908       g_signal_connect_swapped (button[9], "clicked",
909                                 G_CALLBACK (gtk_widget_destroy),
910                                 window);
911       gtk_box_pack_start (GTK_BOX (box2), button[9], TRUE, TRUE, 0);
912       GTK_WIDGET_SET_FLAGS (button[9], GTK_CAN_DEFAULT);
913       gtk_widget_grab_default (button[9]);
914     }
915
916   if (!GTK_WIDGET_VISIBLE (window))
917     gtk_widget_show_all (window);
918   else
919     gtk_widget_destroy (window);
920 }
921
922 /*
923  * GtkToggleButton
924  */
925
926 static void
927 create_toggle_buttons (GtkWidget *widget)
928 {
929   static GtkWidget *window = NULL;
930   GtkWidget *box1;
931   GtkWidget *box2;
932   GtkWidget *button;
933   GtkWidget *separator;
934
935   if (!window)
936     {
937       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
938       gtk_window_set_screen (GTK_WINDOW (window),
939                              gtk_widget_get_screen (widget));
940
941       g_signal_connect (window, "destroy",
942                         G_CALLBACK (gtk_widget_destroyed),
943                         &window);
944
945       gtk_window_set_title (GTK_WINDOW (window), "GtkToggleButton");
946       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
947
948       box1 = gtk_vbox_new (FALSE, 0);
949       gtk_container_add (GTK_CONTAINER (window), box1);
950
951       box2 = gtk_vbox_new (FALSE, 10);
952       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
953       gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
954
955       button = gtk_toggle_button_new_with_label ("button1");
956       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
957
958       button = gtk_toggle_button_new_with_label ("button2");
959       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
960
961       button = gtk_toggle_button_new_with_label ("button3");
962       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
963
964       button = gtk_toggle_button_new_with_label ("inconsistent");
965       gtk_toggle_button_set_inconsistent (GTK_TOGGLE_BUTTON (button), TRUE);
966       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
967       
968       separator = gtk_hseparator_new ();
969       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
970
971       box2 = gtk_vbox_new (FALSE, 10);
972       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
973       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
974
975       button = gtk_button_new_with_label ("close");
976       g_signal_connect_swapped (button, "clicked",
977                                 G_CALLBACK (gtk_widget_destroy),
978                                 window);
979       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
980       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
981       gtk_widget_grab_default (button);
982     }
983
984   if (!GTK_WIDGET_VISIBLE (window))
985     gtk_widget_show_all (window);
986   else
987     gtk_widget_destroy (window);
988 }
989
990 static GtkWidget *
991 create_widget_grid (GType widget_type)
992 {
993   GtkWidget *table;
994   GtkWidget *group_widget = NULL;
995   gint i, j;
996   
997   table = gtk_table_new (FALSE, 3, 3);
998   
999   for (i = 0; i < 5; i++)
1000     {
1001       for (j = 0; j < 5; j++)
1002         {
1003           GtkWidget *widget;
1004           char *tmp;
1005           
1006           if (i == 0 && j == 0)
1007             {
1008               widget = NULL;
1009             }
1010           else if (i == 0)
1011             {
1012               tmp = g_strdup_printf ("%d", j);
1013               widget = gtk_label_new (tmp);
1014               g_free (tmp);
1015             }
1016           else if (j == 0)
1017             {
1018               tmp = g_strdup_printf ("%c", 'A' + i - 1);
1019               widget = gtk_label_new (tmp);
1020               g_free (tmp);
1021             }
1022           else
1023             {
1024               widget = g_object_new (widget_type, NULL);
1025               
1026               if (g_type_is_a (widget_type, GTK_TYPE_RADIO_BUTTON))
1027                 {
1028                   if (!group_widget)
1029                     group_widget = widget;
1030                   else
1031                     g_object_set (widget, "group", group_widget, NULL);
1032                 }
1033             }
1034           
1035           if (widget)
1036             gtk_table_attach (GTK_TABLE (table), widget,
1037                               i, i + 1, j, j + 1,
1038                               0,        0,
1039                               0,        0);
1040         }
1041     }
1042
1043   return table;
1044 }
1045
1046 /*
1047  * GtkCheckButton
1048  */
1049
1050 static void
1051 create_check_buttons (GtkWidget *widget)
1052 {
1053   static GtkWidget *window = NULL;
1054   GtkWidget *box1;
1055   GtkWidget *box2;
1056   GtkWidget *button;
1057   GtkWidget *separator;
1058   GtkWidget *table;
1059   
1060   if (!window)
1061     {
1062       window = gtk_dialog_new_with_buttons ("Check Buttons",
1063                                             NULL, 0,
1064                                             GTK_STOCK_CLOSE,
1065                                             GTK_RESPONSE_NONE,
1066                                             NULL);
1067
1068       gtk_window_set_screen (GTK_WINDOW (window), 
1069                              gtk_widget_get_screen (widget));
1070
1071       g_signal_connect (window, "destroy",
1072                         G_CALLBACK (gtk_widget_destroyed),
1073                         &window);
1074       g_signal_connect (window, "response",
1075                         G_CALLBACK (gtk_widget_destroy),
1076                         NULL);
1077
1078       box1 = GTK_DIALOG (window)->vbox;
1079       
1080       box2 = gtk_vbox_new (FALSE, 10);
1081       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
1082       gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
1083
1084       button = gtk_check_button_new_with_mnemonic ("_button1");
1085       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
1086
1087       button = gtk_check_button_new_with_label ("button2");
1088       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
1089
1090       button = gtk_check_button_new_with_label ("button3");
1091       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
1092
1093       button = gtk_check_button_new_with_label ("inconsistent");
1094       gtk_toggle_button_set_inconsistent (GTK_TOGGLE_BUTTON (button), TRUE);
1095       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
1096
1097       separator = gtk_hseparator_new ();
1098       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
1099
1100       table = create_widget_grid (GTK_TYPE_CHECK_BUTTON);
1101       gtk_container_set_border_width (GTK_CONTAINER (table), 10);
1102       gtk_box_pack_start (GTK_BOX (box1), table, TRUE, TRUE, 0);
1103     }
1104
1105   if (!GTK_WIDGET_VISIBLE (window))
1106     gtk_widget_show_all (window);
1107   else
1108     gtk_widget_destroy (window);
1109 }
1110
1111 /*
1112  * GtkRadioButton
1113  */
1114
1115 static void
1116 create_radio_buttons (GtkWidget *widget)
1117 {
1118   static GtkWidget *window = NULL;
1119   GtkWidget *box1;
1120   GtkWidget *box2;
1121   GtkWidget *button;
1122   GtkWidget *separator;
1123   GtkWidget *table;
1124
1125   if (!window)
1126     {
1127       window = gtk_dialog_new_with_buttons ("Radio Buttons",
1128                                             NULL, 0,
1129                                             GTK_STOCK_CLOSE,
1130                                             GTK_RESPONSE_NONE,
1131                                             NULL);
1132
1133       gtk_window_set_screen (GTK_WINDOW (window),
1134                              gtk_widget_get_screen (widget));
1135
1136       g_signal_connect (window, "destroy",
1137                         G_CALLBACK (gtk_widget_destroyed),
1138                         &window);
1139       g_signal_connect (window, "response",
1140                         G_CALLBACK (gtk_widget_destroy),
1141                         NULL);
1142
1143       box1 = GTK_DIALOG (window)->vbox;
1144
1145       box2 = gtk_vbox_new (FALSE, 10);
1146       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
1147       gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
1148
1149       button = gtk_radio_button_new_with_label (NULL, "button1");
1150       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
1151
1152       button = gtk_radio_button_new_with_label (
1153                  gtk_radio_button_get_group (GTK_RADIO_BUTTON (button)),
1154                  "button2");
1155       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
1156       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
1157
1158       button = gtk_radio_button_new_with_label (
1159                  gtk_radio_button_get_group (GTK_RADIO_BUTTON (button)),
1160                  "button3");
1161       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
1162
1163       button = gtk_radio_button_new_with_label (
1164                  gtk_radio_button_get_group (GTK_RADIO_BUTTON (button)),
1165                  "inconsistent");
1166       gtk_toggle_button_set_inconsistent (GTK_TOGGLE_BUTTON (button), TRUE);
1167       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
1168       
1169       separator = gtk_hseparator_new ();
1170       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
1171
1172       box2 = gtk_vbox_new (FALSE, 10);
1173       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
1174       gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
1175
1176       button = gtk_radio_button_new_with_label (NULL, "button4");
1177       gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (button), FALSE);
1178       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
1179
1180       button = gtk_radio_button_new_with_label (
1181                  gtk_radio_button_get_group (GTK_RADIO_BUTTON (button)),
1182                  "button5");
1183       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
1184       gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (button), FALSE);
1185       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
1186
1187       button = gtk_radio_button_new_with_label (
1188                  gtk_radio_button_get_group (GTK_RADIO_BUTTON (button)),
1189                  "button6");
1190       gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (button), FALSE);
1191       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
1192
1193       separator = gtk_hseparator_new ();
1194       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
1195
1196       table = create_widget_grid (GTK_TYPE_RADIO_BUTTON);
1197       gtk_container_set_border_width (GTK_CONTAINER (table), 10);
1198       gtk_box_pack_start (GTK_BOX (box1), table, TRUE, TRUE, 0);
1199     }
1200
1201   if (!GTK_WIDGET_VISIBLE (window))
1202     gtk_widget_show_all (window);
1203   else
1204     gtk_widget_destroy (window);
1205 }
1206
1207 /*
1208  * GtkButtonBox
1209  */
1210
1211 static GtkWidget *
1212 create_bbox (gint  horizontal,
1213              char* title, 
1214              gint  spacing,
1215              gint  child_w,
1216              gint  child_h,
1217              gint  layout)
1218 {
1219   GtkWidget *frame;
1220   GtkWidget *bbox;
1221   GtkWidget *button;
1222         
1223   frame = gtk_frame_new (title);
1224
1225   if (horizontal)
1226     bbox = gtk_hbutton_box_new ();
1227   else
1228     bbox = gtk_vbutton_box_new ();
1229
1230   gtk_container_set_border_width (GTK_CONTAINER (bbox), 5);
1231   gtk_container_add (GTK_CONTAINER (frame), bbox);
1232
1233   gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), layout);
1234   gtk_box_set_spacing (GTK_BOX (bbox), spacing);
1235   gtk_button_box_set_child_size (GTK_BUTTON_BOX (bbox), child_w, child_h);
1236   
1237   button = gtk_button_new_with_label ("OK");
1238   gtk_container_add (GTK_CONTAINER (bbox), button);
1239   
1240   button = gtk_button_new_with_label ("Cancel");
1241   gtk_container_add (GTK_CONTAINER (bbox), button);
1242   
1243   button = gtk_button_new_with_label ("Help");
1244   gtk_container_add (GTK_CONTAINER (bbox), button);
1245
1246   return frame;
1247 }
1248
1249 static void
1250 create_button_box (GtkWidget *widget)
1251 {
1252   static GtkWidget* window = NULL;
1253   GtkWidget *main_vbox;
1254   GtkWidget *vbox;
1255   GtkWidget *hbox;
1256   GtkWidget *frame_horz;
1257   GtkWidget *frame_vert;
1258
1259   if (!window)
1260   {
1261     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1262     gtk_window_set_screen (GTK_WINDOW (window), gtk_widget_get_screen (widget));
1263     gtk_window_set_title (GTK_WINDOW (window), "Button Boxes");
1264     
1265     g_signal_connect (window, "destroy",
1266                       G_CALLBACK (gtk_widget_destroyed),
1267                       &window);
1268
1269     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
1270
1271     main_vbox = gtk_vbox_new (FALSE, 0);
1272     gtk_container_add (GTK_CONTAINER (window), main_vbox);
1273     
1274     frame_horz = gtk_frame_new ("Horizontal Button Boxes");
1275     gtk_box_pack_start (GTK_BOX (main_vbox), frame_horz, TRUE, TRUE, 10);
1276     
1277     vbox = gtk_vbox_new (FALSE, 0);
1278     gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
1279     gtk_container_add (GTK_CONTAINER (frame_horz), vbox);
1280     
1281     gtk_box_pack_start (GTK_BOX (vbox), 
1282                         create_bbox (TRUE, "Spread", 40, 85, 20, GTK_BUTTONBOX_SPREAD),
1283                         TRUE, TRUE, 0);
1284     
1285     gtk_box_pack_start (GTK_BOX (vbox), 
1286                         create_bbox (TRUE, "Edge", 40, 85, 20, GTK_BUTTONBOX_EDGE),
1287                         TRUE, TRUE, 5);
1288     
1289     gtk_box_pack_start (GTK_BOX (vbox), 
1290                         create_bbox (TRUE, "Start", 40, 85, 20, GTK_BUTTONBOX_START),
1291                         TRUE, TRUE, 5);
1292     
1293     gtk_box_pack_start (GTK_BOX (vbox), 
1294                         create_bbox (TRUE, "End", 40, 85, 20, GTK_BUTTONBOX_END),
1295                         TRUE, TRUE, 5);
1296     
1297     gtk_box_pack_start (GTK_BOX (vbox),
1298                         create_bbox (TRUE, "Center", 40, 85, 20, GTK_BUTTONBOX_CENTER),
1299                         TRUE, TRUE, 5);
1300     
1301     frame_vert = gtk_frame_new ("Vertical Button Boxes");
1302     gtk_box_pack_start (GTK_BOX (main_vbox), frame_vert, TRUE, TRUE, 10);
1303     
1304     hbox = gtk_hbox_new (FALSE, 0);
1305     gtk_container_set_border_width (GTK_CONTAINER (hbox), 10);
1306     gtk_container_add (GTK_CONTAINER (frame_vert), hbox);
1307
1308     gtk_box_pack_start (GTK_BOX (hbox), 
1309                         create_bbox (FALSE, "Spread", 30, 85, 20, GTK_BUTTONBOX_SPREAD),
1310                         TRUE, TRUE, 0);
1311     
1312     gtk_box_pack_start (GTK_BOX (hbox), 
1313                         create_bbox (FALSE, "Edge", 30, 85, 20, GTK_BUTTONBOX_EDGE),
1314                         TRUE, TRUE, 5);
1315     
1316     gtk_box_pack_start (GTK_BOX (hbox), 
1317                         create_bbox (FALSE, "Start", 30, 85, 20, GTK_BUTTONBOX_START),
1318                         TRUE, TRUE, 5);
1319     
1320     gtk_box_pack_start (GTK_BOX (hbox), 
1321                         create_bbox (FALSE, "End", 30, 85, 20, GTK_BUTTONBOX_END),
1322                         TRUE, TRUE, 5);
1323     
1324     gtk_box_pack_start (GTK_BOX (hbox),
1325                         create_bbox (FALSE, "Center", 30, 85, 20, GTK_BUTTONBOX_CENTER),
1326                         TRUE, TRUE, 5);
1327   }
1328
1329   if (!GTK_WIDGET_VISIBLE (window))
1330     gtk_widget_show_all (window);
1331   else
1332     gtk_widget_destroy (window);
1333 }
1334
1335 /*
1336  * GtkToolBar
1337  */
1338
1339 static GtkWidget*
1340 new_pixmap (char      *filename,
1341             GdkWindow *window,
1342             GdkColor  *background)
1343 {
1344   GtkWidget *wpixmap;
1345   GdkPixmap *pixmap;
1346   GdkBitmap *mask;
1347
1348   if (strcmp (filename, "test.xpm") == 0 ||
1349       !file_exists (filename))
1350     {
1351       pixmap = gdk_pixmap_create_from_xpm_d (window, &mask,
1352                                              background,
1353                                              openfile);
1354     }
1355   else
1356     pixmap = gdk_pixmap_create_from_xpm (window, &mask,
1357                                          background,
1358                                          filename);
1359   
1360   wpixmap = gtk_image_new_from_pixmap (pixmap, mask);
1361
1362   return wpixmap;
1363 }
1364
1365
1366 static void
1367 set_toolbar_small_stock (GtkWidget *widget,
1368                          gpointer   data)
1369 {
1370   gtk_toolbar_set_icon_size (GTK_TOOLBAR (data), GTK_ICON_SIZE_SMALL_TOOLBAR);
1371 }
1372
1373 static void
1374 set_toolbar_large_stock (GtkWidget *widget,
1375                          gpointer   data)
1376 {
1377   gtk_toolbar_set_icon_size (GTK_TOOLBAR (data), GTK_ICON_SIZE_LARGE_TOOLBAR);
1378 }
1379
1380 static void
1381 set_toolbar_horizontal (GtkWidget *widget,
1382                         gpointer   data)
1383 {
1384   gtk_toolbar_set_orientation (GTK_TOOLBAR (data), GTK_ORIENTATION_HORIZONTAL);
1385 }
1386
1387 static void
1388 set_toolbar_vertical (GtkWidget *widget,
1389                       gpointer   data)
1390 {
1391   gtk_toolbar_set_orientation (GTK_TOOLBAR (data), GTK_ORIENTATION_VERTICAL);
1392 }
1393
1394 static void
1395 set_toolbar_icons (GtkWidget *widget,
1396                    gpointer   data)
1397 {
1398   gtk_toolbar_set_style (GTK_TOOLBAR (data), GTK_TOOLBAR_ICONS);
1399 }
1400
1401 static void
1402 set_toolbar_text (GtkWidget *widget,
1403                   gpointer   data)
1404 {
1405   gtk_toolbar_set_style (GTK_TOOLBAR (data), GTK_TOOLBAR_TEXT);
1406 }
1407
1408 static void
1409 set_toolbar_both (GtkWidget *widget,
1410                   gpointer   data)
1411 {
1412   gtk_toolbar_set_style (GTK_TOOLBAR (data), GTK_TOOLBAR_BOTH);
1413 }
1414
1415 static void
1416 set_toolbar_both_horiz (GtkWidget *widget,
1417                         gpointer   data)
1418 {
1419   gtk_toolbar_set_style (GTK_TOOLBAR (data), GTK_TOOLBAR_BOTH_HORIZ);
1420 }
1421
1422 static void
1423 set_toolbar_enable (GtkWidget *widget,
1424                     gpointer   data)
1425 {
1426   gtk_toolbar_set_tooltips (GTK_TOOLBAR (data), TRUE);
1427 }
1428
1429 static void
1430 set_toolbar_disable (GtkWidget *widget,
1431                      gpointer   data)
1432 {
1433   gtk_toolbar_set_tooltips (GTK_TOOLBAR (data), FALSE);
1434 }
1435
1436 static void
1437 create_toolbar (GtkWidget *widget)
1438 {
1439   static GtkWidget *window = NULL;
1440   GtkWidget *toolbar;
1441   GtkWidget *entry;
1442
1443   if (!window)
1444     {
1445       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1446       gtk_window_set_screen (GTK_WINDOW (window),
1447                              gtk_widget_get_screen (widget));
1448       
1449       gtk_window_set_title (GTK_WINDOW (window), "Toolbar test");
1450
1451       g_signal_connect (window, "destroy",
1452                         G_CALLBACK (gtk_widget_destroyed),
1453                         &window);
1454
1455       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
1456       gtk_widget_realize (window);
1457
1458       toolbar = gtk_toolbar_new ();
1459
1460       gtk_toolbar_insert_stock (GTK_TOOLBAR (toolbar),
1461                                 GTK_STOCK_NEW,
1462                                 "Stock icon: New", "Toolbar/New",
1463                                 G_CALLBACK (set_toolbar_small_stock), toolbar, -1);
1464       
1465       gtk_toolbar_insert_stock (GTK_TOOLBAR (toolbar),
1466                                 GTK_STOCK_OPEN,
1467                                 "Stock icon: Open", "Toolbar/Open",
1468                                 G_CALLBACK (set_toolbar_large_stock), toolbar, -1);
1469       
1470       gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
1471                                "Horizontal", "Horizontal toolbar layout", "Toolbar/Horizontal",
1472                                new_pixmap ("test.xpm", window->window, &window->style->bg[GTK_STATE_NORMAL]),
1473                                G_CALLBACK (set_toolbar_horizontal), toolbar);
1474       gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
1475                                "Vertical", "Vertical toolbar layout", "Toolbar/Vertical",
1476                                new_pixmap ("test.xpm", window->window, &window->style->bg[GTK_STATE_NORMAL]),
1477                                G_CALLBACK (set_toolbar_vertical), toolbar);
1478
1479       gtk_toolbar_append_space (GTK_TOOLBAR(toolbar));
1480
1481       gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
1482                                "Icons", "Only show toolbar icons", "Toolbar/IconsOnly",
1483                                new_pixmap ("test.xpm", window->window, &window->style->bg[GTK_STATE_NORMAL]),
1484                                G_CALLBACK (set_toolbar_icons), toolbar);
1485       gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
1486                                "Text", "Only show toolbar text", "Toolbar/TextOnly",
1487                                new_pixmap ("test.xpm", window->window, &window->style->bg[GTK_STATE_NORMAL]),
1488                                G_CALLBACK (set_toolbar_text), toolbar);
1489       gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
1490                                "Both", "Show toolbar icons and text", "Toolbar/Both",
1491                                new_pixmap ("test.xpm", window->window, &window->style->bg[GTK_STATE_NORMAL]),
1492                                G_CALLBACK (set_toolbar_both), toolbar);
1493       gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
1494                                "Both (horizontal)",
1495                                "Show toolbar icons and text in a horizontal fashion",
1496                                "Toolbar/BothHoriz",
1497                                new_pixmap ("test.xpm", window->window, &window->style->bg[GTK_STATE_NORMAL]),
1498                                G_CALLBACK (set_toolbar_both_horiz), toolbar);
1499                                
1500       gtk_toolbar_append_space (GTK_TOOLBAR (toolbar));
1501
1502       entry = gtk_entry_new ();
1503
1504       gtk_toolbar_append_widget (GTK_TOOLBAR (toolbar), entry, "This is an unusable GtkEntry ;)", "Hey don't click me!!!");
1505
1506       gtk_toolbar_append_space (GTK_TOOLBAR (toolbar));
1507
1508
1509       gtk_toolbar_append_space (GTK_TOOLBAR (toolbar));
1510
1511       gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
1512                                "Enable", "Enable tooltips", NULL,
1513                                new_pixmap ("test.xpm", window->window, &window->style->bg[GTK_STATE_NORMAL]),
1514                                G_CALLBACK (set_toolbar_enable), toolbar);
1515       gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
1516                                "Disable", "Disable tooltips", NULL,
1517                                new_pixmap ("test.xpm", window->window, &window->style->bg[GTK_STATE_NORMAL]),
1518                                G_CALLBACK (set_toolbar_disable), toolbar);
1519
1520       gtk_toolbar_append_space (GTK_TOOLBAR (toolbar));
1521
1522       gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
1523                                "Frobate", "Frobate tooltip", NULL,
1524                                new_pixmap ("test.xpm", window->window, &window->style->bg[GTK_STATE_NORMAL]),
1525                                NULL, toolbar);
1526       gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
1527                                "Baz", "Baz tooltip", NULL,
1528                                new_pixmap ("test.xpm", window->window, &window->style->bg[GTK_STATE_NORMAL]),
1529                                NULL, toolbar);
1530
1531       gtk_toolbar_append_space (GTK_TOOLBAR (toolbar));
1532       
1533       gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
1534                                "Blah", "Blah tooltip", NULL,
1535                                new_pixmap ("test.xpm", window->window, &window->style->bg[GTK_STATE_NORMAL]),
1536                                NULL, toolbar);
1537       gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
1538                                "Bar", "Bar tooltip", NULL,
1539                                new_pixmap ("test.xpm", window->window, &window->style->bg[GTK_STATE_NORMAL]),
1540                                NULL, toolbar);
1541
1542       gtk_container_add (GTK_CONTAINER (window), toolbar);
1543
1544       gtk_widget_set_size_request (toolbar, 200, -1);
1545     }
1546
1547   if (!GTK_WIDGET_VISIBLE (window))
1548     gtk_widget_show_all (window);
1549   else
1550     gtk_widget_destroy (window);
1551 }
1552
1553 static GtkWidget*
1554 make_toolbar (GtkWidget *window)
1555 {
1556   GtkWidget *toolbar;
1557
1558   if (!GTK_WIDGET_REALIZED (window))
1559     gtk_widget_realize (window);
1560
1561   toolbar = gtk_toolbar_new ();
1562
1563   gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
1564                            "Horizontal", "Horizontal toolbar layout", NULL,
1565                            new_pixmap ("test.xpm", window->window, &window->style->bg[GTK_STATE_NORMAL]),
1566                            G_CALLBACK (set_toolbar_horizontal), toolbar);
1567   gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
1568                            "Vertical", "Vertical toolbar layout", NULL,
1569                            new_pixmap ("test.xpm", window->window, &window->style->bg[GTK_STATE_NORMAL]),
1570                            G_CALLBACK (set_toolbar_vertical), toolbar);
1571
1572   gtk_toolbar_append_space (GTK_TOOLBAR(toolbar));
1573
1574   gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
1575                            "Icons", "Only show toolbar icons", NULL,
1576                            new_pixmap ("test.xpm", window->window, &window->style->bg[GTK_STATE_NORMAL]),
1577                            G_CALLBACK (set_toolbar_icons), toolbar);
1578   gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
1579                            "Text", "Only show toolbar text", NULL,
1580                            new_pixmap ("test.xpm", window->window, &window->style->bg[GTK_STATE_NORMAL]),
1581                            G_CALLBACK (set_toolbar_text), toolbar);
1582   gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
1583                            "Both", "Show toolbar icons and text", NULL,
1584                            new_pixmap ("test.xpm", window->window, &window->style->bg[GTK_STATE_NORMAL]),
1585                            G_CALLBACK (set_toolbar_both), toolbar);
1586
1587   gtk_toolbar_append_space (GTK_TOOLBAR (toolbar));
1588
1589   gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
1590                            "Woot", "Woot woot woot", NULL,
1591                            new_pixmap ("test.xpm", window->window, &window->style->bg[GTK_STATE_NORMAL]),
1592                            NULL, toolbar);
1593   gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
1594                            "Blah", "Blah blah blah", "Toolbar/Big",
1595                            new_pixmap ("test.xpm", window->window, &window->style->bg[GTK_STATE_NORMAL]),
1596                            NULL, toolbar);
1597
1598   gtk_toolbar_append_space (GTK_TOOLBAR (toolbar));
1599
1600   gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
1601                            "Enable", "Enable tooltips", NULL,
1602                            new_pixmap ("test.xpm", window->window, &window->style->bg[GTK_STATE_NORMAL]),
1603                            G_CALLBACK (set_toolbar_enable), toolbar);
1604   gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
1605                            "Disable", "Disable tooltips", NULL,
1606                            new_pixmap ("test.xpm", window->window, &window->style->bg[GTK_STATE_NORMAL]),
1607                            G_CALLBACK (set_toolbar_disable), toolbar);
1608
1609   gtk_toolbar_append_space (GTK_TOOLBAR (toolbar));
1610   
1611   gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
1612                            "Hoo", "Hoo tooltip", NULL,
1613                            new_pixmap ("test.xpm", window->window, &window->style->bg[GTK_STATE_NORMAL]),
1614                            NULL, toolbar);
1615   gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
1616                            "Woo", "Woo tooltip", NULL,
1617                            new_pixmap ("test.xpm", window->window, &window->style->bg[GTK_STATE_NORMAL]),
1618                            NULL, toolbar);
1619
1620   return toolbar;
1621 }
1622
1623 /*
1624  * GtkStatusBar
1625  */
1626
1627 static guint statusbar_counter = 1;
1628
1629 static void
1630 statusbar_push (GtkWidget *button,
1631                 GtkStatusbar *statusbar)
1632 {
1633   gchar text[1024];
1634
1635   sprintf (text, "something %d", statusbar_counter++);
1636
1637   gtk_statusbar_push (statusbar, 1, text);
1638 }
1639
1640 static void
1641 statusbar_push_long (GtkWidget *button,
1642                      GtkStatusbar *statusbar)
1643 {
1644   gchar text[1024];
1645
1646   sprintf (text, "Just because a system has menu choices written with English words, phrases or sentences, that is no guarantee, that it is comprehensible. Individual words may not be familiar to some users (for example, \"repaginate\"), and two menu items may appear to satisfy the users's needs, whereas only one does (for example, \"put away\" or \"eject\").");
1647
1648   gtk_statusbar_push (statusbar, 1, text);
1649 }
1650
1651 static void
1652 statusbar_pop (GtkWidget *button,
1653                GtkStatusbar *statusbar)
1654 {
1655   gtk_statusbar_pop (statusbar, 1);
1656 }
1657
1658 static void
1659 statusbar_steal (GtkWidget *button,
1660                  GtkStatusbar *statusbar)
1661 {
1662   gtk_statusbar_remove (statusbar, 1, 4);
1663 }
1664
1665 static void
1666 statusbar_popped (GtkStatusbar  *statusbar,
1667                   guint          context_id,
1668                   const gchar   *text)
1669 {
1670   if (!statusbar->messages)
1671     statusbar_counter = 1;
1672 }
1673
1674 static void
1675 statusbar_contexts (GtkStatusbar *statusbar)
1676 {
1677   gchar *string;
1678
1679   string = "any context";
1680   g_print ("GtkStatusBar: context=\"%s\", context_id=%d\n",
1681            string,
1682            gtk_statusbar_get_context_id (statusbar, string));
1683   
1684   string = "idle messages";
1685   g_print ("GtkStatusBar: context=\"%s\", context_id=%d\n",
1686            string,
1687            gtk_statusbar_get_context_id (statusbar, string));
1688   
1689   string = "some text";
1690   g_print ("GtkStatusBar: context=\"%s\", context_id=%d\n",
1691            string,
1692            gtk_statusbar_get_context_id (statusbar, string));
1693
1694   string = "hit the mouse";
1695   g_print ("GtkStatusBar: context=\"%s\", context_id=%d\n",
1696            string,
1697            gtk_statusbar_get_context_id (statusbar, string));
1698
1699   string = "hit the mouse2";
1700   g_print ("GtkStatusBar: context=\"%s\", context_id=%d\n",
1701            string,
1702            gtk_statusbar_get_context_id (statusbar, string));
1703 }
1704
1705 static void
1706 create_statusbar (GtkWidget *widget)
1707 {
1708   static GtkWidget *window = NULL;
1709   GtkWidget *box1;
1710   GtkWidget *box2;
1711   GtkWidget *button;
1712   GtkWidget *separator;
1713   GtkWidget *statusbar;
1714
1715   if (!window)
1716     {
1717       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1718       gtk_window_set_screen (GTK_WINDOW (window),
1719                              gtk_widget_get_screen (widget));
1720
1721       g_signal_connect (window, "destroy",
1722                         G_CALLBACK (gtk_widget_destroyed),
1723                         &window);
1724
1725       gtk_window_set_title (GTK_WINDOW (window), "statusbar");
1726       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
1727
1728       box1 = gtk_vbox_new (FALSE, 0);
1729       gtk_container_add (GTK_CONTAINER (window), box1);
1730
1731       box2 = gtk_vbox_new (FALSE, 10);
1732       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
1733       gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
1734
1735       statusbar = gtk_statusbar_new ();
1736       gtk_box_pack_end (GTK_BOX (box1), statusbar, TRUE, TRUE, 0);
1737       g_signal_connect (statusbar,
1738                         "text_popped",
1739                         G_CALLBACK (statusbar_popped),
1740                         NULL);
1741
1742       button = g_object_new (gtk_button_get_type (),
1743                                "label", "push something",
1744                                "visible", TRUE,
1745                                "parent", box2,
1746                                NULL);
1747       g_object_connect (button,
1748                         "signal::clicked", statusbar_push, statusbar,
1749                         NULL);
1750
1751       button = g_object_connect (g_object_new (gtk_button_get_type (),
1752                                                  "label", "pop",
1753                                                  "visible", TRUE,
1754                                                  "parent", box2,
1755                                                  NULL),
1756                                  "signal_after::clicked", statusbar_pop, statusbar,
1757                                  NULL);
1758
1759       button = g_object_connect (g_object_new (gtk_button_get_type (),
1760                                                  "label", "steal #4",
1761                                                  "visible", TRUE,
1762                                                  "parent", box2,
1763                                                  NULL),
1764                                  "signal_after::clicked", statusbar_steal, statusbar,
1765                                  NULL);
1766
1767       button = g_object_connect (g_object_new (gtk_button_get_type (),
1768                                                  "label", "test contexts",
1769                                                  "visible", TRUE,
1770                                                  "parent", box2,
1771                                                  NULL),
1772                                  "swapped_signal_after::clicked", statusbar_contexts, statusbar,
1773                                  NULL);
1774
1775       button = g_object_connect (g_object_new (gtk_button_get_type (),
1776                                                  "label", "push something long",
1777                                                  "visible", TRUE,
1778                                                  "parent", box2,
1779                                                  NULL),
1780                                  "signal_after::clicked", statusbar_push_long, statusbar,
1781                                  NULL);
1782       
1783       separator = gtk_hseparator_new ();
1784       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
1785
1786       box2 = gtk_vbox_new (FALSE, 10);
1787       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
1788       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
1789
1790       button = gtk_button_new_with_label ("close");
1791       g_signal_connect_swapped (button, "clicked",
1792                                 G_CALLBACK (gtk_widget_destroy),
1793                                 window);
1794       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
1795       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
1796       gtk_widget_grab_default (button);
1797     }
1798
1799   if (!GTK_WIDGET_VISIBLE (window))
1800     gtk_widget_show_all (window);
1801   else
1802     gtk_widget_destroy (window);
1803 }
1804
1805 /*
1806  * GtkTree
1807  */
1808
1809 static void
1810 cb_tree_destroy_event(GtkWidget* w)
1811 {
1812   sTreeButtons* tree_buttons;
1813
1814   /* free buttons structure associate at this tree */
1815   tree_buttons = g_object_get_data (G_OBJECT (w), "user_data");
1816   g_free (tree_buttons);
1817 }
1818
1819 static void
1820 cb_add_new_item(GtkWidget* w, GtkTree* tree)
1821 {
1822   sTreeButtons* tree_buttons;
1823   GList* selected_list;
1824   GtkWidget* selected_item;
1825   GtkWidget* subtree;
1826   GtkWidget* item_new;
1827   char buffer[255];
1828
1829   tree_buttons = g_object_get_data (G_OBJECT (tree), "user_data");
1830
1831   selected_list = GTK_TREE_SELECTION_OLD(tree);
1832
1833   if(selected_list == NULL)
1834     {
1835       /* there is no item in tree */
1836       subtree = GTK_WIDGET(tree);
1837     }
1838   else
1839     {
1840       /* list can have only one element */
1841       selected_item = GTK_WIDGET(selected_list->data);
1842       
1843       subtree = GTK_TREE_ITEM_SUBTREE(selected_item);
1844
1845       if(subtree == NULL)
1846         {
1847           /* current selected item have not subtree ... create it */
1848           subtree = gtk_tree_new();
1849           gtk_tree_item_set_subtree(GTK_TREE_ITEM(selected_item), 
1850                                     subtree);
1851         }
1852     }
1853
1854   /* at this point, we know which subtree will be used to add new item */
1855   /* create a new item */
1856   sprintf(buffer, "item add %d", tree_buttons->nb_item_add);
1857   item_new = gtk_tree_item_new_with_label(buffer);
1858   gtk_tree_append(GTK_TREE(subtree), item_new);
1859   gtk_widget_show(item_new);
1860
1861   tree_buttons->nb_item_add++;
1862 }
1863
1864 static void
1865 cb_remove_item(GtkWidget*w, GtkTree* tree)
1866 {
1867   GList* selected_list;
1868   GList* clear_list;
1869   
1870   selected_list = GTK_TREE_SELECTION_OLD(tree);
1871
1872   clear_list = NULL;
1873     
1874   while (selected_list) 
1875     {
1876       clear_list = g_list_prepend (clear_list, selected_list->data);
1877       selected_list = selected_list->next;
1878     }
1879   
1880   clear_list = g_list_reverse (clear_list);
1881   gtk_tree_remove_items(tree, clear_list);
1882
1883   g_list_free (clear_list);
1884 }
1885
1886 static void
1887 cb_remove_subtree(GtkWidget*w, GtkTree* tree)
1888 {
1889   GList* selected_list;
1890   GtkTreeItem *item;
1891   
1892   selected_list = GTK_TREE_SELECTION_OLD(tree);
1893
1894   if (selected_list)
1895     {
1896       item = GTK_TREE_ITEM (selected_list->data);
1897       if (item->subtree)
1898         gtk_tree_item_remove_subtree (item);
1899     }
1900 }
1901
1902 static void
1903 cb_tree_changed(GtkTree* tree)
1904 {
1905   sTreeButtons* tree_buttons;
1906   GList* selected_list;
1907   guint nb_selected;
1908
1909   tree_buttons = g_object_get_data (G_OBJECT (tree), "user_data");
1910
1911   selected_list = GTK_TREE_SELECTION_OLD(tree);
1912   nb_selected = g_list_length(selected_list);
1913
1914   if(nb_selected == 0) 
1915     {
1916       if(tree->children == NULL)
1917         gtk_widget_set_sensitive(tree_buttons->add_button, TRUE);
1918       else
1919         gtk_widget_set_sensitive(tree_buttons->add_button, FALSE);
1920       gtk_widget_set_sensitive(tree_buttons->remove_button, FALSE);
1921       gtk_widget_set_sensitive(tree_buttons->subtree_button, FALSE);
1922     } 
1923   else 
1924     {
1925       gtk_widget_set_sensitive(tree_buttons->remove_button, TRUE);
1926       gtk_widget_set_sensitive(tree_buttons->add_button, (nb_selected == 1));
1927       gtk_widget_set_sensitive(tree_buttons->subtree_button, (nb_selected == 1));
1928     }  
1929 }
1930
1931 static void 
1932 create_subtree(GtkWidget* item, guint level, guint nb_item_max, guint recursion_level_max)
1933 {
1934   GtkWidget* item_subtree;
1935   GtkWidget* item_new;
1936   guint nb_item;
1937   char buffer[255];
1938   int no_root_item;
1939
1940   if(level == recursion_level_max) return;
1941
1942   if(level == -1)
1943     {
1944       /* query with no root item */
1945       level = 0;
1946       item_subtree = item;
1947       no_root_item = 1;
1948     }
1949   else
1950     {
1951       /* query with no root item */
1952       /* create subtree and associate it with current item */
1953       item_subtree = gtk_tree_new();
1954       no_root_item = 0;
1955     }
1956   
1957   for(nb_item = 0; nb_item < nb_item_max; nb_item++)
1958     {
1959       sprintf(buffer, "item %d-%d", level, nb_item);
1960       item_new = gtk_tree_item_new_with_label(buffer);
1961       gtk_tree_append(GTK_TREE(item_subtree), item_new);
1962       create_subtree(item_new, level+1, nb_item_max, recursion_level_max);
1963       gtk_widget_show(item_new);
1964     }
1965
1966   if(!no_root_item)
1967     gtk_tree_item_set_subtree(GTK_TREE_ITEM(item), item_subtree);
1968 }
1969
1970 static void
1971 create_tree_sample(GdkScreen *screen, guint selection_mode, 
1972                    guint draw_line, guint view_line, guint no_root_item,
1973                    guint nb_item_max, guint recursion_level_max) 
1974 {
1975   GtkWidget* window;
1976   GtkWidget* box1;
1977   GtkWidget* box2;
1978   GtkWidget* separator;
1979   GtkWidget* button;
1980   GtkWidget* scrolled_win;
1981   GtkWidget* root_tree;
1982   GtkWidget* root_item;
1983   sTreeButtons* tree_buttons;
1984
1985   /* create tree buttons struct */
1986   if ((tree_buttons = g_malloc (sizeof (sTreeButtons))) == NULL)
1987     {
1988       g_error("can't allocate memory for tree structure !\n");
1989       return;
1990     }
1991   tree_buttons->nb_item_add = 0;
1992
1993   /* create top level window */
1994   window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
1995   gtk_window_set_screen (GTK_WINDOW (window), screen);
1996   gtk_window_set_title(GTK_WINDOW(window), "Tree Sample");
1997   g_signal_connect (window, "destroy",
1998                     G_CALLBACK (cb_tree_destroy_event), NULL);
1999   g_object_set_data (G_OBJECT (window), "user_data", tree_buttons);
2000
2001   box1 = gtk_vbox_new(FALSE, 0);
2002   gtk_container_add(GTK_CONTAINER(window), box1);
2003   gtk_widget_show(box1);
2004
2005   /* create tree box */
2006   box2 = gtk_vbox_new(FALSE, 0);
2007   gtk_box_pack_start(GTK_BOX(box1), box2, TRUE, TRUE, 0);
2008   gtk_container_set_border_width(GTK_CONTAINER(box2), 5);
2009   gtk_widget_show(box2);
2010
2011   /* create scrolled window */
2012   scrolled_win = gtk_scrolled_window_new (NULL, NULL);
2013   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
2014                                   GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
2015   gtk_box_pack_start (GTK_BOX (box2), scrolled_win, TRUE, TRUE, 0);
2016   gtk_widget_set_size_request (scrolled_win, 200, 200);
2017   gtk_widget_show (scrolled_win);
2018   
2019   /* create root tree widget */
2020   root_tree = gtk_tree_new();
2021   g_signal_connect (root_tree, "selection_changed",
2022                     G_CALLBACK (cb_tree_changed),
2023                     NULL);
2024   g_object_set_data (G_OBJECT (root_tree), "user_data", tree_buttons);
2025   gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_win), root_tree);
2026   gtk_tree_set_selection_mode(GTK_TREE(root_tree), selection_mode);
2027   gtk_tree_set_view_lines(GTK_TREE(root_tree), draw_line);
2028   gtk_tree_set_view_mode(GTK_TREE(root_tree), !view_line);
2029   gtk_widget_show(root_tree);
2030
2031   if ( no_root_item )
2032     {
2033       /* set root tree to subtree function with root item variable */
2034       root_item = GTK_WIDGET(root_tree);
2035     }
2036   else
2037     {
2038       /* create root tree item widget */
2039       root_item = gtk_tree_item_new_with_label("root item");
2040       gtk_tree_append(GTK_TREE(root_tree), root_item);
2041       gtk_widget_show(root_item);
2042      }
2043   create_subtree(root_item, -no_root_item, nb_item_max, recursion_level_max);
2044
2045   box2 = gtk_vbox_new(FALSE, 0);
2046   gtk_box_pack_start(GTK_BOX(box1), box2, FALSE, FALSE, 0);
2047   gtk_container_set_border_width(GTK_CONTAINER(box2), 5);
2048   gtk_widget_show(box2);
2049
2050   button = gtk_button_new_with_label("Add Item");
2051   gtk_widget_set_sensitive(button, FALSE);
2052   g_signal_connect (button, "clicked",
2053                     G_CALLBACK (cb_add_new_item),
2054                     root_tree);
2055   gtk_box_pack_start(GTK_BOX(box2), button, TRUE, TRUE, 0);
2056   gtk_widget_show(button);
2057   tree_buttons->add_button = button;
2058
2059   button = gtk_button_new_with_label("Remove Item(s)");
2060   gtk_widget_set_sensitive(button, FALSE);
2061   g_signal_connect (button, "clicked",
2062                     G_CALLBACK (cb_remove_item),
2063                     root_tree);
2064   gtk_box_pack_start(GTK_BOX(box2), button, TRUE, TRUE, 0);
2065   gtk_widget_show(button);
2066   tree_buttons->remove_button = button;
2067
2068   button = gtk_button_new_with_label("Remove Subtree");
2069   gtk_widget_set_sensitive(button, FALSE);
2070   g_signal_connect (button, "clicked",
2071                     G_CALLBACK (cb_remove_subtree),
2072                     root_tree);
2073   gtk_box_pack_start(GTK_BOX(box2), button, TRUE, TRUE, 0);
2074   gtk_widget_show(button);
2075   tree_buttons->subtree_button = button;
2076
2077   /* create separator */
2078   separator = gtk_hseparator_new();
2079   gtk_box_pack_start(GTK_BOX(box1), separator, FALSE, FALSE, 0);
2080   gtk_widget_show(separator);
2081
2082   /* create button box */
2083   box2 = gtk_vbox_new(FALSE, 0);
2084   gtk_box_pack_start(GTK_BOX(box1), box2, FALSE, FALSE, 0);
2085   gtk_container_set_border_width(GTK_CONTAINER(box2), 5);
2086   gtk_widget_show(box2);
2087
2088   button = gtk_button_new_with_label("Close");
2089   gtk_box_pack_start(GTK_BOX(box2), button, TRUE, TRUE, 0);
2090   g_signal_connect_swapped (button, "clicked",
2091                             G_CALLBACK (gtk_widget_destroy),
2092                             window);
2093   gtk_widget_show(button);
2094
2095   gtk_widget_show(window);
2096 }
2097
2098 static void
2099 cb_create_tree(GtkWidget* w)
2100 {
2101   guint selection_mode = GTK_SELECTION_SINGLE;
2102   guint view_line;
2103   guint draw_line;
2104   guint no_root_item;
2105   guint nb_item;
2106   guint recursion_level;
2107
2108   /* get selection mode choice */
2109   if(GTK_TOGGLE_BUTTON(sTreeSampleSelection.single_button)->active)
2110     selection_mode = GTK_SELECTION_SINGLE;
2111   else
2112     if(GTK_TOGGLE_BUTTON(sTreeSampleSelection.browse_button)->active)
2113       selection_mode = GTK_SELECTION_BROWSE;
2114     else
2115       selection_mode = GTK_SELECTION_MULTIPLE;
2116
2117   /* get options choice */
2118   draw_line = GTK_TOGGLE_BUTTON(sTreeSampleSelection.draw_line_button)->active;
2119   view_line = GTK_TOGGLE_BUTTON(sTreeSampleSelection.view_line_button)->active;
2120   no_root_item = GTK_TOGGLE_BUTTON(sTreeSampleSelection.no_root_item_button)->active;
2121     
2122   /* get levels */
2123   nb_item = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(sTreeSampleSelection.nb_item_spinner));
2124   recursion_level = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(sTreeSampleSelection.recursion_spinner));
2125
2126   if (pow (nb_item, recursion_level) > 10000)
2127     {
2128       g_print ("%g total items? That will take a very long time. Try less\n",
2129                pow (nb_item, recursion_level));
2130       return;
2131     }
2132
2133   create_tree_sample(gtk_widget_get_screen (w),
2134                      selection_mode, draw_line, 
2135                      view_line, no_root_item, nb_item, recursion_level);
2136 }
2137
2138 void 
2139 create_tree_mode_window(GtkWidget *widget)
2140 {
2141   static GtkWidget* window;
2142   GtkWidget* box1;
2143   GtkWidget* box2;
2144   GtkWidget* box3;
2145   GtkWidget* box4;
2146   GtkWidget* box5;
2147   GtkWidget* button;
2148   GtkWidget* frame;
2149   GtkWidget* separator;
2150   GtkWidget* label;
2151   GtkWidget* spinner;
2152   GtkAdjustment *adj;
2153
2154   if (!window)
2155     {
2156       /* create toplevel window  */
2157       window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
2158       gtk_window_set_screen (GTK_WINDOW (window),
2159                              gtk_widget_get_screen (widget));
2160       gtk_window_set_title(GTK_WINDOW(window), "Set Tree Parameters");
2161       g_signal_connect (window, "destroy",
2162                         G_CALLBACK (gtk_widget_destroyed),
2163                         &window);
2164       box1 = gtk_vbox_new(FALSE, 0);
2165       gtk_container_add(GTK_CONTAINER(window), box1);
2166
2167       /* create upper box - selection box */
2168       box2 = gtk_vbox_new(FALSE, 5);
2169       gtk_box_pack_start(GTK_BOX(box1), box2, TRUE, TRUE, 0);
2170       gtk_container_set_border_width(GTK_CONTAINER(box2), 5);
2171
2172       box3 = gtk_hbox_new(FALSE, 5);
2173       gtk_box_pack_start(GTK_BOX(box2), box3, TRUE, TRUE, 0);
2174
2175       /* create selection mode frame */
2176       frame = gtk_frame_new("Selection Mode");
2177       gtk_box_pack_start(GTK_BOX(box3), frame, TRUE, TRUE, 0);
2178
2179       box4 = gtk_vbox_new(FALSE, 0);
2180       gtk_container_add(GTK_CONTAINER(frame), box4);
2181       gtk_container_set_border_width(GTK_CONTAINER(box4), 5);
2182
2183       /* create radio button */  
2184       button = gtk_radio_button_new_with_label(NULL, "SINGLE");
2185       gtk_box_pack_start(GTK_BOX(box4), button, TRUE, TRUE, 0);
2186       sTreeSampleSelection.single_button = button;
2187
2188       button = gtk_radio_button_new_with_label(gtk_radio_button_get_group (GTK_RADIO_BUTTON (button)),
2189                                                "BROWSE");
2190       gtk_box_pack_start(GTK_BOX(box4), button, TRUE, TRUE, 0);
2191       sTreeSampleSelection.browse_button = button;
2192
2193       button = gtk_radio_button_new_with_label(gtk_radio_button_get_group (GTK_RADIO_BUTTON (button)),
2194                                                "MULTIPLE");
2195       gtk_box_pack_start(GTK_BOX(box4), button, TRUE, TRUE, 0);
2196       sTreeSampleSelection.multiple_button = button;
2197
2198       sTreeSampleSelection.selection_mode_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (button));
2199
2200       /* create option mode frame */
2201       frame = gtk_frame_new("Options");
2202       gtk_box_pack_start(GTK_BOX(box3), frame, TRUE, TRUE, 0);
2203
2204       box4 = gtk_vbox_new(FALSE, 0);
2205       gtk_container_add(GTK_CONTAINER(frame), box4);
2206       gtk_container_set_border_width(GTK_CONTAINER(box4), 5);
2207
2208       /* create check button */
2209       button = gtk_check_button_new_with_label("Draw line");
2210       gtk_box_pack_start(GTK_BOX(box4), button, TRUE, TRUE, 0);
2211       gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
2212       sTreeSampleSelection.draw_line_button = button;
2213   
2214       button = gtk_check_button_new_with_label("View Line mode");
2215       gtk_box_pack_start(GTK_BOX(box4), button, TRUE, TRUE, 0);
2216       gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
2217       sTreeSampleSelection.view_line_button = button;
2218   
2219       button = gtk_check_button_new_with_label("Without Root item");
2220       gtk_box_pack_start(GTK_BOX(box4), button, TRUE, TRUE, 0);
2221       sTreeSampleSelection.no_root_item_button = button;
2222
2223       /* create recursion parameter */
2224       frame = gtk_frame_new("Size Parameters");
2225       gtk_box_pack_start(GTK_BOX(box2), frame, TRUE, TRUE, 0);
2226
2227       box4 = gtk_hbox_new(FALSE, 5);
2228       gtk_container_add(GTK_CONTAINER(frame), box4);
2229       gtk_container_set_border_width(GTK_CONTAINER(box4), 5);
2230
2231       /* create number of item spin button */
2232       box5 = gtk_hbox_new(FALSE, 5);
2233       gtk_box_pack_start(GTK_BOX(box4), box5, FALSE, FALSE, 0);
2234
2235       label = gtk_label_new("Number of items : ");
2236       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
2237       gtk_box_pack_start (GTK_BOX (box5), label, FALSE, TRUE, 0);
2238
2239       adj = (GtkAdjustment *) gtk_adjustment_new (DEFAULT_NUMBER_OF_ITEM, 1.0, 255.0, 1.0,
2240                                                   5.0, 0.0);
2241       spinner = gtk_spin_button_new (adj, 0, 0);
2242       gtk_box_pack_start (GTK_BOX (box5), spinner, FALSE, TRUE, 0);
2243       sTreeSampleSelection.nb_item_spinner = spinner;
2244   
2245       /* create recursion level spin button */
2246       box5 = gtk_hbox_new(FALSE, 5);
2247       gtk_box_pack_start(GTK_BOX(box4), box5, FALSE, FALSE, 0);
2248
2249       label = gtk_label_new("Depth : ");
2250       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
2251       gtk_box_pack_start (GTK_BOX (box5), label, FALSE, TRUE, 0);
2252
2253       adj = (GtkAdjustment *) gtk_adjustment_new (DEFAULT_RECURSION_LEVEL, 0.0, 255.0, 1.0,
2254                                                   5.0, 0.0);
2255       spinner = gtk_spin_button_new (adj, 0, 0);
2256       gtk_box_pack_start (GTK_BOX (box5), spinner, FALSE, TRUE, 0);
2257       sTreeSampleSelection.recursion_spinner = spinner;
2258   
2259       /* create horizontal separator */
2260       separator = gtk_hseparator_new();
2261       gtk_box_pack_start(GTK_BOX(box1), separator, FALSE, FALSE, 0);
2262
2263       /* create bottom button box */
2264       box2 = gtk_hbox_new(TRUE, 10);
2265       gtk_box_pack_start(GTK_BOX(box1), box2, FALSE, FALSE, 0);
2266       gtk_container_set_border_width(GTK_CONTAINER(box2), 5);
2267
2268       button = gtk_button_new_with_label("Create Tree");
2269       gtk_box_pack_start(GTK_BOX(box2), button, TRUE, TRUE, 0);
2270       g_signal_connect (button, "clicked",
2271                         G_CALLBACK (cb_create_tree), NULL);
2272
2273       button = gtk_button_new_with_label("Close");
2274       gtk_box_pack_start(GTK_BOX(box2), button, TRUE, TRUE, 0);
2275       g_signal_connect_swapped (button, "clicked",
2276                                 G_CALLBACK (gtk_widget_destroy),
2277                                 window);
2278     }
2279   if (!GTK_WIDGET_VISIBLE (window))
2280     gtk_widget_show_all (window);
2281   else
2282     gtk_widget_destroy (window);
2283 }
2284
2285 /*
2286  * Gridded geometry
2287  */
2288 #define GRID_SIZE 20
2289 #define DEFAULT_GEOMETRY "10x10"
2290
2291 static gboolean
2292 gridded_geometry_expose (GtkWidget      *widget,
2293                          GdkEventExpose *event)
2294 {
2295   int i, j;
2296
2297   gdk_draw_rectangle (widget->window, widget->style->base_gc[widget->state], TRUE,
2298                       0, 0, widget->allocation.width, widget->allocation.height);
2299   
2300   for (i = 0 ; i * GRID_SIZE < widget->allocation.width; i++)
2301     for (j = 0 ; j * GRID_SIZE < widget->allocation.height; j++)
2302       {
2303         if ((i + j) % 2 == 0)
2304           gdk_draw_rectangle (widget->window, widget->style->text_gc[widget->state], TRUE,
2305                               i * GRID_SIZE, j * GRID_SIZE, GRID_SIZE, GRID_SIZE);
2306       }
2307
2308   return FALSE;
2309 }
2310
2311 static void
2312 gridded_geometry_subresponse (GtkDialog *dialog,
2313                               gint       response_id,
2314                               gchar     *geometry_string)
2315 {
2316   if (response_id == GTK_RESPONSE_NONE)
2317     {
2318       gtk_widget_destroy (GTK_WIDGET (dialog));
2319     }
2320   else
2321     {
2322       if (!gtk_window_parse_geometry (GTK_WINDOW (dialog), geometry_string))
2323         {
2324           g_print ("Can't parse geometry string %s\n", geometry_string);
2325           gtk_window_parse_geometry (GTK_WINDOW (dialog), DEFAULT_GEOMETRY);
2326         }
2327     }
2328 }
2329
2330 static void
2331 gridded_geometry_response (GtkDialog *dialog,
2332                            gint       response_id,
2333                            GtkEntry  *entry)
2334 {
2335   if (response_id == GTK_RESPONSE_NONE)
2336     {
2337       gtk_widget_destroy (GTK_WIDGET (dialog));
2338     }
2339   else
2340     {
2341       gchar *geometry_string = g_strdup (gtk_entry_get_text (entry));
2342       gchar *title = g_strdup_printf ("Gridded window at: %s", geometry_string);
2343       GtkWidget *window;
2344       GtkWidget *drawing_area;
2345       GtkWidget *box;
2346       GdkGeometry geometry;
2347       
2348       window = gtk_dialog_new_with_buttons (title,
2349                                             NULL, 0,
2350                                             "Reset", 1,
2351                                             GTK_STOCK_CLOSE, GTK_RESPONSE_NONE,
2352                                             NULL);
2353
2354       gtk_window_set_screen (GTK_WINDOW (window), 
2355                              gtk_widget_get_screen (GTK_WIDGET (dialog)));
2356       g_free (title);
2357       g_signal_connect (window, "response",
2358                         G_CALLBACK (gridded_geometry_subresponse), geometry_string);
2359
2360       box = gtk_vbox_new (FALSE, 0);
2361       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), box, TRUE, TRUE, 0);
2362       
2363       gtk_container_set_border_width (GTK_CONTAINER (box), 7);
2364       
2365       drawing_area = gtk_drawing_area_new ();
2366       g_signal_connect (drawing_area, "expose_event",
2367                         G_CALLBACK (gridded_geometry_expose), NULL);
2368       gtk_box_pack_start (GTK_BOX (box), drawing_area, TRUE, TRUE, 0);
2369
2370       /* Gross hack to work around bug 68668... if we set the size request
2371        * large enough, then  the current
2372        *
2373        *   request_of_window - request_of_geometry_widget
2374        *
2375        * method of getting the base size works more or less works.
2376        */
2377       gtk_widget_set_size_request (drawing_area, 2000, 2000);
2378
2379       geometry.base_width = 0;
2380       geometry.base_height = 0;
2381       geometry.min_width = 2 * GRID_SIZE;
2382       geometry.min_height = 2 * GRID_SIZE;
2383       geometry.width_inc = GRID_SIZE;
2384       geometry.height_inc = GRID_SIZE;
2385
2386       gtk_window_set_geometry_hints (GTK_WINDOW (window), drawing_area,
2387                                      &geometry,
2388                                      GDK_HINT_BASE_SIZE | GDK_HINT_MIN_SIZE | GDK_HINT_RESIZE_INC);
2389
2390       if (!gtk_window_parse_geometry (GTK_WINDOW (window), geometry_string))
2391         {
2392           g_print ("Can't parse geometry string %s\n", geometry_string);
2393           gtk_window_parse_geometry (GTK_WINDOW (window), DEFAULT_GEOMETRY);
2394         }
2395
2396       gtk_widget_show_all (window);
2397     }
2398 }
2399
2400 static void 
2401 create_gridded_geometry (GtkWidget *widget)
2402 {
2403   static GtkWidget *window = NULL;
2404   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 = g_object_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 (g_object_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         g_object_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 (g_object_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         g_object_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         g_object_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         g_object_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         g_object_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 = g_object_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 = g_type_class_ref (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   g_type_class_unref (class);
6091
6092   cursor = gdk_cursor_new_for_display (gtk_widget_get_display (widget), c);
6093   gdk_window_set_cursor (widget->window, cursor);
6094   gdk_cursor_unref (cursor);
6095 }
6096
6097 static gint
6098 cursor_event (GtkWidget          *widget,
6099               GdkEvent           *event,
6100               GtkSpinButton      *spinner)
6101 {
6102   if ((event->type == GDK_BUTTON_PRESS) &&
6103       ((event->button.button == 1) ||
6104        (event->button.button == 3)))
6105     {
6106       gtk_spin_button_spin (spinner, event->button.button == 1 ?
6107                             GTK_SPIN_STEP_FORWARD : GTK_SPIN_STEP_BACKWARD, 0);
6108       return TRUE;
6109     }
6110
6111   return FALSE;
6112 }
6113
6114 #ifdef GDK_WINDOWING_X11
6115 #include "x11/gdkx.h"
6116
6117 static void
6118 change_cursor_theme (GtkWidget *widget,
6119                      gpointer   data)
6120 {
6121   const gchar *theme;
6122   gint size;
6123   GList *children;
6124
6125   children = gtk_container_get_children (GTK_CONTAINER (data));
6126
6127   theme = gtk_entry_get_text (GTK_ENTRY (children->next->data));
6128   size = (gint) gtk_spin_button_get_value (GTK_SPIN_BUTTON (children->next->next->data));
6129
6130   g_list_free (children);
6131
6132   gdk_x11_display_set_cursor_theme (gtk_widget_get_display (widget),
6133                                     theme, size);
6134 }
6135 #endif
6136
6137
6138 static void
6139 create_cursors (GtkWidget *widget)
6140 {
6141   static GtkWidget *window = NULL;
6142   GtkWidget *frame;
6143   GtkWidget *hbox;
6144   GtkWidget *main_vbox;
6145   GtkWidget *vbox;
6146   GtkWidget *darea;
6147   GtkWidget *spinner;
6148   GtkWidget *button;
6149   GtkWidget *label;
6150   GtkWidget *any;
6151   GtkAdjustment *adj;
6152   GtkWidget *entry;
6153   GtkWidget *size;  
6154
6155   if (!window)
6156     {
6157       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6158       gtk_window_set_screen (GTK_WINDOW (window), 
6159                              gtk_widget_get_screen (widget));
6160       
6161       g_signal_connect (window, "destroy",
6162                         G_CALLBACK (gtk_widget_destroyed),
6163                         &window);
6164       
6165       gtk_window_set_title (GTK_WINDOW (window), "Cursors");
6166       
6167       main_vbox = gtk_vbox_new (FALSE, 5);
6168       gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 0);
6169       gtk_container_add (GTK_CONTAINER (window), main_vbox);
6170
6171       vbox =
6172         g_object_new (gtk_vbox_get_type (),
6173                         "GtkBox::homogeneous", FALSE,
6174                         "GtkBox::spacing", 5,
6175                         "GtkContainer::border_width", 10,
6176                         "GtkWidget::parent", main_vbox,
6177                         "GtkWidget::visible", TRUE,
6178                         NULL);
6179
6180 #ifdef GDK_WINDOWING_X11
6181       hbox = gtk_hbox_new (FALSE, 0);
6182       gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
6183       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
6184
6185       label = gtk_label_new ("Cursor Theme : ");
6186       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
6187       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
6188
6189       entry = gtk_entry_new ();
6190       gtk_entry_set_text (GTK_ENTRY (entry), "default");
6191       gtk_box_pack_start (GTK_BOX (hbox), entry, FALSE, TRUE, 0);
6192
6193       size = gtk_spin_button_new_with_range (1.0, 64.0, 1.0);
6194       gtk_spin_button_set_value (GTK_SPIN_BUTTON (size), 24.0);
6195       gtk_box_pack_start (GTK_BOX (hbox), size, TRUE, TRUE, 0);
6196       
6197       g_signal_connect (entry, "changed", 
6198                         G_CALLBACK (change_cursor_theme), hbox);
6199       g_signal_connect (size, "changed", 
6200                         G_CALLBACK (change_cursor_theme), hbox);
6201 #endif
6202
6203       hbox = gtk_hbox_new (FALSE, 0);
6204       gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
6205       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
6206
6207       label = gtk_label_new ("Cursor Value : ");
6208       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
6209       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
6210       
6211       adj = (GtkAdjustment *) gtk_adjustment_new (0,
6212                                                   0, 152,
6213                                                   2,
6214                                                   10, 0);
6215       spinner = gtk_spin_button_new (adj, 0, 0);
6216       gtk_box_pack_start (GTK_BOX (hbox), spinner, TRUE, TRUE, 0);
6217
6218       frame =
6219         g_object_new (gtk_frame_get_type (),
6220                         "GtkFrame::shadow", GTK_SHADOW_ETCHED_IN,
6221                         "GtkFrame::label_xalign", 0.5,
6222                         "GtkFrame::label", "Cursor Area",
6223                         "GtkContainer::border_width", 10,
6224                         "GtkWidget::parent", vbox,
6225                         "GtkWidget::visible", TRUE,
6226                         NULL);
6227
6228       darea = gtk_drawing_area_new ();
6229       gtk_widget_set_size_request (darea, 80, 80);
6230       gtk_container_add (GTK_CONTAINER (frame), darea);
6231       g_signal_connect (darea,
6232                         "expose_event",
6233                         G_CALLBACK (cursor_expose_event),
6234                         NULL);
6235       gtk_widget_set_events (darea, GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK);
6236       g_signal_connect (darea,
6237                         "button_press_event",
6238                         G_CALLBACK (cursor_event),
6239                         spinner);
6240       gtk_widget_show (darea);
6241
6242       g_signal_connect (spinner, "changed",
6243                         G_CALLBACK (set_cursor),
6244                         darea);
6245
6246       label = g_object_new (GTK_TYPE_LABEL,
6247                               "visible", TRUE,
6248                               "label", "XXX",
6249                               "parent", vbox,
6250                               NULL);
6251       gtk_container_child_set (GTK_CONTAINER (vbox), label,
6252                                "expand", FALSE,
6253                                NULL);
6254       g_object_set_data (G_OBJECT (spinner), "user_data", label);
6255
6256       any =
6257         g_object_new (gtk_hseparator_get_type (),
6258                         "GtkWidget::visible", TRUE,
6259                         NULL);
6260       gtk_box_pack_start (GTK_BOX (main_vbox), any, FALSE, TRUE, 0);
6261   
6262       hbox = gtk_hbox_new (FALSE, 0);
6263       gtk_container_set_border_width (GTK_CONTAINER (hbox), 10);
6264       gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, TRUE, 0);
6265
6266       button = gtk_button_new_with_label ("Close");
6267       g_signal_connect_swapped (button, "clicked",
6268                                 G_CALLBACK (gtk_widget_destroy),
6269                                 window);
6270       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
6271
6272       gtk_widget_show_all (window);
6273
6274       set_cursor (spinner, darea);
6275     }
6276   else
6277     gtk_widget_destroy (window);
6278 }
6279
6280 /*
6281  * GtkList
6282  */
6283
6284 static void
6285 list_add (GtkWidget *widget,
6286           GtkWidget *list)
6287 {
6288   static int i = 1;
6289   gchar buffer[64];
6290   GtkWidget *list_item;
6291   GtkContainer *container;
6292
6293   container = GTK_CONTAINER (list);
6294
6295   sprintf (buffer, "added item %d", i++);
6296   list_item = gtk_list_item_new_with_label (buffer);
6297   gtk_widget_show (list_item);
6298
6299   gtk_container_add (container, list_item);
6300 }
6301
6302 static void
6303 list_remove (GtkWidget *widget,
6304              GtkList   *list)
6305 {
6306   GList *clear_list = NULL;
6307   GList *sel_row = NULL;
6308   GList *work = NULL;
6309
6310   if (list->selection_mode == GTK_SELECTION_EXTENDED)
6311     {
6312       GtkWidget *item;
6313
6314       item = GTK_CONTAINER (list)->focus_child;
6315       if (!item && list->selection)
6316         item = list->selection->data;
6317
6318       if (item)
6319         {
6320           work = g_list_find (list->children, item);
6321           for (sel_row = work; sel_row; sel_row = sel_row->next)
6322             if (GTK_WIDGET (sel_row->data)->state != GTK_STATE_SELECTED)
6323               break;
6324
6325           if (!sel_row)
6326             {
6327               for (sel_row = work; sel_row; sel_row = sel_row->prev)
6328                 if (GTK_WIDGET (sel_row->data)->state != GTK_STATE_SELECTED)
6329                   break;
6330             }
6331         }
6332     }
6333
6334   for (work = list->selection; work; work = work->next)
6335     clear_list = g_list_prepend (clear_list, work->data);
6336
6337   clear_list = g_list_reverse (clear_list);
6338   gtk_list_remove_items (GTK_LIST (list), clear_list);
6339   g_list_free (clear_list);
6340
6341   if (list->selection_mode == GTK_SELECTION_EXTENDED && sel_row)
6342     gtk_list_select_child (list, GTK_WIDGET(sel_row->data));
6343 }
6344
6345 static void
6346 list_clear (GtkWidget *widget,
6347             GtkWidget *list)
6348 {
6349   gtk_list_clear_items (GTK_LIST (list), 0, -1);
6350 }
6351
6352 static gchar *selection_mode_items[] =
6353 {
6354   "Single",
6355   "Browse",
6356   "Multiple"
6357 };
6358
6359 static const GtkSelectionMode selection_modes[] = {
6360   GTK_SELECTION_SINGLE,
6361   GTK_SELECTION_BROWSE,
6362   GTK_SELECTION_MULTIPLE
6363 };
6364
6365 static GtkWidget *list_omenu;
6366
6367 static void 
6368 list_toggle_sel_mode (GtkWidget *widget, gpointer data)
6369 {
6370   GtkList *list;
6371   gint i;
6372
6373   list = GTK_LIST (data);
6374
6375   if (!GTK_WIDGET_MAPPED (widget))
6376     return;
6377
6378   i = gtk_option_menu_get_history (GTK_OPTION_MENU (widget));
6379
6380   gtk_list_set_selection_mode (list, selection_modes[i]);
6381 }
6382
6383 static void
6384 create_list (GtkWidget *widget)
6385 {
6386   static GtkWidget *window = NULL;
6387
6388   if (!window)
6389     {
6390       GtkWidget *cbox;
6391       GtkWidget *vbox;
6392       GtkWidget *hbox;
6393       GtkWidget *label;
6394       GtkWidget *scrolled_win;
6395       GtkWidget *list;
6396       GtkWidget *button;
6397       GtkWidget *separator;
6398       FILE *infile;
6399
6400       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6401
6402       gtk_window_set_screen (GTK_WINDOW (window),
6403                              gtk_widget_get_screen (widget));
6404
6405       g_signal_connect (window, "destroy",
6406                         G_CALLBACK (gtk_widget_destroyed),
6407                         &window);
6408
6409       gtk_window_set_title (GTK_WINDOW (window), "list");
6410       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
6411
6412       vbox = gtk_vbox_new (FALSE, 0);
6413       gtk_container_add (GTK_CONTAINER (window), vbox);
6414
6415       scrolled_win = gtk_scrolled_window_new (NULL, NULL);
6416       gtk_container_set_border_width (GTK_CONTAINER (scrolled_win), 5);
6417       gtk_widget_set_size_request (scrolled_win, -1, 300);
6418       gtk_box_pack_start (GTK_BOX (vbox), scrolled_win, TRUE, TRUE, 0);
6419       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
6420                                       GTK_POLICY_AUTOMATIC,
6421                                       GTK_POLICY_AUTOMATIC);
6422
6423       list = gtk_list_new ();
6424       gtk_list_set_selection_mode (GTK_LIST (list), GTK_SELECTION_SINGLE);
6425       gtk_scrolled_window_add_with_viewport
6426         (GTK_SCROLLED_WINDOW (scrolled_win), list);
6427       gtk_container_set_focus_vadjustment
6428         (GTK_CONTAINER (list),
6429          gtk_scrolled_window_get_vadjustment
6430          (GTK_SCROLLED_WINDOW (scrolled_win)));
6431       gtk_container_set_focus_hadjustment
6432         (GTK_CONTAINER (list),
6433          gtk_scrolled_window_get_hadjustment
6434          (GTK_SCROLLED_WINDOW (scrolled_win)));
6435
6436       if ((infile = fopen("../gtk/gtkenums.h", "r")))
6437         {
6438           char buffer[256];
6439           char *pos;
6440           GtkWidget *item;
6441
6442           while (fgets (buffer, 256, infile))
6443             {
6444               if ((pos = strchr (buffer, '\n')))
6445                 *pos = 0;
6446               item = gtk_list_item_new_with_label (buffer);
6447               gtk_container_add (GTK_CONTAINER (list), item);
6448             }
6449           
6450           fclose (infile);
6451         }
6452
6453
6454       hbox = gtk_hbox_new (TRUE, 5);
6455       gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
6456       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
6457
6458       button = gtk_button_new_with_label ("Insert Row");
6459       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
6460       g_signal_connect (button, "clicked",
6461                         G_CALLBACK (list_add),
6462                         list);
6463
6464       button = gtk_button_new_with_label ("Clear List");
6465       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
6466       g_signal_connect (button, "clicked",
6467                         G_CALLBACK (list_clear),
6468                         list);
6469
6470       button = gtk_button_new_with_label ("Remove Selection");
6471       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
6472       g_signal_connect (button, "clicked",
6473                         G_CALLBACK (list_remove),
6474                         list);
6475
6476       cbox = gtk_hbox_new (FALSE, 0);
6477       gtk_box_pack_start (GTK_BOX (vbox), cbox, FALSE, TRUE, 0);
6478
6479       hbox = gtk_hbox_new (FALSE, 5);
6480       gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
6481       gtk_box_pack_start (GTK_BOX (cbox), hbox, TRUE, FALSE, 0);
6482
6483       label = gtk_label_new ("Selection Mode :");
6484       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
6485
6486       list_omenu = build_option_menu (selection_mode_items, 3, 3, 
6487                                       list_toggle_sel_mode,
6488                                       list);
6489       gtk_box_pack_start (GTK_BOX (hbox), list_omenu, FALSE, TRUE, 0);
6490
6491       separator = gtk_hseparator_new ();
6492       gtk_box_pack_start (GTK_BOX (vbox), separator, FALSE, TRUE, 0);
6493
6494       cbox = gtk_hbox_new (FALSE, 0);
6495       gtk_box_pack_start (GTK_BOX (vbox), cbox, FALSE, TRUE, 0);
6496
6497       button = gtk_button_new_with_label ("close");
6498       gtk_container_set_border_width (GTK_CONTAINER (button), 10);
6499       gtk_box_pack_start (GTK_BOX (cbox), button, TRUE, TRUE, 0);
6500       g_signal_connect_swapped (button, "clicked",
6501                                 G_CALLBACK (gtk_widget_destroy),
6502                                 window);
6503
6504       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
6505       gtk_widget_grab_default (button);
6506     }
6507
6508   if (!GTK_WIDGET_VISIBLE (window))
6509     gtk_widget_show_all (window);
6510   else
6511     gtk_widget_destroy (window);
6512 }
6513
6514 /*
6515  * GtkCList
6516  */
6517
6518 static char * book_open_xpm[] = {
6519 "16 16 4 1",
6520 "       c None s None",
6521 ".      c black",
6522 "X      c #808080",
6523 "o      c white",
6524 "                ",
6525 "  ..            ",
6526 " .Xo.    ...    ",
6527 " .Xoo. ..oo.    ",
6528 " .Xooo.Xooo...  ",
6529 " .Xooo.oooo.X.  ",
6530 " .Xooo.Xooo.X.  ",
6531 " .Xooo.oooo.X.  ",
6532 " .Xooo.Xooo.X.  ",
6533 " .Xooo.oooo.X.  ",
6534 "  .Xoo.Xoo..X.  ",
6535 "   .Xo.o..ooX.  ",
6536 "    .X..XXXXX.  ",
6537 "    ..X.......  ",
6538 "     ..         ",
6539 "                "};
6540
6541 static char * book_closed_xpm[] = {
6542 "16 16 6 1",
6543 "       c None s None",
6544 ".      c black",
6545 "X      c red",
6546 "o      c yellow",
6547 "O      c #808080",
6548 "#      c white",
6549 "                ",
6550 "       ..       ",
6551 "     ..XX.      ",
6552 "   ..XXXXX.     ",
6553 " ..XXXXXXXX.    ",
6554 ".ooXXXXXXXXX.   ",
6555 "..ooXXXXXXXXX.  ",
6556 ".X.ooXXXXXXXXX. ",
6557 ".XX.ooXXXXXX..  ",
6558 " .XX.ooXXX..#O  ",
6559 "  .XX.oo..##OO. ",
6560 "   .XX..##OO..  ",
6561 "    .X.#OO..    ",
6562 "     ..O..      ",
6563 "      ..        ",
6564 "                "};
6565
6566 static char * mini_page_xpm[] = {
6567 "16 16 4 1",
6568 "       c None s None",
6569 ".      c black",
6570 "X      c white",
6571 "o      c #808080",
6572 "                ",
6573 "   .......      ",
6574 "   .XXXXX..     ",
6575 "   .XoooX.X.    ",
6576 "   .XXXXX....   ",
6577 "   .XooooXoo.o  ",
6578 "   .XXXXXXXX.o  ",
6579 "   .XooooooX.o  ",
6580 "   .XXXXXXXX.o  ",
6581 "   .XooooooX.o  ",
6582 "   .XXXXXXXX.o  ",
6583 "   .XooooooX.o  ",
6584 "   .XXXXXXXX.o  ",
6585 "   ..........o  ",
6586 "    oooooooooo  ",
6587 "                "};
6588
6589 static char * gtk_mini_xpm[] = {
6590 "15 20 17 1",
6591 "       c None",
6592 ".      c #14121F",
6593 "+      c #278828",
6594 "@      c #9B3334",
6595 "#      c #284C72",
6596 "$      c #24692A",
6597 "%      c #69282E",
6598 "&      c #37C539",
6599 "*      c #1D2F4D",
6600 "=      c #6D7076",
6601 "-      c #7D8482",
6602 ";      c #E24A49",
6603 ">      c #515357",
6604 ",      c #9B9C9B",
6605 "'      c #2FA232",
6606 ")      c #3CE23D",
6607 "!      c #3B6CCB",
6608 "               ",
6609 "      ***>     ",
6610 "    >.*!!!*    ",
6611 "   ***....#*=  ",
6612 "  *!*.!!!**!!# ",
6613 " .!!#*!#*!!!!# ",
6614 " @%#!.##.*!!$& ",
6615 " @;%*!*.#!#')) ",
6616 " @;;@%!!*$&)'' ",
6617 " @%.%@%$'&)$+' ",
6618 " @;...@$'*'*)+ ",
6619 " @;%..@$+*.')$ ",
6620 " @;%%;;$+..$)# ",
6621 " @;%%;@$$$'.$# ",
6622 " %;@@;;$$+))&* ",
6623 "  %;;;@+$&)&*  ",
6624 "   %;;@'))+>   ",
6625 "    %;@'&#     ",
6626 "     >%$$      ",
6627 "      >=       "};
6628
6629 #define TESTGTK_CLIST_COLUMNS 12
6630 static gint clist_rows = 0;
6631 static GtkWidget *clist_omenu;
6632
6633 static void
6634 add1000_clist (GtkWidget *widget, gpointer data)
6635 {
6636   gint i, row;
6637   char text[TESTGTK_CLIST_COLUMNS][50];
6638   char *texts[TESTGTK_CLIST_COLUMNS];
6639   GdkBitmap *mask;
6640   GdkPixmap *pixmap;
6641   GtkCList  *clist;
6642
6643   clist = GTK_CLIST (data);
6644
6645   pixmap = gdk_pixmap_create_from_xpm_d (clist->clist_window,
6646                                          &mask, 
6647                                          &GTK_WIDGET (data)->style->white,
6648                                          gtk_mini_xpm);
6649
6650   for (i = 0; i < TESTGTK_CLIST_COLUMNS; i++)
6651     {
6652       texts[i] = text[i];
6653       sprintf (text[i], "Column %d", i);
6654     }
6655   
6656   texts[3] = NULL;
6657   sprintf (text[1], "Right");
6658   sprintf (text[2], "Center");
6659   
6660   gtk_clist_freeze (GTK_CLIST (data));
6661   for (i = 0; i < 1000; i++)
6662     {
6663       sprintf (text[0], "CListRow %d", rand() % 10000);
6664       row = gtk_clist_append (clist, texts);
6665       gtk_clist_set_pixtext (clist, row, 3, "gtk+", 5, pixmap, mask);
6666     }
6667
6668   gtk_clist_thaw (GTK_CLIST (data));
6669
6670   g_object_unref (pixmap);
6671   g_object_unref (mask);
6672 }
6673
6674 static void
6675 add10000_clist (GtkWidget *widget, gpointer data)
6676 {
6677   gint i;
6678   char text[TESTGTK_CLIST_COLUMNS][50];
6679   char *texts[TESTGTK_CLIST_COLUMNS];
6680
6681   for (i = 0; i < TESTGTK_CLIST_COLUMNS; i++)
6682     {
6683       texts[i] = text[i];
6684       sprintf (text[i], "Column %d", i);
6685     }
6686   
6687   sprintf (text[1], "Right");
6688   sprintf (text[2], "Center");
6689   
6690   gtk_clist_freeze (GTK_CLIST (data));
6691   for (i = 0; i < 10000; i++)
6692     {
6693       sprintf (text[0], "CListRow %d", rand() % 10000);
6694       gtk_clist_append (GTK_CLIST (data), texts);
6695     }
6696   gtk_clist_thaw (GTK_CLIST (data));
6697 }
6698
6699 void
6700 clear_clist (GtkWidget *widget, gpointer data)
6701 {
6702   gtk_clist_clear (GTK_CLIST (data));
6703   clist_rows = 0;
6704 }
6705
6706 void clist_remove_selection (GtkWidget *widget, GtkCList *clist)
6707 {
6708   gtk_clist_freeze (clist);
6709
6710   while (clist->selection)
6711     {
6712       gint row;
6713
6714       clist_rows--;
6715       row = GPOINTER_TO_INT (clist->selection->data);
6716
6717       gtk_clist_remove (clist, row);
6718
6719       if (clist->selection_mode == GTK_SELECTION_BROWSE)
6720         break;
6721     }
6722
6723   if (clist->selection_mode == GTK_SELECTION_EXTENDED && !clist->selection &&
6724       clist->focus_row >= 0)
6725     gtk_clist_select_row (clist, clist->focus_row, -1);
6726
6727   gtk_clist_thaw (clist);
6728 }
6729
6730 void toggle_title_buttons (GtkWidget *widget, GtkCList *clist)
6731 {
6732   if (GTK_TOGGLE_BUTTON (widget)->active)
6733     gtk_clist_column_titles_show (clist);
6734   else
6735     gtk_clist_column_titles_hide (clist);
6736 }
6737
6738 void toggle_reorderable (GtkWidget *widget, GtkCList *clist)
6739 {
6740   gtk_clist_set_reorderable (clist, GTK_TOGGLE_BUTTON (widget)->active);
6741 }
6742
6743 static void
6744 insert_row_clist (GtkWidget *widget, gpointer data)
6745 {
6746   static char *text[] =
6747   {
6748     "This", "is an", "inserted", "row.",
6749     "This", "is an", "inserted", "row.",
6750     "This", "is an", "inserted", "row."
6751   };
6752
6753   static GtkStyle *style1 = NULL;
6754   static GtkStyle *style2 = NULL;
6755   static GtkStyle *style3 = NULL;
6756   gint row;
6757   
6758   if (GTK_CLIST (data)->focus_row >= 0)
6759     row = gtk_clist_insert (GTK_CLIST (data), GTK_CLIST (data)->focus_row,
6760                             text);
6761   else
6762     row = gtk_clist_prepend (GTK_CLIST (data), text);
6763
6764   if (!style1)
6765     {
6766       GdkColor col1 = { 0, 0, 56000, 0};
6767       GdkColor col2 = { 0, 32000, 0, 56000};
6768
6769       style1 = gtk_style_copy (GTK_WIDGET (data)->style);
6770       style1->base[GTK_STATE_NORMAL] = col1;
6771       style1->base[GTK_STATE_SELECTED] = col2;
6772
6773       style2 = gtk_style_copy (GTK_WIDGET (data)->style);
6774       style2->fg[GTK_STATE_NORMAL] = col1;
6775       style2->fg[GTK_STATE_SELECTED] = col2;
6776
6777       style3 = gtk_style_copy (GTK_WIDGET (data)->style);
6778       style3->fg[GTK_STATE_NORMAL] = col1;
6779       style3->base[GTK_STATE_NORMAL] = col2;
6780       pango_font_description_free (style3->font_desc);
6781       style3->font_desc = pango_font_description_from_string ("courier 12");
6782     }
6783
6784   gtk_clist_set_cell_style (GTK_CLIST (data), row, 3, style1);
6785   gtk_clist_set_cell_style (GTK_CLIST (data), row, 4, style2);
6786   gtk_clist_set_cell_style (GTK_CLIST (data), row, 0, style3);
6787
6788   clist_rows++;
6789 }
6790
6791 static void
6792 clist_warning_test (GtkWidget *button,
6793                     GtkWidget *clist)
6794 {
6795   GtkWidget *child;
6796   static gboolean add_remove = FALSE;
6797
6798   add_remove = !add_remove;
6799
6800   child = gtk_label_new ("Test");
6801   g_object_ref (child);
6802   gtk_object_sink (GTK_OBJECT (child));
6803
6804   if (add_remove)
6805     gtk_container_add (GTK_CONTAINER (clist), child);
6806   else
6807     {
6808       child->parent = clist;
6809       gtk_container_remove (GTK_CONTAINER (clist), child);
6810       child->parent = NULL;
6811     }
6812
6813   gtk_widget_destroy (child);
6814   g_object_unref (child);
6815 }
6816
6817 static void
6818 undo_selection (GtkWidget *button, GtkCList *clist)
6819 {
6820   gtk_clist_undo_selection (clist);
6821 }
6822
6823 static void 
6824 clist_toggle_sel_mode (GtkWidget *widget, gpointer data)
6825 {
6826   GtkCList *clist;
6827   gint i;
6828
6829   clist = GTK_CLIST (data);
6830
6831   if (!GTK_WIDGET_MAPPED (widget))
6832     return;
6833
6834   i = gtk_option_menu_get_history (GTK_OPTION_MENU (widget));
6835
6836   gtk_clist_set_selection_mode (clist, selection_modes[i]);
6837 }
6838
6839 static void 
6840 clist_click_column (GtkCList *clist, gint column, gpointer data)
6841 {
6842   if (column == 4)
6843     gtk_clist_set_column_visibility (clist, column, FALSE);
6844   else if (column == clist->sort_column)
6845     {
6846       if (clist->sort_type == GTK_SORT_ASCENDING)
6847         clist->sort_type = GTK_SORT_DESCENDING;
6848       else
6849         clist->sort_type = GTK_SORT_ASCENDING;
6850     }
6851   else
6852     gtk_clist_set_sort_column (clist, column);
6853
6854   gtk_clist_sort (clist);
6855 }
6856
6857 static void
6858 create_clist (GtkWidget *widget)
6859 {
6860   gint i;
6861   static GtkWidget *window = NULL;
6862
6863   static char *titles[] =
6864   {
6865     "auto resize", "not resizeable", "max width 100", "min width 50",
6866     "hide column", "Title 5", "Title 6", "Title 7",
6867     "Title 8",  "Title 9",  "Title 10", "Title 11"
6868   };
6869
6870   char text[TESTGTK_CLIST_COLUMNS][50];
6871   char *texts[TESTGTK_CLIST_COLUMNS];
6872
6873   GtkWidget *vbox;
6874   GtkWidget *hbox;
6875   GtkWidget *clist;
6876   GtkWidget *button;
6877   GtkWidget *separator;
6878   GtkWidget *scrolled_win;
6879   GtkWidget *check;
6880
6881   GtkWidget *undo_button;
6882   GtkWidget *label;
6883
6884   GtkStyle *style;
6885   GdkColor red_col = { 0, 56000, 0, 0};
6886   GdkColor light_green_col = { 0, 0, 56000, 32000};
6887
6888   if (!window)
6889     {
6890       clist_rows = 0;
6891       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6892       gtk_window_set_screen (GTK_WINDOW (window), 
6893                              gtk_widget_get_screen (widget));
6894
6895       g_signal_connect (window, "destroy",
6896                         G_CALLBACK (gtk_widget_destroyed), &window);
6897
6898       gtk_window_set_title (GTK_WINDOW (window), "clist");
6899       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
6900
6901       vbox = gtk_vbox_new (FALSE, 0);
6902       gtk_container_add (GTK_CONTAINER (window), vbox);
6903
6904       scrolled_win = gtk_scrolled_window_new (NULL, NULL);
6905       gtk_container_set_border_width (GTK_CONTAINER (scrolled_win), 5);
6906       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
6907                                       GTK_POLICY_AUTOMATIC, 
6908                                       GTK_POLICY_AUTOMATIC);
6909
6910       /* create GtkCList here so we have a pointer to throw at the 
6911        * button callbacks -- more is done with it later */
6912       clist = gtk_clist_new_with_titles (TESTGTK_CLIST_COLUMNS, titles);
6913       gtk_container_add (GTK_CONTAINER (scrolled_win), clist);
6914       g_signal_connect (clist, "click_column",
6915                         G_CALLBACK (clist_click_column), NULL);
6916
6917       /* control buttons */
6918       hbox = gtk_hbox_new (FALSE, 5);
6919       gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
6920       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
6921
6922       button = gtk_button_new_with_label ("Insert Row");
6923       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
6924       g_signal_connect (button, "clicked",
6925                         G_CALLBACK (insert_row_clist), clist);
6926
6927       button = gtk_button_new_with_label ("Add 1,000 Rows With Pixmaps");
6928       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
6929       g_signal_connect (button, "clicked",
6930                         G_CALLBACK (add1000_clist), clist);
6931
6932       button = gtk_button_new_with_label ("Add 10,000 Rows");
6933       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
6934       g_signal_connect (button, "clicked",
6935                         G_CALLBACK (add10000_clist), clist);
6936
6937       /* second layer of buttons */
6938       hbox = gtk_hbox_new (FALSE, 5);
6939       gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
6940       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
6941
6942       button = gtk_button_new_with_label ("Clear List");
6943       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
6944       g_signal_connect (button, "clicked",
6945                         G_CALLBACK (clear_clist), clist);
6946
6947       button = gtk_button_new_with_label ("Remove Selection");
6948       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
6949       g_signal_connect (button, "clicked",
6950                         G_CALLBACK (clist_remove_selection), clist);
6951
6952       undo_button = gtk_button_new_with_label ("Undo Selection");
6953       gtk_box_pack_start (GTK_BOX (hbox), undo_button, TRUE, TRUE, 0);
6954       g_signal_connect (undo_button, "clicked",
6955                         G_CALLBACK (undo_selection), clist);
6956
6957       button = gtk_button_new_with_label ("Warning Test");
6958       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
6959       g_signal_connect (button, "clicked",
6960                         G_CALLBACK (clist_warning_test), clist);
6961
6962       /* third layer of buttons */
6963       hbox = gtk_hbox_new (FALSE, 5);
6964       gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
6965       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
6966
6967       check = gtk_check_button_new_with_label ("Show Title Buttons");
6968       gtk_box_pack_start (GTK_BOX (hbox), check, FALSE, TRUE, 0);
6969       g_signal_connect (check, "clicked",
6970                         G_CALLBACK (toggle_title_buttons), clist);
6971       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check), TRUE);
6972
6973       check = gtk_check_button_new_with_label ("Reorderable");
6974       gtk_box_pack_start (GTK_BOX (hbox), check, FALSE, TRUE, 0);
6975       g_signal_connect (check, "clicked",
6976                         G_CALLBACK (toggle_reorderable), clist);
6977       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check), TRUE);
6978
6979       label = gtk_label_new ("Selection Mode :");
6980       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
6981
6982       clist_omenu = build_option_menu (selection_mode_items, 3, 3, 
6983                                        clist_toggle_sel_mode,
6984                                        clist);
6985       gtk_box_pack_start (GTK_BOX (hbox), clist_omenu, FALSE, TRUE, 0);
6986
6987       /* 
6988        * the rest of the clist configuration
6989        */
6990
6991       gtk_box_pack_start (GTK_BOX (vbox), scrolled_win, TRUE, TRUE, 0);
6992       gtk_clist_set_row_height (GTK_CLIST (clist), 18);
6993       gtk_widget_set_size_request (clist, -1, 300);
6994
6995       for (i = 1; i < TESTGTK_CLIST_COLUMNS; i++)
6996         gtk_clist_set_column_width (GTK_CLIST (clist), i, 80);
6997
6998       gtk_clist_set_column_auto_resize (GTK_CLIST (clist), 0, TRUE);
6999       gtk_clist_set_column_resizeable (GTK_CLIST (clist), 1, FALSE);
7000       gtk_clist_set_column_max_width (GTK_CLIST (clist), 2, 100);
7001       gtk_clist_set_column_min_width (GTK_CLIST (clist), 3, 50);
7002       gtk_clist_set_selection_mode (GTK_CLIST (clist), GTK_SELECTION_EXTENDED);
7003       gtk_clist_set_column_justification (GTK_CLIST (clist), 1,
7004                                           GTK_JUSTIFY_RIGHT);
7005       gtk_clist_set_column_justification (GTK_CLIST (clist), 2,
7006                                           GTK_JUSTIFY_CENTER);
7007       
7008       for (i = 0; i < TESTGTK_CLIST_COLUMNS; i++)
7009         {
7010           texts[i] = text[i];
7011           sprintf (text[i], "Column %d", i);
7012         }
7013
7014       sprintf (text[1], "Right");
7015       sprintf (text[2], "Center");
7016
7017       style = gtk_style_new ();
7018       style->fg[GTK_STATE_NORMAL] = red_col;
7019       style->base[GTK_STATE_NORMAL] = light_green_col;
7020
7021       pango_font_description_set_size (style->font_desc, 14 * PANGO_SCALE);
7022       pango_font_description_set_weight (style->font_desc, PANGO_WEIGHT_BOLD);
7023
7024       for (i = 0; i < 10; i++)
7025         {
7026           sprintf (text[0], "CListRow %d", clist_rows++);
7027           gtk_clist_append (GTK_CLIST (clist), texts);
7028
7029           switch (i % 4)
7030             {
7031             case 2:
7032               gtk_clist_set_row_style (GTK_CLIST (clist), i, style);
7033               break;
7034             default:
7035               gtk_clist_set_cell_style (GTK_CLIST (clist), i, i % 4, style);
7036               break;
7037             }
7038         }
7039
7040       g_object_unref (style);
7041       
7042       separator = gtk_hseparator_new ();
7043       gtk_box_pack_start (GTK_BOX (vbox), separator, FALSE, TRUE, 0);
7044
7045       hbox = gtk_hbox_new (FALSE, 0);
7046       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
7047
7048       button = gtk_button_new_with_label ("close");
7049       gtk_container_set_border_width (GTK_CONTAINER (button), 10);
7050       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
7051       g_signal_connect_swapped (button, "clicked",
7052                                 G_CALLBACK (gtk_widget_destroy),
7053                                 window);
7054
7055       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
7056       gtk_widget_grab_default (button);
7057     }
7058
7059   if (!GTK_WIDGET_VISIBLE (window))
7060     gtk_widget_show_all (window);
7061   else
7062     {
7063       clist_rows = 0;
7064       gtk_widget_destroy (window);
7065     }
7066 }
7067
7068 /*
7069  * GtkCTree
7070  */
7071
7072 typedef struct 
7073 {
7074   GdkPixmap *pixmap1;
7075   GdkPixmap *pixmap2;
7076   GdkPixmap *pixmap3;
7077   GdkBitmap *mask1;
7078   GdkBitmap *mask2;
7079   GdkBitmap *mask3;
7080 } CTreePixmaps;
7081
7082 static gint books = 0;
7083 static gint pages = 0;
7084
7085 static GtkWidget *book_label;
7086 static GtkWidget *page_label;
7087 static GtkWidget *sel_label;
7088 static GtkWidget *vis_label;
7089 static GtkWidget *omenu1;
7090 static GtkWidget *omenu2;
7091 static GtkWidget *omenu3;
7092 static GtkWidget *omenu4;
7093 static GtkWidget *spin1;
7094 static GtkWidget *spin2;
7095 static GtkWidget *spin3;
7096 static gint line_style;
7097
7098
7099 static CTreePixmaps *
7100 get_ctree_pixmaps (GtkCTree *ctree)
7101 {
7102   GdkScreen *screen = gtk_widget_get_screen (GTK_WIDGET (ctree));
7103   CTreePixmaps *pixmaps = g_object_get_data (G_OBJECT (screen), "ctree-pixmaps");
7104
7105   if (!pixmaps)
7106     {
7107       GdkColormap *colormap = gdk_screen_get_rgb_colormap (screen);
7108       pixmaps = g_new (CTreePixmaps, 1);
7109       
7110       pixmaps->pixmap1 = gdk_pixmap_colormap_create_from_xpm_d (NULL, colormap,
7111                                                                 &pixmaps->mask1, 
7112                                                                 NULL, book_closed_xpm);
7113       pixmaps->pixmap2 = gdk_pixmap_colormap_create_from_xpm_d (NULL, colormap,
7114                                                                 &pixmaps->mask2, 
7115                                                                 NULL, book_open_xpm);
7116       pixmaps->pixmap3 = gdk_pixmap_colormap_create_from_xpm_d (NULL, colormap,
7117                                                                 &pixmaps->mask3,
7118                                                                 NULL, mini_page_xpm);
7119       
7120       g_object_set_data (G_OBJECT (screen), "ctree-pixmaps", pixmaps);
7121     }
7122
7123   return pixmaps;
7124 }
7125
7126 void after_press (GtkCTree *ctree, gpointer data)
7127 {
7128   char buf[80];
7129
7130   sprintf (buf, "%d", g_list_length (GTK_CLIST (ctree)->selection));
7131   gtk_label_set_text (GTK_LABEL (sel_label), buf);
7132
7133   sprintf (buf, "%d", g_list_length (GTK_CLIST (ctree)->row_list));
7134   gtk_label_set_text (GTK_LABEL (vis_label), buf);
7135
7136   sprintf (buf, "%d", books);
7137   gtk_label_set_text (GTK_LABEL (book_label), buf);
7138
7139   sprintf (buf, "%d", pages);
7140   gtk_label_set_text (GTK_LABEL (page_label), buf);
7141 }
7142
7143 void after_move (GtkCTree *ctree, GtkCTreeNode *child, GtkCTreeNode *parent, 
7144                  GtkCTreeNode *sibling, gpointer data)
7145 {
7146   char *source;
7147   char *target1;
7148   char *target2;
7149
7150   gtk_ctree_get_node_info (ctree, child, &source, 
7151                            NULL, NULL, NULL, NULL, NULL, NULL, NULL);
7152   if (parent)
7153     gtk_ctree_get_node_info (ctree, parent, &target1, 
7154                              NULL, NULL, NULL, NULL, NULL, NULL, NULL);
7155   if (sibling)
7156     gtk_ctree_get_node_info (ctree, sibling, &target2, 
7157                              NULL, NULL, NULL, NULL, NULL, NULL, NULL);
7158
7159   g_print ("Moving \"%s\" to \"%s\" with sibling \"%s\".\n", source,
7160            (parent) ? target1 : "nil", (sibling) ? target2 : "nil");
7161 }
7162
7163 void count_items (GtkCTree *ctree, GtkCTreeNode *list)
7164 {
7165   if (GTK_CTREE_ROW (list)->is_leaf)
7166     pages--;
7167   else
7168     books--;
7169 }
7170
7171 void expand_all (GtkWidget *widget, GtkCTree *ctree)
7172 {
7173   gtk_ctree_expand_recursive (ctree, NULL);
7174   after_press (ctree, NULL);
7175 }
7176
7177 void collapse_all (GtkWidget *widget, GtkCTree *ctree)
7178 {
7179   gtk_ctree_collapse_recursive (ctree, NULL);
7180   after_press (ctree, NULL);
7181 }
7182
7183 void select_all (GtkWidget *widget, GtkCTree *ctree)
7184 {
7185   gtk_ctree_select_recursive (ctree, NULL);
7186   after_press (ctree, NULL);
7187 }
7188
7189 void change_style (GtkWidget *widget, GtkCTree *ctree)
7190 {
7191   static GtkStyle *style1 = NULL;
7192   static GtkStyle *style2 = NULL;
7193
7194   GtkCTreeNode *node;
7195   GdkColor green_col = { 0, 0, 56000, 0};
7196   GdkColor purple_col = { 0, 32000, 0, 56000};
7197
7198   if (GTK_CLIST (ctree)->focus_row >= 0)
7199     node = GTK_CTREE_NODE
7200       (g_list_nth (GTK_CLIST (ctree)->row_list,GTK_CLIST (ctree)->focus_row));
7201   else
7202     node = GTK_CTREE_NODE (GTK_CLIST (ctree)->row_list);
7203
7204   if (!node)
7205     return;
7206
7207   if (!style1)
7208     {
7209       style1 = gtk_style_new ();
7210       style1->base[GTK_STATE_NORMAL] = green_col;
7211       style1->fg[GTK_STATE_SELECTED] = purple_col;
7212
7213       style2 = gtk_style_new ();
7214       style2->base[GTK_STATE_SELECTED] = purple_col;
7215       style2->fg[GTK_STATE_NORMAL] = green_col;
7216       style2->base[GTK_STATE_NORMAL] = purple_col;
7217       pango_font_description_free (style2->font_desc);
7218       style2->font_desc = pango_font_description_from_string ("courier 30");
7219     }
7220
7221   gtk_ctree_node_set_cell_style (ctree, node, 1, style1);
7222   gtk_ctree_node_set_cell_style (ctree, node, 0, style2);
7223
7224   if (GTK_CTREE_ROW (node)->children)
7225     gtk_ctree_node_set_row_style (ctree, GTK_CTREE_ROW (node)->children,
7226                                   style2);
7227 }
7228
7229 void unselect_all (GtkWidget *widget, GtkCTree *ctree)
7230 {
7231   gtk_ctree_unselect_recursive (ctree, NULL);
7232   after_press (ctree, NULL);
7233 }
7234
7235 void remove_selection (GtkWidget *widget, GtkCTree *ctree)
7236 {
7237   GtkCList *clist;
7238   GtkCTreeNode *node;
7239
7240   clist = GTK_CLIST (ctree);
7241
7242   gtk_clist_freeze (clist);
7243
7244   while (clist->selection)
7245     {
7246       node = clist->selection->data;
7247
7248       if (GTK_CTREE_ROW (node)->is_leaf)
7249         pages--;
7250       else
7251         gtk_ctree_post_recursive (ctree, node,
7252                                   (GtkCTreeFunc) count_items, NULL);
7253
7254       gtk_ctree_remove_node (ctree, node);
7255
7256       if (clist->selection_mode == GTK_SELECTION_BROWSE)
7257         break;
7258     }
7259
7260   if (clist->selection_mode == GTK_SELECTION_EXTENDED && !clist->selection &&
7261       clist->focus_row >= 0)
7262     {
7263       node = gtk_ctree_node_nth (ctree, clist->focus_row);
7264
7265       if (node)
7266         gtk_ctree_select (ctree, node);
7267     }
7268     
7269   gtk_clist_thaw (clist);
7270   after_press (ctree, NULL);
7271 }
7272
7273 struct _ExportStruct {
7274   gchar *tree;
7275   gchar *info;
7276   gboolean is_leaf;
7277 };
7278
7279 typedef struct _ExportStruct ExportStruct;
7280
7281 gboolean
7282 gnode2ctree (GtkCTree   *ctree,
7283              guint       depth,
7284              GNode        *gnode,
7285              GtkCTreeNode *cnode,
7286              gpointer    data)
7287 {
7288   ExportStruct *es;
7289   GdkPixmap *pixmap_closed;
7290   GdkBitmap *mask_closed;
7291   GdkPixmap *pixmap_opened;
7292   GdkBitmap *mask_opened;
7293   CTreePixmaps *pixmaps;
7294
7295   if (!cnode || !gnode || (!(es = gnode->data)))
7296     return FALSE;
7297
7298   pixmaps = get_ctree_pixmaps (ctree);
7299
7300   if (es->is_leaf)
7301     {
7302       pixmap_closed = pixmaps->pixmap3;
7303       mask_closed = pixmaps->mask3;
7304       pixmap_opened = NULL;
7305       mask_opened = NULL;
7306     }
7307   else
7308     {
7309       pixmap_closed = pixmaps->pixmap1;
7310       mask_closed = pixmaps->mask1;
7311       pixmap_opened = pixmaps->pixmap2;
7312       mask_opened = pixmaps->mask2;
7313     }
7314
7315   gtk_ctree_set_node_info (ctree, cnode, es->tree, 2, pixmap_closed,
7316                            mask_closed, pixmap_opened, mask_opened,
7317                            es->is_leaf, (depth < 3));
7318   gtk_ctree_node_set_text (ctree, cnode, 1, es->info);
7319   g_free (es);
7320   gnode->data = NULL;
7321
7322   return TRUE;
7323 }
7324
7325 gboolean
7326 ctree2gnode (GtkCTree   *ctree,
7327              guint       depth,
7328              GNode        *gnode,
7329              GtkCTreeNode *cnode,
7330              gpointer    data)
7331 {
7332   ExportStruct *es;
7333
7334   if (!cnode || !gnode)
7335     return FALSE;
7336   
7337   es = g_new (ExportStruct, 1);
7338   gnode->data = es;
7339   es->is_leaf = GTK_CTREE_ROW (cnode)->is_leaf;
7340   es->tree = GTK_CELL_PIXTEXT (GTK_CTREE_ROW (cnode)->row.cell[0])->text;
7341   es->info = GTK_CELL_PIXTEXT (GTK_CTREE_ROW (cnode)->row.cell[1])->text;
7342   return TRUE;
7343 }
7344
7345 void export_ctree (GtkWidget *widget, GtkCTree *ctree)
7346 {
7347   char *title[] = { "Tree" , "Info" };
7348   static GtkWidget *export_window = NULL;
7349   static GtkCTree *export_ctree;
7350   GtkWidget *vbox;
7351   GtkWidget *scrolled_win;
7352   GtkWidget *button;
7353   GtkWidget *sep;
7354   GNode *gnode;
7355   GtkCTreeNode *node;
7356
7357   if (!export_window)
7358     {
7359       export_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7360
7361       gtk_window_set_screen (GTK_WINDOW (export_window),
7362                              gtk_widget_get_screen (widget));
7363   
7364       g_signal_connect (export_window, "destroy",
7365                         G_CALLBACK (gtk_widget_destroyed),
7366                         &export_window);
7367
7368       gtk_window_set_title (GTK_WINDOW (export_window), "exported ctree");
7369       gtk_container_set_border_width (GTK_CONTAINER (export_window), 5);
7370
7371       vbox = gtk_vbox_new (FALSE, 0);
7372       gtk_container_add (GTK_CONTAINER (export_window), vbox);
7373       
7374       button = gtk_button_new_with_label ("Close");
7375       gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, TRUE, 0);
7376
7377       g_signal_connect_swapped (button, "clicked",
7378                                 G_CALLBACK (gtk_widget_destroy),
7379                                 export_window);
7380
7381       sep = gtk_hseparator_new ();
7382       gtk_box_pack_end (GTK_BOX (vbox), sep, FALSE, TRUE, 10);
7383
7384       export_ctree = GTK_CTREE (gtk_ctree_new_with_titles (2, 0, title));
7385       gtk_ctree_set_line_style (export_ctree, GTK_CTREE_LINES_DOTTED);
7386
7387       scrolled_win = gtk_scrolled_window_new (NULL, NULL);
7388       gtk_container_add (GTK_CONTAINER (scrolled_win),
7389                          GTK_WIDGET (export_ctree));
7390       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
7391                                       GTK_POLICY_AUTOMATIC,
7392                                       GTK_POLICY_AUTOMATIC);
7393       gtk_box_pack_start (GTK_BOX (vbox), scrolled_win, TRUE, TRUE, 0);
7394       gtk_clist_set_selection_mode (GTK_CLIST (export_ctree),
7395                                     GTK_SELECTION_EXTENDED);
7396       gtk_clist_set_column_width (GTK_CLIST (export_ctree), 0, 200);
7397       gtk_clist_set_column_width (GTK_CLIST (export_ctree), 1, 200);
7398       gtk_widget_set_size_request (GTK_WIDGET (export_ctree), 300, 200);
7399     }
7400
7401   if (!GTK_WIDGET_VISIBLE (export_window))
7402     gtk_widget_show_all (export_window);
7403       
7404   gtk_clist_clear (GTK_CLIST (export_ctree));
7405
7406   node = GTK_CTREE_NODE (g_list_nth (GTK_CLIST (ctree)->row_list,
7407                                      GTK_CLIST (ctree)->focus_row));
7408   if (!node)
7409     return;
7410
7411   gnode = gtk_ctree_export_to_gnode (ctree, NULL, NULL, node,
7412                                      ctree2gnode, NULL);
7413   if (gnode)
7414     {
7415       gtk_ctree_insert_gnode (export_ctree, NULL, NULL, gnode,
7416                               gnode2ctree, NULL);
7417       g_node_destroy (gnode);
7418     }
7419 }
7420
7421 void change_indent (GtkWidget *widget, GtkCTree *ctree)
7422 {
7423   gtk_ctree_set_indent (ctree, GTK_ADJUSTMENT (widget)->value);
7424 }
7425
7426 void change_spacing (GtkWidget *widget, GtkCTree *ctree)
7427 {
7428   gtk_ctree_set_spacing (ctree, GTK_ADJUSTMENT (widget)->value);
7429 }
7430
7431 void change_row_height (GtkWidget *widget, GtkCList *clist)
7432 {
7433   gtk_clist_set_row_height (clist, GTK_ADJUSTMENT (widget)->value);
7434 }
7435
7436 void set_background (GtkCTree *ctree, GtkCTreeNode *node, gpointer data)
7437 {
7438   GtkStyle *style = NULL;
7439   
7440   if (!node)
7441     return;
7442   
7443   if (ctree->line_style != GTK_CTREE_LINES_TABBED)
7444     {
7445       if (!GTK_CTREE_ROW (node)->is_leaf)
7446         style = GTK_CTREE_ROW (node)->row.data;
7447       else if (GTK_CTREE_ROW (node)->parent)
7448         style = GTK_CTREE_ROW (GTK_CTREE_ROW (node)->parent)->row.data;
7449     }
7450
7451   gtk_ctree_node_set_row_style (ctree, node, style);
7452 }
7453
7454 void 
7455 ctree_toggle_line_style (GtkWidget *widget, gpointer data)
7456 {
7457   GtkCTree *ctree;
7458   gint i;
7459
7460   ctree = GTK_CTREE (data);
7461
7462   if (!GTK_WIDGET_MAPPED (widget))
7463     return;
7464
7465   i = gtk_option_menu_get_history (GTK_OPTION_MENU (widget));
7466
7467   if ((ctree->line_style == GTK_CTREE_LINES_TABBED && 
7468        ((GtkCTreeLineStyle) i) != GTK_CTREE_LINES_TABBED) ||
7469       (ctree->line_style != GTK_CTREE_LINES_TABBED && 
7470        ((GtkCTreeLineStyle) i) == GTK_CTREE_LINES_TABBED))
7471     gtk_ctree_pre_recursive (ctree, NULL, set_background, NULL);
7472   gtk_ctree_set_line_style (ctree, i);
7473   line_style = i;
7474 }
7475
7476 void 
7477 ctree_toggle_expander_style (GtkWidget *widget, gpointer data)
7478 {
7479   GtkCTree *ctree;
7480   gint i;
7481
7482   ctree = GTK_CTREE (data);
7483
7484   if (!GTK_WIDGET_MAPPED (widget))
7485     return;
7486   
7487   i = gtk_option_menu_get_history (GTK_OPTION_MENU (widget));
7488   
7489   gtk_ctree_set_expander_style (ctree, (GtkCTreeExpanderStyle) i);
7490 }
7491
7492 void 
7493 ctree_toggle_justify (GtkWidget *widget, gpointer data)
7494 {
7495   GtkCTree *ctree;
7496   gint i;
7497
7498   ctree = GTK_CTREE (data);
7499
7500   if (!GTK_WIDGET_MAPPED (widget))
7501     return;
7502
7503   i = gtk_option_menu_get_history (GTK_OPTION_MENU (widget));
7504
7505   gtk_clist_set_column_justification (GTK_CLIST (ctree), ctree->tree_column, 
7506                                       (GtkJustification) i);
7507 }
7508
7509 void 
7510 ctree_toggle_sel_mode (GtkWidget *widget, gpointer data)
7511 {
7512   GtkCTree *ctree;
7513   gint i;
7514
7515   ctree = GTK_CTREE (data);
7516
7517   if (!GTK_WIDGET_MAPPED (widget))
7518     return;
7519
7520   i = gtk_option_menu_get_history (GTK_OPTION_MENU (widget));
7521
7522   gtk_clist_set_selection_mode (GTK_CLIST (ctree), selection_modes[i]);
7523   after_press (ctree, NULL);
7524 }
7525     
7526 void build_recursive (GtkCTree *ctree, gint cur_depth, gint depth, 
7527                       gint num_books, gint num_pages, GtkCTreeNode *parent)
7528 {
7529   gchar *text[2];
7530   gchar buf1[60];
7531   gchar buf2[60];
7532   GtkCTreeNode *sibling;
7533   CTreePixmaps *pixmaps;
7534   gint i;
7535
7536   text[0] = buf1;
7537   text[1] = buf2;
7538   sibling = NULL;
7539
7540   pixmaps = get_ctree_pixmaps (ctree);
7541
7542   for (i = num_pages + num_books; i > num_books; i--)
7543     {
7544       pages++;
7545       sprintf (buf1, "Page %02d", (gint) rand() % 100);
7546       sprintf (buf2, "Item %d-%d", cur_depth, i);
7547       sibling = gtk_ctree_insert_node (ctree, parent, sibling, text, 5,
7548                                        pixmaps->pixmap3, pixmaps->mask3, NULL, NULL,
7549                                        TRUE, FALSE);
7550
7551       if (parent && ctree->line_style == GTK_CTREE_LINES_TABBED)
7552         gtk_ctree_node_set_row_style (ctree, sibling,
7553                                       GTK_CTREE_ROW (parent)->row.style);
7554     }
7555
7556   if (cur_depth == depth)
7557     return;
7558
7559   for (i = num_books; i > 0; i--)
7560     {
7561       GtkStyle *style;
7562
7563       books++;
7564       sprintf (buf1, "Book %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->pixmap1, pixmaps->mask1, pixmaps->pixmap2, pixmaps->mask2,
7568                                        FALSE, FALSE);
7569
7570       style = gtk_style_new ();
7571       switch (cur_depth % 3)
7572         {
7573         case 0:
7574           style->base[GTK_STATE_NORMAL].red   = 10000 * (cur_depth % 6);
7575           style->base[GTK_STATE_NORMAL].green = 0;
7576           style->base[GTK_STATE_NORMAL].blue  = 65535 - ((i * 10000) % 65535);
7577           break;
7578         case 1:
7579           style->base[GTK_STATE_NORMAL].red   = 10000 * (cur_depth % 6);
7580           style->base[GTK_STATE_NORMAL].green = 65535 - ((i * 10000) % 65535);
7581           style->base[GTK_STATE_NORMAL].blue  = 0;
7582           break;
7583         default:
7584           style->base[GTK_STATE_NORMAL].red   = 65535 - ((i * 10000) % 65535);
7585           style->base[GTK_STATE_NORMAL].green = 0;
7586           style->base[GTK_STATE_NORMAL].blue  = 10000 * (cur_depth % 6);
7587           break;
7588         }
7589       gtk_ctree_node_set_row_data_full (ctree, sibling, style,
7590                                         (GDestroyNotify) g_object_unref);
7591
7592       if (ctree->line_style == GTK_CTREE_LINES_TABBED)
7593         gtk_ctree_node_set_row_style (ctree, sibling, style);
7594
7595       build_recursive (ctree, cur_depth + 1, depth, num_books, num_pages,
7596                        sibling);
7597     }
7598 }
7599
7600 void rebuild_tree (GtkWidget *widget, GtkCTree *ctree)
7601 {
7602   gchar *text [2];
7603   gchar label1[] = "Root";
7604   gchar label2[] = "";
7605   GtkCTreeNode *parent;
7606   GtkStyle *style;
7607   guint b, d, p, n;
7608   CTreePixmaps *pixmaps;
7609
7610   pixmaps = get_ctree_pixmaps (ctree);
7611
7612   text[0] = label1;
7613   text[1] = label2;
7614   
7615   d = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (spin1)); 
7616   b = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (spin2));
7617   p = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (spin3));
7618
7619   n = ((pow (b, d) - 1) / (b - 1)) * (p + 1);
7620
7621   if (n > 100000)
7622     {
7623       g_print ("%d total items? Try less\n",n);
7624       return;
7625     }
7626
7627   gtk_clist_freeze (GTK_CLIST (ctree));
7628   gtk_clist_clear (GTK_CLIST (ctree));
7629
7630   books = 1;
7631   pages = 0;
7632
7633   parent = gtk_ctree_insert_node (ctree, NULL, NULL, text, 5, pixmaps->pixmap1,
7634                                   pixmaps->mask1, pixmaps->pixmap2, pixmaps->mask2, FALSE, TRUE);
7635
7636   style = gtk_style_new ();
7637   style->base[GTK_STATE_NORMAL].red   = 0;
7638   style->base[GTK_STATE_NORMAL].green = 45000;
7639   style->base[GTK_STATE_NORMAL].blue  = 55000;
7640   gtk_ctree_node_set_row_data_full (ctree, parent, style,
7641                                     (GDestroyNotify) g_object_unref);
7642
7643   if (ctree->line_style == GTK_CTREE_LINES_TABBED)
7644     gtk_ctree_node_set_row_style (ctree, parent, style);
7645
7646   build_recursive (ctree, 1, d, b, p, parent);
7647   gtk_clist_thaw (GTK_CLIST (ctree));
7648   after_press (ctree, NULL);
7649 }
7650
7651 static void 
7652 ctree_click_column (GtkCTree *ctree, gint column, gpointer data)
7653 {
7654   GtkCList *clist;
7655
7656   clist = GTK_CLIST (ctree);
7657
7658   if (column == clist->sort_column)
7659     {
7660       if (clist->sort_type == GTK_SORT_ASCENDING)
7661         clist->sort_type = GTK_SORT_DESCENDING;
7662       else
7663         clist->sort_type = GTK_SORT_ASCENDING;
7664     }
7665   else
7666     gtk_clist_set_sort_column (clist, column);
7667
7668   gtk_ctree_sort_recursive (ctree, NULL);
7669 }
7670
7671 void create_ctree (GtkWidget *widget)
7672 {
7673   static GtkWidget *window = NULL;
7674   GtkTooltips *tooltips;
7675   GtkCTree *ctree;
7676   GtkWidget *scrolled_win;
7677   GtkWidget *vbox;
7678   GtkWidget *bbox;
7679   GtkWidget *mbox;
7680   GtkWidget *hbox;
7681   GtkWidget *hbox2;
7682   GtkWidget *frame;
7683   GtkWidget *label;
7684   GtkWidget *button;
7685   GtkWidget *check;
7686   GtkAdjustment *adj;
7687   GtkWidget *spinner;
7688
7689   char *title[] = { "Tree" , "Info" };
7690   char buf[80];
7691
7692   static gchar *items1[] =
7693   {
7694     "No lines",
7695     "Solid",
7696     "Dotted",
7697     "Tabbed"
7698   };
7699
7700   static gchar *items2[] =
7701   {
7702     "None",
7703     "Square",
7704     "Triangle",
7705     "Circular"
7706   };
7707
7708   static gchar *items3[] =
7709   {
7710     "Left",
7711     "Right"
7712   };
7713   
7714   if (!window)
7715     {
7716       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7717       gtk_window_set_screen (GTK_WINDOW (window), 
7718                              gtk_widget_get_screen (widget));
7719
7720       g_signal_connect (window, "destroy",
7721                         G_CALLBACK (gtk_widget_destroyed),
7722                         &window);
7723
7724       gtk_window_set_title (GTK_WINDOW (window), "GtkCTree");
7725       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
7726
7727       tooltips = gtk_tooltips_new ();
7728       g_object_ref (tooltips);
7729       gtk_object_sink (GTK_OBJECT (tooltips));
7730
7731       g_object_set_data_full (G_OBJECT (window), "tooltips", tooltips,
7732                               g_object_unref);
7733
7734       vbox = gtk_vbox_new (FALSE, 0);
7735       gtk_container_add (GTK_CONTAINER (window), vbox);
7736
7737       hbox = gtk_hbox_new (FALSE, 5);
7738       gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
7739       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
7740       
7741       label = gtk_label_new ("Depth :");
7742       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
7743       
7744       adj = (GtkAdjustment *) gtk_adjustment_new (4, 1, 10, 1, 5, 0);
7745       spin1 = gtk_spin_button_new (adj, 0, 0);
7746       gtk_box_pack_start (GTK_BOX (hbox), spin1, FALSE, TRUE, 5);
7747   
7748       label = gtk_label_new ("Books :");
7749       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
7750       
7751       adj = (GtkAdjustment *) gtk_adjustment_new (3, 1, 20, 1, 5, 0);
7752       spin2 = gtk_spin_button_new (adj, 0, 0);
7753       gtk_box_pack_start (GTK_BOX (hbox), spin2, FALSE, TRUE, 5);
7754
7755       label = gtk_label_new ("Pages :");
7756       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
7757       
7758       adj = (GtkAdjustment *) gtk_adjustment_new (5, 1, 20, 1, 5, 0);
7759       spin3 = gtk_spin_button_new (adj, 0, 0);
7760       gtk_box_pack_start (GTK_BOX (hbox), spin3, FALSE, TRUE, 5);
7761
7762       button = gtk_button_new_with_label ("Close");
7763       gtk_box_pack_end (GTK_BOX (hbox), button, TRUE, TRUE, 0);
7764
7765       g_signal_connect_swapped (button, "clicked",
7766                                 G_CALLBACK (gtk_widget_destroy),
7767                                 window);
7768
7769       button = gtk_button_new_with_label ("Rebuild Tree");
7770       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
7771
7772       scrolled_win = gtk_scrolled_window_new (NULL, NULL);
7773       gtk_container_set_border_width (GTK_CONTAINER (scrolled_win), 5);
7774       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
7775                                       GTK_POLICY_AUTOMATIC,
7776                                       GTK_POLICY_ALWAYS);
7777       gtk_box_pack_start (GTK_BOX (vbox), scrolled_win, TRUE, TRUE, 0);
7778
7779       ctree = GTK_CTREE (gtk_ctree_new_with_titles (2, 0, title));
7780       gtk_container_add (GTK_CONTAINER (scrolled_win), GTK_WIDGET (ctree));
7781
7782       gtk_clist_set_column_auto_resize (GTK_CLIST (ctree), 0, TRUE);
7783       gtk_clist_set_column_width (GTK_CLIST (ctree), 1, 200);
7784       gtk_clist_set_selection_mode (GTK_CLIST (ctree), GTK_SELECTION_EXTENDED);
7785       gtk_ctree_set_line_style (ctree, GTK_CTREE_LINES_DOTTED);
7786       line_style = GTK_CTREE_LINES_DOTTED;
7787
7788       g_signal_connect (button, "clicked",
7789                         G_CALLBACK (rebuild_tree), ctree);
7790       g_signal_connect (ctree, "click_column",
7791                         G_CALLBACK (ctree_click_column), NULL);
7792
7793       g_signal_connect_after (ctree, "button_press_event",
7794                               G_CALLBACK (after_press), NULL);
7795       g_signal_connect_after (ctree, "button_release_event",
7796                               G_CALLBACK (after_press), NULL);
7797       g_signal_connect_after (ctree, "tree_move",
7798                               G_CALLBACK (after_move), NULL);
7799       g_signal_connect_after (ctree, "end_selection",
7800                               G_CALLBACK (after_press), NULL);
7801       g_signal_connect_after (ctree, "toggle_focus_row",
7802                               G_CALLBACK (after_press), NULL);
7803       g_signal_connect_after (ctree, "select_all",
7804                               G_CALLBACK (after_press), NULL);
7805       g_signal_connect_after (ctree, "unselect_all",
7806                               G_CALLBACK (after_press), NULL);
7807       g_signal_connect_after (ctree, "scroll_vertical",
7808                               G_CALLBACK (after_press), NULL);
7809
7810       bbox = gtk_hbox_new (FALSE, 5);
7811       gtk_container_set_border_width (GTK_CONTAINER (bbox), 5);
7812       gtk_box_pack_start (GTK_BOX (vbox), bbox, FALSE, TRUE, 0);
7813
7814       mbox = gtk_vbox_new (TRUE, 5);
7815       gtk_box_pack_start (GTK_BOX (bbox), mbox, FALSE, TRUE, 0);
7816
7817       label = gtk_label_new ("Row Height :");
7818       gtk_box_pack_start (GTK_BOX (mbox), label, FALSE, FALSE, 0);
7819
7820       label = gtk_label_new ("Indent :");
7821       gtk_box_pack_start (GTK_BOX (mbox), label, FALSE, FALSE, 0);
7822
7823       label = gtk_label_new ("Spacing :");
7824       gtk_box_pack_start (GTK_BOX (mbox), label, FALSE, FALSE, 0);
7825
7826       mbox = gtk_vbox_new (TRUE, 5);
7827       gtk_box_pack_start (GTK_BOX (bbox), mbox, FALSE, TRUE, 0);
7828
7829       adj = (GtkAdjustment *) gtk_adjustment_new (20, 12, 100, 1, 10, 0);
7830       spinner = gtk_spin_button_new (adj, 0, 0);
7831       gtk_box_pack_start (GTK_BOX (mbox), spinner, FALSE, FALSE, 5);
7832       gtk_tooltips_set_tip (tooltips, spinner,
7833                             "Row height of list items", NULL);
7834       g_signal_connect (adj, "value_changed",
7835                         G_CALLBACK (change_row_height), ctree);
7836       gtk_clist_set_row_height ( GTK_CLIST (ctree), adj->value);
7837
7838       adj = (GtkAdjustment *) gtk_adjustment_new (20, 0, 60, 1, 10, 0);
7839       spinner = gtk_spin_button_new (adj, 0, 0);
7840       gtk_box_pack_start (GTK_BOX (mbox), spinner, FALSE, FALSE, 5);
7841       gtk_tooltips_set_tip (tooltips, spinner, "Tree Indentation.", NULL);
7842       g_signal_connect (adj, "value_changed",
7843                         G_CALLBACK (change_indent), ctree);
7844
7845       adj = (GtkAdjustment *) gtk_adjustment_new (5, 0, 60, 1, 10, 0);
7846       spinner = gtk_spin_button_new (adj, 0, 0);
7847       gtk_box_pack_start (GTK_BOX (mbox), spinner, FALSE, FALSE, 5);
7848       gtk_tooltips_set_tip (tooltips, spinner, "Tree Spacing.", NULL);
7849       g_signal_connect (adj, "value_changed",
7850                         G_CALLBACK (change_spacing), ctree);
7851
7852       mbox = gtk_vbox_new (TRUE, 5);
7853       gtk_box_pack_start (GTK_BOX (bbox), mbox, FALSE, TRUE, 0);
7854
7855       hbox = gtk_hbox_new (FALSE, 5);
7856       gtk_box_pack_start (GTK_BOX (mbox), hbox, FALSE, FALSE, 0);
7857
7858       button = gtk_button_new_with_label ("Expand All");
7859       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
7860       g_signal_connect (button, "clicked",
7861                         G_CALLBACK (expand_all), ctree);
7862
7863       button = gtk_button_new_with_label ("Collapse All");
7864       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
7865       g_signal_connect (button, "clicked",
7866                         G_CALLBACK (collapse_all), ctree);
7867
7868       button = gtk_button_new_with_label ("Change Style");
7869       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
7870       g_signal_connect (button, "clicked",
7871                         G_CALLBACK (change_style), ctree);
7872
7873       button = gtk_button_new_with_label ("Export Tree");
7874       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
7875       g_signal_connect (button, "clicked",
7876                         G_CALLBACK (export_ctree), ctree);
7877
7878       hbox = gtk_hbox_new (FALSE, 5);
7879       gtk_box_pack_start (GTK_BOX (mbox), hbox, FALSE, FALSE, 0);
7880
7881       button = gtk_button_new_with_label ("Select All");
7882       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
7883       g_signal_connect (button, "clicked",
7884                         G_CALLBACK (select_all), ctree);
7885
7886       button = gtk_button_new_with_label ("Unselect All");
7887       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
7888       g_signal_connect (button, "clicked",
7889                         G_CALLBACK (unselect_all), ctree);
7890
7891       button = gtk_button_new_with_label ("Remove Selection");
7892       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
7893       g_signal_connect (button, "clicked",
7894                         G_CALLBACK (remove_selection), ctree);
7895
7896       check = gtk_check_button_new_with_label ("Reorderable");
7897       gtk_box_pack_start (GTK_BOX (hbox), check, FALSE, TRUE, 0);
7898       gtk_tooltips_set_tip (tooltips, check,
7899                             "Tree items can be reordered by dragging.", NULL);
7900       g_signal_connect (check, "clicked",
7901                         G_CALLBACK (toggle_reorderable), ctree);
7902       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check), TRUE);
7903
7904       hbox = gtk_hbox_new (TRUE, 5);
7905       gtk_box_pack_start (GTK_BOX (mbox), hbox, FALSE, FALSE, 0);
7906
7907       omenu1 = build_option_menu (items1, 4, 2, 
7908                                   ctree_toggle_line_style,
7909                                   ctree);
7910       gtk_box_pack_start (GTK_BOX (hbox), omenu1, FALSE, TRUE, 0);
7911       gtk_tooltips_set_tip (tooltips, omenu1, "The tree's line style.", NULL);
7912
7913       omenu2 = build_option_menu (items2, 4, 1, 
7914                                   ctree_toggle_expander_style,
7915                                   ctree);
7916       gtk_box_pack_start (GTK_BOX (hbox), omenu2, FALSE, TRUE, 0);
7917       gtk_tooltips_set_tip (tooltips, omenu2, "The tree's expander style.",
7918                             NULL);
7919
7920       omenu3 = build_option_menu (items3, 2, 0, 
7921                                   ctree_toggle_justify, ctree);
7922       gtk_box_pack_start (GTK_BOX (hbox), omenu3, FALSE, TRUE, 0);
7923       gtk_tooltips_set_tip (tooltips, omenu3, "The tree's justification.",
7924                             NULL);
7925
7926       omenu4 = build_option_menu (selection_mode_items, 3, 3, 
7927                                   ctree_toggle_sel_mode, ctree);
7928       gtk_box_pack_start (GTK_BOX (hbox), omenu4, FALSE, TRUE, 0);
7929       gtk_tooltips_set_tip (tooltips, omenu4, "The list's selection mode.",
7930                             NULL);
7931
7932       gtk_widget_realize (window);
7933       
7934       gtk_widget_set_size_request (GTK_WIDGET (ctree), -1, 300);
7935
7936       frame = gtk_frame_new (NULL);
7937       gtk_container_set_border_width (GTK_CONTAINER (frame), 0);
7938       gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT);
7939       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
7940
7941       hbox = gtk_hbox_new (TRUE, 2);
7942       gtk_container_set_border_width (GTK_CONTAINER (hbox), 2);
7943       gtk_container_add (GTK_CONTAINER (frame), hbox);
7944
7945       frame = gtk_frame_new (NULL);
7946       gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
7947       gtk_box_pack_start (GTK_BOX (hbox), frame, FALSE, TRUE, 0);
7948
7949       hbox2 = gtk_hbox_new (FALSE, 0);
7950       gtk_container_set_border_width (GTK_CONTAINER (hbox2), 2);
7951       gtk_container_add (GTK_CONTAINER (frame), hbox2);
7952
7953       label = gtk_label_new ("Books :");
7954       gtk_box_pack_start (GTK_BOX (hbox2), label, FALSE, TRUE, 0);
7955
7956       sprintf (buf, "%d", books);
7957       book_label = gtk_label_new (buf);
7958       gtk_box_pack_end (GTK_BOX (hbox2), book_label, FALSE, TRUE, 5);
7959
7960       frame = gtk_frame_new (NULL);
7961       gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
7962       gtk_box_pack_start (GTK_BOX (hbox), frame, FALSE, TRUE, 0);
7963
7964       hbox2 = gtk_hbox_new (FALSE, 0);
7965       gtk_container_set_border_width (GTK_CONTAINER (hbox2), 2);
7966       gtk_container_add (GTK_CONTAINER (frame), hbox2);
7967
7968       label = gtk_label_new ("Pages :");
7969       gtk_box_pack_start (GTK_BOX (hbox2), label, FALSE, TRUE, 0);
7970
7971       sprintf (buf, "%d", pages);
7972       page_label = gtk_label_new (buf);
7973       gtk_box_pack_end (GTK_BOX (hbox2), page_label, FALSE, TRUE, 5);
7974
7975       frame = gtk_frame_new (NULL);
7976       gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
7977       gtk_box_pack_start (GTK_BOX (hbox), frame, FALSE, TRUE, 0);
7978
7979       hbox2 = gtk_hbox_new (FALSE, 0);
7980       gtk_container_set_border_width (GTK_CONTAINER (hbox2), 2);
7981       gtk_container_add (GTK_CONTAINER (frame), hbox2);
7982
7983       label = gtk_label_new ("Selected :");
7984       gtk_box_pack_start (GTK_BOX (hbox2), label, FALSE, TRUE, 0);
7985
7986       sprintf (buf, "%d", g_list_length (GTK_CLIST (ctree)->selection));
7987       sel_label = gtk_label_new (buf);
7988       gtk_box_pack_end (GTK_BOX (hbox2), sel_label, FALSE, TRUE, 5);
7989
7990       frame = gtk_frame_new (NULL);
7991       gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
7992       gtk_box_pack_start (GTK_BOX (hbox), frame, FALSE, TRUE, 0);
7993
7994       hbox2 = gtk_hbox_new (FALSE, 0);
7995       gtk_container_set_border_width (GTK_CONTAINER (hbox2), 2);
7996       gtk_container_add (GTK_CONTAINER (frame), hbox2);
7997
7998       label = gtk_label_new ("Visible :");
7999       gtk_box_pack_start (GTK_BOX (hbox2), label, FALSE, TRUE, 0);
8000
8001       sprintf (buf, "%d", g_list_length (GTK_CLIST (ctree)->row_list));
8002       vis_label = gtk_label_new (buf);
8003       gtk_box_pack_end (GTK_BOX (hbox2), vis_label, FALSE, TRUE, 5);
8004
8005       rebuild_tree (NULL, ctree);
8006     }
8007
8008   if (!GTK_WIDGET_VISIBLE (window))
8009     gtk_widget_show_all (window);
8010   else
8011     gtk_widget_destroy (window);
8012 }
8013
8014 /*
8015  * GtkColorSelection
8016  */
8017
8018 void
8019 color_selection_ok (GtkWidget               *w,
8020                     GtkColorSelectionDialog *cs)
8021 {
8022   GtkColorSelection *colorsel;
8023   gdouble color[4];
8024
8025   colorsel=GTK_COLOR_SELECTION(cs->colorsel);
8026
8027   gtk_color_selection_get_color(colorsel,color);
8028   gtk_color_selection_set_color(colorsel,color);
8029 }
8030
8031 void
8032 color_selection_changed (GtkWidget *w,
8033                          GtkColorSelectionDialog *cs)
8034 {
8035   GtkColorSelection *colorsel;
8036   gdouble color[4];
8037
8038   colorsel=GTK_COLOR_SELECTION(cs->colorsel);
8039   gtk_color_selection_get_color(colorsel,color);
8040 }
8041
8042 #if 0 /* unused */
8043 static void
8044 opacity_toggled_cb (GtkWidget *w,
8045                     GtkColorSelectionDialog *cs)
8046 {
8047   GtkColorSelection *colorsel;
8048
8049   colorsel = GTK_COLOR_SELECTION (cs->colorsel);
8050   gtk_color_selection_set_has_opacity_control (colorsel,
8051                                                gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w)));
8052 }
8053
8054 static void
8055 palette_toggled_cb (GtkWidget *w,
8056                     GtkColorSelectionDialog *cs)
8057 {
8058   GtkColorSelection *colorsel;
8059
8060   colorsel = GTK_COLOR_SELECTION (cs->colorsel);
8061   gtk_color_selection_set_has_palette (colorsel,
8062                                        gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w)));
8063 }
8064 #endif
8065
8066 void
8067 create_color_selection (GtkWidget *widget)
8068 {
8069   static GtkWidget *window = NULL;
8070
8071   if (!window)
8072     {
8073       GtkWidget *picker;
8074       GtkWidget *hbox;
8075       GtkWidget *label;
8076       
8077       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8078       gtk_window_set_screen (GTK_WINDOW (window), 
8079                              gtk_widget_get_screen (widget));
8080                              
8081       g_signal_connect (window, "destroy",
8082                         G_CALLBACK (gtk_widget_destroyed),
8083                         &window);
8084
8085       gtk_window_set_title (GTK_WINDOW (window), "GtkColorButton");
8086       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
8087
8088       hbox = gtk_hbox_new (FALSE, 8);
8089       gtk_container_set_border_width (GTK_CONTAINER (hbox), 8);
8090       gtk_container_add (GTK_CONTAINER (window), hbox);
8091       
8092       label = gtk_label_new ("Pick a color");
8093       gtk_container_add (GTK_CONTAINER (hbox), label);
8094
8095       picker = gtk_color_button_new ();
8096       gtk_color_button_set_use_alpha (GTK_COLOR_BUTTON (picker), TRUE);
8097       gtk_container_add (GTK_CONTAINER (hbox), picker);
8098     }
8099
8100   if (!GTK_WIDGET_VISIBLE (window))
8101     gtk_widget_show_all (window);
8102   else
8103     gtk_widget_destroy (window);
8104 }
8105
8106 /*
8107  * GtkFileSelection
8108  */
8109
8110 void
8111 show_fileops (GtkWidget        *widget,
8112               GtkFileSelection *fs)
8113 {
8114   gboolean show_ops;
8115
8116   show_ops = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
8117
8118   if (show_ops)
8119     gtk_file_selection_show_fileop_buttons (fs);
8120   else
8121     gtk_file_selection_hide_fileop_buttons (fs);
8122 }
8123
8124 void
8125 select_multiple (GtkWidget        *widget,
8126                  GtkFileSelection *fs)
8127 {
8128   gboolean select_multiple;
8129
8130   select_multiple = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
8131   gtk_file_selection_set_select_multiple (fs, select_multiple);
8132 }
8133
8134 void
8135 file_selection_ok (GtkFileSelection *fs)
8136 {
8137   int i;
8138   gchar **selections;
8139
8140   selections = gtk_file_selection_get_selections (fs);
8141
8142   for (i = 0; selections[i] != NULL; i++)
8143     g_print ("%s\n", selections[i]);
8144
8145   g_strfreev (selections);
8146
8147   gtk_widget_destroy (GTK_WIDGET (fs));
8148 }
8149
8150 void
8151 create_file_selection (GtkWidget *widget)
8152 {
8153   static GtkWidget *window = NULL;
8154   GtkWidget *button;
8155
8156   if (!window)
8157     {
8158       window = gtk_file_selection_new ("file selection dialog");
8159       gtk_window_set_screen (GTK_WINDOW (window),
8160                              gtk_widget_get_screen (widget));
8161
8162       gtk_file_selection_hide_fileop_buttons (GTK_FILE_SELECTION (window));
8163
8164       gtk_window_set_position (GTK_WINDOW (window), GTK_WIN_POS_MOUSE);
8165
8166       g_signal_connect (window, "destroy",
8167                         G_CALLBACK (gtk_widget_destroyed),
8168                         &window);
8169
8170       g_signal_connect_swapped (GTK_FILE_SELECTION (window)->ok_button,
8171                                 "clicked",
8172                                 G_CALLBACK (file_selection_ok),
8173                                 window);
8174       g_signal_connect_swapped (GTK_FILE_SELECTION (window)->cancel_button,
8175                                 "clicked",
8176                                 G_CALLBACK (gtk_widget_destroy),
8177                                 window);
8178       
8179       button = gtk_check_button_new_with_label ("Show Fileops");
8180       g_signal_connect (button, "toggled",
8181                         G_CALLBACK (show_fileops),
8182                         window);
8183       gtk_box_pack_start (GTK_BOX (GTK_FILE_SELECTION (window)->action_area), 
8184                           button, FALSE, FALSE, 0);
8185       gtk_widget_show (button);
8186
8187       button = gtk_check_button_new_with_label ("Select Multiple");
8188       g_signal_connect (button, "clicked",
8189                         G_CALLBACK (select_multiple),
8190                         window);
8191       gtk_box_pack_start (GTK_BOX (GTK_FILE_SELECTION (window)->action_area), 
8192                           button, FALSE, FALSE, 0);
8193       gtk_widget_show (button);
8194     }
8195   
8196   if (!GTK_WIDGET_VISIBLE (window))
8197     gtk_widget_show (window);
8198   else
8199     gtk_widget_destroy (window);
8200 }
8201
8202 void
8203 flipping_toggled_cb (GtkWidget *widget, gpointer data)
8204 {
8205   int state = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
8206   int new_direction = state ? GTK_TEXT_DIR_RTL : GTK_TEXT_DIR_LTR;
8207
8208   gtk_widget_set_default_direction (new_direction);
8209 }
8210
8211 static void
8212 set_direction_recurse (GtkWidget *widget,
8213                        gpointer   data)
8214 {
8215   GtkTextDirection *dir = data;
8216   
8217   gtk_widget_set_direction (widget, *dir);
8218   if (GTK_IS_CONTAINER (widget))
8219     gtk_container_foreach (GTK_CONTAINER (widget),
8220                            set_direction_recurse,
8221                            data);
8222 }
8223
8224 static GtkWidget *
8225 create_forward_back (const char       *title,
8226                      GtkTextDirection  text_dir)
8227 {
8228   GtkWidget *frame = gtk_frame_new (title);
8229   GtkWidget *bbox = gtk_hbutton_box_new ();
8230   GtkWidget *back_button = gtk_button_new_from_stock (GTK_STOCK_GO_BACK);
8231   GtkWidget *forward_button = gtk_button_new_from_stock (GTK_STOCK_GO_FORWARD);
8232
8233   gtk_container_set_border_width (GTK_CONTAINER (bbox), 5);
8234   
8235   gtk_container_add (GTK_CONTAINER (frame), bbox);
8236   gtk_container_add (GTK_CONTAINER (bbox), back_button);
8237   gtk_container_add (GTK_CONTAINER (bbox), forward_button);
8238
8239   set_direction_recurse (frame, &text_dir);
8240
8241   return frame;
8242 }
8243
8244 void
8245 create_flipping (GtkWidget *widget)
8246 {
8247   static GtkWidget *window = NULL;
8248   GtkWidget *check_button, *button;
8249
8250   if (!window)
8251     {
8252       window = gtk_dialog_new ();
8253
8254       gtk_window_set_screen (GTK_WINDOW (window),
8255                              gtk_widget_get_screen (widget));
8256
8257       g_signal_connect (window, "destroy",
8258                         G_CALLBACK (gtk_widget_destroyed),
8259                         &window);
8260
8261       gtk_window_set_title (GTK_WINDOW (window), "Bidirectional Flipping");
8262
8263       check_button = gtk_check_button_new_with_label ("Right-to-left global direction");
8264       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
8265                           check_button, TRUE, TRUE, 0);
8266
8267       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
8268                           create_forward_back ("Default", GTK_TEXT_DIR_NONE),
8269                           TRUE, TRUE, 0);
8270
8271       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
8272                           create_forward_back ("Left-to-Right", GTK_TEXT_DIR_LTR),
8273                           TRUE, TRUE, 0);
8274
8275       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
8276                           create_forward_back ("Right-to-Left", GTK_TEXT_DIR_RTL),
8277                           TRUE, TRUE, 0);
8278
8279       if (gtk_widget_get_default_direction () == GTK_TEXT_DIR_RTL)
8280         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button), TRUE);
8281
8282       g_signal_connect (check_button, "toggled",
8283                         G_CALLBACK (flipping_toggled_cb), NULL);
8284
8285       gtk_container_set_border_width (GTK_CONTAINER (check_button), 10);
8286       
8287       button = gtk_button_new_with_label ("Close");
8288       g_signal_connect_swapped (button, "clicked",
8289                                 G_CALLBACK (gtk_widget_destroy), window);
8290       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
8291                           button, TRUE, TRUE, 0);
8292     }
8293   
8294   if (!GTK_WIDGET_VISIBLE (window))
8295     gtk_widget_show_all (window);
8296   else
8297     gtk_widget_destroy (window);
8298 }
8299
8300 /*
8301  * Focus test
8302  */
8303
8304 static GtkWidget*
8305 make_focus_table (GList **list)
8306 {
8307   GtkWidget *table;
8308   gint i, j;
8309   
8310   table = gtk_table_new (5, 5, FALSE);
8311
8312   i = 0;
8313   j = 0;
8314
8315   while (i < 5)
8316     {
8317       j = 0;
8318       while (j < 5)
8319         {
8320           GtkWidget *widget;
8321           
8322           if ((i + j) % 2)
8323             widget = gtk_entry_new ();
8324           else
8325             widget = gtk_button_new_with_label ("Foo");
8326
8327           *list = g_list_prepend (*list, widget);
8328           
8329           gtk_table_attach (GTK_TABLE (table),
8330                             widget,
8331                             i, i + 1,
8332                             j, j + 1,
8333                             GTK_EXPAND | GTK_FILL,
8334                             GTK_EXPAND | GTK_FILL,
8335                             5, 5);
8336           
8337           ++j;
8338         }
8339
8340       ++i;
8341     }
8342
8343   *list = g_list_reverse (*list);
8344   
8345   return table;
8346 }
8347
8348 static void
8349 create_focus (GtkWidget *widget)
8350 {
8351   static GtkWidget *window = NULL;
8352   
8353   if (!window)
8354     {
8355       GtkWidget *table;
8356       GtkWidget *frame;
8357       GList *list = NULL;
8358       
8359       window = gtk_dialog_new_with_buttons ("Keyboard focus navigation",
8360                                             NULL, 0,
8361                                             GTK_STOCK_CLOSE,
8362                                             GTK_RESPONSE_NONE,
8363                                             NULL);
8364
8365       gtk_window_set_screen (GTK_WINDOW (window),
8366                              gtk_widget_get_screen (widget));
8367
8368       g_signal_connect (window, "destroy",
8369                         G_CALLBACK (gtk_widget_destroyed),
8370                         &window);
8371
8372       g_signal_connect (window, "response",
8373                         G_CALLBACK (gtk_widget_destroy),
8374                         NULL);
8375       
8376       gtk_window_set_title (GTK_WINDOW (window), "Keyboard Focus Navigation");
8377
8378       frame = gtk_frame_new ("Weird tab focus chain");
8379
8380       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
8381                           frame, TRUE, TRUE, 0);
8382       
8383       table = make_focus_table (&list);
8384
8385       gtk_container_add (GTK_CONTAINER (frame), table);
8386
8387       gtk_container_set_focus_chain (GTK_CONTAINER (table),
8388                                      list);
8389
8390       g_list_free (list);
8391       
8392       frame = gtk_frame_new ("Default tab focus chain");
8393
8394       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
8395                           frame, TRUE, TRUE, 0);
8396
8397       list = NULL;
8398       table = make_focus_table (&list);
8399
8400       g_list_free (list);
8401       
8402       gtk_container_add (GTK_CONTAINER (frame), table);      
8403     }
8404   
8405   if (!GTK_WIDGET_VISIBLE (window))
8406     gtk_widget_show_all (window);
8407   else
8408     gtk_widget_destroy (window);
8409 }
8410
8411 /*
8412  * GtkFontSelection
8413  */
8414
8415 void
8416 font_selection_ok (GtkWidget              *w,
8417                    GtkFontSelectionDialog *fs)
8418 {
8419   gchar *s = gtk_font_selection_dialog_get_font_name (fs);
8420
8421   g_print ("%s\n", s);
8422   g_free (s);
8423   gtk_widget_destroy (GTK_WIDGET (fs));
8424 }
8425
8426 void
8427 create_font_selection (GtkWidget *widget)
8428 {
8429   static GtkWidget *window = NULL;
8430
8431   if (!window)
8432     {
8433       GtkWidget *picker;
8434       GtkWidget *hbox;
8435       GtkWidget *label;
8436       
8437       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8438       gtk_window_set_screen (GTK_WINDOW (window),
8439                              gtk_widget_get_screen (widget));
8440
8441       g_signal_connect (window, "destroy",
8442                         G_CALLBACK (gtk_widget_destroyed),
8443                         &window);
8444
8445       gtk_window_set_title (GTK_WINDOW (window), "GtkFontButton");
8446       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
8447
8448       hbox = gtk_hbox_new (FALSE, 8);
8449       gtk_container_set_border_width (GTK_CONTAINER (hbox), 8);
8450       gtk_container_add (GTK_CONTAINER (window), hbox);
8451       
8452       label = gtk_label_new ("Pick a font");
8453       gtk_container_add (GTK_CONTAINER (hbox), label);
8454
8455       picker = gtk_font_button_new ();
8456       gtk_font_button_set_use_font (GTK_FONT_BUTTON (picker), TRUE);
8457       gtk_container_add (GTK_CONTAINER (hbox), picker);
8458     }
8459   
8460   if (!GTK_WIDGET_VISIBLE (window))
8461     gtk_widget_show_all (window);
8462   else
8463     gtk_widget_destroy (window);
8464 }
8465
8466 /*
8467  * GtkDialog
8468  */
8469
8470 static GtkWidget *dialog_window = NULL;
8471
8472 static void
8473 label_toggle (GtkWidget  *widget,
8474               GtkWidget **label)
8475 {
8476   if (!(*label))
8477     {
8478       *label = gtk_label_new ("Dialog Test");
8479       g_signal_connect (*label,
8480                         "destroy",
8481                         G_CALLBACK (gtk_widget_destroyed),
8482                         label);
8483       gtk_misc_set_padding (GTK_MISC (*label), 10, 10);
8484       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog_window)->vbox), 
8485                           *label, TRUE, TRUE, 0);
8486       gtk_widget_show (*label);
8487     }
8488   else
8489     gtk_widget_destroy (*label);
8490 }
8491
8492 #define RESPONSE_TOGGLE_SEPARATOR 1
8493
8494 static void
8495 print_response (GtkWidget *dialog,
8496                 gint       response_id,
8497                 gpointer   data)
8498 {
8499   g_print ("response signal received (%d)\n", response_id);
8500
8501   if (response_id == RESPONSE_TOGGLE_SEPARATOR)
8502     {
8503       gtk_dialog_set_has_separator (GTK_DIALOG (dialog),
8504                                     !gtk_dialog_get_has_separator (GTK_DIALOG (dialog)));
8505     }
8506 }
8507
8508 static void
8509 create_dialog (GtkWidget *widget)
8510 {
8511   static GtkWidget *label;
8512   GtkWidget *button;
8513
8514   if (!dialog_window)
8515     {
8516       /* This is a terrible example; it's much simpler to create
8517        * dialogs than this. Don't use testgtk for example code,
8518        * use gtk-demo ;-)
8519        */
8520       
8521       dialog_window = gtk_dialog_new ();
8522       gtk_window_set_screen (GTK_WINDOW (dialog_window),
8523                              gtk_widget_get_screen (widget));
8524
8525       g_signal_connect (dialog_window,
8526                         "response",
8527                         G_CALLBACK (print_response),
8528                         NULL);
8529       
8530       g_signal_connect (dialog_window, "destroy",
8531                         G_CALLBACK (gtk_widget_destroyed),
8532                         &dialog_window);
8533
8534       gtk_window_set_title (GTK_WINDOW (dialog_window), "GtkDialog");
8535       gtk_container_set_border_width (GTK_CONTAINER (dialog_window), 0);
8536
8537       button = gtk_button_new_with_label ("OK");
8538       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
8539       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog_window)->action_area), 
8540                           button, TRUE, TRUE, 0);
8541       gtk_widget_grab_default (button);
8542       gtk_widget_show (button);
8543
8544       button = gtk_button_new_with_label ("Toggle");
8545       g_signal_connect (button, "clicked",
8546                         G_CALLBACK (label_toggle),
8547                         &label);
8548       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
8549       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog_window)->action_area),
8550                           button, TRUE, TRUE, 0);
8551       gtk_widget_show (button);
8552
8553       label = NULL;
8554       
8555       button = gtk_button_new_with_label ("Separator");
8556
8557       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
8558
8559       gtk_dialog_add_action_widget (GTK_DIALOG (dialog_window),
8560                                     button,
8561                                     RESPONSE_TOGGLE_SEPARATOR);
8562       gtk_widget_show (button);
8563     }
8564
8565   if (!GTK_WIDGET_VISIBLE (dialog_window))
8566     gtk_widget_show (dialog_window);
8567   else
8568     gtk_widget_destroy (dialog_window);
8569 }
8570
8571 /* Display & Screen test 
8572  */
8573
8574 typedef struct 
8575
8576   GtkEntry *entry;
8577   GtkWidget *radio_dpy;
8578   GtkWidget *toplevel; 
8579   GtkWidget *dialog_window;
8580   GList *valid_display_list;
8581 } ScreenDisplaySelection;
8582
8583 static gint
8584 display_name_cmp (gconstpointer a,
8585                   gconstpointer b)
8586 {
8587   return g_ascii_strcasecmp (a,b);
8588 }
8589
8590 static void
8591 screen_display_check (GtkWidget *widget, ScreenDisplaySelection *data)
8592 {
8593   char *display_name;
8594   GdkDisplay *display = gtk_widget_get_display (widget);
8595   GtkWidget *dialog;
8596   GdkScreen *new_screen = NULL;
8597   GdkScreen *current_screen = gtk_widget_get_screen (widget);
8598   
8599   if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (data->radio_dpy)))
8600     {
8601       display_name = g_strdup (gtk_entry_get_text (data->entry));
8602       display = gdk_display_open (display_name);
8603       
8604       if (!display)
8605         {
8606           dialog = gtk_message_dialog_new (GTK_WINDOW (gtk_widget_get_toplevel (widget)),
8607                                            GTK_DIALOG_DESTROY_WITH_PARENT,
8608                                            GTK_MESSAGE_ERROR,
8609                                            GTK_BUTTONS_OK,
8610                                            "The display :\n%s\ncannot be opened",
8611                                            display_name);
8612           gtk_window_set_screen (GTK_WINDOW (dialog), current_screen);
8613           gtk_widget_show (dialog);
8614           g_signal_connect (dialog, "response",
8615                             G_CALLBACK (gtk_widget_destroy),
8616                             NULL);
8617         }
8618       else
8619         {
8620           if (!g_list_find_custom (data->valid_display_list, 
8621                                    display_name,
8622                                    display_name_cmp))
8623             data->valid_display_list = g_list_append (data->valid_display_list,
8624                                                       display_name);
8625           
8626           new_screen = gdk_display_get_default_screen (display);
8627         }
8628     }
8629   else
8630     {
8631       gint number_of_screens = gdk_display_get_n_screens (display);
8632       gint screen_num = gdk_screen_get_number (current_screen);
8633       if ((screen_num +1) < number_of_screens)
8634         new_screen = gdk_display_get_screen (display, screen_num + 1);
8635       else
8636         new_screen = gdk_display_get_screen (display, 0);
8637     }
8638   
8639   if (new_screen) 
8640     {
8641       gtk_window_set_screen (GTK_WINDOW (data->toplevel), new_screen);
8642       gtk_widget_destroy (data->dialog_window);
8643     }
8644 }
8645
8646 void
8647 screen_display_destroy_diag (GtkWidget *widget, GtkWidget *data)
8648 {
8649   gtk_widget_destroy (data);
8650 }
8651
8652 void
8653 create_display_screen (GtkWidget *widget)
8654 {
8655   GtkWidget *table, *frame, *window, *combo_dpy, *vbox;
8656   GtkWidget *radio_dpy, *radio_scr, *applyb, *cancelb;
8657   GtkWidget *bbox;
8658   ScreenDisplaySelection *scr_dpy_data;
8659   GdkScreen *screen = gtk_widget_get_screen (widget);
8660   static GList *valid_display_list = NULL;
8661   
8662   GdkDisplay *display = gdk_screen_get_display (screen);
8663
8664   window = g_object_new (gtk_window_get_type (),
8665                            "screen", screen,
8666                            "user_data", NULL,
8667                            "type", GTK_WINDOW_TOPLEVEL,
8668                            "title",
8669                            "Screen or Display selection",
8670                            "border_width", 10, NULL);
8671   g_signal_connect (window, "destroy", 
8672                     G_CALLBACK (gtk_widget_destroy), NULL);
8673
8674   vbox = gtk_vbox_new (FALSE, 3);
8675   gtk_container_add (GTK_CONTAINER (window), vbox);
8676   
8677   frame = gtk_frame_new ("Select screen or display");
8678   gtk_container_add (GTK_CONTAINER (vbox), frame);
8679   
8680   table = gtk_table_new (2, 2, TRUE);
8681   gtk_table_set_row_spacings (GTK_TABLE (table), 3);
8682   gtk_table_set_col_spacings (GTK_TABLE (table), 3);
8683
8684   gtk_container_add (GTK_CONTAINER (frame), table);
8685
8686   radio_dpy = gtk_radio_button_new_with_label (NULL, "move to another X display");
8687   if (gdk_display_get_n_screens(display) > 1)
8688     radio_scr = gtk_radio_button_new_with_label 
8689     (gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio_dpy)), "move to next screen");
8690   else
8691     {    
8692       radio_scr = gtk_radio_button_new_with_label 
8693         (gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio_dpy)), 
8694          "only one screen on the current display");
8695       gtk_widget_set_sensitive (radio_scr, FALSE);
8696     }
8697   combo_dpy = gtk_combo_new ();
8698   if (!valid_display_list)
8699     valid_display_list = g_list_append (valid_display_list, "diabolo:0.0");
8700     
8701   gtk_combo_set_popdown_strings (GTK_COMBO (combo_dpy), valid_display_list);
8702     
8703   gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (combo_dpy)->entry), 
8704                       "<hostname>:<X Server Num>.<Screen Num>");
8705
8706   gtk_table_attach_defaults (GTK_TABLE (table), radio_dpy, 0, 1, 0, 1);
8707   gtk_table_attach_defaults (GTK_TABLE (table), radio_scr, 0, 1, 1, 2);
8708   gtk_table_attach_defaults (GTK_TABLE (table), combo_dpy, 1, 2, 0, 1);
8709
8710   bbox = gtk_hbutton_box_new ();
8711   applyb = gtk_button_new_from_stock (GTK_STOCK_APPLY);
8712   cancelb = gtk_button_new_from_stock (GTK_STOCK_CANCEL);
8713   
8714   gtk_container_add (GTK_CONTAINER (vbox), bbox);
8715
8716   gtk_container_add (GTK_CONTAINER (bbox), applyb);
8717   gtk_container_add (GTK_CONTAINER (bbox), cancelb);
8718
8719   scr_dpy_data = g_new0 (ScreenDisplaySelection, 1);
8720
8721   scr_dpy_data->entry = GTK_ENTRY (GTK_COMBO (combo_dpy)->entry);
8722   scr_dpy_data->radio_dpy = radio_dpy;
8723   scr_dpy_data->toplevel = gtk_widget_get_toplevel (widget);
8724   scr_dpy_data->dialog_window = window;
8725   scr_dpy_data->valid_display_list = valid_display_list;
8726
8727   g_signal_connect (cancelb, "clicked", 
8728                     G_CALLBACK (screen_display_destroy_diag), window);
8729   g_signal_connect (applyb, "clicked", 
8730                     G_CALLBACK (screen_display_check), scr_dpy_data);
8731   gtk_widget_show_all (window);
8732 }
8733
8734 /* Event Watcher
8735  */
8736 static gboolean event_watcher_enter_id = 0;
8737 static gboolean event_watcher_leave_id = 0;
8738
8739 static gboolean
8740 event_watcher (GSignalInvocationHint *ihint,
8741                guint                  n_param_values,
8742                const GValue          *param_values,
8743                gpointer               data)
8744 {
8745   g_print ("Watch: \"%s\" emitted for %s\n",
8746            g_signal_name (ihint->signal_id),
8747            G_OBJECT_TYPE_NAME (g_value_get_object (param_values + 0)));
8748
8749   return TRUE;
8750 }
8751
8752 static void
8753 event_watcher_down (void)
8754 {
8755   if (event_watcher_enter_id)
8756     {
8757       guint signal_id;
8758
8759       signal_id = g_signal_lookup ("enter_notify_event", GTK_TYPE_WIDGET);
8760       g_signal_remove_emission_hook (signal_id, event_watcher_enter_id);
8761       event_watcher_enter_id = 0;
8762       signal_id = g_signal_lookup ("leave_notify_event", GTK_TYPE_WIDGET);
8763       g_signal_remove_emission_hook (signal_id, event_watcher_leave_id);
8764       event_watcher_leave_id = 0;
8765     }
8766 }
8767
8768 static void
8769 event_watcher_toggle (void)
8770 {
8771   if (event_watcher_enter_id)
8772     event_watcher_down ();
8773   else
8774     {
8775       guint signal_id;
8776
8777       signal_id = g_signal_lookup ("enter_notify_event", GTK_TYPE_WIDGET);
8778       event_watcher_enter_id = g_signal_add_emission_hook (signal_id, 0, event_watcher, NULL, NULL);
8779       signal_id = g_signal_lookup ("leave_notify_event", GTK_TYPE_WIDGET);
8780       event_watcher_leave_id = g_signal_add_emission_hook (signal_id, 0, event_watcher, NULL, NULL);
8781     }
8782 }
8783
8784 static void
8785 create_event_watcher (GtkWidget *widget)
8786 {
8787   GtkWidget *button;
8788
8789   if (!dialog_window)
8790     {
8791       dialog_window = gtk_dialog_new ();
8792       gtk_window_set_screen (GTK_WINDOW (dialog_window),
8793                              gtk_widget_get_screen (widget));
8794
8795       g_signal_connect (dialog_window, "destroy",
8796                         G_CALLBACK (gtk_widget_destroyed),
8797                         &dialog_window);
8798       g_signal_connect (dialog_window, "destroy",
8799                         G_CALLBACK (event_watcher_down),
8800                         NULL);
8801
8802       gtk_window_set_title (GTK_WINDOW (dialog_window), "Event Watcher");
8803       gtk_container_set_border_width (GTK_CONTAINER (dialog_window), 0);
8804       gtk_widget_set_size_request (dialog_window, 200, 110);
8805
8806       button = gtk_toggle_button_new_with_label ("Activate Watch");
8807       g_signal_connect (button, "clicked",
8808                         G_CALLBACK (event_watcher_toggle),
8809                         NULL);
8810       gtk_container_set_border_width (GTK_CONTAINER (button), 10);
8811       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog_window)->vbox), 
8812                           button, TRUE, TRUE, 0);
8813       gtk_widget_show (button);
8814
8815       button = gtk_button_new_with_label ("Close");
8816       g_signal_connect_swapped (button, "clicked",
8817                                 G_CALLBACK (gtk_widget_destroy),
8818                                 dialog_window);
8819       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
8820       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog_window)->action_area),
8821                           button, TRUE, TRUE, 0);
8822       gtk_widget_grab_default (button);
8823       gtk_widget_show (button);
8824     }
8825
8826   if (!GTK_WIDGET_VISIBLE (dialog_window))
8827     gtk_widget_show (dialog_window);
8828   else
8829     gtk_widget_destroy (dialog_window);
8830 }
8831
8832 /*
8833  * GtkRange
8834  */
8835
8836 static gchar*
8837 reformat_value (GtkScale *scale,
8838                 gdouble   value)
8839 {
8840   return g_strdup_printf ("-->%0.*g<--",
8841                           gtk_scale_get_digits (scale), value);
8842 }
8843
8844 static void
8845 create_range_controls (GtkWidget *widget)
8846 {
8847   static GtkWidget *window = NULL;
8848   GtkWidget *box1;
8849   GtkWidget *box2;
8850   GtkWidget *button;
8851   GtkWidget *scrollbar;
8852   GtkWidget *scale;
8853   GtkWidget *separator;
8854   GtkObject *adjustment;
8855   GtkWidget *hbox;
8856
8857   if (!window)
8858     {
8859       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8860
8861       gtk_window_set_screen (GTK_WINDOW (window),
8862                              gtk_widget_get_screen (widget));
8863
8864       g_signal_connect (window, "destroy",
8865                         G_CALLBACK (gtk_widget_destroyed),
8866                         &window);
8867
8868       gtk_window_set_title (GTK_WINDOW (window), "range controls");
8869       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
8870
8871
8872       box1 = gtk_vbox_new (FALSE, 0);
8873       gtk_container_add (GTK_CONTAINER (window), box1);
8874       gtk_widget_show (box1);
8875
8876
8877       box2 = gtk_vbox_new (FALSE, 10);
8878       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
8879       gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
8880       gtk_widget_show (box2);
8881
8882
8883       adjustment = gtk_adjustment_new (0.0, 0.0, 101.0, 0.1, 1.0, 1.0);
8884
8885       scale = gtk_hscale_new (GTK_ADJUSTMENT (adjustment));
8886       gtk_widget_set_size_request (GTK_WIDGET (scale), 150, -1);
8887       gtk_range_set_update_policy (GTK_RANGE (scale), GTK_UPDATE_DELAYED);
8888       gtk_scale_set_digits (GTK_SCALE (scale), 1);
8889       gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE);
8890       gtk_box_pack_start (GTK_BOX (box2), scale, TRUE, TRUE, 0);
8891       gtk_widget_show (scale);
8892
8893       scrollbar = gtk_hscrollbar_new (GTK_ADJUSTMENT (adjustment));
8894       gtk_range_set_update_policy (GTK_RANGE (scrollbar), 
8895                                    GTK_UPDATE_CONTINUOUS);
8896       gtk_box_pack_start (GTK_BOX (box2), scrollbar, TRUE, TRUE, 0);
8897       gtk_widget_show (scrollbar);
8898
8899       scale = gtk_hscale_new (GTK_ADJUSTMENT (adjustment));
8900       gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE);
8901       g_signal_connect (scale,
8902                         "format_value",
8903                         G_CALLBACK (reformat_value),
8904                         NULL);
8905       gtk_box_pack_start (GTK_BOX (box2), scale, TRUE, TRUE, 0);
8906       gtk_widget_show (scale);
8907       
8908       hbox = gtk_hbox_new (FALSE, 0);
8909
8910       scale = gtk_vscale_new (GTK_ADJUSTMENT (adjustment));
8911       gtk_widget_set_size_request (scale, -1, 200);
8912       gtk_scale_set_digits (GTK_SCALE (scale), 2);
8913       gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE);
8914       gtk_box_pack_start (GTK_BOX (hbox), scale, TRUE, TRUE, 0);
8915       gtk_widget_show (scale);
8916
8917       scale = gtk_vscale_new (GTK_ADJUSTMENT (adjustment));
8918       gtk_widget_set_size_request (scale, -1, 200);
8919       gtk_scale_set_digits (GTK_SCALE (scale), 2);
8920       gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE);
8921       gtk_range_set_inverted (GTK_RANGE (scale), TRUE);
8922       gtk_box_pack_start (GTK_BOX (hbox), scale, TRUE, TRUE, 0);
8923       gtk_widget_show (scale);
8924
8925       scale = gtk_vscale_new (GTK_ADJUSTMENT (adjustment));
8926       gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE);
8927       g_signal_connect (scale,
8928                         "format_value",
8929                         G_CALLBACK (reformat_value),
8930                         NULL);
8931       gtk_box_pack_start (GTK_BOX (hbox), scale, TRUE, TRUE, 0);
8932       gtk_widget_show (scale);
8933
8934       
8935       gtk_box_pack_start (GTK_BOX (box2), hbox, TRUE, TRUE, 0);
8936       gtk_widget_show (hbox);
8937       
8938       separator = gtk_hseparator_new ();
8939       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
8940       gtk_widget_show (separator);
8941
8942
8943       box2 = gtk_vbox_new (FALSE, 10);
8944       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
8945       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
8946       gtk_widget_show (box2);
8947
8948
8949       button = gtk_button_new_with_label ("close");
8950       g_signal_connect_swapped (button, "clicked",
8951                                 G_CALLBACK (gtk_widget_destroy),
8952                                 window);
8953       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
8954       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
8955       gtk_widget_grab_default (button);
8956       gtk_widget_show (button);
8957     }
8958
8959   if (!GTK_WIDGET_VISIBLE (window))
8960     gtk_widget_show (window);
8961   else
8962     gtk_widget_destroy (window);
8963 }
8964
8965 /*
8966  * GtkRulers
8967  */
8968
8969 void
8970 create_rulers (GtkWidget *widget)
8971 {
8972   static GtkWidget *window = NULL;
8973   GtkWidget *table;
8974   GtkWidget *ruler;
8975
8976   if (!window)
8977     {
8978       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8979
8980       gtk_window_set_screen (GTK_WINDOW (window),
8981                              gtk_widget_get_screen (widget));
8982
8983       g_object_set (window, "allow_shrink", TRUE, "allow_grow", TRUE, NULL);
8984
8985       g_signal_connect (window, "destroy",
8986                         G_CALLBACK (gtk_widget_destroyed),
8987                         &window);
8988
8989       gtk_window_set_title (GTK_WINDOW (window), "rulers");
8990       gtk_widget_set_size_request (window, 300, 300);
8991       gtk_widget_set_events (window, 
8992                              GDK_POINTER_MOTION_MASK 
8993                              | GDK_POINTER_MOTION_HINT_MASK);
8994       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
8995
8996       table = gtk_table_new (2, 2, FALSE);
8997       gtk_container_add (GTK_CONTAINER (window), table);
8998       gtk_widget_show (table);
8999
9000       ruler = gtk_hruler_new ();
9001       gtk_ruler_set_metric (GTK_RULER (ruler), GTK_CENTIMETERS);
9002       gtk_ruler_set_range (GTK_RULER (ruler), 100, 0, 0, 20);
9003
9004       g_signal_connect_swapped (window, 
9005                                 "motion_notify_event",
9006                                 G_CALLBACK (GTK_WIDGET_GET_CLASS (ruler)->motion_notify_event),
9007                                 ruler);
9008       
9009       gtk_table_attach (GTK_TABLE (table), ruler, 1, 2, 0, 1,
9010                         GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
9011       gtk_widget_show (ruler);
9012
9013
9014       ruler = gtk_vruler_new ();
9015       gtk_ruler_set_range (GTK_RULER (ruler), 5, 15, 0, 20);
9016
9017       g_signal_connect_swapped (window, 
9018                                 "motion_notify_event",
9019                                 G_CALLBACK (GTK_WIDGET_GET_CLASS (ruler)->motion_notify_event),
9020                                 ruler);
9021       
9022       gtk_table_attach (GTK_TABLE (table), ruler, 0, 1, 1, 2,
9023                         GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
9024       gtk_widget_show (ruler);
9025     }
9026
9027   if (!GTK_WIDGET_VISIBLE (window))
9028     gtk_widget_show (window);
9029   else
9030     gtk_widget_destroy (window);
9031 }
9032
9033 static void
9034 text_toggle_editable (GtkWidget *checkbutton,
9035                        GtkWidget *text)
9036 {
9037    gtk_text_set_editable(GTK_TEXT(text),
9038                           GTK_TOGGLE_BUTTON(checkbutton)->active);
9039 }
9040
9041 static void
9042 text_toggle_word_wrap (GtkWidget *checkbutton,
9043                        GtkWidget *text)
9044 {
9045    gtk_text_set_word_wrap(GTK_TEXT(text),
9046                           GTK_TOGGLE_BUTTON(checkbutton)->active);
9047 }
9048
9049 struct {
9050   GdkColor color;
9051   gchar *name;
9052 } text_colors[] = {
9053  { { 0, 0x0000, 0x0000, 0x0000 }, "black" },
9054  { { 0, 0xFFFF, 0xFFFF, 0xFFFF }, "white" },
9055  { { 0, 0xFFFF, 0x0000, 0x0000 }, "red" },
9056  { { 0, 0x0000, 0xFFFF, 0x0000 }, "green" },
9057  { { 0, 0x0000, 0x0000, 0xFFFF }, "blue" }, 
9058  { { 0, 0x0000, 0xFFFF, 0xFFFF }, "cyan" },
9059  { { 0, 0xFFFF, 0x0000, 0xFFFF }, "magenta" },
9060  { { 0, 0xFFFF, 0xFFFF, 0x0000 }, "yellow" }
9061 };
9062
9063 int ntext_colors = sizeof(text_colors) / sizeof(text_colors[0]);
9064
9065 /*
9066  * GtkText
9067  */
9068 void
9069 text_insert_random (GtkWidget *w, GtkText *text)
9070 {
9071   int i;
9072   char c;
9073    for (i=0; i<10; i++)
9074     {
9075       c = 'A' + rand() % ('Z' - 'A');
9076       gtk_text_set_point (text, rand() % gtk_text_get_length (text));
9077       gtk_text_insert (text, NULL, NULL, NULL, &c, 1);
9078     }
9079 }
9080
9081 void
9082 create_text (GtkWidget *widget)
9083 {
9084   int i, j;
9085
9086   static GtkWidget *window = NULL;
9087   GtkWidget *box1;
9088   GtkWidget *box2;
9089   GtkWidget *hbox;
9090   GtkWidget *button;
9091   GtkWidget *check;
9092   GtkWidget *separator;
9093   GtkWidget *scrolled_window;
9094   GtkWidget *text;
9095
9096   FILE *infile;
9097
9098   if (!window)
9099     {
9100       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9101       gtk_window_set_screen (GTK_WINDOW (window),
9102                              gtk_widget_get_screen (widget));
9103
9104       gtk_widget_set_name (window, "text window");
9105       g_object_set (window, "allow_shrink", TRUE, "allow_grow", TRUE, NULL);
9106       gtk_widget_set_size_request (window, 500, 500);
9107
9108       g_signal_connect (window, "destroy",
9109                         G_CALLBACK (gtk_widget_destroyed),
9110                         &window);
9111
9112       gtk_window_set_title (GTK_WINDOW (window), "test");
9113       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
9114
9115
9116       box1 = gtk_vbox_new (FALSE, 0);
9117       gtk_container_add (GTK_CONTAINER (window), box1);
9118       gtk_widget_show (box1);
9119
9120
9121       box2 = gtk_vbox_new (FALSE, 10);
9122       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
9123       gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
9124       gtk_widget_show (box2);
9125
9126
9127       scrolled_window = gtk_scrolled_window_new (NULL, NULL);
9128       gtk_box_pack_start (GTK_BOX (box2), scrolled_window, TRUE, TRUE, 0);
9129       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
9130                                       GTK_POLICY_NEVER,
9131                                       GTK_POLICY_ALWAYS);
9132       gtk_widget_show (scrolled_window);
9133
9134       text = gtk_text_new (NULL, NULL);
9135       gtk_text_set_editable (GTK_TEXT (text), TRUE);
9136       gtk_container_add (GTK_CONTAINER (scrolled_window), text);
9137       gtk_widget_grab_focus (text);
9138       gtk_widget_show (text);
9139
9140
9141       gtk_text_freeze (GTK_TEXT (text));
9142
9143       for (i=0; i<ntext_colors; i++)
9144         {
9145           gtk_text_insert (GTK_TEXT (text), NULL, NULL, NULL, 
9146                            text_colors[i].name, -1);
9147           gtk_text_insert (GTK_TEXT (text), NULL, NULL, NULL, "\t", -1);
9148
9149           for (j=0; j<ntext_colors; j++)
9150             {
9151               gtk_text_insert (GTK_TEXT (text), NULL,
9152                                &text_colors[j].color, &text_colors[i].color,
9153                                "XYZ", -1);
9154             }
9155           gtk_text_insert (GTK_TEXT (text), NULL, NULL, NULL, "\n", -1);
9156         }
9157
9158       infile = fopen("testgtk.c", "r");
9159       
9160       if (infile)
9161         {
9162           char *buffer;
9163           int nbytes_read, nbytes_alloc;
9164           
9165           nbytes_read = 0;
9166           nbytes_alloc = 1024;
9167           buffer = g_new (char, nbytes_alloc);
9168           while (1)
9169             {
9170               int len;
9171               if (nbytes_alloc < nbytes_read + 1024)
9172                 {
9173                   nbytes_alloc *= 2;
9174                   buffer = g_realloc (buffer, nbytes_alloc);
9175                 }
9176               len = fread (buffer + nbytes_read, 1, 1024, infile);
9177               nbytes_read += len;
9178               if (len < 1024)
9179                 break;
9180             }
9181           
9182           gtk_text_insert (GTK_TEXT (text), NULL, NULL,
9183                            NULL, buffer, nbytes_read);
9184           g_free(buffer);
9185           fclose (infile);
9186         }
9187       
9188       gtk_text_thaw (GTK_TEXT (text));
9189
9190       hbox = gtk_hbutton_box_new ();
9191       gtk_box_pack_start (GTK_BOX (box2), hbox, FALSE, FALSE, 0);
9192       gtk_widget_show (hbox);
9193
9194       check = gtk_check_button_new_with_label("Editable");
9195       gtk_box_pack_start (GTK_BOX (hbox), check, FALSE, FALSE, 0);
9196       g_signal_connect (check, "toggled",
9197                         G_CALLBACK (text_toggle_editable), text);
9198       gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), TRUE);
9199       gtk_widget_show (check);
9200
9201       check = gtk_check_button_new_with_label("Wrap Words");
9202       gtk_box_pack_start (GTK_BOX (hbox), check, FALSE, TRUE, 0);
9203       g_signal_connect (check, "toggled",
9204                         G_CALLBACK (text_toggle_word_wrap), text);
9205       gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), FALSE);
9206       gtk_widget_show (check);
9207
9208       separator = gtk_hseparator_new ();
9209       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
9210       gtk_widget_show (separator);
9211
9212
9213       box2 = gtk_vbox_new (FALSE, 10);
9214       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
9215       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
9216       gtk_widget_show (box2);
9217
9218
9219       button = gtk_button_new_with_label ("insert random");
9220       g_signal_connect (button, "clicked",
9221                         G_CALLBACK (text_insert_random),
9222                         text);
9223       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
9224       gtk_widget_show (button);
9225
9226       button = gtk_button_new_with_label ("close");
9227       g_signal_connect_swapped (button, "clicked",
9228                                 G_CALLBACK (gtk_widget_destroy),
9229                                 window);
9230       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
9231       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
9232       gtk_widget_grab_default (button);
9233       gtk_widget_show (button);
9234     }
9235
9236   if (!GTK_WIDGET_VISIBLE (window))
9237     gtk_widget_show (window);
9238   else
9239     gtk_widget_destroy (window);
9240 }
9241
9242 /*
9243  * GtkNotebook
9244  */
9245
9246 GdkPixbuf *book_open;
9247 GdkPixbuf *book_closed;
9248 GtkWidget *sample_notebook;
9249
9250 static void
9251 set_page_image (GtkNotebook *notebook, gint page_num, GdkPixbuf *pixbuf)
9252 {
9253   GtkWidget *page_widget;
9254   GtkWidget *pixwid;
9255
9256   page_widget = gtk_notebook_get_nth_page (notebook, page_num);
9257
9258   pixwid = g_object_get_data (G_OBJECT (page_widget), "tab_pixmap");
9259   gtk_image_set_from_pixbuf (GTK_IMAGE (pixwid), pixbuf);
9260   
9261   pixwid = g_object_get_data (G_OBJECT (page_widget), "menu_pixmap");
9262   gtk_image_set_from_pixbuf (GTK_IMAGE (pixwid), pixbuf);
9263 }
9264
9265 static void
9266 page_switch (GtkWidget *widget, GtkNotebookPage *page, gint page_num)
9267 {
9268   GtkNotebook *notebook = GTK_NOTEBOOK (widget);
9269   gint old_page_num = gtk_notebook_get_current_page (notebook);
9270  
9271   if (page_num == old_page_num)
9272     return;
9273
9274   set_page_image (notebook, page_num, book_open);
9275
9276   if (old_page_num != -1)
9277     set_page_image (notebook, old_page_num, book_closed);
9278 }
9279
9280 static void
9281 tab_fill (GtkToggleButton *button, GtkWidget *child)
9282 {
9283   gboolean expand;
9284   GtkPackType pack_type;
9285
9286   gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (sample_notebook), child,
9287                                         &expand, NULL, &pack_type);
9288   gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (sample_notebook), child,
9289                                       expand, button->active, pack_type);
9290 }
9291
9292 static void
9293 tab_expand (GtkToggleButton *button, GtkWidget *child)
9294 {
9295   gboolean fill;
9296   GtkPackType pack_type;
9297
9298   gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (sample_notebook), child,
9299                                         NULL, &fill, &pack_type);
9300   gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (sample_notebook), child,
9301                                       button->active, fill, pack_type);
9302 }
9303
9304 static void
9305 tab_pack (GtkToggleButton *button, GtkWidget *child)
9306           
9307
9308   gboolean expand;
9309   gboolean fill;
9310
9311   gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (sample_notebook), child,
9312                                         &expand, &fill, NULL);
9313   gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (sample_notebook), child,
9314                                       expand, fill, button->active);
9315 }
9316
9317 static void
9318 create_pages (GtkNotebook *notebook, gint start, gint end)
9319 {
9320   GtkWidget *child = NULL;
9321   GtkWidget *button;
9322   GtkWidget *label;
9323   GtkWidget *hbox;
9324   GtkWidget *vbox;
9325   GtkWidget *label_box;
9326   GtkWidget *menu_box;
9327   GtkWidget *pixwid;
9328   gint i;
9329   char buffer[32];
9330   char accel_buffer[32];
9331
9332   for (i = start; i <= end; i++)
9333     {
9334       sprintf (buffer, "Page %d", i);
9335       sprintf (accel_buffer, "Page _%d", i);
9336
9337       child = gtk_frame_new (buffer);
9338       gtk_container_set_border_width (GTK_CONTAINER (child), 10);
9339
9340       vbox = gtk_vbox_new (TRUE,0);
9341       gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
9342       gtk_container_add (GTK_CONTAINER (child), vbox);
9343
9344       hbox = gtk_hbox_new (TRUE,0);
9345       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 5);
9346
9347       button = gtk_check_button_new_with_label ("Fill Tab");
9348       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
9349       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
9350       g_signal_connect (button, "toggled",
9351                         G_CALLBACK (tab_fill), child);
9352
9353       button = gtk_check_button_new_with_label ("Expand Tab");
9354       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
9355       g_signal_connect (button, "toggled",
9356                         G_CALLBACK (tab_expand), child);
9357
9358       button = gtk_check_button_new_with_label ("Pack end");
9359       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
9360       g_signal_connect (button, "toggled",
9361                         G_CALLBACK (tab_pack), child);
9362
9363       button = gtk_button_new_with_label ("Hide Page");
9364       gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 5);
9365       g_signal_connect_swapped (button, "clicked",
9366                                 G_CALLBACK (gtk_widget_hide),
9367                                 child);
9368
9369       gtk_widget_show_all (child);
9370
9371       label_box = gtk_hbox_new (FALSE, 0);
9372       pixwid = gtk_image_new_from_pixbuf (book_closed);
9373       g_object_set_data (G_OBJECT (child), "tab_pixmap", pixwid);
9374                            
9375       gtk_box_pack_start (GTK_BOX (label_box), pixwid, FALSE, TRUE, 0);
9376       gtk_misc_set_padding (GTK_MISC (pixwid), 3, 1);
9377       label = gtk_label_new_with_mnemonic (accel_buffer);
9378       gtk_box_pack_start (GTK_BOX (label_box), label, FALSE, TRUE, 0);
9379       gtk_widget_show_all (label_box);
9380       
9381                                        
9382       menu_box = gtk_hbox_new (FALSE, 0);
9383       pixwid = gtk_image_new_from_pixbuf (book_closed);
9384       g_object_set_data (G_OBJECT (child), "menu_pixmap", pixwid);
9385       
9386       gtk_box_pack_start (GTK_BOX (menu_box), pixwid, FALSE, TRUE, 0);
9387       gtk_misc_set_padding (GTK_MISC (pixwid), 3, 1);
9388       label = gtk_label_new (buffer);
9389       gtk_box_pack_start (GTK_BOX (menu_box), label, FALSE, TRUE, 0);
9390       gtk_widget_show_all (menu_box);
9391
9392       gtk_notebook_append_page_menu (notebook, child, label_box, menu_box);
9393     }
9394 }
9395
9396 static void
9397 rotate_notebook (GtkButton   *button,
9398                  GtkNotebook *notebook)
9399 {
9400   gtk_notebook_set_tab_pos (notebook, (notebook->tab_pos + 1) % 4);
9401 }
9402
9403 static void
9404 show_all_pages (GtkButton   *button,
9405                 GtkNotebook *notebook)
9406 {  
9407   gtk_container_foreach (GTK_CONTAINER (notebook),
9408                          (GtkCallback) gtk_widget_show, NULL);
9409 }
9410
9411 static void
9412 notebook_type_changed (GtkWidget *optionmenu,
9413                        gpointer   data)
9414 {
9415   GtkNotebook *notebook;
9416   gint i, c;
9417
9418   enum {
9419     STANDARD,
9420     NOTABS,
9421     BORDERLESS,
9422     SCROLLABLE
9423   };
9424
9425   notebook = GTK_NOTEBOOK (data);
9426
9427   c = gtk_option_menu_get_history (GTK_OPTION_MENU (optionmenu));
9428
9429   switch (c)
9430     {
9431     case STANDARD:
9432       /* standard notebook */
9433       gtk_notebook_set_show_tabs (notebook, TRUE);
9434       gtk_notebook_set_show_border (notebook, TRUE);
9435       gtk_notebook_set_scrollable (notebook, FALSE);
9436       break;
9437
9438     case NOTABS:
9439       /* notabs notebook */
9440       gtk_notebook_set_show_tabs (notebook, FALSE);
9441       gtk_notebook_set_show_border (notebook, TRUE);
9442       break;
9443
9444     case BORDERLESS:
9445       /* borderless */
9446       gtk_notebook_set_show_tabs (notebook, FALSE);
9447       gtk_notebook_set_show_border (notebook, FALSE);
9448       break;
9449
9450     case SCROLLABLE:  
9451       /* scrollable */
9452       gtk_notebook_set_show_tabs (notebook, TRUE);
9453       gtk_notebook_set_show_border (notebook, TRUE);
9454       gtk_notebook_set_scrollable (notebook, TRUE);
9455       if (g_list_length (notebook->children) == 5)
9456         create_pages (notebook, 6, 15);
9457       
9458       return;
9459       break;
9460     }
9461   
9462   if (g_list_length (notebook->children) == 15)
9463     for (i = 0; i < 10; i++)
9464       gtk_notebook_remove_page (notebook, 5);
9465 }
9466
9467 static void
9468 notebook_popup (GtkToggleButton *button,
9469                 GtkNotebook     *notebook)
9470 {
9471   if (button->active)
9472     gtk_notebook_popup_enable (notebook);
9473   else
9474     gtk_notebook_popup_disable (notebook);
9475 }
9476
9477 static void
9478 notebook_homogeneous (GtkToggleButton *button,
9479                       GtkNotebook     *notebook)
9480 {
9481   g_object_set (notebook, "homogeneous", button->active, NULL);
9482 }
9483
9484 static void
9485 create_notebook (GtkWidget *widget)
9486 {
9487   static GtkWidget *window = NULL;
9488   GtkWidget *box1;
9489   GtkWidget *box2;
9490   GtkWidget *button;
9491   GtkWidget *separator;
9492   GtkWidget *omenu;
9493   GtkWidget *label;
9494
9495   static gchar *items[] =
9496   {
9497     "Standard",
9498     "No tabs",
9499     "Borderless",
9500     "Scrollable"
9501   };
9502   
9503   if (!window)
9504     {
9505       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9506       gtk_window_set_screen (GTK_WINDOW (window),
9507                              gtk_widget_get_screen (widget));
9508
9509       g_signal_connect (window, "destroy",
9510                         G_CALLBACK (gtk_widget_destroyed),
9511                         &window);
9512
9513       gtk_window_set_title (GTK_WINDOW (window), "notebook");
9514       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
9515
9516       box1 = gtk_vbox_new (FALSE, 0);
9517       gtk_container_add (GTK_CONTAINER (window), box1);
9518
9519       sample_notebook = gtk_notebook_new ();
9520       g_signal_connect (sample_notebook, "switch_page",
9521                         G_CALLBACK (page_switch), NULL);
9522       gtk_notebook_set_tab_pos (GTK_NOTEBOOK (sample_notebook), GTK_POS_TOP);
9523       gtk_box_pack_start (GTK_BOX (box1), sample_notebook, TRUE, TRUE, 0);
9524       gtk_container_set_border_width (GTK_CONTAINER (sample_notebook), 10);
9525
9526       gtk_widget_realize (sample_notebook);
9527
9528       if (!book_open)
9529         book_open = gdk_pixbuf_new_from_xpm_data ((const char **)book_open_xpm);
9530                                                   
9531       if (!book_closed)
9532         book_closed = gdk_pixbuf_new_from_xpm_data ((const char **)book_closed_xpm);
9533
9534       create_pages (GTK_NOTEBOOK (sample_notebook), 1, 5);
9535
9536       separator = gtk_hseparator_new ();
9537       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 10);
9538       
9539       box2 = gtk_hbox_new (FALSE, 5);
9540       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
9541       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
9542
9543       button = gtk_check_button_new_with_label ("popup menu");
9544       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, FALSE, 0);
9545       g_signal_connect (button, "clicked",
9546                         G_CALLBACK (notebook_popup),
9547                         sample_notebook);
9548
9549       button = gtk_check_button_new_with_label ("homogeneous tabs");
9550       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, FALSE, 0);
9551       g_signal_connect (button, "clicked",
9552                         G_CALLBACK (notebook_homogeneous),
9553                         sample_notebook);
9554
9555       box2 = gtk_hbox_new (FALSE, 5);
9556       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
9557       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
9558
9559       label = gtk_label_new ("Notebook Style :");
9560       gtk_box_pack_start (GTK_BOX (box2), label, FALSE, TRUE, 0);
9561
9562       omenu = build_option_menu (items, G_N_ELEMENTS (items), 0,
9563                                  notebook_type_changed,
9564                                  sample_notebook);
9565       gtk_box_pack_start (GTK_BOX (box2), omenu, FALSE, TRUE, 0);
9566
9567       button = gtk_button_new_with_label ("Show all Pages");
9568       gtk_box_pack_start (GTK_BOX (box2), button, FALSE, TRUE, 0);
9569       g_signal_connect (button, "clicked",
9570                         G_CALLBACK (show_all_pages), sample_notebook);
9571
9572       box2 = gtk_hbox_new (TRUE, 10);
9573       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
9574       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
9575
9576       button = gtk_button_new_with_label ("prev");
9577       g_signal_connect_swapped (button, "clicked",
9578                                 G_CALLBACK (gtk_notebook_prev_page),
9579                                 sample_notebook);
9580       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
9581
9582       button = gtk_button_new_with_label ("next");
9583       g_signal_connect_swapped (button, "clicked",
9584                                 G_CALLBACK (gtk_notebook_next_page),
9585                                 sample_notebook);
9586       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
9587
9588       button = gtk_button_new_with_label ("rotate");
9589       g_signal_connect (button, "clicked",
9590                         G_CALLBACK (rotate_notebook), sample_notebook);
9591       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
9592
9593       separator = gtk_hseparator_new ();
9594       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
9595
9596       button = gtk_button_new_with_label ("close");
9597       gtk_container_set_border_width (GTK_CONTAINER (button), 5);
9598       g_signal_connect_swapped (button, "clicked",
9599                                 G_CALLBACK (gtk_widget_destroy),
9600                                 window);
9601       gtk_box_pack_start (GTK_BOX (box1), button, FALSE, FALSE, 0);
9602       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
9603       gtk_widget_grab_default (button);
9604     }
9605
9606   if (!GTK_WIDGET_VISIBLE (window))
9607     gtk_widget_show_all (window);
9608   else
9609     gtk_widget_destroy (window);
9610 }
9611
9612 /*
9613  * GtkPanes
9614  */
9615
9616 void
9617 toggle_resize (GtkWidget *widget, GtkWidget *child)
9618 {
9619   GtkContainer *container = GTK_CONTAINER (gtk_widget_get_parent (child));
9620   GValue value = { 0, };
9621   g_value_init (&value, G_TYPE_BOOLEAN);
9622   gtk_container_child_get_property (container, child, "resize", &value);
9623   g_value_set_boolean (&value, !g_value_get_boolean (&value));
9624   gtk_container_child_set_property (container, child, "resize", &value);
9625 }
9626
9627 void
9628 toggle_shrink (GtkWidget *widget, GtkWidget *child)
9629 {
9630   GtkContainer *container = GTK_CONTAINER (gtk_widget_get_parent (child));
9631   GValue value = { 0, };
9632   g_value_init (&value, G_TYPE_BOOLEAN);
9633   gtk_container_child_get_property (container, child, "shrink", &value);
9634   g_value_set_boolean (&value, !g_value_get_boolean (&value));
9635   gtk_container_child_set_property (container, child, "shrink", &value);
9636 }
9637
9638 static void
9639 paned_props_clicked (GtkWidget *button,
9640                      GObject   *paned)
9641 {
9642   GtkWidget *window = create_prop_editor (paned, GTK_TYPE_PANED);
9643   
9644   gtk_window_set_title (GTK_WINDOW (window), "Paned Properties");
9645 }
9646
9647 GtkWidget *
9648 create_pane_options (GtkPaned    *paned,
9649                      const gchar *frame_label,
9650                      const gchar *label1,
9651                      const gchar *label2)
9652 {
9653   GtkWidget *frame;
9654   GtkWidget *table;
9655   GtkWidget *label;
9656   GtkWidget *button;
9657   GtkWidget *check_button;
9658   
9659   frame = gtk_frame_new (frame_label);
9660   gtk_container_set_border_width (GTK_CONTAINER (frame), 4);
9661   
9662   table = gtk_table_new (4, 2, 4);
9663   gtk_container_add (GTK_CONTAINER (frame), table);
9664   
9665   label = gtk_label_new (label1);
9666   gtk_table_attach_defaults (GTK_TABLE (table), label,
9667                              0, 1, 0, 1);
9668   
9669   check_button = gtk_check_button_new_with_label ("Resize");
9670   gtk_table_attach_defaults (GTK_TABLE (table), check_button,
9671                              0, 1, 1, 2);
9672   g_signal_connect (check_button, "toggled",
9673                     G_CALLBACK (toggle_resize),
9674                     paned->child1);
9675   
9676   check_button = gtk_check_button_new_with_label ("Shrink");
9677   gtk_table_attach_defaults (GTK_TABLE (table), check_button,
9678                              0, 1, 2, 3);
9679   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button),
9680                                TRUE);
9681   g_signal_connect (check_button, "toggled",
9682                     G_CALLBACK (toggle_shrink),
9683                     paned->child1);
9684   
9685   label = gtk_label_new (label2);
9686   gtk_table_attach_defaults (GTK_TABLE (table), label,
9687                              1, 2, 0, 1);
9688   
9689   check_button = gtk_check_button_new_with_label ("Resize");
9690   gtk_table_attach_defaults (GTK_TABLE (table), check_button,
9691                              1, 2, 1, 2);
9692   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button),
9693                                TRUE);
9694   g_signal_connect (check_button, "toggled",
9695                     G_CALLBACK (toggle_resize),
9696                     paned->child2);
9697   
9698   check_button = gtk_check_button_new_with_label ("Shrink");
9699   gtk_table_attach_defaults (GTK_TABLE (table), check_button,
9700                              1, 2, 2, 3);
9701   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button),
9702                                TRUE);
9703   g_signal_connect (check_button, "toggled",
9704                     G_CALLBACK (toggle_shrink),
9705                     paned->child2);
9706
9707   button = gtk_button_new_with_mnemonic ("_Properties");
9708   gtk_table_attach_defaults (GTK_TABLE (table), button,
9709                              0, 2, 3, 4);
9710   g_signal_connect (button, "clicked",
9711                     G_CALLBACK (paned_props_clicked),
9712                     paned);
9713
9714   return frame;
9715 }
9716
9717 void
9718 create_panes (GtkWidget *widget)
9719 {
9720   static GtkWidget *window = NULL;
9721   GtkWidget *frame;
9722   GtkWidget *hpaned;
9723   GtkWidget *vpaned;
9724   GtkWidget *button;
9725   GtkWidget *vbox;
9726
9727   if (!window)
9728     {
9729       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9730
9731       gtk_window_set_screen (GTK_WINDOW (window),
9732                              gtk_widget_get_screen (widget));
9733       
9734       g_signal_connect (window, "destroy",
9735                         G_CALLBACK (gtk_widget_destroyed),
9736                         &window);
9737
9738       gtk_window_set_title (GTK_WINDOW (window), "Panes");
9739       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
9740
9741       vbox = gtk_vbox_new (FALSE, 0);
9742       gtk_container_add (GTK_CONTAINER (window), vbox);
9743       
9744       vpaned = gtk_vpaned_new ();
9745       gtk_box_pack_start (GTK_BOX (vbox), vpaned, TRUE, TRUE, 0);
9746       gtk_container_set_border_width (GTK_CONTAINER(vpaned), 5);
9747
9748       hpaned = gtk_hpaned_new ();
9749       gtk_paned_add1 (GTK_PANED (vpaned), hpaned);
9750
9751       frame = gtk_frame_new (NULL);
9752       gtk_frame_set_shadow_type (GTK_FRAME(frame), GTK_SHADOW_IN);
9753       gtk_widget_set_size_request (frame, 60, 60);
9754       gtk_paned_add1 (GTK_PANED (hpaned), frame);
9755       
9756       button = gtk_button_new_with_label ("Hi there");
9757       gtk_container_add (GTK_CONTAINER(frame), button);
9758
9759       frame = gtk_frame_new (NULL);
9760       gtk_frame_set_shadow_type (GTK_FRAME(frame), GTK_SHADOW_IN);
9761       gtk_widget_set_size_request (frame, 80, 60);
9762       gtk_paned_add2 (GTK_PANED (hpaned), frame);
9763
9764       frame = gtk_frame_new (NULL);
9765       gtk_frame_set_shadow_type (GTK_FRAME(frame), GTK_SHADOW_IN);
9766       gtk_widget_set_size_request (frame, 60, 80);
9767       gtk_paned_add2 (GTK_PANED (vpaned), frame);
9768
9769       /* Now create toggle buttons to control sizing */
9770
9771       gtk_box_pack_start (GTK_BOX (vbox),
9772                           create_pane_options (GTK_PANED (hpaned),
9773                                                "Horizontal",
9774                                                "Left",
9775                                                "Right"),
9776                           FALSE, FALSE, 0);
9777
9778       gtk_box_pack_start (GTK_BOX (vbox),
9779                           create_pane_options (GTK_PANED (vpaned),
9780                                                "Vertical",
9781                                                "Top",
9782                                                "Bottom"),
9783                           FALSE, FALSE, 0);
9784
9785       gtk_widget_show_all (vbox);
9786     }
9787
9788   if (!GTK_WIDGET_VISIBLE (window))
9789     gtk_widget_show (window);
9790   else
9791     gtk_widget_destroy (window);
9792 }
9793
9794 /*
9795  * Paned keyboard navigation
9796  */
9797
9798 static GtkWidget*
9799 paned_keyboard_window1 (GtkWidget *widget)
9800 {
9801   GtkWidget *window1;
9802   GtkWidget *hpaned1;
9803   GtkWidget *frame1;
9804   GtkWidget *vbox1;
9805   GtkWidget *button7;
9806   GtkWidget *button8;
9807   GtkWidget *button9;
9808   GtkWidget *vpaned1;
9809   GtkWidget *frame2;
9810   GtkWidget *frame5;
9811   GtkWidget *hbox1;
9812   GtkWidget *button5;
9813   GtkWidget *button6;
9814   GtkWidget *frame3;
9815   GtkWidget *frame4;
9816   GtkWidget *table1;
9817   GtkWidget *button1;
9818   GtkWidget *button2;
9819   GtkWidget *button3;
9820   GtkWidget *button4;
9821
9822   window1 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9823   gtk_window_set_title (GTK_WINDOW (window1), "Basic paned navigation");
9824   gtk_window_set_screen (GTK_WINDOW (window1), 
9825                          gtk_widget_get_screen (widget));
9826
9827   hpaned1 = gtk_hpaned_new ();
9828   gtk_container_add (GTK_CONTAINER (window1), hpaned1);
9829
9830   frame1 = gtk_frame_new (NULL);
9831   gtk_paned_pack1 (GTK_PANED (hpaned1), frame1, FALSE, TRUE);
9832   gtk_frame_set_shadow_type (GTK_FRAME (frame1), GTK_SHADOW_IN);
9833
9834   vbox1 = gtk_vbox_new (FALSE, 0);
9835   gtk_container_add (GTK_CONTAINER (frame1), vbox1);
9836
9837   button7 = gtk_button_new_with_label ("button7");
9838   gtk_box_pack_start (GTK_BOX (vbox1), button7, FALSE, FALSE, 0);
9839
9840   button8 = gtk_button_new_with_label ("button8");
9841   gtk_box_pack_start (GTK_BOX (vbox1), button8, FALSE, FALSE, 0);
9842
9843   button9 = gtk_button_new_with_label ("button9");
9844   gtk_box_pack_start (GTK_BOX (vbox1), button9, FALSE, FALSE, 0);
9845
9846   vpaned1 = gtk_vpaned_new ();
9847   gtk_paned_pack2 (GTK_PANED (hpaned1), vpaned1, TRUE, TRUE);
9848
9849   frame2 = gtk_frame_new (NULL);
9850   gtk_paned_pack1 (GTK_PANED (vpaned1), frame2, FALSE, TRUE);
9851   gtk_frame_set_shadow_type (GTK_FRAME (frame2), GTK_SHADOW_IN);
9852
9853   frame5 = gtk_frame_new (NULL);
9854   gtk_container_add (GTK_CONTAINER (frame2), frame5);
9855
9856   hbox1 = gtk_hbox_new (FALSE, 0);
9857   gtk_container_add (GTK_CONTAINER (frame5), hbox1);
9858
9859   button5 = gtk_button_new_with_label ("button5");
9860   gtk_box_pack_start (GTK_BOX (hbox1), button5, FALSE, FALSE, 0);
9861
9862   button6 = gtk_button_new_with_label ("button6");
9863   gtk_box_pack_start (GTK_BOX (hbox1), button6, FALSE, FALSE, 0);
9864
9865   frame3 = gtk_frame_new (NULL);
9866   gtk_paned_pack2 (GTK_PANED (vpaned1), frame3, TRUE, TRUE);
9867   gtk_frame_set_shadow_type (GTK_FRAME (frame3), GTK_SHADOW_IN);
9868
9869   frame4 = gtk_frame_new ("Buttons");
9870   gtk_container_add (GTK_CONTAINER (frame3), frame4);
9871   gtk_container_set_border_width (GTK_CONTAINER (frame4), 15);
9872
9873   table1 = gtk_table_new (2, 2, FALSE);
9874   gtk_container_add (GTK_CONTAINER (frame4), table1);
9875   gtk_container_set_border_width (GTK_CONTAINER (table1), 11);
9876
9877   button1 = gtk_button_new_with_label ("button1");
9878   gtk_table_attach (GTK_TABLE (table1), button1, 0, 1, 0, 1,
9879                     (GtkAttachOptions) (GTK_FILL),
9880                     (GtkAttachOptions) (0), 0, 0);
9881
9882   button2 = gtk_button_new_with_label ("button2");
9883   gtk_table_attach (GTK_TABLE (table1), button2, 1, 2, 0, 1,
9884                     (GtkAttachOptions) (GTK_FILL),
9885                     (GtkAttachOptions) (0), 0, 0);
9886
9887   button3 = gtk_button_new_with_label ("button3");
9888   gtk_table_attach (GTK_TABLE (table1), button3, 0, 1, 1, 2,
9889                     (GtkAttachOptions) (GTK_FILL),
9890                     (GtkAttachOptions) (0), 0, 0);
9891
9892   button4 = gtk_button_new_with_label ("button4");
9893   gtk_table_attach (GTK_TABLE (table1), button4, 1, 2, 1, 2,
9894                     (GtkAttachOptions) (GTK_FILL),
9895                     (GtkAttachOptions) (0), 0, 0);
9896
9897   return window1;
9898 }
9899
9900 static GtkWidget*
9901 paned_keyboard_window2 (GtkWidget *widget)
9902 {
9903   GtkWidget *window2;
9904   GtkWidget *hpaned2;
9905   GtkWidget *frame6;
9906   GtkWidget *button13;
9907   GtkWidget *hbox2;
9908   GtkWidget *vpaned2;
9909   GtkWidget *frame7;
9910   GtkWidget *button12;
9911   GtkWidget *frame8;
9912   GtkWidget *button11;
9913   GtkWidget *button10;
9914
9915   window2 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9916   gtk_window_set_title (GTK_WINDOW (window2), "\"button 10\" is not inside the horisontal pane");
9917
9918   gtk_window_set_screen (GTK_WINDOW (window2), 
9919                          gtk_widget_get_screen (widget));
9920
9921   hpaned2 = gtk_hpaned_new ();
9922   gtk_container_add (GTK_CONTAINER (window2), hpaned2);
9923
9924   frame6 = gtk_frame_new (NULL);
9925   gtk_paned_pack1 (GTK_PANED (hpaned2), frame6, FALSE, TRUE);
9926   gtk_frame_set_shadow_type (GTK_FRAME (frame6), GTK_SHADOW_IN);
9927
9928   button13 = gtk_button_new_with_label ("button13");
9929   gtk_container_add (GTK_CONTAINER (frame6), button13);
9930
9931   hbox2 = gtk_hbox_new (FALSE, 0);
9932   gtk_paned_pack2 (GTK_PANED (hpaned2), hbox2, TRUE, TRUE);
9933
9934   vpaned2 = gtk_vpaned_new ();
9935   gtk_box_pack_start (GTK_BOX (hbox2), vpaned2, TRUE, TRUE, 0);
9936
9937   frame7 = gtk_frame_new (NULL);
9938   gtk_paned_pack1 (GTK_PANED (vpaned2), frame7, FALSE, TRUE);
9939   gtk_frame_set_shadow_type (GTK_FRAME (frame7), GTK_SHADOW_IN);
9940
9941   button12 = gtk_button_new_with_label ("button12");
9942   gtk_container_add (GTK_CONTAINER (frame7), button12);
9943
9944   frame8 = gtk_frame_new (NULL);
9945   gtk_paned_pack2 (GTK_PANED (vpaned2), frame8, TRUE, TRUE);
9946   gtk_frame_set_shadow_type (GTK_FRAME (frame8), GTK_SHADOW_IN);
9947
9948   button11 = gtk_button_new_with_label ("button11");
9949   gtk_container_add (GTK_CONTAINER (frame8), button11);
9950
9951   button10 = gtk_button_new_with_label ("button10");
9952   gtk_box_pack_start (GTK_BOX (hbox2), button10, FALSE, FALSE, 0);
9953
9954   return window2;
9955 }
9956
9957 static GtkWidget*
9958 paned_keyboard_window3 (GtkWidget *widget)
9959 {
9960   GtkWidget *window3;
9961   GtkWidget *vbox2;
9962   GtkWidget *label1;
9963   GtkWidget *hpaned3;
9964   GtkWidget *frame9;
9965   GtkWidget *button14;
9966   GtkWidget *hpaned4;
9967   GtkWidget *frame10;
9968   GtkWidget *button15;
9969   GtkWidget *hpaned5;
9970   GtkWidget *frame11;
9971   GtkWidget *button16;
9972   GtkWidget *frame12;
9973   GtkWidget *button17;
9974
9975   window3 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9976   g_object_set_data (G_OBJECT (window3), "window3", window3);
9977   gtk_window_set_title (GTK_WINDOW (window3), "Nested panes");
9978
9979   gtk_window_set_screen (GTK_WINDOW (window3), 
9980                          gtk_widget_get_screen (widget));
9981   
9982
9983   vbox2 = gtk_vbox_new (FALSE, 0);
9984   gtk_container_add (GTK_CONTAINER (window3), vbox2);
9985
9986   label1 = gtk_label_new ("Three panes nested inside each other");
9987   gtk_box_pack_start (GTK_BOX (vbox2), label1, FALSE, FALSE, 0);
9988
9989   hpaned3 = gtk_hpaned_new ();
9990   gtk_box_pack_start (GTK_BOX (vbox2), hpaned3, TRUE, TRUE, 0);
9991
9992   frame9 = gtk_frame_new (NULL);
9993   gtk_paned_pack1 (GTK_PANED (hpaned3), frame9, FALSE, TRUE);
9994   gtk_frame_set_shadow_type (GTK_FRAME (frame9), GTK_SHADOW_IN);
9995
9996   button14 = gtk_button_new_with_label ("button14");
9997   gtk_container_add (GTK_CONTAINER (frame9), button14);
9998
9999   hpaned4 = gtk_hpaned_new ();
10000   gtk_paned_pack2 (GTK_PANED (hpaned3), hpaned4, TRUE, TRUE);
10001
10002   frame10 = gtk_frame_new (NULL);
10003   gtk_paned_pack1 (GTK_PANED (hpaned4), frame10, FALSE, TRUE);
10004   gtk_frame_set_shadow_type (GTK_FRAME (frame10), GTK_SHADOW_IN);
10005
10006   button15 = gtk_button_new_with_label ("button15");
10007   gtk_container_add (GTK_CONTAINER (frame10), button15);
10008
10009   hpaned5 = gtk_hpaned_new ();
10010   gtk_paned_pack2 (GTK_PANED (hpaned4), hpaned5, TRUE, TRUE);
10011
10012   frame11 = gtk_frame_new (NULL);
10013   gtk_paned_pack1 (GTK_PANED (hpaned5), frame11, FALSE, TRUE);
10014   gtk_frame_set_shadow_type (GTK_FRAME (frame11), GTK_SHADOW_IN);
10015
10016   button16 = gtk_button_new_with_label ("button16");
10017   gtk_container_add (GTK_CONTAINER (frame11), button16);
10018
10019   frame12 = gtk_frame_new (NULL);
10020   gtk_paned_pack2 (GTK_PANED (hpaned5), frame12, TRUE, TRUE);
10021   gtk_frame_set_shadow_type (GTK_FRAME (frame12), GTK_SHADOW_IN);
10022
10023   button17 = gtk_button_new_with_label ("button17");
10024   gtk_container_add (GTK_CONTAINER (frame12), button17);
10025
10026   return window3;
10027 }
10028
10029 static GtkWidget*
10030 paned_keyboard_window4 (GtkWidget *widget)
10031 {
10032   GtkWidget *window4;
10033   GtkWidget *vbox3;
10034   GtkWidget *label2;
10035   GtkWidget *hpaned6;
10036   GtkWidget *vpaned3;
10037   GtkWidget *button19;
10038   GtkWidget *button18;
10039   GtkWidget *hbox3;
10040   GtkWidget *vpaned4;
10041   GtkWidget *button21;
10042   GtkWidget *button20;
10043   GtkWidget *vpaned5;
10044   GtkWidget *button23;
10045   GtkWidget *button22;
10046   GtkWidget *vpaned6;
10047   GtkWidget *button25;
10048   GtkWidget *button24;
10049
10050   window4 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
10051   g_object_set_data (G_OBJECT (window4), "window4", window4);
10052   gtk_window_set_title (GTK_WINDOW (window4), "window4");
10053
10054   gtk_window_set_screen (GTK_WINDOW (window4), 
10055                          gtk_widget_get_screen (widget));
10056
10057   vbox3 = gtk_vbox_new (FALSE, 0);
10058   gtk_container_add (GTK_CONTAINER (window4), vbox3);
10059
10060   label2 = gtk_label_new ("Widget tree:\n\nhpaned \n - vpaned\n - hbox\n    - vpaned\n    - vpaned\n    - vpaned\n");
10061   gtk_box_pack_start (GTK_BOX (vbox3), label2, FALSE, FALSE, 0);
10062   gtk_label_set_justify (GTK_LABEL (label2), GTK_JUSTIFY_LEFT);
10063
10064   hpaned6 = gtk_hpaned_new ();
10065   gtk_box_pack_start (GTK_BOX (vbox3), hpaned6, TRUE, TRUE, 0);
10066
10067   vpaned3 = gtk_vpaned_new ();
10068   gtk_paned_pack1 (GTK_PANED (hpaned6), vpaned3, FALSE, TRUE);
10069
10070   button19 = gtk_button_new_with_label ("button19");
10071   gtk_paned_pack1 (GTK_PANED (vpaned3), button19, FALSE, TRUE);
10072
10073   button18 = gtk_button_new_with_label ("button18");
10074   gtk_paned_pack2 (GTK_PANED (vpaned3), button18, TRUE, TRUE);
10075
10076   hbox3 = gtk_hbox_new (FALSE, 0);
10077   gtk_paned_pack2 (GTK_PANED (hpaned6), hbox3, TRUE, TRUE);
10078
10079   vpaned4 = gtk_vpaned_new ();
10080   gtk_box_pack_start (GTK_BOX (hbox3), vpaned4, TRUE, TRUE, 0);
10081
10082   button21 = gtk_button_new_with_label ("button21");
10083   gtk_paned_pack1 (GTK_PANED (vpaned4), button21, FALSE, TRUE);
10084
10085   button20 = gtk_button_new_with_label ("button20");
10086   gtk_paned_pack2 (GTK_PANED (vpaned4), button20, TRUE, TRUE);
10087
10088   vpaned5 = gtk_vpaned_new ();
10089   gtk_box_pack_start (GTK_BOX (hbox3), vpaned5, TRUE, TRUE, 0);
10090
10091   button23 = gtk_button_new_with_label ("button23");
10092   gtk_paned_pack1 (GTK_PANED (vpaned5), button23, FALSE, TRUE);
10093
10094   button22 = gtk_button_new_with_label ("button22");
10095   gtk_paned_pack2 (GTK_PANED (vpaned5), button22, TRUE, TRUE);
10096
10097   vpaned6 = gtk_vpaned_new ();
10098   gtk_box_pack_start (GTK_BOX (hbox3), vpaned6, TRUE, TRUE, 0);
10099
10100   button25 = gtk_button_new_with_label ("button25");
10101   gtk_paned_pack1 (GTK_PANED (vpaned6), button25, FALSE, TRUE);
10102
10103   button24 = gtk_button_new_with_label ("button24");
10104   gtk_paned_pack2 (GTK_PANED (vpaned6), button24, TRUE, TRUE);
10105
10106   return window4;
10107 }
10108
10109 static void
10110 create_paned_keyboard_navigation (GtkWidget *widget)
10111 {
10112   static GtkWidget *window1 = NULL;
10113   static GtkWidget *window2 = NULL;
10114   static GtkWidget *window3 = NULL;
10115   static GtkWidget *window4 = NULL;
10116
10117   if (window1 && 
10118      (gtk_widget_get_screen (window1) != gtk_widget_get_screen (widget)))
10119     {
10120       gtk_widget_destroy (window1);
10121       gtk_widget_destroy (window2);
10122       gtk_widget_destroy (window3);
10123       gtk_widget_destroy (window4);
10124     }
10125   
10126   if (!window1)
10127     {
10128       window1 = paned_keyboard_window1 (widget);
10129       g_signal_connect (window1, "destroy",
10130                         G_CALLBACK (gtk_widget_destroyed),
10131                         &window1);
10132     }
10133
10134   if (!window2)
10135     {
10136       window2 = paned_keyboard_window2 (widget);
10137       g_signal_connect (window2, "destroy",
10138                         G_CALLBACK (gtk_widget_destroyed),
10139                         &window2);
10140     }
10141
10142   if (!window3)
10143     {
10144       window3 = paned_keyboard_window3 (widget);
10145       g_signal_connect (window3, "destroy",
10146                         G_CALLBACK (gtk_widget_destroyed),
10147                         &window3);
10148     }
10149
10150   if (!window4)
10151     {
10152       window4 = paned_keyboard_window4 (widget);
10153       g_signal_connect (window4, "destroy",
10154                         G_CALLBACK (gtk_widget_destroyed),
10155                         &window4);
10156     }
10157
10158   if (GTK_WIDGET_VISIBLE (window1))
10159     gtk_widget_destroy (GTK_WIDGET (window1));
10160   else
10161     gtk_widget_show_all (GTK_WIDGET (window1));
10162
10163   if (GTK_WIDGET_VISIBLE (window2))
10164     gtk_widget_destroy (GTK_WIDGET (window2));
10165   else
10166     gtk_widget_show_all (GTK_WIDGET (window2));
10167
10168   if (GTK_WIDGET_VISIBLE (window3))
10169     gtk_widget_destroy (GTK_WIDGET (window3));
10170   else
10171     gtk_widget_show_all (GTK_WIDGET (window3));
10172
10173   if (GTK_WIDGET_VISIBLE (window4))
10174     gtk_widget_destroy (GTK_WIDGET (window4));
10175   else
10176     gtk_widget_show_all (GTK_WIDGET (window4));
10177 }
10178
10179
10180 /*
10181  * Shaped Windows
10182  */
10183
10184 typedef struct _cursoroffset {gint x,y;} CursorOffset;
10185
10186 static void
10187 shape_pressed (GtkWidget *widget, GdkEventButton *event)
10188 {
10189   CursorOffset *p;
10190
10191   /* ignore double and triple click */
10192   if (event->type != GDK_BUTTON_PRESS)
10193     return;
10194
10195   p = g_object_get_data (G_OBJECT (widget), "cursor_offset");
10196   p->x = (int) event->x;
10197   p->y = (int) event->y;
10198
10199   gtk_grab_add (widget);
10200   gdk_pointer_grab (widget->window, TRUE,
10201                     GDK_BUTTON_RELEASE_MASK |
10202                     GDK_BUTTON_MOTION_MASK |
10203                     GDK_POINTER_MOTION_HINT_MASK,
10204                     NULL, NULL, 0);
10205 }
10206
10207 static void
10208 shape_released (GtkWidget *widget)
10209 {
10210   gtk_grab_remove (widget);
10211   gdk_display_pointer_ungrab (gtk_widget_get_display (widget),
10212                               GDK_CURRENT_TIME);
10213 }
10214
10215 static void
10216 shape_motion (GtkWidget      *widget, 
10217               GdkEventMotion *event)
10218 {
10219   gint xp, yp;
10220   CursorOffset * p;
10221   GdkModifierType mask;
10222
10223   p = g_object_get_data (G_OBJECT (widget), "cursor_offset");
10224
10225   /*
10226    * Can't use event->x / event->y here 
10227    * because I need absolute coordinates.
10228    */
10229   gdk_window_get_pointer (NULL, &xp, &yp, &mask);
10230   gtk_widget_set_uposition (widget, xp  - p->x, yp  - p->y);
10231 }
10232
10233 GtkWidget *
10234 shape_create_icon (GdkScreen *screen,
10235                    char      *xpm_file,
10236                    gint       x,
10237                    gint       y,
10238                    gint       px,
10239                    gint       py,
10240                    gint       window_type)
10241 {
10242   GtkWidget *window;
10243   GtkWidget *pixmap;
10244   GtkWidget *fixed;
10245   CursorOffset* icon_pos;
10246   GdkGC* gc;
10247   GdkBitmap *gdk_pixmap_mask;
10248   GdkPixmap *gdk_pixmap;
10249   GtkStyle *style;
10250
10251   style = gtk_widget_get_default_style ();
10252   gc = style->black_gc; 
10253
10254   /*
10255    * GDK_WINDOW_TOPLEVEL works also, giving you a title border
10256    */
10257   window = gtk_window_new (window_type);
10258   gtk_window_set_screen (GTK_WINDOW (window), screen);
10259   
10260   fixed = gtk_fixed_new ();
10261   gtk_widget_set_size_request (fixed, 100, 100);
10262   gtk_container_add (GTK_CONTAINER (window), fixed);
10263   gtk_widget_show (fixed);
10264   
10265   gtk_widget_set_events (window, 
10266                          gtk_widget_get_events (window) |
10267                          GDK_BUTTON_MOTION_MASK |
10268                          GDK_POINTER_MOTION_HINT_MASK |
10269                          GDK_BUTTON_PRESS_MASK);
10270
10271   gtk_widget_realize (window);
10272   gdk_pixmap = gdk_pixmap_create_from_xpm (window->window, &gdk_pixmap_mask, 
10273                                            &style->bg[GTK_STATE_NORMAL],
10274                                            xpm_file);
10275
10276   pixmap = gtk_image_new_from_pixmap (gdk_pixmap, gdk_pixmap_mask);
10277   gtk_fixed_put (GTK_FIXED (fixed), pixmap, px,py);
10278   gtk_widget_show (pixmap);
10279   
10280   gtk_widget_shape_combine_mask (window, gdk_pixmap_mask, px, py);
10281   
10282   g_object_unref (gdk_pixmap_mask);
10283   g_object_unref (gdk_pixmap);
10284
10285   g_signal_connect (window, "button_press_event",
10286                     G_CALLBACK (shape_pressed), NULL);
10287   g_signal_connect (window, "button_release_event",
10288                     G_CALLBACK (shape_released), NULL);
10289   g_signal_connect (window, "motion_notify_event",
10290                     G_CALLBACK (shape_motion), NULL);
10291
10292   icon_pos = g_new (CursorOffset, 1);
10293   g_object_set_data (G_OBJECT (window), "cursor_offset", icon_pos);
10294
10295   gtk_widget_set_uposition (window, x, y);
10296   gtk_widget_show (window);
10297   
10298   return window;
10299 }
10300
10301 void 
10302 create_shapes (GtkWidget *widget)
10303 {
10304   /* Variables used by the Drag/Drop and Shape Window demos */
10305   static GtkWidget *modeller = NULL;
10306   static GtkWidget *sheets = NULL;
10307   static GtkWidget *rings = NULL;
10308   static GtkWidget *with_region = NULL;
10309   GdkScreen *screen = gtk_widget_get_screen (widget);
10310   
10311   if (!(file_exists ("Modeller.xpm") &&
10312         file_exists ("FilesQueue.xpm") &&
10313         file_exists ("3DRings.xpm")))
10314     return;
10315   
10316
10317   if (!modeller)
10318     {
10319       modeller = shape_create_icon (screen, "Modeller.xpm",
10320                                     440, 140, 0,0, GTK_WINDOW_POPUP);
10321
10322       g_signal_connect (modeller, "destroy",
10323                         G_CALLBACK (gtk_widget_destroyed),
10324                         &modeller);
10325     }
10326   else
10327     gtk_widget_destroy (modeller);
10328
10329   if (!sheets)
10330     {
10331       sheets = shape_create_icon (screen, "FilesQueue.xpm",
10332                                   580, 170, 0,0, GTK_WINDOW_POPUP);
10333
10334       g_signal_connect (sheets, "destroy",
10335                         G_CALLBACK (gtk_widget_destroyed),
10336                         &sheets);
10337
10338     }
10339   else
10340     gtk_widget_destroy (sheets);
10341
10342   if (!rings)
10343     {
10344       rings = shape_create_icon (screen, "3DRings.xpm",
10345                                  460, 270, 25,25, GTK_WINDOW_TOPLEVEL);
10346
10347       g_signal_connect (rings, "destroy",
10348                         G_CALLBACK (gtk_widget_destroyed),
10349                         &rings);
10350     }
10351   else
10352     gtk_widget_destroy (rings);
10353
10354   if (!with_region)
10355     {
10356       GdkRegion *region;
10357       gint x, y;
10358       
10359       with_region = shape_create_icon (screen, "3DRings.xpm",
10360                                        460, 270, 25,25, GTK_WINDOW_TOPLEVEL);
10361
10362       gtk_window_set_decorated (GTK_WINDOW (with_region), FALSE);
10363       
10364       g_signal_connect (with_region, "destroy",
10365                         G_CALLBACK (gtk_widget_destroyed),
10366                         &with_region);
10367
10368       /* reset shape from mask to a region */
10369       x = 0;
10370       y = 0;
10371       region = gdk_region_new ();
10372
10373       while (x < 460)
10374         {
10375           while (y < 270)
10376             {
10377               GdkRectangle rect;
10378               rect.x = x;
10379               rect.y = y;
10380               rect.width = 10;
10381               rect.height = 10;
10382
10383               gdk_region_union_with_rect (region, &rect);
10384               
10385               y += 20;
10386             }
10387           y = 0;
10388           x += 20;
10389         }
10390
10391       gdk_window_shape_combine_region (with_region->window,
10392                                        region,
10393                                        0, 0);
10394     }
10395   else
10396     gtk_widget_destroy (with_region);
10397 }
10398
10399 /*
10400  * WM Hints demo
10401  */
10402
10403 void
10404 create_wmhints (GtkWidget *widget)
10405 {
10406   static GtkWidget *window = NULL;
10407   GtkWidget *label;
10408   GtkWidget *separator;
10409   GtkWidget *button;
10410   GtkWidget *box1;
10411   GtkWidget *box2;
10412
10413   GdkBitmap *circles;
10414
10415   if (!window)
10416     {
10417       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
10418
10419       gtk_window_set_screen (GTK_WINDOW (window),
10420                              gtk_widget_get_screen (widget));
10421       
10422       g_signal_connect (window, "destroy",
10423                         G_CALLBACK (gtk_widget_destroyed),
10424                         &window);
10425
10426       gtk_window_set_title (GTK_WINDOW (window), "WM Hints");
10427       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
10428
10429       gtk_widget_realize (window);
10430       
10431       circles = gdk_bitmap_create_from_data (window->window,
10432                                              (gchar *) circles_bits,
10433                                              circles_width,
10434                                              circles_height);
10435       gdk_window_set_icon (window->window, NULL,
10436                            circles, circles);
10437       
10438       gdk_window_set_icon_name (window->window, "WMHints Test Icon");
10439   
10440       gdk_window_set_decorations (window->window, GDK_DECOR_ALL | GDK_DECOR_MENU);
10441       gdk_window_set_functions (window->window, GDK_FUNC_ALL | GDK_FUNC_RESIZE);
10442       
10443       box1 = gtk_vbox_new (FALSE, 0);
10444       gtk_container_add (GTK_CONTAINER (window), box1);
10445       gtk_widget_show (box1);
10446
10447       label = gtk_label_new ("Try iconizing me!");
10448       gtk_widget_set_size_request (label, 150, 50);
10449       gtk_box_pack_start (GTK_BOX (box1), label, TRUE, TRUE, 0);
10450       gtk_widget_show (label);
10451
10452
10453       separator = gtk_hseparator_new ();
10454       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
10455       gtk_widget_show (separator);
10456
10457
10458       box2 = gtk_vbox_new (FALSE, 10);
10459       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
10460       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
10461       gtk_widget_show (box2);
10462
10463
10464       button = gtk_button_new_with_label ("close");
10465
10466       g_signal_connect_swapped (button, "clicked",
10467                                 G_CALLBACK (gtk_widget_destroy),
10468                                 window);
10469
10470       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
10471       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
10472       gtk_widget_grab_default (button);
10473       gtk_widget_show (button);
10474     }
10475
10476   if (!GTK_WIDGET_VISIBLE (window))
10477     gtk_widget_show (window);
10478   else
10479     gtk_widget_destroy (window);
10480 }
10481
10482
10483 /*
10484  * Window state tracking
10485  */
10486
10487 static gint
10488 window_state_callback (GtkWidget *widget,
10489                        GdkEventWindowState *event,
10490                        gpointer data)
10491 {
10492   GtkWidget *label = data;
10493   gchar *msg;
10494
10495   msg = g_strconcat (GTK_WINDOW (widget)->title, ": ",
10496                      (event->new_window_state & GDK_WINDOW_STATE_WITHDRAWN) ?
10497                      "withdrawn" : "not withdrawn", ", ",
10498                      (event->new_window_state & GDK_WINDOW_STATE_ICONIFIED) ?
10499                      "iconified" : "not iconified", ", ",
10500                      (event->new_window_state & GDK_WINDOW_STATE_STICKY) ?
10501                      "sticky" : "not sticky", ", ",
10502                      (event->new_window_state & GDK_WINDOW_STATE_MAXIMIZED) ?
10503                      "maximized" : "not maximized", ", ",
10504                      (event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN) ?
10505                      "fullscreen" : "not fullscreen",
10506                      (event->new_window_state & GDK_WINDOW_STATE_ABOVE) ?
10507                      "above" : "not above", ", ",
10508                      (event->new_window_state & GDK_WINDOW_STATE_BELOW) ?
10509                      "below" : "not below", ", ",
10510                      NULL);
10511   
10512   gtk_label_set_text (GTK_LABEL (label), msg);
10513
10514   g_free (msg);
10515
10516   return FALSE;
10517 }
10518
10519 static GtkWidget*
10520 tracking_label (GtkWidget *window)
10521 {
10522   GtkWidget *label;
10523   GtkWidget *hbox;
10524   GtkWidget *button;
10525
10526   hbox = gtk_hbox_new (FALSE, 5);
10527
10528   g_signal_connect_object (hbox,
10529                            "destroy",
10530                            G_CALLBACK (gtk_widget_destroy),
10531                            window,
10532                            G_CONNECT_SWAPPED);
10533   
10534   label = gtk_label_new ("<no window state events received>");
10535   gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
10536   gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
10537   
10538   g_signal_connect (window,
10539                     "window_state_event",
10540                     G_CALLBACK (window_state_callback),
10541                     label);
10542
10543   button = gtk_button_new_with_label ("Deiconify");
10544   g_signal_connect_object (button,
10545                            "clicked",
10546                            G_CALLBACK (gtk_window_deiconify),
10547                            window,
10548                            G_CONNECT_SWAPPED);
10549   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
10550
10551   button = gtk_button_new_with_label ("Iconify");
10552   g_signal_connect_object (button,
10553                            "clicked",
10554                            G_CALLBACK (gtk_window_iconify),
10555                            window,
10556                            G_CONNECT_SWAPPED);
10557   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
10558
10559   button = gtk_button_new_with_label ("Fullscreen");
10560   g_signal_connect_object (button,
10561                            "clicked",
10562                            G_CALLBACK (gtk_window_fullscreen),
10563                            window,
10564                            G_CONNECT_SWAPPED);
10565   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
10566
10567   button = gtk_button_new_with_label ("Unfullscreen");
10568   g_signal_connect_object (button,
10569                            "clicked",
10570                            G_CALLBACK (gtk_window_unfullscreen),
10571                            window,
10572                            G_CONNECT_SWAPPED);
10573   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
10574   
10575   button = gtk_button_new_with_label ("Present");
10576   g_signal_connect_object (button,
10577                            "clicked",
10578                            G_CALLBACK (gtk_window_present),
10579                            window,
10580                            G_CONNECT_SWAPPED);
10581   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
10582
10583   button = gtk_button_new_with_label ("Show");
10584   g_signal_connect_object (button,
10585                            "clicked",
10586                            G_CALLBACK (gtk_widget_show),
10587                            window,
10588                            G_CONNECT_SWAPPED);
10589   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
10590   
10591   gtk_widget_show_all (hbox);
10592   
10593   return hbox;
10594 }
10595
10596 void
10597 keep_window_above (GtkToggleButton *togglebutton, gpointer data)
10598 {
10599   GtkWidget *button = g_object_get_data (G_OBJECT (togglebutton), "radio");
10600
10601   gtk_window_set_keep_above (GTK_WINDOW (data),
10602                              gtk_toggle_button_get_active (togglebutton));
10603
10604   if (gtk_toggle_button_get_active (togglebutton))
10605     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE);
10606 }
10607
10608 void
10609 keep_window_below (GtkToggleButton *togglebutton, gpointer data)
10610 {
10611   GtkWidget *button = g_object_get_data (G_OBJECT (togglebutton), "radio");
10612
10613   gtk_window_set_keep_below (GTK_WINDOW (data),
10614                              gtk_toggle_button_get_active (togglebutton));
10615
10616   if (gtk_toggle_button_get_active (togglebutton))
10617     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE);
10618 }
10619
10620
10621 static GtkWidget*
10622 get_state_controls (GtkWidget *window)
10623 {
10624   GtkWidget *vbox;
10625   GtkWidget *button;
10626   GtkWidget *button_above;
10627   GtkWidget *button_below;
10628
10629   vbox = gtk_vbox_new (FALSE, 0);
10630   
10631   button = gtk_button_new_with_label ("Stick");
10632   g_signal_connect_object (button,
10633                            "clicked",
10634                            G_CALLBACK (gtk_window_stick),
10635                            window,
10636                            G_CONNECT_SWAPPED);
10637   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
10638
10639   button = gtk_button_new_with_label ("Unstick");
10640   g_signal_connect_object (button,
10641                            "clicked",
10642                            G_CALLBACK (gtk_window_unstick),
10643                            window,
10644                            G_CONNECT_SWAPPED);
10645   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
10646   
10647   button = gtk_button_new_with_label ("Maximize");
10648   g_signal_connect_object (button,
10649                            "clicked",
10650                            G_CALLBACK (gtk_window_maximize),
10651                            window,
10652                            G_CONNECT_SWAPPED);
10653   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
10654
10655   button = gtk_button_new_with_label ("Unmaximize");
10656   g_signal_connect_object (button,
10657                            "clicked",
10658                            G_CALLBACK (gtk_window_unmaximize),
10659                            window,
10660                            G_CONNECT_SWAPPED);
10661   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
10662
10663   button = gtk_button_new_with_label ("Iconify");
10664   g_signal_connect_object (button,
10665                            "clicked",
10666                            G_CALLBACK (gtk_window_iconify),
10667                            window,
10668                            G_CONNECT_SWAPPED);
10669   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
10670
10671   button = gtk_button_new_with_label ("Fullscreen");
10672   g_signal_connect_object (button,
10673                            "clicked",
10674                            G_CALLBACK (gtk_window_fullscreen),
10675                            window,
10676                            G_CONNECT_SWAPPED);
10677   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
10678
10679   button = gtk_button_new_with_label ("Unfullscreen");
10680   g_signal_connect_object (button,
10681                            "clicked",
10682                            G_CALLBACK (gtk_window_unfullscreen),
10683                            window,
10684                            G_CONNECT_SWAPPED);
10685   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
10686
10687   button_above = gtk_toggle_button_new_with_label ("Keep above");
10688   g_signal_connect (button_above,
10689                     "toggled",
10690                     G_CALLBACK (keep_window_above),
10691                     window);
10692   gtk_box_pack_start (GTK_BOX (vbox), button_above, FALSE, FALSE, 0);
10693
10694   button_below = gtk_toggle_button_new_with_label ("Keep below");
10695   g_signal_connect (button_below,
10696                     "toggled",
10697                     G_CALLBACK (keep_window_below),
10698                     window);
10699   gtk_box_pack_start (GTK_BOX (vbox), button_below, FALSE, FALSE, 0);
10700
10701   g_object_set_data (G_OBJECT (button_above), "radio", button_below);
10702   g_object_set_data (G_OBJECT (button_below), "radio", button_above);
10703
10704   button = gtk_button_new_with_label ("Hide (withdraw)");
10705   g_signal_connect_object (button,
10706                            "clicked",
10707                            G_CALLBACK (gtk_widget_hide),
10708                            window,
10709                            G_CONNECT_SWAPPED);
10710   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
10711   
10712   gtk_widget_show_all (vbox);
10713
10714   return vbox;
10715 }
10716
10717 void
10718 create_window_states (GtkWidget *widget)
10719 {
10720   static GtkWidget *window = NULL;
10721   GtkWidget *label;
10722   GtkWidget *box1;
10723   GtkWidget *iconified;
10724   GtkWidget *normal;
10725   GtkWidget *controls;
10726
10727   if (!window)
10728     {
10729       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
10730       gtk_window_set_screen (GTK_WINDOW (window),
10731                              gtk_widget_get_screen (widget));
10732
10733       g_signal_connect (window, "destroy",
10734                         G_CALLBACK (gtk_widget_destroyed),
10735                         &window);
10736
10737       gtk_window_set_title (GTK_WINDOW (window), "Window states");
10738       
10739       box1 = gtk_vbox_new (FALSE, 0);
10740       gtk_container_add (GTK_CONTAINER (window), box1);
10741
10742       iconified = gtk_window_new (GTK_WINDOW_TOPLEVEL);
10743
10744       gtk_window_set_screen (GTK_WINDOW (iconified),
10745                              gtk_widget_get_screen (widget));
10746       
10747       g_signal_connect_object (iconified, "destroy",
10748                                G_CALLBACK (gtk_widget_destroy),
10749                                window,
10750                                G_CONNECT_SWAPPED);
10751       gtk_window_iconify (GTK_WINDOW (iconified));
10752       gtk_window_set_title (GTK_WINDOW (iconified), "Iconified initially");
10753       controls = get_state_controls (iconified);
10754       gtk_container_add (GTK_CONTAINER (iconified), controls);
10755       
10756       normal = gtk_window_new (GTK_WINDOW_TOPLEVEL);
10757
10758       gtk_window_set_screen (GTK_WINDOW (normal),
10759                              gtk_widget_get_screen (widget));
10760       
10761       g_signal_connect_object (normal, "destroy",
10762                                G_CALLBACK (gtk_widget_destroy),
10763                                window,
10764                                G_CONNECT_SWAPPED);
10765       
10766       gtk_window_set_title (GTK_WINDOW (normal), "Deiconified initially");
10767       controls = get_state_controls (normal);
10768       gtk_container_add (GTK_CONTAINER (normal), controls);
10769       
10770       label = tracking_label (iconified);
10771       gtk_container_add (GTK_CONTAINER (box1), label);
10772
10773       label = tracking_label (normal);
10774       gtk_container_add (GTK_CONTAINER (box1), label);
10775
10776       gtk_widget_show_all (iconified);
10777       gtk_widget_show_all (normal);
10778       gtk_widget_show_all (box1);
10779     }
10780
10781   if (!GTK_WIDGET_VISIBLE (window))
10782     gtk_widget_show (window);
10783   else
10784     gtk_widget_destroy (window);
10785 }
10786
10787 /*
10788  * Window sizing
10789  */
10790
10791 static gint
10792 configure_event_callback (GtkWidget *widget,
10793                           GdkEventConfigure *event,
10794                           gpointer data)
10795 {
10796   GtkWidget *label = data;
10797   gchar *msg;
10798   gint x, y;
10799   
10800   gtk_window_get_position (GTK_WINDOW (widget), &x, &y);
10801   
10802   msg = g_strdup_printf ("event: %d,%d  %d x %d\n"
10803                          "position: %d, %d",
10804                          event->x, event->y, event->width, event->height,
10805                          x, y);
10806   
10807   gtk_label_set_text (GTK_LABEL (label), msg);
10808
10809   g_free (msg);
10810
10811   return FALSE;
10812 }
10813
10814 static void
10815 get_ints (GtkWidget *window,
10816           gint      *a,
10817           gint      *b)
10818 {
10819   GtkWidget *spin1;
10820   GtkWidget *spin2;
10821
10822   spin1 = g_object_get_data (G_OBJECT (window), "spin1");
10823   spin2 = g_object_get_data (G_OBJECT (window), "spin2");
10824
10825   *a = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (spin1));
10826   *b = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (spin2));
10827 }
10828
10829 static void
10830 set_size_callback (GtkWidget *widget,
10831                    gpointer   data)
10832 {
10833   gint w, h;
10834   
10835   get_ints (data, &w, &h);
10836
10837   gtk_window_resize (GTK_WINDOW (g_object_get_data (data, "target")), w, h);
10838 }
10839
10840 static void
10841 unset_default_size_callback (GtkWidget *widget,
10842                              gpointer   data)
10843 {
10844   gtk_window_set_default_size (g_object_get_data (data, "target"),
10845                                -1, -1);
10846 }
10847
10848 static void
10849 set_default_size_callback (GtkWidget *widget,
10850                            gpointer   data)
10851 {
10852   gint w, h;
10853   
10854   get_ints (data, &w, &h);
10855
10856   gtk_window_set_default_size (g_object_get_data (data, "target"),
10857                                w, h);
10858 }
10859
10860 static void
10861 unset_size_request_callback (GtkWidget *widget,
10862                              gpointer   data)
10863 {
10864   gtk_widget_set_size_request (g_object_get_data (data, "target"),
10865                                -1, -1);
10866 }
10867
10868 static void
10869 set_size_request_callback (GtkWidget *widget,
10870                            gpointer   data)
10871 {
10872   gint w, h;
10873   
10874   get_ints (data, &w, &h);
10875
10876   gtk_widget_set_size_request (g_object_get_data (data, "target"),
10877                                w, h);
10878 }
10879
10880 static void
10881 set_location_callback (GtkWidget *widget,
10882                        gpointer   data)
10883 {
10884   gint x, y;
10885   
10886   get_ints (data, &x, &y);
10887
10888   gtk_window_move (g_object_get_data (data, "target"), x, y);
10889 }
10890
10891 static void
10892 move_to_position_callback (GtkWidget *widget,
10893                            gpointer   data)
10894 {
10895   gint x, y;
10896   GtkWindow *window;
10897
10898   window = g_object_get_data (data, "target");
10899   
10900   gtk_window_get_position (window, &x, &y);
10901
10902   gtk_window_move (window, x, y);
10903 }
10904
10905 static void
10906 set_geometry_callback (GtkWidget *entry,
10907                        gpointer   data)
10908 {
10909   gchar *text;
10910   GtkWindow *target;
10911
10912   target = GTK_WINDOW (g_object_get_data (G_OBJECT (data), "target"));
10913   
10914   text = gtk_editable_get_chars (GTK_EDITABLE (entry), 0, -1);
10915
10916   if (!gtk_window_parse_geometry (target, text))
10917     g_print ("Bad geometry string '%s'\n", text);
10918
10919   g_free (text);
10920 }
10921
10922 static void
10923 allow_shrink_callback (GtkWidget *widget,
10924                        gpointer   data)
10925 {
10926   g_object_set (g_object_get_data (data, "target"),
10927                 "allow_shrink",
10928                 GTK_TOGGLE_BUTTON (widget)->active,
10929                 NULL);
10930 }
10931
10932 static void
10933 allow_grow_callback (GtkWidget *widget,
10934                      gpointer   data)
10935 {
10936   g_object_set (g_object_get_data (data, "target"),
10937                 "allow_grow",
10938                 GTK_TOGGLE_BUTTON (widget)->active,
10939                 NULL);
10940 }
10941
10942 static void
10943 gravity_selected (GtkWidget *widget,
10944                   gpointer   data)
10945 {
10946   gtk_window_set_gravity (GTK_WINDOW (g_object_get_data (data, "target")),
10947                           gtk_option_menu_get_history (GTK_OPTION_MENU (widget)) + GDK_GRAVITY_NORTH_WEST);
10948 }
10949
10950 static void
10951 pos_selected (GtkWidget *widget,
10952               gpointer   data)
10953 {
10954   gtk_window_set_position (GTK_WINDOW (g_object_get_data (data, "target")),
10955                            gtk_option_menu_get_history (GTK_OPTION_MENU (widget)) + GTK_WIN_POS_NONE);
10956 }
10957
10958 static void
10959 move_gravity_window_to_current_position (GtkWidget *widget,
10960                                          gpointer   data)
10961 {
10962   gint x, y;
10963   GtkWindow *window;
10964
10965   window = GTK_WINDOW (data);    
10966   
10967   gtk_window_get_position (window, &x, &y);
10968
10969   gtk_window_move (window, x, y);
10970 }
10971
10972 static void
10973 get_screen_corner (GtkWindow *window,
10974                    gint      *x,
10975                    gint      *y)
10976 {
10977   int w, h;
10978   GdkScreen * screen = gtk_window_get_screen (window);
10979   
10980   gtk_window_get_size (GTK_WINDOW (window), &w, &h);
10981
10982   switch (gtk_window_get_gravity (window))
10983     {
10984     case GDK_GRAVITY_SOUTH_EAST:
10985       *x = gdk_screen_get_width (screen) - w;
10986       *y = gdk_screen_get_height (screen) - h;
10987       break;
10988
10989     case GDK_GRAVITY_NORTH_EAST:
10990       *x = gdk_screen_get_width (screen) - w;
10991       *y = 0;
10992       break;
10993
10994     case GDK_GRAVITY_SOUTH_WEST:
10995       *x = 0;
10996       *y = gdk_screen_get_height (screen) - h;
10997       break;
10998
10999     case GDK_GRAVITY_NORTH_WEST:
11000       *x = 0;
11001       *y = 0;
11002       break;
11003       
11004     case GDK_GRAVITY_SOUTH:
11005       *x = (gdk_screen_get_width (screen) - w) / 2;
11006       *y = gdk_screen_get_height (screen) - h;
11007       break;
11008
11009     case GDK_GRAVITY_NORTH:
11010       *x = (gdk_screen_get_width (screen) - w) / 2;
11011       *y = 0;
11012       break;
11013
11014     case GDK_GRAVITY_WEST:
11015       *x = 0;
11016       *y = (gdk_screen_get_height (screen) - h) / 2;
11017       break;
11018
11019     case GDK_GRAVITY_EAST:
11020       *x = gdk_screen_get_width (screen) - w;
11021       *y = (gdk_screen_get_height (screen) - h) / 2;
11022       break;
11023
11024     case GDK_GRAVITY_CENTER:
11025       *x = (gdk_screen_get_width (screen) - w) / 2;
11026       *y = (gdk_screen_get_height (screen) - h) / 2;
11027       break;
11028
11029     case GDK_GRAVITY_STATIC:
11030       /* pick some random numbers */
11031       *x = 350;
11032       *y = 350;
11033       break;
11034
11035     default:
11036       g_assert_not_reached ();
11037       break;
11038     }
11039 }
11040
11041 static void
11042 move_gravity_window_to_starting_position (GtkWidget *widget,
11043                                           gpointer   data)
11044 {
11045   gint x, y;
11046   GtkWindow *window;
11047
11048   window = GTK_WINDOW (data);    
11049   
11050   get_screen_corner (window,
11051                      &x, &y);
11052   
11053   gtk_window_move (window, x, y);
11054 }
11055
11056 static GtkWidget*
11057 make_gravity_window (GtkWidget   *destroy_with,
11058                      GdkGravity   gravity,
11059                      const gchar *title)
11060 {
11061   GtkWidget *window;
11062   GtkWidget *button;
11063   GtkWidget *vbox;
11064   int x, y;
11065   
11066   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
11067
11068   gtk_window_set_screen (GTK_WINDOW (window),
11069                          gtk_widget_get_screen (destroy_with));
11070
11071   vbox = gtk_vbox_new (FALSE, 0);
11072   gtk_widget_show (vbox);
11073   
11074   gtk_container_add (GTK_CONTAINER (window), vbox);
11075   gtk_window_set_title (GTK_WINDOW (window), title);
11076   gtk_window_set_gravity (GTK_WINDOW (window), gravity);
11077
11078   g_signal_connect_object (destroy_with,
11079                            "destroy",
11080                            G_CALLBACK (gtk_widget_destroy),
11081                            window,
11082                            G_CONNECT_SWAPPED);
11083
11084   
11085   button = gtk_button_new_with_mnemonic ("_Move to current position");
11086
11087   g_signal_connect (button, "clicked",
11088                     G_CALLBACK (move_gravity_window_to_current_position),
11089                     window);
11090
11091   gtk_container_add (GTK_CONTAINER (vbox), button);
11092   gtk_widget_show (button);
11093
11094   button = gtk_button_new_with_mnemonic ("Move to _starting position");
11095
11096   g_signal_connect (button, "clicked",
11097                     G_CALLBACK (move_gravity_window_to_starting_position),
11098                     window);
11099
11100   gtk_container_add (GTK_CONTAINER (vbox), button);
11101   gtk_widget_show (button);
11102   
11103   /* Pretend this is the result of --geometry.
11104    * DO NOT COPY THIS CODE unless you are setting --geometry results,
11105    * and in that case you probably should just use gtk_window_parse_geometry().
11106    * AGAIN, DO NOT SET GDK_HINT_USER_POS! It violates the ICCCM unless
11107    * you are parsing --geometry or equivalent.
11108    */
11109   gtk_window_set_geometry_hints (GTK_WINDOW (window),
11110                                  NULL, NULL,
11111                                  GDK_HINT_USER_POS);
11112
11113   gtk_window_set_default_size (GTK_WINDOW (window),
11114                                200, 200);
11115
11116   get_screen_corner (GTK_WINDOW (window), &x, &y);
11117   
11118   gtk_window_move (GTK_WINDOW (window),
11119                    x, y);
11120   
11121   return window;
11122 }
11123
11124 static void
11125 do_gravity_test (GtkWidget *widget,
11126                  gpointer   data)
11127 {
11128   GtkWidget *destroy_with = data;
11129   GtkWidget *window;
11130   
11131   /* We put a window at each gravity point on the screen. */
11132   window = make_gravity_window (destroy_with, GDK_GRAVITY_NORTH_WEST,
11133                                 "NorthWest");
11134   gtk_widget_show (window);
11135   
11136   window = make_gravity_window (destroy_with, GDK_GRAVITY_SOUTH_EAST,
11137                                 "SouthEast");
11138   gtk_widget_show (window);
11139
11140   window = make_gravity_window (destroy_with, GDK_GRAVITY_NORTH_EAST,
11141                                 "NorthEast");
11142   gtk_widget_show (window);
11143
11144   window = make_gravity_window (destroy_with, GDK_GRAVITY_SOUTH_WEST,
11145                                 "SouthWest");
11146   gtk_widget_show (window);
11147
11148   window = make_gravity_window (destroy_with, GDK_GRAVITY_SOUTH,
11149                                 "South");
11150   gtk_widget_show (window);
11151
11152   window = make_gravity_window (destroy_with, GDK_GRAVITY_NORTH,
11153                                 "North");
11154   gtk_widget_show (window);
11155
11156   
11157   window = make_gravity_window (destroy_with, GDK_GRAVITY_WEST,
11158                                 "West");
11159   gtk_widget_show (window);
11160
11161     
11162   window = make_gravity_window (destroy_with, GDK_GRAVITY_EAST,
11163                                 "East");
11164   gtk_widget_show (window);
11165
11166   window = make_gravity_window (destroy_with, GDK_GRAVITY_CENTER,
11167                                 "Center");
11168   gtk_widget_show (window);
11169
11170   window = make_gravity_window (destroy_with, GDK_GRAVITY_STATIC,
11171                                 "Static");
11172   gtk_widget_show (window);
11173 }
11174
11175 static GtkWidget*
11176 window_controls (GtkWidget *window)
11177 {
11178   GtkWidget *control_window;
11179   GtkWidget *label;
11180   GtkWidget *vbox;
11181   GtkWidget *button;
11182   GtkWidget *spin;
11183   GtkAdjustment *adj;
11184   GtkWidget *entry;
11185   GtkWidget *om;
11186   GtkWidget *menu;
11187   gint i;
11188   
11189   control_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
11190
11191   gtk_window_set_screen (GTK_WINDOW (control_window),
11192                          gtk_widget_get_screen (window));
11193
11194   gtk_window_set_title (GTK_WINDOW (control_window), "Size controls");
11195   
11196   g_object_set_data (G_OBJECT (control_window),
11197                      "target",
11198                      window);
11199   
11200   g_signal_connect_object (control_window,
11201                            "destroy",
11202                            G_CALLBACK (gtk_widget_destroy),
11203                            window,
11204                            G_CONNECT_SWAPPED);
11205
11206   vbox = gtk_vbox_new (FALSE, 5);
11207   
11208   gtk_container_add (GTK_CONTAINER (control_window), vbox);
11209   
11210   label = gtk_label_new ("<no configure events>");
11211   gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
11212   
11213   g_signal_connect (window,
11214                     "configure_event",
11215                     G_CALLBACK (configure_event_callback),
11216                     label);
11217
11218   adj = (GtkAdjustment *) gtk_adjustment_new (10.0, -2000.0, 2000.0, 1.0,
11219                                               5.0, 0.0);
11220   spin = gtk_spin_button_new (adj, 0, 0);
11221
11222   gtk_box_pack_start (GTK_BOX (vbox), spin, FALSE, FALSE, 0);
11223
11224   g_object_set_data (G_OBJECT (control_window), "spin1", spin);
11225
11226   adj = (GtkAdjustment *) gtk_adjustment_new (10.0, -2000.0, 2000.0, 1.0,
11227                                               5.0, 0.0);
11228   spin = gtk_spin_button_new (adj, 0, 0);
11229
11230   gtk_box_pack_start (GTK_BOX (vbox), spin, FALSE, FALSE, 0);
11231
11232   g_object_set_data (G_OBJECT (control_window), "spin2", spin);
11233
11234   entry = gtk_entry_new ();
11235   gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
11236
11237   g_signal_connect (entry, "changed",
11238                     G_CALLBACK (set_geometry_callback),
11239                     control_window);
11240
11241   button = gtk_button_new_with_label ("Show gravity test windows");
11242   g_signal_connect_swapped (button,
11243                             "clicked",
11244                             G_CALLBACK (do_gravity_test),
11245                             control_window);
11246   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
11247
11248   button = gtk_button_new_with_label ("Reshow with initial size");
11249   g_signal_connect_object (button,
11250                            "clicked",
11251                            G_CALLBACK (gtk_window_reshow_with_initial_size),
11252                            window,
11253                            G_CONNECT_SWAPPED);
11254   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
11255   
11256   button = gtk_button_new_with_label ("Queue resize");
11257   g_signal_connect_object (button,
11258                            "clicked",
11259                            G_CALLBACK (gtk_widget_queue_resize),
11260                            window,
11261                            G_CONNECT_SWAPPED);
11262   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
11263   
11264   button = gtk_button_new_with_label ("Resize");
11265   g_signal_connect (button,
11266                     "clicked",
11267                     G_CALLBACK (set_size_callback),
11268                     control_window);
11269   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
11270
11271   button = gtk_button_new_with_label ("Set default size");
11272   g_signal_connect (button,
11273                     "clicked",
11274                     G_CALLBACK (set_default_size_callback),
11275                     control_window);
11276   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
11277
11278   button = gtk_button_new_with_label ("Unset default size");
11279   g_signal_connect (button,
11280                     "clicked",
11281                     G_CALLBACK (unset_default_size_callback),
11282                     control_window);
11283   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
11284   
11285   button = gtk_button_new_with_label ("Set size request");
11286   g_signal_connect (button,
11287                     "clicked",
11288                     G_CALLBACK (set_size_request_callback),
11289                     control_window);
11290   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
11291
11292   button = gtk_button_new_with_label ("Unset size request");
11293   g_signal_connect (button,
11294                     "clicked",
11295                     G_CALLBACK (unset_size_request_callback),
11296                     control_window);
11297   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
11298   
11299   button = gtk_button_new_with_label ("Move");
11300   g_signal_connect (button,
11301                     "clicked",
11302                     G_CALLBACK (set_location_callback),
11303                     control_window);
11304   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
11305
11306   button = gtk_button_new_with_label ("Move to current position");
11307   g_signal_connect (button,
11308                     "clicked",
11309                     G_CALLBACK (move_to_position_callback),
11310                     control_window);
11311   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
11312   
11313   button = gtk_check_button_new_with_label ("Allow shrink");
11314   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE);
11315   g_signal_connect (button,
11316                     "toggled",
11317                     G_CALLBACK (allow_shrink_callback),
11318                     control_window);
11319   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
11320
11321   button = gtk_check_button_new_with_label ("Allow grow");
11322   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
11323   g_signal_connect (button,
11324                     "toggled",
11325                     G_CALLBACK (allow_grow_callback),
11326                     control_window);
11327   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
11328   
11329   button = gtk_button_new_with_mnemonic ("_Show");
11330   g_signal_connect_object (button,
11331                            "clicked",
11332                            G_CALLBACK (gtk_widget_show),
11333                            window,
11334                            G_CONNECT_SWAPPED);
11335   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
11336
11337   button = gtk_button_new_with_mnemonic ("_Hide");
11338   g_signal_connect_object (button,
11339                            "clicked",
11340                            G_CALLBACK (gtk_widget_hide),
11341                            window,
11342                            G_CONNECT_SWAPPED);
11343   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
11344   
11345   menu = gtk_menu_new ();
11346   
11347   i = 0;
11348   while (i < 10)
11349     {
11350       GtkWidget *mi;
11351       static gchar *names[] = {
11352         "GDK_GRAVITY_NORTH_WEST",
11353         "GDK_GRAVITY_NORTH",
11354         "GDK_GRAVITY_NORTH_EAST",
11355         "GDK_GRAVITY_WEST",
11356         "GDK_GRAVITY_CENTER",
11357         "GDK_GRAVITY_EAST",
11358         "GDK_GRAVITY_SOUTH_WEST",
11359         "GDK_GRAVITY_SOUTH",
11360         "GDK_GRAVITY_SOUTH_EAST",
11361         "GDK_GRAVITY_STATIC",
11362         NULL
11363       };
11364
11365       g_assert (names[i]);
11366       
11367       mi = gtk_menu_item_new_with_label (names[i]);
11368
11369       gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
11370
11371       ++i;
11372     }
11373   
11374   gtk_widget_show_all (menu);
11375   
11376   om = gtk_option_menu_new ();
11377   gtk_option_menu_set_menu (GTK_OPTION_MENU (om), menu);
11378   
11379
11380   g_signal_connect (om,
11381                     "changed",
11382                     G_CALLBACK (gravity_selected),
11383                     control_window);
11384
11385   gtk_box_pack_end (GTK_BOX (vbox), om, FALSE, FALSE, 0);
11386
11387
11388   menu = gtk_menu_new ();
11389   
11390   i = 0;
11391   while (i < 5)
11392     {
11393       GtkWidget *mi;
11394       static gchar *names[] = {
11395         "GTK_WIN_POS_NONE",
11396         "GTK_WIN_POS_CENTER",
11397         "GTK_WIN_POS_MOUSE",
11398         "GTK_WIN_POS_CENTER_ALWAYS",
11399         "GTK_WIN_POS_CENTER_ON_PARENT",
11400         NULL
11401       };
11402
11403       g_assert (names[i]);
11404       
11405       mi = gtk_menu_item_new_with_label (names[i]);
11406
11407       gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
11408
11409       ++i;
11410     }
11411   
11412   gtk_widget_show_all (menu);
11413   
11414   om = gtk_option_menu_new ();
11415   gtk_option_menu_set_menu (GTK_OPTION_MENU (om), menu);
11416   
11417
11418   g_signal_connect (om,
11419                     "changed",
11420                     G_CALLBACK (pos_selected),
11421                     control_window);
11422
11423   gtk_box_pack_end (GTK_BOX (vbox), om, FALSE, FALSE, 0);
11424   
11425   gtk_widget_show_all (vbox);
11426   
11427   return control_window;
11428 }
11429
11430 void
11431 create_window_sizing (GtkWidget *widget)
11432 {
11433   static GtkWidget *window = NULL;
11434   static GtkWidget *target_window = NULL;
11435
11436   if (!target_window)
11437     {
11438       GtkWidget *label;
11439       
11440       target_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
11441       gtk_window_set_screen (GTK_WINDOW (target_window),
11442                              gtk_widget_get_screen (widget));
11443       label = gtk_label_new (NULL);
11444       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");
11445       gtk_container_add (GTK_CONTAINER (target_window), label);
11446       gtk_widget_show (label);
11447       
11448       g_signal_connect (target_window, "destroy",
11449                         G_CALLBACK (gtk_widget_destroyed),
11450                         &target_window);
11451
11452       window = window_controls (target_window);
11453       
11454       g_signal_connect (window, "destroy",
11455                         G_CALLBACK (gtk_widget_destroyed),
11456                         &window);
11457       
11458       gtk_window_set_title (GTK_WINDOW (target_window), "Window to size");
11459     }
11460
11461   /* don't show target window by default, we want to allow testing
11462    * of behavior on first show.
11463    */
11464   
11465   if (!GTK_WIDGET_VISIBLE (window))
11466     gtk_widget_show (window);
11467   else
11468     gtk_widget_destroy (window);
11469 }
11470
11471 /*
11472  * GtkProgressBar
11473  */
11474
11475 typedef struct _ProgressData {
11476   GtkWidget *window;
11477   GtkWidget *pbar;
11478   GtkWidget *block_spin;
11479   GtkWidget *x_align_spin;
11480   GtkWidget *y_align_spin;
11481   GtkWidget *step_spin;
11482   GtkWidget *act_blocks_spin;
11483   GtkWidget *label;
11484   GtkWidget *omenu1;
11485   GtkWidget *elmenu;
11486   GtkWidget *omenu2;
11487   GtkWidget *entry;
11488   int timer;
11489 } ProgressData;
11490
11491 gint
11492 progress_timeout (gpointer data)
11493 {
11494   gdouble new_val;
11495   GtkAdjustment *adj;
11496
11497   adj = GTK_PROGRESS (data)->adjustment;
11498
11499   new_val = adj->value + 1;
11500   if (new_val > adj->upper)
11501     new_val = adj->lower;
11502
11503   gtk_progress_set_value (GTK_PROGRESS (data), new_val);
11504
11505   return TRUE;
11506 }
11507
11508 static void
11509 destroy_progress (GtkWidget     *widget,
11510                   ProgressData **pdata)
11511 {
11512   gtk_timeout_remove ((*pdata)->timer);
11513   (*pdata)->timer = 0;
11514   (*pdata)->window = NULL;
11515   g_free (*pdata);
11516   *pdata = NULL;
11517 }
11518
11519 static void
11520 progressbar_toggle_orientation (GtkWidget *widget, gpointer data)
11521 {
11522   ProgressData *pdata;
11523   gint i;
11524
11525   pdata = (ProgressData *) data;
11526
11527   if (!GTK_WIDGET_MAPPED (widget))
11528     return;
11529
11530   i = gtk_option_menu_get_history (GTK_OPTION_MENU (widget));
11531
11532   gtk_progress_bar_set_orientation (GTK_PROGRESS_BAR (pdata->pbar),
11533                                     (GtkProgressBarOrientation) i);
11534 }
11535
11536 static void
11537 toggle_show_text (GtkWidget *widget, ProgressData *pdata)
11538 {
11539   gtk_progress_set_show_text (GTK_PROGRESS (pdata->pbar),
11540                               GTK_TOGGLE_BUTTON (widget)->active);
11541   gtk_widget_set_sensitive (pdata->entry, GTK_TOGGLE_BUTTON (widget)->active);
11542   gtk_widget_set_sensitive (pdata->x_align_spin,
11543                             GTK_TOGGLE_BUTTON (widget)->active);
11544   gtk_widget_set_sensitive (pdata->y_align_spin,
11545                             GTK_TOGGLE_BUTTON (widget)->active);
11546 }
11547
11548 static void
11549 progressbar_toggle_ellipsize (GtkWidget *widget,
11550                               gpointer   data)
11551 {
11552   ProgressData *pdata = data;
11553   if (GTK_WIDGET_DRAWABLE (widget))
11554     {
11555       gint i = gtk_option_menu_get_history (GTK_OPTION_MENU (widget));
11556       gtk_progress_bar_set_ellipsize (GTK_PROGRESS_BAR (pdata->pbar), i);
11557     }
11558 }
11559
11560 static void
11561 progressbar_toggle_bar_style (GtkWidget *widget, gpointer data)
11562 {
11563   ProgressData *pdata;
11564   gint i;
11565
11566   pdata = (ProgressData *) data;
11567
11568   if (!GTK_WIDGET_MAPPED (widget))
11569     return;
11570
11571   i = gtk_option_menu_get_history (GTK_OPTION_MENU (widget));
11572
11573   if (i == 1)
11574     gtk_widget_set_sensitive (pdata->block_spin, TRUE);
11575   else
11576     gtk_widget_set_sensitive (pdata->block_spin, FALSE);
11577   
11578   gtk_progress_bar_set_bar_style (GTK_PROGRESS_BAR (pdata->pbar),
11579                                   (GtkProgressBarStyle) i);
11580 }
11581
11582 static void
11583 progress_value_changed (GtkAdjustment *adj, ProgressData *pdata)
11584 {
11585   char buf[20];
11586
11587   if (GTK_PROGRESS (pdata->pbar)->activity_mode)
11588     sprintf (buf, "???");
11589   else
11590     sprintf (buf, "%.0f%%", 100 *
11591              gtk_progress_get_current_percentage (GTK_PROGRESS (pdata->pbar)));
11592   gtk_label_set_text (GTK_LABEL (pdata->label), buf);
11593 }
11594
11595 static void
11596 adjust_blocks (GtkAdjustment *adj, ProgressData *pdata)
11597 {
11598   gtk_progress_set_percentage (GTK_PROGRESS (pdata->pbar), 0);
11599   gtk_progress_bar_set_discrete_blocks (GTK_PROGRESS_BAR (pdata->pbar),
11600      gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (pdata->block_spin)));
11601 }
11602
11603 static void
11604 adjust_step (GtkAdjustment *adj, ProgressData *pdata)
11605 {
11606   gtk_progress_bar_set_activity_step (GTK_PROGRESS_BAR (pdata->pbar),
11607      gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (pdata->step_spin)));
11608 }
11609
11610 static void
11611 adjust_act_blocks (GtkAdjustment *adj, ProgressData *pdata)
11612 {
11613   gtk_progress_bar_set_activity_blocks (GTK_PROGRESS_BAR (pdata->pbar),
11614                gtk_spin_button_get_value_as_int 
11615                       (GTK_SPIN_BUTTON (pdata->act_blocks_spin)));
11616 }
11617
11618 static void
11619 adjust_align (GtkAdjustment *adj, ProgressData *pdata)
11620 {
11621   gtk_progress_set_text_alignment (GTK_PROGRESS (pdata->pbar),
11622          gtk_spin_button_get_value (GTK_SPIN_BUTTON (pdata->x_align_spin)),
11623          gtk_spin_button_get_value (GTK_SPIN_BUTTON (pdata->y_align_spin)));
11624 }
11625
11626 static void
11627 toggle_activity_mode (GtkWidget *widget, ProgressData *pdata)
11628 {
11629   gtk_progress_set_activity_mode (GTK_PROGRESS (pdata->pbar),
11630                                   GTK_TOGGLE_BUTTON (widget)->active);
11631   gtk_widget_set_sensitive (pdata->step_spin, 
11632                             GTK_TOGGLE_BUTTON (widget)->active);
11633   gtk_widget_set_sensitive (pdata->act_blocks_spin, 
11634                             GTK_TOGGLE_BUTTON (widget)->active);
11635 }
11636
11637 static void
11638 entry_changed (GtkWidget *widget, ProgressData *pdata)
11639 {
11640   gtk_progress_set_format_string (GTK_PROGRESS (pdata->pbar),
11641                           gtk_entry_get_text (GTK_ENTRY (pdata->entry)));
11642 }
11643
11644 void
11645 create_progress_bar (GtkWidget *widget)
11646 {
11647   GtkWidget *button;
11648   GtkWidget *vbox;
11649   GtkWidget *vbox2;
11650   GtkWidget *hbox;
11651   GtkWidget *check;
11652   GtkWidget *frame;
11653   GtkWidget *tab;
11654   GtkWidget *label;
11655   GtkWidget *align;
11656   GtkAdjustment *adj;
11657   static ProgressData *pdata = NULL;
11658
11659   static gchar *items1[] =
11660   {
11661     "Left-Right",
11662     "Right-Left",
11663     "Bottom-Top",
11664     "Top-Bottom"
11665   };
11666
11667   static gchar *items2[] =
11668   {
11669     "Continuous",
11670     "Discrete"
11671   };
11672
11673   static char *ellipsize_items[] = {
11674     "None",     // PANGO_ELLIPSIZE_NONE,
11675     "Start",    // PANGO_ELLIPSIZE_START,
11676     "Middle",   // PANGO_ELLIPSIZE_MIDDLE,
11677     "End",      // PANGO_ELLIPSIZE_END
11678   };
11679   
11680   if (!pdata)
11681     pdata = g_new0 (ProgressData, 1);
11682
11683   if (!pdata->window)
11684     {
11685       pdata->window = gtk_dialog_new ();
11686
11687       gtk_window_set_screen (GTK_WINDOW (pdata->window),
11688                              gtk_widget_get_screen (widget));
11689
11690       gtk_window_set_resizable (GTK_WINDOW (pdata->window), TRUE);
11691
11692       g_signal_connect (pdata->window, "destroy",
11693                         G_CALLBACK (destroy_progress),
11694                         &pdata);
11695
11696       pdata->timer = 0;
11697
11698       gtk_window_set_title (GTK_WINDOW (pdata->window), "GtkProgressBar");
11699       gtk_container_set_border_width (GTK_CONTAINER (pdata->window), 0);
11700
11701       vbox = gtk_vbox_new (FALSE, 5);
11702       gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
11703       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (pdata->window)->vbox), 
11704                           vbox, FALSE, TRUE, 0);
11705
11706       frame = gtk_frame_new ("Progress");
11707       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
11708
11709       vbox2 = gtk_vbox_new (FALSE, 5);
11710       gtk_container_add (GTK_CONTAINER (frame), vbox2);
11711
11712       align = gtk_alignment_new (0.5, 0.5, 0, 0);
11713       gtk_box_pack_start (GTK_BOX (vbox2), align, FALSE, FALSE, 5);
11714
11715       adj = (GtkAdjustment *) gtk_adjustment_new (0, 1, 300, 0, 0, 0);
11716       g_signal_connect (adj, "value_changed",
11717                         G_CALLBACK (progress_value_changed), pdata);
11718
11719       pdata->pbar = g_object_new (GTK_TYPE_PROGRESS_BAR,
11720                                     "adjustment", adj,
11721                                     "ellipsize", PANGO_ELLIPSIZE_MIDDLE,
11722                                     NULL);
11723       gtk_progress_set_format_string (GTK_PROGRESS (pdata->pbar),
11724                                       "%v from [%l,%u] (=%p%%)");
11725       gtk_container_add (GTK_CONTAINER (align), pdata->pbar);
11726       pdata->timer = gtk_timeout_add (100, progress_timeout, pdata->pbar);
11727
11728       align = gtk_alignment_new (0.5, 0.5, 0, 0);
11729       gtk_box_pack_start (GTK_BOX (vbox2), align, FALSE, FALSE, 5);
11730
11731       hbox = gtk_hbox_new (FALSE, 5);
11732       gtk_container_add (GTK_CONTAINER (align), hbox);
11733       label = gtk_label_new ("Label updated by user :"); 
11734       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
11735       pdata->label = gtk_label_new ("");
11736       gtk_box_pack_start (GTK_BOX (hbox), pdata->label, FALSE, TRUE, 0);
11737
11738       frame = gtk_frame_new ("Options");
11739       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
11740
11741       vbox2 = gtk_vbox_new (FALSE, 5);
11742       gtk_container_add (GTK_CONTAINER (frame), vbox2);
11743
11744       tab = gtk_table_new (7, 2, FALSE);
11745       gtk_box_pack_start (GTK_BOX (vbox2), tab, FALSE, TRUE, 0);
11746
11747       label = gtk_label_new ("Orientation :");
11748       gtk_table_attach (GTK_TABLE (tab), label, 0, 1, 0, 1,
11749                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
11750                         5, 5);
11751       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
11752
11753       pdata->omenu1 = build_option_menu (items1, 4, 0,
11754                                          progressbar_toggle_orientation,
11755                                          pdata);
11756       hbox = gtk_hbox_new (FALSE, 0);
11757       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 0, 1,
11758                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
11759                         5, 5);
11760       gtk_box_pack_start (GTK_BOX (hbox), pdata->omenu1, TRUE, TRUE, 0);
11761       
11762       check = gtk_check_button_new_with_label ("Show text");
11763       g_signal_connect (check, "clicked",
11764                         G_CALLBACK (toggle_show_text),
11765                         pdata);
11766       gtk_table_attach (GTK_TABLE (tab), check, 0, 1, 1, 2,
11767                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
11768                         5, 5);
11769
11770       hbox = gtk_hbox_new (FALSE, 0);
11771       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 1, 2,
11772                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
11773                         5, 5);
11774
11775       label = gtk_label_new ("Format : ");
11776       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
11777
11778       pdata->entry = gtk_entry_new ();
11779       g_signal_connect (pdata->entry, "changed",
11780                         G_CALLBACK (entry_changed),
11781                         pdata);
11782       gtk_box_pack_start (GTK_BOX (hbox), pdata->entry, TRUE, TRUE, 0);
11783       gtk_entry_set_text (GTK_ENTRY (pdata->entry), "%v from [%l,%u] (=%p%%)");
11784       gtk_widget_set_size_request (pdata->entry, 100, -1);
11785       gtk_widget_set_sensitive (pdata->entry, FALSE);
11786
11787       label = gtk_label_new ("Text align :");
11788       gtk_table_attach (GTK_TABLE (tab), label, 0, 1, 2, 3,
11789                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
11790                         5, 5);
11791       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
11792
11793       hbox = gtk_hbox_new (FALSE, 0);
11794       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 2, 3,
11795                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
11796                         5, 5);
11797
11798       label = gtk_label_new ("x :");
11799       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 5);
11800       
11801       adj = (GtkAdjustment *) gtk_adjustment_new (0.5, 0, 1, 0.1, 0.1, 0);
11802       pdata->x_align_spin = gtk_spin_button_new (adj, 0, 1);
11803       g_signal_connect (adj, "value_changed",
11804                         G_CALLBACK (adjust_align), pdata);
11805       gtk_box_pack_start (GTK_BOX (hbox), pdata->x_align_spin, FALSE, TRUE, 0);
11806       gtk_widget_set_sensitive (pdata->x_align_spin, FALSE);
11807
11808       label = gtk_label_new ("y :");
11809       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 5);
11810
11811       adj = (GtkAdjustment *) gtk_adjustment_new (0.5, 0, 1, 0.1, 0.1, 0);
11812       pdata->y_align_spin = gtk_spin_button_new (adj, 0, 1);
11813       g_signal_connect (adj, "value_changed",
11814                         G_CALLBACK (adjust_align), pdata);
11815       gtk_box_pack_start (GTK_BOX (hbox), pdata->y_align_spin, FALSE, TRUE, 0);
11816       gtk_widget_set_sensitive (pdata->y_align_spin, FALSE);
11817
11818       label = gtk_label_new ("Ellipsize text :");
11819       gtk_table_attach (GTK_TABLE (tab), label, 0, 1, 10, 11,
11820                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
11821                         5, 5);
11822       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
11823       pdata->elmenu = build_option_menu (ellipsize_items,
11824                                          sizeof (ellipsize_items) / sizeof (ellipsize_items[0]),
11825                                          2, // PANGO_ELLIPSIZE_MIDDLE
11826                                          progressbar_toggle_ellipsize,
11827                                          pdata);
11828       hbox = gtk_hbox_new (FALSE, 0);
11829       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 10, 11,
11830                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
11831                         5, 5);
11832       gtk_box_pack_start (GTK_BOX (hbox), pdata->elmenu, TRUE, TRUE, 0);
11833
11834       label = gtk_label_new ("Bar Style :");
11835       gtk_table_attach (GTK_TABLE (tab), label, 0, 1, 13, 14,
11836                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
11837                         5, 5);
11838       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
11839
11840       pdata->omenu2 = build_option_menu (items2, 2, 0,
11841                                          progressbar_toggle_bar_style,
11842                                          pdata);
11843       hbox = gtk_hbox_new (FALSE, 0);
11844       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 13, 14,
11845                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
11846                         5, 5);
11847       gtk_box_pack_start (GTK_BOX (hbox), pdata->omenu2, TRUE, TRUE, 0);
11848
11849       label = gtk_label_new ("Block count :");
11850       gtk_table_attach (GTK_TABLE (tab), label, 0, 1, 14, 15,
11851                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
11852                         5, 5);
11853       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
11854
11855       hbox = gtk_hbox_new (FALSE, 0);
11856       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 14, 15,
11857                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
11858                         5, 5);
11859       adj = (GtkAdjustment *) gtk_adjustment_new (10, 2, 20, 1, 5, 0);
11860       pdata->block_spin = gtk_spin_button_new (adj, 0, 0);
11861       g_signal_connect (adj, "value_changed",
11862                         G_CALLBACK (adjust_blocks), pdata);
11863       gtk_box_pack_start (GTK_BOX (hbox), pdata->block_spin, FALSE, TRUE, 0);
11864       gtk_widget_set_sensitive (pdata->block_spin, FALSE);
11865
11866       check = gtk_check_button_new_with_label ("Activity mode");
11867       g_signal_connect (check, "clicked",
11868                         G_CALLBACK (toggle_activity_mode), pdata);
11869       gtk_table_attach (GTK_TABLE (tab), check, 0, 1, 15, 16,
11870                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
11871                         5, 5);
11872
11873       hbox = gtk_hbox_new (FALSE, 0);
11874       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 15, 16,
11875                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
11876                         5, 5);
11877       label = gtk_label_new ("Step size : ");
11878       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
11879       adj = (GtkAdjustment *) gtk_adjustment_new (3, 1, 20, 1, 5, 0);
11880       pdata->step_spin = gtk_spin_button_new (adj, 0, 0);
11881       g_signal_connect (adj, "value_changed",
11882                         G_CALLBACK (adjust_step), pdata);
11883       gtk_box_pack_start (GTK_BOX (hbox), pdata->step_spin, FALSE, TRUE, 0);
11884       gtk_widget_set_sensitive (pdata->step_spin, FALSE);
11885
11886       hbox = gtk_hbox_new (FALSE, 0);
11887       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 16, 17,
11888                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
11889                         5, 5);
11890       label = gtk_label_new ("Blocks :     ");
11891       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
11892       adj = (GtkAdjustment *) gtk_adjustment_new (5, 2, 10, 1, 5, 0);
11893       pdata->act_blocks_spin = gtk_spin_button_new (adj, 0, 0);
11894       g_signal_connect (adj, "value_changed",
11895                         G_CALLBACK (adjust_act_blocks), pdata);
11896       gtk_box_pack_start (GTK_BOX (hbox), pdata->act_blocks_spin, FALSE, TRUE,
11897                           0);
11898       gtk_widget_set_sensitive (pdata->act_blocks_spin, FALSE);
11899
11900       button = gtk_button_new_with_label ("close");
11901       g_signal_connect_swapped (button, "clicked",
11902                                 G_CALLBACK (gtk_widget_destroy),
11903                                 pdata->window);
11904       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
11905       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (pdata->window)->action_area), 
11906                           button, TRUE, TRUE, 0);
11907       gtk_widget_grab_default (button);
11908     }
11909
11910   if (!GTK_WIDGET_VISIBLE (pdata->window))
11911     gtk_widget_show_all (pdata->window);
11912   else
11913     gtk_widget_destroy (pdata->window);
11914 }
11915
11916 /*
11917  * Properties
11918  */
11919
11920 typedef struct {
11921   int x;
11922   int y;
11923   gboolean found;
11924   gboolean first;
11925   GtkWidget *res_widget;
11926 } FindWidgetData;
11927
11928 static void
11929 find_widget (GtkWidget *widget, FindWidgetData *data)
11930 {
11931   GtkAllocation new_allocation;
11932   gint x_offset = 0;
11933   gint y_offset = 0;
11934
11935   new_allocation = widget->allocation;
11936
11937   if (data->found || !GTK_WIDGET_MAPPED (widget))
11938     return;
11939
11940   /* Note that in the following code, we only count the
11941    * position as being inside a WINDOW widget if it is inside
11942    * widget->window; points that are outside of widget->window
11943    * but within the allocation are not counted. This is consistent
11944    * with the way we highlight drag targets.
11945    */
11946   if (!GTK_WIDGET_NO_WINDOW (widget))
11947     {
11948       new_allocation.x = 0;
11949       new_allocation.y = 0;
11950     }
11951   
11952   if (widget->parent && !data->first)
11953     {
11954       GdkWindow *window = widget->window;
11955       while (window != widget->parent->window)
11956         {
11957           gint tx, ty, twidth, theight;
11958           gdk_drawable_get_size (window, &twidth, &theight);
11959
11960           if (new_allocation.x < 0)
11961             {
11962               new_allocation.width += new_allocation.x;
11963               new_allocation.x = 0;
11964             }
11965           if (new_allocation.y < 0)
11966             {
11967               new_allocation.height += new_allocation.y;
11968               new_allocation.y = 0;
11969             }
11970           if (new_allocation.x + new_allocation.width > twidth)
11971             new_allocation.width = twidth - new_allocation.x;
11972           if (new_allocation.y + new_allocation.height > theight)
11973             new_allocation.height = theight - new_allocation.y;
11974
11975           gdk_window_get_position (window, &tx, &ty);
11976           new_allocation.x += tx;
11977           x_offset += tx;
11978           new_allocation.y += ty;
11979           y_offset += ty;
11980           
11981           window = gdk_window_get_parent (window);
11982         }
11983     }
11984
11985   if ((data->x >= new_allocation.x) && (data->y >= new_allocation.y) &&
11986       (data->x < new_allocation.x + new_allocation.width) && 
11987       (data->y < new_allocation.y + new_allocation.height))
11988     {
11989       /* First, check if the drag is in a valid drop site in
11990        * one of our children 
11991        */
11992       if (GTK_IS_CONTAINER (widget))
11993         {
11994           FindWidgetData new_data = *data;
11995           
11996           new_data.x -= x_offset;
11997           new_data.y -= y_offset;
11998           new_data.found = FALSE;
11999           new_data.first = FALSE;
12000           
12001           gtk_container_forall (GTK_CONTAINER (widget),
12002                                 (GtkCallback)find_widget,
12003                                 &new_data);
12004           
12005           data->found = new_data.found;
12006           if (data->found)
12007             data->res_widget = new_data.res_widget;
12008         }
12009
12010       /* If not, and this widget is registered as a drop site, check to
12011        * emit "drag_motion" to check if we are actually in
12012        * a drop site.
12013        */
12014       if (!data->found)
12015         {
12016           data->found = TRUE;
12017           data->res_widget = widget;
12018         }
12019     }
12020 }
12021
12022 static GtkWidget *
12023 find_widget_at_pointer (GdkDisplay *display)
12024 {
12025   GtkWidget *widget = NULL;
12026   GdkWindow *pointer_window;
12027   gint x, y;
12028   FindWidgetData data;
12029  
12030  pointer_window = gdk_display_get_window_at_pointer (display, NULL, NULL);
12031  
12032  if (pointer_window)
12033    gdk_window_get_user_data (pointer_window, (gpointer) &widget);
12034
12035  if (widget)
12036    {
12037      gdk_window_get_pointer (widget->window,
12038                              &x, &y, NULL);
12039      
12040      data.x = x;
12041      data.y = y;
12042      data.found = FALSE;
12043      data.first = TRUE;
12044
12045      find_widget (widget, &data);
12046      if (data.found)
12047        return data.res_widget;
12048      return widget;
12049    }
12050  return NULL;
12051 }
12052
12053 struct PropertiesData {
12054   GtkWidget **window;
12055   GdkCursor *cursor;
12056   gboolean in_query;
12057   gint handler;
12058 };
12059
12060 static void
12061 destroy_properties (GtkWidget             *widget,
12062                     struct PropertiesData *data)
12063 {
12064   if (data->window)
12065     {
12066       *data->window = NULL;
12067       data->window = NULL;
12068     }
12069
12070   if (data->cursor)
12071     {
12072       gdk_cursor_unref (data->cursor);
12073       data->cursor = NULL;
12074     }
12075
12076   if (data->handler)
12077     {
12078       g_signal_handler_disconnect (widget, data->handler);
12079       data->handler = 0;
12080     }
12081
12082   g_free (data);
12083 }
12084
12085 static gint
12086 property_query_event (GtkWidget        *widget,
12087                       GdkEvent         *event,
12088                       struct PropertiesData *data)
12089 {
12090   GtkWidget *res_widget = NULL;
12091
12092   if (!data->in_query)
12093     return FALSE;
12094   
12095   if (event->type == GDK_BUTTON_RELEASE)
12096     {
12097       gtk_grab_remove (widget);
12098       gdk_display_pointer_ungrab (gtk_widget_get_display (widget),
12099                                   GDK_CURRENT_TIME);
12100       
12101       res_widget = find_widget_at_pointer (gtk_widget_get_display (widget));
12102       if (res_widget)
12103         {
12104           g_object_set_data (G_OBJECT (res_widget), "prop-editor-screen",
12105                              gtk_widget_get_screen (widget));
12106           create_prop_editor (G_OBJECT (res_widget), 0);
12107         }
12108
12109       data->in_query = FALSE;
12110     }
12111   return FALSE;
12112 }
12113
12114
12115 static void
12116 query_properties (GtkButton *button,
12117                   struct PropertiesData *data)
12118 {
12119   gint failure;
12120
12121   g_signal_connect (button, "event",
12122                     G_CALLBACK (property_query_event), data);
12123
12124
12125   if (!data->cursor)
12126     data->cursor = gdk_cursor_new_for_display (gtk_widget_get_display (GTK_WIDGET (button)),
12127                                                GDK_TARGET);
12128   
12129   failure = gdk_pointer_grab (GTK_WIDGET (button)->window,
12130                               TRUE,
12131                               GDK_BUTTON_RELEASE_MASK,
12132                               NULL,
12133                               data->cursor,
12134                               GDK_CURRENT_TIME);
12135
12136   gtk_grab_add (GTK_WIDGET (button));
12137
12138   data->in_query = TRUE;
12139 }
12140
12141 static void
12142 create_properties (GtkWidget *widget)
12143 {
12144   static GtkWidget *window = NULL;
12145   GtkWidget *button;
12146   GtkWidget *vbox;
12147   GtkWidget *label;
12148   struct PropertiesData *data;
12149
12150   data = g_new (struct PropertiesData, 1);
12151   data->window = &window;
12152   data->in_query = FALSE;
12153   data->cursor = NULL;
12154   data->handler = 0;
12155
12156   if (!window)
12157     {
12158       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
12159
12160       gtk_window_set_screen (GTK_WINDOW (window),
12161                              gtk_widget_get_screen (widget));      
12162
12163       data->handler = g_signal_connect (window, "destroy",
12164                                         G_CALLBACK (destroy_properties),
12165                                         data);
12166
12167       gtk_window_set_title (GTK_WINDOW (window), "test properties");
12168       gtk_container_set_border_width (GTK_CONTAINER (window), 10);
12169
12170       vbox = gtk_vbox_new (FALSE, 1);
12171       gtk_container_add (GTK_CONTAINER (window), vbox);
12172             
12173       label = gtk_label_new ("This is just a dumb test to test properties.\nIf you need a generic module, get GLE.");
12174       gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
12175       
12176       button = gtk_button_new_with_label ("Query properties");
12177       gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
12178       g_signal_connect (button, "clicked",
12179                         G_CALLBACK (query_properties),
12180                         data);
12181     }
12182
12183   if (!GTK_WIDGET_VISIBLE (window))
12184     gtk_widget_show_all (window);
12185   else
12186     gtk_widget_destroy (window);
12187   
12188 }
12189
12190 struct SnapshotData {
12191   GtkWidget *toplevel_button;
12192   GtkWidget **window;
12193   GdkCursor *cursor;
12194   gboolean in_query;
12195   gboolean is_toplevel;
12196   gint handler;
12197 };
12198
12199 static void
12200 destroy_snapshot_data (GtkWidget             *widget,
12201                        struct SnapshotData *data)
12202 {
12203   if (*data->window)
12204     *data->window = NULL;
12205   
12206   if (data->cursor)
12207     {
12208       gdk_cursor_unref (data->cursor);
12209       data->cursor = NULL;
12210     }
12211
12212   if (data->handler)
12213     {
12214       g_signal_handler_disconnect (widget, data->handler);
12215       data->handler = 0;
12216     }
12217
12218   g_free (data);
12219 }
12220
12221 static gint
12222 snapshot_widget_event (GtkWidget               *widget,
12223                        GdkEvent        *event,
12224                        struct SnapshotData *data)
12225 {
12226   GtkWidget *res_widget = NULL;
12227
12228   if (!data->in_query)
12229     return FALSE;
12230   
12231   if (event->type == GDK_BUTTON_RELEASE)
12232     {
12233       gtk_grab_remove (widget);
12234       gdk_display_pointer_ungrab (gtk_widget_get_display (widget),
12235                                   GDK_CURRENT_TIME);
12236       
12237       res_widget = find_widget_at_pointer (gtk_widget_get_display (widget));
12238       if (data->is_toplevel && res_widget)
12239         res_widget = gtk_widget_get_toplevel (res_widget);
12240       if (res_widget)
12241         {
12242           GdkPixmap *pixmap;
12243           GtkWidget *window, *image;
12244
12245           window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
12246           pixmap = gtk_widget_get_snapshot (res_widget, NULL);
12247           gtk_widget_realize (window);
12248           if (gdk_drawable_get_depth (window->window) != gdk_drawable_get_depth (pixmap))
12249             {
12250               /* this branch is needed to convert ARGB -> RGB */
12251               int width, height;
12252               GdkPixbuf *pixbuf;
12253               gdk_drawable_get_size (pixmap, &width, &height);
12254               pixbuf = gdk_pixbuf_get_from_drawable (NULL, pixmap,
12255                                                      gtk_widget_get_colormap (res_widget),
12256                                                      0, 0,
12257                                                      0, 0,
12258                                                      width, height);
12259               image = gtk_image_new_from_pixbuf (pixbuf);
12260               g_object_unref (pixbuf);
12261             }
12262           else
12263             image = gtk_image_new_from_pixmap (pixmap, NULL);
12264           gtk_container_add (GTK_CONTAINER (window), image);
12265           g_object_unref (pixmap);
12266           gtk_widget_show_all (window);
12267         }
12268
12269       data->in_query = FALSE;
12270     }
12271   return FALSE;
12272 }
12273
12274
12275 static void
12276 snapshot_widget (GtkButton *button,
12277                  struct SnapshotData *data)
12278 {
12279   gint failure;
12280
12281   g_signal_connect (button, "event",
12282                     G_CALLBACK (snapshot_widget_event), data);
12283
12284   data->is_toplevel = GTK_WIDGET (button) == data->toplevel_button;
12285   
12286   if (!data->cursor)
12287     data->cursor = gdk_cursor_new_for_display (gtk_widget_get_display (GTK_WIDGET (button)),
12288                                                GDK_TARGET);
12289   
12290   failure = gdk_pointer_grab (GTK_WIDGET (button)->window,
12291                               TRUE,
12292                               GDK_BUTTON_RELEASE_MASK,
12293                               NULL,
12294                               data->cursor,
12295                               GDK_CURRENT_TIME);
12296
12297   gtk_grab_add (GTK_WIDGET (button));
12298
12299   data->in_query = TRUE;
12300 }
12301
12302 static void
12303 create_snapshot (GtkWidget *widget)
12304 {
12305   static GtkWidget *window = NULL;
12306   GtkWidget *button;
12307   GtkWidget *vbox;
12308   struct SnapshotData *data;
12309
12310   data = g_new (struct SnapshotData, 1);
12311   data->window = &window;
12312   data->in_query = FALSE;
12313   data->cursor = NULL;
12314   data->handler = 0;
12315
12316   if (!window)
12317     {
12318       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
12319
12320       gtk_window_set_screen (GTK_WINDOW (window),
12321                              gtk_widget_get_screen (widget));      
12322
12323       data->handler = g_signal_connect (window, "destroy",
12324                                         G_CALLBACK (destroy_snapshot_data),
12325                                         data);
12326
12327       gtk_window_set_title (GTK_WINDOW (window), "test snapshot");
12328       gtk_container_set_border_width (GTK_CONTAINER (window), 10);
12329
12330       vbox = gtk_vbox_new (FALSE, 1);
12331       gtk_container_add (GTK_CONTAINER (window), vbox);
12332             
12333       button = gtk_button_new_with_label ("Snapshot widget");
12334       gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
12335       g_signal_connect (button, "clicked",
12336                         G_CALLBACK (snapshot_widget),
12337                         data);
12338       
12339       button = gtk_button_new_with_label ("Snapshot toplevel");
12340       data->toplevel_button = button;
12341       gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
12342       g_signal_connect (button, "clicked",
12343                         G_CALLBACK (snapshot_widget),
12344                         data);
12345     }
12346
12347   if (!GTK_WIDGET_VISIBLE (window))
12348     gtk_widget_show_all (window);
12349   else
12350     gtk_widget_destroy (window);
12351   
12352 }
12353
12354
12355
12356 /*
12357  * Color Preview
12358  */
12359
12360 static int color_idle = 0;
12361
12362 gint
12363 color_idle_func (GtkWidget *preview)
12364 {
12365   static int count = 1;
12366   guchar buf[768];
12367   int i, j, k;
12368
12369   for (i = 0; i < 256; i++)
12370     {
12371       for (j = 0, k = 0; j < 256; j++)
12372         {
12373           buf[k+0] = i + count;
12374           buf[k+1] = 0;
12375           buf[k+2] = j + count;
12376           k += 3;
12377         }
12378
12379       gtk_preview_draw_row (GTK_PREVIEW (preview), buf, 0, i, 256);
12380     }
12381
12382   count += 1;
12383
12384   gtk_widget_queue_draw (preview);
12385   gdk_window_process_updates (preview->window, TRUE);
12386
12387   return TRUE;
12388 }
12389
12390 static void
12391 color_preview_destroy (GtkWidget  *widget,
12392                        GtkWidget **window)
12393 {
12394   gtk_idle_remove (color_idle);
12395   color_idle = 0;
12396
12397   *window = NULL;
12398 }
12399
12400 void
12401 create_color_preview (GtkWidget *widget)
12402 {
12403   static GtkWidget *window = NULL;
12404   GtkWidget *preview;
12405   guchar buf[768];
12406   int i, j, k;
12407
12408   if (!window)
12409     {
12410       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
12411       
12412       gtk_window_set_screen (GTK_WINDOW (window),
12413                              gtk_widget_get_screen (widget));
12414
12415       g_signal_connect (window, "destroy",
12416                         G_CALLBACK (color_preview_destroy),
12417                         &window);
12418
12419       gtk_window_set_title (GTK_WINDOW (window), "test");
12420       gtk_container_set_border_width (GTK_CONTAINER (window), 10);
12421
12422       preview = gtk_preview_new (GTK_PREVIEW_COLOR);
12423       gtk_preview_size (GTK_PREVIEW (preview), 256, 256);
12424       gtk_container_add (GTK_CONTAINER (window), preview);
12425
12426       for (i = 0; i < 256; i++)
12427         {
12428           for (j = 0, k = 0; j < 256; j++)
12429             {
12430               buf[k+0] = i;
12431               buf[k+1] = 0;
12432               buf[k+2] = j;
12433               k += 3;
12434             }
12435
12436           gtk_preview_draw_row (GTK_PREVIEW (preview), buf, 0, i, 256);
12437         }
12438
12439       color_idle = gtk_idle_add ((GtkFunction) color_idle_func, preview);
12440     }
12441
12442   if (!GTK_WIDGET_VISIBLE (window))
12443     gtk_widget_show_all (window);
12444   else
12445     gtk_widget_destroy (window);
12446 }
12447
12448 /*
12449  * Gray Preview
12450  */
12451
12452 static int gray_idle = 0;
12453
12454 gint
12455 gray_idle_func (GtkWidget *preview)
12456 {
12457   static int count = 1;
12458   guchar buf[256];
12459   int i, j;
12460
12461   for (i = 0; i < 256; i++)
12462     {
12463       for (j = 0; j < 256; j++)
12464         buf[j] = i + j + count;
12465
12466       gtk_preview_draw_row (GTK_PREVIEW (preview), buf, 0, i, 256);
12467     }
12468
12469   count += 1;
12470
12471   gtk_widget_draw (preview, NULL);
12472
12473   return TRUE;
12474 }
12475
12476 static void
12477 gray_preview_destroy (GtkWidget  *widget,
12478                       GtkWidget **window)
12479 {
12480   gtk_idle_remove (gray_idle);
12481   gray_idle = 0;
12482
12483   *window = NULL;
12484 }
12485
12486 void
12487 create_gray_preview (GtkWidget *widget)
12488 {
12489   static GtkWidget *window = NULL;
12490   GtkWidget *preview;
12491   guchar buf[256];
12492   int i, j;
12493
12494   if (!window)
12495     {
12496       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
12497
12498       gtk_window_set_screen (GTK_WINDOW (window),
12499                              gtk_widget_get_screen (widget));
12500
12501       g_signal_connect (window, "destroy",
12502                         G_CALLBACK (gray_preview_destroy),
12503                         &window);
12504
12505       gtk_window_set_title (GTK_WINDOW (window), "test");
12506       gtk_container_set_border_width (GTK_CONTAINER (window), 10);
12507
12508       preview = gtk_preview_new (GTK_PREVIEW_GRAYSCALE);
12509       gtk_preview_size (GTK_PREVIEW (preview), 256, 256);
12510       gtk_container_add (GTK_CONTAINER (window), preview);
12511
12512       for (i = 0; i < 256; i++)
12513         {
12514           for (j = 0; j < 256; j++)
12515             buf[j] = i + j;
12516
12517           gtk_preview_draw_row (GTK_PREVIEW (preview), buf, 0, i, 256);
12518         }
12519
12520       gray_idle = gtk_idle_add ((GtkFunction) gray_idle_func, preview);
12521     }
12522
12523   if (!GTK_WIDGET_VISIBLE (window))
12524     gtk_widget_show_all (window);
12525   else
12526     gtk_widget_destroy (window);
12527 }
12528
12529
12530 /*
12531  * Selection Test
12532  */
12533
12534 void
12535 selection_test_received (GtkWidget *list, GtkSelectionData *data)
12536 {
12537   GdkAtom *atoms;
12538   GtkWidget *list_item;
12539   GList *item_list;
12540   int i, l;
12541
12542   if (data->length < 0)
12543     {
12544       g_print ("Selection retrieval failed\n");
12545       return;
12546     }
12547   if (data->type != GDK_SELECTION_TYPE_ATOM)
12548     {
12549       g_print ("Selection \"TARGETS\" was not returned as atoms!\n");
12550       return;
12551     }
12552
12553   /* Clear out any current list items */
12554
12555   gtk_list_clear_items (GTK_LIST(list), 0, -1);
12556
12557   /* Add new items to list */
12558
12559   atoms = (GdkAtom *)data->data;
12560
12561   item_list = NULL;
12562   l = data->length / sizeof (GdkAtom);
12563   for (i = 0; i < l; i++)
12564     {
12565       char *name;
12566       name = gdk_atom_name (atoms[i]);
12567       if (name != NULL)
12568         {
12569           list_item = gtk_list_item_new_with_label (name);
12570           g_free (name);
12571         }
12572       else
12573         list_item = gtk_list_item_new_with_label ("(bad atom)");
12574
12575       gtk_widget_show (list_item);
12576       item_list = g_list_append (item_list, list_item);
12577     }
12578
12579   gtk_list_append_items (GTK_LIST (list), item_list);
12580
12581   return;
12582 }
12583
12584 void
12585 selection_test_get_targets (GtkWidget *widget, GtkWidget *list)
12586 {
12587   static GdkAtom targets_atom = GDK_NONE;
12588
12589   if (targets_atom == GDK_NONE)
12590     targets_atom = gdk_atom_intern ("TARGETS", FALSE);
12591
12592   gtk_selection_convert (list, GDK_SELECTION_PRIMARY, targets_atom,
12593                          GDK_CURRENT_TIME);
12594 }
12595
12596 void
12597 create_selection_test (GtkWidget *widget)
12598 {
12599   static GtkWidget *window = NULL;
12600   GtkWidget *button;
12601   GtkWidget *vbox;
12602   GtkWidget *scrolled_win;
12603   GtkWidget *list;
12604   GtkWidget *label;
12605
12606   if (!window)
12607     {
12608       window = gtk_dialog_new ();
12609       
12610       gtk_window_set_screen (GTK_WINDOW (window),
12611                              gtk_widget_get_screen (widget));
12612
12613       g_signal_connect (window, "destroy",
12614                         G_CALLBACK (gtk_widget_destroyed),
12615                         &window);
12616
12617       gtk_window_set_title (GTK_WINDOW (window), "Selection Test");
12618       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
12619
12620       /* Create the list */
12621
12622       vbox = gtk_vbox_new (FALSE, 5);
12623       gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
12624       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), vbox,
12625                           TRUE, TRUE, 0);
12626
12627       label = gtk_label_new ("Gets available targets for current selection");
12628       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
12629
12630       scrolled_win = gtk_scrolled_window_new (NULL, NULL);
12631       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
12632                                       GTK_POLICY_AUTOMATIC, 
12633                                       GTK_POLICY_AUTOMATIC);
12634       gtk_box_pack_start (GTK_BOX (vbox), scrolled_win, TRUE, TRUE, 0);
12635       gtk_widget_set_size_request (scrolled_win, 100, 200);
12636
12637       list = gtk_list_new ();
12638       gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_win), list);
12639
12640       g_signal_connect (list, "selection_received",
12641                         G_CALLBACK (selection_test_received), NULL);
12642
12643       /* .. And create some buttons */
12644       button = gtk_button_new_with_label ("Get Targets");
12645       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area),
12646                           button, TRUE, TRUE, 0);
12647
12648       g_signal_connect (button, "clicked",
12649                         G_CALLBACK (selection_test_get_targets), list);
12650
12651       button = gtk_button_new_with_label ("Quit");
12652       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area),
12653                           button, TRUE, TRUE, 0);
12654
12655       g_signal_connect_swapped (button, "clicked",
12656                                 G_CALLBACK (gtk_widget_destroy),
12657                                 window);
12658     }
12659
12660   if (!GTK_WIDGET_VISIBLE (window))
12661     gtk_widget_show_all (window);
12662   else
12663     gtk_widget_destroy (window);
12664 }
12665
12666 /*
12667  * Gamma Curve
12668  */
12669
12670 void
12671 create_gamma_curve (GtkWidget *widget)
12672 {
12673   static GtkWidget *window = NULL, *curve;
12674   static int count = 0;
12675   gfloat vec[256];
12676   gint max;
12677   gint i;
12678   
12679   if (!window)
12680     {
12681       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
12682       gtk_window_set_screen (GTK_WINDOW (window),
12683                              gtk_widget_get_screen (widget));
12684
12685       gtk_window_set_title (GTK_WINDOW (window), "test");
12686       gtk_container_set_border_width (GTK_CONTAINER (window), 10);
12687
12688       g_signal_connect (window, "destroy",
12689                         G_CALLBACK(gtk_widget_destroyed),
12690                         &window);
12691
12692       curve = gtk_gamma_curve_new ();
12693       gtk_container_add (GTK_CONTAINER (window), curve);
12694       gtk_widget_show (curve);
12695     }
12696
12697   max = 127 + (count % 2)*128;
12698   gtk_curve_set_range (GTK_CURVE (GTK_GAMMA_CURVE (curve)->curve),
12699                        0, max, 0, max);
12700   for (i = 0; i < max; ++i)
12701     vec[i] = (127 / sqrt (max)) * sqrt (i);
12702   gtk_curve_set_vector (GTK_CURVE (GTK_GAMMA_CURVE (curve)->curve),
12703                         max, vec);
12704
12705   if (!GTK_WIDGET_VISIBLE (window))
12706     gtk_widget_show (window);
12707   else if (count % 4 == 3)
12708     {
12709       gtk_widget_destroy (window);
12710       window = NULL;
12711     }
12712
12713   ++count;
12714 }
12715
12716 /*
12717  * Test scrolling
12718  */
12719
12720 static int scroll_test_pos = 0.0;
12721
12722 static gint
12723 scroll_test_expose (GtkWidget *widget, GdkEventExpose *event,
12724                     GtkAdjustment *adj)
12725 {
12726   gint i,j;
12727   gint imin, imax, jmin, jmax;
12728   
12729   imin = (event->area.x) / 10;
12730   imax = (event->area.x + event->area.width + 9) / 10;
12731
12732   jmin = ((int)adj->value + event->area.y) / 10;
12733   jmax = ((int)adj->value + event->area.y + event->area.height + 9) / 10;
12734
12735   gdk_window_clear_area (widget->window,
12736                          event->area.x, event->area.y,
12737                          event->area.width, event->area.height);
12738
12739   for (i=imin; i<imax; i++)
12740     for (j=jmin; j<jmax; j++)
12741       if ((i+j) % 2)
12742         gdk_draw_rectangle (widget->window, 
12743                             widget->style->black_gc,
12744                             TRUE,
12745                             10*i, 10*j - (int)adj->value, 1+i%10, 1+j%10);
12746
12747   return TRUE;
12748 }
12749
12750 static gint
12751 scroll_test_scroll (GtkWidget *widget, GdkEventScroll *event,
12752                     GtkAdjustment *adj)
12753 {
12754   gdouble new_value = adj->value + ((event->direction == GDK_SCROLL_UP) ?
12755                                     -adj->page_increment / 2:
12756                                     adj->page_increment / 2);
12757   new_value = CLAMP (new_value, adj->lower, adj->upper - adj->page_size);
12758   gtk_adjustment_set_value (adj, new_value);  
12759   
12760   return TRUE;
12761 }
12762
12763 static void
12764 scroll_test_configure (GtkWidget *widget, GdkEventConfigure *event,
12765                        GtkAdjustment *adj)
12766 {
12767   adj->page_increment = 0.9 * widget->allocation.height;
12768   adj->page_size = widget->allocation.height;
12769
12770   g_signal_emit_by_name (adj, "changed");
12771 }
12772
12773 static void
12774 scroll_test_adjustment_changed (GtkAdjustment *adj, GtkWidget *widget)
12775 {
12776   /* gint source_min = (int)adj->value - scroll_test_pos; */
12777   gint dy;
12778
12779   dy = scroll_test_pos - (int)adj->value;
12780   scroll_test_pos = adj->value;
12781
12782   if (!GTK_WIDGET_DRAWABLE (widget))
12783     return;
12784   gdk_window_scroll (widget->window, 0, dy);
12785   gdk_window_process_updates (widget->window, FALSE);
12786 }
12787
12788
12789 void
12790 create_scroll_test (GtkWidget *widget)
12791 {
12792   static GtkWidget *window = NULL;
12793   GtkWidget *hbox;
12794   GtkWidget *drawing_area;
12795   GtkWidget *scrollbar;
12796   GtkWidget *button;
12797   GtkAdjustment *adj;
12798   GdkGeometry geometry;
12799   GdkWindowHints geometry_mask;
12800
12801   if (!window)
12802     {
12803       window = gtk_dialog_new ();
12804
12805       gtk_window_set_screen (GTK_WINDOW (window),
12806                              gtk_widget_get_screen (widget));
12807
12808       g_signal_connect (window, "destroy",
12809                         G_CALLBACK (gtk_widget_destroyed),
12810                         &window);
12811
12812       gtk_window_set_title (GTK_WINDOW (window), "Scroll Test");
12813       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
12814
12815       hbox = gtk_hbox_new (FALSE, 0);
12816       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), hbox,
12817                           TRUE, TRUE, 0);
12818       gtk_widget_show (hbox);
12819
12820       drawing_area = gtk_drawing_area_new ();
12821       gtk_widget_set_size_request (drawing_area, 200, 200);
12822       gtk_box_pack_start (GTK_BOX (hbox), drawing_area, TRUE, TRUE, 0);
12823       gtk_widget_show (drawing_area);
12824
12825       gtk_widget_set_events (drawing_area, GDK_EXPOSURE_MASK | GDK_SCROLL_MASK);
12826
12827       adj = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 1000.0, 1.0, 180.0, 200.0));
12828       scroll_test_pos = 0.0;
12829
12830       scrollbar = gtk_vscrollbar_new (adj);
12831       gtk_box_pack_start (GTK_BOX (hbox), scrollbar, FALSE, FALSE, 0);
12832       gtk_widget_show (scrollbar);
12833
12834       g_signal_connect (drawing_area, "expose_event",
12835                         G_CALLBACK (scroll_test_expose), adj);
12836       g_signal_connect (drawing_area, "configure_event",
12837                         G_CALLBACK (scroll_test_configure), adj);
12838       g_signal_connect (drawing_area, "scroll_event",
12839                         G_CALLBACK (scroll_test_scroll), adj);
12840       
12841       g_signal_connect (adj, "value_changed",
12842                         G_CALLBACK (scroll_test_adjustment_changed),
12843                         drawing_area);
12844       
12845       /* .. And create some buttons */
12846
12847       button = gtk_button_new_with_label ("Quit");
12848       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area),
12849                           button, TRUE, TRUE, 0);
12850
12851       g_signal_connect_swapped (button, "clicked",
12852                                 G_CALLBACK (gtk_widget_destroy),
12853                                 window);
12854       gtk_widget_show (button);
12855
12856       /* Set up gridded geometry */
12857
12858       geometry_mask = GDK_HINT_MIN_SIZE | 
12859                        GDK_HINT_BASE_SIZE | 
12860                        GDK_HINT_RESIZE_INC;
12861
12862       geometry.min_width = 20;
12863       geometry.min_height = 20;
12864       geometry.base_width = 0;
12865       geometry.base_height = 0;
12866       geometry.width_inc = 10;
12867       geometry.height_inc = 10;
12868       
12869       gtk_window_set_geometry_hints (GTK_WINDOW (window),
12870                                drawing_area, &geometry, geometry_mask);
12871     }
12872
12873   if (!GTK_WIDGET_VISIBLE (window))
12874     gtk_widget_show (window);
12875   else
12876     gtk_widget_destroy (window);
12877 }
12878
12879 /*
12880  * Timeout Test
12881  */
12882
12883 static int timer = 0;
12884
12885 gint
12886 timeout_test (GtkWidget *label)
12887 {
12888   static int count = 0;
12889   static char buffer[32];
12890
12891   sprintf (buffer, "count: %d", ++count);
12892   gtk_label_set_text (GTK_LABEL (label), buffer);
12893
12894   return TRUE;
12895 }
12896
12897 void
12898 start_timeout_test (GtkWidget *widget,
12899                     GtkWidget *label)
12900 {
12901   if (!timer)
12902     {
12903       timer = gtk_timeout_add (100, (GtkFunction) timeout_test, label);
12904     }
12905 }
12906
12907 void
12908 stop_timeout_test (GtkWidget *widget,
12909                    gpointer   data)
12910 {
12911   if (timer)
12912     {
12913       gtk_timeout_remove (timer);
12914       timer = 0;
12915     }
12916 }
12917
12918 void
12919 destroy_timeout_test (GtkWidget  *widget,
12920                       GtkWidget **window)
12921 {
12922   stop_timeout_test (NULL, NULL);
12923
12924   *window = NULL;
12925 }
12926
12927 void
12928 create_timeout_test (GtkWidget *widget)
12929 {
12930   static GtkWidget *window = NULL;
12931   GtkWidget *button;
12932   GtkWidget *label;
12933
12934   if (!window)
12935     {
12936       window = gtk_dialog_new ();
12937
12938       gtk_window_set_screen (GTK_WINDOW (window),
12939                              gtk_widget_get_screen (widget));
12940
12941       g_signal_connect (window, "destroy",
12942                         G_CALLBACK (destroy_timeout_test),
12943                         &window);
12944
12945       gtk_window_set_title (GTK_WINDOW (window), "Timeout Test");
12946       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
12947
12948       label = gtk_label_new ("count: 0");
12949       gtk_misc_set_padding (GTK_MISC (label), 10, 10);
12950       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
12951                           label, TRUE, TRUE, 0);
12952       gtk_widget_show (label);
12953
12954       button = gtk_button_new_with_label ("close");
12955       g_signal_connect_swapped (button, "clicked",
12956                                 G_CALLBACK (gtk_widget_destroy),
12957                                 window);
12958       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
12959       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
12960                           button, TRUE, TRUE, 0);
12961       gtk_widget_grab_default (button);
12962       gtk_widget_show (button);
12963
12964       button = gtk_button_new_with_label ("start");
12965       g_signal_connect (button, "clicked",
12966                         G_CALLBACK(start_timeout_test),
12967                         label);
12968       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
12969       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
12970                           button, TRUE, TRUE, 0);
12971       gtk_widget_show (button);
12972
12973       button = gtk_button_new_with_label ("stop");
12974       g_signal_connect (button, "clicked",
12975                         G_CALLBACK (stop_timeout_test),
12976                         NULL);
12977       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
12978       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
12979                           button, TRUE, TRUE, 0);
12980       gtk_widget_show (button);
12981     }
12982
12983   if (!GTK_WIDGET_VISIBLE (window))
12984     gtk_widget_show (window);
12985   else
12986     gtk_widget_destroy (window);
12987 }
12988
12989 /*
12990  * Idle Test
12991  */
12992
12993 static int idle_id = 0;
12994
12995 static gint
12996 idle_test (GtkWidget *label)
12997 {
12998   static int count = 0;
12999   static char buffer[32];
13000
13001   sprintf (buffer, "count: %d", ++count);
13002   gtk_label_set_text (GTK_LABEL (label), buffer);
13003
13004   return TRUE;
13005 }
13006
13007 static void
13008 start_idle_test (GtkWidget *widget,
13009                  GtkWidget *label)
13010 {
13011   if (!idle_id)
13012     {
13013       idle_id = gtk_idle_add ((GtkFunction) idle_test, label);
13014     }
13015 }
13016
13017 static void
13018 stop_idle_test (GtkWidget *widget,
13019                 gpointer   data)
13020 {
13021   if (idle_id)
13022     {
13023       gtk_idle_remove (idle_id);
13024       idle_id = 0;
13025     }
13026 }
13027
13028 static void
13029 destroy_idle_test (GtkWidget  *widget,
13030                    GtkWidget **window)
13031 {
13032   stop_idle_test (NULL, NULL);
13033
13034   *window = NULL;
13035 }
13036
13037 static void
13038 toggle_idle_container (GObject *button,
13039                        GtkContainer *container)
13040 {
13041   gtk_container_set_resize_mode (container, GPOINTER_TO_INT (g_object_get_data (button, "user_data")));
13042 }
13043
13044 static void
13045 create_idle_test (GtkWidget *widget)
13046 {
13047   static GtkWidget *window = NULL;
13048   GtkWidget *button;
13049   GtkWidget *label;
13050   GtkWidget *container;
13051
13052   if (!window)
13053     {
13054       GtkWidget *button2;
13055       GtkWidget *frame;
13056       GtkWidget *box;
13057
13058       window = gtk_dialog_new ();
13059
13060       gtk_window_set_screen (GTK_WINDOW (window),
13061                              gtk_widget_get_screen (widget));
13062
13063       g_signal_connect (window, "destroy",
13064                         G_CALLBACK (destroy_idle_test),
13065                         &window);
13066
13067       gtk_window_set_title (GTK_WINDOW (window), "Idle Test");
13068       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
13069
13070       label = gtk_label_new ("count: 0");
13071       gtk_misc_set_padding (GTK_MISC (label), 10, 10);
13072       gtk_widget_show (label);
13073       
13074       container =
13075         g_object_new (GTK_TYPE_HBOX,
13076                         "visible", TRUE,
13077                         /* "GtkContainer::child", g_object_new (GTK_TYPE_HBOX,
13078                          * "GtkWidget::visible", TRUE,
13079                          */
13080                          "child", label,
13081                         /* NULL), */
13082                         NULL);
13083       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
13084                           container, TRUE, TRUE, 0);
13085
13086       frame =
13087         g_object_new (GTK_TYPE_FRAME,
13088                         "border_width", 5,
13089                         "label", "Label Container",
13090                         "visible", TRUE,
13091                         "parent", GTK_DIALOG (window)->vbox,
13092                         NULL);
13093       box =
13094         g_object_new (GTK_TYPE_VBOX,
13095                         "visible", TRUE,
13096                         "parent", frame,
13097                         NULL);
13098       button =
13099         g_object_connect (g_object_new (GTK_TYPE_RADIO_BUTTON,
13100                                           "label", "Resize-Parent",
13101                                           "user_data", (void*)GTK_RESIZE_PARENT,
13102                                           "visible", TRUE,
13103                                           "parent", box,
13104                                           NULL),
13105                           "signal::clicked", toggle_idle_container, container,
13106                           NULL);
13107       button = g_object_new (GTK_TYPE_RADIO_BUTTON,
13108                                "label", "Resize-Queue",
13109                                "user_data", (void*)GTK_RESIZE_QUEUE,
13110                                "group", button,
13111                                "visible", TRUE,
13112                                "parent", box,
13113                                NULL);
13114       g_object_connect (button,
13115                         "signal::clicked", toggle_idle_container, container,
13116                         NULL);
13117       button2 = g_object_new (GTK_TYPE_RADIO_BUTTON,
13118                                 "label", "Resize-Immediate",
13119                                 "user_data", (void*)GTK_RESIZE_IMMEDIATE,
13120                                 NULL);
13121       g_object_connect (button2,
13122                         "signal::clicked", toggle_idle_container, container,
13123                         NULL);
13124       g_object_set (button2,
13125                     "group", button,
13126                     "visible", TRUE,
13127                     "parent", box,
13128                     NULL);
13129
13130       button = gtk_button_new_with_label ("close");
13131       g_signal_connect_swapped (button, "clicked",
13132                                 G_CALLBACK (gtk_widget_destroy),
13133                                 window);
13134       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
13135       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
13136                           button, TRUE, TRUE, 0);
13137       gtk_widget_grab_default (button);
13138       gtk_widget_show (button);
13139
13140       button = gtk_button_new_with_label ("start");
13141       g_signal_connect (button, "clicked",
13142                         G_CALLBACK (start_idle_test),
13143                         label);
13144       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
13145       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
13146                           button, TRUE, TRUE, 0);
13147       gtk_widget_show (button);
13148
13149       button = gtk_button_new_with_label ("stop");
13150       g_signal_connect (button, "clicked",
13151                         G_CALLBACK (stop_idle_test),
13152                         NULL);
13153       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
13154       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
13155                           button, TRUE, TRUE, 0);
13156       gtk_widget_show (button);
13157     }
13158
13159   if (!GTK_WIDGET_VISIBLE (window))
13160     gtk_widget_show (window);
13161   else
13162     gtk_widget_destroy (window);
13163 }
13164
13165 /*
13166  * rc file test
13167  */
13168
13169 void
13170 reload_all_rc_files (void)
13171 {
13172   static GdkAtom atom_rcfiles = GDK_NONE;
13173
13174   GdkEvent *send_event = gdk_event_new (GDK_CLIENT_EVENT);
13175   int i;
13176   
13177   if (!atom_rcfiles)
13178     atom_rcfiles = gdk_atom_intern("_GTK_READ_RCFILES", FALSE);
13179
13180   for(i = 0; i < 5; i++)
13181     send_event->client.data.l[i] = 0;
13182   send_event->client.data_format = 32;
13183   send_event->client.message_type = atom_rcfiles;
13184   gdk_event_send_clientmessage_toall (send_event);
13185
13186   gdk_event_free (send_event);
13187 }
13188
13189 void
13190 create_rc_file (GtkWidget *widget)
13191 {
13192   static GtkWidget *window = NULL;
13193   GtkWidget *button;
13194   GtkWidget *frame;
13195   GtkWidget *vbox;
13196   GtkWidget *label;
13197
13198   if (!window)
13199     {
13200       window = gtk_dialog_new ();
13201
13202       gtk_window_set_screen (GTK_WINDOW (window),
13203                              gtk_widget_get_screen (widget));
13204
13205       g_signal_connect (window, "destroy",
13206                         G_CALLBACK (gtk_widget_destroyed),
13207                         &window);
13208
13209       frame = gtk_aspect_frame_new ("Testing RC file prioritization", 0.5, 0.5, 0.0, TRUE);
13210       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), frame, FALSE, FALSE, 0);
13211
13212       vbox = gtk_vbox_new (FALSE, 0);
13213       gtk_container_add (GTK_CONTAINER (frame), vbox);
13214       
13215       label = gtk_label_new ("This label should be red");
13216       gtk_widget_set_name (label, "testgtk-red-label");
13217       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
13218
13219       label = gtk_label_new ("This label should be green");
13220       gtk_widget_set_name (label, "testgtk-green-label");
13221       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
13222
13223       label = gtk_label_new ("This label should be blue");
13224       gtk_widget_set_name (label, "testgtk-blue-label");
13225       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
13226
13227       gtk_window_set_title (GTK_WINDOW (window), "Reload Rc file");
13228       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
13229
13230       button = gtk_button_new_with_label ("Reload");
13231       g_signal_connect (button, "clicked",
13232                         G_CALLBACK (gtk_rc_reparse_all), NULL);
13233       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
13234       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
13235                           button, TRUE, TRUE, 0);
13236       gtk_widget_grab_default (button);
13237
13238       button = gtk_button_new_with_label ("Reload All");
13239       g_signal_connect (button, "clicked",
13240                         G_CALLBACK (reload_all_rc_files), NULL);
13241       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
13242       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
13243                           button, TRUE, TRUE, 0);
13244
13245       button = gtk_button_new_with_label ("Close");
13246       g_signal_connect_swapped (button, "clicked",
13247                                 G_CALLBACK (gtk_widget_destroy),
13248                                 window);
13249       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
13250       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
13251                           button, TRUE, TRUE, 0);
13252     }
13253
13254   if (!GTK_WIDGET_VISIBLE (window))
13255     gtk_widget_show_all (window);
13256   else
13257     gtk_widget_destroy (window);
13258 }
13259
13260 /*
13261  * Test of recursive mainloop
13262  */
13263
13264 void
13265 mainloop_destroyed (GtkWidget *w, GtkWidget **window)
13266 {
13267   *window = NULL;
13268   gtk_main_quit ();
13269 }
13270
13271 void
13272 create_mainloop (GtkWidget *widget)
13273 {
13274   static GtkWidget *window = NULL;
13275   GtkWidget *label;
13276   GtkWidget *button;
13277
13278   if (!window)
13279     {
13280       window = gtk_dialog_new ();
13281
13282       gtk_window_set_screen (GTK_WINDOW (window),
13283                              gtk_widget_get_screen (widget));
13284
13285       gtk_window_set_title (GTK_WINDOW (window), "Test Main Loop");
13286
13287       g_signal_connect (window, "destroy",
13288                         G_CALLBACK (mainloop_destroyed),
13289                         &window);
13290
13291       label = gtk_label_new ("In recursive main loop...");
13292       gtk_misc_set_padding (GTK_MISC(label), 20, 20);
13293
13294       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), label,
13295                           TRUE, TRUE, 0);
13296       gtk_widget_show (label);
13297
13298       button = gtk_button_new_with_label ("Leave");
13299       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), button, 
13300                           FALSE, TRUE, 0);
13301
13302       g_signal_connect_swapped (button, "clicked",
13303                                 G_CALLBACK (gtk_widget_destroy),
13304                                 window);
13305
13306       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
13307       gtk_widget_grab_default (button);
13308
13309       gtk_widget_show (button);
13310     }
13311
13312   if (!GTK_WIDGET_VISIBLE (window))
13313     {
13314       gtk_widget_show (window);
13315
13316       g_print ("create_mainloop: start\n");
13317       gtk_main ();
13318       g_print ("create_mainloop: done\n");
13319     }
13320   else
13321     gtk_widget_destroy (window);
13322 }
13323
13324 gboolean
13325 layout_expose_handler (GtkWidget *widget, GdkEventExpose *event)
13326 {
13327   GtkLayout *layout;
13328
13329   gint i,j;
13330   gint imin, imax, jmin, jmax;
13331
13332   layout = GTK_LAYOUT (widget);
13333
13334   if (event->window != layout->bin_window)
13335     return FALSE;
13336   
13337   imin = (event->area.x) / 10;
13338   imax = (event->area.x + event->area.width + 9) / 10;
13339
13340   jmin = (event->area.y) / 10;
13341   jmax = (event->area.y + event->area.height + 9) / 10;
13342
13343   for (i=imin; i<imax; i++)
13344     for (j=jmin; j<jmax; j++)
13345       if ((i+j) % 2)
13346         gdk_draw_rectangle (layout->bin_window,
13347                             widget->style->black_gc,
13348                             TRUE,
13349                             10*i, 10*j, 
13350                             1+i%10, 1+j%10);
13351   
13352   return FALSE;
13353 }
13354
13355 void create_layout (GtkWidget *widget)
13356 {
13357   static GtkWidget *window = NULL;
13358   GtkWidget *layout;
13359   GtkWidget *scrolledwindow;
13360   GtkWidget *button;
13361
13362   if (!window)
13363     {
13364       gchar buf[16];
13365
13366       gint i, j;
13367       
13368       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
13369       gtk_window_set_screen (GTK_WINDOW (window),
13370                              gtk_widget_get_screen (widget));
13371
13372       g_signal_connect (window, "destroy",
13373                         G_CALLBACK (gtk_widget_destroyed),
13374                         &window);
13375
13376       gtk_window_set_title (GTK_WINDOW (window), "Layout");
13377       gtk_widget_set_size_request (window, 200, 200);
13378
13379       scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
13380       gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolledwindow),
13381                                            GTK_SHADOW_IN);
13382       gtk_scrolled_window_set_placement (GTK_SCROLLED_WINDOW (scrolledwindow),
13383                                          GTK_CORNER_TOP_RIGHT);
13384
13385       gtk_container_add (GTK_CONTAINER (window), scrolledwindow);
13386       
13387       layout = gtk_layout_new (NULL, NULL);
13388       gtk_container_add (GTK_CONTAINER (scrolledwindow), layout);
13389
13390       /* We set step sizes here since GtkLayout does not set
13391        * them itself.
13392        */
13393       GTK_LAYOUT (layout)->hadjustment->step_increment = 10.0;
13394       GTK_LAYOUT (layout)->vadjustment->step_increment = 10.0;
13395       
13396       gtk_widget_set_events (layout, GDK_EXPOSURE_MASK);
13397       g_signal_connect (layout, "expose_event",
13398                         G_CALLBACK (layout_expose_handler), NULL);
13399       
13400       gtk_layout_set_size (GTK_LAYOUT (layout), 1600, 128000);
13401       
13402       for (i=0 ; i < 16 ; i++)
13403         for (j=0 ; j < 16 ; j++)
13404           {
13405             sprintf(buf, "Button %d, %d", i, j);
13406             if ((i + j) % 2)
13407               button = gtk_button_new_with_label (buf);
13408             else
13409               button = gtk_label_new (buf);
13410
13411             gtk_layout_put (GTK_LAYOUT (layout), button,
13412                             j*100, i*100);
13413           }
13414
13415       for (i=16; i < 1280; i++)
13416         {
13417           sprintf(buf, "Button %d, %d", i, 0);
13418           if (i % 2)
13419             button = gtk_button_new_with_label (buf);
13420           else
13421             button = gtk_label_new (buf);
13422
13423           gtk_layout_put (GTK_LAYOUT (layout), button,
13424                           0, i*100);
13425         }
13426     }
13427
13428   if (!GTK_WIDGET_VISIBLE (window))
13429     gtk_widget_show_all (window);
13430   else
13431     gtk_widget_destroy (window);
13432 }
13433
13434 void
13435 create_styles (GtkWidget *widget)
13436 {
13437   static GtkWidget *window = NULL;
13438   GtkWidget *label;
13439   GtkWidget *button;
13440   GtkWidget *entry;
13441   GtkWidget *vbox;
13442   static GdkColor red =    { 0, 0xffff, 0,      0      };
13443   static GdkColor green =  { 0, 0,      0xffff, 0      };
13444   static GdkColor blue =   { 0, 0,      0,      0xffff };
13445   static GdkColor yellow = { 0, 0xffff, 0xffff, 0      };
13446   static GdkColor cyan =   { 0, 0     , 0xffff, 0xffff };
13447   PangoFontDescription *font_desc;
13448
13449   GtkRcStyle *rc_style;
13450
13451   if (!window)
13452     {
13453       window = gtk_dialog_new ();
13454       gtk_window_set_screen (GTK_WINDOW (window),
13455                              gtk_widget_get_screen (widget));
13456      
13457       g_signal_connect (window, "destroy",
13458                         G_CALLBACK (gtk_widget_destroyed),
13459                         &window);
13460
13461       
13462       button = gtk_button_new_with_label ("Close");
13463       g_signal_connect_swapped (button, "clicked",
13464                                 G_CALLBACK (gtk_widget_destroy),
13465                                 window);
13466       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
13467       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
13468                           button, TRUE, TRUE, 0);
13469       gtk_widget_show (button);
13470
13471       vbox = gtk_vbox_new (FALSE, 5);
13472       gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
13473       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), vbox, FALSE, FALSE, 0);
13474       
13475       label = gtk_label_new ("Font:");
13476       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
13477       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
13478
13479       font_desc = pango_font_description_from_string ("Helvetica,Sans Oblique 18");
13480
13481       button = gtk_button_new_with_label ("Some Text");
13482       gtk_widget_modify_font (GTK_BIN (button)->child, font_desc);
13483       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
13484
13485       label = gtk_label_new ("Foreground:");
13486       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
13487       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
13488
13489       button = gtk_button_new_with_label ("Some Text");
13490       gtk_widget_modify_fg (GTK_BIN (button)->child, GTK_STATE_NORMAL, &red);
13491       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
13492
13493       label = gtk_label_new ("Background:");
13494       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
13495       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
13496
13497       button = gtk_button_new_with_label ("Some Text");
13498       gtk_widget_modify_bg (button, GTK_STATE_NORMAL, &green);
13499       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
13500
13501       label = gtk_label_new ("Text:");
13502       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
13503       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
13504
13505       entry = gtk_entry_new ();
13506       gtk_entry_set_text (GTK_ENTRY (entry), "Some Text");
13507       gtk_widget_modify_text (entry, GTK_STATE_NORMAL, &blue);
13508       gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
13509
13510       label = gtk_label_new ("Base:");
13511       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
13512       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
13513
13514       entry = gtk_entry_new ();
13515       gtk_entry_set_text (GTK_ENTRY (entry), "Some Text");
13516       gtk_widget_modify_base (entry, GTK_STATE_NORMAL, &yellow);
13517       gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
13518
13519       label = gtk_label_new ("Cursor:");
13520       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
13521       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
13522
13523       entry = gtk_entry_new ();
13524       gtk_entry_set_text (GTK_ENTRY (entry), "Some Text");
13525       gtk_widget_modify_cursor (entry, &red, &red);
13526       gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
13527
13528       label = gtk_label_new ("Multiple:");
13529       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
13530       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
13531
13532       button = gtk_button_new_with_label ("Some Text");
13533
13534       rc_style = gtk_rc_style_new ();
13535
13536       rc_style->font_desc = pango_font_description_copy (font_desc);
13537       rc_style->color_flags[GTK_STATE_NORMAL] = GTK_RC_FG | GTK_RC_BG;
13538       rc_style->color_flags[GTK_STATE_PRELIGHT] = GTK_RC_FG | GTK_RC_BG;
13539       rc_style->color_flags[GTK_STATE_ACTIVE] = GTK_RC_FG | GTK_RC_BG;
13540       rc_style->fg[GTK_STATE_NORMAL] = yellow;
13541       rc_style->bg[GTK_STATE_NORMAL] = blue;
13542       rc_style->fg[GTK_STATE_PRELIGHT] = blue;
13543       rc_style->bg[GTK_STATE_PRELIGHT] = yellow;
13544       rc_style->fg[GTK_STATE_ACTIVE] = red;
13545       rc_style->bg[GTK_STATE_ACTIVE] = cyan;
13546       rc_style->xthickness = 5;
13547       rc_style->ythickness = 5;
13548
13549       gtk_widget_modify_style (button, rc_style);
13550       gtk_widget_modify_style (GTK_BIN (button)->child, rc_style);
13551
13552       g_object_unref (rc_style);
13553       
13554       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
13555     }
13556   
13557   if (!GTK_WIDGET_VISIBLE (window))
13558     gtk_widget_show_all (window);
13559   else
13560     gtk_widget_destroy (window);
13561 }
13562
13563 /*
13564  * Main Window and Exit
13565  */
13566
13567 void
13568 do_exit (GtkWidget *widget, GtkWidget *window)
13569 {
13570   gtk_widget_destroy (window);
13571   gtk_main_quit ();
13572 }
13573
13574 struct {
13575   char *label;
13576   void (*func) (GtkWidget *widget);
13577   gboolean do_not_benchmark;
13578 } buttons[] =
13579 {
13580   { "alpha window", create_alpha_window },
13581 #ifdef G_OS_WIN32
13582   /* dog slow on NT, no working at all on 9x */
13583   { "big windows", create_big_windows, TRUE },
13584 #else
13585   { "big windows", create_big_windows },
13586 #endif
13587   { "button box", create_button_box },
13588   { "buttons", create_buttons },
13589   { "check buttons", create_check_buttons },
13590   { "clist", create_clist},
13591   { "color selection", create_color_selection },
13592   { "composited window", create_composited_window },
13593   { "ctree", create_ctree },
13594   { "cursors", create_cursors },
13595   { "dialog", create_dialog, TRUE },
13596   { "display & screen", create_display_screen, TRUE },
13597   { "entry", create_entry },
13598   { "event box", create_event_box },
13599   { "event watcher", create_event_watcher },
13600   { "expander", create_expander },
13601   { "file selection", create_file_selection },
13602   { "flipping", create_flipping },
13603   { "focus", create_focus },
13604   { "font selection", create_font_selection },
13605   { "gamma curve", create_gamma_curve, TRUE },
13606   { "gridded geometry", create_gridded_geometry },
13607   { "handle box", create_handle_box },
13608   { "image from drawable", create_get_image },
13609   { "image", create_image },
13610   { "item factory", create_item_factory },
13611   { "key lookup", create_key_lookup },
13612   { "labels", create_labels },
13613   { "layout", create_layout },
13614   { "list", create_list },
13615   { "menus", create_menus },
13616   { "message dialog", create_message_dialog },
13617   { "modal window", create_modal_window, TRUE },
13618   { "notebook", create_notebook },
13619   { "panes", create_panes },
13620   { "paned keyboard", create_paned_keyboard_navigation },
13621   { "pixmap", create_pixmap },
13622   { "preview color", create_color_preview, TRUE },
13623   { "preview gray", create_gray_preview, TRUE },
13624   { "progress bar", create_progress_bar },
13625   { "properties", create_properties },
13626   { "radio buttons", create_radio_buttons },
13627   { "range controls", create_range_controls },
13628   { "rc file", create_rc_file },
13629   { "reparent", create_reparent },
13630   { "resize grips", create_resize_grips },
13631   { "rotated label", create_rotated_label },
13632   { "rotated text", create_rotated_text },
13633   { "rulers", create_rulers },
13634   { "saved position", create_saved_position },
13635   { "scrolled windows", create_scrolled_windows },
13636   { "shapes", create_shapes },
13637   { "size groups", create_size_groups },
13638   { "snapshot", create_snapshot },
13639   { "spinbutton", create_spins },
13640   { "statusbar", create_statusbar },
13641   { "styles", create_styles },
13642   { "test idle", create_idle_test },
13643   { "test mainloop", create_mainloop, TRUE },
13644   { "test scrolling", create_scroll_test },
13645   { "test selection", create_selection_test },
13646   { "test timeout", create_timeout_test },
13647   { "text", create_text },
13648   { "toggle buttons", create_toggle_buttons },
13649   { "toolbar", create_toolbar },
13650   { "tooltips", create_tooltips },
13651   { "tree", create_tree_mode_window},
13652   { "WM hints", create_wmhints },
13653   { "window sizing", create_window_sizing },
13654   { "window states", create_window_states }
13655 };
13656 int nbuttons = sizeof (buttons) / sizeof (buttons[0]);
13657
13658 void
13659 create_main_window (void)
13660 {
13661   GtkWidget *window;
13662   GtkWidget *box1;
13663   GtkWidget *box2;
13664   GtkWidget *scrolled_window;
13665   GtkWidget *button;
13666   GtkWidget *label;
13667   gchar buffer[64];
13668   GtkWidget *separator;
13669   GdkGeometry geometry;
13670   int i;
13671
13672   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
13673   gtk_widget_set_name (window, "main window");
13674   gtk_widget_set_uposition (window, 50, 20);
13675   gtk_window_set_default_size (GTK_WINDOW (window), -1, 400);
13676
13677   geometry.min_width = -1;
13678   geometry.min_height = -1;
13679   geometry.max_width = -1;
13680   geometry.max_height = G_MAXSHORT;
13681   gtk_window_set_geometry_hints (GTK_WINDOW (window), NULL,
13682                                  &geometry,
13683                                  GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE);
13684
13685   g_signal_connect (window, "destroy",
13686                     G_CALLBACK (gtk_main_quit),
13687                     NULL);
13688   g_signal_connect (window, "delete-event",
13689                     G_CALLBACK (gtk_false),
13690                     NULL);
13691
13692   box1 = gtk_vbox_new (FALSE, 0);
13693   gtk_container_add (GTK_CONTAINER (window), box1);
13694
13695   if (gtk_micro_version > 0)
13696     sprintf (buffer,
13697              "Gtk+ v%d.%d.%d",
13698              gtk_major_version,
13699              gtk_minor_version,
13700              gtk_micro_version);
13701   else
13702     sprintf (buffer,
13703              "Gtk+ v%d.%d",
13704              gtk_major_version,
13705              gtk_minor_version);
13706
13707   label = gtk_label_new (buffer);
13708   gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);
13709   gtk_widget_set_name (label, "testgtk-version-label");
13710
13711   scrolled_window = gtk_scrolled_window_new (NULL, NULL);
13712   gtk_container_set_border_width (GTK_CONTAINER (scrolled_window), 10);
13713   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
13714                                   GTK_POLICY_NEVER, 
13715                                   GTK_POLICY_AUTOMATIC);
13716   gtk_box_pack_start (GTK_BOX (box1), scrolled_window, TRUE, TRUE, 0);
13717
13718   box2 = gtk_vbox_new (FALSE, 0);
13719   gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
13720   gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_window), box2);
13721   gtk_container_set_focus_vadjustment (GTK_CONTAINER (box2),
13722                                        gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (scrolled_window)));
13723   gtk_widget_show (box2);
13724
13725   for (i = 0; i < nbuttons; i++)
13726     {
13727       button = gtk_button_new_with_label (buttons[i].label);
13728       if (buttons[i].func)
13729         g_signal_connect (button, 
13730                           "clicked", 
13731                           G_CALLBACK(buttons[i].func),
13732                           NULL);
13733       else
13734         gtk_widget_set_sensitive (button, FALSE);
13735       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
13736     }
13737
13738   separator = gtk_hseparator_new ();
13739   gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
13740
13741   box2 = gtk_vbox_new (FALSE, 10);
13742   gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
13743   gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
13744
13745   button = gtk_button_new_with_mnemonic ("_Close");
13746   g_signal_connect (button, "clicked",
13747                     G_CALLBACK (do_exit),
13748                     window);
13749   gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
13750   GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
13751   gtk_widget_grab_default (button);
13752
13753   gtk_widget_show_all (window);
13754 }
13755
13756 static void
13757 test_init (void)
13758 {
13759   if (g_file_test ("../gdk-pixbuf/libpixbufloader-pnm.la",
13760                    G_FILE_TEST_EXISTS))
13761     {
13762       g_setenv ("GDK_PIXBUF_MODULE_FILE", "../gdk-pixbuf/gdk-pixbuf.loaders", TRUE);
13763       g_setenv ("GTK_IM_MODULE_FILE", "../modules/input/gtk.immodules", TRUE);
13764     }
13765 }
13766
13767 static char *
13768 pad (const char *str, int to)
13769 {
13770   static char buf[256];
13771   int len = strlen (str);
13772   int i;
13773
13774   for (i = 0; i < to; i++)
13775     buf[i] = ' ';
13776
13777   buf[to] = '\0';
13778
13779   memcpy (buf, str, len);
13780
13781   return buf;
13782 }
13783
13784 static void
13785 bench_iteration (GtkWidget *widget, void (* fn) (GtkWidget *widget))
13786 {
13787   fn (widget); /* on */
13788   while (g_main_context_iteration (NULL, FALSE));
13789   fn (widget); /* off */
13790   while (g_main_context_iteration (NULL, FALSE));
13791 }
13792
13793 void
13794 do_real_bench (GtkWidget *widget, void (* fn) (GtkWidget *widget), char *name, int num)
13795 {
13796   GTimeVal tv0, tv1;
13797   double dt_first;
13798   double dt;
13799   int n;
13800   static gboolean printed_headers = FALSE;
13801
13802   if (!printed_headers) {
13803     g_print ("Test                 Iters      First      Other\n");
13804     g_print ("-------------------- ----- ---------- ----------\n");
13805     printed_headers = TRUE;
13806   }
13807
13808   g_get_current_time (&tv0);
13809   bench_iteration (widget, fn); 
13810   g_get_current_time (&tv1);
13811
13812   dt_first = ((double)tv1.tv_sec - tv0.tv_sec) * 1000.0
13813         + (tv1.tv_usec - tv0.tv_usec) / 1000.0;
13814
13815   g_get_current_time (&tv0);
13816   for (n = 0; n < num - 1; n++)
13817     bench_iteration (widget, fn); 
13818   g_get_current_time (&tv1);
13819   dt = ((double)tv1.tv_sec - tv0.tv_sec) * 1000.0
13820         + (tv1.tv_usec - tv0.tv_usec) / 1000.0;
13821
13822   g_print ("%s %5d ", pad (name, 20), num);
13823   if (num > 1)
13824     g_print ("%10.1f %10.1f\n", dt_first, dt/(num-1));
13825   else
13826     g_print ("%10.1f\n", dt_first);
13827 }
13828
13829 void
13830 do_bench (char* what, int num)
13831 {
13832   int i;
13833   GtkWidget *widget;
13834   void (* fn) (GtkWidget *widget);
13835   fn = NULL;
13836   widget = gtk_window_new (GTK_WINDOW_TOPLEVEL);
13837
13838   if (g_ascii_strcasecmp (what, "ALL") == 0)
13839     {
13840       for (i = 0; i < nbuttons; i++)
13841         {
13842           if (!buttons[i].do_not_benchmark)
13843             do_real_bench (widget, buttons[i].func, buttons[i].label, num);
13844         }
13845
13846       return;
13847     }
13848   else
13849     {
13850       for (i = 0; i < nbuttons; i++)
13851         {
13852           if (strcmp (buttons[i].label, what) == 0)
13853             {
13854               fn = buttons[i].func;
13855               break;
13856             }
13857         }
13858       
13859       if (!fn)
13860         g_print ("Can't bench: \"%s\" not found.\n", what);
13861       else
13862         do_real_bench (widget, fn, buttons[i].label, num);
13863     }
13864 }
13865
13866 void 
13867 usage (void)
13868 {
13869   fprintf (stderr, "Usage: testgtk [--bench ALL|<bench>[:<count>]]\n");
13870   exit (1);
13871 }
13872
13873 int
13874 main (int argc, char *argv[])
13875 {
13876   GtkBindingSet *binding_set;
13877   int i;
13878   gboolean done_benchmarks = FALSE;
13879
13880   srand (time (NULL));
13881
13882   test_init ();
13883
13884   /* Check to see if we are being run from the correct
13885    * directory.
13886    */
13887   if (file_exists ("testgtkrc"))
13888     gtk_rc_add_default_file ("testgtkrc");
13889
13890   g_set_application_name ("GTK+ Test Program");
13891
13892   gtk_init (&argc, &argv);
13893
13894   gtk_accelerator_set_default_mod_mask (GDK_SHIFT_MASK |
13895                                         GDK_CONTROL_MASK |
13896                                         GDK_MOD1_MASK | 
13897                                         GDK_META_MASK |
13898                                         GDK_SUPER_MASK |
13899                                         GDK_HYPER_MASK |
13900                                         GDK_MOD4_MASK);
13901   /*  benchmarking
13902    */
13903   for (i = 1; i < argc; i++)
13904     {
13905       if (strncmp (argv[i], "--bench", strlen("--bench")) == 0)
13906         {
13907           int num = 1;
13908           char *nextarg;
13909           char *what;
13910           char *count;
13911           
13912           nextarg = strchr (argv[i], '=');
13913           if (nextarg)
13914             nextarg++;
13915           else
13916             {
13917               i++;
13918               if (i == argc)
13919                 usage ();
13920               nextarg = argv[i];
13921             }
13922
13923           count = strchr (nextarg, ':');
13924           if (count)
13925             {
13926               what = g_strndup (nextarg, count - nextarg);
13927               count++;
13928               num = atoi (count);
13929               if (num <= 0)
13930                 usage ();
13931             }
13932           else
13933             what = g_strdup (nextarg);
13934
13935           do_bench (what, num ? num : 1);
13936           done_benchmarks = TRUE;
13937         }
13938       else
13939         usage ();
13940     }
13941   if (done_benchmarks)
13942     return 0;
13943
13944   /* bindings test
13945    */
13946   binding_set = gtk_binding_set_by_class (g_type_class_ref (GTK_TYPE_WIDGET));
13947   gtk_binding_entry_add_signal (binding_set,
13948                                 '9', GDK_CONTROL_MASK | GDK_RELEASE_MASK,
13949                                 "debug_msg",
13950                                 1,
13951                                 G_TYPE_STRING, "GtkWidgetClass <ctrl><release>9 test");
13952   
13953   /* We use gtk_rc_parse_string() here so we can make sure it works across theme
13954    * changes
13955    */
13956
13957   gtk_rc_parse_string ("style \"testgtk-version-label\" { "
13958                        "   fg[NORMAL] = \"#ff0000\"\n"
13959                        "   font = \"Sans 18\"\n"
13960                        "}\n"
13961                        "widget \"*.testgtk-version-label\" style \"testgtk-version-label\"");
13962   
13963   create_main_window ();
13964
13965   gtk_main ();
13966
13967   if (1)
13968     {
13969       while (g_main_context_pending (NULL))
13970         g_main_context_iteration (NULL, FALSE);
13971 #if 0
13972       sleep (1);
13973       while (g_main_context_pending (NULL))
13974         g_main_context_iteration (NULL, FALSE);
13975 #endif
13976     }
13977   return 0;
13978 }