]> Pileus Git - ~andy/gtk/blob - tests/testgtk.c
Remove deprecated code: GtkCheckMenuItem
[~andy/gtk] / tests / testgtk.c
1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /*
21  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
22  * file for a list of people on the GTK+ Team.  See the ChangeLog
23  * files for a list of changes.  These files are distributed with
24  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
25  */
26
27 #undef GTK_DISABLE_DEPRECATED
28
29 #include "config.h"
30
31 #undef  G_LOG_DOMAIN
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <sys/stat.h>
37 #include <math.h>
38 #include <time.h>
39 #ifdef HAVE_UNISTD_H
40 #include <unistd.h>
41 #endif
42
43 #define GTK_ENABLE_BROKEN
44 #include "gtk/gtk.h"
45 #include "gdk/gdk.h"
46 #include "gdk/gdkkeysyms.h"
47
48 #ifdef G_OS_WIN32
49 #define sleep(n) _sleep(n)
50 #endif
51
52 #include "prop-editor.h"
53
54 #include "circles.xbm"
55 #include "test.xpm"
56
57 gboolean
58 file_exists (const char *filename)
59 {
60   struct stat statbuf;
61
62   return stat (filename, &statbuf) == 0;
63 }
64
65 GtkWidget *
66 shape_create_icon (GdkScreen *screen,
67                    char      *xpm_file,
68                    gint       x,
69                    gint       y,
70                    gint       px,
71                    gint       py,
72                    gint       window_type);
73
74 static GtkWidget *
75 build_option_menu (gchar           *items[],
76                    gint             num_items,
77                    gint             history,
78                    void           (*func) (GtkWidget *widget, gpointer data),
79                    gpointer         data);
80
81 /* macro, structure and variables used by tree window demos */
82 #define DEFAULT_NUMBER_OF_ITEM  3
83 #define DEFAULT_RECURSION_LEVEL 3
84
85 struct {
86   GSList* selection_mode_group;
87   GtkWidget* single_button;
88   GtkWidget* browse_button;
89   GtkWidget* multiple_button;
90   GtkWidget* draw_line_button;
91   GtkWidget* view_line_button;
92   GtkWidget* no_root_item_button;
93   GtkWidget* nb_item_spinner;
94   GtkWidget* recursion_spinner;
95 } sTreeSampleSelection;
96
97 typedef struct sTreeButtons {
98   guint nb_item_add;
99   GtkWidget* add_button;
100   GtkWidget* remove_button;
101   GtkWidget* subtree_button;
102 } sTreeButtons;
103 /* end of tree section */
104
105 static GtkWidget *
106 build_option_menu (gchar           *items[],
107                    gint             num_items,
108                    gint             history,
109                    void           (*func)(GtkWidget *widget, gpointer data),
110                    gpointer         data)
111 {
112   GtkWidget *omenu;
113   GtkWidget *menu;
114   GtkWidget *menu_item;
115   GSList *group;
116   gint i;
117
118   omenu = gtk_option_menu_new ();
119   g_signal_connect (omenu, "changed",
120                     G_CALLBACK (func), data);
121       
122   menu = gtk_menu_new ();
123   group = NULL;
124   
125   for (i = 0; i < num_items; i++)
126     {
127       menu_item = gtk_radio_menu_item_new_with_label (group, items[i]);
128       group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (menu_item));
129       gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
130       if (i == history)
131         gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menu_item), TRUE);
132       gtk_widget_show (menu_item);
133     }
134
135   gtk_option_menu_set_menu (GTK_OPTION_MENU (omenu), menu);
136   gtk_option_menu_set_history (GTK_OPTION_MENU (omenu), history);
137   
138   return omenu;
139 }
140
141 static void
142 destroy_tooltips (GtkWidget *widget, GtkWindow **window)
143 {
144   GtkTooltips *tt = g_object_get_data (G_OBJECT (*window), "tooltips");
145   g_object_unref (tt);
146   *window = NULL;
147 }
148
149
150 /*
151  * Windows with an alpha channel
152  */
153
154
155 static gboolean
156 on_alpha_window_expose (GtkWidget      *widget,
157                         GdkEventExpose *expose)
158 {
159   cairo_t *cr;
160   cairo_pattern_t *pattern;
161   int radius;
162
163   cr = gdk_cairo_create (widget->window);
164
165   radius = MIN (widget->allocation.width, widget->allocation.height) / 2;
166   pattern = cairo_pattern_create_radial (widget->allocation.width / 2,
167                                          widget->allocation.height / 2,
168                                          0.0,
169                                          widget->allocation.width / 2,
170                                          widget->allocation.height / 2,
171                                          radius * 1.33);
172
173   if (gdk_screen_get_rgba_colormap (gtk_widget_get_screen (widget)) &&
174       gtk_widget_is_composited (widget))
175     cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 0.0); /* transparent */
176   else
177     cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); /* opaque white */
178     
179   cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
180   cairo_paint (cr);
181   
182   cairo_pattern_add_color_stop_rgba (pattern, 0.0,
183                                      1.0, 0.75, 0.0, 1.0); /* solid orange */
184   cairo_pattern_add_color_stop_rgba (pattern, 1.0,
185                                      1.0, 0.75, 0.0, 0.0); /* transparent orange */
186
187   cairo_set_source (cr, pattern);
188   cairo_pattern_destroy (pattern);
189   
190   cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
191   cairo_paint (cr);
192
193   cairo_destroy (cr);
194
195   return FALSE;
196 }
197
198 static GtkWidget *
199 build_alpha_widgets (void)
200 {
201   GtkWidget *table;
202   GtkWidget *radio_button;
203   GtkWidget *hbox;
204   GtkWidget *label;
205   GtkWidget *entry;
206
207   table = gtk_table_new (1, 1, FALSE);
208
209   radio_button = gtk_radio_button_new_with_label (NULL, "Red");
210   gtk_table_attach (GTK_TABLE (table),
211                     radio_button,
212                     0, 1,                  0, 1,
213                     GTK_EXPAND | GTK_FILL, 0,
214                     0,                     0);
215
216   radio_button = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (radio_button), "Green");
217   gtk_table_attach (GTK_TABLE (table),
218                     radio_button,
219                     0, 1,                  1, 2,
220                     GTK_EXPAND | GTK_FILL, 0,
221                     0,                     0);
222
223   radio_button = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (radio_button), "Blue"),
224   gtk_table_attach (GTK_TABLE (table),
225                     radio_button,
226                     0, 1,                  2, 3,
227                     GTK_EXPAND | GTK_FILL, 0,
228                     0,                     0);
229
230   gtk_table_attach (GTK_TABLE (table),
231                     gtk_check_button_new_with_label ("Sedentary"),
232                     1, 2,                  0, 1,
233                     GTK_EXPAND | GTK_FILL, 0,
234                     0,                     0);
235   gtk_table_attach (GTK_TABLE (table),
236                     gtk_check_button_new_with_label ("Nocturnal"),
237                     1, 2,                  1, 2,
238                     GTK_EXPAND | GTK_FILL, 0,
239                     0,                     0);
240   gtk_table_attach (GTK_TABLE (table),
241                     gtk_check_button_new_with_label ("Compulsive"),
242                     1, 2,                  2, 3,
243                     GTK_EXPAND | GTK_FILL, 0,
244                     0,                     0);
245
246   radio_button = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (radio_button), "Green");
247   gtk_table_attach (GTK_TABLE (table),
248                     radio_button,
249                     0, 1,                  1, 2,
250                     GTK_EXPAND | GTK_FILL, 0,
251                     0,                     0);
252
253   radio_button = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (radio_button), "Blue"),
254   gtk_table_attach (GTK_TABLE (table),
255                     radio_button,
256                     0, 1,                  2, 3,
257                     GTK_EXPAND | GTK_FILL, 0,
258                     0,                     0);
259   
260   hbox = gtk_hbox_new (FALSE, 0);
261   label = gtk_label_new (NULL);
262   gtk_label_set_markup (GTK_LABEL (label), "<i>Entry: </i>");
263   gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
264   entry = gtk_entry_new ();
265   gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0);
266   gtk_table_attach (GTK_TABLE (table),
267                     hbox,
268                     0, 1,                  3, 4,
269                     GTK_EXPAND | GTK_FILL, 0,
270                     0,                     0);
271   
272   return table;
273 }
274
275 static gboolean
276 on_alpha_drawing_expose (GtkWidget      *widget,
277                          GdkEventExpose *expose)
278 {
279   int x = widget->allocation.x;
280   int y = widget->allocation.y;
281   int width = widget->allocation.width;
282   int height = widget->allocation.height;
283   GdkPixbuf *pixbuf;
284   guchar *buffer;
285   guchar *p;
286   int i, j;
287
288   buffer = g_malloc (64 * 64 * 4);
289   
290   gdk_draw_rectangle (widget->window, widget->style->black_gc, FALSE,
291                       x,         y,
292                       width - 1, height - 1);
293
294   p = buffer;
295   for (i = 0; i < 64; i++) {
296     for (j = 0; j < 64; j++) {
297       *(p++) = i * 4 + 3;
298       *(p++) = 0;
299       *(p++) = j + 4 + 3;
300       *(p++) = MIN (255, ((32 - i) * (32 - i) + (32 - j) * (32 - j)) / 8);
301     }
302   }
303   p++;
304
305   gdk_draw_rgb_32_image (widget->window, widget->style->black_gc,
306                          x + 18, y + (height - 64) /2,
307                          64, 64, GDK_RGB_DITHER_NORMAL, buffer, 64 * 4);
308
309   pixbuf = gdk_pixbuf_new_from_data (buffer, GDK_COLORSPACE_RGB, TRUE,
310                                      8, 64, 64, 4 * 64, NULL, NULL);
311
312   gdk_draw_pixbuf (widget->window, widget->style->black_gc, pixbuf,
313                    0, 0, x + width - 18 - 64, y + (height - 64) /2,
314                    64, 64, GDK_RGB_DITHER_NORMAL, 0, 0);
315
316   g_object_unref (pixbuf);
317
318   g_free (buffer);
319   
320   return FALSE;
321 }
322
323 static GtkWidget *
324 build_alpha_drawing ()
325 {
326   GtkWidget *hbox;
327
328   hbox = gtk_hbox_new (FALSE, 0);
329   gtk_widget_set_size_request (hbox, 100, 100);
330
331   g_signal_connect (hbox, "expose-event",
332                     G_CALLBACK (on_alpha_drawing_expose), NULL);
333
334   return hbox;
335 }
336
337 static void
338 on_alpha_screen_changed (GtkWidget *widget,
339                          GdkScreen *old_screen,
340                          GtkWidget *label)
341 {
342   GdkScreen *screen = gtk_widget_get_screen (widget);
343   GdkColormap *colormap = gdk_screen_get_rgba_colormap (screen);
344
345   if (!colormap)
346     {
347       colormap = gdk_screen_get_rgb_colormap (screen);
348       gtk_label_set_markup (GTK_LABEL (label), "<b>Screen doesn't support alpha</b>");
349     }
350   else
351     {
352       gtk_label_set_markup (GTK_LABEL (label), "<b>Screen supports alpha</b>");
353     }
354
355   gtk_widget_set_colormap (widget, colormap);
356 }
357
358 static void
359 on_composited_changed (GtkWidget *window,
360                       GtkLabel *label)
361 {
362   gboolean is_composited = gtk_widget_is_composited (window);
363
364   if (is_composited)
365     gtk_label_set_text (label, "Composited");
366   else
367     gtk_label_set_text (label, "Not composited");
368 }
369
370 void
371 create_alpha_window (GtkWidget *widget)
372 {
373   static GtkWidget *window;
374
375   if (!window)
376     {
377       GtkWidget *vbox;
378       GtkWidget *label;
379       
380       window = gtk_dialog_new_with_buttons ("Alpha Window",
381                                             GTK_WINDOW (gtk_widget_get_toplevel (widget)), 0,
382                                             GTK_STOCK_CLOSE, 0,
383                                             NULL);
384
385       gtk_widget_set_app_paintable (window, TRUE);
386       g_signal_connect (window, "expose-event",
387                         G_CALLBACK (on_alpha_window_expose), NULL);
388       
389       vbox = gtk_vbox_new (FALSE, 8);
390       gtk_container_set_border_width (GTK_CONTAINER (vbox), 12);
391       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), vbox,
392                           TRUE, TRUE, 0);
393
394       label = gtk_label_new (NULL);
395       gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
396       on_alpha_screen_changed (window, NULL, label);
397       g_signal_connect (window, "screen-changed",
398                         G_CALLBACK (on_alpha_screen_changed), label);
399       
400       label = gtk_label_new (NULL);
401       gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
402       on_composited_changed (window, GTK_LABEL (label));
403       g_signal_connect (window, "composited_changed", G_CALLBACK (on_composited_changed), label);
404       
405       gtk_box_pack_start (GTK_BOX (vbox), build_alpha_widgets (), TRUE, TRUE, 0);
406       gtk_box_pack_start (GTK_BOX (vbox), build_alpha_drawing (), TRUE, TRUE, 0);
407
408       g_signal_connect (window, "destroy",
409                         G_CALLBACK (gtk_widget_destroyed),
410                         &window);
411       
412       g_signal_connect (window, "response",
413                         G_CALLBACK (gtk_widget_destroy),
414                         NULL); 
415     }
416
417   if (!gtk_widget_get_visible (window))
418     gtk_widget_show_all (window);
419   else
420     gtk_widget_destroy (window);
421 }
422
423 /*
424  * Composited non-toplevel window
425  */
426
427 /* The expose event handler for the event box.
428  *
429  * This function simply draws a transparency onto a widget on the area
430  * for which it receives expose events.  This is intended to give the
431  * event box a "transparent" background.
432  *
433  * In order for this to work properly, the widget must have an RGBA
434  * colourmap.  The widget should also be set as app-paintable since it
435  * doesn't make sense for GTK to draw a background if we are drawing it
436  * (and because GTK might actually replace our transparency with its
437  * default background colour).
438  */
439 static gboolean
440 transparent_expose (GtkWidget *widget,
441                     GdkEventExpose *event)
442 {
443   cairo_t *cr;
444
445   cr = gdk_cairo_create (widget->window);
446   cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
447   gdk_cairo_region (cr, event->region);
448   cairo_fill (cr);
449   cairo_destroy (cr);
450
451   return FALSE;
452 }
453
454 /* The expose event handler for the window.
455  *
456  * This function performs the actual compositing of the event box onto
457  * the already-existing background of the window at 50% normal opacity.
458  *
459  * In this case we do not want app-paintable to be set on the widget
460  * since we want it to draw its own (red) background.  Because of this,
461  * however, we must ensure that we use g_signal_register_after so that
462  * this handler is called after the red has been drawn.  If it was
463  * called before then GTK would just blindly paint over our work.
464  */
465 static gboolean
466 window_expose_event (GtkWidget *widget,
467                      GdkEventExpose *event)
468 {
469   GdkRegion *region;
470   GtkWidget *child;
471   cairo_t *cr;
472
473   /* get our child (in this case, the event box) */ 
474   child = gtk_bin_get_child (GTK_BIN (widget));
475
476   /* create a cairo context to draw to the window */
477   cr = gdk_cairo_create (widget->window);
478
479   /* the source data is the (composited) event box */
480   gdk_cairo_set_source_pixmap (cr, child->window,
481                                child->allocation.x,
482                                child->allocation.y);
483
484   /* draw no more than our expose event intersects our child */
485   region = gdk_region_rectangle (&child->allocation);
486   gdk_region_intersect (region, event->region);
487   gdk_cairo_region (cr, region);
488   cairo_clip (cr);
489
490   /* composite, with a 50% opacity */
491   cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
492   cairo_paint_with_alpha (cr, 0.5);
493
494   /* we're done */
495   cairo_destroy (cr);
496
497   return FALSE;
498 }
499
500 void
501 create_composited_window (GtkWidget *widget)
502 {
503   static GtkWidget *window;
504
505   if (!window)
506     {
507       GtkWidget *event, *button;
508       GdkScreen *screen;
509       GdkColormap *rgba;
510       GdkColor red;
511
512       /* make the widgets */
513       button = gtk_button_new_with_label ("A Button");
514       event = gtk_event_box_new ();
515       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
516
517       g_signal_connect (window, "destroy",
518                         G_CALLBACK (gtk_widget_destroyed),
519                         &window);
520
521       /* put a red background on the window */
522       gdk_color_parse ("red", &red);
523       gtk_widget_modify_bg (window, GTK_STATE_NORMAL, &red);
524
525       /* set the colourmap for the event box.
526        * must be done before the event box is realised.
527        */
528       screen = gtk_widget_get_screen (event);
529       rgba = gdk_screen_get_rgba_colormap (screen);
530       gtk_widget_set_colormap (event, rgba);
531
532       /* set our event box to have a fully-transparent background
533        * drawn on it.  currently there is no way to simply tell gtk
534        * that "transparency" is the background colour for a widget.
535        */
536       gtk_widget_set_app_paintable (GTK_WIDGET (event), TRUE);
537       g_signal_connect (event, "expose-event",
538                         G_CALLBACK (transparent_expose), NULL);
539
540       /* put them inside one another */
541       gtk_container_set_border_width (GTK_CONTAINER (window), 10);
542       gtk_container_add (GTK_CONTAINER (window), event);
543       gtk_container_add (GTK_CONTAINER (event), button);
544
545       /* realise and show everything */
546       gtk_widget_realize (button);
547
548       /* set the event box GdkWindow to be composited.
549        * obviously must be performed after event box is realised.
550        */
551       gdk_window_set_composited (event->window, TRUE);
552
553       /* set up the compositing handler.
554        * note that we do _after so that the normal (red) background is drawn
555        * by gtk before our compositing occurs.
556        */
557       g_signal_connect_after (window, "expose-event",
558                               G_CALLBACK (window_expose_event), NULL);
559     }
560
561   if (!gtk_widget_get_visible (window))
562     gtk_widget_show_all (window);
563   else
564     gtk_widget_destroy (window);
565 }
566
567 /*
568  * Big windows and guffaw scrolling
569  */
570
571 static gboolean
572 pattern_expose (GtkWidget      *widget,
573                 GdkEventExpose *event,
574                 gpointer        data)
575 {
576   GdkColor *color;
577   GdkWindow *window = event->window;
578
579   color = g_object_get_data (G_OBJECT (window), "pattern-color");
580   if (color)
581     {
582       GdkGC *tmp_gc = gdk_gc_new (window);
583       gdk_gc_set_rgb_fg_color (tmp_gc, color);
584
585       gdk_draw_rectangle (window, tmp_gc, TRUE,
586                           event->area.x, event->area.y,
587                           event->area.width, event->area.height);
588
589       g_object_unref (tmp_gc);
590     }
591
592   return FALSE;
593 }
594
595 static void
596 pattern_set_bg (GtkWidget   *widget,
597                 GdkWindow   *child,
598                 gint         level)
599 {
600   static const GdkColor colors[] = {
601     { 0, 0x4444, 0x4444, 0xffff },
602     { 0, 0x8888, 0x8888, 0xffff },
603     { 0, 0xaaaa, 0xaaaa, 0xffff }
604   };
605     
606   g_object_set_data (G_OBJECT (child), "pattern-color", (gpointer) &colors[level]);
607   gdk_window_set_user_data (child, widget);
608 }
609
610 static void
611 create_pattern (GtkWidget   *widget,
612                 GdkWindow   *parent,
613                 gint         level,
614                 gint         width,
615                 gint         height)
616 {
617   gint h = 1;
618   gint i = 0;
619     
620   GdkWindow *child;
621
622   while (2 * h <= height)
623     {
624       gint w = 1;
625       gint j = 0;
626       
627       while (2 * w <= width)
628         {
629           if ((i + j) % 2 == 0)
630             {
631               gint x = w  - 1;
632               gint y = h - 1;
633               
634               GdkWindowAttr attributes;
635
636               attributes.window_type = GDK_WINDOW_CHILD;
637               attributes.x = x;
638               attributes.y = y;
639               attributes.width = w;
640               attributes.height = h;
641               attributes.wclass = GDK_INPUT_OUTPUT;
642               attributes.event_mask = GDK_EXPOSURE_MASK;
643               attributes.visual = gtk_widget_get_visual (widget);
644               attributes.colormap = gtk_widget_get_colormap (widget);
645               
646               child = gdk_window_new (parent, &attributes,
647                                       GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP);
648
649               pattern_set_bg (widget, child, level);
650
651               if (level < 2)
652                 create_pattern (widget, child, level + 1, w, h);
653
654               gdk_window_show (child);
655             }
656           j++;
657           w *= 2;
658         }
659       i++;
660       h *= 2;
661     }
662 }
663
664 #define PATTERN_SIZE (1 << 18)
665
666 static void
667 pattern_hadj_changed (GtkAdjustment *adj,
668                       GtkWidget     *darea)
669 {
670   gint *old_value = g_object_get_data (G_OBJECT (adj), "old-value");
671   gint new_value = adj->value;
672
673   if (gtk_widget_get_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_get_realized (darea))
688     {
689       gdk_window_scroll (darea->window, 0, *old_value - new_value);
690       *old_value = new_value;
691     }
692 }
693
694 static void
695 pattern_realize (GtkWidget *widget,
696                  gpointer   data)
697 {
698   pattern_set_bg (widget, widget->window, 0);
699   create_pattern (widget, widget->window, 1, PATTERN_SIZE, PATTERN_SIZE);
700 }
701
702 static void 
703 create_big_windows (GtkWidget *widget)
704 {
705   static GtkWidget *window = NULL;
706   GtkWidget *darea, *table, *scrollbar;
707   GtkWidget *eventbox;
708   GtkAdjustment *hadj;
709   GtkAdjustment *vadj;
710   static gint current_x;
711   static gint current_y;
712  
713   if (!window)
714     {
715       current_x = 0;
716       current_y = 0;
717       
718       window = gtk_dialog_new_with_buttons ("Big Windows",
719                                             NULL, 0,
720                                             GTK_STOCK_CLOSE,
721                                             GTK_RESPONSE_NONE,
722                                             NULL);
723  
724       gtk_window_set_screen (GTK_WINDOW (window),
725                              gtk_widget_get_screen (widget));
726
727       gtk_window_set_default_size (GTK_WINDOW (window), 200, 300);
728
729       g_signal_connect (window, "destroy",
730                         G_CALLBACK (gtk_widget_destroyed),
731                         &window);
732
733       g_signal_connect (window, "response",
734                         G_CALLBACK (gtk_widget_destroy),
735                         NULL);
736
737       table = gtk_table_new (2, 2, FALSE);
738       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox),
739                           table, TRUE, TRUE, 0);
740
741       darea = gtk_drawing_area_new ();
742
743       hadj = (GtkAdjustment *)gtk_adjustment_new (0, 0, PATTERN_SIZE, 10, 100, 100);
744       g_signal_connect (hadj, "value_changed",
745                         G_CALLBACK (pattern_hadj_changed), darea);
746       g_object_set_data (G_OBJECT (hadj), "old-value", &current_x);
747       
748       vadj = (GtkAdjustment *)gtk_adjustment_new (0, 0, PATTERN_SIZE, 10, 100, 100);
749       g_signal_connect (vadj, "value_changed",
750                         G_CALLBACK (pattern_vadj_changed), darea);
751       g_object_set_data (G_OBJECT (vadj), "old-value", &current_y);
752       
753       g_signal_connect (darea, "realize",
754                         G_CALLBACK (pattern_realize),
755                         NULL);
756       g_signal_connect (darea, "expose_event",
757                         G_CALLBACK (pattern_expose),
758                         NULL);
759
760       eventbox = gtk_event_box_new ();
761       gtk_table_attach (GTK_TABLE (table), eventbox,
762                         0, 1,                  0, 1,
763                         GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND,
764                         0,                     0);
765
766       gtk_container_add (GTK_CONTAINER (eventbox), darea);
767
768       scrollbar = gtk_hscrollbar_new (hadj);
769       gtk_table_attach (GTK_TABLE (table), scrollbar,
770                         0, 1,                  1, 2,
771                         GTK_FILL | GTK_EXPAND, GTK_FILL,
772                         0,                     0);
773
774       scrollbar = gtk_vscrollbar_new (vadj);
775       gtk_table_attach (GTK_TABLE (table), scrollbar,
776                         1, 2,                  0, 1,
777                         GTK_FILL,              GTK_EXPAND | GTK_FILL,
778                         0,                     0);
779
780     }
781
782   if (!gtk_widget_get_visible (window))
783     gtk_widget_show_all (window);
784   else
785     gtk_widget_hide (window);
786 }
787
788 /*
789  * GtkButton
790  */
791
792 static void
793 button_window (GtkWidget *widget,
794                GtkWidget *button)
795 {
796   if (!gtk_widget_get_visible (button))
797     gtk_widget_show (button);
798   else
799     gtk_widget_hide (button);
800 }
801
802 static void
803 create_buttons (GtkWidget *widget)
804 {
805   static GtkWidget *window = NULL;
806   GtkWidget *box1;
807   GtkWidget *box2;
808   GtkWidget *table;
809   GtkWidget *button[10];
810   GtkWidget *separator;
811
812   if (!window)
813     {
814       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
815       gtk_window_set_screen (GTK_WINDOW (window),
816                              gtk_widget_get_screen (widget));
817
818       g_signal_connect (window, "destroy",
819                         G_CALLBACK (gtk_widget_destroyed),
820                         &window);
821
822       gtk_window_set_title (GTK_WINDOW (window), "GtkButton");
823       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
824
825       box1 = gtk_vbox_new (FALSE, 0);
826       gtk_container_add (GTK_CONTAINER (window), box1);
827
828       table = gtk_table_new (3, 3, FALSE);
829       gtk_table_set_row_spacings (GTK_TABLE (table), 5);
830       gtk_table_set_col_spacings (GTK_TABLE (table), 5);
831       gtk_container_set_border_width (GTK_CONTAINER (table), 10);
832       gtk_box_pack_start (GTK_BOX (box1), table, TRUE, TRUE, 0);
833
834       button[0] = gtk_button_new_with_label ("button1");
835       button[1] = gtk_button_new_with_mnemonic ("_button2");
836       button[2] = gtk_button_new_with_mnemonic ("_button3");
837       button[3] = gtk_button_new_from_stock (GTK_STOCK_OK);
838       button[4] = gtk_button_new_with_label ("button5");
839       button[5] = gtk_button_new_with_label ("button6");
840       button[6] = gtk_button_new_with_label ("button7");
841       button[7] = gtk_button_new_from_stock (GTK_STOCK_CLOSE);
842       button[8] = gtk_button_new_with_label ("button9");
843       
844       g_signal_connect (button[0], "clicked",
845                         G_CALLBACK (button_window),
846                         button[1]);
847
848       gtk_table_attach (GTK_TABLE (table), button[0], 0, 1, 0, 1,
849                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
850
851       g_signal_connect (button[1], "clicked",
852                         G_CALLBACK (button_window),
853                         button[2]);
854
855       gtk_table_attach (GTK_TABLE (table), button[1], 1, 2, 1, 2,
856                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
857
858       g_signal_connect (button[2], "clicked",
859                         G_CALLBACK (button_window),
860                         button[3]);
861       gtk_table_attach (GTK_TABLE (table), button[2], 2, 3, 2, 3,
862                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
863
864       g_signal_connect (button[3], "clicked",
865                         G_CALLBACK (button_window),
866                         button[4]);
867       gtk_table_attach (GTK_TABLE (table), button[3], 0, 1, 2, 3,
868                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
869
870       g_signal_connect (button[4], "clicked",
871                         G_CALLBACK (button_window),
872                         button[5]);
873       gtk_table_attach (GTK_TABLE (table), button[4], 2, 3, 0, 1,
874                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
875
876       g_signal_connect (button[5], "clicked",
877                         G_CALLBACK (button_window),
878                         button[6]);
879       gtk_table_attach (GTK_TABLE (table), button[5], 1, 2, 2, 3,
880                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
881
882       g_signal_connect (button[6], "clicked",
883                         G_CALLBACK (button_window),
884                         button[7]);
885       gtk_table_attach (GTK_TABLE (table), button[6], 1, 2, 0, 1,
886                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
887
888       g_signal_connect (button[7], "clicked",
889                         G_CALLBACK (button_window),
890                         button[8]);
891       gtk_table_attach (GTK_TABLE (table), button[7], 2, 3, 1, 2,
892                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
893
894       g_signal_connect (button[8], "clicked",
895                         G_CALLBACK (button_window),
896                         button[0]);
897       gtk_table_attach (GTK_TABLE (table), button[8], 0, 1, 1, 2,
898                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
899
900       separator = gtk_hseparator_new ();
901       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
902
903       box2 = gtk_vbox_new (FALSE, 10);
904       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
905       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
906
907       button[9] = gtk_button_new_with_label ("close");
908       g_signal_connect_swapped (button[9], "clicked",
909                                 G_CALLBACK (gtk_widget_destroy),
910                                 window);
911       gtk_box_pack_start (GTK_BOX (box2), button[9], TRUE, TRUE, 0);
912       gtk_widget_set_can_default (button[9], TRUE);
913       gtk_widget_grab_default (button[9]);
914     }
915
916   if (!gtk_widget_get_visible (window))
917     gtk_widget_show_all (window);
918   else
919     gtk_widget_destroy (window);
920 }
921
922 /*
923  * GtkToggleButton
924  */
925
926 static void
927 create_toggle_buttons (GtkWidget *widget)
928 {
929   static GtkWidget *window = NULL;
930   GtkWidget *box1;
931   GtkWidget *box2;
932   GtkWidget *button;
933   GtkWidget *separator;
934
935   if (!window)
936     {
937       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
938       gtk_window_set_screen (GTK_WINDOW (window),
939                              gtk_widget_get_screen (widget));
940
941       g_signal_connect (window, "destroy",
942                         G_CALLBACK (gtk_widget_destroyed),
943                         &window);
944
945       gtk_window_set_title (GTK_WINDOW (window), "GtkToggleButton");
946       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
947
948       box1 = gtk_vbox_new (FALSE, 0);
949       gtk_container_add (GTK_CONTAINER (window), box1);
950
951       box2 = gtk_vbox_new (FALSE, 10);
952       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
953       gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
954
955       button = gtk_toggle_button_new_with_label ("button1");
956       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
957
958       button = gtk_toggle_button_new_with_label ("button2");
959       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
960
961       button = gtk_toggle_button_new_with_label ("button3");
962       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
963
964       button = gtk_toggle_button_new_with_label ("inconsistent");
965       gtk_toggle_button_set_inconsistent (GTK_TOGGLE_BUTTON (button), TRUE);
966       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
967       
968       separator = gtk_hseparator_new ();
969       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
970
971       box2 = gtk_vbox_new (FALSE, 10);
972       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
973       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
974
975       button = gtk_button_new_with_label ("close");
976       g_signal_connect_swapped (button, "clicked",
977                                 G_CALLBACK (gtk_widget_destroy),
978                                 window);
979       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
980       gtk_widget_set_can_default (button, TRUE);
981       gtk_widget_grab_default (button);
982     }
983
984   if (!gtk_widget_get_visible (window))
985     gtk_widget_show_all (window);
986   else
987     gtk_widget_destroy (window);
988 }
989
990 static GtkWidget *
991 create_widget_grid (GType widget_type)
992 {
993   GtkWidget *table;
994   GtkWidget *group_widget = NULL;
995   gint i, j;
996   
997   table = gtk_table_new (FALSE, 3, 3);
998   
999   for (i = 0; i < 5; i++)
1000     {
1001       for (j = 0; j < 5; j++)
1002         {
1003           GtkWidget *widget;
1004           char *tmp;
1005           
1006           if (i == 0 && j == 0)
1007             {
1008               widget = NULL;
1009             }
1010           else if (i == 0)
1011             {
1012               tmp = g_strdup_printf ("%d", j);
1013               widget = gtk_label_new (tmp);
1014               g_free (tmp);
1015             }
1016           else if (j == 0)
1017             {
1018               tmp = g_strdup_printf ("%c", 'A' + i - 1);
1019               widget = gtk_label_new (tmp);
1020               g_free (tmp);
1021             }
1022           else
1023             {
1024               widget = g_object_new (widget_type, NULL);
1025               
1026               if (g_type_is_a (widget_type, GTK_TYPE_RADIO_BUTTON))
1027                 {
1028                   if (!group_widget)
1029                     group_widget = widget;
1030                   else
1031                     g_object_set (widget, "group", group_widget, NULL);
1032                 }
1033             }
1034           
1035           if (widget)
1036             gtk_table_attach (GTK_TABLE (table), widget,
1037                               i, i + 1, j, j + 1,
1038                               0,        0,
1039                               0,        0);
1040         }
1041     }
1042
1043   return table;
1044 }
1045
1046 /*
1047  * GtkCheckButton
1048  */
1049
1050 static void
1051 create_check_buttons (GtkWidget *widget)
1052 {
1053   static GtkWidget *window = NULL;
1054   GtkWidget *box1;
1055   GtkWidget *box2;
1056   GtkWidget *button;
1057   GtkWidget *separator;
1058   GtkWidget *table;
1059   
1060   if (!window)
1061     {
1062       window = gtk_dialog_new_with_buttons ("Check Buttons",
1063                                             NULL, 0,
1064                                             GTK_STOCK_CLOSE,
1065                                             GTK_RESPONSE_NONE,
1066                                             NULL);
1067
1068       gtk_window_set_screen (GTK_WINDOW (window), 
1069                              gtk_widget_get_screen (widget));
1070
1071       g_signal_connect (window, "destroy",
1072                         G_CALLBACK (gtk_widget_destroyed),
1073                         &window);
1074       g_signal_connect (window, "response",
1075                         G_CALLBACK (gtk_widget_destroy),
1076                         NULL);
1077
1078       box1 = GTK_DIALOG (window)->vbox;
1079       
1080       box2 = gtk_vbox_new (FALSE, 10);
1081       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
1082       gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
1083
1084       button = gtk_check_button_new_with_mnemonic ("_button1");
1085       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
1086
1087       button = gtk_check_button_new_with_label ("button2");
1088       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
1089
1090       button = gtk_check_button_new_with_label ("button3");
1091       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
1092
1093       button = gtk_check_button_new_with_label ("inconsistent");
1094       gtk_toggle_button_set_inconsistent (GTK_TOGGLE_BUTTON (button), TRUE);
1095       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
1096
1097       separator = gtk_hseparator_new ();
1098       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
1099
1100       table = create_widget_grid (GTK_TYPE_CHECK_BUTTON);
1101       gtk_container_set_border_width (GTK_CONTAINER (table), 10);
1102       gtk_box_pack_start (GTK_BOX (box1), table, TRUE, TRUE, 0);
1103     }
1104
1105   if (!gtk_widget_get_visible (window))
1106     gtk_widget_show_all (window);
1107   else
1108     gtk_widget_destroy (window);
1109 }
1110
1111 /*
1112  * GtkRadioButton
1113  */
1114
1115 static void
1116 create_radio_buttons (GtkWidget *widget)
1117 {
1118   static GtkWidget *window = NULL;
1119   GtkWidget *box1;
1120   GtkWidget *box2;
1121   GtkWidget *button;
1122   GtkWidget *separator;
1123   GtkWidget *table;
1124
1125   if (!window)
1126     {
1127       window = gtk_dialog_new_with_buttons ("Radio Buttons",
1128                                             NULL, 0,
1129                                             GTK_STOCK_CLOSE,
1130                                             GTK_RESPONSE_NONE,
1131                                             NULL);
1132
1133       gtk_window_set_screen (GTK_WINDOW (window),
1134                              gtk_widget_get_screen (widget));
1135
1136       g_signal_connect (window, "destroy",
1137                         G_CALLBACK (gtk_widget_destroyed),
1138                         &window);
1139       g_signal_connect (window, "response",
1140                         G_CALLBACK (gtk_widget_destroy),
1141                         NULL);
1142
1143       box1 = GTK_DIALOG (window)->vbox;
1144
1145       box2 = gtk_vbox_new (FALSE, 10);
1146       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
1147       gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
1148
1149       button = gtk_radio_button_new_with_label (NULL, "button1");
1150       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
1151
1152       button = gtk_radio_button_new_with_label (
1153                  gtk_radio_button_get_group (GTK_RADIO_BUTTON (button)),
1154                  "button2");
1155       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
1156       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
1157
1158       button = gtk_radio_button_new_with_label (
1159                  gtk_radio_button_get_group (GTK_RADIO_BUTTON (button)),
1160                  "button3");
1161       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
1162
1163       button = gtk_radio_button_new_with_label (
1164                  gtk_radio_button_get_group (GTK_RADIO_BUTTON (button)),
1165                  "inconsistent");
1166       gtk_toggle_button_set_inconsistent (GTK_TOGGLE_BUTTON (button), TRUE);
1167       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
1168       
1169       separator = gtk_hseparator_new ();
1170       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
1171
1172       box2 = gtk_vbox_new (FALSE, 10);
1173       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
1174       gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
1175
1176       button = gtk_radio_button_new_with_label (NULL, "button4");
1177       gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (button), FALSE);
1178       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
1179
1180       button = gtk_radio_button_new_with_label (
1181                  gtk_radio_button_get_group (GTK_RADIO_BUTTON (button)),
1182                  "button5");
1183       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
1184       gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (button), FALSE);
1185       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
1186
1187       button = gtk_radio_button_new_with_label (
1188                  gtk_radio_button_get_group (GTK_RADIO_BUTTON (button)),
1189                  "button6");
1190       gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (button), FALSE);
1191       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
1192
1193       separator = gtk_hseparator_new ();
1194       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
1195
1196       table = create_widget_grid (GTK_TYPE_RADIO_BUTTON);
1197       gtk_container_set_border_width (GTK_CONTAINER (table), 10);
1198       gtk_box_pack_start (GTK_BOX (box1), table, TRUE, TRUE, 0);
1199     }
1200
1201   if (!gtk_widget_get_visible (window))
1202     gtk_widget_show_all (window);
1203   else
1204     gtk_widget_destroy (window);
1205 }
1206
1207 /*
1208  * GtkButtonBox
1209  */
1210
1211 static GtkWidget *
1212 create_bbox (gint  horizontal,
1213              char* title, 
1214              gint  spacing,
1215              gint  child_w,
1216              gint  child_h,
1217              gint  layout)
1218 {
1219   GtkWidget *frame;
1220   GtkWidget *bbox;
1221   GtkWidget *button;
1222         
1223   frame = gtk_frame_new (title);
1224
1225   if (horizontal)
1226     bbox = gtk_hbutton_box_new ();
1227   else
1228     bbox = gtk_vbutton_box_new ();
1229
1230   gtk_container_set_border_width (GTK_CONTAINER (bbox), 5);
1231   gtk_container_add (GTK_CONTAINER (frame), bbox);
1232
1233   gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), layout);
1234   gtk_box_set_spacing (GTK_BOX (bbox), spacing);
1235   gtk_button_box_set_child_size (GTK_BUTTON_BOX (bbox), child_w, child_h);
1236   
1237   button = gtk_button_new_with_label ("OK");
1238   gtk_container_add (GTK_CONTAINER (bbox), button);
1239   
1240   button = gtk_button_new_with_label ("Cancel");
1241   gtk_container_add (GTK_CONTAINER (bbox), button);
1242   
1243   button = gtk_button_new_with_label ("Help");
1244   gtk_container_add (GTK_CONTAINER (bbox), button);
1245
1246   return frame;
1247 }
1248
1249 static void
1250 create_button_box (GtkWidget *widget)
1251 {
1252   static GtkWidget* window = NULL;
1253   GtkWidget *main_vbox;
1254   GtkWidget *vbox;
1255   GtkWidget *hbox;
1256   GtkWidget *frame_horz;
1257   GtkWidget *frame_vert;
1258
1259   if (!window)
1260   {
1261     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1262     gtk_window_set_screen (GTK_WINDOW (window), gtk_widget_get_screen (widget));
1263     gtk_window_set_title (GTK_WINDOW (window), "Button Boxes");
1264     
1265     g_signal_connect (window, "destroy",
1266                       G_CALLBACK (gtk_widget_destroyed),
1267                       &window);
1268
1269     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
1270
1271     main_vbox = gtk_vbox_new (FALSE, 0);
1272     gtk_container_add (GTK_CONTAINER (window), main_vbox);
1273     
1274     frame_horz = gtk_frame_new ("Horizontal Button Boxes");
1275     gtk_box_pack_start (GTK_BOX (main_vbox), frame_horz, TRUE, TRUE, 10);
1276     
1277     vbox = gtk_vbox_new (FALSE, 0);
1278     gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
1279     gtk_container_add (GTK_CONTAINER (frame_horz), vbox);
1280     
1281     gtk_box_pack_start (GTK_BOX (vbox), 
1282                         create_bbox (TRUE, "Spread", 40, 85, 20, GTK_BUTTONBOX_SPREAD),
1283                         TRUE, TRUE, 0);
1284     
1285     gtk_box_pack_start (GTK_BOX (vbox), 
1286                         create_bbox (TRUE, "Edge", 40, 85, 20, GTK_BUTTONBOX_EDGE),
1287                         TRUE, TRUE, 5);
1288     
1289     gtk_box_pack_start (GTK_BOX (vbox), 
1290                         create_bbox (TRUE, "Start", 40, 85, 20, GTK_BUTTONBOX_START),
1291                         TRUE, TRUE, 5);
1292     
1293     gtk_box_pack_start (GTK_BOX (vbox), 
1294                         create_bbox (TRUE, "End", 40, 85, 20, GTK_BUTTONBOX_END),
1295                         TRUE, TRUE, 5);
1296     
1297     gtk_box_pack_start (GTK_BOX (vbox),
1298                         create_bbox (TRUE, "Center", 40, 85, 20, GTK_BUTTONBOX_CENTER),
1299                         TRUE, TRUE, 5);
1300     
1301     frame_vert = gtk_frame_new ("Vertical Button Boxes");
1302     gtk_box_pack_start (GTK_BOX (main_vbox), frame_vert, TRUE, TRUE, 10);
1303     
1304     hbox = gtk_hbox_new (FALSE, 0);
1305     gtk_container_set_border_width (GTK_CONTAINER (hbox), 10);
1306     gtk_container_add (GTK_CONTAINER (frame_vert), hbox);
1307
1308     gtk_box_pack_start (GTK_BOX (hbox), 
1309                         create_bbox (FALSE, "Spread", 30, 85, 20, GTK_BUTTONBOX_SPREAD),
1310                         TRUE, TRUE, 0);
1311     
1312     gtk_box_pack_start (GTK_BOX (hbox), 
1313                         create_bbox (FALSE, "Edge", 30, 85, 20, GTK_BUTTONBOX_EDGE),
1314                         TRUE, TRUE, 5);
1315     
1316     gtk_box_pack_start (GTK_BOX (hbox), 
1317                         create_bbox (FALSE, "Start", 30, 85, 20, GTK_BUTTONBOX_START),
1318                         TRUE, TRUE, 5);
1319     
1320     gtk_box_pack_start (GTK_BOX (hbox), 
1321                         create_bbox (FALSE, "End", 30, 85, 20, GTK_BUTTONBOX_END),
1322                         TRUE, TRUE, 5);
1323     
1324     gtk_box_pack_start (GTK_BOX (hbox),
1325                         create_bbox (FALSE, "Center", 30, 85, 20, GTK_BUTTONBOX_CENTER),
1326                         TRUE, TRUE, 5);
1327   }
1328
1329   if (!gtk_widget_get_visible (window))
1330     gtk_widget_show_all (window);
1331   else
1332     gtk_widget_destroy (window);
1333 }
1334
1335 /*
1336  * GtkToolBar
1337  */
1338
1339 static GtkWidget*
1340 new_pixmap (char      *filename,
1341             GdkWindow *window,
1342             GdkColor  *background)
1343 {
1344   GtkWidget *wpixmap;
1345   GdkPixmap *pixmap;
1346   GdkBitmap *mask;
1347
1348   if (strcmp (filename, "test.xpm") == 0 ||
1349       !file_exists (filename))
1350     {
1351       pixmap = gdk_pixmap_create_from_xpm_d (window, &mask,
1352                                              background,
1353                                              openfile);
1354     }
1355   else
1356     pixmap = gdk_pixmap_create_from_xpm (window, &mask,
1357                                          background,
1358                                          filename);
1359   
1360   wpixmap = gtk_image_new_from_pixmap (pixmap, mask);
1361
1362   return wpixmap;
1363 }
1364
1365
1366 static void
1367 set_toolbar_small_stock (GtkWidget *widget,
1368                          gpointer   data)
1369 {
1370   gtk_toolbar_set_icon_size (GTK_TOOLBAR (data), GTK_ICON_SIZE_SMALL_TOOLBAR);
1371 }
1372
1373 static void
1374 set_toolbar_large_stock (GtkWidget *widget,
1375                          gpointer   data)
1376 {
1377   gtk_toolbar_set_icon_size (GTK_TOOLBAR (data), GTK_ICON_SIZE_LARGE_TOOLBAR);
1378 }
1379
1380 static void
1381 set_toolbar_horizontal (GtkWidget *widget,
1382                         gpointer   data)
1383 {
1384   gtk_toolbar_set_orientation (GTK_TOOLBAR (data), GTK_ORIENTATION_HORIZONTAL);
1385 }
1386
1387 static void
1388 set_toolbar_vertical (GtkWidget *widget,
1389                       gpointer   data)
1390 {
1391   gtk_toolbar_set_orientation (GTK_TOOLBAR (data), GTK_ORIENTATION_VERTICAL);
1392 }
1393
1394 static void
1395 set_toolbar_icons (GtkWidget *widget,
1396                    gpointer   data)
1397 {
1398   gtk_toolbar_set_style (GTK_TOOLBAR (data), GTK_TOOLBAR_ICONS);
1399 }
1400
1401 static void
1402 set_toolbar_text (GtkWidget *widget,
1403                   gpointer   data)
1404 {
1405   gtk_toolbar_set_style (GTK_TOOLBAR (data), GTK_TOOLBAR_TEXT);
1406 }
1407
1408 static void
1409 set_toolbar_both (GtkWidget *widget,
1410                   gpointer   data)
1411 {
1412   gtk_toolbar_set_style (GTK_TOOLBAR (data), GTK_TOOLBAR_BOTH);
1413 }
1414
1415 static void
1416 set_toolbar_both_horiz (GtkWidget *widget,
1417                         gpointer   data)
1418 {
1419   gtk_toolbar_set_style (GTK_TOOLBAR (data), GTK_TOOLBAR_BOTH_HORIZ);
1420 }
1421
1422 static void
1423 set_toolbar_enable (GtkWidget *widget,
1424                     gpointer   data)
1425 {
1426   gtk_toolbar_set_tooltips (GTK_TOOLBAR (data), TRUE);
1427 }
1428
1429 static void
1430 set_toolbar_disable (GtkWidget *widget,
1431                      gpointer   data)
1432 {
1433   gtk_toolbar_set_tooltips (GTK_TOOLBAR (data), FALSE);
1434 }
1435
1436 static void
1437 create_toolbar (GtkWidget *widget)
1438 {
1439   static GtkWidget *window = NULL;
1440   GtkWidget *toolbar;
1441   GtkWidget *entry;
1442
1443   if (!window)
1444     {
1445       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1446       gtk_window_set_screen (GTK_WINDOW (window),
1447                              gtk_widget_get_screen (widget));
1448       
1449       gtk_window_set_title (GTK_WINDOW (window), "Toolbar test");
1450
1451       g_signal_connect (window, "destroy",
1452                         G_CALLBACK (gtk_widget_destroyed),
1453                         &window);
1454
1455       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
1456       gtk_widget_realize (window);
1457
1458       toolbar = gtk_toolbar_new ();
1459
1460       gtk_toolbar_insert_stock (GTK_TOOLBAR (toolbar),
1461                                 GTK_STOCK_NEW,
1462                                 "Stock icon: New", "Toolbar/New",
1463                                 G_CALLBACK (set_toolbar_small_stock), toolbar, -1);
1464       
1465       gtk_toolbar_insert_stock (GTK_TOOLBAR (toolbar),
1466                                 GTK_STOCK_OPEN,
1467                                 "Stock icon: Open", "Toolbar/Open",
1468                                 G_CALLBACK (set_toolbar_large_stock), toolbar, -1);
1469       
1470       gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
1471                                "Horizontal", "Horizontal toolbar layout", "Toolbar/Horizontal",
1472                                new_pixmap ("test.xpm", window->window, &window->style->bg[GTK_STATE_NORMAL]),
1473                                G_CALLBACK (set_toolbar_horizontal), toolbar);
1474       gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
1475                                "Vertical", "Vertical toolbar layout", "Toolbar/Vertical",
1476                                new_pixmap ("test.xpm", window->window, &window->style->bg[GTK_STATE_NORMAL]),
1477                                G_CALLBACK (set_toolbar_vertical), toolbar);
1478
1479       gtk_toolbar_append_space (GTK_TOOLBAR(toolbar));
1480
1481       gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
1482                                "Icons", "Only show toolbar icons", "Toolbar/IconsOnly",
1483                                new_pixmap ("test.xpm", window->window, &window->style->bg[GTK_STATE_NORMAL]),
1484                                G_CALLBACK (set_toolbar_icons), toolbar);
1485       gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
1486                                "Text", "Only show toolbar text", "Toolbar/TextOnly",
1487                                new_pixmap ("test.xpm", window->window, &window->style->bg[GTK_STATE_NORMAL]),
1488                                G_CALLBACK (set_toolbar_text), toolbar);
1489       gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
1490                                "Both", "Show toolbar icons and text", "Toolbar/Both",
1491                                new_pixmap ("test.xpm", window->window, &window->style->bg[GTK_STATE_NORMAL]),
1492                                G_CALLBACK (set_toolbar_both), toolbar);
1493       gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
1494                                "Both (horizontal)",
1495                                "Show toolbar icons and text in a horizontal fashion",
1496                                "Toolbar/BothHoriz",
1497                                new_pixmap ("test.xpm", window->window, &window->style->bg[GTK_STATE_NORMAL]),
1498                                G_CALLBACK (set_toolbar_both_horiz), toolbar);
1499                                
1500       gtk_toolbar_append_space (GTK_TOOLBAR (toolbar));
1501
1502       entry = gtk_entry_new ();
1503
1504       gtk_toolbar_append_widget (GTK_TOOLBAR (toolbar), entry, "This is an unusable GtkEntry ;)", "Hey don't click me!!!");
1505
1506       gtk_toolbar_append_space (GTK_TOOLBAR (toolbar));
1507
1508
1509       gtk_toolbar_append_space (GTK_TOOLBAR (toolbar));
1510
1511       gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
1512                                "Enable", "Enable tooltips", NULL,
1513                                new_pixmap ("test.xpm", window->window, &window->style->bg[GTK_STATE_NORMAL]),
1514                                G_CALLBACK (set_toolbar_enable), toolbar);
1515       gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
1516                                "Disable", "Disable tooltips", NULL,
1517                                new_pixmap ("test.xpm", window->window, &window->style->bg[GTK_STATE_NORMAL]),
1518                                G_CALLBACK (set_toolbar_disable), toolbar);
1519
1520       gtk_toolbar_append_space (GTK_TOOLBAR (toolbar));
1521
1522       gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
1523                                "Frobate", "Frobate tooltip", NULL,
1524                                new_pixmap ("test.xpm", window->window, &window->style->bg[GTK_STATE_NORMAL]),
1525                                NULL, toolbar);
1526       gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
1527                                "Baz", "Baz tooltip", NULL,
1528                                new_pixmap ("test.xpm", window->window, &window->style->bg[GTK_STATE_NORMAL]),
1529                                NULL, toolbar);
1530
1531       gtk_toolbar_append_space (GTK_TOOLBAR (toolbar));
1532       
1533       gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
1534                                "Blah", "Blah tooltip", NULL,
1535                                new_pixmap ("test.xpm", window->window, &window->style->bg[GTK_STATE_NORMAL]),
1536                                NULL, toolbar);
1537       gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
1538                                "Bar", "Bar tooltip", NULL,
1539                                new_pixmap ("test.xpm", window->window, &window->style->bg[GTK_STATE_NORMAL]),
1540                                NULL, toolbar);
1541
1542       gtk_container_add (GTK_CONTAINER (window), toolbar);
1543
1544       gtk_widget_set_size_request (toolbar, 200, -1);
1545     }
1546
1547   if (!gtk_widget_get_visible (window))
1548     gtk_widget_show_all (window);
1549   else
1550     gtk_widget_destroy (window);
1551 }
1552
1553 static GtkWidget*
1554 make_toolbar (GtkWidget *window)
1555 {
1556   GtkWidget *toolbar;
1557
1558   if (!gtk_widget_get_realized (window))
1559     gtk_widget_realize (window);
1560
1561   toolbar = gtk_toolbar_new ();
1562
1563   gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
1564                            "Horizontal", "Horizontal toolbar layout", NULL,
1565                            new_pixmap ("test.xpm", window->window, &window->style->bg[GTK_STATE_NORMAL]),
1566                            G_CALLBACK (set_toolbar_horizontal), toolbar);
1567   gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
1568                            "Vertical", "Vertical toolbar layout", NULL,
1569                            new_pixmap ("test.xpm", window->window, &window->style->bg[GTK_STATE_NORMAL]),
1570                            G_CALLBACK (set_toolbar_vertical), toolbar);
1571
1572   gtk_toolbar_append_space (GTK_TOOLBAR(toolbar));
1573
1574   gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
1575                            "Icons", "Only show toolbar icons", NULL,
1576                            new_pixmap ("test.xpm", window->window, &window->style->bg[GTK_STATE_NORMAL]),
1577                            G_CALLBACK (set_toolbar_icons), toolbar);
1578   gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
1579                            "Text", "Only show toolbar text", NULL,
1580                            new_pixmap ("test.xpm", window->window, &window->style->bg[GTK_STATE_NORMAL]),
1581                            G_CALLBACK (set_toolbar_text), toolbar);
1582   gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
1583                            "Both", "Show toolbar icons and text", NULL,
1584                            new_pixmap ("test.xpm", window->window, &window->style->bg[GTK_STATE_NORMAL]),
1585                            G_CALLBACK (set_toolbar_both), toolbar);
1586
1587   gtk_toolbar_append_space (GTK_TOOLBAR (toolbar));
1588
1589   gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
1590                            "Woot", "Woot woot woot", NULL,
1591                            new_pixmap ("test.xpm", window->window, &window->style->bg[GTK_STATE_NORMAL]),
1592                            NULL, toolbar);
1593   gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
1594                            "Blah", "Blah blah blah", "Toolbar/Big",
1595                            new_pixmap ("test.xpm", window->window, &window->style->bg[GTK_STATE_NORMAL]),
1596                            NULL, toolbar);
1597
1598   gtk_toolbar_append_space (GTK_TOOLBAR (toolbar));
1599
1600   gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
1601                            "Enable", "Enable tooltips", NULL,
1602                            new_pixmap ("test.xpm", window->window, &window->style->bg[GTK_STATE_NORMAL]),
1603                            G_CALLBACK (set_toolbar_enable), toolbar);
1604   gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
1605                            "Disable", "Disable tooltips", NULL,
1606                            new_pixmap ("test.xpm", window->window, &window->style->bg[GTK_STATE_NORMAL]),
1607                            G_CALLBACK (set_toolbar_disable), toolbar);
1608
1609   gtk_toolbar_append_space (GTK_TOOLBAR (toolbar));
1610   
1611   gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
1612                            "Hoo", "Hoo tooltip", NULL,
1613                            new_pixmap ("test.xpm", window->window, &window->style->bg[GTK_STATE_NORMAL]),
1614                            NULL, toolbar);
1615   gtk_toolbar_append_item (GTK_TOOLBAR (toolbar),
1616                            "Woo", "Woo tooltip", NULL,
1617                            new_pixmap ("test.xpm", window->window, &window->style->bg[GTK_STATE_NORMAL]),
1618                            NULL, toolbar);
1619
1620   return toolbar;
1621 }
1622
1623 /*
1624  * GtkStatusBar
1625  */
1626
1627 static guint statusbar_counter = 1;
1628
1629 static void
1630 statusbar_push (GtkWidget *button,
1631                 GtkStatusbar *statusbar)
1632 {
1633   gchar text[1024];
1634
1635   sprintf (text, "something %d", statusbar_counter++);
1636
1637   gtk_statusbar_push (statusbar, 1, text);
1638 }
1639
1640 static void
1641 statusbar_push_long (GtkWidget *button,
1642                      GtkStatusbar *statusbar)
1643 {
1644   gchar text[1024];
1645
1646   sprintf (text, "Just because a system has menu choices written with English words, phrases or sentences, that is no guarantee, that it is comprehensible. Individual words may not be familiar to some users (for example, \"repaginate\"), and two menu items may appear to satisfy the users's needs, whereas only one does (for example, \"put away\" or \"eject\").");
1647
1648   gtk_statusbar_push (statusbar, 1, text);
1649 }
1650
1651 static void
1652 statusbar_pop (GtkWidget *button,
1653                GtkStatusbar *statusbar)
1654 {
1655   gtk_statusbar_pop (statusbar, 1);
1656 }
1657
1658 static void
1659 statusbar_steal (GtkWidget *button,
1660                  GtkStatusbar *statusbar)
1661 {
1662   gtk_statusbar_remove (statusbar, 1, 4);
1663 }
1664
1665 static void
1666 statusbar_popped (GtkStatusbar  *statusbar,
1667                   guint          context_id,
1668                   const gchar   *text)
1669 {
1670   if (!statusbar->messages)
1671     statusbar_counter = 1;
1672 }
1673
1674 static void
1675 statusbar_contexts (GtkStatusbar *statusbar)
1676 {
1677   gchar *string;
1678
1679   string = "any context";
1680   g_print ("GtkStatusBar: context=\"%s\", context_id=%d\n",
1681            string,
1682            gtk_statusbar_get_context_id (statusbar, string));
1683   
1684   string = "idle messages";
1685   g_print ("GtkStatusBar: context=\"%s\", context_id=%d\n",
1686            string,
1687            gtk_statusbar_get_context_id (statusbar, string));
1688   
1689   string = "some text";
1690   g_print ("GtkStatusBar: context=\"%s\", context_id=%d\n",
1691            string,
1692            gtk_statusbar_get_context_id (statusbar, string));
1693
1694   string = "hit the mouse";
1695   g_print ("GtkStatusBar: context=\"%s\", context_id=%d\n",
1696            string,
1697            gtk_statusbar_get_context_id (statusbar, string));
1698
1699   string = "hit the mouse2";
1700   g_print ("GtkStatusBar: context=\"%s\", context_id=%d\n",
1701            string,
1702            gtk_statusbar_get_context_id (statusbar, string));
1703 }
1704
1705 static void
1706 create_statusbar (GtkWidget *widget)
1707 {
1708   static GtkWidget *window = NULL;
1709   GtkWidget *box1;
1710   GtkWidget *box2;
1711   GtkWidget *button;
1712   GtkWidget *separator;
1713   GtkWidget *statusbar;
1714
1715   if (!window)
1716     {
1717       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1718       gtk_window_set_screen (GTK_WINDOW (window),
1719                              gtk_widget_get_screen (widget));
1720
1721       g_signal_connect (window, "destroy",
1722                         G_CALLBACK (gtk_widget_destroyed),
1723                         &window);
1724
1725       gtk_window_set_title (GTK_WINDOW (window), "statusbar");
1726       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
1727
1728       box1 = gtk_vbox_new (FALSE, 0);
1729       gtk_container_add (GTK_CONTAINER (window), box1);
1730
1731       box2 = gtk_vbox_new (FALSE, 10);
1732       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
1733       gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
1734
1735       statusbar = gtk_statusbar_new ();
1736       gtk_box_pack_end (GTK_BOX (box1), statusbar, TRUE, TRUE, 0);
1737       g_signal_connect (statusbar,
1738                         "text_popped",
1739                         G_CALLBACK (statusbar_popped),
1740                         NULL);
1741
1742       button = g_object_new (gtk_button_get_type (),
1743                                "label", "push something",
1744                                "visible", TRUE,
1745                                "parent", box2,
1746                                NULL);
1747       g_object_connect (button,
1748                         "signal::clicked", statusbar_push, statusbar,
1749                         NULL);
1750
1751       button = g_object_connect (g_object_new (gtk_button_get_type (),
1752                                                  "label", "pop",
1753                                                  "visible", TRUE,
1754                                                  "parent", box2,
1755                                                  NULL),
1756                                  "signal_after::clicked", statusbar_pop, statusbar,
1757                                  NULL);
1758
1759       button = g_object_connect (g_object_new (gtk_button_get_type (),
1760                                                  "label", "steal #4",
1761                                                  "visible", TRUE,
1762                                                  "parent", box2,
1763                                                  NULL),
1764                                  "signal_after::clicked", statusbar_steal, statusbar,
1765                                  NULL);
1766
1767       button = g_object_connect (g_object_new (gtk_button_get_type (),
1768                                                  "label", "test contexts",
1769                                                  "visible", TRUE,
1770                                                  "parent", box2,
1771                                                  NULL),
1772                                  "swapped_signal_after::clicked", statusbar_contexts, statusbar,
1773                                  NULL);
1774
1775       button = g_object_connect (g_object_new (gtk_button_get_type (),
1776                                                  "label", "push something long",
1777                                                  "visible", TRUE,
1778                                                  "parent", box2,
1779                                                  NULL),
1780                                  "signal_after::clicked", statusbar_push_long, statusbar,
1781                                  NULL);
1782       
1783       separator = gtk_hseparator_new ();
1784       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
1785
1786       box2 = gtk_vbox_new (FALSE, 10);
1787       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
1788       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
1789
1790       button = gtk_button_new_with_label ("close");
1791       g_signal_connect_swapped (button, "clicked",
1792                                 G_CALLBACK (gtk_widget_destroy),
1793                                 window);
1794       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
1795       gtk_widget_set_can_default (button, TRUE);
1796       gtk_widget_grab_default (button);
1797     }
1798
1799   if (!gtk_widget_get_visible (window))
1800     gtk_widget_show_all (window);
1801   else
1802     gtk_widget_destroy (window);
1803 }
1804
1805 /*
1806  * GtkTree
1807  */
1808
1809 static void
1810 cb_tree_destroy_event(GtkWidget* w)
1811 {
1812   sTreeButtons* tree_buttons;
1813
1814   /* free buttons structure associate at this tree */
1815   tree_buttons = g_object_get_data (G_OBJECT (w), "user_data");
1816   g_free (tree_buttons);
1817 }
1818
1819 static void
1820 cb_add_new_item(GtkWidget* w, GtkTree* tree)
1821 {
1822   sTreeButtons* tree_buttons;
1823   GList* selected_list;
1824   GtkWidget* selected_item;
1825   GtkWidget* subtree;
1826   GtkWidget* item_new;
1827   char buffer[255];
1828
1829   tree_buttons = g_object_get_data (G_OBJECT (tree), "user_data");
1830
1831   selected_list = GTK_TREE_SELECTION_OLD(tree);
1832
1833   if(selected_list == NULL)
1834     {
1835       /* there is no item in tree */
1836       subtree = GTK_WIDGET(tree);
1837     }
1838   else
1839     {
1840       /* list can have only one element */
1841       selected_item = GTK_WIDGET(selected_list->data);
1842       
1843       subtree = GTK_TREE_ITEM_SUBTREE(selected_item);
1844
1845       if(subtree == NULL)
1846         {
1847           /* current selected item have not subtree ... create it */
1848           subtree = gtk_tree_new();
1849           gtk_tree_item_set_subtree(GTK_TREE_ITEM(selected_item), 
1850                                     subtree);
1851         }
1852     }
1853
1854   /* at this point, we know which subtree will be used to add new item */
1855   /* create a new item */
1856   sprintf(buffer, "item add %d", tree_buttons->nb_item_add);
1857   item_new = gtk_tree_item_new_with_label(buffer);
1858   gtk_tree_append(GTK_TREE(subtree), item_new);
1859   gtk_widget_show(item_new);
1860
1861   tree_buttons->nb_item_add++;
1862 }
1863
1864 static void
1865 cb_remove_item(GtkWidget*w, GtkTree* tree)
1866 {
1867   GList* selected_list;
1868   GList* clear_list;
1869   
1870   selected_list = GTK_TREE_SELECTION_OLD(tree);
1871
1872   clear_list = NULL;
1873     
1874   while (selected_list) 
1875     {
1876       clear_list = g_list_prepend (clear_list, selected_list->data);
1877       selected_list = selected_list->next;
1878     }
1879   
1880   clear_list = g_list_reverse (clear_list);
1881   gtk_tree_remove_items(tree, clear_list);
1882
1883   g_list_free (clear_list);
1884 }
1885
1886 static void
1887 cb_remove_subtree(GtkWidget*w, GtkTree* tree)
1888 {
1889   GList* selected_list;
1890   GtkTreeItem *item;
1891   
1892   selected_list = GTK_TREE_SELECTION_OLD(tree);
1893
1894   if (selected_list)
1895     {
1896       item = GTK_TREE_ITEM (selected_list->data);
1897       if (item->subtree)
1898         gtk_tree_item_remove_subtree (item);
1899     }
1900 }
1901
1902 static void
1903 cb_tree_changed(GtkTree* tree)
1904 {
1905   sTreeButtons* tree_buttons;
1906   GList* selected_list;
1907   guint nb_selected;
1908
1909   tree_buttons = g_object_get_data (G_OBJECT (tree), "user_data");
1910
1911   selected_list = GTK_TREE_SELECTION_OLD(tree);
1912   nb_selected = g_list_length(selected_list);
1913
1914   if(nb_selected == 0) 
1915     {
1916       if(tree->children == NULL)
1917         gtk_widget_set_sensitive(tree_buttons->add_button, TRUE);
1918       else
1919         gtk_widget_set_sensitive(tree_buttons->add_button, FALSE);
1920       gtk_widget_set_sensitive(tree_buttons->remove_button, FALSE);
1921       gtk_widget_set_sensitive(tree_buttons->subtree_button, FALSE);
1922     } 
1923   else 
1924     {
1925       gtk_widget_set_sensitive(tree_buttons->remove_button, TRUE);
1926       gtk_widget_set_sensitive(tree_buttons->add_button, (nb_selected == 1));
1927       gtk_widget_set_sensitive(tree_buttons->subtree_button, (nb_selected == 1));
1928     }  
1929 }
1930
1931 static void 
1932 create_subtree(GtkWidget* item, guint level, guint nb_item_max, guint recursion_level_max)
1933 {
1934   GtkWidget* item_subtree;
1935   GtkWidget* item_new;
1936   guint nb_item;
1937   char buffer[255];
1938   int no_root_item;
1939
1940   if(level == recursion_level_max) return;
1941
1942   if(level == -1)
1943     {
1944       /* query with no root item */
1945       level = 0;
1946       item_subtree = item;
1947       no_root_item = 1;
1948     }
1949   else
1950     {
1951       /* query with no root item */
1952       /* create subtree and associate it with current item */
1953       item_subtree = gtk_tree_new();
1954       no_root_item = 0;
1955     }
1956   
1957   for(nb_item = 0; nb_item < nb_item_max; nb_item++)
1958     {
1959       sprintf(buffer, "item %d-%d", level, nb_item);
1960       item_new = gtk_tree_item_new_with_label(buffer);
1961       gtk_tree_append(GTK_TREE(item_subtree), item_new);
1962       create_subtree(item_new, level+1, nb_item_max, recursion_level_max);
1963       gtk_widget_show(item_new);
1964     }
1965
1966   if(!no_root_item)
1967     gtk_tree_item_set_subtree(GTK_TREE_ITEM(item), item_subtree);
1968 }
1969
1970 static void
1971 create_tree_sample(GdkScreen *screen, guint selection_mode, 
1972                    guint draw_line, guint view_line, guint no_root_item,
1973                    guint nb_item_max, guint recursion_level_max) 
1974 {
1975   GtkWidget* window;
1976   GtkWidget* box1;
1977   GtkWidget* box2;
1978   GtkWidget* separator;
1979   GtkWidget* button;
1980   GtkWidget* scrolled_win;
1981   GtkWidget* root_tree;
1982   GtkWidget* root_item;
1983   sTreeButtons* tree_buttons;
1984
1985   /* create tree buttons struct */
1986   if ((tree_buttons = g_malloc (sizeof (sTreeButtons))) == NULL)
1987     {
1988       g_error("can't allocate memory for tree structure !\n");
1989       return;
1990     }
1991   tree_buttons->nb_item_add = 0;
1992
1993   /* create top level window */
1994   window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
1995   gtk_window_set_screen (GTK_WINDOW (window), screen);
1996   gtk_window_set_title(GTK_WINDOW(window), "Tree Sample");
1997   g_signal_connect (window, "destroy",
1998                     G_CALLBACK (cb_tree_destroy_event), NULL);
1999   g_object_set_data (G_OBJECT (window), "user_data", tree_buttons);
2000
2001   box1 = gtk_vbox_new(FALSE, 0);
2002   gtk_container_add(GTK_CONTAINER(window), box1);
2003   gtk_widget_show(box1);
2004
2005   /* create tree box */
2006   box2 = gtk_vbox_new(FALSE, 0);
2007   gtk_box_pack_start(GTK_BOX(box1), box2, TRUE, TRUE, 0);
2008   gtk_container_set_border_width(GTK_CONTAINER(box2), 5);
2009   gtk_widget_show(box2);
2010
2011   /* create scrolled window */
2012   scrolled_win = gtk_scrolled_window_new (NULL, NULL);
2013   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
2014                                   GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
2015   gtk_box_pack_start (GTK_BOX (box2), scrolled_win, TRUE, TRUE, 0);
2016   gtk_widget_set_size_request (scrolled_win, 200, 200);
2017   gtk_widget_show (scrolled_win);
2018   
2019   /* create root tree widget */
2020   root_tree = gtk_tree_new();
2021   g_signal_connect (root_tree, "selection_changed",
2022                     G_CALLBACK (cb_tree_changed),
2023                     NULL);
2024   g_object_set_data (G_OBJECT (root_tree), "user_data", tree_buttons);
2025   gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_win), root_tree);
2026   gtk_tree_set_selection_mode(GTK_TREE(root_tree), selection_mode);
2027   gtk_tree_set_view_lines(GTK_TREE(root_tree), draw_line);
2028   gtk_tree_set_view_mode(GTK_TREE(root_tree), !view_line);
2029   gtk_widget_show(root_tree);
2030
2031   if ( no_root_item )
2032     {
2033       /* set root tree to subtree function with root item variable */
2034       root_item = GTK_WIDGET(root_tree);
2035     }
2036   else
2037     {
2038       /* create root tree item widget */
2039       root_item = gtk_tree_item_new_with_label("root item");
2040       gtk_tree_append(GTK_TREE(root_tree), root_item);
2041       gtk_widget_show(root_item);
2042      }
2043   create_subtree(root_item, -no_root_item, nb_item_max, recursion_level_max);
2044
2045   box2 = gtk_vbox_new(FALSE, 0);
2046   gtk_box_pack_start(GTK_BOX(box1), box2, FALSE, FALSE, 0);
2047   gtk_container_set_border_width(GTK_CONTAINER(box2), 5);
2048   gtk_widget_show(box2);
2049
2050   button = gtk_button_new_with_label("Add Item");
2051   gtk_widget_set_sensitive(button, FALSE);
2052   g_signal_connect (button, "clicked",
2053                     G_CALLBACK (cb_add_new_item),
2054                     root_tree);
2055   gtk_box_pack_start(GTK_BOX(box2), button, TRUE, TRUE, 0);
2056   gtk_widget_show(button);
2057   tree_buttons->add_button = button;
2058
2059   button = gtk_button_new_with_label("Remove Item(s)");
2060   gtk_widget_set_sensitive(button, FALSE);
2061   g_signal_connect (button, "clicked",
2062                     G_CALLBACK (cb_remove_item),
2063                     root_tree);
2064   gtk_box_pack_start(GTK_BOX(box2), button, TRUE, TRUE, 0);
2065   gtk_widget_show(button);
2066   tree_buttons->remove_button = button;
2067
2068   button = gtk_button_new_with_label("Remove Subtree");
2069   gtk_widget_set_sensitive(button, FALSE);
2070   g_signal_connect (button, "clicked",
2071                     G_CALLBACK (cb_remove_subtree),
2072                     root_tree);
2073   gtk_box_pack_start(GTK_BOX(box2), button, TRUE, TRUE, 0);
2074   gtk_widget_show(button);
2075   tree_buttons->subtree_button = button;
2076
2077   /* create separator */
2078   separator = gtk_hseparator_new();
2079   gtk_box_pack_start(GTK_BOX(box1), separator, FALSE, FALSE, 0);
2080   gtk_widget_show(separator);
2081
2082   /* create button box */
2083   box2 = gtk_vbox_new(FALSE, 0);
2084   gtk_box_pack_start(GTK_BOX(box1), box2, FALSE, FALSE, 0);
2085   gtk_container_set_border_width(GTK_CONTAINER(box2), 5);
2086   gtk_widget_show(box2);
2087
2088   button = gtk_button_new_with_label("Close");
2089   gtk_box_pack_start(GTK_BOX(box2), button, TRUE, TRUE, 0);
2090   g_signal_connect_swapped (button, "clicked",
2091                             G_CALLBACK (gtk_widget_destroy),
2092                             window);
2093   gtk_widget_show(button);
2094
2095   gtk_widget_show(window);
2096 }
2097
2098 static void
2099 cb_create_tree(GtkWidget* w)
2100 {
2101   guint selection_mode = GTK_SELECTION_SINGLE;
2102   guint view_line;
2103   guint draw_line;
2104   guint no_root_item;
2105   guint nb_item;
2106   guint recursion_level;
2107
2108   /* get selection mode choice */
2109   if(GTK_TOGGLE_BUTTON(sTreeSampleSelection.single_button)->active)
2110     selection_mode = GTK_SELECTION_SINGLE;
2111   else
2112     if(GTK_TOGGLE_BUTTON(sTreeSampleSelection.browse_button)->active)
2113       selection_mode = GTK_SELECTION_BROWSE;
2114     else
2115       selection_mode = GTK_SELECTION_MULTIPLE;
2116
2117   /* get options choice */
2118   draw_line = GTK_TOGGLE_BUTTON(sTreeSampleSelection.draw_line_button)->active;
2119   view_line = GTK_TOGGLE_BUTTON(sTreeSampleSelection.view_line_button)->active;
2120   no_root_item = GTK_TOGGLE_BUTTON(sTreeSampleSelection.no_root_item_button)->active;
2121     
2122   /* get levels */
2123   nb_item = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(sTreeSampleSelection.nb_item_spinner));
2124   recursion_level = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(sTreeSampleSelection.recursion_spinner));
2125
2126   if (pow (nb_item, recursion_level) > 10000)
2127     {
2128       g_print ("%g total items? That will take a very long time. Try less\n",
2129                pow (nb_item, recursion_level));
2130       return;
2131     }
2132
2133   create_tree_sample(gtk_widget_get_screen (w),
2134                      selection_mode, draw_line, 
2135                      view_line, no_root_item, nb_item, recursion_level);
2136 }
2137
2138 void 
2139 create_tree_mode_window(GtkWidget *widget)
2140 {
2141   static GtkWidget* window;
2142   GtkWidget* box1;
2143   GtkWidget* box2;
2144   GtkWidget* box3;
2145   GtkWidget* box4;
2146   GtkWidget* box5;
2147   GtkWidget* button;
2148   GtkWidget* frame;
2149   GtkWidget* separator;
2150   GtkWidget* label;
2151   GtkWidget* spinner;
2152   GtkAdjustment *adj;
2153
2154   if (!window)
2155     {
2156       /* create toplevel window  */
2157       window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
2158       gtk_window_set_screen (GTK_WINDOW (window),
2159                              gtk_widget_get_screen (widget));
2160       gtk_window_set_title(GTK_WINDOW(window), "Set Tree Parameters");
2161       g_signal_connect (window, "destroy",
2162                         G_CALLBACK (gtk_widget_destroyed),
2163                         &window);
2164       box1 = gtk_vbox_new(FALSE, 0);
2165       gtk_container_add(GTK_CONTAINER(window), box1);
2166
2167       /* create upper box - selection box */
2168       box2 = gtk_vbox_new(FALSE, 5);
2169       gtk_box_pack_start(GTK_BOX(box1), box2, TRUE, TRUE, 0);
2170       gtk_container_set_border_width(GTK_CONTAINER(box2), 5);
2171
2172       box3 = gtk_hbox_new(FALSE, 5);
2173       gtk_box_pack_start(GTK_BOX(box2), box3, TRUE, TRUE, 0);
2174
2175       /* create selection mode frame */
2176       frame = gtk_frame_new("Selection Mode");
2177       gtk_box_pack_start(GTK_BOX(box3), frame, TRUE, TRUE, 0);
2178
2179       box4 = gtk_vbox_new(FALSE, 0);
2180       gtk_container_add(GTK_CONTAINER(frame), box4);
2181       gtk_container_set_border_width(GTK_CONTAINER(box4), 5);
2182
2183       /* create radio button */  
2184       button = gtk_radio_button_new_with_label(NULL, "SINGLE");
2185       gtk_box_pack_start(GTK_BOX(box4), button, TRUE, TRUE, 0);
2186       sTreeSampleSelection.single_button = button;
2187
2188       button = gtk_radio_button_new_with_label(gtk_radio_button_get_group (GTK_RADIO_BUTTON (button)),
2189                                                "BROWSE");
2190       gtk_box_pack_start(GTK_BOX(box4), button, TRUE, TRUE, 0);
2191       sTreeSampleSelection.browse_button = button;
2192
2193       button = gtk_radio_button_new_with_label(gtk_radio_button_get_group (GTK_RADIO_BUTTON (button)),
2194                                                "MULTIPLE");
2195       gtk_box_pack_start(GTK_BOX(box4), button, TRUE, TRUE, 0);
2196       sTreeSampleSelection.multiple_button = button;
2197
2198       sTreeSampleSelection.selection_mode_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (button));
2199
2200       /* create option mode frame */
2201       frame = gtk_frame_new("Options");
2202       gtk_box_pack_start(GTK_BOX(box3), frame, TRUE, TRUE, 0);
2203
2204       box4 = gtk_vbox_new(FALSE, 0);
2205       gtk_container_add(GTK_CONTAINER(frame), box4);
2206       gtk_container_set_border_width(GTK_CONTAINER(box4), 5);
2207
2208       /* create check button */
2209       button = gtk_check_button_new_with_label("Draw line");
2210       gtk_box_pack_start(GTK_BOX(box4), button, TRUE, TRUE, 0);
2211       gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
2212       sTreeSampleSelection.draw_line_button = button;
2213   
2214       button = gtk_check_button_new_with_label("View Line mode");
2215       gtk_box_pack_start(GTK_BOX(box4), button, TRUE, TRUE, 0);
2216       gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
2217       sTreeSampleSelection.view_line_button = button;
2218   
2219       button = gtk_check_button_new_with_label("Without Root item");
2220       gtk_box_pack_start(GTK_BOX(box4), button, TRUE, TRUE, 0);
2221       sTreeSampleSelection.no_root_item_button = button;
2222
2223       /* create recursion parameter */
2224       frame = gtk_frame_new("Size Parameters");
2225       gtk_box_pack_start(GTK_BOX(box2), frame, TRUE, TRUE, 0);
2226
2227       box4 = gtk_hbox_new(FALSE, 5);
2228       gtk_container_add(GTK_CONTAINER(frame), box4);
2229       gtk_container_set_border_width(GTK_CONTAINER(box4), 5);
2230
2231       /* create number of item spin button */
2232       box5 = gtk_hbox_new(FALSE, 5);
2233       gtk_box_pack_start(GTK_BOX(box4), box5, FALSE, FALSE, 0);
2234
2235       label = gtk_label_new("Number of items : ");
2236       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
2237       gtk_box_pack_start (GTK_BOX (box5), label, FALSE, TRUE, 0);
2238
2239       adj = (GtkAdjustment *) gtk_adjustment_new (DEFAULT_NUMBER_OF_ITEM, 1.0, 255.0, 1.0,
2240                                                   5.0, 0.0);
2241       spinner = gtk_spin_button_new (adj, 0, 0);
2242       gtk_box_pack_start (GTK_BOX (box5), spinner, FALSE, TRUE, 0);
2243       sTreeSampleSelection.nb_item_spinner = spinner;
2244   
2245       /* create recursion level spin button */
2246       box5 = gtk_hbox_new(FALSE, 5);
2247       gtk_box_pack_start(GTK_BOX(box4), box5, FALSE, FALSE, 0);
2248
2249       label = gtk_label_new("Depth : ");
2250       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
2251       gtk_box_pack_start (GTK_BOX (box5), label, FALSE, TRUE, 0);
2252
2253       adj = (GtkAdjustment *) gtk_adjustment_new (DEFAULT_RECURSION_LEVEL, 0.0, 255.0, 1.0,
2254                                                   5.0, 0.0);
2255       spinner = gtk_spin_button_new (adj, 0, 0);
2256       gtk_box_pack_start (GTK_BOX (box5), spinner, FALSE, TRUE, 0);
2257       sTreeSampleSelection.recursion_spinner = spinner;
2258   
2259       /* create horizontal separator */
2260       separator = gtk_hseparator_new();
2261       gtk_box_pack_start(GTK_BOX(box1), separator, FALSE, FALSE, 0);
2262
2263       /* create bottom button box */
2264       box2 = gtk_hbox_new(TRUE, 10);
2265       gtk_box_pack_start(GTK_BOX(box1), box2, FALSE, FALSE, 0);
2266       gtk_container_set_border_width(GTK_CONTAINER(box2), 5);
2267
2268       button = gtk_button_new_with_label("Create Tree");
2269       gtk_box_pack_start(GTK_BOX(box2), button, TRUE, TRUE, 0);
2270       g_signal_connect (button, "clicked",
2271                         G_CALLBACK (cb_create_tree), NULL);
2272
2273       button = gtk_button_new_with_label("Close");
2274       gtk_box_pack_start(GTK_BOX(box2), button, TRUE, TRUE, 0);
2275       g_signal_connect_swapped (button, "clicked",
2276                                 G_CALLBACK (gtk_widget_destroy),
2277                                 window);
2278     }
2279   if (!gtk_widget_get_visible (window))
2280     gtk_widget_show_all (window);
2281   else
2282     gtk_widget_destroy (window);
2283 }
2284
2285 /*
2286  * Gridded geometry
2287  */
2288 #define GRID_SIZE 20
2289 #define DEFAULT_GEOMETRY "10x10"
2290
2291 static gboolean
2292 gridded_geometry_expose (GtkWidget      *widget,
2293                          GdkEventExpose *event)
2294 {
2295   int i, j;
2296
2297   gdk_draw_rectangle (widget->window, widget->style->base_gc[widget->state], TRUE,
2298                       0, 0, widget->allocation.width, widget->allocation.height);
2299   
2300   for (i = 0 ; i * GRID_SIZE < widget->allocation.width; i++)
2301     for (j = 0 ; j * GRID_SIZE < widget->allocation.height; j++)
2302       {
2303         if ((i + j) % 2 == 0)
2304           gdk_draw_rectangle (widget->window, widget->style->text_gc[widget->state], TRUE,
2305                               i * GRID_SIZE, j * GRID_SIZE, GRID_SIZE, GRID_SIZE);
2306       }
2307
2308   return FALSE;
2309 }
2310
2311 static void
2312 gridded_geometry_subresponse (GtkDialog *dialog,
2313                               gint       response_id,
2314                               gchar     *geometry_string)
2315 {
2316   if (response_id == GTK_RESPONSE_NONE)
2317     {
2318       gtk_widget_destroy (GTK_WIDGET (dialog));
2319     }
2320   else
2321     {
2322       if (!gtk_window_parse_geometry (GTK_WINDOW (dialog), geometry_string))
2323         {
2324           g_print ("Can't parse geometry string %s\n", geometry_string);
2325           gtk_window_parse_geometry (GTK_WINDOW (dialog), DEFAULT_GEOMETRY);
2326         }
2327     }
2328 }
2329
2330 static void
2331 gridded_geometry_response (GtkDialog *dialog,
2332                            gint       response_id,
2333                            GtkEntry  *entry)
2334 {
2335   if (response_id == GTK_RESPONSE_NONE)
2336     {
2337       gtk_widget_destroy (GTK_WIDGET (dialog));
2338     }
2339   else
2340     {
2341       gchar *geometry_string = g_strdup (gtk_entry_get_text (entry));
2342       gchar *title = g_strdup_printf ("Gridded window at: %s", geometry_string);
2343       GtkWidget *window;
2344       GtkWidget *drawing_area;
2345       GtkWidget *box;
2346       GdkGeometry geometry;
2347       
2348       window = gtk_dialog_new_with_buttons (title,
2349                                             NULL, 0,
2350                                             "Reset", 1,
2351                                             GTK_STOCK_CLOSE, GTK_RESPONSE_NONE,
2352                                             NULL);
2353
2354       gtk_window_set_screen (GTK_WINDOW (window), 
2355                              gtk_widget_get_screen (GTK_WIDGET (dialog)));
2356       g_free (title);
2357       g_signal_connect (window, "response",
2358                         G_CALLBACK (gridded_geometry_subresponse), geometry_string);
2359
2360       box = gtk_vbox_new (FALSE, 0);
2361       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), box, TRUE, TRUE, 0);
2362       
2363       gtk_container_set_border_width (GTK_CONTAINER (box), 7);
2364       
2365       drawing_area = gtk_drawing_area_new ();
2366       g_signal_connect (drawing_area, "expose_event",
2367                         G_CALLBACK (gridded_geometry_expose), NULL);
2368       gtk_box_pack_start (GTK_BOX (box), drawing_area, TRUE, TRUE, 0);
2369
2370       /* Gross hack to work around bug 68668... if we set the size request
2371        * large enough, then  the current
2372        *
2373        *   request_of_window - request_of_geometry_widget
2374        *
2375        * method of getting the base size works more or less works.
2376        */
2377       gtk_widget_set_size_request (drawing_area, 2000, 2000);
2378
2379       geometry.base_width = 0;
2380       geometry.base_height = 0;
2381       geometry.min_width = 2 * GRID_SIZE;
2382       geometry.min_height = 2 * GRID_SIZE;
2383       geometry.width_inc = GRID_SIZE;
2384       geometry.height_inc = GRID_SIZE;
2385
2386       gtk_window_set_geometry_hints (GTK_WINDOW (window), drawing_area,
2387                                      &geometry,
2388                                      GDK_HINT_BASE_SIZE | GDK_HINT_MIN_SIZE | GDK_HINT_RESIZE_INC);
2389
2390       if (!gtk_window_parse_geometry (GTK_WINDOW (window), geometry_string))
2391         {
2392           g_print ("Can't parse geometry string %s\n", geometry_string);
2393           gtk_window_parse_geometry (GTK_WINDOW (window), DEFAULT_GEOMETRY);
2394         }
2395
2396       gtk_widget_show_all (window);
2397     }
2398 }
2399
2400 static void 
2401 create_gridded_geometry (GtkWidget *widget)
2402 {
2403   static GtkWidget *window = NULL;
2404   gpointer window_ptr;
2405   GtkWidget *entry;
2406   GtkWidget *label;
2407
2408   if (!window)
2409     {
2410       window = gtk_dialog_new_with_buttons ("Gridded Geometry",
2411                                             NULL, 0,
2412                                             "Create", 1,
2413                                             GTK_STOCK_CLOSE, GTK_RESPONSE_NONE,
2414                                             NULL);
2415       
2416       gtk_window_set_screen (GTK_WINDOW (window),
2417                              gtk_widget_get_screen (widget));
2418
2419       label = gtk_label_new ("Geometry string:");
2420       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), label, FALSE, FALSE, 0);
2421
2422       entry = gtk_entry_new ();
2423       gtk_entry_set_text (GTK_ENTRY (entry), DEFAULT_GEOMETRY);
2424       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), entry, FALSE, FALSE, 0);
2425
2426       g_signal_connect (window, "response",
2427                         G_CALLBACK (gridded_geometry_response), entry);
2428       window_ptr = &window;
2429       g_object_add_weak_pointer (G_OBJECT (window), window_ptr);
2430
2431       gtk_widget_show_all (window);
2432     }
2433   else
2434     gtk_widget_destroy (window);
2435 }
2436
2437 /*
2438  * GtkHandleBox
2439  */
2440
2441 static void
2442 handle_box_child_signal (GtkHandleBox *hb,
2443                          GtkWidget    *child,
2444                          const gchar  *action)
2445 {
2446   printf ("%s: child <%s> %sed\n",
2447           g_type_name (G_OBJECT_TYPE (hb)),
2448           g_type_name (G_OBJECT_TYPE (child)),
2449           action);
2450 }
2451
2452 static void
2453 create_handle_box (GtkWidget *widget)
2454 {
2455   static GtkWidget* window = NULL;
2456   GtkWidget *handle_box;
2457   GtkWidget *handle_box2;
2458   GtkWidget *vbox;
2459   GtkWidget *hbox;
2460   GtkWidget *toolbar;
2461   GtkWidget *label;
2462   GtkWidget *separator;
2463
2464   if (!window)
2465   {
2466     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
2467     
2468     gtk_window_set_screen (GTK_WINDOW (window),
2469                            gtk_widget_get_screen (widget));
2470     gtk_window_set_modal (GTK_WINDOW (window), FALSE);
2471     gtk_window_set_title (GTK_WINDOW (window),
2472                           "Handle Box Test");
2473     gtk_window_set_resizable (GTK_WINDOW (window), TRUE);
2474     
2475     g_signal_connect (window, "destroy",
2476                       G_CALLBACK (gtk_widget_destroyed),
2477                       &window);
2478     
2479     gtk_container_set_border_width (GTK_CONTAINER (window), 20);
2480
2481     vbox = gtk_vbox_new (FALSE, 0);
2482     gtk_container_add (GTK_CONTAINER (window), vbox);
2483     gtk_widget_show (vbox);
2484
2485     label = gtk_label_new ("Above");
2486     gtk_container_add (GTK_CONTAINER (vbox), label);
2487     gtk_widget_show (label);
2488
2489     separator = gtk_hseparator_new ();
2490     gtk_container_add (GTK_CONTAINER (vbox), separator);
2491     gtk_widget_show (separator);
2492     
2493     hbox = gtk_hbox_new (FALSE, 10);
2494     gtk_container_add (GTK_CONTAINER (vbox), hbox);
2495     gtk_widget_show (hbox);
2496
2497     separator = gtk_hseparator_new ();
2498     gtk_container_add (GTK_CONTAINER (vbox), separator);
2499     gtk_widget_show (separator);
2500
2501     label = gtk_label_new ("Below");
2502     gtk_container_add (GTK_CONTAINER (vbox), label);
2503     gtk_widget_show (label);
2504
2505     handle_box = gtk_handle_box_new ();
2506     gtk_box_pack_start (GTK_BOX (hbox), handle_box, FALSE, FALSE, 0);
2507     g_signal_connect (handle_box,
2508                       "child_attached",
2509                       G_CALLBACK (handle_box_child_signal),
2510                       "attached");
2511     g_signal_connect (handle_box,
2512                       "child_detached",
2513                       G_CALLBACK (handle_box_child_signal),
2514                       "detached");
2515     gtk_widget_show (handle_box);
2516
2517     toolbar = make_toolbar (window);
2518     
2519     gtk_container_add (GTK_CONTAINER (handle_box), toolbar);
2520     gtk_widget_show (toolbar);
2521
2522     handle_box = gtk_handle_box_new ();
2523     gtk_box_pack_start (GTK_BOX (hbox), handle_box, FALSE, FALSE, 0);
2524     g_signal_connect (handle_box,
2525                       "child_attached",
2526                       G_CALLBACK (handle_box_child_signal),
2527                       "attached");
2528     g_signal_connect (handle_box,
2529                       "child_detached",
2530                       G_CALLBACK (handle_box_child_signal),
2531                       "detached");
2532     gtk_widget_show (handle_box);
2533
2534     handle_box2 = gtk_handle_box_new ();
2535     gtk_container_add (GTK_CONTAINER (handle_box), handle_box2);
2536     g_signal_connect (handle_box2,
2537                       "child_attached",
2538                       G_CALLBACK (handle_box_child_signal),
2539                       "attached");
2540     g_signal_connect (handle_box2,
2541                       "child_detached",
2542                       G_CALLBACK (handle_box_child_signal),
2543                       "detached");
2544     gtk_widget_show (handle_box2);
2545
2546     hbox = g_object_new (GTK_TYPE_HBOX, "visible", 1, "parent", handle_box2, NULL);
2547     label = gtk_label_new ("Fooo!");
2548     gtk_container_add (GTK_CONTAINER (hbox), label);
2549     gtk_widget_show (label);
2550     g_object_new (GTK_TYPE_ARROW, "visible", 1, "parent", hbox, NULL);
2551   }
2552
2553   if (!gtk_widget_get_visible (window))
2554     gtk_widget_show (window);
2555   else
2556     gtk_widget_destroy (window);
2557 }
2558
2559 /*
2560  * Test for getting an image from a drawable
2561  */
2562
2563 struct GetImageData
2564 {
2565   GtkWidget *src;
2566   GtkWidget *snap;
2567   GtkWidget *sw;
2568 };
2569
2570 static void
2571 take_snapshot (GtkWidget *button,
2572                gpointer data)
2573 {
2574   struct GetImageData *gid = data;
2575   GdkRectangle visible;
2576   int width_fraction;
2577   int height_fraction;
2578   GdkGC *gc;
2579   GdkGC *black_gc;
2580   GdkColor color = { 0, 30000, 0, 0 };
2581   GdkRectangle target;
2582   GdkImage *shot;
2583   
2584   /* Do some begin_paint_rect on some random rects, draw some
2585    * distinctive stuff into those rects, then take the snapshot.
2586    * figure out whether any rects were overlapped and report to
2587    * user.
2588    */
2589
2590   visible = gid->sw->allocation;
2591
2592   visible.x = gtk_scrolled_window_get_hadjustment (GTK_SCROLLED_WINDOW (gid->sw))->value;
2593   visible.y = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (gid->sw))->value;
2594   
2595   width_fraction = visible.width / 4;
2596   height_fraction = visible.height / 4;
2597
2598   gc = gdk_gc_new (gid->src->window);
2599   black_gc = gid->src->style->black_gc;
2600   
2601   gdk_gc_set_rgb_fg_color (gc, &color);
2602
2603     
2604   target.x = visible.x + width_fraction;
2605   target.y = visible.y + height_fraction * 3;
2606   target.width = width_fraction;
2607   target.height = height_fraction / 2;
2608   
2609   gdk_window_begin_paint_rect (gid->src->window,
2610                                &target);
2611
2612   gdk_draw_rectangle (gid->src->window,
2613                       gc,
2614                       TRUE,
2615                       target.x, target.y,
2616                       target.width, target.height);
2617
2618   gdk_draw_rectangle (gid->src->window,
2619                       black_gc,
2620                       FALSE,
2621                       target.x + 10, target.y + 10,
2622                       target.width - 20, target.height - 20);
2623   
2624   target.x = visible.x + width_fraction;
2625   target.y = visible.y + height_fraction;
2626   target.width = width_fraction;
2627   target.height = height_fraction;
2628   
2629   gdk_window_begin_paint_rect (gid->src->window,
2630                                &target);
2631
2632   gdk_draw_rectangle (gid->src->window,
2633                       gc,
2634                       TRUE,
2635                       target.x, target.y,
2636                       target.width, target.height);
2637
2638   gdk_draw_rectangle (gid->src->window,
2639                       black_gc,
2640                       FALSE,
2641                       target.x + 10, target.y + 10,
2642                       target.width - 20, target.height - 20);
2643   
2644   target.x = visible.x + width_fraction * 3;
2645   target.y = visible.y + height_fraction;
2646   target.width = width_fraction / 2;
2647   target.height = height_fraction;
2648   
2649   gdk_window_begin_paint_rect (gid->src->window,
2650                                &target);
2651
2652   gdk_draw_rectangle (gid->src->window,
2653                       gc,
2654                       TRUE,
2655                       target.x, target.y,
2656                       target.width, target.height);
2657
2658   gdk_draw_rectangle (gid->src->window,
2659                       black_gc,
2660                       FALSE,
2661                       target.x + 10, target.y + 10,
2662                       target.width - 20, target.height - 20);
2663   
2664   target.x = visible.x + width_fraction * 2;
2665   target.y = visible.y + height_fraction * 2;
2666   target.width = width_fraction / 4;
2667   target.height = height_fraction / 4;
2668   
2669   gdk_window_begin_paint_rect (gid->src->window,
2670                                &target);
2671
2672   gdk_draw_rectangle (gid->src->window,
2673                       gc,
2674                       TRUE,
2675                       target.x, target.y,
2676                       target.width, target.height);
2677
2678   gdk_draw_rectangle (gid->src->window,
2679                       black_gc,
2680                       FALSE,
2681                       target.x + 10, target.y + 10,
2682                       target.width - 20, target.height - 20);  
2683
2684   target.x += target.width / 2;
2685   target.y += target.width / 2;
2686   
2687   gdk_window_begin_paint_rect (gid->src->window,
2688                                &target);
2689
2690   gdk_draw_rectangle (gid->src->window,
2691                       gc,
2692                       TRUE,
2693                       target.x, target.y,
2694                       target.width, target.height);
2695
2696   gdk_draw_rectangle (gid->src->window,
2697                       black_gc,
2698                       FALSE,
2699                       target.x + 10, target.y + 10,
2700                       target.width - 20, target.height - 20);
2701   
2702   /* Screen shot area */
2703
2704   target.x = visible.x + width_fraction * 1.5;
2705   target.y = visible.y + height_fraction * 1.5;
2706   target.width = width_fraction * 2;
2707   target.height = height_fraction * 2;  
2708
2709   shot = gdk_drawable_get_image (gid->src->window,
2710                                  target.x, target.y,
2711                                  target.width, target.height);
2712
2713   gtk_image_set_from_image (GTK_IMAGE (gid->snap),
2714                             shot, NULL);
2715
2716   g_object_unref (shot);
2717   
2718   gdk_window_end_paint (gid->src->window);
2719   gdk_window_end_paint (gid->src->window);
2720   gdk_window_end_paint (gid->src->window);
2721   gdk_window_end_paint (gid->src->window);
2722   gdk_window_end_paint (gid->src->window);
2723
2724   gdk_draw_rectangle (gid->src->window,
2725                       gid->src->style->black_gc,
2726                       FALSE,
2727                       target.x, target.y,
2728                       target.width, target.height);
2729   
2730   g_object_unref (gc);
2731 }
2732
2733 static gint
2734 image_source_expose (GtkWidget *da,
2735                      GdkEventExpose *event,
2736                      gpointer data)
2737 {
2738   int x = event->area.x;
2739   GdkColor red = { 0, 65535, 0, 0 };
2740   GdkColor green = { 0, 0, 65535, 0 };
2741   GdkColor blue = { 0, 0, 0, 65535 };
2742   GdkGC *gc;
2743
2744   gc = gdk_gc_new (event->window);
2745   
2746   while (x < (event->area.x + event->area.width))
2747     {
2748       switch (x % 7)
2749         {
2750         case 0:
2751         case 1:
2752         case 2:
2753           gdk_gc_set_rgb_fg_color (gc, &red);
2754           break;
2755
2756         case 3:
2757         case 4:
2758         case 5:
2759           gdk_gc_set_rgb_fg_color (gc, &green);
2760           break;
2761
2762         case 6:
2763         case 7:
2764         case 8:
2765           gdk_gc_set_rgb_fg_color (gc, &blue);
2766           break;
2767
2768         default:
2769           g_assert_not_reached ();
2770           break;
2771         }
2772
2773       gdk_draw_line (event->window,
2774                      gc,
2775                      x, event->area.y,
2776                      x, event->area.y + event->area.height);
2777       
2778       ++x;
2779     }
2780
2781   g_object_unref (gc);
2782   
2783   return TRUE;
2784 }
2785
2786 static void
2787 create_get_image (GtkWidget *widget)
2788 {
2789   static GtkWidget *window = NULL;
2790
2791   if (window)
2792     gtk_widget_destroy (window);
2793   else
2794     {
2795       GtkWidget *sw;
2796       GtkWidget *src;
2797       GtkWidget *snap;
2798       GtkWidget *hbox;
2799       GtkWidget *vbox;
2800       GtkWidget *button;
2801       struct GetImageData *gid;
2802
2803       gid = g_new (struct GetImageData, 1);
2804       
2805       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
2806       
2807       gtk_window_set_screen (GTK_WINDOW (window),
2808                              gtk_widget_get_screen (widget));
2809
2810       g_signal_connect (window,
2811                         "destroy",
2812                         G_CALLBACK (gtk_widget_destroyed),
2813                         &window);
2814
2815       g_object_set_data_full (G_OBJECT (window),
2816                               "testgtk-get-image-data",
2817                               gid,
2818                               g_free);
2819       
2820       hbox = gtk_hbox_new (FALSE, 0);
2821       
2822       gtk_container_add (GTK_CONTAINER (window), hbox);
2823       
2824       sw = gtk_scrolled_window_new (NULL, NULL);
2825       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
2826                                       GTK_POLICY_AUTOMATIC,
2827                                       GTK_POLICY_AUTOMATIC);
2828
2829       gid->sw = sw;
2830
2831       gtk_widget_set_size_request (sw, 400, 400);
2832       
2833       src = gtk_drawing_area_new ();
2834       gtk_widget_set_size_request (src, 10000, 10000);
2835
2836       g_signal_connect (src,
2837                         "expose_event",
2838                         G_CALLBACK (image_source_expose),
2839                         gid);
2840       
2841       gid->src = src;
2842       
2843       gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (sw),
2844                                              src);
2845       
2846       gtk_box_pack_start (GTK_BOX (hbox),
2847                           sw, TRUE, TRUE, 0);
2848
2849
2850       vbox = gtk_vbox_new (FALSE, 3);
2851
2852       snap = g_object_new (GTK_TYPE_IMAGE, NULL);
2853
2854       gid->snap = snap;
2855
2856       sw = gtk_scrolled_window_new (NULL, NULL);
2857       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
2858                                       GTK_POLICY_AUTOMATIC,
2859                                       GTK_POLICY_AUTOMATIC);
2860       gtk_widget_set_size_request (sw, 300, 300);
2861       
2862       gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (sw), snap);
2863
2864       gtk_box_pack_end (GTK_BOX (vbox), sw, FALSE, FALSE, 5);
2865
2866       button = gtk_button_new_with_label ("Get image from drawable");
2867
2868       g_signal_connect (button,
2869                         "clicked",
2870                         G_CALLBACK (take_snapshot),
2871                         gid);
2872       
2873       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
2874
2875       gtk_box_pack_end (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
2876       
2877       gtk_widget_show_all (window);
2878     }
2879 }
2880
2881 /* 
2882  * Label Demo
2883  */
2884 static void
2885 sensitivity_toggled (GtkWidget *toggle,
2886                      GtkWidget *widget)
2887 {
2888   gtk_widget_set_sensitive (widget,  GTK_TOGGLE_BUTTON (toggle)->active);  
2889 }
2890
2891 static GtkWidget*
2892 create_sensitivity_control (GtkWidget *widget)
2893 {
2894   GtkWidget *button;
2895
2896   button = gtk_toggle_button_new_with_label ("Sensitive");  
2897
2898   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
2899                                 gtk_widget_is_sensitive (widget));
2900   
2901   g_signal_connect (button,
2902                     "toggled",
2903                     G_CALLBACK (sensitivity_toggled),
2904                     widget);
2905   
2906   gtk_widget_show_all (button);
2907
2908   return button;
2909 }
2910
2911 static void
2912 set_selectable_recursive (GtkWidget *widget,
2913                           gboolean   setting)
2914 {
2915   if (GTK_IS_CONTAINER (widget))
2916     {
2917       GList *children;
2918       GList *tmp;
2919       
2920       children = gtk_container_get_children (GTK_CONTAINER (widget));
2921       tmp = children;
2922       while (tmp)
2923         {
2924           set_selectable_recursive (tmp->data, setting);
2925
2926           tmp = tmp->next;
2927         }
2928       g_list_free (children);
2929     }
2930   else if (GTK_IS_LABEL (widget))
2931     {
2932       gtk_label_set_selectable (GTK_LABEL (widget), setting);
2933     }
2934 }
2935
2936 static void
2937 selectable_toggled (GtkWidget *toggle,
2938                     GtkWidget *widget)
2939 {
2940   set_selectable_recursive (widget,
2941                             GTK_TOGGLE_BUTTON (toggle)->active);
2942 }
2943
2944 static GtkWidget*
2945 create_selectable_control (GtkWidget *widget)
2946 {
2947   GtkWidget *button;
2948
2949   button = gtk_toggle_button_new_with_label ("Selectable");  
2950
2951   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
2952                                 FALSE);
2953   
2954   g_signal_connect (button,
2955                     "toggled",
2956                     G_CALLBACK (selectable_toggled),
2957                     widget);
2958   
2959   gtk_widget_show_all (button);
2960
2961   return button;
2962 }
2963
2964 static void
2965 dialog_response (GtkWidget *dialog, gint response_id, GtkLabel *label)
2966 {
2967   const gchar *text;
2968
2969   gtk_widget_destroy (dialog);
2970
2971   text = "Some <a href=\"http://en.wikipedia.org/wiki/Text\" title=\"plain text\">text</a> may be marked up\n"
2972          "as hyperlinks, which can be clicked\n"
2973          "or activated via <a href=\"keynav\">keynav</a>.\n"
2974          "The links remain the same.";
2975   gtk_label_set_markup (label, text);
2976 }
2977
2978 static gboolean
2979 activate_link (GtkWidget *label, const gchar *uri, gpointer data)
2980 {
2981   if (g_strcmp0 (uri, "keynav") == 0)
2982     {
2983       GtkWidget *dialog;
2984
2985       dialog = gtk_message_dialog_new_with_markup (GTK_WINDOW (gtk_widget_get_toplevel (label)),
2986                                        GTK_DIALOG_DESTROY_WITH_PARENT,
2987                                        GTK_MESSAGE_INFO,
2988                                        GTK_BUTTONS_OK,
2989                                        "The term <i>keynav</i> is a shorthand for "
2990                                        "keyboard navigation and refers to the process of using a program "
2991                                        "(exclusively) via keyboard input.");
2992
2993       gtk_window_present (GTK_WINDOW (dialog));
2994
2995       g_signal_connect (dialog, "response", G_CALLBACK (dialog_response), label);
2996
2997       return TRUE;
2998     }
2999
3000   return FALSE;
3001 }
3002
3003 void create_labels (GtkWidget *widget)
3004 {
3005   static GtkWidget *window = NULL;
3006   GtkWidget *hbox;
3007   GtkWidget *vbox;
3008   GtkWidget *frame;
3009   GtkWidget *label;
3010   GtkWidget *button;
3011
3012   if (!window)
3013     {
3014       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3015
3016       gtk_window_set_screen (GTK_WINDOW (window),
3017                              gtk_widget_get_screen (widget));
3018
3019       g_signal_connect (window, "destroy",
3020                         G_CALLBACK (gtk_widget_destroyed),
3021                         &window);
3022
3023       gtk_window_set_title (GTK_WINDOW (window), "Label");
3024
3025       vbox = gtk_vbox_new (FALSE, 5);
3026       
3027       hbox = gtk_hbox_new (FALSE, 5);
3028       gtk_container_add (GTK_CONTAINER (window), vbox);
3029
3030       gtk_box_pack_end (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
3031
3032       button = create_sensitivity_control (hbox);
3033
3034       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
3035
3036       button = create_selectable_control (hbox);
3037
3038       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
3039       
3040       vbox = gtk_vbox_new (FALSE, 5);
3041       
3042       gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
3043       gtk_container_set_border_width (GTK_CONTAINER (window), 5);
3044
3045       frame = gtk_frame_new ("Normal Label");
3046       label = gtk_label_new ("This is a Normal label");
3047       gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_START);
3048       gtk_container_add (GTK_CONTAINER (frame), label);
3049       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3050
3051       frame = gtk_frame_new ("Multi-line Label");
3052       label = gtk_label_new ("This is a Multi-line label.\nSecond line\nThird line");
3053       gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_END);
3054       gtk_container_add (GTK_CONTAINER (frame), label);
3055       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3056
3057       frame = gtk_frame_new ("Left Justified Label");
3058       label = gtk_label_new ("This is a Left-Justified\nMulti-line label.\nThird      line");
3059       gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_MIDDLE);
3060       gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
3061       gtk_container_add (GTK_CONTAINER (frame), label);
3062       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3063
3064       frame = gtk_frame_new ("Right Justified Label");
3065       gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_START);
3066       label = gtk_label_new ("This is a Right-Justified\nMulti-line label.\nFourth line, (j/k)");
3067       gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_RIGHT);
3068       gtk_container_add (GTK_CONTAINER (frame), label);
3069       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3070
3071       frame = gtk_frame_new ("Internationalized Label");
3072       label = gtk_label_new (NULL);
3073       gtk_label_set_markup (GTK_LABEL (label),
3074                             "French (Fran\303\247ais) Bonjour, Salut\n"
3075                             "Korean (\355\225\234\352\270\200)   \354\225\210\353\205\225\355\225\230\354\204\270\354\232\224, \354\225\210\353\205\225\355\225\230\354\213\255\353\213\210\352\271\214\n"
3076                             "Russian (\320\240\321\203\321\201\321\201\320\272\320\270\320\271) \320\227\320\264\321\200\320\260\320\262\321\201\321\202\320\262\321\203\320\271\321\202\320\265!\n"
3077                             "Chinese (Simplified) <span lang=\"zh-cn\">\345\205\203\346\260\224 \345\274\200\345\217\221</span>\n"
3078                             "Chinese (Traditional) <span lang=\"zh-tw\">\345\205\203\346\260\243        \351\226\213\347\231\274</span>\n"
3079                             "Japanese <span lang=\"ja\">\345\205\203\346\260\227        \351\226\213\347\231\272</span>");
3080       gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
3081       gtk_container_add (GTK_CONTAINER (frame), label);
3082       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3083
3084       frame = gtk_frame_new ("Bidirection Label");
3085       label = gtk_label_new ("\342\200\217Arabic        \330\247\331\204\330\263\331\204\330\247\331\205 \330\271\331\204\331\212\331\203\331\205\n"
3086                              "\342\200\217Hebrew        \327\251\327\234\327\225\327\235");
3087       gtk_container_add (GTK_CONTAINER (frame), label);
3088       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3089
3090       frame = gtk_frame_new ("Links in a label");
3091       label = gtk_label_new ("Some <a href=\"http://en.wikipedia.org/wiki/Text\" title=\"plain text\">text</a> may be marked up\n"
3092                              "as hyperlinks, which can be clicked\n"
3093                              "or activated via <a href=\"keynav\">keynav</a>");
3094       gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
3095       gtk_container_add (GTK_CONTAINER (frame), label);
3096       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3097       g_signal_connect (label, "activate-link", G_CALLBACK (activate_link), NULL);
3098
3099       vbox = gtk_vbox_new (FALSE, 5);
3100       gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
3101       frame = gtk_frame_new ("Line wrapped label");
3102       label = gtk_label_new ("This is an example of a line-wrapped label.  It should not be taking "\
3103                              "up the entire             "/* big space to test spacing */\
3104                              "width allocated to it, but automatically wraps the words to fit.  "\
3105                              "The time has come, for all good men, to come to the aid of their party.  "\
3106                              "The sixth sheik's six sheep's sick.\n"\
3107                              "     It supports multiple paragraphs correctly, and  correctly   adds "\
3108                              "many          extra  spaces. ");
3109
3110       gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
3111       gtk_container_add (GTK_CONTAINER (frame), label);
3112       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3113
3114       frame = gtk_frame_new ("Filled, wrapped label");
3115       label = gtk_label_new ("This is an example of a line-wrapped, filled label.  It should be taking "\
3116                              "up the entire              width allocated to it.  Here is a seneance to prove "\
3117                              "my point.  Here is another sentence. "\
3118                              "Here comes the sun, do de do de do.\n"\
3119                              "    This is a new paragraph.\n"\
3120                              "    This is another newer, longer, better paragraph.  It is coming to an end, "\
3121                              "unfortunately.");
3122       gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_FILL);
3123       gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
3124       gtk_container_add (GTK_CONTAINER (frame), label);
3125       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3126
3127       frame = gtk_frame_new ("Underlined label");
3128       label = gtk_label_new ("This label is underlined!\n"
3129                              "This one is underlined (\343\201\223\343\202\223\343\201\253\343\201\241\343\201\257) in quite a funky fashion");
3130       gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
3131       gtk_label_set_pattern (GTK_LABEL (label), "_________________________ _ _________ _ _____ _ __ __  ___ ____ _____");
3132       gtk_container_add (GTK_CONTAINER (frame), label);
3133       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3134
3135       frame = gtk_frame_new ("Markup label");
3136       label = gtk_label_new (NULL);
3137
3138       /* There's also a gtk_label_set_markup() without accel if you
3139        * don't have an accelerator key
3140        */
3141       gtk_label_set_markup_with_mnemonic (GTK_LABEL (label),
3142                                           "This <span foreground=\"blue\" background=\"orange\">label</span> has "
3143                                           "<b>markup</b> _such as "
3144                                           "<big><i>Big Italics</i></big>\n"
3145                                           "<tt>Monospace font</tt>\n"
3146                                           "<u>Underline!</u>\n"
3147                                           "foo\n"
3148                                           "<span foreground=\"green\" background=\"red\">Ugly colors</span>\n"
3149                                           "and nothing on this line,\n"
3150                                           "or this.\n"
3151                                           "or this either\n"
3152                                           "or even on this one\n"
3153                                           "la <big>la <big>la <big>la <big>la</big></big></big></big>\n"
3154                                           "but this _word is <span foreground=\"purple\"><big>purple</big></span>\n"
3155                                           "<span underline=\"double\">We like <sup>superscript</sup> and <sub>subscript</sub> too</span>");
3156
3157       g_assert (gtk_label_get_mnemonic_keyval (GTK_LABEL (label)) == GDK_s);
3158       
3159       gtk_container_add (GTK_CONTAINER (frame), label);
3160       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
3161     }
3162   
3163   if (!gtk_widget_get_visible (window))
3164     gtk_widget_show_all (window);
3165   else
3166     gtk_widget_destroy (window);
3167 }
3168
3169 static void
3170 on_angle_scale_changed (GtkRange *range,
3171                         GtkLabel *label)
3172 {
3173   gtk_label_set_angle (GTK_LABEL (label), gtk_range_get_value (range));
3174 }
3175
3176 static void
3177 create_rotated_label (GtkWidget *widget)
3178 {
3179   static GtkWidget *window = NULL;
3180   GtkWidget *vbox;
3181   GtkWidget *hscale;
3182   GtkWidget *label;  
3183   GtkWidget *scale_label;  
3184   GtkWidget *scale_hbox;  
3185
3186   if (!window)
3187     {
3188       window = gtk_dialog_new_with_buttons ("Rotated Label",
3189                                             GTK_WINDOW (gtk_widget_get_toplevel (widget)), 0,
3190                                             GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
3191                                             NULL);
3192
3193       gtk_window_set_resizable (GTK_WINDOW (window), TRUE);
3194
3195       gtk_window_set_screen (GTK_WINDOW (window),
3196                              gtk_widget_get_screen (widget));
3197
3198       g_signal_connect (window, "response",
3199                         G_CALLBACK (gtk_object_destroy), NULL);
3200       g_signal_connect (window, "destroy",
3201                         G_CALLBACK (gtk_widget_destroyed), &window);
3202
3203       vbox = gtk_vbox_new (FALSE, 5);
3204       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), vbox, TRUE, TRUE, 0);
3205       gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
3206
3207       label = gtk_label_new (NULL);
3208       gtk_label_set_markup (GTK_LABEL (label), "Hello World\n<i>Rotate</i> <span underline='single' foreground='blue'>me</span>");
3209       gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
3210
3211       scale_hbox = gtk_hbox_new (FALSE, 0);
3212       gtk_box_pack_start (GTK_BOX (vbox), scale_hbox, FALSE, FALSE, 0);
3213       
3214       scale_label = gtk_label_new (NULL);
3215       gtk_label_set_markup (GTK_LABEL (scale_label), "<i>Angle: </i>");
3216       gtk_box_pack_start (GTK_BOX (scale_hbox), scale_label, FALSE, FALSE, 0);
3217
3218       hscale = gtk_hscale_new_with_range (0, 360, 5);
3219       g_signal_connect (hscale, "value-changed",
3220                         G_CALLBACK (on_angle_scale_changed), label);
3221       
3222       gtk_range_set_value (GTK_RANGE (hscale), 45);
3223       gtk_widget_set_usize (hscale, 200, -1);
3224       gtk_box_pack_start (GTK_BOX (scale_hbox), hscale, TRUE, TRUE, 0);
3225     }
3226   
3227   if (!gtk_widget_get_visible (window))
3228     gtk_widget_show_all (window);
3229   else
3230     gtk_widget_destroy (window);
3231 }
3232
3233 #define DEFAULT_TEXT_RADIUS 200
3234
3235 static void
3236 on_rotated_text_unrealize (GtkWidget *widget)
3237 {
3238   g_object_set_data (G_OBJECT (widget), "text-gc", NULL);
3239 }
3240
3241 static gboolean
3242 on_rotated_text_expose (GtkWidget      *widget,
3243                         GdkEventExpose *event,
3244                         GdkPixbuf      *tile_pixbuf)
3245 {
3246   static const gchar *words[] = { "The", "grand", "old", "Duke", "of", "York",
3247                                   "had", "10,000", "men" };
3248   PangoRenderer *renderer;
3249   GdkGC *gc;
3250   int n_words;
3251   int i;
3252   double radius;
3253   PangoMatrix matrix = PANGO_MATRIX_INIT;
3254   PangoLayout *layout;
3255   PangoContext *context;
3256   PangoFontDescription *desc;
3257
3258   gc = g_object_get_data (G_OBJECT (widget), "text-gc");
3259   if (!gc)
3260     {
3261       static GdkColor black = { 0, 0, 0, 0 };
3262       
3263       gc = gdk_gc_new (widget->window);
3264       gdk_gc_set_rgb_fg_color (gc, &black);
3265       
3266       if (tile_pixbuf)
3267         {
3268           GdkPixmap *tile;
3269           
3270           gint width = gdk_pixbuf_get_width (tile_pixbuf);
3271           gint height = gdk_pixbuf_get_height (tile_pixbuf);
3272           
3273           tile = gdk_pixmap_new (widget->window, width, height, -1);
3274           gdk_draw_pixbuf (tile, gc, tile_pixbuf,
3275                            0, 0, 0, 0, width, height,
3276                            GDK_RGB_DITHER_NORMAL, 0, 0);
3277
3278           gdk_gc_set_tile (gc, tile);
3279           gdk_gc_set_fill (gc, GDK_TILED);
3280
3281           g_object_unref (tile);
3282         }
3283
3284       g_object_set_data_full (G_OBJECT (widget), "text-gc", gc, (GDestroyNotify)g_object_unref);
3285     }
3286
3287   renderer = gdk_pango_renderer_get_default (gtk_widget_get_screen (widget));
3288   gdk_pango_renderer_set_drawable (GDK_PANGO_RENDERER (renderer), widget->window);
3289   gdk_pango_renderer_set_gc (GDK_PANGO_RENDERER (renderer), gc);
3290
3291   radius = MIN (widget->allocation.width, widget->allocation.height) / 2.;
3292
3293   pango_matrix_translate (&matrix,
3294                           radius + (widget->allocation.width - 2 * radius) / 2,
3295                           radius + (widget->allocation.height - 2 * radius) / 2);
3296   pango_matrix_scale (&matrix, radius / DEFAULT_TEXT_RADIUS, radius / DEFAULT_TEXT_RADIUS);
3297
3298   context = gtk_widget_get_pango_context (widget);
3299   layout = pango_layout_new (context);
3300   desc = pango_font_description_from_string ("Sans Bold 30");
3301   pango_layout_set_font_description (layout, desc);
3302   pango_font_description_free (desc);
3303     
3304   n_words = G_N_ELEMENTS (words);
3305   for (i = 0; i < n_words; i++)
3306     {
3307       PangoMatrix rotated_matrix = matrix;
3308       int width, height;
3309       
3310       pango_matrix_rotate (&rotated_matrix, - (360. * i) / n_words);
3311
3312       pango_context_set_matrix (context, &rotated_matrix);
3313       pango_layout_context_changed (layout);
3314       pango_layout_set_text (layout, words[i], -1);
3315       
3316       pango_layout_get_size (layout, &width, &height);
3317
3318       pango_renderer_draw_layout (renderer, layout,
3319                                   - width / 2, - DEFAULT_TEXT_RADIUS * PANGO_SCALE);
3320     }
3321
3322   gdk_pango_renderer_set_drawable (GDK_PANGO_RENDERER (renderer), NULL);
3323   gdk_pango_renderer_set_gc (GDK_PANGO_RENDERER (renderer), NULL);
3324   
3325   g_object_unref (layout);
3326
3327   return FALSE;
3328 }
3329
3330 static void
3331 create_rotated_text (GtkWidget *widget)
3332 {
3333   static GtkWidget *window = NULL;
3334
3335   if (!window)
3336     {
3337       const GdkColor white = { 0, 0xffff, 0xffff, 0xffff };
3338       GtkRequisition requisition;
3339       GtkWidget *drawing_area;
3340       GdkPixbuf *tile_pixbuf;
3341
3342       window = gtk_dialog_new_with_buttons ("Rotated Text",
3343                                             GTK_WINDOW (gtk_widget_get_toplevel (widget)), 0,
3344                                             GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
3345                                             NULL);
3346
3347       gtk_window_set_resizable (GTK_WINDOW (window), TRUE);
3348
3349       gtk_window_set_screen (GTK_WINDOW (window),
3350                              gtk_widget_get_screen (widget));
3351
3352       g_signal_connect (window, "response",
3353                         G_CALLBACK (gtk_object_destroy), NULL);
3354       g_signal_connect (window, "destroy",
3355                         G_CALLBACK (gtk_widget_destroyed), &window);
3356
3357       drawing_area = gtk_drawing_area_new ();
3358       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), drawing_area, TRUE, TRUE, 0);
3359       gtk_widget_modify_bg (drawing_area, GTK_STATE_NORMAL, &white);
3360
3361       tile_pixbuf = gdk_pixbuf_new_from_file ("marble.xpm", NULL);
3362       
3363       g_signal_connect (drawing_area, "expose-event",
3364                         G_CALLBACK (on_rotated_text_expose), tile_pixbuf);
3365       g_signal_connect (drawing_area, "unrealize",
3366                         G_CALLBACK (on_rotated_text_unrealize), NULL);
3367
3368       gtk_widget_show_all (GTK_BIN (window)->child);
3369       
3370       gtk_widget_set_size_request (drawing_area, DEFAULT_TEXT_RADIUS * 2, DEFAULT_TEXT_RADIUS * 2);
3371       gtk_widget_size_request (window, &requisition);
3372       gtk_widget_set_size_request (drawing_area, -1, -1);
3373       gtk_window_resize (GTK_WINDOW (window), requisition.width, requisition.height);
3374     }
3375   
3376   if (!gtk_widget_get_visible (window))
3377     gtk_widget_show (window);
3378   else
3379     gtk_widget_destroy (window);
3380 }
3381
3382 /*
3383  * Reparent demo
3384  */
3385
3386 static void
3387 reparent_label (GtkWidget *widget,
3388                 GtkWidget *new_parent)
3389 {
3390   GtkWidget *label;
3391
3392   label = g_object_get_data (G_OBJECT (widget), "user_data");
3393
3394   gtk_widget_reparent (label, new_parent);
3395 }
3396
3397 static void
3398 set_parent_signal (GtkWidget *child,
3399                    GtkWidget *old_parent,
3400                    gpointer   func_data)
3401 {
3402   g_message ("set_parent for \"%s\": new parent: \"%s\", old parent: \"%s\", data: %d\n",
3403              g_type_name (G_OBJECT_TYPE (child)),
3404              child->parent ? g_type_name (G_OBJECT_TYPE (child->parent)) : "NULL",
3405              old_parent ? g_type_name (G_OBJECT_TYPE (old_parent)) : "NULL",
3406              GPOINTER_TO_INT (func_data));
3407 }
3408
3409 static void
3410 create_reparent (GtkWidget *widget)
3411 {
3412   static GtkWidget *window = NULL;
3413   GtkWidget *box1;
3414   GtkWidget *box2;
3415   GtkWidget *box3;
3416   GtkWidget *frame;
3417   GtkWidget *button;
3418   GtkWidget *label;
3419   GtkWidget *separator;
3420   GtkWidget *event_box;
3421
3422   if (!window)
3423     {
3424       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3425
3426       gtk_window_set_screen (GTK_WINDOW (window),
3427                              gtk_widget_get_screen (widget));
3428
3429       g_signal_connect (window, "destroy",
3430                         G_CALLBACK (gtk_widget_destroyed),
3431                         &window);
3432
3433       gtk_window_set_title (GTK_WINDOW (window), "reparent");
3434       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
3435
3436       box1 = gtk_vbox_new (FALSE, 0);
3437       gtk_container_add (GTK_CONTAINER (window), box1);
3438
3439       box2 = gtk_hbox_new (FALSE, 5);
3440       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
3441       gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
3442
3443       label = gtk_label_new ("Hello World");
3444
3445       frame = gtk_frame_new ("Frame 1");
3446       gtk_box_pack_start (GTK_BOX (box2), frame, TRUE, TRUE, 0);
3447
3448       box3 = gtk_vbox_new (FALSE, 5);
3449       gtk_container_set_border_width (GTK_CONTAINER (box3), 5);
3450       gtk_container_add (GTK_CONTAINER (frame), box3);
3451
3452       button = gtk_button_new_with_label ("switch");
3453       g_object_set_data (G_OBJECT (button), "user_data", label);
3454       gtk_box_pack_start (GTK_BOX (box3), button, FALSE, TRUE, 0);
3455
3456       event_box = gtk_event_box_new ();
3457       gtk_box_pack_start (GTK_BOX (box3), event_box, FALSE, TRUE, 0);
3458       gtk_container_add (GTK_CONTAINER (event_box), label);
3459                          
3460       g_signal_connect (button, "clicked",
3461                         G_CALLBACK (reparent_label),
3462                         event_box);
3463       
3464       g_signal_connect (label, "parent_set",
3465                         G_CALLBACK (set_parent_signal),
3466                         GINT_TO_POINTER (42));
3467
3468       frame = gtk_frame_new ("Frame 2");
3469       gtk_box_pack_start (GTK_BOX (box2), frame, TRUE, TRUE, 0);
3470
3471       box3 = gtk_vbox_new (FALSE, 5);
3472       gtk_container_set_border_width (GTK_CONTAINER (box3), 5);
3473       gtk_container_add (GTK_CONTAINER (frame), box3);
3474
3475       button = gtk_button_new_with_label ("switch");
3476       g_object_set_data (G_OBJECT (button), "user_data", label);
3477       gtk_box_pack_start (GTK_BOX (box3), button, FALSE, TRUE, 0);
3478       
3479       event_box = gtk_event_box_new ();
3480       gtk_box_pack_start (GTK_BOX (box3), event_box, FALSE, TRUE, 0);
3481
3482       g_signal_connect (button, "clicked",
3483                         G_CALLBACK (reparent_label),
3484                         event_box);
3485
3486       separator = gtk_hseparator_new ();
3487       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
3488
3489       box2 = gtk_vbox_new (FALSE, 10);
3490       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
3491       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
3492
3493       button = gtk_button_new_with_label ("close");
3494       g_signal_connect_swapped (button, "clicked",
3495                                 G_CALLBACK (gtk_widget_destroy), window);
3496       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
3497       gtk_widget_set_can_default (button, TRUE);
3498       gtk_widget_grab_default (button);
3499     }
3500
3501   if (!gtk_widget_get_visible (window))
3502     gtk_widget_show_all (window);
3503   else
3504     gtk_widget_destroy (window);
3505 }
3506
3507 /*
3508  * Resize Grips
3509  */
3510 static gboolean
3511 grippy_button_press (GtkWidget *area, GdkEventButton *event, GdkWindowEdge edge)
3512 {
3513   if (event->type == GDK_BUTTON_PRESS) 
3514     {
3515       if (event->button == 1)
3516         gtk_window_begin_resize_drag (GTK_WINDOW (gtk_widget_get_toplevel (area)), edge,
3517                                       event->button, event->x_root, event->y_root,
3518                                       event->time);
3519       else if (event->button == 2)
3520         gtk_window_begin_move_drag (GTK_WINDOW (gtk_widget_get_toplevel (area)), 
3521                                     event->button, event->x_root, event->y_root,
3522                                     event->time);
3523     }
3524   return TRUE;
3525 }
3526
3527 static gboolean
3528 grippy_expose (GtkWidget *area, GdkEventExpose *event, GdkWindowEdge edge)
3529 {
3530   gtk_paint_resize_grip (area->style,
3531                          area->window,
3532                          gtk_widget_get_state (area),
3533                          &event->area,
3534                          area,
3535                          "statusbar",
3536                          edge,
3537                          0, 0,
3538                          area->allocation.width,
3539                          area->allocation.height);
3540
3541   return TRUE;
3542 }
3543
3544 static void
3545 create_resize_grips (GtkWidget *widget)
3546 {
3547   static GtkWidget *window = NULL;
3548   GtkWidget *area;
3549   GtkWidget *hbox, *vbox;
3550   if (!window)
3551     {
3552       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3553
3554       gtk_window_set_screen (GTK_WINDOW (window),
3555                              gtk_widget_get_screen (widget));
3556
3557       gtk_window_set_title (GTK_WINDOW (window), "resize grips");
3558       
3559       g_signal_connect (window, "destroy",
3560                         G_CALLBACK (gtk_widget_destroyed),
3561                         &window);
3562
3563       vbox = gtk_vbox_new (FALSE, 0);
3564       gtk_container_add (GTK_CONTAINER (window), vbox);
3565       
3566       hbox = gtk_hbox_new (FALSE, 0);
3567       gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);
3568
3569       /* North west */
3570       area = gtk_drawing_area_new ();
3571       gtk_widget_add_events (area, GDK_BUTTON_PRESS_MASK);
3572       gtk_box_pack_start (GTK_BOX (hbox), area, TRUE, TRUE, 0);
3573       g_signal_connect (area, "expose_event", G_CALLBACK (grippy_expose),
3574                         GINT_TO_POINTER (GDK_WINDOW_EDGE_NORTH_WEST));
3575       g_signal_connect (area, "button_press_event", G_CALLBACK (grippy_button_press),
3576                         GINT_TO_POINTER (GDK_WINDOW_EDGE_NORTH_WEST));
3577       
3578       /* North */
3579       area = gtk_drawing_area_new ();
3580       gtk_widget_add_events (area, GDK_BUTTON_PRESS_MASK);
3581       gtk_box_pack_start (GTK_BOX (hbox), area, TRUE, TRUE, 0);
3582       g_signal_connect (area, "expose_event", G_CALLBACK (grippy_expose),
3583                         GINT_TO_POINTER (GDK_WINDOW_EDGE_NORTH));
3584       g_signal_connect (area, "button_press_event", G_CALLBACK (grippy_button_press),
3585                         GINT_TO_POINTER (GDK_WINDOW_EDGE_NORTH));
3586
3587       /* North east */
3588       area = gtk_drawing_area_new ();
3589       gtk_widget_add_events (area, GDK_BUTTON_PRESS_MASK);
3590       gtk_box_pack_start (GTK_BOX (hbox), area, TRUE, TRUE, 0);
3591       g_signal_connect (area, "expose_event", G_CALLBACK (grippy_expose),
3592                         GINT_TO_POINTER (GDK_WINDOW_EDGE_NORTH_EAST));
3593       g_signal_connect (area, "button_press_event", G_CALLBACK (grippy_button_press),
3594                         GINT_TO_POINTER (GDK_WINDOW_EDGE_NORTH_EAST));
3595
3596       hbox = gtk_hbox_new (FALSE, 0);
3597       gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);
3598
3599       /* West */
3600       area = gtk_drawing_area_new ();
3601       gtk_widget_add_events (area, GDK_BUTTON_PRESS_MASK);
3602       gtk_box_pack_start (GTK_BOX (hbox), area, TRUE, TRUE, 0);
3603       g_signal_connect (area, "expose_event", G_CALLBACK (grippy_expose),
3604                         GINT_TO_POINTER (GDK_WINDOW_EDGE_WEST));
3605       g_signal_connect (area, "button_press_event", G_CALLBACK (grippy_button_press),
3606                         GINT_TO_POINTER (GDK_WINDOW_EDGE_WEST));
3607
3608       /* Middle */
3609       area = gtk_drawing_area_new ();
3610       gtk_box_pack_start (GTK_BOX (hbox), area, TRUE, TRUE, 0);
3611
3612       /* East */
3613       area = gtk_drawing_area_new ();
3614       gtk_widget_add_events (area, GDK_BUTTON_PRESS_MASK);
3615       gtk_box_pack_start (GTK_BOX (hbox), area, TRUE, TRUE, 0);
3616       g_signal_connect (area, "expose_event", G_CALLBACK (grippy_expose),
3617                         GINT_TO_POINTER (GDK_WINDOW_EDGE_EAST));
3618       g_signal_connect (area, "button_press_event", G_CALLBACK (grippy_button_press),
3619                         GINT_TO_POINTER (GDK_WINDOW_EDGE_EAST));
3620
3621
3622       hbox = gtk_hbox_new (FALSE, 0);
3623       gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);
3624
3625       /* South west */
3626       area = gtk_drawing_area_new ();
3627       gtk_widget_add_events (area, GDK_BUTTON_PRESS_MASK);
3628       gtk_box_pack_start (GTK_BOX (hbox), area, TRUE, TRUE, 0);
3629       g_signal_connect (area, "expose_event", G_CALLBACK (grippy_expose),
3630                         GINT_TO_POINTER (GDK_WINDOW_EDGE_SOUTH_WEST));
3631       g_signal_connect (area, "button_press_event", G_CALLBACK (grippy_button_press),
3632                         GINT_TO_POINTER (GDK_WINDOW_EDGE_SOUTH_WEST));
3633       /* South */
3634       area = gtk_drawing_area_new ();
3635       gtk_widget_add_events (area, GDK_BUTTON_PRESS_MASK);
3636       gtk_box_pack_start (GTK_BOX (hbox), area, TRUE, TRUE, 0);
3637       g_signal_connect (area, "expose_event", G_CALLBACK (grippy_expose),
3638                         GINT_TO_POINTER (GDK_WINDOW_EDGE_SOUTH));
3639       g_signal_connect (area, "button_press_event", G_CALLBACK (grippy_button_press),
3640                         GINT_TO_POINTER (GDK_WINDOW_EDGE_SOUTH));
3641       
3642       /* South east */
3643       area = gtk_drawing_area_new ();
3644       gtk_widget_add_events (area, GDK_BUTTON_PRESS_MASK);
3645       gtk_box_pack_start (GTK_BOX (hbox), area, TRUE, TRUE, 0);
3646       g_signal_connect (area, "expose_event", G_CALLBACK (grippy_expose),
3647                         GINT_TO_POINTER (GDK_WINDOW_EDGE_SOUTH_EAST));
3648       g_signal_connect (area, "button_press_event", G_CALLBACK (grippy_button_press),
3649                         GINT_TO_POINTER (GDK_WINDOW_EDGE_SOUTH_EAST));
3650     }
3651
3652   if (!gtk_widget_get_visible (window))
3653     gtk_widget_show_all (window);
3654   else
3655     gtk_widget_destroy (window);
3656 }
3657
3658 /*
3659  * Saved Position
3660  */
3661 gint upositionx = 0;
3662 gint upositiony = 0;
3663
3664 static gint
3665 uposition_configure (GtkWidget *window)
3666 {
3667   GtkLabel *lx;
3668   GtkLabel *ly;
3669   gchar buffer[64];
3670
3671   lx = g_object_get_data (G_OBJECT (window), "x");
3672   ly = g_object_get_data (G_OBJECT (window), "y");
3673
3674   gdk_window_get_root_origin (window->window, &upositionx, &upositiony);
3675   sprintf (buffer, "%d", upositionx);
3676   gtk_label_set_text (lx, buffer);
3677   sprintf (buffer, "%d", upositiony);
3678   gtk_label_set_text (ly, buffer);
3679
3680   return FALSE;
3681 }
3682
3683 static void
3684 uposition_stop_configure (GtkToggleButton *toggle,
3685                           GtkObject       *window)
3686 {
3687   if (toggle->active)
3688     g_signal_handlers_block_by_func (window, G_CALLBACK (uposition_configure), NULL);
3689   else
3690     g_signal_handlers_unblock_by_func (window, G_CALLBACK (uposition_configure), NULL);
3691 }
3692
3693 static void
3694 create_saved_position (GtkWidget *widget)
3695 {
3696   static GtkWidget *window = NULL;
3697
3698   if (!window)
3699     {
3700       GtkWidget *hbox;
3701       GtkWidget *main_vbox;
3702       GtkWidget *vbox;
3703       GtkWidget *x_label;
3704       GtkWidget *y_label;
3705       GtkWidget *button;
3706       GtkWidget *label;
3707       GtkWidget *any;
3708
3709       window = g_object_connect (g_object_new (GTK_TYPE_WINDOW,
3710                                                  "type", GTK_WINDOW_TOPLEVEL,
3711                                                  "title", "Saved Position",
3712                                                  NULL),
3713                                  "signal::configure_event", uposition_configure, NULL,
3714                                  NULL);
3715
3716       gtk_window_move (GTK_WINDOW (window), upositionx, upositiony);
3717
3718       gtk_window_set_screen (GTK_WINDOW (window),
3719                              gtk_widget_get_screen (widget));
3720       
3721
3722       g_signal_connect (window, "destroy",
3723                         G_CALLBACK (gtk_widget_destroyed),
3724                         &window);
3725
3726       main_vbox = gtk_vbox_new (FALSE, 5);
3727       gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 0);
3728       gtk_container_add (GTK_CONTAINER (window), main_vbox);
3729
3730       vbox =
3731         g_object_new (gtk_vbox_get_type (),
3732                         "GtkBox::homogeneous", FALSE,
3733                         "GtkBox::spacing", 5,
3734                         "GtkContainer::border_width", 10,
3735                         "GtkWidget::parent", main_vbox,
3736                         "GtkWidget::visible", TRUE,
3737                         "child", g_object_connect (g_object_new (GTK_TYPE_TOGGLE_BUTTON,
3738                                                                    "label", "Stop Events",
3739                                                                    "active", FALSE,
3740                                                                    "visible", TRUE,
3741                                                                    NULL),
3742                                                    "signal::clicked", uposition_stop_configure, window,
3743                                                    NULL),
3744                         NULL);
3745
3746       hbox = gtk_hbox_new (FALSE, 0);
3747       gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
3748       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
3749
3750       label = gtk_label_new ("X Origin : ");
3751       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
3752       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
3753
3754       x_label = gtk_label_new ("");
3755       gtk_box_pack_start (GTK_BOX (hbox), x_label, TRUE, TRUE, 0);
3756       g_object_set_data (G_OBJECT (window), "x", x_label);
3757
3758       hbox = gtk_hbox_new (FALSE, 0);
3759       gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
3760       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
3761
3762       label = gtk_label_new ("Y Origin : ");
3763       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
3764       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
3765
3766       y_label = gtk_label_new ("");
3767       gtk_box_pack_start (GTK_BOX (hbox), y_label, TRUE, TRUE, 0);
3768       g_object_set_data (G_OBJECT (window), "y", y_label);
3769
3770       any =
3771         g_object_new (gtk_hseparator_get_type (),
3772                         "GtkWidget::visible", TRUE,
3773                         NULL);
3774       gtk_box_pack_start (GTK_BOX (main_vbox), any, FALSE, TRUE, 0);
3775
3776       hbox = gtk_hbox_new (FALSE, 0);
3777       gtk_container_set_border_width (GTK_CONTAINER (hbox), 10);
3778       gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, TRUE, 0);
3779
3780       button = gtk_button_new_with_label ("Close");
3781       g_signal_connect_swapped (button, "clicked",
3782                                 G_CALLBACK (gtk_widget_destroy),
3783                                 window);
3784       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
3785       gtk_widget_set_can_default (button, TRUE);
3786       gtk_widget_grab_default (button);
3787       
3788       gtk_widget_show_all (window);
3789     }
3790   else
3791     gtk_widget_destroy (window);
3792 }
3793
3794 /*
3795  * GtkPixmap
3796  */
3797
3798 static void
3799 create_pixmap (GtkWidget *widget)
3800 {
3801   static GtkWidget *window = NULL;
3802   GtkWidget *box1;
3803   GtkWidget *box2;
3804   GtkWidget *box3;
3805   GtkWidget *button;
3806   GtkWidget *label;
3807   GtkWidget *separator;
3808   GtkWidget *pixmapwid;
3809
3810   if (!window)
3811     {
3812       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3813
3814       gtk_window_set_screen (GTK_WINDOW (window),
3815                              gtk_widget_get_screen (widget));
3816
3817       g_signal_connect (window, "destroy",
3818                         G_CALLBACK (gtk_widget_destroyed),
3819                         &window);
3820
3821       gtk_window_set_title (GTK_WINDOW (window), "GtkPixmap");
3822       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
3823       gtk_widget_realize(window);
3824
3825       box1 = gtk_vbox_new (FALSE, 0);
3826       gtk_container_add (GTK_CONTAINER (window), box1);
3827
3828       box2 = gtk_vbox_new (FALSE, 10);
3829       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
3830       gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
3831
3832       button = gtk_button_new ();
3833       gtk_box_pack_start (GTK_BOX (box2), button, FALSE, FALSE, 0);
3834
3835       pixmapwid = new_pixmap ("test.xpm", window->window, NULL);
3836
3837       label = gtk_label_new ("Pixmap\ntest");
3838       box3 = gtk_hbox_new (FALSE, 0);
3839       gtk_container_set_border_width (GTK_CONTAINER (box3), 2);
3840       gtk_container_add (GTK_CONTAINER (box3), pixmapwid);
3841       gtk_container_add (GTK_CONTAINER (box3), label);
3842       gtk_container_add (GTK_CONTAINER (button), box3);
3843
3844       button = gtk_button_new ();
3845       gtk_box_pack_start (GTK_BOX (box2), button, FALSE, FALSE, 0);
3846       
3847       pixmapwid = new_pixmap ("test.xpm", window->window, NULL);
3848
3849       label = gtk_label_new ("Pixmap\ntest");
3850       box3 = gtk_hbox_new (FALSE, 0);
3851       gtk_container_set_border_width (GTK_CONTAINER (box3), 2);
3852       gtk_container_add (GTK_CONTAINER (box3), pixmapwid);
3853       gtk_container_add (GTK_CONTAINER (box3), label);
3854       gtk_container_add (GTK_CONTAINER (button), box3);
3855
3856       gtk_widget_set_sensitive (button, FALSE);
3857       
3858       separator = gtk_hseparator_new ();
3859       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
3860
3861       box2 = gtk_vbox_new (FALSE, 10);
3862       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
3863       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
3864
3865       button = gtk_button_new_with_label ("close");
3866       g_signal_connect_swapped (button, "clicked",
3867                                 G_CALLBACK (gtk_widget_destroy),
3868                                 window);
3869       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
3870       gtk_widget_set_can_default (button, TRUE);
3871       gtk_widget_grab_default (button);
3872     }
3873
3874   if (!gtk_widget_get_visible (window))
3875     gtk_widget_show_all (window);
3876   else
3877     gtk_widget_destroy (window);
3878 }
3879
3880 static void
3881 tips_query_widget_entered (GtkTipsQuery   *tips_query,
3882                            GtkWidget      *widget,
3883                            const gchar    *tip_text,
3884                            const gchar    *tip_private,
3885                            GtkWidget      *toggle)
3886 {
3887   if (GTK_TOGGLE_BUTTON (toggle)->active)
3888     {
3889       gtk_label_set_text (GTK_LABEL (tips_query), tip_text ? "There is a Tip!" : "There is no Tip!");
3890       /* don't let GtkTipsQuery reset its label */
3891       g_signal_stop_emission_by_name (tips_query, "widget_entered");
3892     }
3893 }
3894
3895 static gint
3896 tips_query_widget_selected (GtkWidget      *tips_query,
3897                             GtkWidget      *widget,
3898                             const gchar    *tip_text,
3899                             const gchar    *tip_private,
3900                             GdkEventButton *event,
3901                             gpointer        func_data)
3902 {
3903   if (widget)
3904     g_print ("Help \"%s\" requested for <%s>\n",
3905              tip_private ? tip_private : "None",
3906              g_type_name (G_OBJECT_TYPE (widget)));
3907   return TRUE;
3908 }
3909
3910 static void
3911 create_tooltips (GtkWidget *widget)
3912 {
3913   static GtkWidget *window = NULL;
3914   GtkWidget *box1;
3915   GtkWidget *box2;
3916   GtkWidget *box3;
3917   GtkWidget *button;
3918   GtkWidget *toggle;
3919   GtkWidget *frame;
3920   GtkWidget *tips_query;
3921   GtkWidget *separator;
3922   GtkTooltips *tooltips;
3923
3924   if (!window)
3925     {
3926       window =
3927         g_object_new (gtk_window_get_type (),
3928                         "GtkWindow::type", GTK_WINDOW_TOPLEVEL,
3929                         "GtkContainer::border_width", 0,
3930                         "GtkWindow::title", "Tooltips",
3931                         "GtkWindow::allow_shrink", TRUE,
3932                         "GtkWindow::allow_grow", FALSE,
3933                         NULL);
3934
3935       gtk_window_set_screen (GTK_WINDOW (window),
3936                              gtk_widget_get_screen (widget));
3937
3938       g_signal_connect (window, "destroy",
3939                         G_CALLBACK (destroy_tooltips),
3940                         &window);
3941
3942       tooltips=gtk_tooltips_new();
3943       g_object_ref (tooltips);
3944       gtk_object_sink (GTK_OBJECT (tooltips));
3945       g_object_set_data (G_OBJECT (window), "tooltips", tooltips);
3946       
3947       box1 = gtk_vbox_new (FALSE, 0);
3948       gtk_container_add (GTK_CONTAINER (window), box1);
3949
3950       box2 = gtk_vbox_new (FALSE, 10);
3951       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
3952       gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
3953
3954       button = gtk_toggle_button_new_with_label ("button1");
3955       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
3956
3957       gtk_tooltips_set_tip (tooltips,
3958                             button,
3959                             "This is button 1",
3960                             "ContextHelp/buttons/1");
3961
3962       button = gtk_toggle_button_new_with_label ("button2");
3963       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
3964
3965       gtk_tooltips_set_tip (tooltips,
3966                             button,
3967                             "This is button 2. This is also a really long tooltip which probably won't fit on a single line and will therefore need to be wrapped. Hopefully the wrapping will work correctly.",
3968                             "ContextHelp/buttons/2_long");
3969
3970       toggle = gtk_toggle_button_new_with_label ("Override TipsQuery Label");
3971       gtk_box_pack_start (GTK_BOX (box2), toggle, TRUE, TRUE, 0);
3972
3973       gtk_tooltips_set_tip (tooltips,
3974                             toggle,
3975                             "Toggle TipsQuery view.",
3976                             "Hi msw! ;)");
3977
3978       box3 =
3979         g_object_new (gtk_vbox_get_type (),
3980                         "homogeneous", FALSE,
3981                         "spacing", 5,
3982                         "border_width", 5,
3983                         "visible", TRUE,
3984                         NULL);
3985
3986       tips_query = gtk_tips_query_new ();
3987
3988       button =
3989         g_object_new (gtk_button_get_type (),
3990                         "label", "[?]",
3991                         "visible", TRUE,
3992                         "parent", box3,
3993                         NULL);
3994       g_object_connect (button,
3995                         "swapped_signal::clicked", gtk_tips_query_start_query, tips_query,
3996                         NULL);
3997       gtk_box_set_child_packing (GTK_BOX (box3), button, FALSE, FALSE, 0, GTK_PACK_START);
3998       gtk_tooltips_set_tip (tooltips,
3999                             button,
4000                             "Start the Tooltips Inspector",
4001                             "ContextHelp/buttons/?");
4002       
4003       
4004       g_object_set (g_object_connect (tips_query,
4005                                       "signal::widget_entered", tips_query_widget_entered, toggle,
4006                                       "signal::widget_selected", tips_query_widget_selected, NULL,
4007                                       NULL),
4008                     "visible", TRUE,
4009                     "parent", box3,
4010                     "caller", button,
4011                     NULL);
4012       
4013       frame = g_object_new (gtk_frame_get_type (),
4014                               "label", "ToolTips Inspector",
4015                               "label_xalign", (double) 0.5,
4016                               "border_width", 0,
4017                               "visible", TRUE,
4018                               "parent", box2,
4019                               "child", box3,
4020                               NULL);
4021       gtk_box_set_child_packing (GTK_BOX (box2), frame, TRUE, TRUE, 10, GTK_PACK_START);
4022
4023       separator = gtk_hseparator_new ();
4024       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
4025
4026       box2 = gtk_vbox_new (FALSE, 10);
4027       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
4028       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
4029
4030       button = gtk_button_new_with_label ("close");
4031       g_signal_connect_swapped (button, "clicked",
4032                                 G_CALLBACK (gtk_widget_destroy),
4033                                 window);
4034       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
4035       gtk_widget_set_can_default (button, TRUE);
4036       gtk_widget_grab_default (button);
4037
4038       gtk_tooltips_set_tip (tooltips, button, "Push this button to close window", "ContextHelp/buttons/Close");
4039     }
4040
4041   if (!gtk_widget_get_visible (window))
4042     gtk_widget_show_all (window);
4043   else
4044     gtk_widget_destroy (window);
4045 }
4046
4047 /*
4048  * GtkImage
4049  */
4050
4051 static void
4052 pack_image (GtkWidget *box,
4053             const gchar *text,
4054             GtkWidget *image)
4055 {
4056   gtk_box_pack_start (GTK_BOX (box),
4057                       gtk_label_new (text),
4058                       FALSE, FALSE, 0);
4059
4060   gtk_box_pack_start (GTK_BOX (box),
4061                       image,
4062                       TRUE, TRUE, 0);  
4063 }
4064
4065 static void
4066 create_image (GtkWidget *widget)
4067 {
4068   static GtkWidget *window = NULL;
4069
4070   if (window == NULL)
4071     {
4072       GtkWidget *vbox;
4073       GdkPixmap *pixmap;
4074       GdkBitmap *mask;
4075         
4076       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
4077       
4078       gtk_window_set_screen (GTK_WINDOW (window),
4079                              gtk_widget_get_screen (widget));
4080
4081       /* this is bogus for testing drawing when allocation < request,
4082        * don't copy into real code
4083        */
4084       g_object_set (window, "allow_shrink", TRUE, "allow_grow", TRUE, NULL);
4085       
4086       g_signal_connect (window, "destroy",
4087                         G_CALLBACK (gtk_widget_destroyed),
4088                         &window);
4089
4090       vbox = gtk_vbox_new (FALSE, 5);
4091
4092       gtk_container_add (GTK_CONTAINER (window), vbox);
4093
4094       pack_image (vbox, "Stock Warning Dialog",
4095                   gtk_image_new_from_stock (GTK_STOCK_DIALOG_WARNING,
4096                                             GTK_ICON_SIZE_DIALOG));
4097
4098       pixmap = gdk_pixmap_colormap_create_from_xpm_d (NULL,
4099                                                       gtk_widget_get_colormap (window),
4100                                                       &mask,
4101                                                       NULL,
4102                                                       openfile);
4103       
4104       pack_image (vbox, "Pixmap",
4105                   gtk_image_new_from_pixmap (pixmap, mask));
4106     }
4107
4108   if (!gtk_widget_get_visible (window))
4109     gtk_widget_show_all (window);
4110   else
4111     gtk_widget_destroy (window);
4112 }
4113      
4114 /*
4115  * Menu demo
4116  */
4117
4118 static GtkWidget*
4119 create_menu (GdkScreen *screen, gint depth, gint length, gboolean tearoff)
4120 {
4121   GtkWidget *menu;
4122   GtkWidget *menuitem;
4123   GtkWidget *image;
4124   GSList *group;
4125   char buf[32];
4126   int i, j;
4127
4128   if (depth < 1)
4129     return NULL;
4130
4131   menu = gtk_menu_new ();
4132   gtk_menu_set_screen (GTK_MENU (menu), screen);
4133
4134   group = NULL;
4135
4136   if (tearoff)
4137     {
4138       menuitem = gtk_tearoff_menu_item_new ();
4139       gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
4140       gtk_widget_show (menuitem);
4141     }
4142
4143   image = gtk_image_new_from_stock (GTK_STOCK_OPEN,
4144                                     GTK_ICON_SIZE_MENU);
4145   gtk_widget_show (image);
4146   menuitem = gtk_image_menu_item_new_with_label ("Image item");
4147   gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), image);
4148   gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
4149   gtk_widget_show (menuitem);
4150   
4151   for (i = 0, j = 1; i < length; i++, j++)
4152     {
4153       sprintf (buf, "item %2d - %d", depth, j);
4154
4155       menuitem = gtk_radio_menu_item_new_with_label (group, buf);
4156       group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (menuitem));
4157
4158       gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
4159       gtk_widget_show (menuitem);
4160       if (i == 3)
4161         gtk_widget_set_sensitive (menuitem, FALSE);
4162
4163       if (i == 5)
4164         gtk_check_menu_item_set_inconsistent (GTK_CHECK_MENU_ITEM (menuitem),
4165                                               TRUE);
4166
4167       if (i < 5)
4168         gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), 
4169                                    create_menu (screen, depth - 1, 5,  TRUE));
4170     }
4171
4172   return menu;
4173 }
4174
4175 static GtkWidget*
4176 create_table_menu (GdkScreen *screen, gint cols, gint rows, gboolean tearoff)
4177 {
4178   GtkWidget *menu;
4179   GtkWidget *menuitem;
4180   GtkWidget *submenu;
4181   GtkWidget *image;
4182   char buf[32];
4183   int i, j;
4184
4185   menu = gtk_menu_new ();
4186   gtk_menu_set_screen (GTK_MENU (menu), screen);
4187
4188   j = 0;
4189   if (tearoff)
4190     {
4191       menuitem = gtk_tearoff_menu_item_new ();
4192       gtk_menu_attach (GTK_MENU (menu), menuitem, 0, cols, j, j + 1);
4193       gtk_widget_show (menuitem);
4194       j++;
4195     }
4196   
4197   menuitem = gtk_menu_item_new_with_label ("items");
4198   gtk_menu_attach (GTK_MENU (menu), menuitem, 0, cols, j, j + 1);
4199
4200   submenu = gtk_menu_new ();
4201   gtk_menu_set_screen (GTK_MENU (submenu), screen);
4202   gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), submenu);
4203   gtk_widget_show (menuitem);
4204   j++;
4205
4206   /* now fill the items submenu */
4207   image = gtk_image_new_from_stock (GTK_STOCK_HELP,
4208                                     GTK_ICON_SIZE_MENU);
4209   gtk_widget_show (image);
4210   menuitem = gtk_image_menu_item_new_with_label ("Image");
4211   gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), image);
4212   gtk_menu_attach (GTK_MENU (submenu), menuitem, 0, 1, 0, 1);
4213   gtk_widget_show (menuitem);
4214
4215   menuitem = gtk_menu_item_new_with_label ("x");
4216   gtk_menu_attach (GTK_MENU (submenu), menuitem, 1, 2, 0, 1);
4217   gtk_widget_show (menuitem);
4218
4219   menuitem = gtk_menu_item_new_with_label ("x");
4220   gtk_menu_attach (GTK_MENU (submenu), menuitem, 0, 1, 1, 2);
4221   gtk_widget_show (menuitem);
4222   
4223   image = gtk_image_new_from_stock (GTK_STOCK_HELP,
4224                                     GTK_ICON_SIZE_MENU);
4225   gtk_widget_show (image);
4226   menuitem = gtk_image_menu_item_new_with_label ("Image");
4227   gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), image);
4228   gtk_menu_attach (GTK_MENU (submenu), menuitem, 1, 2, 1, 2);
4229   gtk_widget_show (menuitem);
4230
4231   menuitem = gtk_radio_menu_item_new_with_label (NULL, "Radio");
4232   gtk_menu_attach (GTK_MENU (submenu), menuitem, 0, 1, 2, 3);
4233   gtk_widget_show (menuitem);
4234
4235   menuitem = gtk_menu_item_new_with_label ("x");
4236   gtk_menu_attach (GTK_MENU (submenu), menuitem, 1, 2, 2, 3);
4237   gtk_widget_show (menuitem);
4238
4239   menuitem = gtk_menu_item_new_with_label ("x");
4240   gtk_menu_attach (GTK_MENU (submenu), menuitem, 0, 1, 3, 4);
4241   gtk_widget_show (menuitem);
4242   
4243   menuitem = gtk_radio_menu_item_new_with_label (NULL, "Radio");
4244   gtk_menu_attach (GTK_MENU (submenu), menuitem, 1, 2, 3, 4);
4245   gtk_widget_show (menuitem);
4246
4247   menuitem = gtk_check_menu_item_new_with_label ("Check");
4248   gtk_menu_attach (GTK_MENU (submenu), menuitem, 0, 1, 4, 5);
4249   gtk_widget_show (menuitem);
4250
4251   menuitem = gtk_menu_item_new_with_label ("x");
4252   gtk_menu_attach (GTK_MENU (submenu), menuitem, 1, 2, 4, 5);
4253   gtk_widget_show (menuitem);
4254
4255   menuitem = gtk_menu_item_new_with_label ("x");
4256   gtk_menu_attach (GTK_MENU (submenu), menuitem, 0, 1, 5, 6);
4257   gtk_widget_show (menuitem);
4258   
4259   menuitem = gtk_check_menu_item_new_with_label ("Check");
4260   gtk_menu_attach (GTK_MENU (submenu), menuitem, 1, 2, 5, 6);
4261   gtk_widget_show (menuitem);
4262
4263   menuitem = gtk_menu_item_new_with_label ("1. Inserted normally (8)");
4264   gtk_widget_show (menuitem);
4265   gtk_menu_shell_insert (GTK_MENU_SHELL (submenu), menuitem, 8);
4266
4267   menuitem = gtk_menu_item_new_with_label ("2. Inserted normally (2)");
4268   gtk_widget_show (menuitem);
4269   gtk_menu_shell_insert (GTK_MENU_SHELL (submenu), menuitem, 2);
4270
4271   menuitem = gtk_menu_item_new_with_label ("3. Inserted normally (0)");
4272   gtk_widget_show (menuitem);
4273   gtk_menu_shell_insert (GTK_MENU_SHELL (submenu), menuitem, 0);
4274
4275   menuitem = gtk_menu_item_new_with_label ("4. Inserted normally (-1)");
4276   gtk_widget_show (menuitem);
4277   gtk_menu_shell_insert (GTK_MENU_SHELL (submenu), menuitem, -1);
4278   
4279   /* end of items submenu */
4280
4281   menuitem = gtk_menu_item_new_with_label ("spanning");
4282   gtk_menu_attach (GTK_MENU (menu), menuitem, 0, cols, j, j + 1);
4283
4284   submenu = gtk_menu_new ();
4285   gtk_menu_set_screen (GTK_MENU (submenu), screen);
4286   gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), submenu);
4287   gtk_widget_show (menuitem);
4288   j++;
4289
4290   /* now fill the spanning submenu */
4291   menuitem = gtk_menu_item_new_with_label ("a");
4292   gtk_menu_attach (GTK_MENU (submenu), menuitem, 0, 2, 0, 1);
4293   gtk_widget_show (menuitem);
4294
4295   menuitem = gtk_menu_item_new_with_label ("b");
4296   gtk_menu_attach (GTK_MENU (submenu), menuitem, 2, 3, 0, 2);
4297   gtk_widget_show (menuitem);
4298
4299   menuitem = gtk_menu_item_new_with_label ("c");
4300   gtk_menu_attach (GTK_MENU (submenu), menuitem, 0, 1, 1, 3);
4301   gtk_widget_show (menuitem);
4302
4303   menuitem = gtk_menu_item_new_with_label ("d");
4304   gtk_menu_attach (GTK_MENU (submenu), menuitem, 1, 2, 1, 2);
4305   gtk_widget_show (menuitem);
4306
4307   menuitem = gtk_menu_item_new_with_label ("e");
4308   gtk_menu_attach (GTK_MENU (submenu), menuitem, 1, 3, 2, 3);
4309   gtk_widget_show (menuitem);
4310   /* end of spanning submenu */
4311   
4312   menuitem = gtk_menu_item_new_with_label ("left");
4313   gtk_menu_attach (GTK_MENU (menu), menuitem, 0, 1, j, j + 1);
4314   submenu = gtk_menu_new ();
4315   gtk_menu_set_screen (GTK_MENU (submenu), screen);
4316   gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), submenu);
4317   gtk_widget_show (menuitem);
4318
4319   menuitem = gtk_menu_item_new_with_label ("Empty");
4320   gtk_menu_attach (GTK_MENU (submenu), menuitem, 0, 1, 0, 1);
4321   submenu = gtk_menu_new ();
4322   gtk_menu_set_screen (GTK_MENU (submenu), screen);
4323   gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), submenu);
4324   gtk_widget_show (menuitem);
4325
4326   menuitem = gtk_menu_item_new_with_label ("right");
4327   gtk_menu_attach (GTK_MENU (menu), menuitem, 1, 2, j, j + 1);
4328   submenu = gtk_menu_new ();
4329   gtk_menu_set_screen (GTK_MENU (submenu), screen);
4330   gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), submenu);
4331   gtk_widget_show (menuitem);
4332
4333   menuitem = gtk_menu_item_new_with_label ("Empty");
4334   gtk_menu_attach (GTK_MENU (submenu), menuitem, 0, 1, 0, 1);
4335   gtk_widget_show (menuitem);
4336
4337   j++;
4338
4339   for (; j < rows; j++)
4340       for (i = 0; i < cols; i++)
4341       {
4342         sprintf (buf, "(%d %d)", i, j);
4343         menuitem = gtk_menu_item_new_with_label (buf);
4344         gtk_menu_attach (GTK_MENU (menu), menuitem, i, i + 1, j, j + 1);
4345         gtk_widget_show (menuitem);
4346       }
4347   
4348   menuitem = gtk_menu_item_new_with_label ("1. Inserted normally (8)");
4349   gtk_menu_shell_insert (GTK_MENU_SHELL (menu), menuitem, 8);
4350   gtk_widget_show (menuitem);
4351   menuitem = gtk_menu_item_new_with_label ("2. Inserted normally (2)");
4352   gtk_menu_shell_insert (GTK_MENU_SHELL (menu), menuitem, 2);
4353   gtk_widget_show (menuitem);
4354   menuitem = gtk_menu_item_new_with_label ("3. Inserted normally (0)");
4355   gtk_menu_shell_insert (GTK_MENU_SHELL (menu), menuitem, 0);
4356   gtk_widget_show (menuitem);
4357   menuitem = gtk_menu_item_new_with_label ("4. Inserted normally (-1)");
4358   gtk_menu_shell_insert (GTK_MENU_SHELL (menu), menuitem, -1);
4359   gtk_widget_show (menuitem);
4360   
4361   return menu;
4362 }
4363
4364 static void
4365 create_menus (GtkWidget *widget)
4366 {
4367   static GtkWidget *window = NULL;
4368   GtkWidget *box1;
4369   GtkWidget *box2;
4370   GtkWidget *button;
4371   GtkWidget *optionmenu;
4372   GtkWidget *separator;
4373   
4374   if (!window)
4375     {
4376       GtkWidget *menubar;
4377       GtkWidget *menu;
4378       GtkWidget *menuitem;
4379       GtkAccelGroup *accel_group;
4380       GtkWidget *image;
4381       GdkScreen *screen = gtk_widget_get_screen (widget);
4382       
4383       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
4384
4385       gtk_window_set_screen (GTK_WINDOW (window), screen);
4386       
4387       g_signal_connect (window, "destroy",
4388                         G_CALLBACK (gtk_widget_destroyed),
4389                         &window);
4390       g_signal_connect (window, "delete-event",
4391                         G_CALLBACK (gtk_true),
4392                         NULL);
4393       
4394       accel_group = gtk_accel_group_new ();
4395       gtk_window_add_accel_group (GTK_WINDOW (window), accel_group);
4396
4397       gtk_window_set_title (GTK_WINDOW (window), "menus");
4398       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
4399       
4400       
4401       box1 = gtk_vbox_new (FALSE, 0);
4402       gtk_container_add (GTK_CONTAINER (window), box1);
4403       gtk_widget_show (box1);
4404       
4405       menubar = gtk_menu_bar_new ();
4406       gtk_box_pack_start (GTK_BOX (box1), menubar, FALSE, TRUE, 0);
4407       gtk_widget_show (menubar);
4408       
4409       menu = create_menu (screen, 2, 50, TRUE);
4410       
4411       menuitem = gtk_menu_item_new_with_label ("test\nline2");
4412       gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), menu);
4413       gtk_menu_shell_append (GTK_MENU_SHELL (menubar), menuitem);
4414       gtk_widget_show (menuitem);
4415
4416       menu = create_table_menu (screen, 2, 50, TRUE);
4417       
4418       menuitem = gtk_menu_item_new_with_label ("table");
4419       gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), menu);
4420       gtk_menu_shell_append (GTK_MENU_SHELL (menubar), menuitem);
4421       gtk_widget_show (menuitem);
4422       
4423       menuitem = gtk_menu_item_new_with_label ("foo");
4424       gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), create_menu (screen, 3, 5, TRUE));
4425       gtk_menu_shell_append (GTK_MENU_SHELL (menubar), menuitem);
4426       gtk_widget_show (menuitem);
4427
4428       image = gtk_image_new_from_stock (GTK_STOCK_HELP,
4429                                         GTK_ICON_SIZE_MENU);
4430       gtk_widget_show (image);
4431       menuitem = gtk_image_menu_item_new_with_label ("Help");
4432       gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), image);
4433       gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), create_menu (screen, 4, 5, TRUE));
4434       gtk_menu_item_set_right_justified (GTK_MENU_ITEM (menuitem), TRUE);
4435       gtk_menu_shell_append (GTK_MENU_SHELL (menubar), menuitem);
4436       gtk_widget_show (menuitem);
4437       
4438       menubar = gtk_menu_bar_new ();
4439       gtk_box_pack_start (GTK_BOX (box1), menubar, FALSE, TRUE, 0);
4440       gtk_widget_show (menubar);
4441       
4442       menu = create_menu (screen, 2, 10, TRUE);
4443       
4444       menuitem = gtk_menu_item_new_with_label ("Second menu bar");
4445       gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), menu);
4446       gtk_menu_shell_append (GTK_MENU_SHELL (menubar), menuitem);
4447       gtk_widget_show (menuitem);
4448       
4449       box2 = gtk_vbox_new (FALSE, 10);
4450       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
4451       gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
4452       gtk_widget_show (box2);
4453       
4454       menu = create_menu (screen, 1, 5, FALSE);
4455       gtk_menu_set_accel_group (GTK_MENU (menu), accel_group);
4456
4457       menuitem = gtk_image_menu_item_new_from_stock (GTK_STOCK_NEW, accel_group);
4458       gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
4459       gtk_widget_show (menuitem);
4460       
4461       menuitem = gtk_check_menu_item_new_with_label ("Accelerate Me");
4462       gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
4463       gtk_widget_show (menuitem);
4464       gtk_widget_add_accelerator (menuitem,
4465                                   "activate",
4466                                   accel_group,
4467                                   GDK_F1,
4468                                   0,
4469                                   GTK_ACCEL_VISIBLE);
4470       menuitem = gtk_check_menu_item_new_with_label ("Accelerator Locked");
4471       gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
4472       gtk_widget_show (menuitem);
4473       gtk_widget_add_accelerator (menuitem,
4474                                   "activate",
4475                                   accel_group,
4476                                   GDK_F2,
4477                                   0,
4478                                   GTK_ACCEL_VISIBLE | GTK_ACCEL_LOCKED);
4479       menuitem = gtk_check_menu_item_new_with_label ("Accelerators Frozen");
4480       gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
4481       gtk_widget_show (menuitem);
4482       gtk_widget_add_accelerator (menuitem,
4483                                   "activate",
4484                                   accel_group,
4485                                   GDK_F2,
4486                                   0,
4487                                   GTK_ACCEL_VISIBLE);
4488       gtk_widget_add_accelerator (menuitem,
4489                                   "activate",
4490                                   accel_group,
4491                                   GDK_F3,
4492                                   0,
4493                                   GTK_ACCEL_VISIBLE);
4494       
4495       optionmenu = gtk_option_menu_new ();
4496       gtk_option_menu_set_menu (GTK_OPTION_MENU (optionmenu), menu);
4497       gtk_option_menu_set_history (GTK_OPTION_MENU (optionmenu), 3);
4498       gtk_box_pack_start (GTK_BOX (box2), optionmenu, TRUE, TRUE, 0);
4499       gtk_widget_show (optionmenu);
4500
4501       separator = gtk_hseparator_new ();
4502       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
4503       gtk_widget_show (separator);
4504
4505       box2 = gtk_vbox_new (FALSE, 10);
4506       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
4507       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
4508       gtk_widget_show (box2);
4509
4510       button = gtk_button_new_with_label ("close");
4511       g_signal_connect_swapped (button, "clicked",
4512                                 G_CALLBACK (gtk_widget_destroy),
4513                                 window);
4514       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
4515       gtk_widget_set_can_default (button, TRUE);
4516       gtk_widget_grab_default (button);
4517       gtk_widget_show (button);
4518     }
4519
4520   if (!gtk_widget_get_visible (window))
4521     gtk_widget_show (window);
4522   else
4523     gtk_widget_destroy (window);
4524 }
4525
4526 static void
4527 gtk_ifactory_cb (gpointer             callback_data,
4528                  guint                callback_action,
4529                  GtkWidget           *widget)
4530 {
4531   g_message ("ItemFactory: activated \"%s\"", gtk_item_factory_path_from_widget (widget));
4532 }
4533
4534 /* GdkPixbuf RGBA C-Source image dump */
4535
4536 static const guint8 apple[] = 
4537 { ""
4538   /* Pixbuf magic (0x47646b50) */
4539   "GdkP"
4540   /* length: header (24) + pixel_data (2304) */
4541   "\0\0\11\30"
4542   /* pixdata_type (0x1010002) */
4543   "\1\1\0\2"
4544   /* rowstride (96) */
4545   "\0\0\0`"
4546   /* width (24) */
4547   "\0\0\0\30"
4548   /* height (24) */
4549   "\0\0\0\30"
4550   /* pixel_data: */
4551   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
4552   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
4553   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
4554   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
4555   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
4556   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
4557   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\26\24"
4558   "\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"
4559   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`m"
4560   "[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"
4561   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
4562   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0`l[Blza\373s\202d\354w\206g\372p~c"
4563   "\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"
4564   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
4565   "\0\0\0\0\0\0`l\\\20iw_\356y\211h\373x\207g\364~\216i\364u\204e\366gt"
4566   "_\374^jX\241A;-_\0\0\0~\0\0\0\0SM4)SM21B9&\22\320\270\204\1\320\270\204"
4567   "\0\0\0\0\0\0\0\0\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"
4568   "]\212r\200c\366v\205f\371jx_\323_kY\232_kZH^jY\26]iW\211@G9\272:6%j\220"
4569   "\211]\320\221\211`\377\212\203Z\377~xP\377mkE\331]^;|/0\37\21\0\0\0\0"
4570   "\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["
4571   "eT<\216\200Z\203\227\211_\354\234\217c\377\232\217b\362\232\220c\337"
4572   "\243\233k\377\252\241p\377\250\236p\377\241\225h\377\231\214_\377\210"
4573   "\202U\377srI\377[]:\355KO0U\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0i"
4574   "v^\200`lY\211^jY\"\0\0\0\0\221\204\\\273\250\233r\377\302\267\224\377"
4575   "\311\300\237\377\272\256\204\377\271\256\177\377\271\257\200\377\267"
4576   "\260\177\377\260\251x\377\250\236l\377\242\225e\377\226\213]\377~zP\377"
4577   "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"
4578   "\0\213\203[v\253\240t\377\334\326\301\377\344\340\317\377\321\312\253"
4579   "\377\303\271\217\377\300\270\213\377\277\267\210\377\272\264\203\377"
4580   "\261\255z\377\250\242n\377\243\232h\377\232\220`\377\210\202V\377nnE"
4581   "\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"
4582   "\234\222e\362\304\274\232\377\337\333\306\377\332\325\273\377\311\302"
4583   "\232\377\312\303\236\377\301\273\216\377\300\271\212\377\270\264\200"
4584   "\377\256\253v\377\246\243n\377\236\232h\377\230\220`\377\213\203V\377"
4585   "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"
4586   "\203Zl\242\234l\377\321\315\260\377\331\324\271\377\320\313\251\377\307"
4587   "\301\232\377\303\276\224\377\300\272\214\377\274\267\206\377\264\260"
4588   "|\377\253\251s\377\244\243n\377\232\230e\377\223\216^\377\207\200U\377"
4589   "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"
4590   "\210\204Y\240\245\237o\377\316\310\253\377\310\303\237\377\304\300\230"
4591   "\377\303\277\225\377\277\272\216\377\274\270\210\377\266\263\200\377"
4592   "\256\254v\377\247\246p\377\237\236j\377\227\226d\377\215\212[\377\203"
4593   "\177T\377qsH\377X]8\377FN.\377DK-\200\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
4594   "\0\0\0\0\207\204X\257\244\240o\377\300\275\231\377\301\275\226\377\274"
4595   "\270\213\377\274\270\214\377\267\264\205\377\264\262\200\377\260\256"
4596   "z\377\251\251s\377\243\244n\377\231\232g\377\220\222`\377\210\211Y\377"
4597   "|}Q\377hlC\377PU3\377CK,\377DL/Y\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
4598   "\0\0\205\204X\220\232\230h\377\261\260\204\377\266\264\212\377\261\260"
4599   "\201\377\263\260\200\377\260\257}\377\256\256x\377\253\254t\377\244\246"
4600   "o\377\233\236i\377\221\224b\377\211\214\\\377\202\204V\377txM\377]b>"
4601   "\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>"
4602   "\215\215_\377\237\237r\377\247\247x\377\247\247t\377\252\252w\377\252"
4603   "\252u\377\252\253t\377\243\246o\377\235\240j\377\223\230c\377\213\217"
4604   "]\377\201\206V\377x}P\377gkD\377RY5\377BI,\377AI,\262\0\0\0\0\0\0\0\0"
4605   "\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"
4606   "\232g\377\234\236i\377\236\241l\377\241\244n\377\240\244m\377\232\237"
4607   "i\377\223\230c\377\212\221]\377\200\210W\377v|P\377jnG\377Za>\377HP2"
4608   "\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"
4609   "\0wzQ6\177\201U\371\206\211Z\377\216\222`\377\220\225a\377\220\225b\377"
4610   "\220\226a\377\213\221_\377\204\213Z\377{\203R\377ryN\377iqH\377^fA\377"
4611   "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"
4612   "\0\0\0\0\0\0\0\0\0\0\0\0ptJTw|Q\371z\177R\377}\202T\377|\203T\377z\200"
4613   "R\377v|O\377pwL\377jpF\377dlB\377`hB\377Yb@\377LT6\377<C*\377\11\12\6"
4614   "\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"
4615   "\0\0\0\0\0\0\0\0\0\0\\`=UgnE\370hnG\377gmE\377djB\377]d>\377[c<\377Y"
4616   "b<\377Zc>\377V_>\377OW8\377BK/\377\16\20\12\377\0\0\0\377\0\0\0\377\0"
4617   "\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"
4618   "\0\1\0\0\0\40\22\24\15\260@D+\377W`;\377OV5\377.3\36\377.3\37\377IP0"
4619   "\377RZ7\377PZ8\3776=&\377\14\15\10\377\0\0\0\377\0\0\0\377\0\0\0\377"
4620   "\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"
4621   "\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"
4622   "\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"
4623   "\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"
4624   "\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"
4625   "\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"
4626   "\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"
4627   "\0\0\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"
4628   "\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"
4629   "\0\0\5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"};
4630
4631
4632 static void
4633 dump_accels (gpointer             callback_data,
4634              guint                callback_action,
4635              GtkWidget           *widget)
4636 {
4637   gtk_accel_map_save_fd (1 /* stdout */);
4638 }
4639     
4640 static GtkItemFactoryEntry menu_items[] =
4641 {
4642   { "/_File",                  NULL,         NULL,                  0, "<Branch>" },
4643   { "/File/tearoff1",          NULL,         gtk_ifactory_cb,       0, "<Tearoff>" },
4644   { "/File/_New",              NULL,         gtk_ifactory_cb,       0, "<StockItem>", GTK_STOCK_NEW },
4645   { "/File/_Open",             NULL,         gtk_ifactory_cb,       0, "<StockItem>", GTK_STOCK_OPEN },
4646   { "/File/_Save",             NULL,         gtk_ifactory_cb,       0, "<StockItem>", GTK_STOCK_SAVE },
4647   { "/File/Save _As...",       "<control>A", gtk_ifactory_cb,       0, "<StockItem>", GTK_STOCK_SAVE },
4648   { "/File/_Dump \"_Accels\"",  NULL,        dump_accels,           0 },
4649   { "/File/\\/Test__Escaping/And\\/\n\tWei\\\\rdly",
4650                                 NULL,        gtk_ifactory_cb,       0 },
4651   { "/File/sep1",        NULL,               gtk_ifactory_cb,       0, "<Separator>" },
4652   { "/File/_Quit",       NULL,               gtk_ifactory_cb,       0, "<StockItem>", GTK_STOCK_QUIT },
4653
4654   { "/_Preferences",                    NULL, 0,               0, "<Branch>" },
4655   { "/_Preferences/_Color",             NULL, 0,               0, "<Branch>" },
4656   { "/_Preferences/Color/_Red",         NULL, gtk_ifactory_cb, 0, "<RadioItem>" },
4657   { "/_Preferences/Color/_Green",       NULL, gtk_ifactory_cb, 0, "/Preferences/Color/Red" },
4658   { "/_Preferences/Color/_Blue",        NULL, gtk_ifactory_cb, 0, "/Preferences/Color/Red" },
4659   { "/_Preferences/_Shape",             NULL, 0,               0, "<Branch>" },
4660   { "/_Preferences/Shape/_Square",      NULL, gtk_ifactory_cb, 0, "<RadioItem>" },
4661   { "/_Preferences/Shape/_Rectangle",   NULL, gtk_ifactory_cb, 0, "/Preferences/Shape/Square" },
4662   { "/_Preferences/Shape/_Oval",        NULL, gtk_ifactory_cb, 0, "/Preferences/Shape/Rectangle" },
4663   { "/_Preferences/Shape/_Rectangle",   NULL, gtk_ifactory_cb, 0, "/Preferences/Shape/Square" },
4664   { "/_Preferences/Shape/_Oval",        NULL, gtk_ifactory_cb, 0, "/Preferences/Shape/Rectangle" },
4665   { "/_Preferences/Shape/_Image",       NULL, gtk_ifactory_cb, 0, "<ImageItem>", apple },
4666   { "/_Preferences/Coffee",                  NULL, gtk_ifactory_cb, 0, "<CheckItem>" },
4667   { "/_Preferences/Toast",                   NULL, gtk_ifactory_cb, 0, "<CheckItem>" },
4668   { "/_Preferences/Marshmallow Froot Loops", NULL, gtk_ifactory_cb, 0, "<CheckItem>" },
4669
4670   /* For testing deletion of menus */
4671   { "/_Preferences/Should_NotAppear",          NULL, 0,               0, "<Branch>" },
4672   { "/Preferences/ShouldNotAppear/SubItem1",   NULL, gtk_ifactory_cb, 0 },
4673   { "/Preferences/ShouldNotAppear/SubItem2",   NULL, gtk_ifactory_cb, 0 },
4674
4675   { "/_Help",            NULL,         0,                     0, "<LastBranch>" },
4676   { "/Help/_Help",       NULL,         gtk_ifactory_cb,       0, "<StockItem>", GTK_STOCK_HELP},
4677   { "/Help/_About",      NULL,         gtk_ifactory_cb,       0 },
4678 };
4679
4680
4681 static int nmenu_items = sizeof (menu_items) / sizeof (menu_items[0]);
4682
4683 static void
4684 create_item_factory (GtkWidget *widget)
4685 {
4686   static GtkWidget *window = NULL;
4687   
4688   if (!window)
4689     {
4690       GtkWidget *box1;
4691       GtkWidget *box2;
4692       GtkWidget *separator;
4693       GtkWidget *label;
4694       GtkWidget *button;
4695       GtkAccelGroup *accel_group;
4696       GtkItemFactory *item_factory;
4697       GtkTooltips *tooltips;
4698       
4699       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
4700       
4701       gtk_window_set_screen (GTK_WINDOW (window),
4702                              gtk_widget_get_screen (widget));
4703       
4704       g_signal_connect (window, "destroy",
4705                         G_CALLBACK(gtk_widget_destroyed),
4706                         &window);
4707       g_signal_connect (window, "delete-event",
4708                         G_CALLBACK (gtk_true),
4709                         NULL);
4710       
4711       accel_group = gtk_accel_group_new ();
4712       item_factory = gtk_item_factory_new (GTK_TYPE_MENU_BAR, "<main>", accel_group);
4713       g_object_set_data_full (G_OBJECT (window),
4714                               "<main>",
4715                               item_factory,
4716                               g_object_unref);
4717       gtk_window_add_accel_group (GTK_WINDOW (window), accel_group);
4718       gtk_window_set_title (GTK_WINDOW (window), "Item Factory");
4719       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
4720       gtk_item_factory_create_items (item_factory, nmenu_items, menu_items, NULL);
4721
4722       /* preselect /Preferences/Shape/Oval over the other radios
4723        */
4724       gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_item_factory_get_item (item_factory,
4725                                                                                       "/Preferences/Shape/Oval")),
4726                                       TRUE);
4727
4728       /* preselect /Preferences/Coffee
4729        */
4730       gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_item_factory_get_item (item_factory,
4731                                                                                       "/Preferences/Coffee")),
4732                                       TRUE);
4733
4734       /* preselect /Preferences/Marshmallow Froot Loops and set it insensitive
4735        */
4736       gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (gtk_item_factory_get_item (item_factory,
4737                                                                                       "/Preferences/Marshmallow Froot Loops")),
4738                                       TRUE);
4739       gtk_widget_set_sensitive (GTK_WIDGET (gtk_item_factory_get_item (item_factory,
4740                                                                        "/Preferences/Marshmallow Froot Loops")),
4741                                 FALSE);
4742        
4743       /* Test how tooltips (ugh) work on menu items
4744        */
4745       tooltips = gtk_tooltips_new ();
4746       g_object_ref (tooltips);
4747       gtk_object_sink (GTK_OBJECT (tooltips));
4748       g_object_set_data_full (G_OBJECT (window), "testgtk-tooltips",
4749                               tooltips, (GDestroyNotify)g_object_unref);
4750       
4751       gtk_tooltips_set_tip (tooltips, gtk_item_factory_get_item (item_factory, "/File/New"),
4752                             "Create a new file", NULL);
4753       gtk_tooltips_set_tip (tooltips, gtk_item_factory_get_item (item_factory, "/File/Open"),
4754                             "Open a file", NULL);
4755       gtk_tooltips_set_tip (tooltips, gtk_item_factory_get_item (item_factory, "/File/Save"),
4756                             "Safe file", NULL);
4757       gtk_tooltips_set_tip (tooltips, gtk_item_factory_get_item (item_factory, "/Preferences/Color"),
4758                             "Modify color", NULL);
4759
4760       box1 = gtk_vbox_new (FALSE, 0);
4761       gtk_container_add (GTK_CONTAINER (window), box1);
4762       
4763       gtk_box_pack_start (GTK_BOX (box1),
4764                           gtk_item_factory_get_widget (item_factory, "<main>"),
4765                           FALSE, FALSE, 0);
4766
4767       label = gtk_label_new ("Type\n<alt>\nto start");
4768       gtk_widget_set_size_request (label, 200, 200);
4769       gtk_misc_set_alignment (GTK_MISC (label), 0.5, 0.5);
4770       gtk_box_pack_start (GTK_BOX (box1), label, TRUE, TRUE, 0);
4771
4772
4773       separator = gtk_hseparator_new ();
4774       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
4775
4776
4777       box2 = gtk_vbox_new (FALSE, 10);
4778       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
4779       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
4780
4781       button = gtk_button_new_with_label ("close");
4782       g_signal_connect_swapped (button, "clicked",
4783                                 G_CALLBACK (gtk_widget_destroy),
4784                                 window);
4785       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
4786       gtk_widget_set_can_default (button, TRUE);
4787       gtk_widget_grab_default (button);
4788
4789       gtk_item_factory_delete_item (item_factory, "/Preferences/ShouldNotAppear");
4790       
4791       gtk_widget_show_all (window);
4792     }
4793   else
4794     gtk_widget_destroy (window);
4795 }
4796
4797 static GtkWidget *
4798 accel_button_new (GtkAccelGroup *accel_group,
4799                   const gchar   *text,
4800                   const gchar   *accel)
4801 {
4802   guint keyval;
4803   GdkModifierType modifiers;
4804   GtkWidget *button;
4805   GtkWidget *label;
4806
4807   gtk_accelerator_parse (accel, &keyval, &modifiers);
4808   g_assert (keyval);
4809
4810   button = gtk_button_new ();
4811   gtk_widget_add_accelerator (button, "activate", accel_group,
4812                               keyval, modifiers, GTK_ACCEL_VISIBLE | GTK_ACCEL_LOCKED);
4813
4814   label = gtk_accel_label_new (text);
4815   gtk_accel_label_set_accel_widget (GTK_ACCEL_LABEL (label), button);
4816   gtk_widget_show (label);
4817   
4818   gtk_container_add (GTK_CONTAINER (button), label);
4819
4820   return button;
4821 }
4822
4823 static void
4824 create_key_lookup (GtkWidget *widget)
4825 {
4826   static GtkWidget *window = NULL;
4827   gpointer window_ptr;
4828
4829   if (!window)
4830     {
4831       GtkAccelGroup *accel_group = gtk_accel_group_new ();
4832       GtkWidget *button;
4833       
4834       window = gtk_dialog_new_with_buttons ("Key Lookup", NULL, 0,
4835                                             GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
4836                                             NULL);
4837
4838       gtk_window_set_screen (GTK_WINDOW (window),
4839                              gtk_widget_get_screen (widget));
4840
4841       /* We have to expand it so the accel labels will draw their labels
4842        */
4843       gtk_window_set_default_size (GTK_WINDOW (window), 300, -1);
4844       
4845       gtk_window_add_accel_group (GTK_WINDOW (window), accel_group);
4846       
4847       button = gtk_button_new_with_mnemonic ("Button 1 (_a)");
4848       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
4849       button = gtk_button_new_with_mnemonic ("Button 2 (_A)");
4850       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
4851       button = gtk_button_new_with_mnemonic ("Button 3 (_\321\204)");
4852       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
4853       button = gtk_button_new_with_mnemonic ("Button 4 (_\320\244)");
4854       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
4855       button = gtk_button_new_with_mnemonic ("Button 6 (_b)");
4856       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
4857       button = accel_button_new (accel_group, "Button 7", "<Alt><Shift>b");
4858       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
4859       button = accel_button_new (accel_group, "Button 8", "<Alt>d");
4860       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
4861       button = accel_button_new (accel_group, "Button 9", "<Alt>Cyrillic_ve");
4862       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
4863       button = gtk_button_new_with_mnemonic ("Button 10 (_1)");
4864       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
4865       button = gtk_button_new_with_mnemonic ("Button 11 (_!)");
4866       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
4867       button = accel_button_new (accel_group, "Button 12", "<Super>a");
4868       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
4869       button = accel_button_new (accel_group, "Button 13", "<Hyper>a");
4870       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
4871       button = accel_button_new (accel_group, "Button 14", "<Meta>a");
4872       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
4873       button = accel_button_new (accel_group, "Button 15", "<Shift><Mod4>b");
4874       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
4875
4876       window_ptr = &window;
4877       g_object_add_weak_pointer (G_OBJECT (window), window_ptr);
4878       g_signal_connect (window, "response", G_CALLBACK (gtk_object_destroy), NULL);
4879
4880       gtk_widget_show_all (window);
4881     }
4882   else
4883     gtk_widget_destroy (window);
4884 }
4885
4886
4887 /*
4888  create_modal_window
4889  */
4890
4891 static gboolean
4892 cmw_destroy_cb(GtkWidget *widget)
4893 {
4894   /* This is needed to get out of gtk_main */
4895   gtk_main_quit ();
4896
4897   return FALSE;
4898 }
4899
4900 static void
4901 cmw_color (GtkWidget *widget, GtkWidget *parent)
4902 {
4903     GtkWidget *csd;
4904
4905     csd = gtk_color_selection_dialog_new ("This is a modal color selection dialog");
4906
4907     gtk_window_set_screen (GTK_WINDOW (csd), gtk_widget_get_screen (parent));
4908
4909     gtk_color_selection_set_has_palette (GTK_COLOR_SELECTION (GTK_COLOR_SELECTION_DIALOG (csd)->colorsel),
4910                                          TRUE);
4911     
4912     /* Set as modal */
4913     gtk_window_set_modal (GTK_WINDOW(csd),TRUE);
4914
4915     /* And mark it as a transient dialog */
4916     gtk_window_set_transient_for (GTK_WINDOW (csd), GTK_WINDOW (parent));
4917     
4918     g_signal_connect (csd, "destroy",
4919                       G_CALLBACK (cmw_destroy_cb), NULL);
4920
4921     g_signal_connect_swapped (GTK_COLOR_SELECTION_DIALOG (csd)->ok_button,
4922                              "clicked", G_CALLBACK (gtk_widget_destroy), csd);
4923     g_signal_connect_swapped (GTK_COLOR_SELECTION_DIALOG (csd)->cancel_button,
4924                              "clicked", G_CALLBACK (gtk_widget_destroy), csd);
4925     
4926     /* wait until destroy calls gtk_main_quit */
4927     gtk_widget_show (csd);    
4928     gtk_main ();
4929 }
4930
4931 static void
4932 cmw_file (GtkWidget *widget, GtkWidget *parent)
4933 {
4934     GtkWidget *fs;
4935
4936     fs = gtk_file_selection_new("This is a modal file selection dialog");
4937
4938     gtk_window_set_screen (GTK_WINDOW (fs), gtk_widget_get_screen (parent));
4939
4940     /* Set as modal */
4941     gtk_window_set_modal (GTK_WINDOW(fs),TRUE);
4942
4943     /* And mark it as a transient dialog */
4944     gtk_window_set_transient_for (GTK_WINDOW (fs), GTK_WINDOW (parent));
4945
4946     g_signal_connect (fs, "destroy",
4947                       G_CALLBACK (cmw_destroy_cb), NULL);
4948
4949     g_signal_connect_swapped (GTK_FILE_SELECTION (fs)->ok_button,
4950                               "clicked", G_CALLBACK (gtk_widget_destroy), fs);
4951     g_signal_connect_swapped (GTK_FILE_SELECTION (fs)->cancel_button,
4952                               "clicked", G_CALLBACK (gtk_widget_destroy), fs);
4953     
4954     /* wait until destroy calls gtk_main_quit */
4955     gtk_widget_show (fs);
4956     
4957     gtk_main();
4958 }
4959
4960
4961 static void
4962 create_modal_window (GtkWidget *widget)
4963 {
4964   GtkWidget *window = NULL;
4965   GtkWidget *box1,*box2;
4966   GtkWidget *frame1;
4967   GtkWidget *btnColor,*btnFile,*btnClose;
4968
4969   /* Create modal window (Here you can use any window descendent )*/
4970   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
4971   gtk_window_set_screen (GTK_WINDOW (window),
4972                          gtk_widget_get_screen (widget));
4973
4974   gtk_window_set_title (GTK_WINDOW(window),"This window is modal");
4975
4976   /* Set window as modal */
4977   gtk_window_set_modal (GTK_WINDOW(window),TRUE);
4978
4979   /* Create widgets */
4980   box1 = gtk_vbox_new (FALSE,5);
4981   frame1 = gtk_frame_new ("Standard dialogs in modal form");
4982   box2 = gtk_vbox_new (TRUE,5);
4983   btnColor = gtk_button_new_with_label ("Color");
4984   btnFile = gtk_button_new_with_label ("File Selection");
4985   btnClose = gtk_button_new_with_label ("Close");
4986
4987   /* Init widgets */
4988   gtk_container_set_border_width (GTK_CONTAINER (box1), 3);
4989   gtk_container_set_border_width (GTK_CONTAINER (box2), 3);
4990     
4991   /* Pack widgets */
4992   gtk_container_add (GTK_CONTAINER (window), box1);
4993   gtk_box_pack_start (GTK_BOX (box1), frame1, TRUE, TRUE, 4);
4994   gtk_container_add (GTK_CONTAINER (frame1), box2);
4995   gtk_box_pack_start (GTK_BOX (box2), btnColor, FALSE, FALSE, 4);
4996   gtk_box_pack_start (GTK_BOX (box2), btnFile, FALSE, FALSE, 4);
4997   gtk_box_pack_start (GTK_BOX (box1), gtk_hseparator_new (), FALSE, FALSE, 4);
4998   gtk_box_pack_start (GTK_BOX (box1), btnClose, FALSE, FALSE, 4);
4999    
5000   /* connect signals */
5001   g_signal_connect_swapped (btnClose, "clicked",
5002                             G_CALLBACK (gtk_widget_destroy), window);
5003
5004   g_signal_connect (window, "destroy",
5005                     G_CALLBACK (cmw_destroy_cb), NULL);
5006   
5007   g_signal_connect (btnColor, "clicked",
5008                     G_CALLBACK (cmw_color), window);
5009   g_signal_connect (btnFile, "clicked",
5010                     G_CALLBACK (cmw_file), window);
5011
5012   /* Show widgets */
5013   gtk_widget_show_all (window);
5014
5015   /* wait until dialog get destroyed */
5016   gtk_main();
5017 }
5018
5019 /*
5020  * GtkMessageDialog
5021  */
5022
5023 static void
5024 make_message_dialog (GdkScreen *screen,
5025                      GtkWidget **dialog,
5026                      GtkMessageType  type,
5027                      GtkButtonsType  buttons,
5028                      guint           default_response)
5029 {
5030   if (*dialog)
5031     {
5032       gtk_widget_destroy (*dialog);
5033
5034       return;
5035     }
5036
5037   *dialog = gtk_message_dialog_new (NULL, 0, type, buttons,
5038                                     "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.)");
5039
5040   gtk_window_set_screen (GTK_WINDOW (*dialog), screen);
5041
5042   g_signal_connect_swapped (*dialog,
5043                             "response",
5044                             G_CALLBACK (gtk_widget_destroy),
5045                             *dialog);
5046   
5047   g_signal_connect (*dialog,
5048                     "destroy",
5049                     G_CALLBACK (gtk_widget_destroyed),
5050                     dialog);
5051
5052   gtk_dialog_set_default_response (GTK_DIALOG (*dialog), default_response);
5053
5054   gtk_widget_show (*dialog);
5055 }
5056
5057 static void
5058 create_message_dialog (GtkWidget *widget)
5059 {
5060   static GtkWidget *info = NULL;
5061   static GtkWidget *warning = NULL;
5062   static GtkWidget *error = NULL;
5063   static GtkWidget *question = NULL;
5064   GdkScreen *screen = gtk_widget_get_screen (widget);
5065
5066   make_message_dialog (screen, &info, GTK_MESSAGE_INFO, GTK_BUTTONS_OK, GTK_RESPONSE_OK);
5067   make_message_dialog (screen, &warning, GTK_MESSAGE_WARNING, GTK_BUTTONS_CLOSE, GTK_RESPONSE_CLOSE);
5068   make_message_dialog (screen, &error, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK_CANCEL, GTK_RESPONSE_OK);
5069   make_message_dialog (screen, &question, GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO, GTK_RESPONSE_NO);
5070 }
5071
5072 /*
5073  * GtkScrolledWindow
5074  */
5075
5076 static GtkWidget *sw_parent = NULL;
5077 static GtkWidget *sw_float_parent;
5078 static guint sw_destroyed_handler = 0;
5079
5080 static gboolean
5081 scrolled_windows_delete_cb (GtkWidget *widget, GdkEventAny *event, GtkWidget *scrollwin)
5082 {
5083   gtk_widget_reparent (scrollwin, sw_parent);
5084   
5085   g_signal_handler_disconnect (sw_parent, sw_destroyed_handler);
5086   sw_float_parent = NULL;
5087   sw_parent = NULL;
5088   sw_destroyed_handler = 0;
5089
5090   return FALSE;
5091 }
5092
5093 static void
5094 scrolled_windows_destroy_cb (GtkWidget *widget, GtkWidget *scrollwin)
5095 {
5096   gtk_widget_destroy (sw_float_parent);
5097
5098   sw_float_parent = NULL;
5099   sw_parent = NULL;
5100   sw_destroyed_handler = 0;
5101 }
5102
5103 static void
5104 scrolled_windows_remove (GtkWidget *widget, GtkWidget *scrollwin)
5105 {
5106   if (sw_parent)
5107     {
5108       gtk_widget_reparent (scrollwin, sw_parent);
5109       gtk_widget_destroy (sw_float_parent);
5110
5111       g_signal_handler_disconnect (sw_parent, sw_destroyed_handler);
5112       sw_float_parent = NULL;
5113       sw_parent = NULL;
5114       sw_destroyed_handler = 0;
5115     }
5116   else
5117     {
5118       sw_parent = scrollwin->parent;
5119       sw_float_parent = gtk_window_new (GTK_WINDOW_TOPLEVEL);
5120       gtk_window_set_screen (GTK_WINDOW (sw_float_parent),
5121                              gtk_widget_get_screen (widget));
5122       
5123       gtk_window_set_default_size (GTK_WINDOW (sw_float_parent), 200, 200);
5124       
5125       gtk_widget_reparent (scrollwin, sw_float_parent);
5126       gtk_widget_show (sw_float_parent);
5127
5128       sw_destroyed_handler =
5129         g_signal_connect (sw_parent, "destroy",
5130                           G_CALLBACK (scrolled_windows_destroy_cb), scrollwin);
5131       g_signal_connect (sw_float_parent, "delete_event",
5132                         G_CALLBACK (scrolled_windows_delete_cb), scrollwin);
5133     }
5134 }
5135
5136 static void
5137 create_scrolled_windows (GtkWidget *widget)
5138 {
5139   static GtkWidget *window;
5140   GtkWidget *scrolled_window;
5141   GtkWidget *table;
5142   GtkWidget *button;
5143   char buffer[32];
5144   int i, j;
5145
5146   if (!window)
5147     {
5148       window = gtk_dialog_new ();
5149
5150       gtk_window_set_screen (GTK_WINDOW (window),
5151                              gtk_widget_get_screen (widget));
5152
5153       g_signal_connect (window, "destroy",
5154                         G_CALLBACK (gtk_widget_destroyed),
5155                         &window);
5156
5157       gtk_window_set_title (GTK_WINDOW (window), "dialog");
5158       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
5159
5160
5161       scrolled_window = gtk_scrolled_window_new (NULL, NULL);
5162       gtk_container_set_border_width (GTK_CONTAINER (scrolled_window), 10);
5163       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
5164                                       GTK_POLICY_AUTOMATIC,
5165                                       GTK_POLICY_AUTOMATIC);
5166       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
5167                           scrolled_window, TRUE, TRUE, 0);
5168       gtk_widget_show (scrolled_window);
5169
5170       table = gtk_table_new (20, 20, FALSE);
5171       gtk_table_set_row_spacings (GTK_TABLE (table), 10);
5172       gtk_table_set_col_spacings (GTK_TABLE (table), 10);
5173       gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_window), table);
5174       gtk_container_set_focus_hadjustment (GTK_CONTAINER (table),
5175                                            gtk_scrolled_window_get_hadjustment (GTK_SCROLLED_WINDOW (scrolled_window)));
5176       gtk_container_set_focus_vadjustment (GTK_CONTAINER (table),
5177                                            gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (scrolled_window)));
5178       gtk_widget_show (table);
5179
5180       for (i = 0; i < 20; i++)
5181         for (j = 0; j < 20; j++)
5182           {
5183             sprintf (buffer, "button (%d,%d)\n", i, j);
5184             button = gtk_toggle_button_new_with_label (buffer);
5185             gtk_table_attach_defaults (GTK_TABLE (table), button,
5186                                        i, i+1, j, j+1);
5187             gtk_widget_show (button);
5188           }
5189
5190
5191       button = gtk_button_new_with_label ("Close");
5192       g_signal_connect_swapped (button, "clicked",
5193                                 G_CALLBACK (gtk_widget_destroy),
5194                                 window);
5195       gtk_widget_set_can_default (button, TRUE);
5196       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
5197                           button, TRUE, TRUE, 0);
5198       gtk_widget_grab_default (button);
5199       gtk_widget_show (button);
5200
5201       button = gtk_button_new_with_label ("Reparent Out");
5202       g_signal_connect (button, "clicked",
5203                         G_CALLBACK (scrolled_windows_remove),
5204                         scrolled_window);
5205       gtk_widget_set_can_default (button, TRUE);
5206       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
5207                           button, TRUE, TRUE, 0);
5208       gtk_widget_grab_default (button);
5209       gtk_widget_show (button);
5210
5211       gtk_window_set_default_size (GTK_WINDOW (window), 300, 300);
5212     }
5213
5214   if (!gtk_widget_get_visible (window))
5215     gtk_widget_show (window);
5216   else
5217     gtk_widget_destroy (window);
5218 }
5219
5220 /*
5221  * GtkEntry
5222  */
5223
5224 static void
5225 entry_toggle_frame (GtkWidget *checkbutton,
5226                     GtkWidget *entry)
5227 {
5228    gtk_entry_set_has_frame (GTK_ENTRY(entry),
5229                             GTK_TOGGLE_BUTTON(checkbutton)->active);
5230 }
5231
5232 static void
5233 entry_toggle_sensitive (GtkWidget *checkbutton,
5234                         GtkWidget *entry)
5235 {
5236    gtk_widget_set_sensitive (entry, GTK_TOGGLE_BUTTON(checkbutton)->active);
5237 }
5238
5239 static gboolean
5240 entry_progress_timeout (gpointer data)
5241 {
5242   if (GPOINTER_TO_INT (g_object_get_data (G_OBJECT (data), "progress-pulse")))
5243     {
5244       gtk_entry_progress_pulse (GTK_ENTRY (data));
5245     }
5246   else
5247     {
5248       gdouble fraction;
5249
5250       fraction = gtk_entry_get_progress_fraction (GTK_ENTRY (data));
5251
5252       fraction += 0.05;
5253       if (fraction > 1.0001)
5254         fraction = 0.0;
5255
5256       gtk_entry_set_progress_fraction (GTK_ENTRY (data), fraction);
5257     }
5258
5259   return TRUE;
5260 }
5261
5262 static void
5263 entry_remove_timeout (gpointer data)
5264 {
5265   g_source_remove (GPOINTER_TO_UINT (data));
5266 }
5267
5268 static void
5269 entry_toggle_progress (GtkWidget *checkbutton,
5270                        GtkWidget *entry)
5271 {
5272   if (GTK_TOGGLE_BUTTON (checkbutton)->active)
5273     {
5274       guint timeout = gdk_threads_add_timeout (100,
5275                                                entry_progress_timeout,
5276                                                entry);
5277       g_object_set_data_full (G_OBJECT (entry), "timeout-id",
5278                               GUINT_TO_POINTER (timeout),
5279                               entry_remove_timeout);
5280     }
5281   else
5282     {
5283       g_object_set_data (G_OBJECT (entry), "timeout-id",
5284                          GUINT_TO_POINTER (0));
5285
5286       gtk_entry_set_progress_fraction (GTK_ENTRY (entry), 0.0);
5287     }
5288 }
5289
5290 static void
5291 entry_toggle_pulse (GtkWidget *checkbutton,
5292                     GtkWidget *entry)
5293 {
5294   g_object_set_data (G_OBJECT (entry), "progress-pulse",
5295                      GUINT_TO_POINTER ((guint) GTK_TOGGLE_BUTTON (checkbutton)->active));
5296 }
5297
5298 static void
5299 props_clicked (GtkWidget *button,
5300                GObject   *object)
5301 {
5302   GtkWidget *window = create_prop_editor (object, 0);
5303
5304   gtk_window_set_title (GTK_WINDOW (window), "Object Properties");
5305 }
5306
5307 static void
5308 create_entry (GtkWidget *widget)
5309 {
5310   static GtkWidget *window = NULL;
5311   GtkWidget *box1;
5312   GtkWidget *box2;
5313   GtkWidget *hbox;
5314   GtkWidget *has_frame_check;
5315   GtkWidget *sensitive_check;
5316   GtkWidget *progress_check;
5317   GtkWidget *entry, *cb;
5318   GtkWidget *button;
5319   GtkWidget *separator;
5320   GList *cbitems = NULL;
5321
5322   if (!window)
5323     {
5324       cbitems = g_list_append(cbitems, "item0");
5325       cbitems = g_list_append(cbitems, "item1 item1");
5326       cbitems = g_list_append(cbitems, "item2 item2 item2");
5327       cbitems = g_list_append(cbitems, "item3 item3 item3 item3");
5328       cbitems = g_list_append(cbitems, "item4 item4 item4 item4 item4");
5329       cbitems = g_list_append(cbitems, "item5 item5 item5 item5 item5 item5");
5330       cbitems = g_list_append(cbitems, "item6 item6 item6 item6 item6");
5331       cbitems = g_list_append(cbitems, "item7 item7 item7 item7");
5332       cbitems = g_list_append(cbitems, "item8 item8 item8");
5333       cbitems = g_list_append(cbitems, "item9 item9");
5334
5335       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
5336       gtk_window_set_screen (GTK_WINDOW (window),
5337                              gtk_widget_get_screen (widget));
5338
5339       g_signal_connect (window, "destroy",
5340                         G_CALLBACK (gtk_widget_destroyed),
5341                         &window);
5342
5343       gtk_window_set_title (GTK_WINDOW (window), "entry");
5344       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
5345
5346
5347       box1 = gtk_vbox_new (FALSE, 0);
5348       gtk_container_add (GTK_CONTAINER (window), box1);
5349
5350
5351       box2 = gtk_vbox_new (FALSE, 10);
5352       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
5353       gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
5354
5355       hbox = gtk_hbox_new (FALSE, 5);
5356       gtk_box_pack_start (GTK_BOX (box2), hbox, TRUE, TRUE, 0);
5357       
5358       entry = gtk_entry_new ();
5359       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");
5360       gtk_editable_select_region (GTK_EDITABLE (entry), 0, 5);
5361       gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0);
5362
5363       button = gtk_button_new_with_mnemonic ("_Props");
5364       gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
5365       g_signal_connect (button, "clicked",
5366                         G_CALLBACK (props_clicked),
5367                         entry);
5368
5369       cb = gtk_combo_new ();
5370       gtk_combo_set_popdown_strings (GTK_COMBO (cb), cbitems);
5371       gtk_entry_set_text (GTK_ENTRY (GTK_COMBO(cb)->entry), "hello world \n\n\n foo");
5372       gtk_editable_select_region (GTK_EDITABLE (GTK_COMBO(cb)->entry),
5373                                   0, -1);
5374       gtk_box_pack_start (GTK_BOX (box2), cb, TRUE, TRUE, 0);
5375
5376       sensitive_check = gtk_check_button_new_with_label("Sensitive");
5377       gtk_box_pack_start (GTK_BOX (box2), sensitive_check, FALSE, TRUE, 0);
5378       g_signal_connect (sensitive_check, "toggled",
5379                         G_CALLBACK (entry_toggle_sensitive), entry);
5380       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sensitive_check), TRUE);
5381
5382       has_frame_check = gtk_check_button_new_with_label("Has Frame");
5383       gtk_box_pack_start (GTK_BOX (box2), has_frame_check, FALSE, TRUE, 0);
5384       g_signal_connect (has_frame_check, "toggled",
5385                         G_CALLBACK (entry_toggle_frame), entry);
5386       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (has_frame_check), TRUE);
5387
5388       progress_check = gtk_check_button_new_with_label("Show Progress");
5389       gtk_box_pack_start (GTK_BOX (box2), progress_check, FALSE, TRUE, 0);
5390       g_signal_connect (progress_check, "toggled",
5391                         G_CALLBACK (entry_toggle_progress), entry);
5392
5393       progress_check = gtk_check_button_new_with_label("Pulse Progress");
5394       gtk_box_pack_start (GTK_BOX (box2), progress_check, FALSE, TRUE, 0);
5395       g_signal_connect (progress_check, "toggled",
5396                         G_CALLBACK (entry_toggle_pulse), entry);
5397
5398       separator = gtk_hseparator_new ();
5399       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
5400
5401       box2 = gtk_vbox_new (FALSE, 10);
5402       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
5403       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
5404
5405       button = gtk_button_new_with_label ("close");
5406       g_signal_connect_swapped (button, "clicked",
5407                                 G_CALLBACK (gtk_widget_destroy),
5408                                 window);
5409       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
5410       gtk_widget_set_can_default (button, TRUE);
5411       gtk_widget_grab_default (button);
5412     }
5413
5414   if (!gtk_widget_get_visible (window))
5415     gtk_widget_show_all (window);
5416   else
5417     gtk_widget_destroy (window);
5418 }
5419
5420 static void
5421 create_expander (GtkWidget *widget)
5422 {
5423   GtkWidget *box1;
5424   GtkWidget *expander;
5425   GtkWidget *hidden;
5426   static GtkWidget *window = NULL;
5427
5428   if (!window)
5429     {
5430       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
5431       gtk_window_set_screen (GTK_WINDOW (window),
5432                              gtk_widget_get_screen (widget));
5433       
5434       g_signal_connect (window, "destroy",
5435                         G_CALLBACK (gtk_widget_destroyed),
5436                         &window);
5437       
5438       gtk_window_set_title (GTK_WINDOW (window), "expander");
5439       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
5440       
5441       box1 = gtk_vbox_new (FALSE, 0);
5442       gtk_container_add (GTK_CONTAINER (window), box1);
5443       
5444       expander = gtk_expander_new ("The Hidden");
5445       
5446       gtk_box_pack_start (GTK_BOX (box1), expander, TRUE, TRUE, 0);
5447       
5448       hidden = gtk_label_new ("Revealed!");
5449       
5450       gtk_container_add (GTK_CONTAINER (expander), hidden);
5451     }
5452   
5453   if (!gtk_widget_get_visible (window))
5454     gtk_widget_show_all (window);
5455   else
5456     gtk_widget_destroy (window);
5457 }
5458
5459
5460 /* GtkEventBox */
5461
5462
5463 static void
5464 event_box_label_pressed (GtkWidget        *widget,
5465                          GdkEventButton   *event,
5466                          gpointer user_data)
5467 {
5468   g_print ("clicked on event box\n");
5469 }
5470
5471 static void
5472 event_box_button_clicked (GtkWidget *widget,
5473                           GtkWidget *button,
5474                           gpointer user_data)
5475 {
5476   g_print ("pushed button\n");
5477 }
5478
5479 static void
5480 event_box_toggle_visible_window (GtkWidget *checkbutton,
5481                                  GtkEventBox *event_box)
5482 {
5483   gtk_event_box_set_visible_window (event_box,
5484                                     GTK_TOGGLE_BUTTON(checkbutton)->active);
5485 }
5486
5487 static void
5488 event_box_toggle_above_child (GtkWidget *checkbutton,
5489                               GtkEventBox *event_box)
5490 {
5491   gtk_event_box_set_above_child (event_box,
5492                                  GTK_TOGGLE_BUTTON(checkbutton)->active);
5493 }
5494
5495 static void
5496 create_event_box (GtkWidget *widget)
5497 {
5498   static GtkWidget *window = NULL;
5499   GtkWidget *box1;
5500   GtkWidget *box2;
5501   GtkWidget *hbox;
5502   GtkWidget *vbox;
5503   GtkWidget *button;
5504   GtkWidget *separator;
5505   GtkWidget *event_box;
5506   GtkWidget *label;
5507   GtkWidget *visible_window_check;
5508   GtkWidget *above_child_check;
5509   GdkColor color;
5510
5511   if (!window)
5512     {
5513       color.red = 0;
5514       color.blue = 65535;
5515       color.green = 0;
5516       
5517       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
5518       gtk_window_set_screen (GTK_WINDOW (window),
5519                              gtk_widget_get_screen (widget));
5520
5521       g_signal_connect (window, "destroy",
5522                         G_CALLBACK (gtk_widget_destroyed),
5523                         &window);
5524
5525       gtk_window_set_title (GTK_WINDOW (window), "event box");
5526       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
5527
5528       box1 = gtk_vbox_new (FALSE, 0);
5529       gtk_container_add (GTK_CONTAINER (window), box1);
5530       gtk_widget_modify_bg (window, GTK_STATE_NORMAL, &color);
5531
5532       hbox = gtk_hbox_new (FALSE, 0);
5533       gtk_box_pack_start (GTK_BOX (box1), hbox, TRUE, FALSE, 0);
5534       
5535       event_box = gtk_event_box_new ();
5536       gtk_box_pack_start (GTK_BOX (hbox), event_box, TRUE, FALSE, 0);
5537
5538       vbox = gtk_vbox_new (FALSE, 0);
5539       gtk_container_add (GTK_CONTAINER (event_box), vbox);
5540       g_signal_connect (event_box, "button_press_event",
5541                         G_CALLBACK (event_box_label_pressed),
5542                         NULL);
5543       
5544       label = gtk_label_new ("Click on this label");
5545       gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, FALSE, 0);
5546
5547       button = gtk_button_new_with_label ("button in eventbox");
5548       gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, FALSE, 0);
5549       g_signal_connect (button, "clicked",
5550                         G_CALLBACK (event_box_button_clicked),
5551                         NULL);
5552       
5553
5554       visible_window_check = gtk_check_button_new_with_label("Visible Window");
5555       gtk_box_pack_start (GTK_BOX (box1), visible_window_check, FALSE, TRUE, 0);
5556       g_signal_connect (visible_window_check, "toggled",
5557                         G_CALLBACK (event_box_toggle_visible_window), event_box);
5558       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (visible_window_check), FALSE);
5559       
5560       above_child_check = gtk_check_button_new_with_label("Above Child");
5561       gtk_box_pack_start (GTK_BOX (box1), above_child_check, FALSE, TRUE, 0);
5562       g_signal_connect (above_child_check, "toggled",
5563                         G_CALLBACK (event_box_toggle_above_child), event_box);
5564       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (above_child_check), FALSE);
5565       
5566       separator = gtk_hseparator_new ();
5567       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
5568
5569       box2 = gtk_vbox_new (FALSE, 10);
5570       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
5571       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
5572
5573       button = gtk_button_new_with_label ("close");
5574       g_signal_connect_swapped (button, "clicked",
5575                                 G_CALLBACK (gtk_widget_destroy),
5576                                 window);
5577       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
5578       gtk_widget_set_can_default (button, TRUE);
5579       gtk_widget_grab_default (button);
5580     }
5581
5582   if (!gtk_widget_get_visible (window))
5583     gtk_widget_show_all (window);
5584   else
5585     gtk_widget_destroy (window);
5586 }
5587
5588
5589 /*
5590  * GtkSizeGroup
5591  */
5592
5593 #define SIZE_GROUP_INITIAL_SIZE 50
5594
5595 static void
5596 size_group_hsize_changed (GtkSpinButton *spin_button,
5597                           GtkWidget     *button)
5598 {
5599   gtk_widget_set_size_request (GTK_BIN (button)->child,
5600                                gtk_spin_button_get_value_as_int (spin_button),
5601                                -1);
5602 }
5603
5604 static void
5605 size_group_vsize_changed (GtkSpinButton *spin_button,
5606                           GtkWidget     *button)
5607 {
5608   gtk_widget_set_size_request (GTK_BIN (button)->child,
5609                                -1,
5610                                gtk_spin_button_get_value_as_int (spin_button));
5611 }
5612
5613 static GtkWidget *
5614 create_size_group_window (GdkScreen    *screen,
5615                           GtkSizeGroup *master_size_group)
5616 {
5617   GtkWidget *window;
5618   GtkWidget *table;
5619   GtkWidget *main_button;
5620   GtkWidget *button;
5621   GtkWidget *spin_button;
5622   GtkWidget *hbox;
5623   GtkSizeGroup *hgroup1;
5624   GtkSizeGroup *hgroup2;
5625   GtkSizeGroup *vgroup1;
5626   GtkSizeGroup *vgroup2;
5627
5628   window = gtk_dialog_new_with_buttons ("GtkSizeGroup",
5629                                         NULL, 0,
5630                                         GTK_STOCK_CLOSE,
5631                                         GTK_RESPONSE_NONE,
5632                                         NULL);
5633
5634   gtk_window_set_screen (GTK_WINDOW (window), screen);
5635
5636   gtk_window_set_resizable (GTK_WINDOW (window), TRUE);
5637
5638   g_signal_connect (window, "response",
5639                     G_CALLBACK (gtk_widget_destroy),
5640                     NULL);
5641
5642   table = gtk_table_new (2, 2, FALSE);
5643   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), table, TRUE, TRUE, 0);
5644
5645   gtk_table_set_row_spacings (GTK_TABLE (table), 5);
5646   gtk_table_set_col_spacings (GTK_TABLE (table), 5);
5647   gtk_container_set_border_width (GTK_CONTAINER (table), 5);
5648   gtk_widget_set_size_request (table, 250, 250);
5649
5650   hgroup1 = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
5651   hgroup2 = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
5652   vgroup1 = gtk_size_group_new (GTK_SIZE_GROUP_VERTICAL);
5653   vgroup2 = gtk_size_group_new (GTK_SIZE_GROUP_VERTICAL);
5654
5655   main_button = gtk_button_new_with_label ("X");
5656   
5657   gtk_table_attach (GTK_TABLE (table), main_button,
5658                     0, 1,       0, 1,
5659                     GTK_EXPAND, GTK_EXPAND,
5660                     0,          0);
5661   gtk_size_group_add_widget (master_size_group, main_button);
5662   gtk_size_group_add_widget (hgroup1, main_button);
5663   gtk_size_group_add_widget (vgroup1, main_button);
5664   gtk_widget_set_size_request (GTK_BIN (main_button)->child,
5665                                SIZE_GROUP_INITIAL_SIZE,
5666                                SIZE_GROUP_INITIAL_SIZE);
5667
5668   button = gtk_button_new ();
5669   gtk_table_attach (GTK_TABLE (table), button,
5670                     1, 2,       0, 1,
5671                     GTK_EXPAND, GTK_EXPAND,
5672                     0,          0);
5673   gtk_size_group_add_widget (vgroup1, button);
5674   gtk_size_group_add_widget (vgroup2, button);
5675
5676   button = gtk_button_new ();
5677   gtk_table_attach (GTK_TABLE (table), button,
5678                     0, 1,       1, 2,
5679                     GTK_EXPAND, GTK_EXPAND,
5680                     0,          0);
5681   gtk_size_group_add_widget (hgroup1, button);
5682   gtk_size_group_add_widget (hgroup2, button);
5683
5684   button = gtk_button_new ();
5685   gtk_table_attach (GTK_TABLE (table), button,
5686                     1, 2,       1, 2,
5687                     GTK_EXPAND, GTK_EXPAND,
5688                     0,          0);
5689   gtk_size_group_add_widget (hgroup2, button);
5690   gtk_size_group_add_widget (vgroup2, button);
5691
5692   g_object_unref (hgroup1);
5693   g_object_unref (hgroup2);
5694   g_object_unref (vgroup1);
5695   g_object_unref (vgroup2);
5696   
5697   hbox = gtk_hbox_new (FALSE, 5);
5698   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), hbox, FALSE, FALSE, 0);
5699   
5700   spin_button = gtk_spin_button_new_with_range (1, 100, 1);
5701   gtk_spin_button_set_value (GTK_SPIN_BUTTON (spin_button), SIZE_GROUP_INITIAL_SIZE);
5702   gtk_box_pack_start (GTK_BOX (hbox), spin_button, TRUE, TRUE, 0);
5703   g_signal_connect (spin_button, "value_changed",
5704                     G_CALLBACK (size_group_hsize_changed), main_button);
5705
5706   spin_button = gtk_spin_button_new_with_range (1, 100, 1);
5707   gtk_spin_button_set_value (GTK_SPIN_BUTTON (spin_button), SIZE_GROUP_INITIAL_SIZE);
5708   gtk_box_pack_start (GTK_BOX (hbox), spin_button, TRUE, TRUE, 0);
5709   g_signal_connect (spin_button, "value_changed",
5710                     G_CALLBACK (size_group_vsize_changed), main_button);
5711
5712   return window;
5713 }
5714
5715 static void
5716 create_size_groups (GtkWidget *widget)
5717 {
5718   static GtkWidget *window1 = NULL;
5719   static GtkWidget *window2 = NULL;
5720   static GtkSizeGroup *master_size_group;
5721
5722   if (!master_size_group)
5723     master_size_group = gtk_size_group_new (GTK_SIZE_GROUP_BOTH);
5724
5725   if (!window1)
5726     {
5727       window1 = create_size_group_window (gtk_widget_get_screen (widget),
5728                                           master_size_group);
5729
5730       g_signal_connect (window1, "destroy",
5731                         G_CALLBACK (gtk_widget_destroyed),
5732                         &window1);
5733     }
5734
5735   if (!window2)
5736     {
5737       window2 = create_size_group_window (gtk_widget_get_screen (widget),
5738                                           master_size_group);
5739
5740       g_signal_connect (window2, "destroy",
5741                         G_CALLBACK (gtk_widget_destroyed),
5742                         &window2);
5743     }
5744
5745   if (gtk_widget_get_visible (window1) && gtk_widget_get_visible (window2))
5746     {
5747       gtk_widget_destroy (window1);
5748       gtk_widget_destroy (window2);
5749     }
5750   else
5751     {
5752       if (!gtk_widget_get_visible (window1))
5753         gtk_widget_show_all (window1);
5754       if (!gtk_widget_get_visible (window2))
5755         gtk_widget_show_all (window2);
5756     }
5757 }
5758
5759 /*
5760  * GtkSpinButton
5761  */
5762
5763 static GtkWidget *spinner1;
5764
5765 static void
5766 toggle_snap (GtkWidget *widget, GtkSpinButton *spin)
5767 {
5768   gtk_spin_button_set_snap_to_ticks (spin, GTK_TOGGLE_BUTTON (widget)->active);
5769 }
5770
5771 static void
5772 toggle_numeric (GtkWidget *widget, GtkSpinButton *spin)
5773 {
5774   gtk_spin_button_set_numeric (spin, GTK_TOGGLE_BUTTON (widget)->active);
5775 }
5776
5777 static void
5778 change_digits (GtkWidget *widget, GtkSpinButton *spin)
5779 {
5780   gtk_spin_button_set_digits (GTK_SPIN_BUTTON (spinner1),
5781                               gtk_spin_button_get_value_as_int (spin));
5782 }
5783
5784 static void
5785 get_value (GtkWidget *widget, gpointer data)
5786 {
5787   gchar buf[32];
5788   GtkLabel *label;
5789   GtkSpinButton *spin;
5790
5791   spin = GTK_SPIN_BUTTON (spinner1);
5792   label = GTK_LABEL (g_object_get_data (G_OBJECT (widget), "user_data"));
5793   if (GPOINTER_TO_INT (data) == 1)
5794     sprintf (buf, "%d", gtk_spin_button_get_value_as_int (spin));
5795   else
5796     sprintf (buf, "%0.*f", spin->digits, gtk_spin_button_get_value (spin));
5797   gtk_label_set_text (label, buf);
5798 }
5799
5800 static void
5801 get_spin_value (GtkWidget *widget, gpointer data)
5802 {
5803   gchar *buffer;
5804   GtkLabel *label;
5805   GtkSpinButton *spin;
5806
5807   spin = GTK_SPIN_BUTTON (widget);
5808   label = GTK_LABEL (data);
5809
5810   buffer = g_strdup_printf ("%0.*f", spin->digits,
5811                             gtk_spin_button_get_value (spin));
5812   gtk_label_set_text (label, buffer);
5813
5814   g_free (buffer);
5815 }
5816
5817 static gint
5818 spin_button_time_output_func (GtkSpinButton *spin_button)
5819 {
5820   static gchar buf[6];
5821   gdouble hours;
5822   gdouble minutes;
5823
5824   hours = spin_button->adjustment->value / 60.0;
5825   minutes = (fabs(floor (hours) - hours) < 1e-5) ? 0.0 : 30;
5826   sprintf (buf, "%02.0f:%02.0f", floor (hours), minutes);
5827   if (strcmp (buf, gtk_entry_get_text (GTK_ENTRY (spin_button))))
5828     gtk_entry_set_text (GTK_ENTRY (spin_button), buf);
5829   return TRUE;
5830 }
5831
5832 static gint
5833 spin_button_month_input_func (GtkSpinButton *spin_button,
5834                               gdouble       *new_val)
5835 {
5836   gint i;
5837   static gchar *month[12] = { "January", "February", "March", "April",
5838                               "May", "June", "July", "August",
5839                               "September", "October", "November", "December" };
5840   gchar *tmp1, *tmp2;
5841   gboolean found = FALSE;
5842
5843   for (i = 1; i <= 12; i++)
5844     {
5845       tmp1 = g_ascii_strup (month[i - 1], -1);
5846       tmp2 = g_ascii_strup (gtk_entry_get_text (GTK_ENTRY (spin_button)), -1);
5847       if (strstr (tmp1, tmp2) == tmp1)
5848         found = TRUE;
5849       g_free (tmp1);
5850       g_free (tmp2);
5851       if (found)
5852         break;
5853     }
5854   if (!found)
5855     {
5856       *new_val = 0.0;
5857       return GTK_INPUT_ERROR;
5858     }
5859   *new_val = (gdouble) i;
5860   return TRUE;
5861 }
5862
5863 static gint
5864 spin_button_month_output_func (GtkSpinButton *spin_button)
5865 {
5866   gint i;
5867   static gchar *month[12] = { "January", "February", "March", "April",
5868                               "May", "June", "July", "August", "September",
5869                               "October", "November", "December" };
5870
5871   for (i = 1; i <= 12; i++)
5872     if (fabs (spin_button->adjustment->value - (double)i) < 1e-5)
5873       {
5874         if (strcmp (month[i-1], gtk_entry_get_text (GTK_ENTRY (spin_button))))
5875           gtk_entry_set_text (GTK_ENTRY (spin_button), month[i-1]);
5876       }
5877   return TRUE;
5878 }
5879
5880 static gint
5881 spin_button_hex_input_func (GtkSpinButton *spin_button,
5882                             gdouble       *new_val)
5883 {
5884   const gchar *buf;
5885   gchar *err;
5886   gdouble res;
5887
5888   buf = gtk_entry_get_text (GTK_ENTRY (spin_button));
5889   res = strtol(buf, &err, 16);
5890   *new_val = res;
5891   if (*err)
5892     return GTK_INPUT_ERROR;
5893   else
5894     return TRUE;
5895 }
5896
5897 static gint
5898 spin_button_hex_output_func (GtkSpinButton *spin_button)
5899 {
5900   static gchar buf[7];
5901   gint val;
5902
5903   val = (gint) spin_button->adjustment->value;
5904   if (fabs (val) < 1e-5)
5905     sprintf (buf, "0x00");
5906   else
5907     sprintf (buf, "0x%.2X", val);
5908   if (strcmp (buf, gtk_entry_get_text (GTK_ENTRY (spin_button))))
5909     gtk_entry_set_text (GTK_ENTRY (spin_button), buf);
5910   return TRUE;
5911 }
5912
5913 static void
5914 create_spins (GtkWidget *widget)
5915 {
5916   static GtkWidget *window = NULL;
5917   GtkWidget *frame;
5918   GtkWidget *hbox;
5919   GtkWidget *main_vbox;
5920   GtkWidget *vbox;
5921   GtkWidget *vbox2;
5922   GtkWidget *spinner2;
5923   GtkWidget *spinner;
5924   GtkWidget *button;
5925   GtkWidget *label;
5926   GtkWidget *val_label;
5927   GtkAdjustment *adj;
5928
5929   if (!window)
5930     {
5931       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
5932       gtk_window_set_screen (GTK_WINDOW (window),
5933                              gtk_widget_get_screen (widget));
5934       
5935       g_signal_connect (window, "destroy",
5936                         G_CALLBACK (gtk_widget_destroyed),
5937                         &window);
5938       
5939       gtk_window_set_title (GTK_WINDOW (window), "GtkSpinButton");
5940       
5941       main_vbox = gtk_vbox_new (FALSE, 5);
5942       gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 10);
5943       gtk_container_add (GTK_CONTAINER (window), main_vbox);
5944       
5945       frame = gtk_frame_new ("Not accelerated");
5946       gtk_box_pack_start (GTK_BOX (main_vbox), frame, TRUE, TRUE, 0);
5947       
5948       vbox = gtk_vbox_new (FALSE, 0);
5949       gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
5950       gtk_container_add (GTK_CONTAINER (frame), vbox);
5951       
5952       /* Time, month, hex spinners */
5953       
5954       hbox = gtk_hbox_new (FALSE, 0);
5955       gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 5);
5956       
5957       vbox2 = gtk_vbox_new (FALSE, 0);
5958       gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 5);
5959       
5960       label = gtk_label_new ("Time :");
5961       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
5962       gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
5963       
5964       adj = (GtkAdjustment *) gtk_adjustment_new (0, 0, 1410, 30, 60, 0);
5965       spinner = gtk_spin_button_new (adj, 0, 0);
5966       gtk_editable_set_editable (GTK_EDITABLE (spinner), FALSE);
5967       g_signal_connect (spinner,
5968                         "output",
5969                         G_CALLBACK (spin_button_time_output_func),
5970                         NULL);
5971       gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner), TRUE);
5972       gtk_entry_set_width_chars (GTK_ENTRY (spinner), 5);
5973       gtk_box_pack_start (GTK_BOX (vbox2), spinner, FALSE, TRUE, 0);
5974
5975       vbox2 = gtk_vbox_new (FALSE, 0);
5976       gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 5);
5977       
5978       label = gtk_label_new ("Month :");
5979       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
5980       gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
5981       
5982       adj = (GtkAdjustment *) gtk_adjustment_new (1.0, 1.0, 12.0, 1.0,
5983                                                   5.0, 0.0);
5984       spinner = gtk_spin_button_new (adj, 0, 0);
5985       gtk_spin_button_set_update_policy (GTK_SPIN_BUTTON (spinner),
5986                                          GTK_UPDATE_IF_VALID);
5987       g_signal_connect (spinner,
5988                         "input",
5989                         G_CALLBACK (spin_button_month_input_func),
5990                         NULL);
5991       g_signal_connect (spinner,
5992                         "output",
5993                         G_CALLBACK (spin_button_month_output_func),
5994                         NULL);
5995       gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner), TRUE);
5996       gtk_entry_set_width_chars (GTK_ENTRY (spinner), 9);
5997       gtk_box_pack_start (GTK_BOX (vbox2), spinner, FALSE, TRUE, 0);
5998       
5999       vbox2 = gtk_vbox_new (FALSE, 0);
6000       gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 5);
6001
6002       label = gtk_label_new ("Hex :");
6003       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
6004       gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
6005
6006       adj = (GtkAdjustment *) gtk_adjustment_new (0, 0, 255, 1, 16, 0);
6007       spinner = gtk_spin_button_new (adj, 0, 0);
6008       gtk_editable_set_editable (GTK_EDITABLE (spinner), TRUE);
6009       g_signal_connect (spinner,
6010                         "input",
6011                         G_CALLBACK (spin_button_hex_input_func),
6012                         NULL);
6013       g_signal_connect (spinner,
6014                         "output",
6015                         G_CALLBACK (spin_button_hex_output_func),
6016                         NULL);
6017       gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner), TRUE);
6018       gtk_entry_set_width_chars (GTK_ENTRY (spinner), 4);
6019       gtk_box_pack_start (GTK_BOX (vbox2), spinner, FALSE, TRUE, 0);
6020
6021       frame = gtk_frame_new ("Accelerated");
6022       gtk_box_pack_start (GTK_BOX (main_vbox), frame, TRUE, TRUE, 0);
6023   
6024       vbox = gtk_vbox_new (FALSE, 0);
6025       gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
6026       gtk_container_add (GTK_CONTAINER (frame), vbox);
6027       
6028       hbox = gtk_hbox_new (FALSE, 0);
6029       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 5);
6030       
6031       vbox2 = gtk_vbox_new (FALSE, 0);
6032       gtk_box_pack_start (GTK_BOX (hbox), vbox2, FALSE, FALSE, 5);
6033       
6034       label = gtk_label_new ("Value :");
6035       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
6036       gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
6037
6038       adj = (GtkAdjustment *) gtk_adjustment_new (0.0, -10000.0, 10000.0,
6039                                                   0.5, 100.0, 0.0);
6040       spinner1 = gtk_spin_button_new (adj, 1.0, 2);
6041       gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner1), TRUE);
6042       gtk_box_pack_start (GTK_BOX (vbox2), spinner1, FALSE, TRUE, 0);
6043
6044       vbox2 = gtk_vbox_new (FALSE, 0);
6045       gtk_box_pack_start (GTK_BOX (hbox), vbox2, FALSE, FALSE, 5);
6046
6047       label = gtk_label_new ("Digits :");
6048       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
6049       gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
6050
6051       adj = (GtkAdjustment *) gtk_adjustment_new (2, 1, 15, 1, 1, 0);
6052       spinner2 = gtk_spin_button_new (adj, 0.0, 0);
6053       g_signal_connect (adj, "value_changed",
6054                         G_CALLBACK (change_digits),
6055                         spinner2);
6056       gtk_box_pack_start (GTK_BOX (vbox2), spinner2, FALSE, TRUE, 0);
6057
6058       hbox = gtk_hbox_new (FALSE, 0);
6059       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 5);
6060
6061       button = gtk_check_button_new_with_label ("Snap to 0.5-ticks");
6062       g_signal_connect (button, "clicked",
6063                         G_CALLBACK (toggle_snap),
6064                         spinner1);
6065       gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
6066       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
6067
6068       button = gtk_check_button_new_with_label ("Numeric only input mode");
6069       g_signal_connect (button, "clicked",
6070                         G_CALLBACK (toggle_numeric),
6071                         spinner1);
6072       gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
6073       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
6074
6075       val_label = gtk_label_new ("");
6076
6077       hbox = gtk_hbox_new (FALSE, 0);
6078       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 5);
6079
6080       button = gtk_button_new_with_label ("Value as Int");
6081       g_object_set_data (G_OBJECT (button), "user_data", val_label);
6082       g_signal_connect (button, "clicked",
6083                         G_CALLBACK (get_value),
6084                         GINT_TO_POINTER (1));
6085       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
6086
6087       button = gtk_button_new_with_label ("Value as Float");
6088       g_object_set_data (G_OBJECT (button), "user_data", val_label);
6089       g_signal_connect (button, "clicked",
6090                         G_CALLBACK (get_value),
6091                         GINT_TO_POINTER (2));
6092       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
6093
6094       gtk_box_pack_start (GTK_BOX (vbox), val_label, TRUE, TRUE, 0);
6095       gtk_label_set_text (GTK_LABEL (val_label), "0");
6096
6097       frame = gtk_frame_new ("Using Convenience Constructor");
6098       gtk_box_pack_start (GTK_BOX (main_vbox), frame, TRUE, TRUE, 0);
6099   
6100       hbox = gtk_hbox_new (FALSE, 0);
6101       gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
6102       gtk_container_add (GTK_CONTAINER (frame), hbox);
6103       
6104       val_label = gtk_label_new ("0.0");
6105
6106       spinner = gtk_spin_button_new_with_range (0.0, 10.0, 0.009);
6107       gtk_spin_button_set_value (GTK_SPIN_BUTTON (spinner), 0.0);
6108       g_signal_connect (spinner, "value_changed",
6109                         G_CALLBACK (get_spin_value), val_label);
6110       gtk_box_pack_start (GTK_BOX (hbox), spinner, TRUE, TRUE, 5);
6111       gtk_box_pack_start (GTK_BOX (hbox), val_label, TRUE, TRUE, 5);
6112
6113       hbox = gtk_hbox_new (FALSE, 0);
6114       gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, TRUE, 0);
6115   
6116       button = gtk_button_new_with_label ("Close");
6117       g_signal_connect_swapped (button, "clicked",
6118                                 G_CALLBACK (gtk_widget_destroy),
6119                                 window);
6120       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
6121     }
6122
6123   if (!gtk_widget_get_visible (window))
6124     gtk_widget_show_all (window);
6125   else
6126     gtk_widget_destroy (window);
6127 }
6128
6129
6130 /*
6131  * Cursors
6132  */
6133
6134 static gint
6135 cursor_expose_event (GtkWidget *widget,
6136                      GdkEvent  *event,
6137                      gpointer   user_data)
6138 {
6139   GtkDrawingArea *darea;
6140   GdkDrawable *drawable;
6141   GdkGC *black_gc;
6142   GdkGC *gray_gc;
6143   GdkGC *white_gc;
6144   guint max_width;
6145   guint max_height;
6146
6147   g_return_val_if_fail (widget != NULL, TRUE);
6148   g_return_val_if_fail (GTK_IS_DRAWING_AREA (widget), TRUE);
6149
6150   darea = GTK_DRAWING_AREA (widget);
6151   drawable = widget->window;
6152   white_gc = widget->style->white_gc;
6153   gray_gc = widget->style->bg_gc[GTK_STATE_NORMAL];
6154   black_gc = widget->style->black_gc;
6155   max_width = widget->allocation.width;
6156   max_height = widget->allocation.height;
6157
6158   gdk_draw_rectangle (drawable, white_gc,
6159                       TRUE,
6160                       0,
6161                       0,
6162                       max_width,
6163                       max_height / 2);
6164
6165   gdk_draw_rectangle (drawable, black_gc,
6166                       TRUE,
6167                       0,
6168                       max_height / 2,
6169                       max_width,
6170                       max_height / 2);
6171
6172   gdk_draw_rectangle (drawable, gray_gc,
6173                       TRUE,
6174                       max_width / 3,
6175                       max_height / 3,
6176                       max_width / 3,
6177                       max_height / 3);
6178
6179   return TRUE;
6180 }
6181
6182 static void
6183 set_cursor (GtkWidget *spinner,
6184             GtkWidget *widget)
6185 {
6186   guint c;
6187   GdkCursor *cursor;
6188   GtkWidget *label;
6189   GEnumClass *class;
6190   GEnumValue *vals;
6191
6192   c = CLAMP (gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (spinner)), 0, 152);
6193   c &= 0xfe;
6194
6195   label = g_object_get_data (G_OBJECT (spinner), "user_data");
6196   
6197   class = g_type_class_ref (GDK_TYPE_CURSOR_TYPE);
6198   vals = class->values;
6199
6200   while (vals && vals->value != c)
6201     vals++;
6202   if (vals)
6203     gtk_label_set_text (GTK_LABEL (label), vals->value_nick);
6204   else
6205     gtk_label_set_text (GTK_LABEL (label), "<unknown>");
6206
6207   g_type_class_unref (class);
6208
6209   cursor = gdk_cursor_new_for_display (gtk_widget_get_display (widget), c);
6210   gdk_window_set_cursor (widget->window, cursor);
6211   gdk_cursor_unref (cursor);
6212 }
6213
6214 static gint
6215 cursor_event (GtkWidget          *widget,
6216               GdkEvent           *event,
6217               GtkSpinButton      *spinner)
6218 {
6219   if ((event->type == GDK_BUTTON_PRESS) &&
6220       ((event->button.button == 1) ||
6221        (event->button.button == 3)))
6222     {
6223       gtk_spin_button_spin (spinner, event->button.button == 1 ?
6224                             GTK_SPIN_STEP_FORWARD : GTK_SPIN_STEP_BACKWARD, 0);
6225       return TRUE;
6226     }
6227
6228   return FALSE;
6229 }
6230
6231 #ifdef GDK_WINDOWING_X11
6232 #include "x11/gdkx.h"
6233
6234 static void
6235 change_cursor_theme (GtkWidget *widget,
6236                      gpointer   data)
6237 {
6238   const gchar *theme;
6239   gint size;
6240   GList *children;
6241
6242   children = gtk_container_get_children (GTK_CONTAINER (data));
6243
6244   theme = gtk_entry_get_text (GTK_ENTRY (children->next->data));
6245   size = (gint) gtk_spin_button_get_value (GTK_SPIN_BUTTON (children->next->next->data));
6246
6247   g_list_free (children);
6248
6249   gdk_x11_display_set_cursor_theme (gtk_widget_get_display (widget),
6250                                     theme, size);
6251 }
6252 #endif
6253
6254
6255 static void
6256 create_cursors (GtkWidget *widget)
6257 {
6258   static GtkWidget *window = NULL;
6259   GtkWidget *frame;
6260   GtkWidget *hbox;
6261   GtkWidget *main_vbox;
6262   GtkWidget *vbox;
6263   GtkWidget *darea;
6264   GtkWidget *spinner;
6265   GtkWidget *button;
6266   GtkWidget *label;
6267   GtkWidget *any;
6268   GtkAdjustment *adj;
6269   GtkWidget *entry;
6270   GtkWidget *size;  
6271
6272   if (!window)
6273     {
6274       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6275       gtk_window_set_screen (GTK_WINDOW (window), 
6276                              gtk_widget_get_screen (widget));
6277       
6278       g_signal_connect (window, "destroy",
6279                         G_CALLBACK (gtk_widget_destroyed),
6280                         &window);
6281       
6282       gtk_window_set_title (GTK_WINDOW (window), "Cursors");
6283       
6284       main_vbox = gtk_vbox_new (FALSE, 5);
6285       gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 0);
6286       gtk_container_add (GTK_CONTAINER (window), main_vbox);
6287
6288       vbox =
6289         g_object_new (gtk_vbox_get_type (),
6290                         "GtkBox::homogeneous", FALSE,
6291                         "GtkBox::spacing", 5,
6292                         "GtkContainer::border_width", 10,
6293                         "GtkWidget::parent", main_vbox,
6294                         "GtkWidget::visible", TRUE,
6295                         NULL);
6296
6297 #ifdef GDK_WINDOWING_X11
6298       hbox = gtk_hbox_new (FALSE, 0);
6299       gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
6300       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
6301
6302       label = gtk_label_new ("Cursor Theme : ");
6303       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
6304       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
6305
6306       entry = gtk_entry_new ();
6307       gtk_entry_set_text (GTK_ENTRY (entry), "default");
6308       gtk_box_pack_start (GTK_BOX (hbox), entry, FALSE, TRUE, 0);
6309
6310       size = gtk_spin_button_new_with_range (1.0, 64.0, 1.0);
6311       gtk_spin_button_set_value (GTK_SPIN_BUTTON (size), 24.0);
6312       gtk_box_pack_start (GTK_BOX (hbox), size, TRUE, TRUE, 0);
6313       
6314       g_signal_connect (entry, "changed", 
6315                         G_CALLBACK (change_cursor_theme), hbox);
6316       g_signal_connect (size, "changed", 
6317                         G_CALLBACK (change_cursor_theme), hbox);
6318 #endif
6319
6320       hbox = gtk_hbox_new (FALSE, 0);
6321       gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
6322       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
6323
6324       label = gtk_label_new ("Cursor Value : ");
6325       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
6326       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
6327       
6328       adj = (GtkAdjustment *) gtk_adjustment_new (0,
6329                                                   0, 152,
6330                                                   2,
6331                                                   10, 0);
6332       spinner = gtk_spin_button_new (adj, 0, 0);
6333       gtk_box_pack_start (GTK_BOX (hbox), spinner, TRUE, TRUE, 0);
6334
6335       frame =
6336         g_object_new (gtk_frame_get_type (),
6337                         "GtkFrame::shadow", GTK_SHADOW_ETCHED_IN,
6338                         "GtkFrame::label_xalign", 0.5,
6339                         "GtkFrame::label", "Cursor Area",
6340                         "GtkContainer::border_width", 10,
6341                         "GtkWidget::parent", vbox,
6342                         "GtkWidget::visible", TRUE,
6343                         NULL);
6344
6345       darea = gtk_drawing_area_new ();
6346       gtk_widget_set_size_request (darea, 80, 80);
6347       gtk_container_add (GTK_CONTAINER (frame), darea);
6348       g_signal_connect (darea,
6349                         "expose_event",
6350                         G_CALLBACK (cursor_expose_event),
6351                         NULL);
6352       gtk_widget_set_events (darea, GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK);
6353       g_signal_connect (darea,
6354                         "button_press_event",
6355                         G_CALLBACK (cursor_event),
6356                         spinner);
6357       gtk_widget_show (darea);
6358
6359       g_signal_connect (spinner, "changed",
6360                         G_CALLBACK (set_cursor),
6361                         darea);
6362
6363       label = g_object_new (GTK_TYPE_LABEL,
6364                               "visible", TRUE,
6365                               "label", "XXX",
6366                               "parent", vbox,
6367                               NULL);
6368       gtk_container_child_set (GTK_CONTAINER (vbox), label,
6369                                "expand", FALSE,
6370                                NULL);
6371       g_object_set_data (G_OBJECT (spinner), "user_data", label);
6372
6373       any =
6374         g_object_new (gtk_hseparator_get_type (),
6375                         "GtkWidget::visible", TRUE,
6376                         NULL);
6377       gtk_box_pack_start (GTK_BOX (main_vbox), any, FALSE, TRUE, 0);
6378   
6379       hbox = gtk_hbox_new (FALSE, 0);
6380       gtk_container_set_border_width (GTK_CONTAINER (hbox), 10);
6381       gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, TRUE, 0);
6382
6383       button = gtk_button_new_with_label ("Close");
6384       g_signal_connect_swapped (button, "clicked",
6385                                 G_CALLBACK (gtk_widget_destroy),
6386                                 window);
6387       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
6388
6389       gtk_widget_show_all (window);
6390
6391       set_cursor (spinner, darea);
6392     }
6393   else
6394     gtk_widget_destroy (window);
6395 }
6396
6397 /*
6398  * GtkColorSelection
6399  */
6400
6401 void
6402 color_selection_ok (GtkWidget               *w,
6403                     GtkColorSelectionDialog *cs)
6404 {
6405   GtkColorSelection *colorsel;
6406   gdouble color[4];
6407
6408   colorsel=GTK_COLOR_SELECTION(cs->colorsel);
6409
6410   gtk_color_selection_get_color(colorsel,color);
6411   gtk_color_selection_set_color(colorsel,color);
6412 }
6413
6414 void
6415 color_selection_changed (GtkWidget *w,
6416                          GtkColorSelectionDialog *cs)
6417 {
6418   GtkColorSelection *colorsel;
6419   gdouble color[4];
6420
6421   colorsel=GTK_COLOR_SELECTION(cs->colorsel);
6422   gtk_color_selection_get_color(colorsel,color);
6423 }
6424
6425 #if 0 /* unused */
6426 static void
6427 opacity_toggled_cb (GtkWidget *w,
6428                     GtkColorSelectionDialog *cs)
6429 {
6430   GtkColorSelection *colorsel;
6431
6432   colorsel = GTK_COLOR_SELECTION (cs->colorsel);
6433   gtk_color_selection_set_has_opacity_control (colorsel,
6434                                                gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w)));
6435 }
6436
6437 static void
6438 palette_toggled_cb (GtkWidget *w,
6439                     GtkColorSelectionDialog *cs)
6440 {
6441   GtkColorSelection *colorsel;
6442
6443   colorsel = GTK_COLOR_SELECTION (cs->colorsel);
6444   gtk_color_selection_set_has_palette (colorsel,
6445                                        gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w)));
6446 }
6447 #endif
6448
6449 void
6450 create_color_selection (GtkWidget *widget)
6451 {
6452   static GtkWidget *window = NULL;
6453
6454   if (!window)
6455     {
6456       GtkWidget *picker;
6457       GtkWidget *hbox;
6458       GtkWidget *label;
6459       GtkWidget *button;
6460       
6461       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6462       gtk_window_set_screen (GTK_WINDOW (window), 
6463                              gtk_widget_get_screen (widget));
6464                              
6465       g_signal_connect (window, "destroy",
6466                         G_CALLBACK (gtk_widget_destroyed),
6467                         &window);
6468
6469       gtk_window_set_title (GTK_WINDOW (window), "GtkColorButton");
6470       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
6471
6472       hbox = gtk_hbox_new (FALSE, 8);
6473       gtk_container_set_border_width (GTK_CONTAINER (hbox), 8);
6474       gtk_container_add (GTK_CONTAINER (window), hbox);
6475       
6476       label = gtk_label_new ("Pick a color");
6477       gtk_container_add (GTK_CONTAINER (hbox), label);
6478
6479       picker = gtk_color_button_new ();
6480       gtk_color_button_set_use_alpha (GTK_COLOR_BUTTON (picker), TRUE);
6481       gtk_container_add (GTK_CONTAINER (hbox), picker);
6482
6483       button = gtk_button_new_with_mnemonic ("_Props");
6484       gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
6485       g_signal_connect (button, "clicked",
6486                         G_CALLBACK (props_clicked),
6487                         picker);
6488     }
6489
6490   if (!gtk_widget_get_visible (window))
6491     gtk_widget_show_all (window);
6492   else
6493     gtk_widget_destroy (window);
6494 }
6495
6496 void
6497 flipping_toggled_cb (GtkWidget *widget, gpointer data)
6498 {
6499   int state = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
6500   int new_direction = state ? GTK_TEXT_DIR_RTL : GTK_TEXT_DIR_LTR;
6501
6502   gtk_widget_set_default_direction (new_direction);
6503 }
6504
6505 static void
6506 orientable_toggle_orientation (GtkOrientable *orientable)
6507 {
6508   GtkOrientation orientation;
6509
6510   orientation = gtk_orientable_get_orientation (orientable);
6511   gtk_orientable_set_orientation (orientable,
6512                                   orientation == GTK_ORIENTATION_HORIZONTAL ?
6513                                   GTK_ORIENTATION_VERTICAL :
6514                                   GTK_ORIENTATION_HORIZONTAL);
6515
6516   if (GTK_IS_CONTAINER (orientable))
6517     {
6518       GList *children;
6519       GList *child;
6520
6521       children = gtk_container_get_children (GTK_CONTAINER (orientable));
6522
6523       for (child = children; child; child = child->next)
6524         {
6525           if (GTK_IS_ORIENTABLE (child->data))
6526             orientable_toggle_orientation (child->data);
6527         }
6528
6529       g_list_free (children);
6530     }
6531 }
6532
6533 void
6534 flipping_orientation_toggled_cb (GtkWidget *widget, gpointer data)
6535 {
6536   orientable_toggle_orientation (GTK_ORIENTABLE (GTK_DIALOG (gtk_widget_get_toplevel (widget))->vbox));
6537 }
6538
6539 static void
6540 set_direction_recurse (GtkWidget *widget,
6541                        gpointer   data)
6542 {
6543   GtkTextDirection *dir = data;
6544   
6545   gtk_widget_set_direction (widget, *dir);
6546   if (GTK_IS_CONTAINER (widget))
6547     gtk_container_foreach (GTK_CONTAINER (widget),
6548                            set_direction_recurse,
6549                            data);
6550 }
6551
6552 static GtkWidget *
6553 create_forward_back (const char       *title,
6554                      GtkTextDirection  text_dir)
6555 {
6556   GtkWidget *frame = gtk_frame_new (title);
6557   GtkWidget *bbox = gtk_hbutton_box_new ();
6558   GtkWidget *back_button = gtk_button_new_from_stock (GTK_STOCK_GO_BACK);
6559   GtkWidget *forward_button = gtk_button_new_from_stock (GTK_STOCK_GO_FORWARD);
6560
6561   gtk_container_set_border_width (GTK_CONTAINER (bbox), 5);
6562   
6563   gtk_container_add (GTK_CONTAINER (frame), bbox);
6564   gtk_container_add (GTK_CONTAINER (bbox), back_button);
6565   gtk_container_add (GTK_CONTAINER (bbox), forward_button);
6566
6567   set_direction_recurse (frame, &text_dir);
6568
6569   return frame;
6570 }
6571
6572 void
6573 create_flipping (GtkWidget *widget)
6574 {
6575   static GtkWidget *window = NULL;
6576   GtkWidget *check_button, *button;
6577
6578   if (!window)
6579     {
6580       window = gtk_dialog_new ();
6581
6582       gtk_window_set_screen (GTK_WINDOW (window),
6583                              gtk_widget_get_screen (widget));
6584
6585       g_signal_connect (window, "destroy",
6586                         G_CALLBACK (gtk_widget_destroyed),
6587                         &window);
6588
6589       gtk_window_set_title (GTK_WINDOW (window), "Bidirectional Flipping");
6590
6591       check_button = gtk_check_button_new_with_label ("Right-to-left global direction");
6592       gtk_container_set_border_width (GTK_CONTAINER (check_button), 10);
6593       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox),
6594                           check_button, TRUE, TRUE, 0);
6595
6596       if (gtk_widget_get_default_direction () == GTK_TEXT_DIR_RTL)
6597         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button), TRUE);
6598
6599       g_signal_connect (check_button, "toggled",
6600                         G_CALLBACK (flipping_toggled_cb), NULL);
6601
6602       check_button = gtk_check_button_new_with_label ("Toggle orientation of all boxes");
6603       gtk_container_set_border_width (GTK_CONTAINER (check_button), 10);
6604       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
6605                           check_button, TRUE, TRUE, 0);
6606
6607       g_signal_connect (check_button, "toggled",
6608                         G_CALLBACK (flipping_orientation_toggled_cb), NULL);
6609
6610       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
6611                           create_forward_back ("Default", GTK_TEXT_DIR_NONE),
6612                           TRUE, TRUE, 0);
6613
6614       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
6615                           create_forward_back ("Left-to-Right", GTK_TEXT_DIR_LTR),
6616                           TRUE, TRUE, 0);
6617
6618       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
6619                           create_forward_back ("Right-to-Left", GTK_TEXT_DIR_RTL),
6620                           TRUE, TRUE, 0);
6621
6622       button = gtk_button_new_with_label ("Close");
6623       g_signal_connect_swapped (button, "clicked",
6624                                 G_CALLBACK (gtk_widget_destroy), window);
6625       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
6626                           button, TRUE, TRUE, 0);
6627     }
6628   
6629   if (!gtk_widget_get_visible (window))
6630     gtk_widget_show_all (window);
6631   else
6632     gtk_widget_destroy (window);
6633 }
6634
6635 /*
6636  * Focus test
6637  */
6638
6639 static GtkWidget*
6640 make_focus_table (GList **list)
6641 {
6642   GtkWidget *table;
6643   gint i, j;
6644   
6645   table = gtk_table_new (5, 5, FALSE);
6646
6647   i = 0;
6648   j = 0;
6649
6650   while (i < 5)
6651     {
6652       j = 0;
6653       while (j < 5)
6654         {
6655           GtkWidget *widget;
6656           
6657           if ((i + j) % 2)
6658             widget = gtk_entry_new ();
6659           else
6660             widget = gtk_button_new_with_label ("Foo");
6661
6662           *list = g_list_prepend (*list, widget);
6663           
6664           gtk_table_attach (GTK_TABLE (table),
6665                             widget,
6666                             i, i + 1,
6667                             j, j + 1,
6668                             GTK_EXPAND | GTK_FILL,
6669                             GTK_EXPAND | GTK_FILL,
6670                             5, 5);
6671           
6672           ++j;
6673         }
6674
6675       ++i;
6676     }
6677
6678   *list = g_list_reverse (*list);
6679   
6680   return table;
6681 }
6682
6683 static void
6684 create_focus (GtkWidget *widget)
6685 {
6686   static GtkWidget *window = NULL;
6687   
6688   if (!window)
6689     {
6690       GtkWidget *table;
6691       GtkWidget *frame;
6692       GList *list = NULL;
6693       
6694       window = gtk_dialog_new_with_buttons ("Keyboard focus navigation",
6695                                             NULL, 0,
6696                                             GTK_STOCK_CLOSE,
6697                                             GTK_RESPONSE_NONE,
6698                                             NULL);
6699
6700       gtk_window_set_screen (GTK_WINDOW (window),
6701                              gtk_widget_get_screen (widget));
6702
6703       g_signal_connect (window, "destroy",
6704                         G_CALLBACK (gtk_widget_destroyed),
6705                         &window);
6706
6707       g_signal_connect (window, "response",
6708                         G_CALLBACK (gtk_widget_destroy),
6709                         NULL);
6710       
6711       gtk_window_set_title (GTK_WINDOW (window), "Keyboard Focus Navigation");
6712
6713       frame = gtk_frame_new ("Weird tab focus chain");
6714
6715       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
6716                           frame, TRUE, TRUE, 0);
6717       
6718       table = make_focus_table (&list);
6719
6720       gtk_container_add (GTK_CONTAINER (frame), table);
6721
6722       gtk_container_set_focus_chain (GTK_CONTAINER (table),
6723                                      list);
6724
6725       g_list_free (list);
6726       
6727       frame = gtk_frame_new ("Default tab focus chain");
6728
6729       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
6730                           frame, TRUE, TRUE, 0);
6731
6732       list = NULL;
6733       table = make_focus_table (&list);
6734
6735       g_list_free (list);
6736       
6737       gtk_container_add (GTK_CONTAINER (frame), table);      
6738     }
6739   
6740   if (!gtk_widget_get_visible (window))
6741     gtk_widget_show_all (window);
6742   else
6743     gtk_widget_destroy (window);
6744 }
6745
6746 /*
6747  * GtkFontSelection
6748  */
6749
6750 void
6751 font_selection_ok (GtkWidget              *w,
6752                    GtkFontSelectionDialog *fs)
6753 {
6754   gchar *s = gtk_font_selection_dialog_get_font_name (fs);
6755
6756   g_print ("%s\n", s);
6757   g_free (s);
6758   gtk_widget_destroy (GTK_WIDGET (fs));
6759 }
6760
6761 void
6762 create_font_selection (GtkWidget *widget)
6763 {
6764   static GtkWidget *window = NULL;
6765
6766   if (!window)
6767     {
6768       GtkWidget *picker;
6769       GtkWidget *hbox;
6770       GtkWidget *label;
6771       
6772       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6773       gtk_window_set_screen (GTK_WINDOW (window),
6774                              gtk_widget_get_screen (widget));
6775
6776       g_signal_connect (window, "destroy",
6777                         G_CALLBACK (gtk_widget_destroyed),
6778                         &window);
6779
6780       gtk_window_set_title (GTK_WINDOW (window), "GtkFontButton");
6781       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
6782
6783       hbox = gtk_hbox_new (FALSE, 8);
6784       gtk_container_set_border_width (GTK_CONTAINER (hbox), 8);
6785       gtk_container_add (GTK_CONTAINER (window), hbox);
6786       
6787       label = gtk_label_new ("Pick a font");
6788       gtk_container_add (GTK_CONTAINER (hbox), label);
6789
6790       picker = gtk_font_button_new ();
6791       gtk_font_button_set_use_font (GTK_FONT_BUTTON (picker), TRUE);
6792       gtk_container_add (GTK_CONTAINER (hbox), picker);
6793     }
6794   
6795   if (!gtk_widget_get_visible (window))
6796     gtk_widget_show_all (window);
6797   else
6798     gtk_widget_destroy (window);
6799 }
6800
6801 /*
6802  * GtkDialog
6803  */
6804
6805 static GtkWidget *dialog_window = NULL;
6806
6807 static void
6808 label_toggle (GtkWidget  *widget,
6809               GtkWidget **label)
6810 {
6811   if (!(*label))
6812     {
6813       *label = gtk_label_new ("Dialog Test");
6814       g_signal_connect (*label,
6815                         "destroy",
6816                         G_CALLBACK (gtk_widget_destroyed),
6817                         label);
6818       gtk_misc_set_padding (GTK_MISC (*label), 10, 10);
6819       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog_window)->vbox), 
6820                           *label, TRUE, TRUE, 0);
6821       gtk_widget_show (*label);
6822     }
6823   else
6824     gtk_widget_destroy (*label);
6825 }
6826
6827 #define RESPONSE_TOGGLE_SEPARATOR 1
6828
6829 static void
6830 print_response (GtkWidget *dialog,
6831                 gint       response_id,
6832                 gpointer   data)
6833 {
6834   g_print ("response signal received (%d)\n", response_id);
6835
6836   if (response_id == RESPONSE_TOGGLE_SEPARATOR)
6837     {
6838       gtk_dialog_set_has_separator (GTK_DIALOG (dialog),
6839                                     !gtk_dialog_get_has_separator (GTK_DIALOG (dialog)));
6840     }
6841 }
6842
6843 static void
6844 create_dialog (GtkWidget *widget)
6845 {
6846   static GtkWidget *label;
6847   GtkWidget *button;
6848
6849   if (!dialog_window)
6850     {
6851       /* This is a terrible example; it's much simpler to create
6852        * dialogs than this. Don't use testgtk for example code,
6853        * use gtk-demo ;-)
6854        */
6855       
6856       dialog_window = gtk_dialog_new ();
6857       gtk_window_set_screen (GTK_WINDOW (dialog_window),
6858                              gtk_widget_get_screen (widget));
6859
6860       g_signal_connect (dialog_window,
6861                         "response",
6862                         G_CALLBACK (print_response),
6863                         NULL);
6864       
6865       g_signal_connect (dialog_window, "destroy",
6866                         G_CALLBACK (gtk_widget_destroyed),
6867                         &dialog_window);
6868
6869       gtk_window_set_title (GTK_WINDOW (dialog_window), "GtkDialog");
6870       gtk_container_set_border_width (GTK_CONTAINER (dialog_window), 0);
6871
6872       button = gtk_button_new_with_label ("OK");
6873       gtk_widget_set_can_default (button, TRUE);
6874       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog_window)->action_area), 
6875                           button, TRUE, TRUE, 0);
6876       gtk_widget_grab_default (button);
6877       gtk_widget_show (button);
6878
6879       button = gtk_button_new_with_label ("Toggle");
6880       g_signal_connect (button, "clicked",
6881                         G_CALLBACK (label_toggle),
6882                         &label);
6883       gtk_widget_set_can_default (button, TRUE);
6884       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog_window)->action_area),
6885                           button, TRUE, TRUE, 0);
6886       gtk_widget_show (button);
6887
6888       label = NULL;
6889       
6890       button = gtk_button_new_with_label ("Separator");
6891
6892       gtk_widget_set_can_default (button, TRUE);
6893
6894       gtk_dialog_add_action_widget (GTK_DIALOG (dialog_window),
6895                                     button,
6896                                     RESPONSE_TOGGLE_SEPARATOR);
6897       gtk_widget_show (button);
6898     }
6899
6900   if (!gtk_widget_get_visible (dialog_window))
6901     gtk_widget_show (dialog_window);
6902   else
6903     gtk_widget_destroy (dialog_window);
6904 }
6905
6906 /* Display & Screen test 
6907  */
6908
6909 typedef struct 
6910
6911   GtkEntry *entry;
6912   GtkWidget *radio_dpy;
6913   GtkWidget *toplevel; 
6914   GtkWidget *dialog_window;
6915   GList *valid_display_list;
6916 } ScreenDisplaySelection;
6917
6918 static gint
6919 display_name_cmp (gconstpointer a,
6920                   gconstpointer b)
6921 {
6922   return g_ascii_strcasecmp (a,b);
6923 }
6924
6925 static void
6926 screen_display_check (GtkWidget *widget, ScreenDisplaySelection *data)
6927 {
6928   char *display_name;
6929   GdkDisplay *display = gtk_widget_get_display (widget);
6930   GtkWidget *dialog;
6931   GdkScreen *new_screen = NULL;
6932   GdkScreen *current_screen = gtk_widget_get_screen (widget);
6933   
6934   if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (data->radio_dpy)))
6935     {
6936       display_name = g_strdup (gtk_entry_get_text (data->entry));
6937       display = gdk_display_open (display_name);
6938       
6939       if (!display)
6940         {
6941           dialog = gtk_message_dialog_new (GTK_WINDOW (gtk_widget_get_toplevel (widget)),
6942                                            GTK_DIALOG_DESTROY_WITH_PARENT,
6943                                            GTK_MESSAGE_ERROR,
6944                                            GTK_BUTTONS_OK,
6945                                            "The display :\n%s\ncannot be opened",
6946                                            display_name);
6947           gtk_window_set_screen (GTK_WINDOW (dialog), current_screen);
6948           gtk_widget_show (dialog);
6949           g_signal_connect (dialog, "response",
6950                             G_CALLBACK (gtk_widget_destroy),
6951                             NULL);
6952         }
6953       else
6954         {
6955           if (!g_list_find_custom (data->valid_display_list, 
6956                                    display_name,
6957                                    display_name_cmp))
6958             data->valid_display_list = g_list_append (data->valid_display_list,
6959                                                       display_name);
6960           
6961           new_screen = gdk_display_get_default_screen (display);
6962         }
6963     }
6964   else
6965     {
6966       gint number_of_screens = gdk_display_get_n_screens (display);
6967       gint screen_num = gdk_screen_get_number (current_screen);
6968       if ((screen_num +1) < number_of_screens)
6969         new_screen = gdk_display_get_screen (display, screen_num + 1);
6970       else
6971         new_screen = gdk_display_get_screen (display, 0);
6972     }
6973   
6974   if (new_screen) 
6975     {
6976       gtk_window_set_screen (GTK_WINDOW (data->toplevel), new_screen);
6977       gtk_widget_destroy (data->dialog_window);
6978     }
6979 }
6980
6981 void
6982 screen_display_destroy_diag (GtkWidget *widget, GtkWidget *data)
6983 {
6984   gtk_widget_destroy (data);
6985 }
6986
6987 void
6988 create_display_screen (GtkWidget *widget)
6989 {
6990   GtkWidget *table, *frame, *window, *combo_dpy, *vbox;
6991   GtkWidget *radio_dpy, *radio_scr, *applyb, *cancelb;
6992   GtkWidget *bbox;
6993   ScreenDisplaySelection *scr_dpy_data;
6994   GdkScreen *screen = gtk_widget_get_screen (widget);
6995   static GList *valid_display_list = NULL;
6996   
6997   GdkDisplay *display = gdk_screen_get_display (screen);
6998
6999   window = g_object_new (gtk_window_get_type (),
7000                            "screen", screen,
7001                            "user_data", NULL,
7002                            "type", GTK_WINDOW_TOPLEVEL,
7003                            "title",
7004                            "Screen or Display selection",
7005                            "border_width", 10, NULL);
7006   g_signal_connect (window, "destroy", 
7007                     G_CALLBACK (gtk_widget_destroy), NULL);
7008
7009   vbox = gtk_vbox_new (FALSE, 3);
7010   gtk_container_add (GTK_CONTAINER (window), vbox);
7011   
7012   frame = gtk_frame_new ("Select screen or display");
7013   gtk_container_add (GTK_CONTAINER (vbox), frame);
7014   
7015   table = gtk_table_new (2, 2, TRUE);
7016   gtk_table_set_row_spacings (GTK_TABLE (table), 3);
7017   gtk_table_set_col_spacings (GTK_TABLE (table), 3);
7018
7019   gtk_container_add (GTK_CONTAINER (frame), table);
7020
7021   radio_dpy = gtk_radio_button_new_with_label (NULL, "move to another X display");
7022   if (gdk_display_get_n_screens(display) > 1)
7023     radio_scr = gtk_radio_button_new_with_label 
7024     (gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio_dpy)), "move to next screen");
7025   else
7026     {    
7027       radio_scr = gtk_radio_button_new_with_label 
7028         (gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio_dpy)), 
7029          "only one screen on the current display");
7030       gtk_widget_set_sensitive (radio_scr, FALSE);
7031     }
7032   combo_dpy = gtk_combo_new ();
7033   if (!valid_display_list)
7034     valid_display_list = g_list_append (valid_display_list, "diabolo:0.0");
7035     
7036   gtk_combo_set_popdown_strings (GTK_COMBO (combo_dpy), valid_display_list);
7037     
7038   gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (combo_dpy)->entry), 
7039                       "<hostname>:<X Server Num>.<Screen Num>");
7040
7041   gtk_table_attach_defaults (GTK_TABLE (table), radio_dpy, 0, 1, 0, 1);
7042   gtk_table_attach_defaults (GTK_TABLE (table), radio_scr, 0, 1, 1, 2);
7043   gtk_table_attach_defaults (GTK_TABLE (table), combo_dpy, 1, 2, 0, 1);
7044
7045   bbox = gtk_hbutton_box_new ();
7046   applyb = gtk_button_new_from_stock (GTK_STOCK_APPLY);
7047   cancelb = gtk_button_new_from_stock (GTK_STOCK_CANCEL);
7048   
7049   gtk_container_add (GTK_CONTAINER (vbox), bbox);
7050
7051   gtk_container_add (GTK_CONTAINER (bbox), applyb);
7052   gtk_container_add (GTK_CONTAINER (bbox), cancelb);
7053
7054   scr_dpy_data = g_new0 (ScreenDisplaySelection, 1);
7055
7056   scr_dpy_data->entry = GTK_ENTRY (GTK_COMBO (combo_dpy)->entry);
7057   scr_dpy_data->radio_dpy = radio_dpy;
7058   scr_dpy_data->toplevel = gtk_widget_get_toplevel (widget);
7059   scr_dpy_data->dialog_window = window;
7060   scr_dpy_data->valid_display_list = valid_display_list;
7061
7062   g_signal_connect (cancelb, "clicked", 
7063                     G_CALLBACK (screen_display_destroy_diag), window);
7064   g_signal_connect (applyb, "clicked", 
7065                     G_CALLBACK (screen_display_check), scr_dpy_data);
7066   gtk_widget_show_all (window);
7067 }
7068
7069 /* Event Watcher
7070  */
7071 static gboolean event_watcher_enter_id = 0;
7072 static gboolean event_watcher_leave_id = 0;
7073
7074 static gboolean
7075 event_watcher (GSignalInvocationHint *ihint,
7076                guint                  n_param_values,
7077                const GValue          *param_values,
7078                gpointer               data)
7079 {
7080   g_print ("Watch: \"%s\" emitted for %s\n",
7081            g_signal_name (ihint->signal_id),
7082            G_OBJECT_TYPE_NAME (g_value_get_object (param_values + 0)));
7083
7084   return TRUE;
7085 }
7086
7087 static void
7088 event_watcher_down (void)
7089 {
7090   if (event_watcher_enter_id)
7091     {
7092       guint signal_id;
7093
7094       signal_id = g_signal_lookup ("enter_notify_event", GTK_TYPE_WIDGET);
7095       g_signal_remove_emission_hook (signal_id, event_watcher_enter_id);
7096       event_watcher_enter_id = 0;
7097       signal_id = g_signal_lookup ("leave_notify_event", GTK_TYPE_WIDGET);
7098       g_signal_remove_emission_hook (signal_id, event_watcher_leave_id);
7099       event_watcher_leave_id = 0;
7100     }
7101 }
7102
7103 static void
7104 event_watcher_toggle (void)
7105 {
7106   if (event_watcher_enter_id)
7107     event_watcher_down ();
7108   else
7109     {
7110       guint signal_id;
7111
7112       signal_id = g_signal_lookup ("enter_notify_event", GTK_TYPE_WIDGET);
7113       event_watcher_enter_id = g_signal_add_emission_hook (signal_id, 0, event_watcher, NULL, NULL);
7114       signal_id = g_signal_lookup ("leave_notify_event", GTK_TYPE_WIDGET);
7115       event_watcher_leave_id = g_signal_add_emission_hook (signal_id, 0, event_watcher, NULL, NULL);
7116     }
7117 }
7118
7119 static void
7120 create_event_watcher (GtkWidget *widget)
7121 {
7122   GtkWidget *button;
7123
7124   if (!dialog_window)
7125     {
7126       dialog_window = gtk_dialog_new ();
7127       gtk_window_set_screen (GTK_WINDOW (dialog_window),
7128                              gtk_widget_get_screen (widget));
7129
7130       g_signal_connect (dialog_window, "destroy",
7131                         G_CALLBACK (gtk_widget_destroyed),
7132                         &dialog_window);
7133       g_signal_connect (dialog_window, "destroy",
7134                         G_CALLBACK (event_watcher_down),
7135                         NULL);
7136
7137       gtk_window_set_title (GTK_WINDOW (dialog_window), "Event Watcher");
7138       gtk_container_set_border_width (GTK_CONTAINER (dialog_window), 0);
7139       gtk_widget_set_size_request (dialog_window, 200, 110);
7140
7141       button = gtk_toggle_button_new_with_label ("Activate Watch");
7142       g_signal_connect (button, "clicked",
7143                         G_CALLBACK (event_watcher_toggle),
7144                         NULL);
7145       gtk_container_set_border_width (GTK_CONTAINER (button), 10);
7146       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog_window)->vbox), 
7147                           button, TRUE, TRUE, 0);
7148       gtk_widget_show (button);
7149
7150       button = gtk_button_new_with_label ("Close");
7151       g_signal_connect_swapped (button, "clicked",
7152                                 G_CALLBACK (gtk_widget_destroy),
7153                                 dialog_window);
7154       gtk_widget_set_can_default (button, TRUE);
7155       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog_window)->action_area),
7156                           button, TRUE, TRUE, 0);
7157       gtk_widget_grab_default (button);
7158       gtk_widget_show (button);
7159     }
7160
7161   if (!gtk_widget_get_visible (dialog_window))
7162     gtk_widget_show (dialog_window);
7163   else
7164     gtk_widget_destroy (dialog_window);
7165 }
7166
7167 /*
7168  * GtkRange
7169  */
7170
7171 static gchar*
7172 reformat_value (GtkScale *scale,
7173                 gdouble   value)
7174 {
7175   return g_strdup_printf ("-->%0.*g<--",
7176                           gtk_scale_get_digits (scale), value);
7177 }
7178
7179 static void
7180 create_range_controls (GtkWidget *widget)
7181 {
7182   static GtkWidget *window = NULL;
7183   GtkWidget *box1;
7184   GtkWidget *box2;
7185   GtkWidget *button;
7186   GtkWidget *scrollbar;
7187   GtkWidget *scale;
7188   GtkWidget *separator;
7189   GtkObject *adjustment;
7190   GtkWidget *hbox;
7191
7192   if (!window)
7193     {
7194       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7195
7196       gtk_window_set_screen (GTK_WINDOW (window),
7197                              gtk_widget_get_screen (widget));
7198
7199       g_signal_connect (window, "destroy",
7200                         G_CALLBACK (gtk_widget_destroyed),
7201                         &window);
7202
7203       gtk_window_set_title (GTK_WINDOW (window), "range controls");
7204       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
7205
7206
7207       box1 = gtk_vbox_new (FALSE, 0);
7208       gtk_container_add (GTK_CONTAINER (window), box1);
7209       gtk_widget_show (box1);
7210
7211
7212       box2 = gtk_vbox_new (FALSE, 10);
7213       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
7214       gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
7215       gtk_widget_show (box2);
7216
7217
7218       adjustment = gtk_adjustment_new (0.0, 0.0, 101.0, 0.1, 1.0, 1.0);
7219
7220       scale = gtk_hscale_new (GTK_ADJUSTMENT (adjustment));
7221       gtk_widget_set_size_request (GTK_WIDGET (scale), 150, -1);
7222       gtk_range_set_update_policy (GTK_RANGE (scale), GTK_UPDATE_DELAYED);
7223       gtk_scale_set_digits (GTK_SCALE (scale), 1);
7224       gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE);
7225       gtk_box_pack_start (GTK_BOX (box2), scale, TRUE, TRUE, 0);
7226       gtk_widget_show (scale);
7227
7228       scrollbar = gtk_hscrollbar_new (GTK_ADJUSTMENT (adjustment));
7229       gtk_range_set_update_policy (GTK_RANGE (scrollbar), 
7230                                    GTK_UPDATE_CONTINUOUS);
7231       gtk_box_pack_start (GTK_BOX (box2), scrollbar, TRUE, TRUE, 0);
7232       gtk_widget_show (scrollbar);
7233
7234       scale = gtk_hscale_new (GTK_ADJUSTMENT (adjustment));
7235       gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE);
7236       g_signal_connect (scale,
7237                         "format_value",
7238                         G_CALLBACK (reformat_value),
7239                         NULL);
7240       gtk_box_pack_start (GTK_BOX (box2), scale, TRUE, TRUE, 0);
7241       gtk_widget_show (scale);
7242       
7243       hbox = gtk_hbox_new (FALSE, 0);
7244
7245       scale = gtk_vscale_new (GTK_ADJUSTMENT (adjustment));
7246       gtk_widget_set_size_request (scale, -1, 200);
7247       gtk_scale_set_digits (GTK_SCALE (scale), 2);
7248       gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE);
7249       gtk_box_pack_start (GTK_BOX (hbox), scale, TRUE, TRUE, 0);
7250       gtk_widget_show (scale);
7251
7252       scale = gtk_vscale_new (GTK_ADJUSTMENT (adjustment));
7253       gtk_widget_set_size_request (scale, -1, 200);
7254       gtk_scale_set_digits (GTK_SCALE (scale), 2);
7255       gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE);
7256       gtk_range_set_inverted (GTK_RANGE (scale), TRUE);
7257       gtk_box_pack_start (GTK_BOX (hbox), scale, TRUE, TRUE, 0);
7258       gtk_widget_show (scale);
7259
7260       scale = gtk_vscale_new (GTK_ADJUSTMENT (adjustment));
7261       gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE);
7262       g_signal_connect (scale,
7263                         "format_value",
7264                         G_CALLBACK (reformat_value),
7265                         NULL);
7266       gtk_box_pack_start (GTK_BOX (hbox), scale, TRUE, TRUE, 0);
7267       gtk_widget_show (scale);
7268
7269       
7270       gtk_box_pack_start (GTK_BOX (box2), hbox, TRUE, TRUE, 0);
7271       gtk_widget_show (hbox);
7272       
7273       separator = gtk_hseparator_new ();
7274       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
7275       gtk_widget_show (separator);
7276
7277
7278       box2 = gtk_vbox_new (FALSE, 10);
7279       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
7280       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
7281       gtk_widget_show (box2);
7282
7283
7284       button = gtk_button_new_with_label ("close");
7285       g_signal_connect_swapped (button, "clicked",
7286                                 G_CALLBACK (gtk_widget_destroy),
7287                                 window);
7288       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
7289       gtk_widget_set_can_default (button, TRUE);
7290       gtk_widget_grab_default (button);
7291       gtk_widget_show (button);
7292     }
7293
7294   if (!gtk_widget_get_visible (window))
7295     gtk_widget_show (window);
7296   else
7297     gtk_widget_destroy (window);
7298 }
7299
7300 /*
7301  * GtkRulers
7302  */
7303
7304 void
7305 create_rulers (GtkWidget *widget)
7306 {
7307   static GtkWidget *window = NULL;
7308   GtkWidget *table;
7309   GtkWidget *ruler;
7310
7311   if (!window)
7312     {
7313       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7314
7315       gtk_window_set_screen (GTK_WINDOW (window),
7316                              gtk_widget_get_screen (widget));
7317
7318       g_object_set (window, "allow_shrink", TRUE, "allow_grow", TRUE, NULL);
7319
7320       g_signal_connect (window, "destroy",
7321                         G_CALLBACK (gtk_widget_destroyed),
7322                         &window);
7323
7324       gtk_window_set_title (GTK_WINDOW (window), "rulers");
7325       gtk_widget_set_size_request (window, 300, 300);
7326       gtk_widget_set_events (window, 
7327                              GDK_POINTER_MOTION_MASK 
7328                              | GDK_POINTER_MOTION_HINT_MASK);
7329       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
7330
7331       table = gtk_table_new (2, 2, FALSE);
7332       gtk_container_add (GTK_CONTAINER (window), table);
7333       gtk_widget_show (table);
7334
7335       ruler = gtk_hruler_new ();
7336       gtk_ruler_set_metric (GTK_RULER (ruler), GTK_CENTIMETERS);
7337       gtk_ruler_set_range (GTK_RULER (ruler), 100, 0, 0, 20);
7338
7339       g_signal_connect_swapped (window, 
7340                                 "motion_notify_event",
7341                                 G_CALLBACK (GTK_WIDGET_GET_CLASS (ruler)->motion_notify_event),
7342                                 ruler);
7343       
7344       gtk_table_attach (GTK_TABLE (table), ruler, 1, 2, 0, 1,
7345                         GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
7346       gtk_widget_show (ruler);
7347
7348
7349       ruler = gtk_vruler_new ();
7350       gtk_ruler_set_range (GTK_RULER (ruler), 5, 15, 0, 20);
7351
7352       g_signal_connect_swapped (window, 
7353                                 "motion_notify_event",
7354                                 G_CALLBACK (GTK_WIDGET_GET_CLASS (ruler)->motion_notify_event),
7355                                 ruler);
7356       
7357       gtk_table_attach (GTK_TABLE (table), ruler, 0, 1, 1, 2,
7358                         GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
7359       gtk_widget_show (ruler);
7360     }
7361
7362   if (!gtk_widget_get_visible (window))
7363     gtk_widget_show (window);
7364   else
7365     gtk_widget_destroy (window);
7366 }
7367
7368 static void
7369 text_toggle_editable (GtkWidget *checkbutton,
7370                        GtkWidget *text)
7371 {
7372    gtk_text_set_editable(GTK_TEXT(text),
7373                           GTK_TOGGLE_BUTTON(checkbutton)->active);
7374 }
7375
7376 static void
7377 text_toggle_word_wrap (GtkWidget *checkbutton,
7378                        GtkWidget *text)
7379 {
7380    gtk_text_set_word_wrap(GTK_TEXT(text),
7381                           GTK_TOGGLE_BUTTON(checkbutton)->active);
7382 }
7383
7384 struct {
7385   GdkColor color;
7386   gchar *name;
7387 } text_colors[] = {
7388  { { 0, 0x0000, 0x0000, 0x0000 }, "black" },
7389  { { 0, 0xFFFF, 0xFFFF, 0xFFFF }, "white" },
7390  { { 0, 0xFFFF, 0x0000, 0x0000 }, "red" },
7391  { { 0, 0x0000, 0xFFFF, 0x0000 }, "green" },
7392  { { 0, 0x0000, 0x0000, 0xFFFF }, "blue" }, 
7393  { { 0, 0x0000, 0xFFFF, 0xFFFF }, "cyan" },
7394  { { 0, 0xFFFF, 0x0000, 0xFFFF }, "magenta" },
7395  { { 0, 0xFFFF, 0xFFFF, 0x0000 }, "yellow" }
7396 };
7397
7398 int ntext_colors = sizeof(text_colors) / sizeof(text_colors[0]);
7399
7400 /*
7401  * GtkText
7402  */
7403 void
7404 text_insert_random (GtkWidget *w, GtkText *text)
7405 {
7406   int i;
7407   char c;
7408    for (i=0; i<10; i++)
7409     {
7410       c = 'A' + rand() % ('Z' - 'A');
7411       gtk_text_set_point (text, rand() % gtk_text_get_length (text));
7412       gtk_text_insert (text, NULL, NULL, NULL, &c, 1);
7413     }
7414 }
7415
7416 void
7417 create_text (GtkWidget *widget)
7418 {
7419   int i, j;
7420
7421   static GtkWidget *window = NULL;
7422   GtkWidget *box1;
7423   GtkWidget *box2;
7424   GtkWidget *hbox;
7425   GtkWidget *button;
7426   GtkWidget *check;
7427   GtkWidget *separator;
7428   GtkWidget *scrolled_window;
7429   GtkWidget *text;
7430
7431   FILE *infile;
7432
7433   if (!window)
7434     {
7435       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7436       gtk_window_set_screen (GTK_WINDOW (window),
7437                              gtk_widget_get_screen (widget));
7438
7439       gtk_widget_set_name (window, "text window");
7440       g_object_set (window, "allow_shrink", TRUE, "allow_grow", TRUE, NULL);
7441       gtk_widget_set_size_request (window, 500, 500);
7442
7443       g_signal_connect (window, "destroy",
7444                         G_CALLBACK (gtk_widget_destroyed),
7445                         &window);
7446
7447       gtk_window_set_title (GTK_WINDOW (window), "test");
7448       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
7449
7450
7451       box1 = gtk_vbox_new (FALSE, 0);
7452       gtk_container_add (GTK_CONTAINER (window), box1);
7453       gtk_widget_show (box1);
7454
7455
7456       box2 = gtk_vbox_new (FALSE, 10);
7457       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
7458       gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
7459       gtk_widget_show (box2);
7460
7461
7462       scrolled_window = gtk_scrolled_window_new (NULL, NULL);
7463       gtk_box_pack_start (GTK_BOX (box2), scrolled_window, TRUE, TRUE, 0);
7464       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
7465                                       GTK_POLICY_NEVER,
7466                                       GTK_POLICY_ALWAYS);
7467       gtk_widget_show (scrolled_window);
7468
7469       text = gtk_text_new (NULL, NULL);
7470       gtk_text_set_editable (GTK_TEXT (text), TRUE);
7471       gtk_container_add (GTK_CONTAINER (scrolled_window), text);
7472       gtk_widget_grab_focus (text);
7473       gtk_widget_show (text);
7474
7475
7476       gtk_text_freeze (GTK_TEXT (text));
7477
7478       for (i=0; i<ntext_colors; i++)
7479         {
7480           gtk_text_insert (GTK_TEXT (text), NULL, NULL, NULL, 
7481                            text_colors[i].name, -1);
7482           gtk_text_insert (GTK_TEXT (text), NULL, NULL, NULL, "\t", -1);
7483
7484           for (j=0; j<ntext_colors; j++)
7485             {
7486               gtk_text_insert (GTK_TEXT (text), NULL,
7487                                &text_colors[j].color, &text_colors[i].color,
7488                                "XYZ", -1);
7489             }
7490           gtk_text_insert (GTK_TEXT (text), NULL, NULL, NULL, "\n", -1);
7491         }
7492
7493       infile = fopen("testgtk.c", "r");
7494       
7495       if (infile)
7496         {
7497           char *buffer;
7498           int nbytes_read, nbytes_alloc;
7499           
7500           nbytes_read = 0;
7501           nbytes_alloc = 1024;
7502           buffer = g_new (char, nbytes_alloc);
7503           while (1)
7504             {
7505               int len;
7506               if (nbytes_alloc < nbytes_read + 1024)
7507                 {
7508                   nbytes_alloc *= 2;
7509                   buffer = g_realloc (buffer, nbytes_alloc);
7510                 }
7511               len = fread (buffer + nbytes_read, 1, 1024, infile);
7512               nbytes_read += len;
7513               if (len < 1024)
7514                 break;
7515             }
7516           
7517           gtk_text_insert (GTK_TEXT (text), NULL, NULL,
7518                            NULL, buffer, nbytes_read);
7519           g_free(buffer);
7520           fclose (infile);
7521         }
7522       
7523       gtk_text_thaw (GTK_TEXT (text));
7524
7525       hbox = gtk_hbutton_box_new ();
7526       gtk_box_pack_start (GTK_BOX (box2), hbox, FALSE, FALSE, 0);
7527       gtk_widget_show (hbox);
7528
7529       check = gtk_check_button_new_with_label("Editable");
7530       gtk_box_pack_start (GTK_BOX (hbox), check, FALSE, FALSE, 0);
7531       g_signal_connect (check, "toggled",
7532                         G_CALLBACK (text_toggle_editable), text);
7533       gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), TRUE);
7534       gtk_widget_show (check);
7535
7536       check = gtk_check_button_new_with_label("Wrap Words");
7537       gtk_box_pack_start (GTK_BOX (hbox), check, FALSE, TRUE, 0);
7538       g_signal_connect (check, "toggled",
7539                         G_CALLBACK (text_toggle_word_wrap), text);
7540       gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), FALSE);
7541       gtk_widget_show (check);
7542
7543       separator = gtk_hseparator_new ();
7544       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
7545       gtk_widget_show (separator);
7546
7547
7548       box2 = gtk_vbox_new (FALSE, 10);
7549       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
7550       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
7551       gtk_widget_show (box2);
7552
7553
7554       button = gtk_button_new_with_label ("insert random");
7555       g_signal_connect (button, "clicked",
7556                         G_CALLBACK (text_insert_random),
7557                         text);
7558       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
7559       gtk_widget_show (button);
7560
7561       button = gtk_button_new_with_label ("close");
7562       g_signal_connect_swapped (button, "clicked",
7563                                 G_CALLBACK (gtk_widget_destroy),
7564                                 window);
7565       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
7566       gtk_widget_set_can_default (button, TRUE);
7567       gtk_widget_grab_default (button);
7568       gtk_widget_show (button);
7569     }
7570
7571   if (!gtk_widget_get_visible (window))
7572     gtk_widget_show (window);
7573   else
7574     gtk_widget_destroy (window);
7575 }
7576
7577 /*
7578  * GtkNotebook
7579  */
7580
7581 GdkPixbuf *book_open;
7582 GdkPixbuf *book_closed;
7583 GtkWidget *sample_notebook;
7584
7585 static void
7586 set_page_image (GtkNotebook *notebook, gint page_num, GdkPixbuf *pixbuf)
7587 {
7588   GtkWidget *page_widget;
7589   GtkWidget *pixwid;
7590
7591   page_widget = gtk_notebook_get_nth_page (notebook, page_num);
7592
7593   pixwid = g_object_get_data (G_OBJECT (page_widget), "tab_pixmap");
7594   gtk_image_set_from_pixbuf (GTK_IMAGE (pixwid), pixbuf);
7595   
7596   pixwid = g_object_get_data (G_OBJECT (page_widget), "menu_pixmap");
7597   gtk_image_set_from_pixbuf (GTK_IMAGE (pixwid), pixbuf);
7598 }
7599
7600 static void
7601 page_switch (GtkWidget *widget, GtkNotebookPage *page, gint page_num)
7602 {
7603   GtkNotebook *notebook = GTK_NOTEBOOK (widget);
7604   gint old_page_num = gtk_notebook_get_current_page (notebook);
7605  
7606   if (page_num == old_page_num)
7607     return;
7608
7609   set_page_image (notebook, page_num, book_open);
7610
7611   if (old_page_num != -1)
7612     set_page_image (notebook, old_page_num, book_closed);
7613 }
7614
7615 static void
7616 tab_fill (GtkToggleButton *button, GtkWidget *child)
7617 {
7618   gboolean expand;
7619   GtkPackType pack_type;
7620
7621   gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (sample_notebook), child,
7622                                         &expand, NULL, &pack_type);
7623   gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (sample_notebook), child,
7624                                       expand, button->active, pack_type);
7625 }
7626
7627 static void
7628 tab_expand (GtkToggleButton *button, GtkWidget *child)
7629 {
7630   gboolean fill;
7631   GtkPackType pack_type;
7632
7633   gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (sample_notebook), child,
7634                                         NULL, &fill, &pack_type);
7635   gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (sample_notebook), child,
7636                                       button->active, fill, pack_type);
7637 }
7638
7639 static void
7640 tab_pack (GtkToggleButton *button, GtkWidget *child)
7641           
7642
7643   gboolean expand;
7644   gboolean fill;
7645
7646   gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (sample_notebook), child,
7647                                         &expand, &fill, NULL);
7648   gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (sample_notebook), child,
7649                                       expand, fill, button->active);
7650 }
7651
7652 static void
7653 create_pages (GtkNotebook *notebook, gint start, gint end)
7654 {
7655   GtkWidget *child = NULL;
7656   GtkWidget *button;
7657   GtkWidget *label;
7658   GtkWidget *hbox;
7659   GtkWidget *vbox;
7660   GtkWidget *label_box;
7661   GtkWidget *menu_box;
7662   GtkWidget *pixwid;
7663   gint i;
7664   char buffer[32];
7665   char accel_buffer[32];
7666
7667   for (i = start; i <= end; i++)
7668     {
7669       sprintf (buffer, "Page %d", i);
7670       sprintf (accel_buffer, "Page _%d", i);
7671
7672       child = gtk_frame_new (buffer);
7673       gtk_container_set_border_width (GTK_CONTAINER (child), 10);
7674
7675       vbox = gtk_vbox_new (TRUE,0);
7676       gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
7677       gtk_container_add (GTK_CONTAINER (child), vbox);
7678
7679       hbox = gtk_hbox_new (TRUE,0);
7680       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 5);
7681
7682       button = gtk_check_button_new_with_label ("Fill Tab");
7683       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
7684       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
7685       g_signal_connect (button, "toggled",
7686                         G_CALLBACK (tab_fill), child);
7687
7688       button = gtk_check_button_new_with_label ("Expand Tab");
7689       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
7690       g_signal_connect (button, "toggled",
7691                         G_CALLBACK (tab_expand), child);
7692
7693       button = gtk_check_button_new_with_label ("Pack end");
7694       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
7695       g_signal_connect (button, "toggled",
7696                         G_CALLBACK (tab_pack), child);
7697
7698       button = gtk_button_new_with_label ("Hide Page");
7699       gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 5);
7700       g_signal_connect_swapped (button, "clicked",
7701                                 G_CALLBACK (gtk_widget_hide),
7702                                 child);
7703
7704       gtk_widget_show_all (child);
7705
7706       label_box = gtk_hbox_new (FALSE, 0);
7707       pixwid = gtk_image_new_from_pixbuf (book_closed);
7708       g_object_set_data (G_OBJECT (child), "tab_pixmap", pixwid);
7709                            
7710       gtk_box_pack_start (GTK_BOX (label_box), pixwid, FALSE, TRUE, 0);
7711       gtk_misc_set_padding (GTK_MISC (pixwid), 3, 1);
7712       label = gtk_label_new_with_mnemonic (accel_buffer);
7713       gtk_box_pack_start (GTK_BOX (label_box), label, FALSE, TRUE, 0);
7714       gtk_widget_show_all (label_box);
7715       
7716                                        
7717       menu_box = gtk_hbox_new (FALSE, 0);
7718       pixwid = gtk_image_new_from_pixbuf (book_closed);
7719       g_object_set_data (G_OBJECT (child), "menu_pixmap", pixwid);
7720       
7721       gtk_box_pack_start (GTK_BOX (menu_box), pixwid, FALSE, TRUE, 0);
7722       gtk_misc_set_padding (GTK_MISC (pixwid), 3, 1);
7723       label = gtk_label_new (buffer);
7724       gtk_box_pack_start (GTK_BOX (menu_box), label, FALSE, TRUE, 0);
7725       gtk_widget_show_all (menu_box);
7726
7727       gtk_notebook_append_page_menu (notebook, child, label_box, menu_box);
7728     }
7729 }
7730
7731 static void
7732 rotate_notebook (GtkButton   *button,
7733                  GtkNotebook *notebook)
7734 {
7735   gtk_notebook_set_tab_pos (notebook, (notebook->tab_pos + 1) % 4);
7736 }
7737
7738 static void
7739 show_all_pages (GtkButton   *button,
7740                 GtkNotebook *notebook)
7741 {  
7742   gtk_container_foreach (GTK_CONTAINER (notebook),
7743                          (GtkCallback) gtk_widget_show, NULL);
7744 }
7745
7746 static void
7747 notebook_type_changed (GtkWidget *optionmenu,
7748                        gpointer   data)
7749 {
7750   GtkNotebook *notebook;
7751   gint i, c;
7752
7753   enum {
7754     STANDARD,
7755     NOTABS,
7756     BORDERLESS,
7757     SCROLLABLE
7758   };
7759
7760   notebook = GTK_NOTEBOOK (data);
7761
7762   c = gtk_option_menu_get_history (GTK_OPTION_MENU (optionmenu));
7763
7764   switch (c)
7765     {
7766     case STANDARD:
7767       /* standard notebook */
7768       gtk_notebook_set_show_tabs (notebook, TRUE);
7769       gtk_notebook_set_show_border (notebook, TRUE);
7770       gtk_notebook_set_scrollable (notebook, FALSE);
7771       break;
7772
7773     case NOTABS:
7774       /* notabs notebook */
7775       gtk_notebook_set_show_tabs (notebook, FALSE);
7776       gtk_notebook_set_show_border (notebook, TRUE);
7777       break;
7778
7779     case BORDERLESS:
7780       /* borderless */
7781       gtk_notebook_set_show_tabs (notebook, FALSE);
7782       gtk_notebook_set_show_border (notebook, FALSE);
7783       break;
7784
7785     case SCROLLABLE:  
7786       /* scrollable */
7787       gtk_notebook_set_show_tabs (notebook, TRUE);
7788       gtk_notebook_set_show_border (notebook, TRUE);
7789       gtk_notebook_set_scrollable (notebook, TRUE);
7790       if (g_list_length (notebook->children) == 5)
7791         create_pages (notebook, 6, 15);
7792       
7793       return;
7794       break;
7795     }
7796   
7797   if (g_list_length (notebook->children) == 15)
7798     for (i = 0; i < 10; i++)
7799       gtk_notebook_remove_page (notebook, 5);
7800 }
7801
7802 static void
7803 notebook_popup (GtkToggleButton *button,
7804                 GtkNotebook     *notebook)
7805 {
7806   if (button->active)
7807     gtk_notebook_popup_enable (notebook);
7808   else
7809     gtk_notebook_popup_disable (notebook);
7810 }
7811
7812 static void
7813 notebook_homogeneous (GtkToggleButton *button,
7814                       GtkNotebook     *notebook)
7815 {
7816   g_object_set (notebook, "homogeneous", button->active, NULL);
7817 }
7818
7819 static void
7820 create_notebook (GtkWidget *widget)
7821 {
7822   static GtkWidget *window = NULL;
7823   GtkWidget *box1;
7824   GtkWidget *box2;
7825   GtkWidget *button;
7826   GtkWidget *separator;
7827   GtkWidget *omenu;
7828   GtkWidget *label;
7829
7830   static gchar *items[] =
7831   {
7832     "Standard",
7833     "No tabs",
7834     "Borderless",
7835     "Scrollable"
7836   };
7837   
7838   if (!window)
7839     {
7840       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7841       gtk_window_set_screen (GTK_WINDOW (window),
7842                              gtk_widget_get_screen (widget));
7843
7844       g_signal_connect (window, "destroy",
7845                         G_CALLBACK (gtk_widget_destroyed),
7846                         &window);
7847
7848       gtk_window_set_title (GTK_WINDOW (window), "notebook");
7849       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
7850
7851       box1 = gtk_vbox_new (FALSE, 0);
7852       gtk_container_add (GTK_CONTAINER (window), box1);
7853
7854       sample_notebook = gtk_notebook_new ();
7855       g_signal_connect (sample_notebook, "switch_page",
7856                         G_CALLBACK (page_switch), NULL);
7857       gtk_notebook_set_tab_pos (GTK_NOTEBOOK (sample_notebook), GTK_POS_TOP);
7858       gtk_box_pack_start (GTK_BOX (box1), sample_notebook, TRUE, TRUE, 0);
7859       gtk_container_set_border_width (GTK_CONTAINER (sample_notebook), 10);
7860
7861       gtk_widget_realize (sample_notebook);
7862
7863       if (!book_open)
7864         book_open = gdk_pixbuf_new_from_xpm_data ((const char **)book_open_xpm);
7865                                                   
7866       if (!book_closed)
7867         book_closed = gdk_pixbuf_new_from_xpm_data ((const char **)book_closed_xpm);
7868
7869       create_pages (GTK_NOTEBOOK (sample_notebook), 1, 5);
7870
7871       separator = gtk_hseparator_new ();
7872       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 10);
7873       
7874       box2 = gtk_hbox_new (FALSE, 5);
7875       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
7876       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
7877
7878       button = gtk_check_button_new_with_label ("popup menu");
7879       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, FALSE, 0);
7880       g_signal_connect (button, "clicked",
7881                         G_CALLBACK (notebook_popup),
7882                         sample_notebook);
7883
7884       button = gtk_check_button_new_with_label ("homogeneous tabs");
7885       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, FALSE, 0);
7886       g_signal_connect (button, "clicked",
7887                         G_CALLBACK (notebook_homogeneous),
7888                         sample_notebook);
7889
7890       box2 = gtk_hbox_new (FALSE, 5);
7891       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
7892       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
7893
7894       label = gtk_label_new ("Notebook Style :");
7895       gtk_box_pack_start (GTK_BOX (box2), label, FALSE, TRUE, 0);
7896
7897       omenu = build_option_menu (items, G_N_ELEMENTS (items), 0,
7898                                  notebook_type_changed,
7899                                  sample_notebook);
7900       gtk_box_pack_start (GTK_BOX (box2), omenu, FALSE, TRUE, 0);
7901
7902       button = gtk_button_new_with_label ("Show all Pages");
7903       gtk_box_pack_start (GTK_BOX (box2), button, FALSE, TRUE, 0);
7904       g_signal_connect (button, "clicked",
7905                         G_CALLBACK (show_all_pages), sample_notebook);
7906
7907       box2 = gtk_hbox_new (TRUE, 10);
7908       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
7909       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
7910
7911       button = gtk_button_new_with_label ("prev");
7912       g_signal_connect_swapped (button, "clicked",
7913                                 G_CALLBACK (gtk_notebook_prev_page),
7914                                 sample_notebook);
7915       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
7916
7917       button = gtk_button_new_with_label ("next");
7918       g_signal_connect_swapped (button, "clicked",
7919                                 G_CALLBACK (gtk_notebook_next_page),
7920                                 sample_notebook);
7921       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
7922
7923       button = gtk_button_new_with_label ("rotate");
7924       g_signal_connect (button, "clicked",
7925                         G_CALLBACK (rotate_notebook), sample_notebook);
7926       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
7927
7928       separator = gtk_hseparator_new ();
7929       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
7930
7931       button = gtk_button_new_with_label ("close");
7932       gtk_container_set_border_width (GTK_CONTAINER (button), 5);
7933       g_signal_connect_swapped (button, "clicked",
7934                                 G_CALLBACK (gtk_widget_destroy),
7935                                 window);
7936       gtk_box_pack_start (GTK_BOX (box1), button, FALSE, FALSE, 0);
7937       gtk_widget_set_can_default (button, TRUE);
7938       gtk_widget_grab_default (button);
7939     }
7940
7941   if (!gtk_widget_get_visible (window))
7942     gtk_widget_show_all (window);
7943   else
7944     gtk_widget_destroy (window);
7945 }
7946
7947 /*
7948  * GtkPanes
7949  */
7950
7951 void
7952 toggle_resize (GtkWidget *widget, GtkWidget *child)
7953 {
7954   GtkContainer *container = GTK_CONTAINER (gtk_widget_get_parent (child));
7955   GValue value = { 0, };
7956   g_value_init (&value, G_TYPE_BOOLEAN);
7957   gtk_container_child_get_property (container, child, "resize", &value);
7958   g_value_set_boolean (&value, !g_value_get_boolean (&value));
7959   gtk_container_child_set_property (container, child, "resize", &value);
7960 }
7961
7962 void
7963 toggle_shrink (GtkWidget *widget, GtkWidget *child)
7964 {
7965   GtkContainer *container = GTK_CONTAINER (gtk_widget_get_parent (child));
7966   GValue value = { 0, };
7967   g_value_init (&value, G_TYPE_BOOLEAN);
7968   gtk_container_child_get_property (container, child, "shrink", &value);
7969   g_value_set_boolean (&value, !g_value_get_boolean (&value));
7970   gtk_container_child_set_property (container, child, "shrink", &value);
7971 }
7972
7973 static void
7974 paned_props_clicked (GtkWidget *button,
7975                      GObject   *paned)
7976 {
7977   GtkWidget *window = create_prop_editor (paned, GTK_TYPE_PANED);
7978   
7979   gtk_window_set_title (GTK_WINDOW (window), "Paned Properties");
7980 }
7981
7982 GtkWidget *
7983 create_pane_options (GtkPaned    *paned,
7984                      const gchar *frame_label,
7985                      const gchar *label1,
7986                      const gchar *label2)
7987 {
7988   GtkWidget *frame;
7989   GtkWidget *table;
7990   GtkWidget *label;
7991   GtkWidget *button;
7992   GtkWidget *check_button;
7993   
7994   frame = gtk_frame_new (frame_label);
7995   gtk_container_set_border_width (GTK_CONTAINER (frame), 4);
7996   
7997   table = gtk_table_new (4, 2, 4);
7998   gtk_container_add (GTK_CONTAINER (frame), table);
7999   
8000   label = gtk_label_new (label1);
8001   gtk_table_attach_defaults (GTK_TABLE (table), label,
8002                              0, 1, 0, 1);
8003   
8004   check_button = gtk_check_button_new_with_label ("Resize");
8005   gtk_table_attach_defaults (GTK_TABLE (table), check_button,
8006                              0, 1, 1, 2);
8007   g_signal_connect (check_button, "toggled",
8008                     G_CALLBACK (toggle_resize),
8009                     paned->child1);
8010   
8011   check_button = gtk_check_button_new_with_label ("Shrink");
8012   gtk_table_attach_defaults (GTK_TABLE (table), check_button,
8013                              0, 1, 2, 3);
8014   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button),
8015                                TRUE);
8016   g_signal_connect (check_button, "toggled",
8017                     G_CALLBACK (toggle_shrink),
8018                     paned->child1);
8019   
8020   label = gtk_label_new (label2);
8021   gtk_table_attach_defaults (GTK_TABLE (table), label,
8022                              1, 2, 0, 1);
8023   
8024   check_button = gtk_check_button_new_with_label ("Resize");
8025   gtk_table_attach_defaults (GTK_TABLE (table), check_button,
8026                              1, 2, 1, 2);
8027   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button),
8028                                TRUE);
8029   g_signal_connect (check_button, "toggled",
8030                     G_CALLBACK (toggle_resize),
8031                     paned->child2);
8032   
8033   check_button = gtk_check_button_new_with_label ("Shrink");
8034   gtk_table_attach_defaults (GTK_TABLE (table), check_button,
8035                              1, 2, 2, 3);
8036   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button),
8037                                TRUE);
8038   g_signal_connect (check_button, "toggled",
8039                     G_CALLBACK (toggle_shrink),
8040                     paned->child2);
8041
8042   button = gtk_button_new_with_mnemonic ("_Properties");
8043   gtk_table_attach_defaults (GTK_TABLE (table), button,
8044                              0, 2, 3, 4);
8045   g_signal_connect (button, "clicked",
8046                     G_CALLBACK (paned_props_clicked),
8047                     paned);
8048
8049   return frame;
8050 }
8051
8052 void
8053 create_panes (GtkWidget *widget)
8054 {
8055   static GtkWidget *window = NULL;
8056   GtkWidget *frame;
8057   GtkWidget *hpaned;
8058   GtkWidget *vpaned;
8059   GtkWidget *button;
8060   GtkWidget *vbox;
8061
8062   if (!window)
8063     {
8064       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8065
8066       gtk_window_set_screen (GTK_WINDOW (window),
8067                              gtk_widget_get_screen (widget));
8068       
8069       g_signal_connect (window, "destroy",
8070                         G_CALLBACK (gtk_widget_destroyed),
8071                         &window);
8072
8073       gtk_window_set_title (GTK_WINDOW (window), "Panes");
8074       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
8075
8076       vbox = gtk_vbox_new (FALSE, 0);
8077       gtk_container_add (GTK_CONTAINER (window), vbox);
8078       
8079       vpaned = gtk_vpaned_new ();
8080       gtk_box_pack_start (GTK_BOX (vbox), vpaned, TRUE, TRUE, 0);
8081       gtk_container_set_border_width (GTK_CONTAINER(vpaned), 5);
8082
8083       hpaned = gtk_hpaned_new ();
8084       gtk_paned_add1 (GTK_PANED (vpaned), hpaned);
8085
8086       frame = gtk_frame_new (NULL);
8087       gtk_frame_set_shadow_type (GTK_FRAME(frame), GTK_SHADOW_IN);
8088       gtk_widget_set_size_request (frame, 60, 60);
8089       gtk_paned_add1 (GTK_PANED (hpaned), frame);
8090       
8091       button = gtk_button_new_with_label ("Hi there");
8092       gtk_container_add (GTK_CONTAINER(frame), button);
8093
8094       frame = gtk_frame_new (NULL);
8095       gtk_frame_set_shadow_type (GTK_FRAME(frame), GTK_SHADOW_IN);
8096       gtk_widget_set_size_request (frame, 80, 60);
8097       gtk_paned_add2 (GTK_PANED (hpaned), frame);
8098
8099       frame = gtk_frame_new (NULL);
8100       gtk_frame_set_shadow_type (GTK_FRAME(frame), GTK_SHADOW_IN);
8101       gtk_widget_set_size_request (frame, 60, 80);
8102       gtk_paned_add2 (GTK_PANED (vpaned), frame);
8103
8104       /* Now create toggle buttons to control sizing */
8105
8106       gtk_box_pack_start (GTK_BOX (vbox),
8107                           create_pane_options (GTK_PANED (hpaned),
8108                                                "Horizontal",
8109                                                "Left",
8110                                                "Right"),
8111                           FALSE, FALSE, 0);
8112
8113       gtk_box_pack_start (GTK_BOX (vbox),
8114                           create_pane_options (GTK_PANED (vpaned),
8115                                                "Vertical",
8116                                                "Top",
8117                                                "Bottom"),
8118                           FALSE, FALSE, 0);
8119
8120       gtk_widget_show_all (vbox);
8121     }
8122
8123   if (!gtk_widget_get_visible (window))
8124     gtk_widget_show (window);
8125   else
8126     gtk_widget_destroy (window);
8127 }
8128
8129 /*
8130  * Paned keyboard navigation
8131  */
8132
8133 static GtkWidget*
8134 paned_keyboard_window1 (GtkWidget *widget)
8135 {
8136   GtkWidget *window1;
8137   GtkWidget *hpaned1;
8138   GtkWidget *frame1;
8139   GtkWidget *vbox1;
8140   GtkWidget *button7;
8141   GtkWidget *button8;
8142   GtkWidget *button9;
8143   GtkWidget *vpaned1;
8144   GtkWidget *frame2;
8145   GtkWidget *frame5;
8146   GtkWidget *hbox1;
8147   GtkWidget *button5;
8148   GtkWidget *button6;
8149   GtkWidget *frame3;
8150   GtkWidget *frame4;
8151   GtkWidget *table1;
8152   GtkWidget *button1;
8153   GtkWidget *button2;
8154   GtkWidget *button3;
8155   GtkWidget *button4;
8156
8157   window1 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8158   gtk_window_set_title (GTK_WINDOW (window1), "Basic paned navigation");
8159   gtk_window_set_screen (GTK_WINDOW (window1), 
8160                          gtk_widget_get_screen (widget));
8161
8162   hpaned1 = gtk_hpaned_new ();
8163   gtk_container_add (GTK_CONTAINER (window1), hpaned1);
8164
8165   frame1 = gtk_frame_new (NULL);
8166   gtk_paned_pack1 (GTK_PANED (hpaned1), frame1, FALSE, TRUE);
8167   gtk_frame_set_shadow_type (GTK_FRAME (frame1), GTK_SHADOW_IN);
8168
8169   vbox1 = gtk_vbox_new (FALSE, 0);
8170   gtk_container_add (GTK_CONTAINER (frame1), vbox1);
8171
8172   button7 = gtk_button_new_with_label ("button7");
8173   gtk_box_pack_start (GTK_BOX (vbox1), button7, FALSE, FALSE, 0);
8174
8175   button8 = gtk_button_new_with_label ("button8");
8176   gtk_box_pack_start (GTK_BOX (vbox1), button8, FALSE, FALSE, 0);
8177
8178   button9 = gtk_button_new_with_label ("button9");
8179   gtk_box_pack_start (GTK_BOX (vbox1), button9, FALSE, FALSE, 0);
8180
8181   vpaned1 = gtk_vpaned_new ();
8182   gtk_paned_pack2 (GTK_PANED (hpaned1), vpaned1, TRUE, TRUE);
8183
8184   frame2 = gtk_frame_new (NULL);
8185   gtk_paned_pack1 (GTK_PANED (vpaned1), frame2, FALSE, TRUE);
8186   gtk_frame_set_shadow_type (GTK_FRAME (frame2), GTK_SHADOW_IN);
8187
8188   frame5 = gtk_frame_new (NULL);
8189   gtk_container_add (GTK_CONTAINER (frame2), frame5);
8190
8191   hbox1 = gtk_hbox_new (FALSE, 0);
8192   gtk_container_add (GTK_CONTAINER (frame5), hbox1);
8193
8194   button5 = gtk_button_new_with_label ("button5");
8195   gtk_box_pack_start (GTK_BOX (hbox1), button5, FALSE, FALSE, 0);
8196
8197   button6 = gtk_button_new_with_label ("button6");
8198   gtk_box_pack_start (GTK_BOX (hbox1), button6, FALSE, FALSE, 0);
8199
8200   frame3 = gtk_frame_new (NULL);
8201   gtk_paned_pack2 (GTK_PANED (vpaned1), frame3, TRUE, TRUE);
8202   gtk_frame_set_shadow_type (GTK_FRAME (frame3), GTK_SHADOW_IN);
8203
8204   frame4 = gtk_frame_new ("Buttons");
8205   gtk_container_add (GTK_CONTAINER (frame3), frame4);
8206   gtk_container_set_border_width (GTK_CONTAINER (frame4), 15);
8207
8208   table1 = gtk_table_new (2, 2, FALSE);
8209   gtk_container_add (GTK_CONTAINER (frame4), table1);
8210   gtk_container_set_border_width (GTK_CONTAINER (table1), 11);
8211
8212   button1 = gtk_button_new_with_label ("button1");
8213   gtk_table_attach (GTK_TABLE (table1), button1, 0, 1, 0, 1,
8214                     (GtkAttachOptions) (GTK_FILL),
8215                     (GtkAttachOptions) (0), 0, 0);
8216
8217   button2 = gtk_button_new_with_label ("button2");
8218   gtk_table_attach (GTK_TABLE (table1), button2, 1, 2, 0, 1,
8219                     (GtkAttachOptions) (GTK_FILL),
8220                     (GtkAttachOptions) (0), 0, 0);
8221
8222   button3 = gtk_button_new_with_label ("button3");
8223   gtk_table_attach (GTK_TABLE (table1), button3, 0, 1, 1, 2,
8224                     (GtkAttachOptions) (GTK_FILL),
8225                     (GtkAttachOptions) (0), 0, 0);
8226
8227   button4 = gtk_button_new_with_label ("button4");
8228   gtk_table_attach (GTK_TABLE (table1), button4, 1, 2, 1, 2,
8229                     (GtkAttachOptions) (GTK_FILL),
8230                     (GtkAttachOptions) (0), 0, 0);
8231
8232   return window1;
8233 }
8234
8235 static GtkWidget*
8236 paned_keyboard_window2 (GtkWidget *widget)
8237 {
8238   GtkWidget *window2;
8239   GtkWidget *hpaned2;
8240   GtkWidget *frame6;
8241   GtkWidget *button13;
8242   GtkWidget *hbox2;
8243   GtkWidget *vpaned2;
8244   GtkWidget *frame7;
8245   GtkWidget *button12;
8246   GtkWidget *frame8;
8247   GtkWidget *button11;
8248   GtkWidget *button10;
8249
8250   window2 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8251   gtk_window_set_title (GTK_WINDOW (window2), "\"button 10\" is not inside the horisontal pane");
8252
8253   gtk_window_set_screen (GTK_WINDOW (window2), 
8254                          gtk_widget_get_screen (widget));
8255
8256   hpaned2 = gtk_hpaned_new ();
8257   gtk_container_add (GTK_CONTAINER (window2), hpaned2);
8258
8259   frame6 = gtk_frame_new (NULL);
8260   gtk_paned_pack1 (GTK_PANED (hpaned2), frame6, FALSE, TRUE);
8261   gtk_frame_set_shadow_type (GTK_FRAME (frame6), GTK_SHADOW_IN);
8262
8263   button13 = gtk_button_new_with_label ("button13");
8264   gtk_container_add (GTK_CONTAINER (frame6), button13);
8265
8266   hbox2 = gtk_hbox_new (FALSE, 0);
8267   gtk_paned_pack2 (GTK_PANED (hpaned2), hbox2, TRUE, TRUE);
8268
8269   vpaned2 = gtk_vpaned_new ();
8270   gtk_box_pack_start (GTK_BOX (hbox2), vpaned2, TRUE, TRUE, 0);
8271
8272   frame7 = gtk_frame_new (NULL);
8273   gtk_paned_pack1 (GTK_PANED (vpaned2), frame7, FALSE, TRUE);
8274   gtk_frame_set_shadow_type (GTK_FRAME (frame7), GTK_SHADOW_IN);
8275
8276   button12 = gtk_button_new_with_label ("button12");
8277   gtk_container_add (GTK_CONTAINER (frame7), button12);
8278
8279   frame8 = gtk_frame_new (NULL);
8280   gtk_paned_pack2 (GTK_PANED (vpaned2), frame8, TRUE, TRUE);
8281   gtk_frame_set_shadow_type (GTK_FRAME (frame8), GTK_SHADOW_IN);
8282
8283   button11 = gtk_button_new_with_label ("button11");
8284   gtk_container_add (GTK_CONTAINER (frame8), button11);
8285
8286   button10 = gtk_button_new_with_label ("button10");
8287   gtk_box_pack_start (GTK_BOX (hbox2), button10, FALSE, FALSE, 0);
8288
8289   return window2;
8290 }
8291
8292 static GtkWidget*
8293 paned_keyboard_window3 (GtkWidget *widget)
8294 {
8295   GtkWidget *window3;
8296   GtkWidget *vbox2;
8297   GtkWidget *label1;
8298   GtkWidget *hpaned3;
8299   GtkWidget *frame9;
8300   GtkWidget *button14;
8301   GtkWidget *hpaned4;
8302   GtkWidget *frame10;
8303   GtkWidget *button15;
8304   GtkWidget *hpaned5;
8305   GtkWidget *frame11;
8306   GtkWidget *button16;
8307   GtkWidget *frame12;
8308   GtkWidget *button17;
8309
8310   window3 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8311   g_object_set_data (G_OBJECT (window3), "window3", window3);
8312   gtk_window_set_title (GTK_WINDOW (window3), "Nested panes");
8313
8314   gtk_window_set_screen (GTK_WINDOW (window3), 
8315                          gtk_widget_get_screen (widget));
8316   
8317
8318   vbox2 = gtk_vbox_new (FALSE, 0);
8319   gtk_container_add (GTK_CONTAINER (window3), vbox2);
8320
8321   label1 = gtk_label_new ("Three panes nested inside each other");
8322   gtk_box_pack_start (GTK_BOX (vbox2), label1, FALSE, FALSE, 0);
8323
8324   hpaned3 = gtk_hpaned_new ();
8325   gtk_box_pack_start (GTK_BOX (vbox2), hpaned3, TRUE, TRUE, 0);
8326
8327   frame9 = gtk_frame_new (NULL);
8328   gtk_paned_pack1 (GTK_PANED (hpaned3), frame9, FALSE, TRUE);
8329   gtk_frame_set_shadow_type (GTK_FRAME (frame9), GTK_SHADOW_IN);
8330
8331   button14 = gtk_button_new_with_label ("button14");
8332   gtk_container_add (GTK_CONTAINER (frame9), button14);
8333
8334   hpaned4 = gtk_hpaned_new ();
8335   gtk_paned_pack2 (GTK_PANED (hpaned3), hpaned4, TRUE, TRUE);
8336
8337   frame10 = gtk_frame_new (NULL);
8338   gtk_paned_pack1 (GTK_PANED (hpaned4), frame10, FALSE, TRUE);
8339   gtk_frame_set_shadow_type (GTK_FRAME (frame10), GTK_SHADOW_IN);
8340
8341   button15 = gtk_button_new_with_label ("button15");
8342   gtk_container_add (GTK_CONTAINER (frame10), button15);
8343
8344   hpaned5 = gtk_hpaned_new ();
8345   gtk_paned_pack2 (GTK_PANED (hpaned4), hpaned5, TRUE, TRUE);
8346
8347   frame11 = gtk_frame_new (NULL);
8348   gtk_paned_pack1 (GTK_PANED (hpaned5), frame11, FALSE, TRUE);
8349   gtk_frame_set_shadow_type (GTK_FRAME (frame11), GTK_SHADOW_IN);
8350
8351   button16 = gtk_button_new_with_label ("button16");
8352   gtk_container_add (GTK_CONTAINER (frame11), button16);
8353
8354   frame12 = gtk_frame_new (NULL);
8355   gtk_paned_pack2 (GTK_PANED (hpaned5), frame12, TRUE, TRUE);
8356   gtk_frame_set_shadow_type (GTK_FRAME (frame12), GTK_SHADOW_IN);
8357
8358   button17 = gtk_button_new_with_label ("button17");
8359   gtk_container_add (GTK_CONTAINER (frame12), button17);
8360
8361   return window3;
8362 }
8363
8364 static GtkWidget*
8365 paned_keyboard_window4 (GtkWidget *widget)
8366 {
8367   GtkWidget *window4;
8368   GtkWidget *vbox3;
8369   GtkWidget *label2;
8370   GtkWidget *hpaned6;
8371   GtkWidget *vpaned3;
8372   GtkWidget *button19;
8373   GtkWidget *button18;
8374   GtkWidget *hbox3;
8375   GtkWidget *vpaned4;
8376   GtkWidget *button21;
8377   GtkWidget *button20;
8378   GtkWidget *vpaned5;
8379   GtkWidget *button23;
8380   GtkWidget *button22;
8381   GtkWidget *vpaned6;
8382   GtkWidget *button25;
8383   GtkWidget *button24;
8384
8385   window4 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8386   g_object_set_data (G_OBJECT (window4), "window4", window4);
8387   gtk_window_set_title (GTK_WINDOW (window4), "window4");
8388
8389   gtk_window_set_screen (GTK_WINDOW (window4), 
8390                          gtk_widget_get_screen (widget));
8391
8392   vbox3 = gtk_vbox_new (FALSE, 0);
8393   gtk_container_add (GTK_CONTAINER (window4), vbox3);
8394
8395   label2 = gtk_label_new ("Widget tree:\n\nhpaned \n - vpaned\n - hbox\n    - vpaned\n    - vpaned\n    - vpaned\n");
8396   gtk_box_pack_start (GTK_BOX (vbox3), label2, FALSE, FALSE, 0);
8397   gtk_label_set_justify (GTK_LABEL (label2), GTK_JUSTIFY_LEFT);
8398
8399   hpaned6 = gtk_hpaned_new ();
8400   gtk_box_pack_start (GTK_BOX (vbox3), hpaned6, TRUE, TRUE, 0);
8401
8402   vpaned3 = gtk_vpaned_new ();
8403   gtk_paned_pack1 (GTK_PANED (hpaned6), vpaned3, FALSE, TRUE);
8404
8405   button19 = gtk_button_new_with_label ("button19");
8406   gtk_paned_pack1 (GTK_PANED (vpaned3), button19, FALSE, TRUE);
8407
8408   button18 = gtk_button_new_with_label ("button18");
8409   gtk_paned_pack2 (GTK_PANED (vpaned3), button18, TRUE, TRUE);
8410
8411   hbox3 = gtk_hbox_new (FALSE, 0);
8412   gtk_paned_pack2 (GTK_PANED (hpaned6), hbox3, TRUE, TRUE);
8413
8414   vpaned4 = gtk_vpaned_new ();
8415   gtk_box_pack_start (GTK_BOX (hbox3), vpaned4, TRUE, TRUE, 0);
8416
8417   button21 = gtk_button_new_with_label ("button21");
8418   gtk_paned_pack1 (GTK_PANED (vpaned4), button21, FALSE, TRUE);
8419
8420   button20 = gtk_button_new_with_label ("button20");
8421   gtk_paned_pack2 (GTK_PANED (vpaned4), button20, TRUE, TRUE);
8422
8423   vpaned5 = gtk_vpaned_new ();
8424   gtk_box_pack_start (GTK_BOX (hbox3), vpaned5, TRUE, TRUE, 0);
8425
8426   button23 = gtk_button_new_with_label ("button23");
8427   gtk_paned_pack1 (GTK_PANED (vpaned5), button23, FALSE, TRUE);
8428
8429   button22 = gtk_button_new_with_label ("button22");
8430   gtk_paned_pack2 (GTK_PANED (vpaned5), button22, TRUE, TRUE);
8431
8432   vpaned6 = gtk_vpaned_new ();
8433   gtk_box_pack_start (GTK_BOX (hbox3), vpaned6, TRUE, TRUE, 0);
8434
8435   button25 = gtk_button_new_with_label ("button25");
8436   gtk_paned_pack1 (GTK_PANED (vpaned6), button25, FALSE, TRUE);
8437
8438   button24 = gtk_button_new_with_label ("button24");
8439   gtk_paned_pack2 (GTK_PANED (vpaned6), button24, TRUE, TRUE);
8440
8441   return window4;
8442 }
8443
8444 static void
8445 create_paned_keyboard_navigation (GtkWidget *widget)
8446 {
8447   static GtkWidget *window1 = NULL;
8448   static GtkWidget *window2 = NULL;
8449   static GtkWidget *window3 = NULL;
8450   static GtkWidget *window4 = NULL;
8451
8452   if (window1 && 
8453      (gtk_widget_get_screen (window1) != gtk_widget_get_screen (widget)))
8454     {
8455       gtk_widget_destroy (window1);
8456       gtk_widget_destroy (window2);
8457       gtk_widget_destroy (window3);
8458       gtk_widget_destroy (window4);
8459     }
8460   
8461   if (!window1)
8462     {
8463       window1 = paned_keyboard_window1 (widget);
8464       g_signal_connect (window1, "destroy",
8465                         G_CALLBACK (gtk_widget_destroyed),
8466                         &window1);
8467     }
8468
8469   if (!window2)
8470     {
8471       window2 = paned_keyboard_window2 (widget);
8472       g_signal_connect (window2, "destroy",
8473                         G_CALLBACK (gtk_widget_destroyed),
8474                         &window2);
8475     }
8476
8477   if (!window3)
8478     {
8479       window3 = paned_keyboard_window3 (widget);
8480       g_signal_connect (window3, "destroy",
8481                         G_CALLBACK (gtk_widget_destroyed),
8482                         &window3);
8483     }
8484
8485   if (!window4)
8486     {
8487       window4 = paned_keyboard_window4 (widget);
8488       g_signal_connect (window4, "destroy",
8489                         G_CALLBACK (gtk_widget_destroyed),
8490                         &window4);
8491     }
8492
8493   if (gtk_widget_get_visible (window1))
8494     gtk_widget_destroy (GTK_WIDGET (window1));
8495   else
8496     gtk_widget_show_all (GTK_WIDGET (window1));
8497
8498   if (gtk_widget_get_visible (window2))
8499     gtk_widget_destroy (GTK_WIDGET (window2));
8500   else
8501     gtk_widget_show_all (GTK_WIDGET (window2));
8502
8503   if (gtk_widget_get_visible (window3))
8504     gtk_widget_destroy (GTK_WIDGET (window3));
8505   else
8506     gtk_widget_show_all (GTK_WIDGET (window3));
8507
8508   if (gtk_widget_get_visible (window4))
8509     gtk_widget_destroy (GTK_WIDGET (window4));
8510   else
8511     gtk_widget_show_all (GTK_WIDGET (window4));
8512 }
8513
8514
8515 /*
8516  * Shaped Windows
8517  */
8518
8519 typedef struct _cursoroffset {gint x,y;} CursorOffset;
8520
8521 static void
8522 shape_pressed (GtkWidget *widget, GdkEventButton *event)
8523 {
8524   CursorOffset *p;
8525
8526   /* ignore double and triple click */
8527   if (event->type != GDK_BUTTON_PRESS)
8528     return;
8529
8530   p = g_object_get_data (G_OBJECT (widget), "cursor_offset");
8531   p->x = (int) event->x;
8532   p->y = (int) event->y;
8533
8534   gtk_grab_add (widget);
8535   gdk_pointer_grab (widget->window, TRUE,
8536                     GDK_BUTTON_RELEASE_MASK |
8537                     GDK_BUTTON_MOTION_MASK |
8538                     GDK_POINTER_MOTION_HINT_MASK,
8539                     NULL, NULL, 0);
8540 }
8541
8542 static void
8543 shape_released (GtkWidget *widget)
8544 {
8545   gtk_grab_remove (widget);
8546   gdk_display_pointer_ungrab (gtk_widget_get_display (widget),
8547                               GDK_CURRENT_TIME);
8548 }
8549
8550 static void
8551 shape_motion (GtkWidget      *widget, 
8552               GdkEventMotion *event)
8553 {
8554   gint xp, yp;
8555   CursorOffset * p;
8556   GdkModifierType mask;
8557
8558   p = g_object_get_data (G_OBJECT (widget), "cursor_offset");
8559
8560   /*
8561    * Can't use event->x / event->y here 
8562    * because I need absolute coordinates.
8563    */
8564   gdk_window_get_pointer (NULL, &xp, &yp, &mask);
8565   gtk_widget_set_uposition (widget, xp  - p->x, yp  - p->y);
8566 }
8567
8568 GtkWidget *
8569 shape_create_icon (GdkScreen *screen,
8570                    char      *xpm_file,
8571                    gint       x,
8572                    gint       y,
8573                    gint       px,
8574                    gint       py,
8575                    gint       window_type)
8576 {
8577   GtkWidget *window;
8578   GtkWidget *pixmap;
8579   GtkWidget *fixed;
8580   CursorOffset* icon_pos;
8581   GdkGC* gc;
8582   GdkBitmap *gdk_pixmap_mask;
8583   GdkPixmap *gdk_pixmap;
8584   GtkStyle *style;
8585
8586   style = gtk_widget_get_default_style ();
8587   gc = style->black_gc; 
8588
8589   /*
8590    * GDK_WINDOW_TOPLEVEL works also, giving you a title border
8591    */
8592   window = gtk_window_new (window_type);
8593   gtk_window_set_screen (GTK_WINDOW (window), screen);
8594   
8595   fixed = gtk_fixed_new ();
8596   gtk_widget_set_size_request (fixed, 100, 100);
8597   gtk_container_add (GTK_CONTAINER (window), fixed);
8598   gtk_widget_show (fixed);
8599   
8600   gtk_widget_set_events (window, 
8601                          gtk_widget_get_events (window) |
8602                          GDK_BUTTON_MOTION_MASK |
8603                          GDK_POINTER_MOTION_HINT_MASK |
8604                          GDK_BUTTON_PRESS_MASK);
8605
8606   gtk_widget_realize (window);
8607   gdk_pixmap = gdk_pixmap_create_from_xpm (window->window, &gdk_pixmap_mask, 
8608                                            &style->bg[GTK_STATE_NORMAL],
8609                                            xpm_file);
8610
8611   pixmap = gtk_image_new_from_pixmap (gdk_pixmap, gdk_pixmap_mask);
8612   gtk_fixed_put (GTK_FIXED (fixed), pixmap, px,py);
8613   gtk_widget_show (pixmap);
8614   
8615   gtk_widget_shape_combine_mask (window, gdk_pixmap_mask, px, py);
8616   
8617   g_object_unref (gdk_pixmap_mask);
8618   g_object_unref (gdk_pixmap);
8619
8620   g_signal_connect (window, "button_press_event",
8621                     G_CALLBACK (shape_pressed), NULL);
8622   g_signal_connect (window, "button_release_event",
8623                     G_CALLBACK (shape_released), NULL);
8624   g_signal_connect (window, "motion_notify_event",
8625                     G_CALLBACK (shape_motion), NULL);
8626
8627   icon_pos = g_new (CursorOffset, 1);
8628   g_object_set_data (G_OBJECT (window), "cursor_offset", icon_pos);
8629
8630   gtk_widget_set_uposition (window, x, y);
8631   gtk_widget_show (window);
8632   
8633   return window;
8634 }
8635
8636 void 
8637 create_shapes (GtkWidget *widget)
8638 {
8639   /* Variables used by the Drag/Drop and Shape Window demos */
8640   static GtkWidget *modeller = NULL;
8641   static GtkWidget *sheets = NULL;
8642   static GtkWidget *rings = NULL;
8643   static GtkWidget *with_region = NULL;
8644   GdkScreen *screen = gtk_widget_get_screen (widget);
8645   
8646   if (!(file_exists ("Modeller.xpm") &&
8647         file_exists ("FilesQueue.xpm") &&
8648         file_exists ("3DRings.xpm")))
8649     return;
8650   
8651
8652   if (!modeller)
8653     {
8654       modeller = shape_create_icon (screen, "Modeller.xpm",
8655                                     440, 140, 0,0, GTK_WINDOW_POPUP);
8656
8657       g_signal_connect (modeller, "destroy",
8658                         G_CALLBACK (gtk_widget_destroyed),
8659                         &modeller);
8660     }
8661   else
8662     gtk_widget_destroy (modeller);
8663
8664   if (!sheets)
8665     {
8666       sheets = shape_create_icon (screen, "FilesQueue.xpm",
8667                                   580, 170, 0,0, GTK_WINDOW_POPUP);
8668
8669       g_signal_connect (sheets, "destroy",
8670                         G_CALLBACK (gtk_widget_destroyed),
8671                         &sheets);
8672
8673     }
8674   else
8675     gtk_widget_destroy (sheets);
8676
8677   if (!rings)
8678     {
8679       rings = shape_create_icon (screen, "3DRings.xpm",
8680                                  460, 270, 25,25, GTK_WINDOW_TOPLEVEL);
8681
8682       g_signal_connect (rings, "destroy",
8683                         G_CALLBACK (gtk_widget_destroyed),
8684                         &rings);
8685     }
8686   else
8687     gtk_widget_destroy (rings);
8688
8689   if (!with_region)
8690     {
8691       GdkRegion *region;
8692       gint x, y;
8693       
8694       with_region = shape_create_icon (screen, "3DRings.xpm",
8695                                        460, 270, 25,25, GTK_WINDOW_TOPLEVEL);
8696
8697       gtk_window_set_decorated (GTK_WINDOW (with_region), FALSE);
8698       
8699       g_signal_connect (with_region, "destroy",
8700                         G_CALLBACK (gtk_widget_destroyed),
8701                         &with_region);
8702
8703       /* reset shape from mask to a region */
8704       x = 0;
8705       y = 0;
8706       region = gdk_region_new ();
8707
8708       while (x < 460)
8709         {
8710           while (y < 270)
8711             {
8712               GdkRectangle rect;
8713               rect.x = x;
8714               rect.y = y;
8715               rect.width = 10;
8716               rect.height = 10;
8717
8718               gdk_region_union_with_rect (region, &rect);
8719               
8720               y += 20;
8721             }
8722           y = 0;
8723           x += 20;
8724         }
8725
8726       gdk_window_shape_combine_region (with_region->window,
8727                                        region,
8728                                        0, 0);
8729     }
8730   else
8731     gtk_widget_destroy (with_region);
8732 }
8733
8734 /*
8735  * WM Hints demo
8736  */
8737
8738 void
8739 create_wmhints (GtkWidget *widget)
8740 {
8741   static GtkWidget *window = NULL;
8742   GtkWidget *label;
8743   GtkWidget *separator;
8744   GtkWidget *button;
8745   GtkWidget *box1;
8746   GtkWidget *box2;
8747
8748   GdkBitmap *circles;
8749
8750   if (!window)
8751     {
8752       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8753
8754       gtk_window_set_screen (GTK_WINDOW (window),
8755                              gtk_widget_get_screen (widget));
8756       
8757       g_signal_connect (window, "destroy",
8758                         G_CALLBACK (gtk_widget_destroyed),
8759                         &window);
8760
8761       gtk_window_set_title (GTK_WINDOW (window), "WM Hints");
8762       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
8763
8764       gtk_widget_realize (window);
8765       
8766       circles = gdk_bitmap_create_from_data (window->window,
8767                                              (gchar *) circles_bits,
8768                                              circles_width,
8769                                              circles_height);
8770       gdk_window_set_icon (window->window, NULL,
8771                            circles, circles);
8772       
8773       gdk_window_set_icon_name (window->window, "WMHints Test Icon");
8774   
8775       gdk_window_set_decorations (window->window, GDK_DECOR_ALL | GDK_DECOR_MENU);
8776       gdk_window_set_functions (window->window, GDK_FUNC_ALL | GDK_FUNC_RESIZE);
8777       
8778       box1 = gtk_vbox_new (FALSE, 0);
8779       gtk_container_add (GTK_CONTAINER (window), box1);
8780       gtk_widget_show (box1);
8781
8782       label = gtk_label_new ("Try iconizing me!");
8783       gtk_widget_set_size_request (label, 150, 50);
8784       gtk_box_pack_start (GTK_BOX (box1), label, TRUE, TRUE, 0);
8785       gtk_widget_show (label);
8786
8787
8788       separator = gtk_hseparator_new ();
8789       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
8790       gtk_widget_show (separator);
8791
8792
8793       box2 = gtk_vbox_new (FALSE, 10);
8794       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
8795       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
8796       gtk_widget_show (box2);
8797
8798
8799       button = gtk_button_new_with_label ("close");
8800
8801       g_signal_connect_swapped (button, "clicked",
8802                                 G_CALLBACK (gtk_widget_destroy),
8803                                 window);
8804
8805       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
8806       gtk_widget_set_can_default (button, TRUE);
8807       gtk_widget_grab_default (button);
8808       gtk_widget_show (button);
8809     }
8810
8811   if (!gtk_widget_get_visible (window))
8812     gtk_widget_show (window);
8813   else
8814     gtk_widget_destroy (window);
8815 }
8816
8817
8818 /*
8819  * Window state tracking
8820  */
8821
8822 static gint
8823 window_state_callback (GtkWidget *widget,
8824                        GdkEventWindowState *event,
8825                        gpointer data)
8826 {
8827   GtkWidget *label = data;
8828   gchar *msg;
8829
8830   msg = g_strconcat (GTK_WINDOW (widget)->title, ": ",
8831                      (event->new_window_state & GDK_WINDOW_STATE_WITHDRAWN) ?
8832                      "withdrawn" : "not withdrawn", ", ",
8833                      (event->new_window_state & GDK_WINDOW_STATE_ICONIFIED) ?
8834                      "iconified" : "not iconified", ", ",
8835                      (event->new_window_state & GDK_WINDOW_STATE_STICKY) ?
8836                      "sticky" : "not sticky", ", ",
8837                      (event->new_window_state & GDK_WINDOW_STATE_MAXIMIZED) ?
8838                      "maximized" : "not maximized", ", ",
8839                      (event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN) ?
8840                      "fullscreen" : "not fullscreen",
8841                      (event->new_window_state & GDK_WINDOW_STATE_ABOVE) ?
8842                      "above" : "not above", ", ",
8843                      (event->new_window_state & GDK_WINDOW_STATE_BELOW) ?
8844                      "below" : "not below", ", ",
8845                      NULL);
8846   
8847   gtk_label_set_text (GTK_LABEL (label), msg);
8848
8849   g_free (msg);
8850
8851   return FALSE;
8852 }
8853
8854 static GtkWidget*
8855 tracking_label (GtkWidget *window)
8856 {
8857   GtkWidget *label;
8858   GtkWidget *hbox;
8859   GtkWidget *button;
8860
8861   hbox = gtk_hbox_new (FALSE, 5);
8862
8863   g_signal_connect_object (hbox,
8864                            "destroy",
8865                            G_CALLBACK (gtk_widget_destroy),
8866                            window,
8867                            G_CONNECT_SWAPPED);
8868   
8869   label = gtk_label_new ("<no window state events received>");
8870   gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
8871   gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
8872   
8873   g_signal_connect (window,
8874                     "window_state_event",
8875                     G_CALLBACK (window_state_callback),
8876                     label);
8877
8878   button = gtk_button_new_with_label ("Deiconify");
8879   g_signal_connect_object (button,
8880                            "clicked",
8881                            G_CALLBACK (gtk_window_deiconify),
8882                            window,
8883                            G_CONNECT_SWAPPED);
8884   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
8885
8886   button = gtk_button_new_with_label ("Iconify");
8887   g_signal_connect_object (button,
8888                            "clicked",
8889                            G_CALLBACK (gtk_window_iconify),
8890                            window,
8891                            G_CONNECT_SWAPPED);
8892   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
8893
8894   button = gtk_button_new_with_label ("Fullscreen");
8895   g_signal_connect_object (button,
8896                            "clicked",
8897                            G_CALLBACK (gtk_window_fullscreen),
8898                            window,
8899                            G_CONNECT_SWAPPED);
8900   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
8901
8902   button = gtk_button_new_with_label ("Unfullscreen");
8903   g_signal_connect_object (button,
8904                            "clicked",
8905                            G_CALLBACK (gtk_window_unfullscreen),
8906                            window,
8907                            G_CONNECT_SWAPPED);
8908   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
8909   
8910   button = gtk_button_new_with_label ("Present");
8911   g_signal_connect_object (button,
8912                            "clicked",
8913                            G_CALLBACK (gtk_window_present),
8914                            window,
8915                            G_CONNECT_SWAPPED);
8916   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
8917
8918   button = gtk_button_new_with_label ("Show");
8919   g_signal_connect_object (button,
8920                            "clicked",
8921                            G_CALLBACK (gtk_widget_show),
8922                            window,
8923                            G_CONNECT_SWAPPED);
8924   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
8925   
8926   gtk_widget_show_all (hbox);
8927   
8928   return hbox;
8929 }
8930
8931 void
8932 keep_window_above (GtkToggleButton *togglebutton, gpointer data)
8933 {
8934   GtkWidget *button = g_object_get_data (G_OBJECT (togglebutton), "radio");
8935
8936   gtk_window_set_keep_above (GTK_WINDOW (data),
8937                              gtk_toggle_button_get_active (togglebutton));
8938
8939   if (gtk_toggle_button_get_active (togglebutton))
8940     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE);
8941 }
8942
8943 void
8944 keep_window_below (GtkToggleButton *togglebutton, gpointer data)
8945 {
8946   GtkWidget *button = g_object_get_data (G_OBJECT (togglebutton), "radio");
8947
8948   gtk_window_set_keep_below (GTK_WINDOW (data),
8949                              gtk_toggle_button_get_active (togglebutton));
8950
8951   if (gtk_toggle_button_get_active (togglebutton))
8952     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE);
8953 }
8954
8955
8956 static GtkWidget*
8957 get_state_controls (GtkWidget *window)
8958 {
8959   GtkWidget *vbox;
8960   GtkWidget *button;
8961   GtkWidget *button_above;
8962   GtkWidget *button_below;
8963
8964   vbox = gtk_vbox_new (FALSE, 0);
8965   
8966   button = gtk_button_new_with_label ("Stick");
8967   g_signal_connect_object (button,
8968                            "clicked",
8969                            G_CALLBACK (gtk_window_stick),
8970                            window,
8971                            G_CONNECT_SWAPPED);
8972   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8973
8974   button = gtk_button_new_with_label ("Unstick");
8975   g_signal_connect_object (button,
8976                            "clicked",
8977                            G_CALLBACK (gtk_window_unstick),
8978                            window,
8979                            G_CONNECT_SWAPPED);
8980   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8981   
8982   button = gtk_button_new_with_label ("Maximize");
8983   g_signal_connect_object (button,
8984                            "clicked",
8985                            G_CALLBACK (gtk_window_maximize),
8986                            window,
8987                            G_CONNECT_SWAPPED);
8988   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8989
8990   button = gtk_button_new_with_label ("Unmaximize");
8991   g_signal_connect_object (button,
8992                            "clicked",
8993                            G_CALLBACK (gtk_window_unmaximize),
8994                            window,
8995                            G_CONNECT_SWAPPED);
8996   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8997
8998   button = gtk_button_new_with_label ("Iconify");
8999   g_signal_connect_object (button,
9000                            "clicked",
9001                            G_CALLBACK (gtk_window_iconify),
9002                            window,
9003                            G_CONNECT_SWAPPED);
9004   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
9005
9006   button = gtk_button_new_with_label ("Fullscreen");
9007   g_signal_connect_object (button,
9008                            "clicked",
9009                            G_CALLBACK (gtk_window_fullscreen),
9010                            window,
9011                            G_CONNECT_SWAPPED);
9012   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
9013
9014   button = gtk_button_new_with_label ("Unfullscreen");
9015   g_signal_connect_object (button,
9016                            "clicked",
9017                            G_CALLBACK (gtk_window_unfullscreen),
9018                            window,
9019                            G_CONNECT_SWAPPED);
9020   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
9021
9022   button_above = gtk_toggle_button_new_with_label ("Keep above");
9023   g_signal_connect (button_above,
9024                     "toggled",
9025                     G_CALLBACK (keep_window_above),
9026                     window);
9027   gtk_box_pack_start (GTK_BOX (vbox), button_above, FALSE, FALSE, 0);
9028
9029   button_below = gtk_toggle_button_new_with_label ("Keep below");
9030   g_signal_connect (button_below,
9031                     "toggled",
9032                     G_CALLBACK (keep_window_below),
9033                     window);
9034   gtk_box_pack_start (GTK_BOX (vbox), button_below, FALSE, FALSE, 0);
9035
9036   g_object_set_data (G_OBJECT (button_above), "radio", button_below);
9037   g_object_set_data (G_OBJECT (button_below), "radio", button_above);
9038
9039   button = gtk_button_new_with_label ("Hide (withdraw)");
9040   g_signal_connect_object (button,
9041                            "clicked",
9042                            G_CALLBACK (gtk_widget_hide),
9043                            window,
9044                            G_CONNECT_SWAPPED);
9045   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
9046   
9047   gtk_widget_show_all (vbox);
9048
9049   return vbox;
9050 }
9051
9052 void
9053 create_window_states (GtkWidget *widget)
9054 {
9055   static GtkWidget *window = NULL;
9056   GtkWidget *label;
9057   GtkWidget *box1;
9058   GtkWidget *iconified;
9059   GtkWidget *normal;
9060   GtkWidget *controls;
9061
9062   if (!window)
9063     {
9064       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9065       gtk_window_set_screen (GTK_WINDOW (window),
9066                              gtk_widget_get_screen (widget));
9067
9068       g_signal_connect (window, "destroy",
9069                         G_CALLBACK (gtk_widget_destroyed),
9070                         &window);
9071
9072       gtk_window_set_title (GTK_WINDOW (window), "Window states");
9073       
9074       box1 = gtk_vbox_new (FALSE, 0);
9075       gtk_container_add (GTK_CONTAINER (window), box1);
9076
9077       iconified = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9078
9079       gtk_window_set_screen (GTK_WINDOW (iconified),
9080                              gtk_widget_get_screen (widget));
9081       
9082       g_signal_connect_object (iconified, "destroy",
9083                                G_CALLBACK (gtk_widget_destroy),
9084                                window,
9085                                G_CONNECT_SWAPPED);
9086       gtk_window_iconify (GTK_WINDOW (iconified));
9087       gtk_window_set_title (GTK_WINDOW (iconified), "Iconified initially");
9088       controls = get_state_controls (iconified);
9089       gtk_container_add (GTK_CONTAINER (iconified), controls);
9090       
9091       normal = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9092
9093       gtk_window_set_screen (GTK_WINDOW (normal),
9094                              gtk_widget_get_screen (widget));
9095       
9096       g_signal_connect_object (normal, "destroy",
9097                                G_CALLBACK (gtk_widget_destroy),
9098                                window,
9099                                G_CONNECT_SWAPPED);
9100       
9101       gtk_window_set_title (GTK_WINDOW (normal), "Deiconified initially");
9102       controls = get_state_controls (normal);
9103       gtk_container_add (GTK_CONTAINER (normal), controls);
9104       
9105       label = tracking_label (iconified);
9106       gtk_container_add (GTK_CONTAINER (box1), label);
9107
9108       label = tracking_label (normal);
9109       gtk_container_add (GTK_CONTAINER (box1), label);
9110
9111       gtk_widget_show_all (iconified);
9112       gtk_widget_show_all (normal);
9113       gtk_widget_show_all (box1);
9114     }
9115
9116   if (!gtk_widget_get_visible (window))
9117     gtk_widget_show (window);
9118   else
9119     gtk_widget_destroy (window);
9120 }
9121
9122 /*
9123  * Window sizing
9124  */
9125
9126 static gint
9127 configure_event_callback (GtkWidget *widget,
9128                           GdkEventConfigure *event,
9129                           gpointer data)
9130 {
9131   GtkWidget *label = data;
9132   gchar *msg;
9133   gint x, y;
9134   
9135   gtk_window_get_position (GTK_WINDOW (widget), &x, &y);
9136   
9137   msg = g_strdup_printf ("event: %d,%d  %d x %d\n"
9138                          "position: %d, %d",
9139                          event->x, event->y, event->width, event->height,
9140                          x, y);
9141   
9142   gtk_label_set_text (GTK_LABEL (label), msg);
9143
9144   g_free (msg);
9145
9146   return FALSE;
9147 }
9148
9149 static void
9150 get_ints (GtkWidget *window,
9151           gint      *a,
9152           gint      *b)
9153 {
9154   GtkWidget *spin1;
9155   GtkWidget *spin2;
9156
9157   spin1 = g_object_get_data (G_OBJECT (window), "spin1");
9158   spin2 = g_object_get_data (G_OBJECT (window), "spin2");
9159
9160   *a = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (spin1));
9161   *b = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (spin2));
9162 }
9163
9164 static void
9165 set_size_callback (GtkWidget *widget,
9166                    gpointer   data)
9167 {
9168   gint w, h;
9169   
9170   get_ints (data, &w, &h);
9171
9172   gtk_window_resize (GTK_WINDOW (g_object_get_data (data, "target")), w, h);
9173 }
9174
9175 static void
9176 unset_default_size_callback (GtkWidget *widget,
9177                              gpointer   data)
9178 {
9179   gtk_window_set_default_size (g_object_get_data (data, "target"),
9180                                -1, -1);
9181 }
9182
9183 static void
9184 set_default_size_callback (GtkWidget *widget,
9185                            gpointer   data)
9186 {
9187   gint w, h;
9188   
9189   get_ints (data, &w, &h);
9190
9191   gtk_window_set_default_size (g_object_get_data (data, "target"),
9192                                w, h);
9193 }
9194
9195 static void
9196 unset_size_request_callback (GtkWidget *widget,
9197                              gpointer   data)
9198 {
9199   gtk_widget_set_size_request (g_object_get_data (data, "target"),
9200                                -1, -1);
9201 }
9202
9203 static void
9204 set_size_request_callback (GtkWidget *widget,
9205                            gpointer   data)
9206 {
9207   gint w, h;
9208   
9209   get_ints (data, &w, &h);
9210
9211   gtk_widget_set_size_request (g_object_get_data (data, "target"),
9212                                w, h);
9213 }
9214
9215 static void
9216 set_location_callback (GtkWidget *widget,
9217                        gpointer   data)
9218 {
9219   gint x, y;
9220   
9221   get_ints (data, &x, &y);
9222
9223   gtk_window_move (g_object_get_data (data, "target"), x, y);
9224 }
9225
9226 static void
9227 move_to_position_callback (GtkWidget *widget,
9228                            gpointer   data)
9229 {
9230   gint x, y;
9231   GtkWindow *window;
9232
9233   window = g_object_get_data (data, "target");
9234   
9235   gtk_window_get_position (window, &x, &y);
9236
9237   gtk_window_move (window, x, y);
9238 }
9239
9240 static void
9241 set_geometry_callback (GtkWidget *entry,
9242                        gpointer   data)
9243 {
9244   gchar *text;
9245   GtkWindow *target;
9246
9247   target = GTK_WINDOW (g_object_get_data (G_OBJECT (data), "target"));
9248   
9249   text = gtk_editable_get_chars (GTK_EDITABLE (entry), 0, -1);
9250
9251   if (!gtk_window_parse_geometry (target, text))
9252     g_print ("Bad geometry string '%s'\n", text);
9253
9254   g_free (text);
9255 }
9256
9257 static void
9258 allow_shrink_callback (GtkWidget *widget,
9259                        gpointer   data)
9260 {
9261   g_object_set (g_object_get_data (data, "target"),
9262                 "allow_shrink",
9263                 GTK_TOGGLE_BUTTON (widget)->active,
9264                 NULL);
9265 }
9266
9267 static void
9268 allow_grow_callback (GtkWidget *widget,
9269                      gpointer   data)
9270 {
9271   g_object_set (g_object_get_data (data, "target"),
9272                 "allow_grow",
9273                 GTK_TOGGLE_BUTTON (widget)->active,
9274                 NULL);
9275 }
9276
9277 static void
9278 gravity_selected (GtkWidget *widget,
9279                   gpointer   data)
9280 {
9281   gtk_window_set_gravity (GTK_WINDOW (g_object_get_data (data, "target")),
9282                           gtk_option_menu_get_history (GTK_OPTION_MENU (widget)) + GDK_GRAVITY_NORTH_WEST);
9283 }
9284
9285 static void
9286 pos_selected (GtkWidget *widget,
9287               gpointer   data)
9288 {
9289   gtk_window_set_position (GTK_WINDOW (g_object_get_data (data, "target")),
9290                            gtk_option_menu_get_history (GTK_OPTION_MENU (widget)) + GTK_WIN_POS_NONE);
9291 }
9292
9293 static void
9294 move_gravity_window_to_current_position (GtkWidget *widget,
9295                                          gpointer   data)
9296 {
9297   gint x, y;
9298   GtkWindow *window;
9299
9300   window = GTK_WINDOW (data);    
9301   
9302   gtk_window_get_position (window, &x, &y);
9303
9304   gtk_window_move (window, x, y);
9305 }
9306
9307 static void
9308 get_screen_corner (GtkWindow *window,
9309                    gint      *x,
9310                    gint      *y)
9311 {
9312   int w, h;
9313   GdkScreen * screen = gtk_window_get_screen (window);
9314   
9315   gtk_window_get_size (GTK_WINDOW (window), &w, &h);
9316
9317   switch (gtk_window_get_gravity (window))
9318     {
9319     case GDK_GRAVITY_SOUTH_EAST:
9320       *x = gdk_screen_get_width (screen) - w;
9321       *y = gdk_screen_get_height (screen) - h;
9322       break;
9323
9324     case GDK_GRAVITY_NORTH_EAST:
9325       *x = gdk_screen_get_width (screen) - w;
9326       *y = 0;
9327       break;
9328
9329     case GDK_GRAVITY_SOUTH_WEST:
9330       *x = 0;
9331       *y = gdk_screen_get_height (screen) - h;
9332       break;
9333
9334     case GDK_GRAVITY_NORTH_WEST:
9335       *x = 0;
9336       *y = 0;
9337       break;
9338       
9339     case GDK_GRAVITY_SOUTH:
9340       *x = (gdk_screen_get_width (screen) - w) / 2;
9341       *y = gdk_screen_get_height (screen) - h;
9342       break;
9343
9344     case GDK_GRAVITY_NORTH:
9345       *x = (gdk_screen_get_width (screen) - w) / 2;
9346       *y = 0;
9347       break;
9348
9349     case GDK_GRAVITY_WEST:
9350       *x = 0;
9351       *y = (gdk_screen_get_height (screen) - h) / 2;
9352       break;
9353
9354     case GDK_GRAVITY_EAST:
9355       *x = gdk_screen_get_width (screen) - w;
9356       *y = (gdk_screen_get_height (screen) - h) / 2;
9357       break;
9358
9359     case GDK_GRAVITY_CENTER:
9360       *x = (gdk_screen_get_width (screen) - w) / 2;
9361       *y = (gdk_screen_get_height (screen) - h) / 2;
9362       break;
9363
9364     case GDK_GRAVITY_STATIC:
9365       /* pick some random numbers */
9366       *x = 350;
9367       *y = 350;
9368       break;
9369
9370     default:
9371       g_assert_not_reached ();
9372       break;
9373     }
9374 }
9375
9376 static void
9377 move_gravity_window_to_starting_position (GtkWidget *widget,
9378                                           gpointer   data)
9379 {
9380   gint x, y;
9381   GtkWindow *window;
9382
9383   window = GTK_WINDOW (data);    
9384   
9385   get_screen_corner (window,
9386                      &x, &y);
9387   
9388   gtk_window_move (window, x, y);
9389 }
9390
9391 static GtkWidget*
9392 make_gravity_window (GtkWidget   *destroy_with,
9393                      GdkGravity   gravity,
9394                      const gchar *title)
9395 {
9396   GtkWidget *window;
9397   GtkWidget *button;
9398   GtkWidget *vbox;
9399   int x, y;
9400   
9401   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9402
9403   gtk_window_set_screen (GTK_WINDOW (window),
9404                          gtk_widget_get_screen (destroy_with));
9405
9406   vbox = gtk_vbox_new (FALSE, 0);
9407   gtk_widget_show (vbox);
9408   
9409   gtk_container_add (GTK_CONTAINER (window), vbox);
9410   gtk_window_set_title (GTK_WINDOW (window), title);
9411   gtk_window_set_gravity (GTK_WINDOW (window), gravity);
9412
9413   g_signal_connect_object (destroy_with,
9414                            "destroy",
9415                            G_CALLBACK (gtk_widget_destroy),
9416                            window,
9417                            G_CONNECT_SWAPPED);
9418
9419   
9420   button = gtk_button_new_with_mnemonic ("_Move to current position");
9421
9422   g_signal_connect (button, "clicked",
9423                     G_CALLBACK (move_gravity_window_to_current_position),
9424                     window);
9425
9426   gtk_container_add (GTK_CONTAINER (vbox), button);
9427   gtk_widget_show (button);
9428
9429   button = gtk_button_new_with_mnemonic ("Move to _starting position");
9430
9431   g_signal_connect (button, "clicked",
9432                     G_CALLBACK (move_gravity_window_to_starting_position),
9433                     window);
9434
9435   gtk_container_add (GTK_CONTAINER (vbox), button);
9436   gtk_widget_show (button);
9437   
9438   /* Pretend this is the result of --geometry.
9439    * DO NOT COPY THIS CODE unless you are setting --geometry results,
9440    * and in that case you probably should just use gtk_window_parse_geometry().
9441    * AGAIN, DO NOT SET GDK_HINT_USER_POS! It violates the ICCCM unless
9442    * you are parsing --geometry or equivalent.
9443    */
9444   gtk_window_set_geometry_hints (GTK_WINDOW (window),
9445                                  NULL, NULL,
9446                                  GDK_HINT_USER_POS);
9447
9448   gtk_window_set_default_size (GTK_WINDOW (window),
9449                                200, 200);
9450
9451   get_screen_corner (GTK_WINDOW (window), &x, &y);
9452   
9453   gtk_window_move (GTK_WINDOW (window),
9454                    x, y);
9455   
9456   return window;
9457 }
9458
9459 static void
9460 do_gravity_test (GtkWidget *widget,
9461                  gpointer   data)
9462 {
9463   GtkWidget *destroy_with = data;
9464   GtkWidget *window;
9465   
9466   /* We put a window at each gravity point on the screen. */
9467   window = make_gravity_window (destroy_with, GDK_GRAVITY_NORTH_WEST,
9468                                 "NorthWest");
9469   gtk_widget_show (window);
9470   
9471   window = make_gravity_window (destroy_with, GDK_GRAVITY_SOUTH_EAST,
9472                                 "SouthEast");
9473   gtk_widget_show (window);
9474
9475   window = make_gravity_window (destroy_with, GDK_GRAVITY_NORTH_EAST,
9476                                 "NorthEast");
9477   gtk_widget_show (window);
9478
9479   window = make_gravity_window (destroy_with, GDK_GRAVITY_SOUTH_WEST,
9480                                 "SouthWest");
9481   gtk_widget_show (window);
9482
9483   window = make_gravity_window (destroy_with, GDK_GRAVITY_SOUTH,
9484                                 "South");
9485   gtk_widget_show (window);
9486
9487   window = make_gravity_window (destroy_with, GDK_GRAVITY_NORTH,
9488                                 "North");
9489   gtk_widget_show (window);
9490
9491   
9492   window = make_gravity_window (destroy_with, GDK_GRAVITY_WEST,
9493                                 "West");
9494   gtk_widget_show (window);
9495
9496     
9497   window = make_gravity_window (destroy_with, GDK_GRAVITY_EAST,
9498                                 "East");
9499   gtk_widget_show (window);
9500
9501   window = make_gravity_window (destroy_with, GDK_GRAVITY_CENTER,
9502                                 "Center");
9503   gtk_widget_show (window);
9504
9505   window = make_gravity_window (destroy_with, GDK_GRAVITY_STATIC,
9506                                 "Static");
9507   gtk_widget_show (window);
9508 }
9509
9510 static GtkWidget*
9511 window_controls (GtkWidget *window)
9512 {
9513   GtkWidget *control_window;
9514   GtkWidget *label;
9515   GtkWidget *vbox;
9516   GtkWidget *button;
9517   GtkWidget *spin;
9518   GtkAdjustment *adj;
9519   GtkWidget *entry;
9520   GtkWidget *om;
9521   GtkWidget *menu;
9522   gint i;
9523   
9524   control_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9525
9526   gtk_window_set_screen (GTK_WINDOW (control_window),
9527                          gtk_widget_get_screen (window));
9528
9529   gtk_window_set_title (GTK_WINDOW (control_window), "Size controls");
9530   
9531   g_object_set_data (G_OBJECT (control_window),
9532                      "target",
9533                      window);
9534   
9535   g_signal_connect_object (control_window,
9536                            "destroy",
9537                            G_CALLBACK (gtk_widget_destroy),
9538                            window,
9539                            G_CONNECT_SWAPPED);
9540
9541   vbox = gtk_vbox_new (FALSE, 5);
9542   
9543   gtk_container_add (GTK_CONTAINER (control_window), vbox);
9544   
9545   label = gtk_label_new ("<no configure events>");
9546   gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
9547   
9548   g_signal_connect (window,
9549                     "configure_event",
9550                     G_CALLBACK (configure_event_callback),
9551                     label);
9552
9553   adj = (GtkAdjustment *) gtk_adjustment_new (10.0, -2000.0, 2000.0, 1.0,
9554                                               5.0, 0.0);
9555   spin = gtk_spin_button_new (adj, 0, 0);
9556
9557   gtk_box_pack_start (GTK_BOX (vbox), spin, FALSE, FALSE, 0);
9558
9559   g_object_set_data (G_OBJECT (control_window), "spin1", spin);
9560
9561   adj = (GtkAdjustment *) gtk_adjustment_new (10.0, -2000.0, 2000.0, 1.0,
9562                                               5.0, 0.0);
9563   spin = gtk_spin_button_new (adj, 0, 0);
9564
9565   gtk_box_pack_start (GTK_BOX (vbox), spin, FALSE, FALSE, 0);
9566
9567   g_object_set_data (G_OBJECT (control_window), "spin2", spin);
9568
9569   entry = gtk_entry_new ();
9570   gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
9571
9572   g_signal_connect (entry, "changed",
9573                     G_CALLBACK (set_geometry_callback),
9574                     control_window);
9575
9576   button = gtk_button_new_with_label ("Show gravity test windows");
9577   g_signal_connect_swapped (button,
9578                             "clicked",
9579                             G_CALLBACK (do_gravity_test),
9580                             control_window);
9581   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
9582
9583   button = gtk_button_new_with_label ("Reshow with initial size");
9584   g_signal_connect_object (button,
9585                            "clicked",
9586                            G_CALLBACK (gtk_window_reshow_with_initial_size),
9587                            window,
9588                            G_CONNECT_SWAPPED);
9589   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
9590   
9591   button = gtk_button_new_with_label ("Queue resize");
9592   g_signal_connect_object (button,
9593                            "clicked",
9594                            G_CALLBACK (gtk_widget_queue_resize),
9595                            window,
9596                            G_CONNECT_SWAPPED);
9597   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
9598   
9599   button = gtk_button_new_with_label ("Resize");
9600   g_signal_connect (button,
9601                     "clicked",
9602                     G_CALLBACK (set_size_callback),
9603                     control_window);
9604   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
9605
9606   button = gtk_button_new_with_label ("Set default size");
9607   g_signal_connect (button,
9608                     "clicked",
9609                     G_CALLBACK (set_default_size_callback),
9610                     control_window);
9611   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
9612
9613   button = gtk_button_new_with_label ("Unset default size");
9614   g_signal_connect (button,
9615                     "clicked",
9616                     G_CALLBACK (unset_default_size_callback),
9617                     control_window);
9618   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
9619   
9620   button = gtk_button_new_with_label ("Set size request");
9621   g_signal_connect (button,
9622                     "clicked",
9623                     G_CALLBACK (set_size_request_callback),
9624                     control_window);
9625   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
9626
9627   button = gtk_button_new_with_label ("Unset size request");
9628   g_signal_connect (button,
9629                     "clicked",
9630                     G_CALLBACK (unset_size_request_callback),
9631                     control_window);
9632   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
9633   
9634   button = gtk_button_new_with_label ("Move");
9635   g_signal_connect (button,
9636                     "clicked",
9637                     G_CALLBACK (set_location_callback),
9638                     control_window);
9639   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
9640
9641   button = gtk_button_new_with_label ("Move to current position");
9642   g_signal_connect (button,
9643                     "clicked",
9644                     G_CALLBACK (move_to_position_callback),
9645                     control_window);
9646   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
9647   
9648   button = gtk_check_button_new_with_label ("Allow shrink");
9649   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE);
9650   g_signal_connect (button,
9651                     "toggled",
9652                     G_CALLBACK (allow_shrink_callback),
9653                     control_window);
9654   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
9655
9656   button = gtk_check_button_new_with_label ("Allow grow");
9657   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
9658   g_signal_connect (button,
9659                     "toggled",
9660                     G_CALLBACK (allow_grow_callback),
9661                     control_window);
9662   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
9663   
9664   button = gtk_button_new_with_mnemonic ("_Show");
9665   g_signal_connect_object (button,
9666                            "clicked",
9667                            G_CALLBACK (gtk_widget_show),
9668                            window,
9669                            G_CONNECT_SWAPPED);
9670   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
9671
9672   button = gtk_button_new_with_mnemonic ("_Hide");
9673   g_signal_connect_object (button,
9674                            "clicked",
9675                            G_CALLBACK (gtk_widget_hide),
9676                            window,
9677                            G_CONNECT_SWAPPED);
9678   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
9679   
9680   menu = gtk_menu_new ();
9681   
9682   i = 0;
9683   while (i < 10)
9684     {
9685       GtkWidget *mi;
9686       static gchar *names[] = {
9687         "GDK_GRAVITY_NORTH_WEST",
9688         "GDK_GRAVITY_NORTH",
9689         "GDK_GRAVITY_NORTH_EAST",
9690         "GDK_GRAVITY_WEST",
9691         "GDK_GRAVITY_CENTER",
9692         "GDK_GRAVITY_EAST",
9693         "GDK_GRAVITY_SOUTH_WEST",
9694         "GDK_GRAVITY_SOUTH",
9695         "GDK_GRAVITY_SOUTH_EAST",
9696         "GDK_GRAVITY_STATIC",
9697         NULL
9698       };
9699
9700       g_assert (names[i]);
9701       
9702       mi = gtk_menu_item_new_with_label (names[i]);
9703
9704       gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
9705
9706       ++i;
9707     }
9708   
9709   gtk_widget_show_all (menu);
9710   
9711   om = gtk_option_menu_new ();
9712   gtk_option_menu_set_menu (GTK_OPTION_MENU (om), menu);
9713   
9714
9715   g_signal_connect (om,
9716                     "changed",
9717                     G_CALLBACK (gravity_selected),
9718                     control_window);
9719
9720   gtk_box_pack_end (GTK_BOX (vbox), om, FALSE, FALSE, 0);
9721
9722
9723   menu = gtk_menu_new ();
9724   
9725   i = 0;
9726   while (i < 5)
9727     {
9728       GtkWidget *mi;
9729       static gchar *names[] = {
9730         "GTK_WIN_POS_NONE",
9731         "GTK_WIN_POS_CENTER",
9732         "GTK_WIN_POS_MOUSE",
9733         "GTK_WIN_POS_CENTER_ALWAYS",
9734         "GTK_WIN_POS_CENTER_ON_PARENT",
9735         NULL
9736       };
9737
9738       g_assert (names[i]);
9739       
9740       mi = gtk_menu_item_new_with_label (names[i]);
9741
9742       gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
9743
9744       ++i;
9745     }
9746   
9747   gtk_widget_show_all (menu);
9748   
9749   om = gtk_option_menu_new ();
9750   gtk_option_menu_set_menu (GTK_OPTION_MENU (om), menu);
9751   
9752
9753   g_signal_connect (om,
9754                     "changed",
9755                     G_CALLBACK (pos_selected),
9756                     control_window);
9757
9758   gtk_box_pack_end (GTK_BOX (vbox), om, FALSE, FALSE, 0);
9759   
9760   gtk_widget_show_all (vbox);
9761   
9762   return control_window;
9763 }
9764
9765 void
9766 create_window_sizing (GtkWidget *widget)
9767 {
9768   static GtkWidget *window = NULL;
9769   static GtkWidget *target_window = NULL;
9770
9771   if (!target_window)
9772     {
9773       GtkWidget *label;
9774       
9775       target_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9776       gtk_window_set_screen (GTK_WINDOW (target_window),
9777                              gtk_widget_get_screen (widget));
9778       label = gtk_label_new (NULL);
9779       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");
9780       gtk_container_add (GTK_CONTAINER (target_window), label);
9781       gtk_widget_show (label);
9782       
9783       g_signal_connect (target_window, "destroy",
9784                         G_CALLBACK (gtk_widget_destroyed),
9785                         &target_window);
9786
9787       window = window_controls (target_window);
9788       
9789       g_signal_connect (window, "destroy",
9790                         G_CALLBACK (gtk_widget_destroyed),
9791                         &window);
9792       
9793       gtk_window_set_title (GTK_WINDOW (target_window), "Window to size");
9794     }
9795
9796   /* don't show target window by default, we want to allow testing
9797    * of behavior on first show.
9798    */
9799   
9800   if (!gtk_widget_get_visible (window))
9801     gtk_widget_show (window);
9802   else
9803     gtk_widget_destroy (window);
9804 }
9805
9806 /*
9807  * GtkProgressBar
9808  */
9809
9810 typedef struct _ProgressData {
9811   GtkWidget *window;
9812   GtkWidget *pbar;
9813   GtkWidget *block_spin;
9814   GtkWidget *x_align_spin;
9815   GtkWidget *y_align_spin;
9816   GtkWidget *step_spin;
9817   GtkWidget *act_blocks_spin;
9818   GtkWidget *label;
9819   GtkWidget *omenu1;
9820   GtkWidget *elmenu;
9821   GtkWidget *omenu2;
9822   GtkWidget *entry;
9823   int timer;
9824 } ProgressData;
9825
9826 gint
9827 progress_timeout (gpointer data)
9828 {
9829   gdouble new_val;
9830   GtkAdjustment *adj;
9831
9832   adj = GTK_PROGRESS (data)->adjustment;
9833
9834   new_val = adj->value + 1;
9835   if (new_val > adj->upper)
9836     new_val = adj->lower;
9837
9838   gtk_progress_set_value (GTK_PROGRESS (data), new_val);
9839
9840   return TRUE;
9841 }
9842
9843 static void
9844 destroy_progress (GtkWidget     *widget,
9845                   ProgressData **pdata)
9846 {
9847   gtk_timeout_remove ((*pdata)->timer);
9848   (*pdata)->timer = 0;
9849   (*pdata)->window = NULL;
9850   g_free (*pdata);
9851   *pdata = NULL;
9852 }
9853
9854 static void
9855 progressbar_toggle_orientation (GtkWidget *widget, gpointer data)
9856 {
9857   ProgressData *pdata;
9858   gint i;
9859
9860   pdata = (ProgressData *) data;
9861
9862   if (!gtk_widget_get_mapped (widget))
9863     return;
9864
9865   i = gtk_option_menu_get_history (GTK_OPTION_MENU (widget));
9866
9867   gtk_progress_bar_set_orientation (GTK_PROGRESS_BAR (pdata->pbar),
9868                                     (GtkProgressBarOrientation) i);
9869 }
9870
9871 static void
9872 toggle_show_text (GtkWidget *widget, ProgressData *pdata)
9873 {
9874   gtk_progress_set_show_text (GTK_PROGRESS (pdata->pbar),
9875                               GTK_TOGGLE_BUTTON (widget)->active);
9876   gtk_widget_set_sensitive (pdata->entry, GTK_TOGGLE_BUTTON (widget)->active);
9877   gtk_widget_set_sensitive (pdata->x_align_spin,
9878                             GTK_TOGGLE_BUTTON (widget)->active);
9879   gtk_widget_set_sensitive (pdata->y_align_spin,
9880                             GTK_TOGGLE_BUTTON (widget)->active);
9881 }
9882
9883 static void
9884 progressbar_toggle_ellipsize (GtkWidget *widget,
9885                               gpointer   data)
9886 {
9887   ProgressData *pdata = data;
9888   if (gtk_widget_is_drawable (widget))
9889     {
9890       gint i = gtk_option_menu_get_history (GTK_OPTION_MENU (widget));
9891       gtk_progress_bar_set_ellipsize (GTK_PROGRESS_BAR (pdata->pbar), i);
9892     }
9893 }
9894
9895 static void
9896 progressbar_toggle_bar_style (GtkWidget *widget, gpointer data)
9897 {
9898   ProgressData *pdata;
9899   gint i;
9900
9901   pdata = (ProgressData *) data;
9902
9903   if (!gtk_widget_get_mapped (widget))
9904     return;
9905
9906   i = gtk_option_menu_get_history (GTK_OPTION_MENU (widget));
9907
9908   if (i == 1)
9909     gtk_widget_set_sensitive (pdata->block_spin, TRUE);
9910   else
9911     gtk_widget_set_sensitive (pdata->block_spin, FALSE);
9912   
9913   gtk_progress_bar_set_bar_style (GTK_PROGRESS_BAR (pdata->pbar),
9914                                   (GtkProgressBarStyle) i);
9915 }
9916
9917 static void
9918 progress_value_changed (GtkAdjustment *adj, ProgressData *pdata)
9919 {
9920   char buf[20];
9921
9922   if (GTK_PROGRESS (pdata->pbar)->activity_mode)
9923     sprintf (buf, "???");
9924   else
9925     sprintf (buf, "%.0f%%", 100 *
9926              gtk_progress_get_current_percentage (GTK_PROGRESS (pdata->pbar)));
9927   gtk_label_set_text (GTK_LABEL (pdata->label), buf);
9928 }
9929
9930 static void
9931 adjust_blocks (GtkAdjustment *adj, ProgressData *pdata)
9932 {
9933   gtk_progress_set_percentage (GTK_PROGRESS (pdata->pbar), 0);
9934   gtk_progress_bar_set_discrete_blocks (GTK_PROGRESS_BAR (pdata->pbar),
9935      gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (pdata->block_spin)));
9936 }
9937
9938 static void
9939 adjust_step (GtkAdjustment *adj, ProgressData *pdata)
9940 {
9941   gtk_progress_bar_set_activity_step (GTK_PROGRESS_BAR (pdata->pbar),
9942      gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (pdata->step_spin)));
9943 }
9944
9945 static void
9946 adjust_act_blocks (GtkAdjustment *adj, ProgressData *pdata)
9947 {
9948   gtk_progress_bar_set_activity_blocks (GTK_PROGRESS_BAR (pdata->pbar),
9949                gtk_spin_button_get_value_as_int 
9950                       (GTK_SPIN_BUTTON (pdata->act_blocks_spin)));
9951 }
9952
9953 static void
9954 adjust_align (GtkAdjustment *adj, ProgressData *pdata)
9955 {
9956   gtk_progress_set_text_alignment (GTK_PROGRESS (pdata->pbar),
9957          gtk_spin_button_get_value (GTK_SPIN_BUTTON (pdata->x_align_spin)),
9958          gtk_spin_button_get_value (GTK_SPIN_BUTTON (pdata->y_align_spin)));
9959 }
9960
9961 static void
9962 toggle_activity_mode (GtkWidget *widget, ProgressData *pdata)
9963 {
9964   gtk_progress_set_activity_mode (GTK_PROGRESS (pdata->pbar),
9965                                   GTK_TOGGLE_BUTTON (widget)->active);
9966   gtk_widget_set_sensitive (pdata->step_spin, 
9967                             GTK_TOGGLE_BUTTON (widget)->active);
9968   gtk_widget_set_sensitive (pdata->act_blocks_spin, 
9969                             GTK_TOGGLE_BUTTON (widget)->active);
9970 }
9971
9972 static void
9973 entry_changed (GtkWidget *widget, ProgressData *pdata)
9974 {
9975   gtk_progress_set_format_string (GTK_PROGRESS (pdata->pbar),
9976                           gtk_entry_get_text (GTK_ENTRY (pdata->entry)));
9977 }
9978
9979 void
9980 create_progress_bar (GtkWidget *widget)
9981 {
9982   GtkWidget *button;
9983   GtkWidget *vbox;
9984   GtkWidget *vbox2;
9985   GtkWidget *hbox;
9986   GtkWidget *check;
9987   GtkWidget *frame;
9988   GtkWidget *tab;
9989   GtkWidget *label;
9990   GtkWidget *align;
9991   GtkAdjustment *adj;
9992   static ProgressData *pdata = NULL;
9993
9994   static gchar *items1[] =
9995   {
9996     "Left-Right",
9997     "Right-Left",
9998     "Bottom-Top",
9999     "Top-Bottom"
10000   };
10001
10002   static gchar *items2[] =
10003   {
10004     "Continuous",
10005     "Discrete"
10006   };
10007
10008   static char *ellipsize_items[] = {
10009     "None",     // PANGO_ELLIPSIZE_NONE,
10010     "Start",    // PANGO_ELLIPSIZE_START,
10011     "Middle",   // PANGO_ELLIPSIZE_MIDDLE,
10012     "End",      // PANGO_ELLIPSIZE_END
10013   };
10014   
10015   if (!pdata)
10016     pdata = g_new0 (ProgressData, 1);
10017
10018   if (!pdata->window)
10019     {
10020       pdata->window = gtk_dialog_new ();
10021
10022       gtk_window_set_screen (GTK_WINDOW (pdata->window),
10023                              gtk_widget_get_screen (widget));
10024
10025       gtk_window_set_resizable (GTK_WINDOW (pdata->window), TRUE);
10026
10027       g_signal_connect (pdata->window, "destroy",
10028                         G_CALLBACK (destroy_progress),
10029                         &pdata);
10030
10031       pdata->timer = 0;
10032
10033       gtk_window_set_title (GTK_WINDOW (pdata->window), "GtkProgressBar");
10034       gtk_container_set_border_width (GTK_CONTAINER (pdata->window), 0);
10035
10036       vbox = gtk_vbox_new (FALSE, 5);
10037       gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
10038       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (pdata->window)->vbox), 
10039                           vbox, FALSE, TRUE, 0);
10040
10041       frame = gtk_frame_new ("Progress");
10042       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
10043
10044       vbox2 = gtk_vbox_new (FALSE, 5);
10045       gtk_container_add (GTK_CONTAINER (frame), vbox2);
10046
10047       align = gtk_alignment_new (0.5, 0.5, 0, 0);
10048       gtk_box_pack_start (GTK_BOX (vbox2), align, FALSE, FALSE, 5);
10049
10050       adj = (GtkAdjustment *) gtk_adjustment_new (0, 1, 300, 0, 0, 0);
10051       g_signal_connect (adj, "value_changed",
10052                         G_CALLBACK (progress_value_changed), pdata);
10053
10054       pdata->pbar = g_object_new (GTK_TYPE_PROGRESS_BAR,
10055                                     "adjustment", adj,
10056                                     "ellipsize", PANGO_ELLIPSIZE_MIDDLE,
10057                                     NULL);
10058       gtk_progress_set_format_string (GTK_PROGRESS (pdata->pbar),
10059                                       "%v from [%l,%u] (=%p%%)");
10060       gtk_container_add (GTK_CONTAINER (align), pdata->pbar);
10061       pdata->timer = gtk_timeout_add (100, progress_timeout, pdata->pbar);
10062
10063       align = gtk_alignment_new (0.5, 0.5, 0, 0);
10064       gtk_box_pack_start (GTK_BOX (vbox2), align, FALSE, FALSE, 5);
10065
10066       hbox = gtk_hbox_new (FALSE, 5);
10067       gtk_container_add (GTK_CONTAINER (align), hbox);
10068       label = gtk_label_new ("Label updated by user :"); 
10069       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
10070       pdata->label = gtk_label_new ("");
10071       gtk_box_pack_start (GTK_BOX (hbox), pdata->label, FALSE, TRUE, 0);
10072
10073       frame = gtk_frame_new ("Options");
10074       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
10075
10076       vbox2 = gtk_vbox_new (FALSE, 5);
10077       gtk_container_add (GTK_CONTAINER (frame), vbox2);
10078
10079       tab = gtk_table_new (7, 2, FALSE);
10080       gtk_box_pack_start (GTK_BOX (vbox2), tab, FALSE, TRUE, 0);
10081
10082       label = gtk_label_new ("Orientation :");
10083       gtk_table_attach (GTK_TABLE (tab), label, 0, 1, 0, 1,
10084                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
10085                         5, 5);
10086       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
10087
10088       pdata->omenu1 = build_option_menu (items1, 4, 0,
10089                                          progressbar_toggle_orientation,
10090                                          pdata);
10091       hbox = gtk_hbox_new (FALSE, 0);
10092       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 0, 1,
10093                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
10094                         5, 5);
10095       gtk_box_pack_start (GTK_BOX (hbox), pdata->omenu1, TRUE, TRUE, 0);
10096       
10097       check = gtk_check_button_new_with_label ("Show text");
10098       g_signal_connect (check, "clicked",
10099                         G_CALLBACK (toggle_show_text),
10100                         pdata);
10101       gtk_table_attach (GTK_TABLE (tab), check, 0, 1, 1, 2,
10102                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
10103                         5, 5);
10104
10105       hbox = gtk_hbox_new (FALSE, 0);
10106       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 1, 2,
10107                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
10108                         5, 5);
10109
10110       label = gtk_label_new ("Format : ");
10111       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
10112
10113       pdata->entry = gtk_entry_new ();
10114       g_signal_connect (pdata->entry, "changed",
10115                         G_CALLBACK (entry_changed),
10116                         pdata);
10117       gtk_box_pack_start (GTK_BOX (hbox), pdata->entry, TRUE, TRUE, 0);
10118       gtk_entry_set_text (GTK_ENTRY (pdata->entry), "%v from [%l,%u] (=%p%%)");
10119       gtk_widget_set_size_request (pdata->entry, 100, -1);
10120       gtk_widget_set_sensitive (pdata->entry, FALSE);
10121
10122       label = gtk_label_new ("Text align :");
10123       gtk_table_attach (GTK_TABLE (tab), label, 0, 1, 2, 3,
10124                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
10125                         5, 5);
10126       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
10127
10128       hbox = gtk_hbox_new (FALSE, 0);
10129       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 2, 3,
10130                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
10131                         5, 5);
10132
10133       label = gtk_label_new ("x :");
10134       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 5);
10135       
10136       adj = (GtkAdjustment *) gtk_adjustment_new (0.5, 0, 1, 0.1, 0.1, 0);
10137       pdata->x_align_spin = gtk_spin_button_new (adj, 0, 1);
10138       g_signal_connect (adj, "value_changed",
10139                         G_CALLBACK (adjust_align), pdata);
10140       gtk_box_pack_start (GTK_BOX (hbox), pdata->x_align_spin, FALSE, TRUE, 0);
10141       gtk_widget_set_sensitive (pdata->x_align_spin, FALSE);
10142
10143       label = gtk_label_new ("y :");
10144       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 5);
10145
10146       adj = (GtkAdjustment *) gtk_adjustment_new (0.5, 0, 1, 0.1, 0.1, 0);
10147       pdata->y_align_spin = gtk_spin_button_new (adj, 0, 1);
10148       g_signal_connect (adj, "value_changed",
10149                         G_CALLBACK (adjust_align), pdata);
10150       gtk_box_pack_start (GTK_BOX (hbox), pdata->y_align_spin, FALSE, TRUE, 0);
10151       gtk_widget_set_sensitive (pdata->y_align_spin, FALSE);
10152
10153       label = gtk_label_new ("Ellipsize text :");
10154       gtk_table_attach (GTK_TABLE (tab), label, 0, 1, 10, 11,
10155                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
10156                         5, 5);
10157       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
10158       pdata->elmenu = build_option_menu (ellipsize_items,
10159                                          sizeof (ellipsize_items) / sizeof (ellipsize_items[0]),
10160                                          2, // PANGO_ELLIPSIZE_MIDDLE
10161                                          progressbar_toggle_ellipsize,
10162                                          pdata);
10163       hbox = gtk_hbox_new (FALSE, 0);
10164       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 10, 11,
10165                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
10166                         5, 5);
10167       gtk_box_pack_start (GTK_BOX (hbox), pdata->elmenu, TRUE, TRUE, 0);
10168
10169       label = gtk_label_new ("Bar Style :");
10170       gtk_table_attach (GTK_TABLE (tab), label, 0, 1, 13, 14,
10171                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
10172                         5, 5);
10173       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
10174
10175       pdata->omenu2 = build_option_menu (items2, 2, 0,
10176                                          progressbar_toggle_bar_style,
10177                                          pdata);
10178       hbox = gtk_hbox_new (FALSE, 0);
10179       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 13, 14,
10180                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
10181                         5, 5);
10182       gtk_box_pack_start (GTK_BOX (hbox), pdata->omenu2, TRUE, TRUE, 0);
10183
10184       label = gtk_label_new ("Block count :");
10185       gtk_table_attach (GTK_TABLE (tab), label, 0, 1, 14, 15,
10186                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
10187                         5, 5);
10188       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
10189
10190       hbox = gtk_hbox_new (FALSE, 0);
10191       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 14, 15,
10192                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
10193                         5, 5);
10194       adj = (GtkAdjustment *) gtk_adjustment_new (10, 2, 20, 1, 5, 0);
10195       pdata->block_spin = gtk_spin_button_new (adj, 0, 0);
10196       g_signal_connect (adj, "value_changed",
10197                         G_CALLBACK (adjust_blocks), pdata);
10198       gtk_box_pack_start (GTK_BOX (hbox), pdata->block_spin, FALSE, TRUE, 0);
10199       gtk_widget_set_sensitive (pdata->block_spin, FALSE);
10200
10201       check = gtk_check_button_new_with_label ("Activity mode");
10202       g_signal_connect (check, "clicked",
10203                         G_CALLBACK (toggle_activity_mode), pdata);
10204       gtk_table_attach (GTK_TABLE (tab), check, 0, 1, 15, 16,
10205                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
10206                         5, 5);
10207
10208       hbox = gtk_hbox_new (FALSE, 0);
10209       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 15, 16,
10210                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
10211                         5, 5);
10212       label = gtk_label_new ("Step size : ");
10213       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
10214       adj = (GtkAdjustment *) gtk_adjustment_new (3, 1, 20, 1, 5, 0);
10215       pdata->step_spin = gtk_spin_button_new (adj, 0, 0);
10216       g_signal_connect (adj, "value_changed",
10217                         G_CALLBACK (adjust_step), pdata);
10218       gtk_box_pack_start (GTK_BOX (hbox), pdata->step_spin, FALSE, TRUE, 0);
10219       gtk_widget_set_sensitive (pdata->step_spin, FALSE);
10220
10221       hbox = gtk_hbox_new (FALSE, 0);
10222       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 16, 17,
10223                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
10224                         5, 5);
10225       label = gtk_label_new ("Blocks :     ");
10226       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
10227       adj = (GtkAdjustment *) gtk_adjustment_new (5, 2, 10, 1, 5, 0);
10228       pdata->act_blocks_spin = gtk_spin_button_new (adj, 0, 0);
10229       g_signal_connect (adj, "value_changed",
10230                         G_CALLBACK (adjust_act_blocks), pdata);
10231       gtk_box_pack_start (GTK_BOX (hbox), pdata->act_blocks_spin, FALSE, TRUE,
10232                           0);
10233       gtk_widget_set_sensitive (pdata->act_blocks_spin, FALSE);
10234
10235       button = gtk_button_new_with_label ("close");
10236       g_signal_connect_swapped (button, "clicked",
10237                                 G_CALLBACK (gtk_widget_destroy),
10238                                 pdata->window);
10239       gtk_widget_set_can_default (button, TRUE);
10240       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (pdata->window)->action_area), 
10241                           button, TRUE, TRUE, 0);
10242       gtk_widget_grab_default (button);
10243     }
10244
10245   if (!gtk_widget_get_visible (pdata->window))
10246     gtk_widget_show_all (pdata->window);
10247   else
10248     gtk_widget_destroy (pdata->window);
10249 }
10250
10251 /*
10252  * Properties
10253  */
10254
10255 typedef struct {
10256   int x;
10257   int y;
10258   gboolean found;
10259   gboolean first;
10260   GtkWidget *res_widget;
10261 } FindWidgetData;
10262
10263 static void
10264 find_widget (GtkWidget *widget, FindWidgetData *data)
10265 {
10266   GtkAllocation new_allocation;
10267   gint x_offset = 0;
10268   gint y_offset = 0;
10269
10270   new_allocation = widget->allocation;
10271
10272   if (data->found || !gtk_widget_get_mapped (widget))
10273     return;
10274
10275   /* Note that in the following code, we only count the
10276    * position as being inside a WINDOW widget if it is inside
10277    * widget->window; points that are outside of widget->window
10278    * but within the allocation are not counted. This is consistent
10279    * with the way we highlight drag targets.
10280    */
10281   if (gtk_widget_get_has_window (widget))
10282     {
10283       new_allocation.x = 0;
10284       new_allocation.y = 0;
10285     }
10286   
10287   if (widget->parent && !data->first)
10288     {
10289       GdkWindow *window = widget->window;
10290       while (window != widget->parent->window)
10291         {
10292           gint tx, ty, twidth, theight;
10293           gdk_drawable_get_size (window, &twidth, &theight);
10294
10295           if (new_allocation.x < 0)
10296             {
10297               new_allocation.width += new_allocation.x;
10298               new_allocation.x = 0;
10299             }
10300           if (new_allocation.y < 0)
10301             {
10302               new_allocation.height += new_allocation.y;
10303               new_allocation.y = 0;
10304             }
10305           if (new_allocation.x + new_allocation.width > twidth)
10306             new_allocation.width = twidth - new_allocation.x;
10307           if (new_allocation.y + new_allocation.height > theight)
10308             new_allocation.height = theight - new_allocation.y;
10309
10310           gdk_window_get_position (window, &tx, &ty);
10311           new_allocation.x += tx;
10312           x_offset += tx;
10313           new_allocation.y += ty;
10314           y_offset += ty;
10315           
10316           window = gdk_window_get_parent (window);
10317         }
10318     }
10319
10320   if ((data->x >= new_allocation.x) && (data->y >= new_allocation.y) &&
10321       (data->x < new_allocation.x + new_allocation.width) && 
10322       (data->y < new_allocation.y + new_allocation.height))
10323     {
10324       /* First, check if the drag is in a valid drop site in
10325        * one of our children 
10326        */
10327       if (GTK_IS_CONTAINER (widget))
10328         {
10329           FindWidgetData new_data = *data;
10330           
10331           new_data.x -= x_offset;
10332           new_data.y -= y_offset;
10333           new_data.found = FALSE;
10334           new_data.first = FALSE;
10335           
10336           gtk_container_forall (GTK_CONTAINER (widget),
10337                                 (GtkCallback)find_widget,
10338                                 &new_data);
10339           
10340           data->found = new_data.found;
10341           if (data->found)
10342             data->res_widget = new_data.res_widget;
10343         }
10344
10345       /* If not, and this widget is registered as a drop site, check to
10346        * emit "drag_motion" to check if we are actually in
10347        * a drop site.
10348        */
10349       if (!data->found)
10350         {
10351           data->found = TRUE;
10352           data->res_widget = widget;
10353         }
10354     }
10355 }
10356
10357 static GtkWidget *
10358 find_widget_at_pointer (GdkDisplay *display)
10359 {
10360   GtkWidget *widget = NULL;
10361   GdkWindow *pointer_window;
10362   gint x, y;
10363   FindWidgetData data;
10364  
10365  pointer_window = gdk_display_get_window_at_pointer (display, NULL, NULL);
10366  
10367  if (pointer_window)
10368    {
10369      gpointer widget_ptr;
10370
10371      gdk_window_get_user_data (pointer_window, &widget_ptr);
10372      widget = widget_ptr;
10373    }
10374
10375  if (widget)
10376    {
10377      gdk_window_get_pointer (widget->window,
10378                              &x, &y, NULL);
10379      
10380      data.x = x;
10381      data.y = y;
10382      data.found = FALSE;
10383      data.first = TRUE;
10384
10385      find_widget (widget, &data);
10386      if (data.found)
10387        return data.res_widget;
10388      return widget;
10389    }
10390  return NULL;
10391 }
10392
10393 struct PropertiesData {
10394   GtkWidget **window;
10395   GdkCursor *cursor;
10396   gboolean in_query;
10397   gint handler;
10398 };
10399
10400 static void
10401 destroy_properties (GtkWidget             *widget,
10402                     struct PropertiesData *data)
10403 {
10404   if (data->window)
10405     {
10406       *data->window = NULL;
10407       data->window = NULL;
10408     }
10409
10410   if (data->cursor)
10411     {
10412       gdk_cursor_unref (data->cursor);
10413       data->cursor = NULL;
10414     }
10415
10416   if (data->handler)
10417     {
10418       g_signal_handler_disconnect (widget, data->handler);
10419       data->handler = 0;
10420     }
10421
10422   g_free (data);
10423 }
10424
10425 static gint
10426 property_query_event (GtkWidget        *widget,
10427                       GdkEvent         *event,
10428                       struct PropertiesData *data)
10429 {
10430   GtkWidget *res_widget = NULL;
10431
10432   if (!data->in_query)
10433     return FALSE;
10434   
10435   if (event->type == GDK_BUTTON_RELEASE)
10436     {
10437       gtk_grab_remove (widget);
10438       gdk_display_pointer_ungrab (gtk_widget_get_display (widget),
10439                                   GDK_CURRENT_TIME);
10440       
10441       res_widget = find_widget_at_pointer (gtk_widget_get_display (widget));
10442       if (res_widget)
10443         {
10444           g_object_set_data (G_OBJECT (res_widget), "prop-editor-screen",
10445                              gtk_widget_get_screen (widget));
10446           create_prop_editor (G_OBJECT (res_widget), 0);
10447         }
10448
10449       data->in_query = FALSE;
10450     }
10451   return FALSE;
10452 }
10453
10454
10455 static void
10456 query_properties (GtkButton *button,
10457                   struct PropertiesData *data)
10458 {
10459   gint failure;
10460
10461   g_signal_connect (button, "event",
10462                     G_CALLBACK (property_query_event), data);
10463
10464
10465   if (!data->cursor)
10466     data->cursor = gdk_cursor_new_for_display (gtk_widget_get_display (GTK_WIDGET (button)),
10467                                                GDK_TARGET);
10468   
10469   failure = gdk_pointer_grab (GTK_WIDGET (button)->window,
10470                               TRUE,
10471                               GDK_BUTTON_RELEASE_MASK,
10472                               NULL,
10473                               data->cursor,
10474                               GDK_CURRENT_TIME);
10475
10476   gtk_grab_add (GTK_WIDGET (button));
10477
10478   data->in_query = TRUE;
10479 }
10480
10481 static void
10482 create_properties (GtkWidget *widget)
10483 {
10484   static GtkWidget *window = NULL;
10485   GtkWidget *button;
10486   GtkWidget *vbox;
10487   GtkWidget *label;
10488   struct PropertiesData *data;
10489
10490   data = g_new (struct PropertiesData, 1);
10491   data->window = &window;
10492   data->in_query = FALSE;
10493   data->cursor = NULL;
10494   data->handler = 0;
10495
10496   if (!window)
10497     {
10498       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
10499
10500       gtk_window_set_screen (GTK_WINDOW (window),
10501                              gtk_widget_get_screen (widget));      
10502
10503       data->handler = g_signal_connect (window, "destroy",
10504                                         G_CALLBACK (destroy_properties),
10505                                         data);
10506
10507       gtk_window_set_title (GTK_WINDOW (window), "test properties");
10508       gtk_container_set_border_width (GTK_CONTAINER (window), 10);
10509
10510       vbox = gtk_vbox_new (FALSE, 1);
10511       gtk_container_add (GTK_CONTAINER (window), vbox);
10512             
10513       label = gtk_label_new ("This is just a dumb test to test properties.\nIf you need a generic module, get GLE.");
10514       gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
10515       
10516       button = gtk_button_new_with_label ("Query properties");
10517       gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
10518       g_signal_connect (button, "clicked",
10519                         G_CALLBACK (query_properties),
10520                         data);
10521     }
10522
10523   if (!gtk_widget_get_visible (window))
10524     gtk_widget_show_all (window);
10525   else
10526     gtk_widget_destroy (window);
10527   
10528 }
10529
10530 struct SnapshotData {
10531   GtkWidget *toplevel_button;
10532   GtkWidget **window;
10533   GdkCursor *cursor;
10534   gboolean in_query;
10535   gboolean is_toplevel;
10536   gint handler;
10537 };
10538
10539 static void
10540 destroy_snapshot_data (GtkWidget             *widget,
10541                        struct SnapshotData *data)
10542 {
10543   if (*data->window)
10544     *data->window = NULL;
10545   
10546   if (data->cursor)
10547     {
10548       gdk_cursor_unref (data->cursor);
10549       data->cursor = NULL;
10550     }
10551
10552   if (data->handler)
10553     {
10554       g_signal_handler_disconnect (widget, data->handler);
10555       data->handler = 0;
10556     }
10557
10558   g_free (data);
10559 }
10560
10561 static gint
10562 snapshot_widget_event (GtkWidget               *widget,
10563                        GdkEvent        *event,
10564                        struct SnapshotData *data)
10565 {
10566   GtkWidget *res_widget = NULL;
10567
10568   if (!data->in_query)
10569     return FALSE;
10570   
10571   if (event->type == GDK_BUTTON_RELEASE)
10572     {
10573       gtk_grab_remove (widget);
10574       gdk_display_pointer_ungrab (gtk_widget_get_display (widget),
10575                                   GDK_CURRENT_TIME);
10576       
10577       res_widget = find_widget_at_pointer (gtk_widget_get_display (widget));
10578       if (data->is_toplevel && res_widget)
10579         res_widget = gtk_widget_get_toplevel (res_widget);
10580       if (res_widget)
10581         {
10582           GdkPixmap *pixmap;
10583           GtkWidget *window, *image;
10584
10585           window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
10586           pixmap = gtk_widget_get_snapshot (res_widget, NULL);
10587           gtk_widget_realize (window);
10588           if (gdk_drawable_get_depth (window->window) != gdk_drawable_get_depth (pixmap))
10589             {
10590               /* this branch is needed to convert ARGB -> RGB */
10591               int width, height;
10592               GdkPixbuf *pixbuf;
10593               gdk_drawable_get_size (pixmap, &width, &height);
10594               pixbuf = gdk_pixbuf_get_from_drawable (NULL, pixmap,
10595                                                      gtk_widget_get_colormap (res_widget),
10596                                                      0, 0,
10597                                                      0, 0,
10598                                                      width, height);
10599               image = gtk_image_new_from_pixbuf (pixbuf);
10600               g_object_unref (pixbuf);
10601             }
10602           else
10603             image = gtk_image_new_from_pixmap (pixmap, NULL);
10604           gtk_container_add (GTK_CONTAINER (window), image);
10605           g_object_unref (pixmap);
10606           gtk_widget_show_all (window);
10607         }
10608
10609       data->in_query = FALSE;
10610     }
10611   return FALSE;
10612 }
10613
10614
10615 static void
10616 snapshot_widget (GtkButton *button,
10617                  struct SnapshotData *data)
10618 {
10619   gint failure;
10620
10621   g_signal_connect (button, "event",
10622                     G_CALLBACK (snapshot_widget_event), data);
10623
10624   data->is_toplevel = GTK_WIDGET (button) == data->toplevel_button;
10625   
10626   if (!data->cursor)
10627     data->cursor = gdk_cursor_new_for_display (gtk_widget_get_display (GTK_WIDGET (button)),
10628                                                GDK_TARGET);
10629   
10630   failure = gdk_pointer_grab (GTK_WIDGET (button)->window,
10631                               TRUE,
10632                               GDK_BUTTON_RELEASE_MASK,
10633                               NULL,
10634                               data->cursor,
10635                               GDK_CURRENT_TIME);
10636
10637   gtk_grab_add (GTK_WIDGET (button));
10638
10639   data->in_query = TRUE;
10640 }
10641
10642 static void
10643 create_snapshot (GtkWidget *widget)
10644 {
10645   static GtkWidget *window = NULL;
10646   GtkWidget *button;
10647   GtkWidget *vbox;
10648   struct SnapshotData *data;
10649
10650   data = g_new (struct SnapshotData, 1);
10651   data->window = &window;
10652   data->in_query = FALSE;
10653   data->cursor = NULL;
10654   data->handler = 0;
10655
10656   if (!window)
10657     {
10658       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
10659
10660       gtk_window_set_screen (GTK_WINDOW (window),
10661                              gtk_widget_get_screen (widget));      
10662
10663       data->handler = g_signal_connect (window, "destroy",
10664                                         G_CALLBACK (destroy_snapshot_data),
10665                                         data);
10666
10667       gtk_window_set_title (GTK_WINDOW (window), "test snapshot");
10668       gtk_container_set_border_width (GTK_CONTAINER (window), 10);
10669
10670       vbox = gtk_vbox_new (FALSE, 1);
10671       gtk_container_add (GTK_CONTAINER (window), vbox);
10672             
10673       button = gtk_button_new_with_label ("Snapshot widget");
10674       gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
10675       g_signal_connect (button, "clicked",
10676                         G_CALLBACK (snapshot_widget),
10677                         data);
10678       
10679       button = gtk_button_new_with_label ("Snapshot toplevel");
10680       data->toplevel_button = button;
10681       gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
10682       g_signal_connect (button, "clicked",
10683                         G_CALLBACK (snapshot_widget),
10684                         data);
10685     }
10686
10687   if (!gtk_widget_get_visible (window))
10688     gtk_widget_show_all (window);
10689   else
10690     gtk_widget_destroy (window);
10691   
10692 }
10693
10694 /*
10695  * Selection Test
10696  */
10697
10698 void
10699 selection_test_received (GtkWidget *list, GtkSelectionData *data)
10700 {
10701   GdkAtom *atoms;
10702   GtkWidget *list_item;
10703   GList *item_list;
10704   int i, l;
10705
10706   if (data->length < 0)
10707     {
10708       g_print ("Selection retrieval failed\n");
10709       return;
10710     }
10711   if (data->type != GDK_SELECTION_TYPE_ATOM)
10712     {
10713       g_print ("Selection \"TARGETS\" was not returned as atoms!\n");
10714       return;
10715     }
10716
10717   /* Clear out any current list items */
10718
10719   gtk_list_clear_items (GTK_LIST(list), 0, -1);
10720
10721   /* Add new items to list */
10722
10723   atoms = (GdkAtom *)data->data;
10724
10725   item_list = NULL;
10726   l = data->length / sizeof (GdkAtom);
10727   for (i = 0; i < l; i++)
10728     {
10729       char *name;
10730       name = gdk_atom_name (atoms[i]);
10731       if (name != NULL)
10732         {
10733           list_item = gtk_list_item_new_with_label (name);
10734           g_free (name);
10735         }
10736       else
10737         list_item = gtk_list_item_new_with_label ("(bad atom)");
10738
10739       gtk_widget_show (list_item);
10740       item_list = g_list_append (item_list, list_item);
10741     }
10742
10743   gtk_list_append_items (GTK_LIST (list), item_list);
10744
10745   return;
10746 }
10747
10748 void
10749 selection_test_get_targets (GtkWidget *widget, GtkWidget *list)
10750 {
10751   static GdkAtom targets_atom = GDK_NONE;
10752
10753   if (targets_atom == GDK_NONE)
10754     targets_atom = gdk_atom_intern ("TARGETS", FALSE);
10755
10756   gtk_selection_convert (list, GDK_SELECTION_PRIMARY, targets_atom,
10757                          GDK_CURRENT_TIME);
10758 }
10759
10760 void
10761 create_selection_test (GtkWidget *widget)
10762 {
10763   static GtkWidget *window = NULL;
10764   GtkWidget *button;
10765   GtkWidget *vbox;
10766   GtkWidget *scrolled_win;
10767   GtkWidget *list;
10768   GtkWidget *label;
10769
10770   if (!window)
10771     {
10772       window = gtk_dialog_new ();
10773       
10774       gtk_window_set_screen (GTK_WINDOW (window),
10775                              gtk_widget_get_screen (widget));
10776
10777       g_signal_connect (window, "destroy",
10778                         G_CALLBACK (gtk_widget_destroyed),
10779                         &window);
10780
10781       gtk_window_set_title (GTK_WINDOW (window), "Selection Test");
10782       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
10783
10784       /* Create the list */
10785
10786       vbox = gtk_vbox_new (FALSE, 5);
10787       gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
10788       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), vbox,
10789                           TRUE, TRUE, 0);
10790
10791       label = gtk_label_new ("Gets available targets for current selection");
10792       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
10793
10794       scrolled_win = gtk_scrolled_window_new (NULL, NULL);
10795       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
10796                                       GTK_POLICY_AUTOMATIC, 
10797                                       GTK_POLICY_AUTOMATIC);
10798       gtk_box_pack_start (GTK_BOX (vbox), scrolled_win, TRUE, TRUE, 0);
10799       gtk_widget_set_size_request (scrolled_win, 100, 200);
10800
10801       list = gtk_list_new ();
10802       gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_win), list);
10803
10804       g_signal_connect (list, "selection_received",
10805                         G_CALLBACK (selection_test_received), NULL);
10806
10807       /* .. And create some buttons */
10808       button = gtk_button_new_with_label ("Get Targets");
10809       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area),
10810                           button, TRUE, TRUE, 0);
10811
10812       g_signal_connect (button, "clicked",
10813                         G_CALLBACK (selection_test_get_targets), list);
10814
10815       button = gtk_button_new_with_label ("Quit");
10816       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area),
10817                           button, TRUE, TRUE, 0);
10818
10819       g_signal_connect_swapped (button, "clicked",
10820                                 G_CALLBACK (gtk_widget_destroy),
10821                                 window);
10822     }
10823
10824   if (!gtk_widget_get_visible (window))
10825     gtk_widget_show_all (window);
10826   else
10827     gtk_widget_destroy (window);
10828 }
10829
10830 /*
10831  * Gamma Curve
10832  */
10833
10834 void
10835 create_gamma_curve (GtkWidget *widget)
10836 {
10837   static GtkWidget *window = NULL, *curve;
10838   static int count = 0;
10839   gfloat vec[256];
10840   gint max;
10841   gint i;
10842   
10843   if (!window)
10844     {
10845       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
10846       gtk_window_set_screen (GTK_WINDOW (window),
10847                              gtk_widget_get_screen (widget));
10848
10849       gtk_window_set_title (GTK_WINDOW (window), "test");
10850       gtk_container_set_border_width (GTK_CONTAINER (window), 10);
10851
10852       g_signal_connect (window, "destroy",
10853                         G_CALLBACK(gtk_widget_destroyed),
10854                         &window);
10855
10856       curve = gtk_gamma_curve_new ();
10857       gtk_container_add (GTK_CONTAINER (window), curve);
10858       gtk_widget_show (curve);
10859     }
10860
10861   max = 127 + (count % 2)*128;
10862   gtk_curve_set_range (GTK_CURVE (GTK_GAMMA_CURVE (curve)->curve),
10863                        0, max, 0, max);
10864   for (i = 0; i < max; ++i)
10865     vec[i] = (127 / sqrt (max)) * sqrt (i);
10866   gtk_curve_set_vector (GTK_CURVE (GTK_GAMMA_CURVE (curve)->curve),
10867                         max, vec);
10868
10869   if (!gtk_widget_get_visible (window))
10870     gtk_widget_show (window);
10871   else if (count % 4 == 3)
10872     {
10873       gtk_widget_destroy (window);
10874       window = NULL;
10875     }
10876
10877   ++count;
10878 }
10879
10880 /*
10881  * Test scrolling
10882  */
10883
10884 static int scroll_test_pos = 0.0;
10885
10886 static gint
10887 scroll_test_expose (GtkWidget *widget, GdkEventExpose *event,
10888                     GtkAdjustment *adj)
10889 {
10890   gint i,j;
10891   gint imin, imax, jmin, jmax;
10892   
10893   imin = (event->area.x) / 10;
10894   imax = (event->area.x + event->area.width + 9) / 10;
10895
10896   jmin = ((int)adj->value + event->area.y) / 10;
10897   jmax = ((int)adj->value + event->area.y + event->area.height + 9) / 10;
10898
10899   gdk_window_clear_area (widget->window,
10900                          event->area.x, event->area.y,
10901                          event->area.width, event->area.height);
10902
10903   for (i=imin; i<imax; i++)
10904     for (j=jmin; j<jmax; j++)
10905       if ((i+j) % 2)
10906         gdk_draw_rectangle (widget->window, 
10907                             widget->style->black_gc,
10908                             TRUE,
10909                             10*i, 10*j - (int)adj->value, 1+i%10, 1+j%10);
10910
10911   return TRUE;
10912 }
10913
10914 static gint
10915 scroll_test_scroll (GtkWidget *widget, GdkEventScroll *event,
10916                     GtkAdjustment *adj)
10917 {
10918   gdouble new_value = adj->value + ((event->direction == GDK_SCROLL_UP) ?
10919                                     -adj->page_increment / 2:
10920                                     adj->page_increment / 2);
10921   new_value = CLAMP (new_value, adj->lower, adj->upper - adj->page_size);
10922   gtk_adjustment_set_value (adj, new_value);  
10923   
10924   return TRUE;
10925 }
10926
10927 static void
10928 scroll_test_configure (GtkWidget *widget, GdkEventConfigure *event,
10929                        GtkAdjustment *adj)
10930 {
10931   adj->page_increment = 0.9 * widget->allocation.height;
10932   adj->page_size = widget->allocation.height;
10933
10934   g_signal_emit_by_name (adj, "changed");
10935 }
10936
10937 static void
10938 scroll_test_adjustment_changed (GtkAdjustment *adj, GtkWidget *widget)
10939 {
10940   /* gint source_min = (int)adj->value - scroll_test_pos; */
10941   gint dy;
10942
10943   dy = scroll_test_pos - (int)adj->value;
10944   scroll_test_pos = adj->value;
10945
10946   if (!gtk_widget_is_drawable (widget))
10947     return;
10948   gdk_window_scroll (widget->window, 0, dy);
10949   gdk_window_process_updates (widget->window, FALSE);
10950 }
10951
10952
10953 void
10954 create_scroll_test (GtkWidget *widget)
10955 {
10956   static GtkWidget *window = NULL;
10957   GtkWidget *hbox;
10958   GtkWidget *drawing_area;
10959   GtkWidget *scrollbar;
10960   GtkWidget *button;
10961   GtkAdjustment *adj;
10962   GdkGeometry geometry;
10963   GdkWindowHints geometry_mask;
10964
10965   if (!window)
10966     {
10967       window = gtk_dialog_new ();
10968
10969       gtk_window_set_screen (GTK_WINDOW (window),
10970                              gtk_widget_get_screen (widget));
10971
10972       g_signal_connect (window, "destroy",
10973                         G_CALLBACK (gtk_widget_destroyed),
10974                         &window);
10975
10976       gtk_window_set_title (GTK_WINDOW (window), "Scroll Test");
10977       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
10978
10979       hbox = gtk_hbox_new (FALSE, 0);
10980       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), hbox,
10981                           TRUE, TRUE, 0);
10982       gtk_widget_show (hbox);
10983
10984       drawing_area = gtk_drawing_area_new ();
10985       gtk_widget_set_size_request (drawing_area, 200, 200);
10986       gtk_box_pack_start (GTK_BOX (hbox), drawing_area, TRUE, TRUE, 0);
10987       gtk_widget_show (drawing_area);
10988
10989       gtk_widget_set_events (drawing_area, GDK_EXPOSURE_MASK | GDK_SCROLL_MASK);
10990
10991       adj = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 1000.0, 1.0, 180.0, 200.0));
10992       scroll_test_pos = 0.0;
10993
10994       scrollbar = gtk_vscrollbar_new (adj);
10995       gtk_box_pack_start (GTK_BOX (hbox), scrollbar, FALSE, FALSE, 0);
10996       gtk_widget_show (scrollbar);
10997
10998       g_signal_connect (drawing_area, "expose_event",
10999                         G_CALLBACK (scroll_test_expose), adj);
11000       g_signal_connect (drawing_area, "configure_event",
11001                         G_CALLBACK (scroll_test_configure), adj);
11002       g_signal_connect (drawing_area, "scroll_event",
11003                         G_CALLBACK (scroll_test_scroll), adj);
11004       
11005       g_signal_connect (adj, "value_changed",
11006                         G_CALLBACK (scroll_test_adjustment_changed),
11007                         drawing_area);
11008       
11009       /* .. And create some buttons */
11010
11011       button = gtk_button_new_with_label ("Quit");
11012       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area),
11013                           button, TRUE, TRUE, 0);
11014
11015       g_signal_connect_swapped (button, "clicked",
11016                                 G_CALLBACK (gtk_widget_destroy),
11017                                 window);
11018       gtk_widget_show (button);
11019
11020       /* Set up gridded geometry */
11021
11022       geometry_mask = GDK_HINT_MIN_SIZE | 
11023                        GDK_HINT_BASE_SIZE | 
11024                        GDK_HINT_RESIZE_INC;
11025
11026       geometry.min_width = 20;
11027       geometry.min_height = 20;
11028       geometry.base_width = 0;
11029       geometry.base_height = 0;
11030       geometry.width_inc = 10;
11031       geometry.height_inc = 10;
11032       
11033       gtk_window_set_geometry_hints (GTK_WINDOW (window),
11034                                drawing_area, &geometry, geometry_mask);
11035     }
11036
11037   if (!gtk_widget_get_visible (window))
11038     gtk_widget_show (window);
11039   else
11040     gtk_widget_destroy (window);
11041 }
11042
11043 /*
11044  * Timeout Test
11045  */
11046
11047 static int timer = 0;
11048
11049 gint
11050 timeout_test (GtkWidget *label)
11051 {
11052   static int count = 0;
11053   static char buffer[32];
11054
11055   sprintf (buffer, "count: %d", ++count);
11056   gtk_label_set_text (GTK_LABEL (label), buffer);
11057
11058   return TRUE;
11059 }
11060
11061 void
11062 start_timeout_test (GtkWidget *widget,
11063                     GtkWidget *label)
11064 {
11065   if (!timer)
11066     {
11067       timer = gtk_timeout_add (100, (GtkFunction) timeout_test, label);
11068     }
11069 }
11070
11071 void
11072 stop_timeout_test (GtkWidget *widget,
11073                    gpointer   data)
11074 {
11075   if (timer)
11076     {
11077       gtk_timeout_remove (timer);
11078       timer = 0;
11079     }
11080 }
11081
11082 void
11083 destroy_timeout_test (GtkWidget  *widget,
11084                       GtkWidget **window)
11085 {
11086   stop_timeout_test (NULL, NULL);
11087
11088   *window = NULL;
11089 }
11090
11091 void
11092 create_timeout_test (GtkWidget *widget)
11093 {
11094   static GtkWidget *window = NULL;
11095   GtkWidget *button;
11096   GtkWidget *label;
11097
11098   if (!window)
11099     {
11100       window = gtk_dialog_new ();
11101
11102       gtk_window_set_screen (GTK_WINDOW (window),
11103                              gtk_widget_get_screen (widget));
11104
11105       g_signal_connect (window, "destroy",
11106                         G_CALLBACK (destroy_timeout_test),
11107                         &window);
11108
11109       gtk_window_set_title (GTK_WINDOW (window), "Timeout Test");
11110       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
11111
11112       label = gtk_label_new ("count: 0");
11113       gtk_misc_set_padding (GTK_MISC (label), 10, 10);
11114       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
11115                           label, TRUE, TRUE, 0);
11116       gtk_widget_show (label);
11117
11118       button = gtk_button_new_with_label ("close");
11119       g_signal_connect_swapped (button, "clicked",
11120                                 G_CALLBACK (gtk_widget_destroy),
11121                                 window);
11122       gtk_widget_set_can_default (button, TRUE);
11123       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
11124                           button, TRUE, TRUE, 0);
11125       gtk_widget_grab_default (button);
11126       gtk_widget_show (button);
11127
11128       button = gtk_button_new_with_label ("start");
11129       g_signal_connect (button, "clicked",
11130                         G_CALLBACK(start_timeout_test),
11131                         label);
11132       gtk_widget_set_can_default (button, TRUE);
11133       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
11134                           button, TRUE, TRUE, 0);
11135       gtk_widget_show (button);
11136
11137       button = gtk_button_new_with_label ("stop");
11138       g_signal_connect (button, "clicked",
11139                         G_CALLBACK (stop_timeout_test),
11140                         NULL);
11141       gtk_widget_set_can_default (button, TRUE);
11142       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
11143                           button, TRUE, TRUE, 0);
11144       gtk_widget_show (button);
11145     }
11146
11147   if (!gtk_widget_get_visible (window))
11148     gtk_widget_show (window);
11149   else
11150     gtk_widget_destroy (window);
11151 }
11152
11153 /*
11154  * Idle Test
11155  */
11156
11157 static int idle_id = 0;
11158
11159 static gint
11160 idle_test (GtkWidget *label)
11161 {
11162   static int count = 0;
11163   static char buffer[32];
11164
11165   sprintf (buffer, "count: %d", ++count);
11166   gtk_label_set_text (GTK_LABEL (label), buffer);
11167
11168   return TRUE;
11169 }
11170
11171 static void
11172 start_idle_test (GtkWidget *widget,
11173                  GtkWidget *label)
11174 {
11175   if (!idle_id)
11176     {
11177       idle_id = gtk_idle_add ((GtkFunction) idle_test, label);
11178     }
11179 }
11180
11181 static void
11182 stop_idle_test (GtkWidget *widget,
11183                 gpointer   data)
11184 {
11185   if (idle_id)
11186     {
11187       gtk_idle_remove (idle_id);
11188       idle_id = 0;
11189     }
11190 }
11191
11192 static void
11193 destroy_idle_test (GtkWidget  *widget,
11194                    GtkWidget **window)
11195 {
11196   stop_idle_test (NULL, NULL);
11197
11198   *window = NULL;
11199 }
11200
11201 static void
11202 toggle_idle_container (GObject *button,
11203                        GtkContainer *container)
11204 {
11205   gtk_container_set_resize_mode (container, GPOINTER_TO_INT (g_object_get_data (button, "user_data")));
11206 }
11207
11208 static void
11209 create_idle_test (GtkWidget *widget)
11210 {
11211   static GtkWidget *window = NULL;
11212   GtkWidget *button;
11213   GtkWidget *label;
11214   GtkWidget *container;
11215
11216   if (!window)
11217     {
11218       GtkWidget *button2;
11219       GtkWidget *frame;
11220       GtkWidget *box;
11221
11222       window = gtk_dialog_new ();
11223
11224       gtk_window_set_screen (GTK_WINDOW (window),
11225                              gtk_widget_get_screen (widget));
11226
11227       g_signal_connect (window, "destroy",
11228                         G_CALLBACK (destroy_idle_test),
11229                         &window);
11230
11231       gtk_window_set_title (GTK_WINDOW (window), "Idle Test");
11232       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
11233
11234       label = gtk_label_new ("count: 0");
11235       gtk_misc_set_padding (GTK_MISC (label), 10, 10);
11236       gtk_widget_show (label);
11237       
11238       container =
11239         g_object_new (GTK_TYPE_HBOX,
11240                         "visible", TRUE,
11241                         /* "GtkContainer::child", g_object_new (GTK_TYPE_HBOX,
11242                          * "GtkWidget::visible", TRUE,
11243                          */
11244                          "child", label,
11245                         /* NULL), */
11246                         NULL);
11247       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
11248                           container, TRUE, TRUE, 0);
11249
11250       frame =
11251         g_object_new (GTK_TYPE_FRAME,
11252                         "border_width", 5,
11253                         "label", "Label Container",
11254                         "visible", TRUE,
11255                         "parent", GTK_DIALOG (window)->vbox,
11256                         NULL);
11257       box =
11258         g_object_new (GTK_TYPE_VBOX,
11259                         "visible", TRUE,
11260                         "parent", frame,
11261                         NULL);
11262       button =
11263         g_object_connect (g_object_new (GTK_TYPE_RADIO_BUTTON,
11264                                           "label", "Resize-Parent",
11265                                           "user_data", (void*)GTK_RESIZE_PARENT,
11266                                           "visible", TRUE,
11267                                           "parent", box,
11268                                           NULL),
11269                           "signal::clicked", toggle_idle_container, container,
11270                           NULL);
11271       button = g_object_new (GTK_TYPE_RADIO_BUTTON,
11272                                "label", "Resize-Queue",
11273                                "user_data", (void*)GTK_RESIZE_QUEUE,
11274                                "group", button,
11275                                "visible", TRUE,
11276                                "parent", box,
11277                                NULL);
11278       g_object_connect (button,
11279                         "signal::clicked", toggle_idle_container, container,
11280                         NULL);
11281       button2 = g_object_new (GTK_TYPE_RADIO_BUTTON,
11282                                 "label", "Resize-Immediate",
11283                                 "user_data", (void*)GTK_RESIZE_IMMEDIATE,
11284                                 NULL);
11285       g_object_connect (button2,
11286                         "signal::clicked", toggle_idle_container, container,
11287                         NULL);
11288       g_object_set (button2,
11289                     "group", button,
11290                     "visible", TRUE,
11291                     "parent", box,
11292                     NULL);
11293
11294       button = gtk_button_new_with_label ("close");
11295       g_signal_connect_swapped (button, "clicked",
11296                                 G_CALLBACK (gtk_widget_destroy),
11297                                 window);
11298       gtk_widget_set_can_default (button, TRUE);
11299       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
11300                           button, TRUE, TRUE, 0);
11301       gtk_widget_grab_default (button);
11302       gtk_widget_show (button);
11303
11304       button = gtk_button_new_with_label ("start");
11305       g_signal_connect (button, "clicked",
11306                         G_CALLBACK (start_idle_test),
11307                         label);
11308       gtk_widget_set_can_default (button, TRUE);
11309       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
11310                           button, TRUE, TRUE, 0);
11311       gtk_widget_show (button);
11312
11313       button = gtk_button_new_with_label ("stop");
11314       g_signal_connect (button, "clicked",
11315                         G_CALLBACK (stop_idle_test),
11316                         NULL);
11317       gtk_widget_set_can_default (button, TRUE);
11318       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
11319                           button, TRUE, TRUE, 0);
11320       gtk_widget_show (button);
11321     }
11322
11323   if (!gtk_widget_get_visible (window))
11324     gtk_widget_show (window);
11325   else
11326     gtk_widget_destroy (window);
11327 }
11328
11329 /*
11330  * rc file test
11331  */
11332
11333 void
11334 reload_all_rc_files (void)
11335 {
11336   static GdkAtom atom_rcfiles = GDK_NONE;
11337
11338   GdkEvent *send_event = gdk_event_new (GDK_CLIENT_EVENT);
11339   int i;
11340   
11341   if (!atom_rcfiles)
11342     atom_rcfiles = gdk_atom_intern("_GTK_READ_RCFILES", FALSE);
11343
11344   for(i = 0; i < 5; i++)
11345     send_event->client.data.l[i] = 0;
11346   send_event->client.data_format = 32;
11347   send_event->client.message_type = atom_rcfiles;
11348   gdk_event_send_clientmessage_toall (send_event);
11349
11350   gdk_event_free (send_event);
11351 }
11352
11353 void
11354 create_rc_file (GtkWidget *widget)
11355 {
11356   static GtkWidget *window = NULL;
11357   GtkWidget *button;
11358   GtkWidget *frame;
11359   GtkWidget *vbox;
11360   GtkWidget *label;
11361
11362   if (!window)
11363     {
11364       window = gtk_dialog_new ();
11365
11366       gtk_window_set_screen (GTK_WINDOW (window),
11367                              gtk_widget_get_screen (widget));
11368
11369       g_signal_connect (window, "destroy",
11370                         G_CALLBACK (gtk_widget_destroyed),
11371                         &window);
11372
11373       frame = gtk_aspect_frame_new ("Testing RC file prioritization", 0.5, 0.5, 0.0, TRUE);
11374       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), frame, FALSE, FALSE, 0);
11375
11376       vbox = gtk_vbox_new (FALSE, 0);
11377       gtk_container_add (GTK_CONTAINER (frame), vbox);
11378       
11379       label = gtk_label_new ("This label should be red");
11380       gtk_widget_set_name (label, "testgtk-red-label");
11381       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
11382
11383       label = gtk_label_new ("This label should be green");
11384       gtk_widget_set_name (label, "testgtk-green-label");
11385       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
11386
11387       label = gtk_label_new ("This label should be blue");
11388       gtk_widget_set_name (label, "testgtk-blue-label");
11389       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
11390
11391       gtk_window_set_title (GTK_WINDOW (window), "Reload Rc file");
11392       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
11393
11394       button = gtk_button_new_with_label ("Reload");
11395       g_signal_connect (button, "clicked",
11396                         G_CALLBACK (gtk_rc_reparse_all), NULL);
11397       gtk_widget_set_can_default (button, TRUE);
11398       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
11399                           button, TRUE, TRUE, 0);
11400       gtk_widget_grab_default (button);
11401
11402       button = gtk_button_new_with_label ("Reload All");
11403       g_signal_connect (button, "clicked",
11404                         G_CALLBACK (reload_all_rc_files), NULL);
11405       gtk_widget_set_can_default (button, TRUE);
11406       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
11407                           button, TRUE, TRUE, 0);
11408
11409       button = gtk_button_new_with_label ("Close");
11410       g_signal_connect_swapped (button, "clicked",
11411                                 G_CALLBACK (gtk_widget_destroy),
11412                                 window);
11413       gtk_widget_set_can_default (button, TRUE);
11414       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
11415                           button, TRUE, TRUE, 0);
11416     }
11417
11418   if (!gtk_widget_get_visible (window))
11419     gtk_widget_show_all (window);
11420   else
11421     gtk_widget_destroy (window);
11422 }
11423
11424 /*
11425  * Test of recursive mainloop
11426  */
11427
11428 void
11429 mainloop_destroyed (GtkWidget *w, GtkWidget **window)
11430 {
11431   *window = NULL;
11432   gtk_main_quit ();
11433 }
11434
11435 void
11436 create_mainloop (GtkWidget *widget)
11437 {
11438   static GtkWidget *window = NULL;
11439   GtkWidget *label;
11440   GtkWidget *button;
11441
11442   if (!window)
11443     {
11444       window = gtk_dialog_new ();
11445
11446       gtk_window_set_screen (GTK_WINDOW (window),
11447                              gtk_widget_get_screen (widget));
11448
11449       gtk_window_set_title (GTK_WINDOW (window), "Test Main Loop");
11450
11451       g_signal_connect (window, "destroy",
11452                         G_CALLBACK (mainloop_destroyed),
11453                         &window);
11454
11455       label = gtk_label_new ("In recursive main loop...");
11456       gtk_misc_set_padding (GTK_MISC(label), 20, 20);
11457
11458       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), label,
11459                           TRUE, TRUE, 0);
11460       gtk_widget_show (label);
11461
11462       button = gtk_button_new_with_label ("Leave");
11463       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), button, 
11464                           FALSE, TRUE, 0);
11465
11466       g_signal_connect_swapped (button, "clicked",
11467                                 G_CALLBACK (gtk_widget_destroy),
11468                                 window);
11469
11470       gtk_widget_set_can_default (button, TRUE);
11471       gtk_widget_grab_default (button);
11472
11473       gtk_widget_show (button);
11474     }
11475
11476   if (!gtk_widget_get_visible (window))
11477     {
11478       gtk_widget_show (window);
11479
11480       g_print ("create_mainloop: start\n");
11481       gtk_main ();
11482       g_print ("create_mainloop: done\n");
11483     }
11484   else
11485     gtk_widget_destroy (window);
11486 }
11487
11488 gboolean
11489 layout_expose_handler (GtkWidget *widget, GdkEventExpose *event)
11490 {
11491   GtkLayout *layout;
11492
11493   gint i,j;
11494   gint imin, imax, jmin, jmax;
11495
11496   layout = GTK_LAYOUT (widget);
11497
11498   if (event->window != layout->bin_window)
11499     return FALSE;
11500   
11501   imin = (event->area.x) / 10;
11502   imax = (event->area.x + event->area.width + 9) / 10;
11503
11504   jmin = (event->area.y) / 10;
11505   jmax = (event->area.y + event->area.height + 9) / 10;
11506
11507   for (i=imin; i<imax; i++)
11508     for (j=jmin; j<jmax; j++)
11509       if ((i+j) % 2)
11510         gdk_draw_rectangle (layout->bin_window,
11511                             widget->style->black_gc,
11512                             TRUE,
11513                             10*i, 10*j, 
11514                             1+i%10, 1+j%10);
11515   
11516   return FALSE;
11517 }
11518
11519 void create_layout (GtkWidget *widget)
11520 {
11521   static GtkWidget *window = NULL;
11522   GtkWidget *layout;
11523   GtkWidget *scrolledwindow;
11524   GtkWidget *button;
11525
11526   if (!window)
11527     {
11528       gchar buf[16];
11529
11530       gint i, j;
11531       
11532       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
11533       gtk_window_set_screen (GTK_WINDOW (window),
11534                              gtk_widget_get_screen (widget));
11535
11536       g_signal_connect (window, "destroy",
11537                         G_CALLBACK (gtk_widget_destroyed),
11538                         &window);
11539
11540       gtk_window_set_title (GTK_WINDOW (window), "Layout");
11541       gtk_widget_set_size_request (window, 200, 200);
11542
11543       scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
11544       gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolledwindow),
11545                                            GTK_SHADOW_IN);
11546       gtk_scrolled_window_set_placement (GTK_SCROLLED_WINDOW (scrolledwindow),
11547                                          GTK_CORNER_TOP_RIGHT);
11548
11549       gtk_container_add (GTK_CONTAINER (window), scrolledwindow);
11550       
11551       layout = gtk_layout_new (NULL, NULL);
11552       gtk_container_add (GTK_CONTAINER (scrolledwindow), layout);
11553
11554       /* We set step sizes here since GtkLayout does not set
11555        * them itself.
11556        */
11557       GTK_LAYOUT (layout)->hadjustment->step_increment = 10.0;
11558       GTK_LAYOUT (layout)->vadjustment->step_increment = 10.0;
11559       
11560       gtk_widget_set_events (layout, GDK_EXPOSURE_MASK);
11561       g_signal_connect (layout, "expose_event",
11562                         G_CALLBACK (layout_expose_handler), NULL);
11563       
11564       gtk_layout_set_size (GTK_LAYOUT (layout), 1600, 128000);
11565       
11566       for (i=0 ; i < 16 ; i++)
11567         for (j=0 ; j < 16 ; j++)
11568           {
11569             sprintf(buf, "Button %d, %d", i, j);
11570             if ((i + j) % 2)
11571               button = gtk_button_new_with_label (buf);
11572             else
11573               button = gtk_label_new (buf);
11574
11575             gtk_layout_put (GTK_LAYOUT (layout), button,
11576                             j*100, i*100);
11577           }
11578
11579       for (i=16; i < 1280; i++)
11580         {
11581           sprintf(buf, "Button %d, %d", i, 0);
11582           if (i % 2)
11583             button = gtk_button_new_with_label (buf);
11584           else
11585             button = gtk_label_new (buf);
11586
11587           gtk_layout_put (GTK_LAYOUT (layout), button,
11588                           0, i*100);
11589         }
11590     }
11591
11592   if (!gtk_widget_get_visible (window))
11593     gtk_widget_show_all (window);
11594   else
11595     gtk_widget_destroy (window);
11596 }
11597
11598 void
11599 create_styles (GtkWidget *widget)
11600 {
11601   static GtkWidget *window = NULL;
11602   GtkWidget *label;
11603   GtkWidget *button;
11604   GtkWidget *entry;
11605   GtkWidget *vbox;
11606   static GdkColor red =    { 0, 0xffff, 0,      0      };
11607   static GdkColor green =  { 0, 0,      0xffff, 0      };
11608   static GdkColor blue =   { 0, 0,      0,      0xffff };
11609   static GdkColor yellow = { 0, 0xffff, 0xffff, 0      };
11610   static GdkColor cyan =   { 0, 0     , 0xffff, 0xffff };
11611   PangoFontDescription *font_desc;
11612
11613   GtkRcStyle *rc_style;
11614
11615   if (!window)
11616     {
11617       window = gtk_dialog_new ();
11618       gtk_window_set_screen (GTK_WINDOW (window),
11619                              gtk_widget_get_screen (widget));
11620      
11621       g_signal_connect (window, "destroy",
11622                         G_CALLBACK (gtk_widget_destroyed),
11623                         &window);
11624
11625       
11626       button = gtk_button_new_with_label ("Close");
11627       g_signal_connect_swapped (button, "clicked",
11628                                 G_CALLBACK (gtk_widget_destroy),
11629                                 window);
11630       gtk_widget_set_can_default (button, TRUE);
11631       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
11632                           button, TRUE, TRUE, 0);
11633       gtk_widget_show (button);
11634
11635       vbox = gtk_vbox_new (FALSE, 5);
11636       gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
11637       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), vbox, FALSE, FALSE, 0);
11638       
11639       label = gtk_label_new ("Font:");
11640       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
11641       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
11642
11643       font_desc = pango_font_description_from_string ("Helvetica,Sans Oblique 18");
11644
11645       button = gtk_button_new_with_label ("Some Text");
11646       gtk_widget_modify_font (GTK_BIN (button)->child, font_desc);
11647       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
11648
11649       label = gtk_label_new ("Foreground:");
11650       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
11651       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
11652
11653       button = gtk_button_new_with_label ("Some Text");
11654       gtk_widget_modify_fg (GTK_BIN (button)->child, GTK_STATE_NORMAL, &red);
11655       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
11656
11657       label = gtk_label_new ("Background:");
11658       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
11659       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
11660
11661       button = gtk_button_new_with_label ("Some Text");
11662       gtk_widget_modify_bg (button, GTK_STATE_NORMAL, &green);
11663       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
11664
11665       label = gtk_label_new ("Text:");
11666       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
11667       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
11668
11669       entry = gtk_entry_new ();
11670       gtk_entry_set_text (GTK_ENTRY (entry), "Some Text");
11671       gtk_widget_modify_text (entry, GTK_STATE_NORMAL, &blue);
11672       gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
11673
11674       label = gtk_label_new ("Base:");
11675       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
11676       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
11677
11678       entry = gtk_entry_new ();
11679       gtk_entry_set_text (GTK_ENTRY (entry), "Some Text");
11680       gtk_widget_modify_base (entry, GTK_STATE_NORMAL, &yellow);
11681       gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
11682
11683       label = gtk_label_new ("Cursor:");
11684       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
11685       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
11686
11687       entry = gtk_entry_new ();
11688       gtk_entry_set_text (GTK_ENTRY (entry), "Some Text");
11689       gtk_widget_modify_cursor (entry, &red, &red);
11690       gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
11691
11692       label = gtk_label_new ("Multiple:");
11693       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
11694       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
11695
11696       button = gtk_button_new_with_label ("Some Text");
11697
11698       rc_style = gtk_rc_style_new ();
11699
11700       rc_style->font_desc = pango_font_description_copy (font_desc);
11701       rc_style->color_flags[GTK_STATE_NORMAL] = GTK_RC_FG | GTK_RC_BG;
11702       rc_style->color_flags[GTK_STATE_PRELIGHT] = GTK_RC_FG | GTK_RC_BG;
11703       rc_style->color_flags[GTK_STATE_ACTIVE] = GTK_RC_FG | GTK_RC_BG;
11704       rc_style->fg[GTK_STATE_NORMAL] = yellow;
11705       rc_style->bg[GTK_STATE_NORMAL] = blue;
11706       rc_style->fg[GTK_STATE_PRELIGHT] = blue;
11707       rc_style->bg[GTK_STATE_PRELIGHT] = yellow;
11708       rc_style->fg[GTK_STATE_ACTIVE] = red;
11709       rc_style->bg[GTK_STATE_ACTIVE] = cyan;
11710       rc_style->xthickness = 5;
11711       rc_style->ythickness = 5;
11712
11713       gtk_widget_modify_style (button, rc_style);
11714       gtk_widget_modify_style (GTK_BIN (button)->child, rc_style);
11715
11716       g_object_unref (rc_style);
11717       
11718       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
11719     }
11720   
11721   if (!gtk_widget_get_visible (window))
11722     gtk_widget_show_all (window);
11723   else
11724     gtk_widget_destroy (window);
11725 }
11726
11727 /*
11728  * Main Window and Exit
11729  */
11730
11731 void
11732 do_exit (GtkWidget *widget, GtkWidget *window)
11733 {
11734   gtk_widget_destroy (window);
11735   gtk_main_quit ();
11736 }
11737
11738 struct {
11739   char *label;
11740   void (*func) (GtkWidget *widget);
11741   gboolean do_not_benchmark;
11742 } buttons[] =
11743 {
11744   { "alpha window", create_alpha_window },
11745   { "big windows", create_big_windows },
11746   { "button box", create_button_box },
11747   { "buttons", create_buttons },
11748   { "check buttons", create_check_buttons },
11749   { "color selection", create_color_selection },
11750   { "composited window", create_composited_window },
11751   { "cursors", create_cursors },
11752   { "dialog", create_dialog },
11753   { "display & screen", create_display_screen, TRUE },
11754   { "entry", create_entry },
11755   { "event box", create_event_box },
11756   { "event watcher", create_event_watcher },
11757   { "expander", create_expander },
11758   { "flipping", create_flipping },
11759   { "focus", create_focus },
11760   { "font selection", create_font_selection },
11761   { "gamma curve", create_gamma_curve, TRUE },
11762   { "gridded geometry", create_gridded_geometry },
11763   { "handle box", create_handle_box },
11764   { "image from drawable", create_get_image },
11765   { "image", create_image },
11766   { "item factory", create_item_factory },
11767   { "key lookup", create_key_lookup },
11768   { "labels", create_labels },
11769   { "layout", create_layout },
11770   { "list", create_list },
11771   { "menus", create_menus },
11772   { "message dialog", create_message_dialog },
11773   { "modal window", create_modal_window, TRUE },
11774   { "notebook", create_notebook },
11775   { "panes", create_panes },
11776   { "paned keyboard", create_paned_keyboard_navigation },
11777   { "pixmap", create_pixmap },
11778   { "progress bar", create_progress_bar },
11779   { "properties", create_properties },
11780   { "radio buttons", create_radio_buttons },
11781   { "range controls", create_range_controls },
11782   { "rc file", create_rc_file },
11783   { "reparent", create_reparent },
11784   { "resize grips", create_resize_grips },
11785   { "rotated label", create_rotated_label },
11786   { "rotated text", create_rotated_text },
11787   { "rulers", create_rulers },
11788   { "saved position", create_saved_position },
11789   { "scrolled windows", create_scrolled_windows },
11790   { "shapes", create_shapes },
11791   { "size groups", create_size_groups },
11792   { "snapshot", create_snapshot },
11793   { "spinbutton", create_spins },
11794   { "statusbar", create_statusbar },
11795   { "styles", create_styles },
11796   { "test idle", create_idle_test },
11797   { "test mainloop", create_mainloop, TRUE },
11798   { "test scrolling", create_scroll_test },
11799   { "test selection", create_selection_test },
11800   { "test timeout", create_timeout_test },
11801   { "text", create_text },
11802   { "toggle buttons", create_toggle_buttons },
11803   { "toolbar", create_toolbar },
11804   { "tooltips", create_tooltips },
11805   { "tree", create_tree_mode_window},
11806   { "WM hints", create_wmhints },
11807   { "window sizing", create_window_sizing },
11808   { "window states", create_window_states }
11809 };
11810 int nbuttons = sizeof (buttons) / sizeof (buttons[0]);
11811
11812 void
11813 create_main_window (void)
11814 {
11815   GtkWidget *window;
11816   GtkWidget *box1;
11817   GtkWidget *box2;
11818   GtkWidget *scrolled_window;
11819   GtkWidget *button;
11820   GtkWidget *label;
11821   gchar buffer[64];
11822   GtkWidget *separator;
11823   GdkGeometry geometry;
11824   int i;
11825
11826   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
11827   gtk_widget_set_name (window, "main window");
11828   gtk_widget_set_uposition (window, 50, 20);
11829   gtk_window_set_default_size (GTK_WINDOW (window), -1, 400);
11830
11831   geometry.min_width = -1;
11832   geometry.min_height = -1;
11833   geometry.max_width = -1;
11834   geometry.max_height = G_MAXSHORT;
11835   gtk_window_set_geometry_hints (GTK_WINDOW (window), NULL,
11836                                  &geometry,
11837                                  GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE);
11838
11839   g_signal_connect (window, "destroy",
11840                     G_CALLBACK (gtk_main_quit),
11841                     NULL);
11842   g_signal_connect (window, "delete-event",
11843                     G_CALLBACK (gtk_false),
11844                     NULL);
11845
11846   box1 = gtk_vbox_new (FALSE, 0);
11847   gtk_container_add (GTK_CONTAINER (window), box1);
11848
11849   if (gtk_micro_version > 0)
11850     sprintf (buffer,
11851              "Gtk+ v%d.%d.%d",
11852              gtk_major_version,
11853              gtk_minor_version,
11854              gtk_micro_version);
11855   else
11856     sprintf (buffer,
11857              "Gtk+ v%d.%d",
11858              gtk_major_version,
11859              gtk_minor_version);
11860
11861   label = gtk_label_new (buffer);
11862   gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);
11863   gtk_widget_set_name (label, "testgtk-version-label");
11864
11865   scrolled_window = gtk_scrolled_window_new (NULL, NULL);
11866   gtk_container_set_border_width (GTK_CONTAINER (scrolled_window), 10);
11867   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
11868                                   GTK_POLICY_NEVER, 
11869                                   GTK_POLICY_AUTOMATIC);
11870   gtk_box_pack_start (GTK_BOX (box1), scrolled_window, TRUE, TRUE, 0);
11871
11872   box2 = gtk_vbox_new (FALSE, 0);
11873   gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
11874   gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_window), box2);
11875   gtk_container_set_focus_vadjustment (GTK_CONTAINER (box2),
11876                                        gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (scrolled_window)));
11877   gtk_widget_show (box2);
11878
11879   for (i = 0; i < nbuttons; i++)
11880     {
11881       button = gtk_button_new_with_label (buttons[i].label);
11882       if (buttons[i].func)
11883         g_signal_connect (button, 
11884                           "clicked", 
11885                           G_CALLBACK(buttons[i].func),
11886                           NULL);
11887       else
11888         gtk_widget_set_sensitive (button, FALSE);
11889       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
11890     }
11891
11892   separator = gtk_hseparator_new ();
11893   gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
11894
11895   box2 = gtk_vbox_new (FALSE, 10);
11896   gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
11897   gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
11898
11899   button = gtk_button_new_with_mnemonic ("_Close");
11900   g_signal_connect (button, "clicked",
11901                     G_CALLBACK (do_exit),
11902                     window);
11903   gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
11904   gtk_widget_set_can_default (button, TRUE);
11905   gtk_widget_grab_default (button);
11906
11907   gtk_widget_show_all (window);
11908 }
11909
11910 static void
11911 test_init (void)
11912 {
11913   if (g_file_test ("../gdk-pixbuf/libpixbufloader-pnm.la",
11914                    G_FILE_TEST_EXISTS))
11915     {
11916       g_setenv ("GDK_PIXBUF_MODULE_FILE", "../gdk-pixbuf/gdk-pixbuf.loaders", TRUE);
11917       g_setenv ("GTK_IM_MODULE_FILE", "../modules/input/gtk.immodules", TRUE);
11918     }
11919 }
11920
11921 static char *
11922 pad (const char *str, int to)
11923 {
11924   static char buf[256];
11925   int len = strlen (str);
11926   int i;
11927
11928   for (i = 0; i < to; i++)
11929     buf[i] = ' ';
11930
11931   buf[to] = '\0';
11932
11933   memcpy (buf, str, len);
11934
11935   return buf;
11936 }
11937
11938 static void
11939 bench_iteration (GtkWidget *widget, void (* fn) (GtkWidget *widget))
11940 {
11941   fn (widget); /* on */
11942   while (g_main_context_iteration (NULL, FALSE));
11943   fn (widget); /* off */
11944   while (g_main_context_iteration (NULL, FALSE));
11945 }
11946
11947 void
11948 do_real_bench (GtkWidget *widget, void (* fn) (GtkWidget *widget), char *name, int num)
11949 {
11950   GTimeVal tv0, tv1;
11951   double dt_first;
11952   double dt;
11953   int n;
11954   static gboolean printed_headers = FALSE;
11955
11956   if (!printed_headers) {
11957     g_print ("Test                 Iters      First      Other\n");
11958     g_print ("-------------------- ----- ---------- ----------\n");
11959     printed_headers = TRUE;
11960   }
11961
11962   g_get_current_time (&tv0);
11963   bench_iteration (widget, fn); 
11964   g_get_current_time (&tv1);
11965
11966   dt_first = ((double)tv1.tv_sec - tv0.tv_sec) * 1000.0
11967         + (tv1.tv_usec - tv0.tv_usec) / 1000.0;
11968
11969   g_get_current_time (&tv0);
11970   for (n = 0; n < num - 1; n++)
11971     bench_iteration (widget, fn); 
11972   g_get_current_time (&tv1);
11973   dt = ((double)tv1.tv_sec - tv0.tv_sec) * 1000.0
11974         + (tv1.tv_usec - tv0.tv_usec) / 1000.0;
11975
11976   g_print ("%s %5d ", pad (name, 20), num);
11977   if (num > 1)
11978     g_print ("%10.1f %10.1f\n", dt_first, dt/(num-1));
11979   else
11980     g_print ("%10.1f\n", dt_first);
11981 }
11982
11983 void
11984 do_bench (char* what, int num)
11985 {
11986   int i;
11987   GtkWidget *widget;
11988   void (* fn) (GtkWidget *widget);
11989   fn = NULL;
11990   widget = gtk_window_new (GTK_WINDOW_TOPLEVEL);
11991
11992   if (g_ascii_strcasecmp (what, "ALL") == 0)
11993     {
11994       for (i = 0; i < nbuttons; i++)
11995         {
11996           if (!buttons[i].do_not_benchmark)
11997             do_real_bench (widget, buttons[i].func, buttons[i].label, num);
11998         }
11999
12000       return;
12001     }
12002   else
12003     {
12004       for (i = 0; i < nbuttons; i++)
12005         {
12006           if (strcmp (buttons[i].label, what) == 0)
12007             {
12008               fn = buttons[i].func;
12009               break;
12010             }
12011         }
12012       
12013       if (!fn)
12014         g_print ("Can't bench: \"%s\" not found.\n", what);
12015       else
12016         do_real_bench (widget, fn, buttons[i].label, num);
12017     }
12018 }
12019
12020 void 
12021 usage (void)
12022 {
12023   fprintf (stderr, "Usage: testgtk [--bench ALL|<bench>[:<count>]]\n");
12024   exit (1);
12025 }
12026
12027 int
12028 main (int argc, char *argv[])
12029 {
12030   GtkBindingSet *binding_set;
12031   int i;
12032   gboolean done_benchmarks = FALSE;
12033
12034   srand (time (NULL));
12035
12036   test_init ();
12037
12038   /* Check to see if we are being run from the correct
12039    * directory.
12040    */
12041   if (file_exists ("testgtkrc"))
12042     gtk_rc_add_default_file ("testgtkrc");
12043   else if (file_exists ("tests/testgtkrc"))
12044     gtk_rc_add_default_file ("tests/testgtkrc");
12045   else
12046     g_warning ("Couldn't find file \"testgtkrc\".");
12047
12048   g_set_application_name ("GTK+ Test Program");
12049
12050   gtk_init (&argc, &argv);
12051
12052   gtk_accelerator_set_default_mod_mask (GDK_SHIFT_MASK |
12053                                         GDK_CONTROL_MASK |
12054                                         GDK_MOD1_MASK | 
12055                                         GDK_META_MASK |
12056                                         GDK_SUPER_MASK |
12057                                         GDK_HYPER_MASK |
12058                                         GDK_MOD4_MASK);
12059   /*  benchmarking
12060    */
12061   for (i = 1; i < argc; i++)
12062     {
12063       if (strncmp (argv[i], "--bench", strlen("--bench")) == 0)
12064         {
12065           int num = 1;
12066           char *nextarg;
12067           char *what;
12068           char *count;
12069           
12070           nextarg = strchr (argv[i], '=');
12071           if (nextarg)
12072             nextarg++;
12073           else
12074             {
12075               i++;
12076               if (i == argc)
12077                 usage ();
12078               nextarg = argv[i];
12079             }
12080
12081           count = strchr (nextarg, ':');
12082           if (count)
12083             {
12084               what = g_strndup (nextarg, count - nextarg);
12085               count++;
12086               num = atoi (count);
12087               if (num <= 0)
12088                 usage ();
12089             }
12090           else
12091             what = g_strdup (nextarg);
12092
12093           do_bench (what, num ? num : 1);
12094           done_benchmarks = TRUE;
12095         }
12096       else
12097         usage ();
12098     }
12099   if (done_benchmarks)
12100     return 0;
12101
12102   /* bindings test
12103    */
12104   binding_set = gtk_binding_set_by_class (g_type_class_ref (GTK_TYPE_WIDGET));
12105   gtk_binding_entry_add_signal (binding_set,
12106                                 '9', GDK_CONTROL_MASK | GDK_RELEASE_MASK,
12107                                 "debug_msg",
12108                                 1,
12109                                 G_TYPE_STRING, "GtkWidgetClass <ctrl><release>9 test");
12110   
12111   /* We use gtk_rc_parse_string() here so we can make sure it works across theme
12112    * changes
12113    */
12114
12115   gtk_rc_parse_string ("style \"testgtk-version-label\" { "
12116                        "   fg[NORMAL] = \"#ff0000\"\n"
12117                        "   font = \"Sans 18\"\n"
12118                        "}\n"
12119                        "widget \"*.testgtk-version-label\" style \"testgtk-version-label\"");
12120   
12121   create_main_window ();
12122
12123   gtk_main ();
12124
12125   if (1)
12126     {
12127       while (g_main_context_pending (NULL))
12128         g_main_context_iteration (NULL, FALSE);
12129 #if 0
12130       sleep (1);
12131       while (g_main_context_pending (NULL))
12132         g_main_context_iteration (NULL, FALSE);
12133 #endif
12134     }
12135   return 0;
12136 }