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