]> Pileus Git - ~andy/gtk/blob - tests/testgtk.c
Use GtkComboBoxEntry in entry test in 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_usize (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 tips_query_widget_entered (GtkTipsQuery   *tips_query,
3363                            GtkWidget      *widget,
3364                            const gchar    *tip_text,
3365                            const gchar    *tip_private,
3366                            GtkWidget      *toggle)
3367 {
3368   if (GTK_TOGGLE_BUTTON (toggle)->active)
3369     {
3370       gtk_label_set_text (GTK_LABEL (tips_query), tip_text ? "There is a Tip!" : "There is no Tip!");
3371       /* don't let GtkTipsQuery reset its label */
3372       g_signal_stop_emission_by_name (tips_query, "widget_entered");
3373     }
3374 }
3375
3376 static gint
3377 tips_query_widget_selected (GtkWidget      *tips_query,
3378                             GtkWidget      *widget,
3379                             const gchar    *tip_text,
3380                             const gchar    *tip_private,
3381                             GdkEventButton *event,
3382                             gpointer        func_data)
3383 {
3384   if (widget)
3385     g_print ("Help \"%s\" requested for <%s>\n",
3386              tip_private ? tip_private : "None",
3387              g_type_name (G_OBJECT_TYPE (widget)));
3388   return TRUE;
3389 }
3390
3391 static void
3392 create_tooltips (GtkWidget *widget)
3393 {
3394   static GtkWidget *window = NULL;
3395   GtkWidget *box1;
3396   GtkWidget *box2;
3397   GtkWidget *box3;
3398   GtkWidget *button;
3399   GtkWidget *toggle;
3400   GtkWidget *frame;
3401   GtkWidget *tips_query;
3402   GtkWidget *separator;
3403
3404   if (!window)
3405     {
3406       window =
3407         g_object_new (gtk_window_get_type (),
3408                         "GtkWindow::type", GTK_WINDOW_TOPLEVEL,
3409                         "GtkContainer::border_width", 0,
3410                         "GtkWindow::title", "Tooltips",
3411                         "GtkWindow::allow_shrink", TRUE,
3412                         "GtkWindow::allow_grow", FALSE,
3413                         NULL);
3414
3415       gtk_window_set_screen (GTK_WINDOW (window),
3416                              gtk_widget_get_screen (widget));
3417
3418       box1 = gtk_vbox_new (FALSE, 0);
3419       gtk_container_add (GTK_CONTAINER (window), box1);
3420
3421       box2 = gtk_vbox_new (FALSE, 10);
3422       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
3423       gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
3424
3425       button = gtk_toggle_button_new_with_label ("button1");
3426       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
3427
3428       gtk_widget_set_tooltip_text (button, "This is button 1");
3429
3430       button = gtk_toggle_button_new_with_label ("button2");
3431       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
3432
3433       gtk_widget_set_tooltip_text (button,
3434         "This is button 2. This is also a really long tooltip which probably "
3435         "won't fit on a single line and will therefore need to be wrapped. "
3436         "Hopefully the wrapping will work correctly.");
3437
3438       toggle = gtk_toggle_button_new_with_label ("Override TipsQuery Label");
3439       gtk_box_pack_start (GTK_BOX (box2), toggle, TRUE, TRUE, 0);
3440
3441       gtk_widget_set_tooltip_text (toggle, "Toggle TipsQuery view.");
3442
3443       box3 =
3444         g_object_new (gtk_vbox_get_type (),
3445                         "homogeneous", FALSE,
3446                         "spacing", 5,
3447                         "border_width", 5,
3448                         "visible", TRUE,
3449                         NULL);
3450
3451       tips_query = gtk_tips_query_new ();
3452
3453       button =
3454         g_object_new (gtk_button_get_type (),
3455                         "label", "[?]",
3456                         "visible", TRUE,
3457                         "parent", box3,
3458                         NULL);
3459       g_object_connect (button,
3460                         "swapped_signal::clicked", gtk_tips_query_start_query, tips_query,
3461                         NULL);
3462       gtk_box_set_child_packing (GTK_BOX (box3), button, FALSE, FALSE, 0, GTK_PACK_START);
3463       gtk_widget_set_tooltip_text (button "Start the Tooltips Inspector");
3464       
3465       g_object_set (g_object_connect (tips_query,
3466                                       "signal::widget_entered", tips_query_widget_entered, toggle,
3467                                       "signal::widget_selected", tips_query_widget_selected, NULL,
3468                                       NULL),
3469                     "visible", TRUE,
3470                     "parent", box3,
3471                     "caller", button,
3472                     NULL);
3473       
3474       frame = g_object_new (gtk_frame_get_type (),
3475                               "label", "ToolTips Inspector",
3476                               "label_xalign", (double) 0.5,
3477                               "border_width", 0,
3478                               "visible", TRUE,
3479                               "parent", box2,
3480                               "child", box3,
3481                               NULL);
3482       gtk_box_set_child_packing (GTK_BOX (box2), frame, TRUE, TRUE, 10, GTK_PACK_START);
3483
3484       separator = gtk_hseparator_new ();
3485       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
3486
3487       box2 = gtk_vbox_new (FALSE, 10);
3488       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
3489       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
3490
3491       button = gtk_button_new_with_label ("close");
3492       g_signal_connect_swapped (button, "clicked",
3493                                 G_CALLBACK (gtk_widget_destroy),
3494                                 window);
3495       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
3496       gtk_widget_set_can_default (button, TRUE);
3497       gtk_widget_grab_default (button);
3498
3499       gtk_widget_set_tooltip_text (button, "Push this button to close window");
3500     }
3501
3502   if (!gtk_widget_get_visible (window))
3503     gtk_widget_show_all (window);
3504   else
3505     gtk_widget_destroy (window);
3506 }
3507
3508 /*
3509  * GtkImage
3510  */
3511
3512 static void
3513 pack_image (GtkWidget *box,
3514             const gchar *text,
3515             GtkWidget *image)
3516 {
3517   gtk_box_pack_start (GTK_BOX (box),
3518                       gtk_label_new (text),
3519                       FALSE, FALSE, 0);
3520
3521   gtk_box_pack_start (GTK_BOX (box),
3522                       image,
3523                       TRUE, TRUE, 0);  
3524 }
3525
3526 static void
3527 create_image (GtkWidget *widget)
3528 {
3529   static GtkWidget *window = NULL;
3530
3531   if (window == NULL)
3532     {
3533       GtkWidget *vbox;
3534       GdkPixmap *pixmap;
3535       GdkBitmap *mask;
3536         
3537       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3538       
3539       gtk_window_set_screen (GTK_WINDOW (window),
3540                              gtk_widget_get_screen (widget));
3541
3542       /* this is bogus for testing drawing when allocation < request,
3543        * don't copy into real code
3544        */
3545       g_object_set (window, "allow_shrink", TRUE, "allow_grow", TRUE, NULL);
3546       
3547       g_signal_connect (window, "destroy",
3548                         G_CALLBACK (gtk_widget_destroyed),
3549                         &window);
3550
3551       vbox = gtk_vbox_new (FALSE, 5);
3552
3553       gtk_container_add (GTK_CONTAINER (window), vbox);
3554
3555       pack_image (vbox, "Stock Warning Dialog",
3556                   gtk_image_new_from_stock (GTK_STOCK_DIALOG_WARNING,
3557                                             GTK_ICON_SIZE_DIALOG));
3558
3559       pixmap = gdk_pixmap_colormap_create_from_xpm_d (NULL,
3560                                                       gtk_widget_get_colormap (window),
3561                                                       &mask,
3562                                                       NULL,
3563                                                       openfile);
3564       
3565       pack_image (vbox, "Pixmap",
3566                   gtk_image_new_from_pixmap (pixmap, mask));
3567     }
3568
3569   if (!gtk_widget_get_visible (window))
3570     gtk_widget_show_all (window);
3571   else
3572     gtk_widget_destroy (window);
3573 }
3574      
3575 /*
3576  * Menu demo
3577  */
3578
3579 static GtkWidget*
3580 create_menu (GdkScreen *screen, gint depth, gint length, gboolean tearoff)
3581 {
3582   GtkWidget *menu;
3583   GtkWidget *menuitem;
3584   GtkWidget *image;
3585   GSList *group;
3586   char buf[32];
3587   int i, j;
3588
3589   if (depth < 1)
3590     return NULL;
3591
3592   menu = gtk_menu_new ();
3593   gtk_menu_set_screen (GTK_MENU (menu), screen);
3594
3595   group = NULL;
3596
3597   if (tearoff)
3598     {
3599       menuitem = gtk_tearoff_menu_item_new ();
3600       gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
3601       gtk_widget_show (menuitem);
3602     }
3603
3604   image = gtk_image_new_from_stock (GTK_STOCK_OPEN,
3605                                     GTK_ICON_SIZE_MENU);
3606   gtk_widget_show (image);
3607   menuitem = gtk_image_menu_item_new_with_label ("Image item");
3608   gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), image);
3609   gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
3610   gtk_widget_show (menuitem);
3611   
3612   for (i = 0, j = 1; i < length; i++, j++)
3613     {
3614       sprintf (buf, "item %2d - %d", depth, j);
3615
3616       menuitem = gtk_radio_menu_item_new_with_label (group, buf);
3617       group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (menuitem));
3618
3619       gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
3620       gtk_widget_show (menuitem);
3621       if (i == 3)
3622         gtk_widget_set_sensitive (menuitem, FALSE);
3623
3624       if (i == 5)
3625         gtk_check_menu_item_set_inconsistent (GTK_CHECK_MENU_ITEM (menuitem),
3626                                               TRUE);
3627
3628       if (i < 5)
3629         gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), 
3630                                    create_menu (screen, depth - 1, 5,  TRUE));
3631     }
3632
3633   return menu;
3634 }
3635
3636 static GtkWidget*
3637 create_table_menu (GdkScreen *screen, gint cols, gint rows, gboolean tearoff)
3638 {
3639   GtkWidget *menu;
3640   GtkWidget *menuitem;
3641   GtkWidget *submenu;
3642   GtkWidget *image;
3643   char buf[32];
3644   int i, j;
3645
3646   menu = gtk_menu_new ();
3647   gtk_menu_set_screen (GTK_MENU (menu), screen);
3648
3649   j = 0;
3650   if (tearoff)
3651     {
3652       menuitem = gtk_tearoff_menu_item_new ();
3653       gtk_menu_attach (GTK_MENU (menu), menuitem, 0, cols, j, j + 1);
3654       gtk_widget_show (menuitem);
3655       j++;
3656     }
3657   
3658   menuitem = gtk_menu_item_new_with_label ("items");
3659   gtk_menu_attach (GTK_MENU (menu), menuitem, 0, cols, j, j + 1);
3660
3661   submenu = gtk_menu_new ();
3662   gtk_menu_set_screen (GTK_MENU (submenu), screen);
3663   gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), submenu);
3664   gtk_widget_show (menuitem);
3665   j++;
3666
3667   /* now fill the items submenu */
3668   image = gtk_image_new_from_stock (GTK_STOCK_HELP,
3669                                     GTK_ICON_SIZE_MENU);
3670   gtk_widget_show (image);
3671   menuitem = gtk_image_menu_item_new_with_label ("Image");
3672   gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), image);
3673   gtk_menu_attach (GTK_MENU (submenu), menuitem, 0, 1, 0, 1);
3674   gtk_widget_show (menuitem);
3675
3676   menuitem = gtk_menu_item_new_with_label ("x");
3677   gtk_menu_attach (GTK_MENU (submenu), menuitem, 1, 2, 0, 1);
3678   gtk_widget_show (menuitem);
3679
3680   menuitem = gtk_menu_item_new_with_label ("x");
3681   gtk_menu_attach (GTK_MENU (submenu), menuitem, 0, 1, 1, 2);
3682   gtk_widget_show (menuitem);
3683   
3684   image = gtk_image_new_from_stock (GTK_STOCK_HELP,
3685                                     GTK_ICON_SIZE_MENU);
3686   gtk_widget_show (image);
3687   menuitem = gtk_image_menu_item_new_with_label ("Image");
3688   gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), image);
3689   gtk_menu_attach (GTK_MENU (submenu), menuitem, 1, 2, 1, 2);
3690   gtk_widget_show (menuitem);
3691
3692   menuitem = gtk_radio_menu_item_new_with_label (NULL, "Radio");
3693   gtk_menu_attach (GTK_MENU (submenu), menuitem, 0, 1, 2, 3);
3694   gtk_widget_show (menuitem);
3695
3696   menuitem = gtk_menu_item_new_with_label ("x");
3697   gtk_menu_attach (GTK_MENU (submenu), menuitem, 1, 2, 2, 3);
3698   gtk_widget_show (menuitem);
3699
3700   menuitem = gtk_menu_item_new_with_label ("x");
3701   gtk_menu_attach (GTK_MENU (submenu), menuitem, 0, 1, 3, 4);
3702   gtk_widget_show (menuitem);
3703   
3704   menuitem = gtk_radio_menu_item_new_with_label (NULL, "Radio");
3705   gtk_menu_attach (GTK_MENU (submenu), menuitem, 1, 2, 3, 4);
3706   gtk_widget_show (menuitem);
3707
3708   menuitem = gtk_check_menu_item_new_with_label ("Check");
3709   gtk_menu_attach (GTK_MENU (submenu), menuitem, 0, 1, 4, 5);
3710   gtk_widget_show (menuitem);
3711
3712   menuitem = gtk_menu_item_new_with_label ("x");
3713   gtk_menu_attach (GTK_MENU (submenu), menuitem, 1, 2, 4, 5);
3714   gtk_widget_show (menuitem);
3715
3716   menuitem = gtk_menu_item_new_with_label ("x");
3717   gtk_menu_attach (GTK_MENU (submenu), menuitem, 0, 1, 5, 6);
3718   gtk_widget_show (menuitem);
3719   
3720   menuitem = gtk_check_menu_item_new_with_label ("Check");
3721   gtk_menu_attach (GTK_MENU (submenu), menuitem, 1, 2, 5, 6);
3722   gtk_widget_show (menuitem);
3723
3724   menuitem = gtk_menu_item_new_with_label ("1. Inserted normally (8)");
3725   gtk_widget_show (menuitem);
3726   gtk_menu_shell_insert (GTK_MENU_SHELL (submenu), menuitem, 8);
3727
3728   menuitem = gtk_menu_item_new_with_label ("2. Inserted normally (2)");
3729   gtk_widget_show (menuitem);
3730   gtk_menu_shell_insert (GTK_MENU_SHELL (submenu), menuitem, 2);
3731
3732   menuitem = gtk_menu_item_new_with_label ("3. Inserted normally (0)");
3733   gtk_widget_show (menuitem);
3734   gtk_menu_shell_insert (GTK_MENU_SHELL (submenu), menuitem, 0);
3735
3736   menuitem = gtk_menu_item_new_with_label ("4. Inserted normally (-1)");
3737   gtk_widget_show (menuitem);
3738   gtk_menu_shell_insert (GTK_MENU_SHELL (submenu), menuitem, -1);
3739   
3740   /* end of items submenu */
3741
3742   menuitem = gtk_menu_item_new_with_label ("spanning");
3743   gtk_menu_attach (GTK_MENU (menu), menuitem, 0, cols, j, j + 1);
3744
3745   submenu = gtk_menu_new ();
3746   gtk_menu_set_screen (GTK_MENU (submenu), screen);
3747   gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), submenu);
3748   gtk_widget_show (menuitem);
3749   j++;
3750
3751   /* now fill the spanning submenu */
3752   menuitem = gtk_menu_item_new_with_label ("a");
3753   gtk_menu_attach (GTK_MENU (submenu), menuitem, 0, 2, 0, 1);
3754   gtk_widget_show (menuitem);
3755
3756   menuitem = gtk_menu_item_new_with_label ("b");
3757   gtk_menu_attach (GTK_MENU (submenu), menuitem, 2, 3, 0, 2);
3758   gtk_widget_show (menuitem);
3759
3760   menuitem = gtk_menu_item_new_with_label ("c");
3761   gtk_menu_attach (GTK_MENU (submenu), menuitem, 0, 1, 1, 3);
3762   gtk_widget_show (menuitem);
3763
3764   menuitem = gtk_menu_item_new_with_label ("d");
3765   gtk_menu_attach (GTK_MENU (submenu), menuitem, 1, 2, 1, 2);
3766   gtk_widget_show (menuitem);
3767
3768   menuitem = gtk_menu_item_new_with_label ("e");
3769   gtk_menu_attach (GTK_MENU (submenu), menuitem, 1, 3, 2, 3);
3770   gtk_widget_show (menuitem);
3771   /* end of spanning submenu */
3772   
3773   menuitem = gtk_menu_item_new_with_label ("left");
3774   gtk_menu_attach (GTK_MENU (menu), menuitem, 0, 1, j, j + 1);
3775   submenu = gtk_menu_new ();
3776   gtk_menu_set_screen (GTK_MENU (submenu), screen);
3777   gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), submenu);
3778   gtk_widget_show (menuitem);
3779
3780   menuitem = gtk_menu_item_new_with_label ("Empty");
3781   gtk_menu_attach (GTK_MENU (submenu), menuitem, 0, 1, 0, 1);
3782   submenu = gtk_menu_new ();
3783   gtk_menu_set_screen (GTK_MENU (submenu), screen);
3784   gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), submenu);
3785   gtk_widget_show (menuitem);
3786
3787   menuitem = gtk_menu_item_new_with_label ("right");
3788   gtk_menu_attach (GTK_MENU (menu), menuitem, 1, 2, j, j + 1);
3789   submenu = gtk_menu_new ();
3790   gtk_menu_set_screen (GTK_MENU (submenu), screen);
3791   gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), submenu);
3792   gtk_widget_show (menuitem);
3793
3794   menuitem = gtk_menu_item_new_with_label ("Empty");
3795   gtk_menu_attach (GTK_MENU (submenu), menuitem, 0, 1, 0, 1);
3796   gtk_widget_show (menuitem);
3797
3798   j++;
3799
3800   for (; j < rows; j++)
3801       for (i = 0; i < cols; i++)
3802       {
3803         sprintf (buf, "(%d %d)", i, j);
3804         menuitem = gtk_menu_item_new_with_label (buf);
3805         gtk_menu_attach (GTK_MENU (menu), menuitem, i, i + 1, j, j + 1);
3806         gtk_widget_show (menuitem);
3807       }
3808   
3809   menuitem = gtk_menu_item_new_with_label ("1. Inserted normally (8)");
3810   gtk_menu_shell_insert (GTK_MENU_SHELL (menu), menuitem, 8);
3811   gtk_widget_show (menuitem);
3812   menuitem = gtk_menu_item_new_with_label ("2. Inserted normally (2)");
3813   gtk_menu_shell_insert (GTK_MENU_SHELL (menu), menuitem, 2);
3814   gtk_widget_show (menuitem);
3815   menuitem = gtk_menu_item_new_with_label ("3. Inserted normally (0)");
3816   gtk_menu_shell_insert (GTK_MENU_SHELL (menu), menuitem, 0);
3817   gtk_widget_show (menuitem);
3818   menuitem = gtk_menu_item_new_with_label ("4. Inserted normally (-1)");
3819   gtk_menu_shell_insert (GTK_MENU_SHELL (menu), menuitem, -1);
3820   gtk_widget_show (menuitem);
3821   
3822   return menu;
3823 }
3824
3825 static void
3826 create_menus (GtkWidget *widget)
3827 {
3828   static GtkWidget *window = NULL;
3829   GtkWidget *box1;
3830   GtkWidget *box2;
3831   GtkWidget *button;
3832   GtkWidget *optionmenu;
3833   GtkWidget *separator;
3834   
3835   if (!window)
3836     {
3837       GtkWidget *menubar;
3838       GtkWidget *menu;
3839       GtkWidget *menuitem;
3840       GtkAccelGroup *accel_group;
3841       GtkWidget *image;
3842       GdkScreen *screen = gtk_widget_get_screen (widget);
3843       
3844       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
3845
3846       gtk_window_set_screen (GTK_WINDOW (window), screen);
3847       
3848       g_signal_connect (window, "destroy",
3849                         G_CALLBACK (gtk_widget_destroyed),
3850                         &window);
3851       g_signal_connect (window, "delete-event",
3852                         G_CALLBACK (gtk_true),
3853                         NULL);
3854       
3855       accel_group = gtk_accel_group_new ();
3856       gtk_window_add_accel_group (GTK_WINDOW (window), accel_group);
3857
3858       gtk_window_set_title (GTK_WINDOW (window), "menus");
3859       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
3860       
3861       
3862       box1 = gtk_vbox_new (FALSE, 0);
3863       gtk_container_add (GTK_CONTAINER (window), box1);
3864       gtk_widget_show (box1);
3865       
3866       menubar = gtk_menu_bar_new ();
3867       gtk_box_pack_start (GTK_BOX (box1), menubar, FALSE, TRUE, 0);
3868       gtk_widget_show (menubar);
3869       
3870       menu = create_menu (screen, 2, 50, TRUE);
3871       
3872       menuitem = gtk_menu_item_new_with_label ("test\nline2");
3873       gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), menu);
3874       gtk_menu_shell_append (GTK_MENU_SHELL (menubar), menuitem);
3875       gtk_widget_show (menuitem);
3876
3877       menu = create_table_menu (screen, 2, 50, TRUE);
3878       
3879       menuitem = gtk_menu_item_new_with_label ("table");
3880       gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), menu);
3881       gtk_menu_shell_append (GTK_MENU_SHELL (menubar), menuitem);
3882       gtk_widget_show (menuitem);
3883       
3884       menuitem = gtk_menu_item_new_with_label ("foo");
3885       gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), create_menu (screen, 3, 5, TRUE));
3886       gtk_menu_shell_append (GTK_MENU_SHELL (menubar), menuitem);
3887       gtk_widget_show (menuitem);
3888
3889       image = gtk_image_new_from_stock (GTK_STOCK_HELP,
3890                                         GTK_ICON_SIZE_MENU);
3891       gtk_widget_show (image);
3892       menuitem = gtk_image_menu_item_new_with_label ("Help");
3893       gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), image);
3894       gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), create_menu (screen, 4, 5, TRUE));
3895       gtk_menu_item_set_right_justified (GTK_MENU_ITEM (menuitem), TRUE);
3896       gtk_menu_shell_append (GTK_MENU_SHELL (menubar), menuitem);
3897       gtk_widget_show (menuitem);
3898       
3899       menubar = gtk_menu_bar_new ();
3900       gtk_box_pack_start (GTK_BOX (box1), menubar, FALSE, TRUE, 0);
3901       gtk_widget_show (menubar);
3902       
3903       menu = create_menu (screen, 2, 10, TRUE);
3904       
3905       menuitem = gtk_menu_item_new_with_label ("Second menu bar");
3906       gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), menu);
3907       gtk_menu_shell_append (GTK_MENU_SHELL (menubar), menuitem);
3908       gtk_widget_show (menuitem);
3909       
3910       box2 = gtk_vbox_new (FALSE, 10);
3911       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
3912       gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
3913       gtk_widget_show (box2);
3914       
3915       menu = create_menu (screen, 1, 5, FALSE);
3916       gtk_menu_set_accel_group (GTK_MENU (menu), accel_group);
3917
3918       menuitem = gtk_image_menu_item_new_from_stock (GTK_STOCK_NEW, accel_group);
3919       gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
3920       gtk_widget_show (menuitem);
3921       
3922       menuitem = gtk_check_menu_item_new_with_label ("Accelerate Me");
3923       gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
3924       gtk_widget_show (menuitem);
3925       gtk_widget_add_accelerator (menuitem,
3926                                   "activate",
3927                                   accel_group,
3928                                   GDK_F1,
3929                                   0,
3930                                   GTK_ACCEL_VISIBLE);
3931       menuitem = gtk_check_menu_item_new_with_label ("Accelerator Locked");
3932       gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
3933       gtk_widget_show (menuitem);
3934       gtk_widget_add_accelerator (menuitem,
3935                                   "activate",
3936                                   accel_group,
3937                                   GDK_F2,
3938                                   0,
3939                                   GTK_ACCEL_VISIBLE | GTK_ACCEL_LOCKED);
3940       menuitem = gtk_check_menu_item_new_with_label ("Accelerators Frozen");
3941       gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
3942       gtk_widget_show (menuitem);
3943       gtk_widget_add_accelerator (menuitem,
3944                                   "activate",
3945                                   accel_group,
3946                                   GDK_F2,
3947                                   0,
3948                                   GTK_ACCEL_VISIBLE);
3949       gtk_widget_add_accelerator (menuitem,
3950                                   "activate",
3951                                   accel_group,
3952                                   GDK_F3,
3953                                   0,
3954                                   GTK_ACCEL_VISIBLE);
3955       
3956       optionmenu = gtk_combo_box_new_text ();
3957       gtk_combo_box_set_active (GTK_COMBO_BOX (optionmenu), 3);
3958       gtk_box_pack_start (GTK_BOX (box2), optionmenu, TRUE, TRUE, 0);
3959       gtk_widget_show (optionmenu);
3960
3961       separator = gtk_hseparator_new ();
3962       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
3963       gtk_widget_show (separator);
3964
3965       box2 = gtk_vbox_new (FALSE, 10);
3966       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
3967       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
3968       gtk_widget_show (box2);
3969
3970       button = gtk_button_new_with_label ("close");
3971       g_signal_connect_swapped (button, "clicked",
3972                                 G_CALLBACK (gtk_widget_destroy),
3973                                 window);
3974       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
3975       gtk_widget_set_can_default (button, TRUE);
3976       gtk_widget_grab_default (button);
3977       gtk_widget_show (button);
3978     }
3979
3980   if (!gtk_widget_get_visible (window))
3981     gtk_widget_show (window);
3982   else
3983     gtk_widget_destroy (window);
3984 }
3985
3986 /* GdkPixbuf RGBA C-Source image dump */
3987
3988 static const guint8 apple[] = 
3989 { ""
3990   /* Pixbuf magic (0x47646b50) */
3991   "GdkP"
3992   /* length: header (24) + pixel_data (2304) */
3993   "\0\0\11\30"
3994   /* pixdata_type (0x1010002) */
3995   "\1\1\0\2"
3996   /* rowstride (96) */
3997   "\0\0\0`"
3998   /* width (24) */
3999   "\0\0\0\30"
4000   /* height (24) */
4001   "\0\0\0\30"
4002   /* pixel_data: */
4003   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
4004   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
4005   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
4006   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
4007   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
4008   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
4009   "\0\0\0\0\0\0\0\0\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"
4010   "\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"
4011   "\0\0\0\0\0\0\0\0\0\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"
4012   "[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"
4013   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
4014   "\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"
4015   "\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"
4016   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
4017   "\0\0\0\0\0\0`l\\\20iw_\356y\211h\373x\207g\364~\216i\364u\204e\366gt"
4018   "_\374^jX\241A;-_\0\0\0~\0\0\0\0SM4)SM21B9&\22\320\270\204\1\320\270\204"
4019   "\0\0\0\0\0\0\0\0\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"
4020   "]\212r\200c\366v\205f\371jx_\323_kY\232_kZH^jY\26]iW\211@G9\272:6%j\220"
4021   "\211]\320\221\211`\377\212\203Z\377~xP\377mkE\331]^;|/0\37\21\0\0\0\0"
4022   "\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["
4023   "eT<\216\200Z\203\227\211_\354\234\217c\377\232\217b\362\232\220c\337"
4024   "\243\233k\377\252\241p\377\250\236p\377\241\225h\377\231\214_\377\210"
4025   "\202U\377srI\377[]:\355KO0U\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0i"
4026   "v^\200`lY\211^jY\"\0\0\0\0\221\204\\\273\250\233r\377\302\267\224\377"
4027   "\311\300\237\377\272\256\204\377\271\256\177\377\271\257\200\377\267"
4028   "\260\177\377\260\251x\377\250\236l\377\242\225e\377\226\213]\377~zP\377"
4029   "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"
4030   "\0\213\203[v\253\240t\377\334\326\301\377\344\340\317\377\321\312\253"
4031   "\377\303\271\217\377\300\270\213\377\277\267\210\377\272\264\203\377"
4032   "\261\255z\377\250\242n\377\243\232h\377\232\220`\377\210\202V\377nnE"
4033   "\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"
4034   "\234\222e\362\304\274\232\377\337\333\306\377\332\325\273\377\311\302"
4035   "\232\377\312\303\236\377\301\273\216\377\300\271\212\377\270\264\200"
4036   "\377\256\253v\377\246\243n\377\236\232h\377\230\220`\377\213\203V\377"
4037   "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"
4038   "\203Zl\242\234l\377\321\315\260\377\331\324\271\377\320\313\251\377\307"
4039   "\301\232\377\303\276\224\377\300\272\214\377\274\267\206\377\264\260"
4040   "|\377\253\251s\377\244\243n\377\232\230e\377\223\216^\377\207\200U\377"
4041   "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"
4042   "\210\204Y\240\245\237o\377\316\310\253\377\310\303\237\377\304\300\230"
4043   "\377\303\277\225\377\277\272\216\377\274\270\210\377\266\263\200\377"
4044   "\256\254v\377\247\246p\377\237\236j\377\227\226d\377\215\212[\377\203"
4045   "\177T\377qsH\377X]8\377FN.\377DK-\200\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
4046   "\0\0\0\0\207\204X\257\244\240o\377\300\275\231\377\301\275\226\377\274"
4047   "\270\213\377\274\270\214\377\267\264\205\377\264\262\200\377\260\256"
4048   "z\377\251\251s\377\243\244n\377\231\232g\377\220\222`\377\210\211Y\377"
4049   "|}Q\377hlC\377PU3\377CK,\377DL/Y\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
4050   "\0\0\205\204X\220\232\230h\377\261\260\204\377\266\264\212\377\261\260"
4051   "\201\377\263\260\200\377\260\257}\377\256\256x\377\253\254t\377\244\246"
4052   "o\377\233\236i\377\221\224b\377\211\214\\\377\202\204V\377txM\377]b>"
4053   "\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>"
4054   "\215\215_\377\237\237r\377\247\247x\377\247\247t\377\252\252w\377\252"
4055   "\252u\377\252\253t\377\243\246o\377\235\240j\377\223\230c\377\213\217"
4056   "]\377\201\206V\377x}P\377gkD\377RY5\377BI,\377AI,\262\0\0\0\0\0\0\0\0"
4057   "\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"
4058   "\232g\377\234\236i\377\236\241l\377\241\244n\377\240\244m\377\232\237"
4059   "i\377\223\230c\377\212\221]\377\200\210W\377v|P\377jnG\377Za>\377HP2"
4060   "\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"
4061   "\0wzQ6\177\201U\371\206\211Z\377\216\222`\377\220\225a\377\220\225b\377"
4062   "\220\226a\377\213\221_\377\204\213Z\377{\203R\377ryN\377iqH\377^fA\377"
4063   "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"
4064   "\0\0\0\0\0\0\0\0\0\0\0\0ptJTw|Q\371z\177R\377}\202T\377|\203T\377z\200"
4065   "R\377v|O\377pwL\377jpF\377dlB\377`hB\377Yb@\377LT6\377<C*\377\11\12\6"
4066   "\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"
4067   "\0\0\0\0\0\0\0\0\0\0\\`=UgnE\370hnG\377gmE\377djB\377]d>\377[c<\377Y"
4068   "b<\377Zc>\377V_>\377OW8\377BK/\377\16\20\12\377\0\0\0\377\0\0\0\377\0"
4069   "\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"
4070   "\0\1\0\0\0\40\22\24\15\260@D+\377W`;\377OV5\377.3\36\377.3\37\377IP0"
4071   "\377RZ7\377PZ8\3776=&\377\14\15\10\377\0\0\0\377\0\0\0\377\0\0\0\377"
4072   "\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"
4073   "\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"
4074   "\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"
4075   "\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"
4076   "\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"
4077   "\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"
4078   "\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"
4079   "\0\0\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"
4080   "\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"
4081   "\0\0\5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"};
4082
4083
4084 static void
4085 dump_accels (gpointer             callback_data,
4086              guint                callback_action,
4087              GtkWidget           *widget)
4088 {
4089   gtk_accel_map_save_fd (1 /* stdout */);
4090 }
4091
4092 static GtkWidget *
4093 accel_button_new (GtkAccelGroup *accel_group,
4094                   const gchar   *text,
4095                   const gchar   *accel)
4096 {
4097   guint keyval;
4098   GdkModifierType modifiers;
4099   GtkWidget *button;
4100   GtkWidget *label;
4101
4102   gtk_accelerator_parse (accel, &keyval, &modifiers);
4103   g_assert (keyval);
4104
4105   button = gtk_button_new ();
4106   gtk_widget_add_accelerator (button, "activate", accel_group,
4107                               keyval, modifiers, GTK_ACCEL_VISIBLE | GTK_ACCEL_LOCKED);
4108
4109   label = gtk_accel_label_new (text);
4110   gtk_accel_label_set_accel_widget (GTK_ACCEL_LABEL (label), button);
4111   gtk_widget_show (label);
4112   
4113   gtk_container_add (GTK_CONTAINER (button), label);
4114
4115   return button;
4116 }
4117
4118 static void
4119 create_key_lookup (GtkWidget *widget)
4120 {
4121   static GtkWidget *window = NULL;
4122   gpointer window_ptr;
4123
4124   if (!window)
4125     {
4126       GtkAccelGroup *accel_group = gtk_accel_group_new ();
4127       GtkWidget *button;
4128       
4129       window = gtk_dialog_new_with_buttons ("Key Lookup", NULL, 0,
4130                                             GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
4131                                             NULL);
4132
4133       gtk_window_set_screen (GTK_WINDOW (window),
4134                              gtk_widget_get_screen (widget));
4135
4136       /* We have to expand it so the accel labels will draw their labels
4137        */
4138       gtk_window_set_default_size (GTK_WINDOW (window), 300, -1);
4139       
4140       gtk_window_add_accel_group (GTK_WINDOW (window), accel_group);
4141       
4142       button = gtk_button_new_with_mnemonic ("Button 1 (_a)");
4143       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
4144       button = gtk_button_new_with_mnemonic ("Button 2 (_A)");
4145       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
4146       button = gtk_button_new_with_mnemonic ("Button 3 (_\321\204)");
4147       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
4148       button = gtk_button_new_with_mnemonic ("Button 4 (_\320\244)");
4149       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
4150       button = gtk_button_new_with_mnemonic ("Button 6 (_b)");
4151       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
4152       button = accel_button_new (accel_group, "Button 7", "<Alt><Shift>b");
4153       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
4154       button = accel_button_new (accel_group, "Button 8", "<Alt>d");
4155       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
4156       button = accel_button_new (accel_group, "Button 9", "<Alt>Cyrillic_ve");
4157       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
4158       button = gtk_button_new_with_mnemonic ("Button 10 (_1)");
4159       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
4160       button = gtk_button_new_with_mnemonic ("Button 11 (_!)");
4161       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
4162       button = accel_button_new (accel_group, "Button 12", "<Super>a");
4163       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
4164       button = accel_button_new (accel_group, "Button 13", "<Hyper>a");
4165       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
4166       button = accel_button_new (accel_group, "Button 14", "<Meta>a");
4167       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
4168       button = accel_button_new (accel_group, "Button 15", "<Shift><Mod4>b");
4169       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
4170
4171       window_ptr = &window;
4172       g_object_add_weak_pointer (G_OBJECT (window), window_ptr);
4173       g_signal_connect (window, "response", G_CALLBACK (gtk_object_destroy), NULL);
4174
4175       gtk_widget_show_all (window);
4176     }
4177   else
4178     gtk_widget_destroy (window);
4179 }
4180
4181
4182 /*
4183  create_modal_window
4184  */
4185
4186 static gboolean
4187 cmw_destroy_cb(GtkWidget *widget)
4188 {
4189   /* This is needed to get out of gtk_main */
4190   gtk_main_quit ();
4191
4192   return FALSE;
4193 }
4194
4195 static void
4196 cmw_color (GtkWidget *widget, GtkWidget *parent)
4197 {
4198     GtkWidget *csd;
4199
4200     csd = gtk_color_selection_dialog_new ("This is a modal color selection dialog");
4201
4202     gtk_window_set_screen (GTK_WINDOW (csd), gtk_widget_get_screen (parent));
4203
4204     gtk_color_selection_set_has_palette (GTK_COLOR_SELECTION (GTK_COLOR_SELECTION_DIALOG (csd)->colorsel),
4205                                          TRUE);
4206     
4207     /* Set as modal */
4208     gtk_window_set_modal (GTK_WINDOW(csd),TRUE);
4209
4210     /* And mark it as a transient dialog */
4211     gtk_window_set_transient_for (GTK_WINDOW (csd), GTK_WINDOW (parent));
4212     
4213     g_signal_connect (csd, "destroy",
4214                       G_CALLBACK (cmw_destroy_cb), NULL);
4215
4216     g_signal_connect_swapped (GTK_COLOR_SELECTION_DIALOG (csd)->ok_button,
4217                              "clicked", G_CALLBACK (gtk_widget_destroy), csd);
4218     g_signal_connect_swapped (GTK_COLOR_SELECTION_DIALOG (csd)->cancel_button,
4219                              "clicked", G_CALLBACK (gtk_widget_destroy), csd);
4220     
4221     /* wait until destroy calls gtk_main_quit */
4222     gtk_widget_show (csd);    
4223     gtk_main ();
4224 }
4225
4226 static void
4227 cmw_file (GtkWidget *widget, GtkWidget *parent)
4228 {
4229     GtkWidget *fs;
4230
4231     fs = gtk_file_selection_new("This is a modal file selection dialog");
4232
4233     gtk_window_set_screen (GTK_WINDOW (fs), gtk_widget_get_screen (parent));
4234
4235     /* Set as modal */
4236     gtk_window_set_modal (GTK_WINDOW(fs),TRUE);
4237
4238     /* And mark it as a transient dialog */
4239     gtk_window_set_transient_for (GTK_WINDOW (fs), GTK_WINDOW (parent));
4240
4241     g_signal_connect (fs, "destroy",
4242                       G_CALLBACK (cmw_destroy_cb), NULL);
4243
4244     g_signal_connect_swapped (GTK_FILE_SELECTION (fs)->ok_button,
4245                               "clicked", G_CALLBACK (gtk_widget_destroy), fs);
4246     g_signal_connect_swapped (GTK_FILE_SELECTION (fs)->cancel_button,
4247                               "clicked", G_CALLBACK (gtk_widget_destroy), fs);
4248     
4249     /* wait until destroy calls gtk_main_quit */
4250     gtk_widget_show (fs);
4251     
4252     gtk_main();
4253 }
4254
4255
4256 static void
4257 create_modal_window (GtkWidget *widget)
4258 {
4259   GtkWidget *window = NULL;
4260   GtkWidget *box1,*box2;
4261   GtkWidget *frame1;
4262   GtkWidget *btnColor,*btnFile,*btnClose;
4263
4264   /* Create modal window (Here you can use any window descendent )*/
4265   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
4266   gtk_window_set_screen (GTK_WINDOW (window),
4267                          gtk_widget_get_screen (widget));
4268
4269   gtk_window_set_title (GTK_WINDOW(window),"This window is modal");
4270
4271   /* Set window as modal */
4272   gtk_window_set_modal (GTK_WINDOW(window),TRUE);
4273
4274   /* Create widgets */
4275   box1 = gtk_vbox_new (FALSE,5);
4276   frame1 = gtk_frame_new ("Standard dialogs in modal form");
4277   box2 = gtk_vbox_new (TRUE,5);
4278   btnColor = gtk_button_new_with_label ("Color");
4279   btnFile = gtk_button_new_with_label ("File Selection");
4280   btnClose = gtk_button_new_with_label ("Close");
4281
4282   /* Init widgets */
4283   gtk_container_set_border_width (GTK_CONTAINER (box1), 3);
4284   gtk_container_set_border_width (GTK_CONTAINER (box2), 3);
4285     
4286   /* Pack widgets */
4287   gtk_container_add (GTK_CONTAINER (window), box1);
4288   gtk_box_pack_start (GTK_BOX (box1), frame1, TRUE, TRUE, 4);
4289   gtk_container_add (GTK_CONTAINER (frame1), box2);
4290   gtk_box_pack_start (GTK_BOX (box2), btnColor, FALSE, FALSE, 4);
4291   gtk_box_pack_start (GTK_BOX (box2), btnFile, FALSE, FALSE, 4);
4292   gtk_box_pack_start (GTK_BOX (box1), gtk_hseparator_new (), FALSE, FALSE, 4);
4293   gtk_box_pack_start (GTK_BOX (box1), btnClose, FALSE, FALSE, 4);
4294    
4295   /* connect signals */
4296   g_signal_connect_swapped (btnClose, "clicked",
4297                             G_CALLBACK (gtk_widget_destroy), window);
4298
4299   g_signal_connect (window, "destroy",
4300                     G_CALLBACK (cmw_destroy_cb), NULL);
4301   
4302   g_signal_connect (btnColor, "clicked",
4303                     G_CALLBACK (cmw_color), window);
4304   g_signal_connect (btnFile, "clicked",
4305                     G_CALLBACK (cmw_file), window);
4306
4307   /* Show widgets */
4308   gtk_widget_show_all (window);
4309
4310   /* wait until dialog get destroyed */
4311   gtk_main();
4312 }
4313
4314 /*
4315  * GtkMessageDialog
4316  */
4317
4318 static void
4319 make_message_dialog (GdkScreen *screen,
4320                      GtkWidget **dialog,
4321                      GtkMessageType  type,
4322                      GtkButtonsType  buttons,
4323                      guint           default_response)
4324 {
4325   if (*dialog)
4326     {
4327       gtk_widget_destroy (*dialog);
4328
4329       return;
4330     }
4331
4332   *dialog = gtk_message_dialog_new (NULL, 0, type, buttons,
4333                                     "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.)");
4334
4335   gtk_window_set_screen (GTK_WINDOW (*dialog), screen);
4336
4337   g_signal_connect_swapped (*dialog,
4338                             "response",
4339                             G_CALLBACK (gtk_widget_destroy),
4340                             *dialog);
4341   
4342   g_signal_connect (*dialog,
4343                     "destroy",
4344                     G_CALLBACK (gtk_widget_destroyed),
4345                     dialog);
4346
4347   gtk_dialog_set_default_response (GTK_DIALOG (*dialog), default_response);
4348
4349   gtk_widget_show (*dialog);
4350 }
4351
4352 static void
4353 create_message_dialog (GtkWidget *widget)
4354 {
4355   static GtkWidget *info = NULL;
4356   static GtkWidget *warning = NULL;
4357   static GtkWidget *error = NULL;
4358   static GtkWidget *question = NULL;
4359   GdkScreen *screen = gtk_widget_get_screen (widget);
4360
4361   make_message_dialog (screen, &info, GTK_MESSAGE_INFO, GTK_BUTTONS_OK, GTK_RESPONSE_OK);
4362   make_message_dialog (screen, &warning, GTK_MESSAGE_WARNING, GTK_BUTTONS_CLOSE, GTK_RESPONSE_CLOSE);
4363   make_message_dialog (screen, &error, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK_CANCEL, GTK_RESPONSE_OK);
4364   make_message_dialog (screen, &question, GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO, GTK_RESPONSE_NO);
4365 }
4366
4367 /*
4368  * GtkScrolledWindow
4369  */
4370
4371 static GtkWidget *sw_parent = NULL;
4372 static GtkWidget *sw_float_parent;
4373 static guint sw_destroyed_handler = 0;
4374
4375 static gboolean
4376 scrolled_windows_delete_cb (GtkWidget *widget, GdkEventAny *event, GtkWidget *scrollwin)
4377 {
4378   gtk_widget_reparent (scrollwin, sw_parent);
4379   
4380   g_signal_handler_disconnect (sw_parent, sw_destroyed_handler);
4381   sw_float_parent = NULL;
4382   sw_parent = NULL;
4383   sw_destroyed_handler = 0;
4384
4385   return FALSE;
4386 }
4387
4388 static void
4389 scrolled_windows_destroy_cb (GtkWidget *widget, GtkWidget *scrollwin)
4390 {
4391   gtk_widget_destroy (sw_float_parent);
4392
4393   sw_float_parent = NULL;
4394   sw_parent = NULL;
4395   sw_destroyed_handler = 0;
4396 }
4397
4398 static void
4399 scrolled_windows_remove (GtkWidget *widget, GtkWidget *scrollwin)
4400 {
4401   if (sw_parent)
4402     {
4403       gtk_widget_reparent (scrollwin, sw_parent);
4404       gtk_widget_destroy (sw_float_parent);
4405
4406       g_signal_handler_disconnect (sw_parent, sw_destroyed_handler);
4407       sw_float_parent = NULL;
4408       sw_parent = NULL;
4409       sw_destroyed_handler = 0;
4410     }
4411   else
4412     {
4413       sw_parent = scrollwin->parent;
4414       sw_float_parent = gtk_window_new (GTK_WINDOW_TOPLEVEL);
4415       gtk_window_set_screen (GTK_WINDOW (sw_float_parent),
4416                              gtk_widget_get_screen (widget));
4417       
4418       gtk_window_set_default_size (GTK_WINDOW (sw_float_parent), 200, 200);
4419       
4420       gtk_widget_reparent (scrollwin, sw_float_parent);
4421       gtk_widget_show (sw_float_parent);
4422
4423       sw_destroyed_handler =
4424         g_signal_connect (sw_parent, "destroy",
4425                           G_CALLBACK (scrolled_windows_destroy_cb), scrollwin);
4426       g_signal_connect (sw_float_parent, "delete_event",
4427                         G_CALLBACK (scrolled_windows_delete_cb), scrollwin);
4428     }
4429 }
4430
4431 static void
4432 create_scrolled_windows (GtkWidget *widget)
4433 {
4434   static GtkWidget *window;
4435   GtkWidget *scrolled_window;
4436   GtkWidget *table;
4437   GtkWidget *button;
4438   char buffer[32];
4439   int i, j;
4440
4441   if (!window)
4442     {
4443       window = gtk_dialog_new ();
4444
4445       gtk_window_set_screen (GTK_WINDOW (window),
4446                              gtk_widget_get_screen (widget));
4447
4448       g_signal_connect (window, "destroy",
4449                         G_CALLBACK (gtk_widget_destroyed),
4450                         &window);
4451
4452       gtk_window_set_title (GTK_WINDOW (window), "dialog");
4453       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
4454
4455
4456       scrolled_window = gtk_scrolled_window_new (NULL, NULL);
4457       gtk_container_set_border_width (GTK_CONTAINER (scrolled_window), 10);
4458       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
4459                                       GTK_POLICY_AUTOMATIC,
4460                                       GTK_POLICY_AUTOMATIC);
4461       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
4462                           scrolled_window, TRUE, TRUE, 0);
4463       gtk_widget_show (scrolled_window);
4464
4465       table = gtk_table_new (20, 20, FALSE);
4466       gtk_table_set_row_spacings (GTK_TABLE (table), 10);
4467       gtk_table_set_col_spacings (GTK_TABLE (table), 10);
4468       gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_window), table);
4469       gtk_container_set_focus_hadjustment (GTK_CONTAINER (table),
4470                                            gtk_scrolled_window_get_hadjustment (GTK_SCROLLED_WINDOW (scrolled_window)));
4471       gtk_container_set_focus_vadjustment (GTK_CONTAINER (table),
4472                                            gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (scrolled_window)));
4473       gtk_widget_show (table);
4474
4475       for (i = 0; i < 20; i++)
4476         for (j = 0; j < 20; j++)
4477           {
4478             sprintf (buffer, "button (%d,%d)\n", i, j);
4479             button = gtk_toggle_button_new_with_label (buffer);
4480             gtk_table_attach_defaults (GTK_TABLE (table), button,
4481                                        i, i+1, j, j+1);
4482             gtk_widget_show (button);
4483           }
4484
4485
4486       button = gtk_button_new_with_label ("Close");
4487       g_signal_connect_swapped (button, "clicked",
4488                                 G_CALLBACK (gtk_widget_destroy),
4489                                 window);
4490       gtk_widget_set_can_default (button, TRUE);
4491       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
4492                           button, TRUE, TRUE, 0);
4493       gtk_widget_grab_default (button);
4494       gtk_widget_show (button);
4495
4496       button = gtk_button_new_with_label ("Reparent Out");
4497       g_signal_connect (button, "clicked",
4498                         G_CALLBACK (scrolled_windows_remove),
4499                         scrolled_window);
4500       gtk_widget_set_can_default (button, TRUE);
4501       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
4502                           button, TRUE, TRUE, 0);
4503       gtk_widget_grab_default (button);
4504       gtk_widget_show (button);
4505
4506       gtk_window_set_default_size (GTK_WINDOW (window), 300, 300);
4507     }
4508
4509   if (!gtk_widget_get_visible (window))
4510     gtk_widget_show (window);
4511   else
4512     gtk_widget_destroy (window);
4513 }
4514
4515 /*
4516  * GtkEntry
4517  */
4518
4519 static void
4520 entry_toggle_frame (GtkWidget *checkbutton,
4521                     GtkWidget *entry)
4522 {
4523    gtk_entry_set_has_frame (GTK_ENTRY(entry),
4524                             GTK_TOGGLE_BUTTON(checkbutton)->active);
4525 }
4526
4527 static void
4528 entry_toggle_sensitive (GtkWidget *checkbutton,
4529                         GtkWidget *entry)
4530 {
4531    gtk_widget_set_sensitive (entry, GTK_TOGGLE_BUTTON(checkbutton)->active);
4532 }
4533
4534 static gboolean
4535 entry_progress_timeout (gpointer data)
4536 {
4537   if (GPOINTER_TO_INT (g_object_get_data (G_OBJECT (data), "progress-pulse")))
4538     {
4539       gtk_entry_progress_pulse (GTK_ENTRY (data));
4540     }
4541   else
4542     {
4543       gdouble fraction;
4544
4545       fraction = gtk_entry_get_progress_fraction (GTK_ENTRY (data));
4546
4547       fraction += 0.05;
4548       if (fraction > 1.0001)
4549         fraction = 0.0;
4550
4551       gtk_entry_set_progress_fraction (GTK_ENTRY (data), fraction);
4552     }
4553
4554   return TRUE;
4555 }
4556
4557 static void
4558 entry_remove_timeout (gpointer data)
4559 {
4560   g_source_remove (GPOINTER_TO_UINT (data));
4561 }
4562
4563 static void
4564 entry_toggle_progress (GtkWidget *checkbutton,
4565                        GtkWidget *entry)
4566 {
4567   if (GTK_TOGGLE_BUTTON (checkbutton)->active)
4568     {
4569       guint timeout = gdk_threads_add_timeout (100,
4570                                                entry_progress_timeout,
4571                                                entry);
4572       g_object_set_data_full (G_OBJECT (entry), "timeout-id",
4573                               GUINT_TO_POINTER (timeout),
4574                               entry_remove_timeout);
4575     }
4576   else
4577     {
4578       g_object_set_data (G_OBJECT (entry), "timeout-id",
4579                          GUINT_TO_POINTER (0));
4580
4581       gtk_entry_set_progress_fraction (GTK_ENTRY (entry), 0.0);
4582     }
4583 }
4584
4585 static void
4586 entry_toggle_pulse (GtkWidget *checkbutton,
4587                     GtkWidget *entry)
4588 {
4589   g_object_set_data (G_OBJECT (entry), "progress-pulse",
4590                      GUINT_TO_POINTER ((guint) GTK_TOGGLE_BUTTON (checkbutton)->active));
4591 }
4592
4593 static void
4594 props_clicked (GtkWidget *button,
4595                GObject   *object)
4596 {
4597   GtkWidget *window = create_prop_editor (object, 0);
4598
4599   gtk_window_set_title (GTK_WINDOW (window), "Object Properties");
4600 }
4601
4602 static void
4603 create_entry (GtkWidget *widget)
4604 {
4605   static GtkWidget *window = NULL;
4606   GtkWidget *box1;
4607   GtkWidget *box2;
4608   GtkWidget *hbox;
4609   GtkWidget *has_frame_check;
4610   GtkWidget *sensitive_check;
4611   GtkWidget *progress_check;
4612   GtkWidget *entry;
4613   GtkComboBox *cb;
4614   GtkWidget *cb_entry;
4615   GtkWidget *button;
4616   GtkWidget *separator;
4617
4618   if (!window)
4619     {
4620       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
4621       gtk_window_set_screen (GTK_WINDOW (window),
4622                              gtk_widget_get_screen (widget));
4623
4624       g_signal_connect (window, "destroy",
4625                         G_CALLBACK (gtk_widget_destroyed),
4626                         &window);
4627
4628       gtk_window_set_title (GTK_WINDOW (window), "entry");
4629       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
4630
4631
4632       box1 = gtk_vbox_new (FALSE, 0);
4633       gtk_container_add (GTK_CONTAINER (window), box1);
4634
4635
4636       box2 = gtk_vbox_new (FALSE, 10);
4637       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
4638       gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
4639
4640       hbox = gtk_hbox_new (FALSE, 5);
4641       gtk_box_pack_start (GTK_BOX (box2), hbox, TRUE, TRUE, 0);
4642       
4643       entry = gtk_entry_new ();
4644       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");
4645       gtk_editable_select_region (GTK_EDITABLE (entry), 0, 5);
4646       gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0);
4647
4648       button = gtk_button_new_with_mnemonic ("_Props");
4649       gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
4650       g_signal_connect (button, "clicked",
4651                         G_CALLBACK (props_clicked),
4652                         entry);
4653
4654       cb = GTK_COMBO_BOX (gtk_combo_box_entry_new_text ());
4655       gtk_combo_box_append_text (cb, "item0");
4656       gtk_combo_box_append_text (cb, "item0");
4657       gtk_combo_box_append_text (cb, "item1 item1");
4658       gtk_combo_box_append_text (cb, "item2 item2 item2");
4659       gtk_combo_box_append_text (cb, "item3 item3 item3 item3");
4660       gtk_combo_box_append_text (cb, "item4 item4 item4 item4 item4");
4661       gtk_combo_box_append_text (cb, "item5 item5 item5 item5 item5 item5");
4662       gtk_combo_box_append_text (cb, "item6 item6 item6 item6 item6");
4663       gtk_combo_box_append_text (cb, "item7 item7 item7 item7");
4664       gtk_combo_box_append_text (cb, "item8 item8 item8");
4665       gtk_combo_box_append_text (cb, "item9 item9");
4666
4667       cb_entry = gtk_bin_get_child (GTK_BIN (cb));
4668       gtk_entry_set_text (GTK_ENTRY (cb_entry), "hello world \n\n\n foo");
4669       gtk_editable_select_region (GTK_EDITABLE (cb_entry), 0, -1);
4670       gtk_box_pack_start (GTK_BOX (box2), GTK_WIDGET (cb), TRUE, TRUE, 0);
4671
4672       sensitive_check = gtk_check_button_new_with_label("Sensitive");
4673       gtk_box_pack_start (GTK_BOX (box2), sensitive_check, FALSE, TRUE, 0);
4674       g_signal_connect (sensitive_check, "toggled",
4675                         G_CALLBACK (entry_toggle_sensitive), entry);
4676       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sensitive_check), TRUE);
4677
4678       has_frame_check = gtk_check_button_new_with_label("Has Frame");
4679       gtk_box_pack_start (GTK_BOX (box2), has_frame_check, FALSE, TRUE, 0);
4680       g_signal_connect (has_frame_check, "toggled",
4681                         G_CALLBACK (entry_toggle_frame), entry);
4682       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (has_frame_check), TRUE);
4683
4684       progress_check = gtk_check_button_new_with_label("Show Progress");
4685       gtk_box_pack_start (GTK_BOX (box2), progress_check, FALSE, TRUE, 0);
4686       g_signal_connect (progress_check, "toggled",
4687                         G_CALLBACK (entry_toggle_progress), entry);
4688
4689       progress_check = gtk_check_button_new_with_label("Pulse Progress");
4690       gtk_box_pack_start (GTK_BOX (box2), progress_check, FALSE, TRUE, 0);
4691       g_signal_connect (progress_check, "toggled",
4692                         G_CALLBACK (entry_toggle_pulse), entry);
4693
4694       separator = gtk_hseparator_new ();
4695       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
4696
4697       box2 = gtk_vbox_new (FALSE, 10);
4698       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
4699       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
4700
4701       button = gtk_button_new_with_label ("close");
4702       g_signal_connect_swapped (button, "clicked",
4703                                 G_CALLBACK (gtk_widget_destroy),
4704                                 window);
4705       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
4706       gtk_widget_set_can_default (button, TRUE);
4707       gtk_widget_grab_default (button);
4708     }
4709
4710   if (!gtk_widget_get_visible (window))
4711     gtk_widget_show_all (window);
4712   else
4713     gtk_widget_destroy (window);
4714 }
4715
4716 static void
4717 create_expander (GtkWidget *widget)
4718 {
4719   GtkWidget *box1;
4720   GtkWidget *expander;
4721   GtkWidget *hidden;
4722   static GtkWidget *window = NULL;
4723
4724   if (!window)
4725     {
4726       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
4727       gtk_window_set_screen (GTK_WINDOW (window),
4728                              gtk_widget_get_screen (widget));
4729       
4730       g_signal_connect (window, "destroy",
4731                         G_CALLBACK (gtk_widget_destroyed),
4732                         &window);
4733       
4734       gtk_window_set_title (GTK_WINDOW (window), "expander");
4735       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
4736       
4737       box1 = gtk_vbox_new (FALSE, 0);
4738       gtk_container_add (GTK_CONTAINER (window), box1);
4739       
4740       expander = gtk_expander_new ("The Hidden");
4741       
4742       gtk_box_pack_start (GTK_BOX (box1), expander, TRUE, TRUE, 0);
4743       
4744       hidden = gtk_label_new ("Revealed!");
4745       
4746       gtk_container_add (GTK_CONTAINER (expander), hidden);
4747     }
4748   
4749   if (!gtk_widget_get_visible (window))
4750     gtk_widget_show_all (window);
4751   else
4752     gtk_widget_destroy (window);
4753 }
4754
4755
4756 /* GtkEventBox */
4757
4758
4759 static void
4760 event_box_label_pressed (GtkWidget        *widget,
4761                          GdkEventButton   *event,
4762                          gpointer user_data)
4763 {
4764   g_print ("clicked on event box\n");
4765 }
4766
4767 static void
4768 event_box_button_clicked (GtkWidget *widget,
4769                           GtkWidget *button,
4770                           gpointer user_data)
4771 {
4772   g_print ("pushed button\n");
4773 }
4774
4775 static void
4776 event_box_toggle_visible_window (GtkWidget *checkbutton,
4777                                  GtkEventBox *event_box)
4778 {
4779   gtk_event_box_set_visible_window (event_box,
4780                                     GTK_TOGGLE_BUTTON(checkbutton)->active);
4781 }
4782
4783 static void
4784 event_box_toggle_above_child (GtkWidget *checkbutton,
4785                               GtkEventBox *event_box)
4786 {
4787   gtk_event_box_set_above_child (event_box,
4788                                  GTK_TOGGLE_BUTTON(checkbutton)->active);
4789 }
4790
4791 static void
4792 create_event_box (GtkWidget *widget)
4793 {
4794   static GtkWidget *window = NULL;
4795   GtkWidget *box1;
4796   GtkWidget *box2;
4797   GtkWidget *hbox;
4798   GtkWidget *vbox;
4799   GtkWidget *button;
4800   GtkWidget *separator;
4801   GtkWidget *event_box;
4802   GtkWidget *label;
4803   GtkWidget *visible_window_check;
4804   GtkWidget *above_child_check;
4805   GdkColor color;
4806
4807   if (!window)
4808     {
4809       color.red = 0;
4810       color.blue = 65535;
4811       color.green = 0;
4812       
4813       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
4814       gtk_window_set_screen (GTK_WINDOW (window),
4815                              gtk_widget_get_screen (widget));
4816
4817       g_signal_connect (window, "destroy",
4818                         G_CALLBACK (gtk_widget_destroyed),
4819                         &window);
4820
4821       gtk_window_set_title (GTK_WINDOW (window), "event box");
4822       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
4823
4824       box1 = gtk_vbox_new (FALSE, 0);
4825       gtk_container_add (GTK_CONTAINER (window), box1);
4826       gtk_widget_modify_bg (window, GTK_STATE_NORMAL, &color);
4827
4828       hbox = gtk_hbox_new (FALSE, 0);
4829       gtk_box_pack_start (GTK_BOX (box1), hbox, TRUE, FALSE, 0);
4830       
4831       event_box = gtk_event_box_new ();
4832       gtk_box_pack_start (GTK_BOX (hbox), event_box, TRUE, FALSE, 0);
4833
4834       vbox = gtk_vbox_new (FALSE, 0);
4835       gtk_container_add (GTK_CONTAINER (event_box), vbox);
4836       g_signal_connect (event_box, "button_press_event",
4837                         G_CALLBACK (event_box_label_pressed),
4838                         NULL);
4839       
4840       label = gtk_label_new ("Click on this label");
4841       gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, FALSE, 0);
4842
4843       button = gtk_button_new_with_label ("button in eventbox");
4844       gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, FALSE, 0);
4845       g_signal_connect (button, "clicked",
4846                         G_CALLBACK (event_box_button_clicked),
4847                         NULL);
4848       
4849
4850       visible_window_check = gtk_check_button_new_with_label("Visible Window");
4851       gtk_box_pack_start (GTK_BOX (box1), visible_window_check, FALSE, TRUE, 0);
4852       g_signal_connect (visible_window_check, "toggled",
4853                         G_CALLBACK (event_box_toggle_visible_window), event_box);
4854       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (visible_window_check), FALSE);
4855       
4856       above_child_check = gtk_check_button_new_with_label("Above Child");
4857       gtk_box_pack_start (GTK_BOX (box1), above_child_check, FALSE, TRUE, 0);
4858       g_signal_connect (above_child_check, "toggled",
4859                         G_CALLBACK (event_box_toggle_above_child), event_box);
4860       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (above_child_check), FALSE);
4861       
4862       separator = gtk_hseparator_new ();
4863       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
4864
4865       box2 = gtk_vbox_new (FALSE, 10);
4866       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
4867       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
4868
4869       button = gtk_button_new_with_label ("close");
4870       g_signal_connect_swapped (button, "clicked",
4871                                 G_CALLBACK (gtk_widget_destroy),
4872                                 window);
4873       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
4874       gtk_widget_set_can_default (button, TRUE);
4875       gtk_widget_grab_default (button);
4876     }
4877
4878   if (!gtk_widget_get_visible (window))
4879     gtk_widget_show_all (window);
4880   else
4881     gtk_widget_destroy (window);
4882 }
4883
4884
4885 /*
4886  * GtkSizeGroup
4887  */
4888
4889 #define SIZE_GROUP_INITIAL_SIZE 50
4890
4891 static void
4892 size_group_hsize_changed (GtkSpinButton *spin_button,
4893                           GtkWidget     *button)
4894 {
4895   gtk_widget_set_size_request (GTK_BIN (button)->child,
4896                                gtk_spin_button_get_value_as_int (spin_button),
4897                                -1);
4898 }
4899
4900 static void
4901 size_group_vsize_changed (GtkSpinButton *spin_button,
4902                           GtkWidget     *button)
4903 {
4904   gtk_widget_set_size_request (GTK_BIN (button)->child,
4905                                -1,
4906                                gtk_spin_button_get_value_as_int (spin_button));
4907 }
4908
4909 static GtkWidget *
4910 create_size_group_window (GdkScreen    *screen,
4911                           GtkSizeGroup *master_size_group)
4912 {
4913   GtkWidget *window;
4914   GtkWidget *table;
4915   GtkWidget *main_button;
4916   GtkWidget *button;
4917   GtkWidget *spin_button;
4918   GtkWidget *hbox;
4919   GtkSizeGroup *hgroup1;
4920   GtkSizeGroup *hgroup2;
4921   GtkSizeGroup *vgroup1;
4922   GtkSizeGroup *vgroup2;
4923
4924   window = gtk_dialog_new_with_buttons ("GtkSizeGroup",
4925                                         NULL, 0,
4926                                         GTK_STOCK_CLOSE,
4927                                         GTK_RESPONSE_NONE,
4928                                         NULL);
4929
4930   gtk_window_set_screen (GTK_WINDOW (window), screen);
4931
4932   gtk_window_set_resizable (GTK_WINDOW (window), TRUE);
4933
4934   g_signal_connect (window, "response",
4935                     G_CALLBACK (gtk_widget_destroy),
4936                     NULL);
4937
4938   table = gtk_table_new (2, 2, FALSE);
4939   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), table, TRUE, TRUE, 0);
4940
4941   gtk_table_set_row_spacings (GTK_TABLE (table), 5);
4942   gtk_table_set_col_spacings (GTK_TABLE (table), 5);
4943   gtk_container_set_border_width (GTK_CONTAINER (table), 5);
4944   gtk_widget_set_size_request (table, 250, 250);
4945
4946   hgroup1 = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
4947   hgroup2 = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
4948   vgroup1 = gtk_size_group_new (GTK_SIZE_GROUP_VERTICAL);
4949   vgroup2 = gtk_size_group_new (GTK_SIZE_GROUP_VERTICAL);
4950
4951   main_button = gtk_button_new_with_label ("X");
4952   
4953   gtk_table_attach (GTK_TABLE (table), main_button,
4954                     0, 1,       0, 1,
4955                     GTK_EXPAND, GTK_EXPAND,
4956                     0,          0);
4957   gtk_size_group_add_widget (master_size_group, main_button);
4958   gtk_size_group_add_widget (hgroup1, main_button);
4959   gtk_size_group_add_widget (vgroup1, main_button);
4960   gtk_widget_set_size_request (GTK_BIN (main_button)->child,
4961                                SIZE_GROUP_INITIAL_SIZE,
4962                                SIZE_GROUP_INITIAL_SIZE);
4963
4964   button = gtk_button_new ();
4965   gtk_table_attach (GTK_TABLE (table), button,
4966                     1, 2,       0, 1,
4967                     GTK_EXPAND, GTK_EXPAND,
4968                     0,          0);
4969   gtk_size_group_add_widget (vgroup1, button);
4970   gtk_size_group_add_widget (vgroup2, button);
4971
4972   button = gtk_button_new ();
4973   gtk_table_attach (GTK_TABLE (table), button,
4974                     0, 1,       1, 2,
4975                     GTK_EXPAND, GTK_EXPAND,
4976                     0,          0);
4977   gtk_size_group_add_widget (hgroup1, button);
4978   gtk_size_group_add_widget (hgroup2, button);
4979
4980   button = gtk_button_new ();
4981   gtk_table_attach (GTK_TABLE (table), button,
4982                     1, 2,       1, 2,
4983                     GTK_EXPAND, GTK_EXPAND,
4984                     0,          0);
4985   gtk_size_group_add_widget (hgroup2, button);
4986   gtk_size_group_add_widget (vgroup2, button);
4987
4988   g_object_unref (hgroup1);
4989   g_object_unref (hgroup2);
4990   g_object_unref (vgroup1);
4991   g_object_unref (vgroup2);
4992   
4993   hbox = gtk_hbox_new (FALSE, 5);
4994   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), hbox, FALSE, FALSE, 0);
4995   
4996   spin_button = gtk_spin_button_new_with_range (1, 100, 1);
4997   gtk_spin_button_set_value (GTK_SPIN_BUTTON (spin_button), SIZE_GROUP_INITIAL_SIZE);
4998   gtk_box_pack_start (GTK_BOX (hbox), spin_button, TRUE, TRUE, 0);
4999   g_signal_connect (spin_button, "value_changed",
5000                     G_CALLBACK (size_group_hsize_changed), main_button);
5001
5002   spin_button = gtk_spin_button_new_with_range (1, 100, 1);
5003   gtk_spin_button_set_value (GTK_SPIN_BUTTON (spin_button), SIZE_GROUP_INITIAL_SIZE);
5004   gtk_box_pack_start (GTK_BOX (hbox), spin_button, TRUE, TRUE, 0);
5005   g_signal_connect (spin_button, "value_changed",
5006                     G_CALLBACK (size_group_vsize_changed), main_button);
5007
5008   return window;
5009 }
5010
5011 static void
5012 create_size_groups (GtkWidget *widget)
5013 {
5014   static GtkWidget *window1 = NULL;
5015   static GtkWidget *window2 = NULL;
5016   static GtkSizeGroup *master_size_group;
5017
5018   if (!master_size_group)
5019     master_size_group = gtk_size_group_new (GTK_SIZE_GROUP_BOTH);
5020
5021   if (!window1)
5022     {
5023       window1 = create_size_group_window (gtk_widget_get_screen (widget),
5024                                           master_size_group);
5025
5026       g_signal_connect (window1, "destroy",
5027                         G_CALLBACK (gtk_widget_destroyed),
5028                         &window1);
5029     }
5030
5031   if (!window2)
5032     {
5033       window2 = create_size_group_window (gtk_widget_get_screen (widget),
5034                                           master_size_group);
5035
5036       g_signal_connect (window2, "destroy",
5037                         G_CALLBACK (gtk_widget_destroyed),
5038                         &window2);
5039     }
5040
5041   if (gtk_widget_get_visible (window1) && gtk_widget_get_visible (window2))
5042     {
5043       gtk_widget_destroy (window1);
5044       gtk_widget_destroy (window2);
5045     }
5046   else
5047     {
5048       if (!gtk_widget_get_visible (window1))
5049         gtk_widget_show_all (window1);
5050       if (!gtk_widget_get_visible (window2))
5051         gtk_widget_show_all (window2);
5052     }
5053 }
5054
5055 /*
5056  * GtkSpinButton
5057  */
5058
5059 static GtkWidget *spinner1;
5060
5061 static void
5062 toggle_snap (GtkWidget *widget, GtkSpinButton *spin)
5063 {
5064   gtk_spin_button_set_snap_to_ticks (spin, GTK_TOGGLE_BUTTON (widget)->active);
5065 }
5066
5067 static void
5068 toggle_numeric (GtkWidget *widget, GtkSpinButton *spin)
5069 {
5070   gtk_spin_button_set_numeric (spin, GTK_TOGGLE_BUTTON (widget)->active);
5071 }
5072
5073 static void
5074 change_digits (GtkWidget *widget, GtkSpinButton *spin)
5075 {
5076   gtk_spin_button_set_digits (GTK_SPIN_BUTTON (spinner1),
5077                               gtk_spin_button_get_value_as_int (spin));
5078 }
5079
5080 static void
5081 get_value (GtkWidget *widget, gpointer data)
5082 {
5083   gchar buf[32];
5084   GtkLabel *label;
5085   GtkSpinButton *spin;
5086
5087   spin = GTK_SPIN_BUTTON (spinner1);
5088   label = GTK_LABEL (g_object_get_data (G_OBJECT (widget), "user_data"));
5089   if (GPOINTER_TO_INT (data) == 1)
5090     sprintf (buf, "%d", gtk_spin_button_get_value_as_int (spin));
5091   else
5092     sprintf (buf, "%0.*f", spin->digits, gtk_spin_button_get_value (spin));
5093   gtk_label_set_text (label, buf);
5094 }
5095
5096 static void
5097 get_spin_value (GtkWidget *widget, gpointer data)
5098 {
5099   gchar *buffer;
5100   GtkLabel *label;
5101   GtkSpinButton *spin;
5102
5103   spin = GTK_SPIN_BUTTON (widget);
5104   label = GTK_LABEL (data);
5105
5106   buffer = g_strdup_printf ("%0.*f", spin->digits,
5107                             gtk_spin_button_get_value (spin));
5108   gtk_label_set_text (label, buffer);
5109
5110   g_free (buffer);
5111 }
5112
5113 static gint
5114 spin_button_time_output_func (GtkSpinButton *spin_button)
5115 {
5116   static gchar buf[6];
5117   gdouble hours;
5118   gdouble minutes;
5119
5120   hours = spin_button->adjustment->value / 60.0;
5121   minutes = (fabs(floor (hours) - hours) < 1e-5) ? 0.0 : 30;
5122   sprintf (buf, "%02.0f:%02.0f", floor (hours), minutes);
5123   if (strcmp (buf, gtk_entry_get_text (GTK_ENTRY (spin_button))))
5124     gtk_entry_set_text (GTK_ENTRY (spin_button), buf);
5125   return TRUE;
5126 }
5127
5128 static gint
5129 spin_button_month_input_func (GtkSpinButton *spin_button,
5130                               gdouble       *new_val)
5131 {
5132   gint i;
5133   static gchar *month[12] = { "January", "February", "March", "April",
5134                               "May", "June", "July", "August",
5135                               "September", "October", "November", "December" };
5136   gchar *tmp1, *tmp2;
5137   gboolean found = FALSE;
5138
5139   for (i = 1; i <= 12; i++)
5140     {
5141       tmp1 = g_ascii_strup (month[i - 1], -1);
5142       tmp2 = g_ascii_strup (gtk_entry_get_text (GTK_ENTRY (spin_button)), -1);
5143       if (strstr (tmp1, tmp2) == tmp1)
5144         found = TRUE;
5145       g_free (tmp1);
5146       g_free (tmp2);
5147       if (found)
5148         break;
5149     }
5150   if (!found)
5151     {
5152       *new_val = 0.0;
5153       return GTK_INPUT_ERROR;
5154     }
5155   *new_val = (gdouble) i;
5156   return TRUE;
5157 }
5158
5159 static gint
5160 spin_button_month_output_func (GtkSpinButton *spin_button)
5161 {
5162   gint i;
5163   static gchar *month[12] = { "January", "February", "March", "April",
5164                               "May", "June", "July", "August", "September",
5165                               "October", "November", "December" };
5166
5167   for (i = 1; i <= 12; i++)
5168     if (fabs (spin_button->adjustment->value - (double)i) < 1e-5)
5169       {
5170         if (strcmp (month[i-1], gtk_entry_get_text (GTK_ENTRY (spin_button))))
5171           gtk_entry_set_text (GTK_ENTRY (spin_button), month[i-1]);
5172       }
5173   return TRUE;
5174 }
5175
5176 static gint
5177 spin_button_hex_input_func (GtkSpinButton *spin_button,
5178                             gdouble       *new_val)
5179 {
5180   const gchar *buf;
5181   gchar *err;
5182   gdouble res;
5183
5184   buf = gtk_entry_get_text (GTK_ENTRY (spin_button));
5185   res = strtol(buf, &err, 16);
5186   *new_val = res;
5187   if (*err)
5188     return GTK_INPUT_ERROR;
5189   else
5190     return TRUE;
5191 }
5192
5193 static gint
5194 spin_button_hex_output_func (GtkSpinButton *spin_button)
5195 {
5196   static gchar buf[7];
5197   gint val;
5198
5199   val = (gint) spin_button->adjustment->value;
5200   if (fabs (val) < 1e-5)
5201     sprintf (buf, "0x00");
5202   else
5203     sprintf (buf, "0x%.2X", val);
5204   if (strcmp (buf, gtk_entry_get_text (GTK_ENTRY (spin_button))))
5205     gtk_entry_set_text (GTK_ENTRY (spin_button), buf);
5206   return TRUE;
5207 }
5208
5209 static void
5210 create_spins (GtkWidget *widget)
5211 {
5212   static GtkWidget *window = NULL;
5213   GtkWidget *frame;
5214   GtkWidget *hbox;
5215   GtkWidget *main_vbox;
5216   GtkWidget *vbox;
5217   GtkWidget *vbox2;
5218   GtkWidget *spinner2;
5219   GtkWidget *spinner;
5220   GtkWidget *button;
5221   GtkWidget *label;
5222   GtkWidget *val_label;
5223   GtkAdjustment *adj;
5224
5225   if (!window)
5226     {
5227       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
5228       gtk_window_set_screen (GTK_WINDOW (window),
5229                              gtk_widget_get_screen (widget));
5230       
5231       g_signal_connect (window, "destroy",
5232                         G_CALLBACK (gtk_widget_destroyed),
5233                         &window);
5234       
5235       gtk_window_set_title (GTK_WINDOW (window), "GtkSpinButton");
5236       
5237       main_vbox = gtk_vbox_new (FALSE, 5);
5238       gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 10);
5239       gtk_container_add (GTK_CONTAINER (window), main_vbox);
5240       
5241       frame = gtk_frame_new ("Not accelerated");
5242       gtk_box_pack_start (GTK_BOX (main_vbox), frame, TRUE, TRUE, 0);
5243       
5244       vbox = gtk_vbox_new (FALSE, 0);
5245       gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
5246       gtk_container_add (GTK_CONTAINER (frame), vbox);
5247       
5248       /* Time, month, hex spinners */
5249       
5250       hbox = gtk_hbox_new (FALSE, 0);
5251       gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 5);
5252       
5253       vbox2 = gtk_vbox_new (FALSE, 0);
5254       gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 5);
5255       
5256       label = gtk_label_new ("Time :");
5257       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
5258       gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
5259       
5260       adj = (GtkAdjustment *) gtk_adjustment_new (0, 0, 1410, 30, 60, 0);
5261       spinner = gtk_spin_button_new (adj, 0, 0);
5262       gtk_editable_set_editable (GTK_EDITABLE (spinner), FALSE);
5263       g_signal_connect (spinner,
5264                         "output",
5265                         G_CALLBACK (spin_button_time_output_func),
5266                         NULL);
5267       gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner), TRUE);
5268       gtk_entry_set_width_chars (GTK_ENTRY (spinner), 5);
5269       gtk_box_pack_start (GTK_BOX (vbox2), spinner, FALSE, TRUE, 0);
5270
5271       vbox2 = gtk_vbox_new (FALSE, 0);
5272       gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 5);
5273       
5274       label = gtk_label_new ("Month :");
5275       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
5276       gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
5277       
5278       adj = (GtkAdjustment *) gtk_adjustment_new (1.0, 1.0, 12.0, 1.0,
5279                                                   5.0, 0.0);
5280       spinner = gtk_spin_button_new (adj, 0, 0);
5281       gtk_spin_button_set_update_policy (GTK_SPIN_BUTTON (spinner),
5282                                          GTK_UPDATE_IF_VALID);
5283       g_signal_connect (spinner,
5284                         "input",
5285                         G_CALLBACK (spin_button_month_input_func),
5286                         NULL);
5287       g_signal_connect (spinner,
5288                         "output",
5289                         G_CALLBACK (spin_button_month_output_func),
5290                         NULL);
5291       gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner), TRUE);
5292       gtk_entry_set_width_chars (GTK_ENTRY (spinner), 9);
5293       gtk_box_pack_start (GTK_BOX (vbox2), spinner, FALSE, TRUE, 0);
5294       
5295       vbox2 = gtk_vbox_new (FALSE, 0);
5296       gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 5);
5297
5298       label = gtk_label_new ("Hex :");
5299       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
5300       gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
5301
5302       adj = (GtkAdjustment *) gtk_adjustment_new (0, 0, 255, 1, 16, 0);
5303       spinner = gtk_spin_button_new (adj, 0, 0);
5304       gtk_editable_set_editable (GTK_EDITABLE (spinner), TRUE);
5305       g_signal_connect (spinner,
5306                         "input",
5307                         G_CALLBACK (spin_button_hex_input_func),
5308                         NULL);
5309       g_signal_connect (spinner,
5310                         "output",
5311                         G_CALLBACK (spin_button_hex_output_func),
5312                         NULL);
5313       gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner), TRUE);
5314       gtk_entry_set_width_chars (GTK_ENTRY (spinner), 4);
5315       gtk_box_pack_start (GTK_BOX (vbox2), spinner, FALSE, TRUE, 0);
5316
5317       frame = gtk_frame_new ("Accelerated");
5318       gtk_box_pack_start (GTK_BOX (main_vbox), frame, TRUE, TRUE, 0);
5319   
5320       vbox = gtk_vbox_new (FALSE, 0);
5321       gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
5322       gtk_container_add (GTK_CONTAINER (frame), vbox);
5323       
5324       hbox = gtk_hbox_new (FALSE, 0);
5325       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 5);
5326       
5327       vbox2 = gtk_vbox_new (FALSE, 0);
5328       gtk_box_pack_start (GTK_BOX (hbox), vbox2, FALSE, FALSE, 5);
5329       
5330       label = gtk_label_new ("Value :");
5331       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
5332       gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
5333
5334       adj = (GtkAdjustment *) gtk_adjustment_new (0.0, -10000.0, 10000.0,
5335                                                   0.5, 100.0, 0.0);
5336       spinner1 = gtk_spin_button_new (adj, 1.0, 2);
5337       gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (spinner1), TRUE);
5338       gtk_box_pack_start (GTK_BOX (vbox2), spinner1, FALSE, TRUE, 0);
5339
5340       vbox2 = gtk_vbox_new (FALSE, 0);
5341       gtk_box_pack_start (GTK_BOX (hbox), vbox2, FALSE, FALSE, 5);
5342
5343       label = gtk_label_new ("Digits :");
5344       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
5345       gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, TRUE, 0);
5346
5347       adj = (GtkAdjustment *) gtk_adjustment_new (2, 1, 15, 1, 1, 0);
5348       spinner2 = gtk_spin_button_new (adj, 0.0, 0);
5349       g_signal_connect (adj, "value_changed",
5350                         G_CALLBACK (change_digits),
5351                         spinner2);
5352       gtk_box_pack_start (GTK_BOX (vbox2), spinner2, FALSE, TRUE, 0);
5353
5354       hbox = gtk_hbox_new (FALSE, 0);
5355       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 5);
5356
5357       button = gtk_check_button_new_with_label ("Snap to 0.5-ticks");
5358       g_signal_connect (button, "clicked",
5359                         G_CALLBACK (toggle_snap),
5360                         spinner1);
5361       gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
5362       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
5363
5364       button = gtk_check_button_new_with_label ("Numeric only input mode");
5365       g_signal_connect (button, "clicked",
5366                         G_CALLBACK (toggle_numeric),
5367                         spinner1);
5368       gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
5369       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
5370
5371       val_label = gtk_label_new ("");
5372
5373       hbox = gtk_hbox_new (FALSE, 0);
5374       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 5);
5375
5376       button = gtk_button_new_with_label ("Value as Int");
5377       g_object_set_data (G_OBJECT (button), "user_data", val_label);
5378       g_signal_connect (button, "clicked",
5379                         G_CALLBACK (get_value),
5380                         GINT_TO_POINTER (1));
5381       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
5382
5383       button = gtk_button_new_with_label ("Value as Float");
5384       g_object_set_data (G_OBJECT (button), "user_data", val_label);
5385       g_signal_connect (button, "clicked",
5386                         G_CALLBACK (get_value),
5387                         GINT_TO_POINTER (2));
5388       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
5389
5390       gtk_box_pack_start (GTK_BOX (vbox), val_label, TRUE, TRUE, 0);
5391       gtk_label_set_text (GTK_LABEL (val_label), "0");
5392
5393       frame = gtk_frame_new ("Using Convenience Constructor");
5394       gtk_box_pack_start (GTK_BOX (main_vbox), frame, TRUE, TRUE, 0);
5395   
5396       hbox = gtk_hbox_new (FALSE, 0);
5397       gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
5398       gtk_container_add (GTK_CONTAINER (frame), hbox);
5399       
5400       val_label = gtk_label_new ("0.0");
5401
5402       spinner = gtk_spin_button_new_with_range (0.0, 10.0, 0.009);
5403       gtk_spin_button_set_value (GTK_SPIN_BUTTON (spinner), 0.0);
5404       g_signal_connect (spinner, "value_changed",
5405                         G_CALLBACK (get_spin_value), val_label);
5406       gtk_box_pack_start (GTK_BOX (hbox), spinner, TRUE, TRUE, 5);
5407       gtk_box_pack_start (GTK_BOX (hbox), val_label, TRUE, TRUE, 5);
5408
5409       hbox = gtk_hbox_new (FALSE, 0);
5410       gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, TRUE, 0);
5411   
5412       button = gtk_button_new_with_label ("Close");
5413       g_signal_connect_swapped (button, "clicked",
5414                                 G_CALLBACK (gtk_widget_destroy),
5415                                 window);
5416       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
5417     }
5418
5419   if (!gtk_widget_get_visible (window))
5420     gtk_widget_show_all (window);
5421   else
5422     gtk_widget_destroy (window);
5423 }
5424
5425
5426 /*
5427  * Cursors
5428  */
5429
5430 static gint
5431 cursor_expose_event (GtkWidget *widget,
5432                      GdkEvent  *event,
5433                      gpointer   user_data)
5434 {
5435   GtkDrawingArea *darea;
5436   GdkDrawable *drawable;
5437   GdkGC *black_gc;
5438   GdkGC *gray_gc;
5439   GdkGC *white_gc;
5440   guint max_width;
5441   guint max_height;
5442
5443   g_return_val_if_fail (widget != NULL, TRUE);
5444   g_return_val_if_fail (GTK_IS_DRAWING_AREA (widget), TRUE);
5445
5446   darea = GTK_DRAWING_AREA (widget);
5447   drawable = widget->window;
5448   white_gc = widget->style->white_gc;
5449   gray_gc = widget->style->bg_gc[GTK_STATE_NORMAL];
5450   black_gc = widget->style->black_gc;
5451   max_width = widget->allocation.width;
5452   max_height = widget->allocation.height;
5453
5454   gdk_draw_rectangle (drawable, white_gc,
5455                       TRUE,
5456                       0,
5457                       0,
5458                       max_width,
5459                       max_height / 2);
5460
5461   gdk_draw_rectangle (drawable, black_gc,
5462                       TRUE,
5463                       0,
5464                       max_height / 2,
5465                       max_width,
5466                       max_height / 2);
5467
5468   gdk_draw_rectangle (drawable, gray_gc,
5469                       TRUE,
5470                       max_width / 3,
5471                       max_height / 3,
5472                       max_width / 3,
5473                       max_height / 3);
5474
5475   return TRUE;
5476 }
5477
5478 static void
5479 set_cursor (GtkWidget *spinner,
5480             GtkWidget *widget)
5481 {
5482   guint c;
5483   GdkCursor *cursor;
5484   GtkWidget *label;
5485   GEnumClass *class;
5486   GEnumValue *vals;
5487
5488   c = CLAMP (gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (spinner)), 0, 152);
5489   c &= 0xfe;
5490
5491   label = g_object_get_data (G_OBJECT (spinner), "user_data");
5492   
5493   class = g_type_class_ref (GDK_TYPE_CURSOR_TYPE);
5494   vals = class->values;
5495
5496   while (vals && vals->value != c)
5497     vals++;
5498   if (vals)
5499     gtk_label_set_text (GTK_LABEL (label), vals->value_nick);
5500   else
5501     gtk_label_set_text (GTK_LABEL (label), "<unknown>");
5502
5503   g_type_class_unref (class);
5504
5505   cursor = gdk_cursor_new_for_display (gtk_widget_get_display (widget), c);
5506   gdk_window_set_cursor (widget->window, cursor);
5507   gdk_cursor_unref (cursor);
5508 }
5509
5510 static gint
5511 cursor_event (GtkWidget          *widget,
5512               GdkEvent           *event,
5513               GtkSpinButton      *spinner)
5514 {
5515   if ((event->type == GDK_BUTTON_PRESS) &&
5516       ((event->button.button == 1) ||
5517        (event->button.button == 3)))
5518     {
5519       gtk_spin_button_spin (spinner, event->button.button == 1 ?
5520                             GTK_SPIN_STEP_FORWARD : GTK_SPIN_STEP_BACKWARD, 0);
5521       return TRUE;
5522     }
5523
5524   return FALSE;
5525 }
5526
5527 #ifdef GDK_WINDOWING_X11
5528 #include "x11/gdkx.h"
5529
5530 static void
5531 change_cursor_theme (GtkWidget *widget,
5532                      gpointer   data)
5533 {
5534   const gchar *theme;
5535   gint size;
5536   GList *children;
5537
5538   children = gtk_container_get_children (GTK_CONTAINER (data));
5539
5540   theme = gtk_entry_get_text (GTK_ENTRY (children->next->data));
5541   size = (gint) gtk_spin_button_get_value (GTK_SPIN_BUTTON (children->next->next->data));
5542
5543   g_list_free (children);
5544
5545   gdk_x11_display_set_cursor_theme (gtk_widget_get_display (widget),
5546                                     theme, size);
5547 }
5548 #endif
5549
5550
5551 static void
5552 create_cursors (GtkWidget *widget)
5553 {
5554   static GtkWidget *window = NULL;
5555   GtkWidget *frame;
5556   GtkWidget *hbox;
5557   GtkWidget *main_vbox;
5558   GtkWidget *vbox;
5559   GtkWidget *darea;
5560   GtkWidget *spinner;
5561   GtkWidget *button;
5562   GtkWidget *label;
5563   GtkWidget *any;
5564   GtkAdjustment *adj;
5565   GtkWidget *entry;
5566   GtkWidget *size;  
5567
5568   if (!window)
5569     {
5570       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
5571       gtk_window_set_screen (GTK_WINDOW (window), 
5572                              gtk_widget_get_screen (widget));
5573       
5574       g_signal_connect (window, "destroy",
5575                         G_CALLBACK (gtk_widget_destroyed),
5576                         &window);
5577       
5578       gtk_window_set_title (GTK_WINDOW (window), "Cursors");
5579       
5580       main_vbox = gtk_vbox_new (FALSE, 5);
5581       gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 0);
5582       gtk_container_add (GTK_CONTAINER (window), main_vbox);
5583
5584       vbox =
5585         g_object_new (gtk_vbox_get_type (),
5586                         "GtkBox::homogeneous", FALSE,
5587                         "GtkBox::spacing", 5,
5588                         "GtkContainer::border_width", 10,
5589                         "GtkWidget::parent", main_vbox,
5590                         "GtkWidget::visible", TRUE,
5591                         NULL);
5592
5593 #ifdef GDK_WINDOWING_X11
5594       hbox = gtk_hbox_new (FALSE, 0);
5595       gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
5596       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
5597
5598       label = gtk_label_new ("Cursor Theme : ");
5599       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
5600       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
5601
5602       entry = gtk_entry_new ();
5603       gtk_entry_set_text (GTK_ENTRY (entry), "default");
5604       gtk_box_pack_start (GTK_BOX (hbox), entry, FALSE, TRUE, 0);
5605
5606       size = gtk_spin_button_new_with_range (1.0, 64.0, 1.0);
5607       gtk_spin_button_set_value (GTK_SPIN_BUTTON (size), 24.0);
5608       gtk_box_pack_start (GTK_BOX (hbox), size, TRUE, TRUE, 0);
5609       
5610       g_signal_connect (entry, "changed", 
5611                         G_CALLBACK (change_cursor_theme), hbox);
5612       g_signal_connect (size, "changed", 
5613                         G_CALLBACK (change_cursor_theme), hbox);
5614 #endif
5615
5616       hbox = gtk_hbox_new (FALSE, 0);
5617       gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
5618       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
5619
5620       label = gtk_label_new ("Cursor Value : ");
5621       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
5622       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
5623       
5624       adj = (GtkAdjustment *) gtk_adjustment_new (0,
5625                                                   0, 152,
5626                                                   2,
5627                                                   10, 0);
5628       spinner = gtk_spin_button_new (adj, 0, 0);
5629       gtk_box_pack_start (GTK_BOX (hbox), spinner, TRUE, TRUE, 0);
5630
5631       frame =
5632         g_object_new (gtk_frame_get_type (),
5633                         "GtkFrame::shadow", GTK_SHADOW_ETCHED_IN,
5634                         "GtkFrame::label_xalign", 0.5,
5635                         "GtkFrame::label", "Cursor Area",
5636                         "GtkContainer::border_width", 10,
5637                         "GtkWidget::parent", vbox,
5638                         "GtkWidget::visible", TRUE,
5639                         NULL);
5640
5641       darea = gtk_drawing_area_new ();
5642       gtk_widget_set_size_request (darea, 80, 80);
5643       gtk_container_add (GTK_CONTAINER (frame), darea);
5644       g_signal_connect (darea,
5645                         "expose_event",
5646                         G_CALLBACK (cursor_expose_event),
5647                         NULL);
5648       gtk_widget_set_events (darea, GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK);
5649       g_signal_connect (darea,
5650                         "button_press_event",
5651                         G_CALLBACK (cursor_event),
5652                         spinner);
5653       gtk_widget_show (darea);
5654
5655       g_signal_connect (spinner, "changed",
5656                         G_CALLBACK (set_cursor),
5657                         darea);
5658
5659       label = g_object_new (GTK_TYPE_LABEL,
5660                               "visible", TRUE,
5661                               "label", "XXX",
5662                               "parent", vbox,
5663                               NULL);
5664       gtk_container_child_set (GTK_CONTAINER (vbox), label,
5665                                "expand", FALSE,
5666                                NULL);
5667       g_object_set_data (G_OBJECT (spinner), "user_data", label);
5668
5669       any =
5670         g_object_new (gtk_hseparator_get_type (),
5671                         "GtkWidget::visible", TRUE,
5672                         NULL);
5673       gtk_box_pack_start (GTK_BOX (main_vbox), any, FALSE, TRUE, 0);
5674   
5675       hbox = gtk_hbox_new (FALSE, 0);
5676       gtk_container_set_border_width (GTK_CONTAINER (hbox), 10);
5677       gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, TRUE, 0);
5678
5679       button = gtk_button_new_with_label ("Close");
5680       g_signal_connect_swapped (button, "clicked",
5681                                 G_CALLBACK (gtk_widget_destroy),
5682                                 window);
5683       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
5684
5685       gtk_widget_show_all (window);
5686
5687       set_cursor (spinner, darea);
5688     }
5689   else
5690     gtk_widget_destroy (window);
5691 }
5692
5693 /*
5694  * GtkColorSelection
5695  */
5696
5697 void
5698 color_selection_ok (GtkWidget               *w,
5699                     GtkColorSelectionDialog *cs)
5700 {
5701   GtkColorSelection *colorsel;
5702   gdouble color[4];
5703
5704   colorsel=GTK_COLOR_SELECTION(cs->colorsel);
5705
5706   gtk_color_selection_get_color(colorsel,color);
5707   gtk_color_selection_set_color(colorsel,color);
5708 }
5709
5710 void
5711 color_selection_changed (GtkWidget *w,
5712                          GtkColorSelectionDialog *cs)
5713 {
5714   GtkColorSelection *colorsel;
5715   gdouble color[4];
5716
5717   colorsel=GTK_COLOR_SELECTION(cs->colorsel);
5718   gtk_color_selection_get_color(colorsel,color);
5719 }
5720
5721 #if 0 /* unused */
5722 static void
5723 opacity_toggled_cb (GtkWidget *w,
5724                     GtkColorSelectionDialog *cs)
5725 {
5726   GtkColorSelection *colorsel;
5727
5728   colorsel = GTK_COLOR_SELECTION (cs->colorsel);
5729   gtk_color_selection_set_has_opacity_control (colorsel,
5730                                                gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w)));
5731 }
5732
5733 static void
5734 palette_toggled_cb (GtkWidget *w,
5735                     GtkColorSelectionDialog *cs)
5736 {
5737   GtkColorSelection *colorsel;
5738
5739   colorsel = GTK_COLOR_SELECTION (cs->colorsel);
5740   gtk_color_selection_set_has_palette (colorsel,
5741                                        gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w)));
5742 }
5743 #endif
5744
5745 void
5746 create_color_selection (GtkWidget *widget)
5747 {
5748   static GtkWidget *window = NULL;
5749
5750   if (!window)
5751     {
5752       GtkWidget *picker;
5753       GtkWidget *hbox;
5754       GtkWidget *label;
5755       GtkWidget *button;
5756       
5757       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
5758       gtk_window_set_screen (GTK_WINDOW (window), 
5759                              gtk_widget_get_screen (widget));
5760                              
5761       g_signal_connect (window, "destroy",
5762                         G_CALLBACK (gtk_widget_destroyed),
5763                         &window);
5764
5765       gtk_window_set_title (GTK_WINDOW (window), "GtkColorButton");
5766       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
5767
5768       hbox = gtk_hbox_new (FALSE, 8);
5769       gtk_container_set_border_width (GTK_CONTAINER (hbox), 8);
5770       gtk_container_add (GTK_CONTAINER (window), hbox);
5771       
5772       label = gtk_label_new ("Pick a color");
5773       gtk_container_add (GTK_CONTAINER (hbox), label);
5774
5775       picker = gtk_color_button_new ();
5776       gtk_color_button_set_use_alpha (GTK_COLOR_BUTTON (picker), TRUE);
5777       gtk_container_add (GTK_CONTAINER (hbox), picker);
5778
5779       button = gtk_button_new_with_mnemonic ("_Props");
5780       gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
5781       g_signal_connect (button, "clicked",
5782                         G_CALLBACK (props_clicked),
5783                         picker);
5784     }
5785
5786   if (!gtk_widget_get_visible (window))
5787     gtk_widget_show_all (window);
5788   else
5789     gtk_widget_destroy (window);
5790 }
5791
5792 void
5793 flipping_toggled_cb (GtkWidget *widget, gpointer data)
5794 {
5795   int state = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
5796   int new_direction = state ? GTK_TEXT_DIR_RTL : GTK_TEXT_DIR_LTR;
5797
5798   gtk_widget_set_default_direction (new_direction);
5799 }
5800
5801 static void
5802 orientable_toggle_orientation (GtkOrientable *orientable)
5803 {
5804   GtkOrientation orientation;
5805
5806   orientation = gtk_orientable_get_orientation (orientable);
5807   gtk_orientable_set_orientation (orientable,
5808                                   orientation == GTK_ORIENTATION_HORIZONTAL ?
5809                                   GTK_ORIENTATION_VERTICAL :
5810                                   GTK_ORIENTATION_HORIZONTAL);
5811
5812   if (GTK_IS_CONTAINER (orientable))
5813     {
5814       GList *children;
5815       GList *child;
5816
5817       children = gtk_container_get_children (GTK_CONTAINER (orientable));
5818
5819       for (child = children; child; child = child->next)
5820         {
5821           if (GTK_IS_ORIENTABLE (child->data))
5822             orientable_toggle_orientation (child->data);
5823         }
5824
5825       g_list_free (children);
5826     }
5827 }
5828
5829 void
5830 flipping_orientation_toggled_cb (GtkWidget *widget, gpointer data)
5831 {
5832   orientable_toggle_orientation (GTK_ORIENTABLE (GTK_DIALOG (gtk_widget_get_toplevel (widget))->vbox));
5833 }
5834
5835 static void
5836 set_direction_recurse (GtkWidget *widget,
5837                        gpointer   data)
5838 {
5839   GtkTextDirection *dir = data;
5840   
5841   gtk_widget_set_direction (widget, *dir);
5842   if (GTK_IS_CONTAINER (widget))
5843     gtk_container_foreach (GTK_CONTAINER (widget),
5844                            set_direction_recurse,
5845                            data);
5846 }
5847
5848 static GtkWidget *
5849 create_forward_back (const char       *title,
5850                      GtkTextDirection  text_dir)
5851 {
5852   GtkWidget *frame = gtk_frame_new (title);
5853   GtkWidget *bbox = gtk_hbutton_box_new ();
5854   GtkWidget *back_button = gtk_button_new_from_stock (GTK_STOCK_GO_BACK);
5855   GtkWidget *forward_button = gtk_button_new_from_stock (GTK_STOCK_GO_FORWARD);
5856
5857   gtk_container_set_border_width (GTK_CONTAINER (bbox), 5);
5858   
5859   gtk_container_add (GTK_CONTAINER (frame), bbox);
5860   gtk_container_add (GTK_CONTAINER (bbox), back_button);
5861   gtk_container_add (GTK_CONTAINER (bbox), forward_button);
5862
5863   set_direction_recurse (frame, &text_dir);
5864
5865   return frame;
5866 }
5867
5868 void
5869 create_flipping (GtkWidget *widget)
5870 {
5871   static GtkWidget *window = NULL;
5872   GtkWidget *check_button, *button;
5873
5874   if (!window)
5875     {
5876       window = gtk_dialog_new ();
5877
5878       gtk_window_set_screen (GTK_WINDOW (window),
5879                              gtk_widget_get_screen (widget));
5880
5881       g_signal_connect (window, "destroy",
5882                         G_CALLBACK (gtk_widget_destroyed),
5883                         &window);
5884
5885       gtk_window_set_title (GTK_WINDOW (window), "Bidirectional Flipping");
5886
5887       check_button = gtk_check_button_new_with_label ("Right-to-left global direction");
5888       gtk_container_set_border_width (GTK_CONTAINER (check_button), 10);
5889       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox),
5890                           check_button, TRUE, TRUE, 0);
5891
5892       if (gtk_widget_get_default_direction () == GTK_TEXT_DIR_RTL)
5893         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button), TRUE);
5894
5895       g_signal_connect (check_button, "toggled",
5896                         G_CALLBACK (flipping_toggled_cb), NULL);
5897
5898       check_button = gtk_check_button_new_with_label ("Toggle orientation of all boxes");
5899       gtk_container_set_border_width (GTK_CONTAINER (check_button), 10);
5900       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
5901                           check_button, TRUE, TRUE, 0);
5902
5903       g_signal_connect (check_button, "toggled",
5904                         G_CALLBACK (flipping_orientation_toggled_cb), NULL);
5905
5906       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
5907                           create_forward_back ("Default", GTK_TEXT_DIR_NONE),
5908                           TRUE, TRUE, 0);
5909
5910       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
5911                           create_forward_back ("Left-to-Right", GTK_TEXT_DIR_LTR),
5912                           TRUE, TRUE, 0);
5913
5914       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
5915                           create_forward_back ("Right-to-Left", GTK_TEXT_DIR_RTL),
5916                           TRUE, TRUE, 0);
5917
5918       button = gtk_button_new_with_label ("Close");
5919       g_signal_connect_swapped (button, "clicked",
5920                                 G_CALLBACK (gtk_widget_destroy), window);
5921       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
5922                           button, TRUE, TRUE, 0);
5923     }
5924   
5925   if (!gtk_widget_get_visible (window))
5926     gtk_widget_show_all (window);
5927   else
5928     gtk_widget_destroy (window);
5929 }
5930
5931 /*
5932  * Focus test
5933  */
5934
5935 static GtkWidget*
5936 make_focus_table (GList **list)
5937 {
5938   GtkWidget *table;
5939   gint i, j;
5940   
5941   table = gtk_table_new (5, 5, FALSE);
5942
5943   i = 0;
5944   j = 0;
5945
5946   while (i < 5)
5947     {
5948       j = 0;
5949       while (j < 5)
5950         {
5951           GtkWidget *widget;
5952           
5953           if ((i + j) % 2)
5954             widget = gtk_entry_new ();
5955           else
5956             widget = gtk_button_new_with_label ("Foo");
5957
5958           *list = g_list_prepend (*list, widget);
5959           
5960           gtk_table_attach (GTK_TABLE (table),
5961                             widget,
5962                             i, i + 1,
5963                             j, j + 1,
5964                             GTK_EXPAND | GTK_FILL,
5965                             GTK_EXPAND | GTK_FILL,
5966                             5, 5);
5967           
5968           ++j;
5969         }
5970
5971       ++i;
5972     }
5973
5974   *list = g_list_reverse (*list);
5975   
5976   return table;
5977 }
5978
5979 static void
5980 create_focus (GtkWidget *widget)
5981 {
5982   static GtkWidget *window = NULL;
5983   
5984   if (!window)
5985     {
5986       GtkWidget *table;
5987       GtkWidget *frame;
5988       GList *list = NULL;
5989       
5990       window = gtk_dialog_new_with_buttons ("Keyboard focus navigation",
5991                                             NULL, 0,
5992                                             GTK_STOCK_CLOSE,
5993                                             GTK_RESPONSE_NONE,
5994                                             NULL);
5995
5996       gtk_window_set_screen (GTK_WINDOW (window),
5997                              gtk_widget_get_screen (widget));
5998
5999       g_signal_connect (window, "destroy",
6000                         G_CALLBACK (gtk_widget_destroyed),
6001                         &window);
6002
6003       g_signal_connect (window, "response",
6004                         G_CALLBACK (gtk_widget_destroy),
6005                         NULL);
6006       
6007       gtk_window_set_title (GTK_WINDOW (window), "Keyboard Focus Navigation");
6008
6009       frame = gtk_frame_new ("Weird tab focus chain");
6010
6011       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
6012                           frame, TRUE, TRUE, 0);
6013       
6014       table = make_focus_table (&list);
6015
6016       gtk_container_add (GTK_CONTAINER (frame), table);
6017
6018       gtk_container_set_focus_chain (GTK_CONTAINER (table),
6019                                      list);
6020
6021       g_list_free (list);
6022       
6023       frame = gtk_frame_new ("Default tab focus chain");
6024
6025       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
6026                           frame, TRUE, TRUE, 0);
6027
6028       list = NULL;
6029       table = make_focus_table (&list);
6030
6031       g_list_free (list);
6032       
6033       gtk_container_add (GTK_CONTAINER (frame), table);      
6034     }
6035   
6036   if (!gtk_widget_get_visible (window))
6037     gtk_widget_show_all (window);
6038   else
6039     gtk_widget_destroy (window);
6040 }
6041
6042 /*
6043  * GtkFontSelection
6044  */
6045
6046 void
6047 font_selection_ok (GtkWidget              *w,
6048                    GtkFontSelectionDialog *fs)
6049 {
6050   gchar *s = gtk_font_selection_dialog_get_font_name (fs);
6051
6052   g_print ("%s\n", s);
6053   g_free (s);
6054   gtk_widget_destroy (GTK_WIDGET (fs));
6055 }
6056
6057 void
6058 create_font_selection (GtkWidget *widget)
6059 {
6060   static GtkWidget *window = NULL;
6061
6062   if (!window)
6063     {
6064       GtkWidget *picker;
6065       GtkWidget *hbox;
6066       GtkWidget *label;
6067       
6068       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6069       gtk_window_set_screen (GTK_WINDOW (window),
6070                              gtk_widget_get_screen (widget));
6071
6072       g_signal_connect (window, "destroy",
6073                         G_CALLBACK (gtk_widget_destroyed),
6074                         &window);
6075
6076       gtk_window_set_title (GTK_WINDOW (window), "GtkFontButton");
6077       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
6078
6079       hbox = gtk_hbox_new (FALSE, 8);
6080       gtk_container_set_border_width (GTK_CONTAINER (hbox), 8);
6081       gtk_container_add (GTK_CONTAINER (window), hbox);
6082       
6083       label = gtk_label_new ("Pick a font");
6084       gtk_container_add (GTK_CONTAINER (hbox), label);
6085
6086       picker = gtk_font_button_new ();
6087       gtk_font_button_set_use_font (GTK_FONT_BUTTON (picker), TRUE);
6088       gtk_container_add (GTK_CONTAINER (hbox), picker);
6089     }
6090   
6091   if (!gtk_widget_get_visible (window))
6092     gtk_widget_show_all (window);
6093   else
6094     gtk_widget_destroy (window);
6095 }
6096
6097 /*
6098  * GtkDialog
6099  */
6100
6101 static GtkWidget *dialog_window = NULL;
6102
6103 static void
6104 label_toggle (GtkWidget  *widget,
6105               GtkWidget **label)
6106 {
6107   if (!(*label))
6108     {
6109       *label = gtk_label_new ("Dialog Test");
6110       g_signal_connect (*label,
6111                         "destroy",
6112                         G_CALLBACK (gtk_widget_destroyed),
6113                         label);
6114       gtk_misc_set_padding (GTK_MISC (*label), 10, 10);
6115       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog_window)->vbox), 
6116                           *label, TRUE, TRUE, 0);
6117       gtk_widget_show (*label);
6118     }
6119   else
6120     gtk_widget_destroy (*label);
6121 }
6122
6123 #define RESPONSE_TOGGLE_SEPARATOR 1
6124
6125 static void
6126 print_response (GtkWidget *dialog,
6127                 gint       response_id,
6128                 gpointer   data)
6129 {
6130   g_print ("response signal received (%d)\n", response_id);
6131
6132   if (response_id == RESPONSE_TOGGLE_SEPARATOR)
6133     {
6134       gtk_dialog_set_has_separator (GTK_DIALOG (dialog),
6135                                     !gtk_dialog_get_has_separator (GTK_DIALOG (dialog)));
6136     }
6137 }
6138
6139 static void
6140 create_dialog (GtkWidget *widget)
6141 {
6142   static GtkWidget *label;
6143   GtkWidget *button;
6144
6145   if (!dialog_window)
6146     {
6147       /* This is a terrible example; it's much simpler to create
6148        * dialogs than this. Don't use testgtk for example code,
6149        * use gtk-demo ;-)
6150        */
6151       
6152       dialog_window = gtk_dialog_new ();
6153       gtk_window_set_screen (GTK_WINDOW (dialog_window),
6154                              gtk_widget_get_screen (widget));
6155
6156       g_signal_connect (dialog_window,
6157                         "response",
6158                         G_CALLBACK (print_response),
6159                         NULL);
6160       
6161       g_signal_connect (dialog_window, "destroy",
6162                         G_CALLBACK (gtk_widget_destroyed),
6163                         &dialog_window);
6164
6165       gtk_window_set_title (GTK_WINDOW (dialog_window), "GtkDialog");
6166       gtk_container_set_border_width (GTK_CONTAINER (dialog_window), 0);
6167
6168       button = gtk_button_new_with_label ("OK");
6169       gtk_widget_set_can_default (button, TRUE);
6170       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog_window)->action_area), 
6171                           button, TRUE, TRUE, 0);
6172       gtk_widget_grab_default (button);
6173       gtk_widget_show (button);
6174
6175       button = gtk_button_new_with_label ("Toggle");
6176       g_signal_connect (button, "clicked",
6177                         G_CALLBACK (label_toggle),
6178                         &label);
6179       gtk_widget_set_can_default (button, TRUE);
6180       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog_window)->action_area),
6181                           button, TRUE, TRUE, 0);
6182       gtk_widget_show (button);
6183
6184       label = NULL;
6185       
6186       button = gtk_button_new_with_label ("Separator");
6187
6188       gtk_widget_set_can_default (button, TRUE);
6189
6190       gtk_dialog_add_action_widget (GTK_DIALOG (dialog_window),
6191                                     button,
6192                                     RESPONSE_TOGGLE_SEPARATOR);
6193       gtk_widget_show (button);
6194     }
6195
6196   if (!gtk_widget_get_visible (dialog_window))
6197     gtk_widget_show (dialog_window);
6198   else
6199     gtk_widget_destroy (dialog_window);
6200 }
6201
6202 /* Display & Screen test 
6203  */
6204
6205 typedef struct 
6206
6207   GtkEntry *entry;
6208   GtkWidget *radio_dpy;
6209   GtkWidget *toplevel; 
6210   GtkWidget *dialog_window;
6211   GList *valid_display_list;
6212 } ScreenDisplaySelection;
6213
6214 static gint
6215 display_name_cmp (gconstpointer a,
6216                   gconstpointer b)
6217 {
6218   return g_ascii_strcasecmp (a,b);
6219 }
6220
6221 static void
6222 screen_display_check (GtkWidget *widget, ScreenDisplaySelection *data)
6223 {
6224   char *display_name;
6225   GdkDisplay *display = gtk_widget_get_display (widget);
6226   GtkWidget *dialog;
6227   GdkScreen *new_screen = NULL;
6228   GdkScreen *current_screen = gtk_widget_get_screen (widget);
6229   
6230   if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (data->radio_dpy)))
6231     {
6232       display_name = g_strdup (gtk_entry_get_text (data->entry));
6233       display = gdk_display_open (display_name);
6234       
6235       if (!display)
6236         {
6237           dialog = gtk_message_dialog_new (GTK_WINDOW (gtk_widget_get_toplevel (widget)),
6238                                            GTK_DIALOG_DESTROY_WITH_PARENT,
6239                                            GTK_MESSAGE_ERROR,
6240                                            GTK_BUTTONS_OK,
6241                                            "The display :\n%s\ncannot be opened",
6242                                            display_name);
6243           gtk_window_set_screen (GTK_WINDOW (dialog), current_screen);
6244           gtk_widget_show (dialog);
6245           g_signal_connect (dialog, "response",
6246                             G_CALLBACK (gtk_widget_destroy),
6247                             NULL);
6248         }
6249       else
6250         {
6251           if (!g_list_find_custom (data->valid_display_list, 
6252                                    display_name,
6253                                    display_name_cmp))
6254             data->valid_display_list = g_list_append (data->valid_display_list,
6255                                                       display_name);
6256           
6257           new_screen = gdk_display_get_default_screen (display);
6258         }
6259     }
6260   else
6261     {
6262       gint number_of_screens = gdk_display_get_n_screens (display);
6263       gint screen_num = gdk_screen_get_number (current_screen);
6264       if ((screen_num +1) < number_of_screens)
6265         new_screen = gdk_display_get_screen (display, screen_num + 1);
6266       else
6267         new_screen = gdk_display_get_screen (display, 0);
6268     }
6269   
6270   if (new_screen) 
6271     {
6272       gtk_window_set_screen (GTK_WINDOW (data->toplevel), new_screen);
6273       gtk_widget_destroy (data->dialog_window);
6274     }
6275 }
6276
6277 void
6278 screen_display_destroy_diag (GtkWidget *widget, GtkWidget *data)
6279 {
6280   gtk_widget_destroy (data);
6281 }
6282
6283 void
6284 create_display_screen (GtkWidget *widget)
6285 {
6286   GtkWidget *table, *frame, *window, *combo_dpy, *vbox;
6287   GtkWidget *radio_dpy, *radio_scr, *applyb, *cancelb;
6288   GtkWidget *bbox;
6289   ScreenDisplaySelection *scr_dpy_data;
6290   GdkScreen *screen = gtk_widget_get_screen (widget);
6291   static GList *valid_display_list = NULL;
6292   
6293   GdkDisplay *display = gdk_screen_get_display (screen);
6294
6295   window = g_object_new (gtk_window_get_type (),
6296                            "screen", screen,
6297                            "user_data", NULL,
6298                            "type", GTK_WINDOW_TOPLEVEL,
6299                            "title",
6300                            "Screen or Display selection",
6301                            "border_width", 10, NULL);
6302   g_signal_connect (window, "destroy", 
6303                     G_CALLBACK (gtk_widget_destroy), NULL);
6304
6305   vbox = gtk_vbox_new (FALSE, 3);
6306   gtk_container_add (GTK_CONTAINER (window), vbox);
6307   
6308   frame = gtk_frame_new ("Select screen or display");
6309   gtk_container_add (GTK_CONTAINER (vbox), frame);
6310   
6311   table = gtk_table_new (2, 2, TRUE);
6312   gtk_table_set_row_spacings (GTK_TABLE (table), 3);
6313   gtk_table_set_col_spacings (GTK_TABLE (table), 3);
6314
6315   gtk_container_add (GTK_CONTAINER (frame), table);
6316
6317   radio_dpy = gtk_radio_button_new_with_label (NULL, "move to another X display");
6318   if (gdk_display_get_n_screens(display) > 1)
6319     radio_scr = gtk_radio_button_new_with_label 
6320     (gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio_dpy)), "move to next screen");
6321   else
6322     {    
6323       radio_scr = gtk_radio_button_new_with_label 
6324         (gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio_dpy)), 
6325          "only one screen on the current display");
6326       gtk_widget_set_sensitive (radio_scr, FALSE);
6327     }
6328   combo_dpy = gtk_combo_new ();
6329   if (!valid_display_list)
6330     valid_display_list = g_list_append (valid_display_list, "diabolo:0.0");
6331     
6332   gtk_combo_set_popdown_strings (GTK_COMBO (combo_dpy), valid_display_list);
6333     
6334   gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (combo_dpy)->entry), 
6335                       "<hostname>:<X Server Num>.<Screen Num>");
6336
6337   gtk_table_attach_defaults (GTK_TABLE (table), radio_dpy, 0, 1, 0, 1);
6338   gtk_table_attach_defaults (GTK_TABLE (table), radio_scr, 0, 1, 1, 2);
6339   gtk_table_attach_defaults (GTK_TABLE (table), combo_dpy, 1, 2, 0, 1);
6340
6341   bbox = gtk_hbutton_box_new ();
6342   applyb = gtk_button_new_from_stock (GTK_STOCK_APPLY);
6343   cancelb = gtk_button_new_from_stock (GTK_STOCK_CANCEL);
6344   
6345   gtk_container_add (GTK_CONTAINER (vbox), bbox);
6346
6347   gtk_container_add (GTK_CONTAINER (bbox), applyb);
6348   gtk_container_add (GTK_CONTAINER (bbox), cancelb);
6349
6350   scr_dpy_data = g_new0 (ScreenDisplaySelection, 1);
6351
6352   scr_dpy_data->entry = GTK_ENTRY (GTK_COMBO (combo_dpy)->entry);
6353   scr_dpy_data->radio_dpy = radio_dpy;
6354   scr_dpy_data->toplevel = gtk_widget_get_toplevel (widget);
6355   scr_dpy_data->dialog_window = window;
6356   scr_dpy_data->valid_display_list = valid_display_list;
6357
6358   g_signal_connect (cancelb, "clicked", 
6359                     G_CALLBACK (screen_display_destroy_diag), window);
6360   g_signal_connect (applyb, "clicked", 
6361                     G_CALLBACK (screen_display_check), scr_dpy_data);
6362   gtk_widget_show_all (window);
6363 }
6364
6365 /* Event Watcher
6366  */
6367 static gboolean event_watcher_enter_id = 0;
6368 static gboolean event_watcher_leave_id = 0;
6369
6370 static gboolean
6371 event_watcher (GSignalInvocationHint *ihint,
6372                guint                  n_param_values,
6373                const GValue          *param_values,
6374                gpointer               data)
6375 {
6376   g_print ("Watch: \"%s\" emitted for %s\n",
6377            g_signal_name (ihint->signal_id),
6378            G_OBJECT_TYPE_NAME (g_value_get_object (param_values + 0)));
6379
6380   return TRUE;
6381 }
6382
6383 static void
6384 event_watcher_down (void)
6385 {
6386   if (event_watcher_enter_id)
6387     {
6388       guint signal_id;
6389
6390       signal_id = g_signal_lookup ("enter_notify_event", GTK_TYPE_WIDGET);
6391       g_signal_remove_emission_hook (signal_id, event_watcher_enter_id);
6392       event_watcher_enter_id = 0;
6393       signal_id = g_signal_lookup ("leave_notify_event", GTK_TYPE_WIDGET);
6394       g_signal_remove_emission_hook (signal_id, event_watcher_leave_id);
6395       event_watcher_leave_id = 0;
6396     }
6397 }
6398
6399 static void
6400 event_watcher_toggle (void)
6401 {
6402   if (event_watcher_enter_id)
6403     event_watcher_down ();
6404   else
6405     {
6406       guint signal_id;
6407
6408       signal_id = g_signal_lookup ("enter_notify_event", GTK_TYPE_WIDGET);
6409       event_watcher_enter_id = g_signal_add_emission_hook (signal_id, 0, event_watcher, NULL, NULL);
6410       signal_id = g_signal_lookup ("leave_notify_event", GTK_TYPE_WIDGET);
6411       event_watcher_leave_id = g_signal_add_emission_hook (signal_id, 0, event_watcher, NULL, NULL);
6412     }
6413 }
6414
6415 static void
6416 create_event_watcher (GtkWidget *widget)
6417 {
6418   GtkWidget *button;
6419
6420   if (!dialog_window)
6421     {
6422       dialog_window = gtk_dialog_new ();
6423       gtk_window_set_screen (GTK_WINDOW (dialog_window),
6424                              gtk_widget_get_screen (widget));
6425
6426       g_signal_connect (dialog_window, "destroy",
6427                         G_CALLBACK (gtk_widget_destroyed),
6428                         &dialog_window);
6429       g_signal_connect (dialog_window, "destroy",
6430                         G_CALLBACK (event_watcher_down),
6431                         NULL);
6432
6433       gtk_window_set_title (GTK_WINDOW (dialog_window), "Event Watcher");
6434       gtk_container_set_border_width (GTK_CONTAINER (dialog_window), 0);
6435       gtk_widget_set_size_request (dialog_window, 200, 110);
6436
6437       button = gtk_toggle_button_new_with_label ("Activate Watch");
6438       g_signal_connect (button, "clicked",
6439                         G_CALLBACK (event_watcher_toggle),
6440                         NULL);
6441       gtk_container_set_border_width (GTK_CONTAINER (button), 10);
6442       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog_window)->vbox), 
6443                           button, TRUE, TRUE, 0);
6444       gtk_widget_show (button);
6445
6446       button = gtk_button_new_with_label ("Close");
6447       g_signal_connect_swapped (button, "clicked",
6448                                 G_CALLBACK (gtk_widget_destroy),
6449                                 dialog_window);
6450       gtk_widget_set_can_default (button, TRUE);
6451       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog_window)->action_area),
6452                           button, TRUE, TRUE, 0);
6453       gtk_widget_grab_default (button);
6454       gtk_widget_show (button);
6455     }
6456
6457   if (!gtk_widget_get_visible (dialog_window))
6458     gtk_widget_show (dialog_window);
6459   else
6460     gtk_widget_destroy (dialog_window);
6461 }
6462
6463 /*
6464  * GtkRange
6465  */
6466
6467 static gchar*
6468 reformat_value (GtkScale *scale,
6469                 gdouble   value)
6470 {
6471   return g_strdup_printf ("-->%0.*g<--",
6472                           gtk_scale_get_digits (scale), value);
6473 }
6474
6475 static void
6476 create_range_controls (GtkWidget *widget)
6477 {
6478   static GtkWidget *window = NULL;
6479   GtkWidget *box1;
6480   GtkWidget *box2;
6481   GtkWidget *button;
6482   GtkWidget *scrollbar;
6483   GtkWidget *scale;
6484   GtkWidget *separator;
6485   GtkObject *adjustment;
6486   GtkWidget *hbox;
6487
6488   if (!window)
6489     {
6490       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6491
6492       gtk_window_set_screen (GTK_WINDOW (window),
6493                              gtk_widget_get_screen (widget));
6494
6495       g_signal_connect (window, "destroy",
6496                         G_CALLBACK (gtk_widget_destroyed),
6497                         &window);
6498
6499       gtk_window_set_title (GTK_WINDOW (window), "range controls");
6500       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
6501
6502
6503       box1 = gtk_vbox_new (FALSE, 0);
6504       gtk_container_add (GTK_CONTAINER (window), box1);
6505       gtk_widget_show (box1);
6506
6507
6508       box2 = gtk_vbox_new (FALSE, 10);
6509       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
6510       gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
6511       gtk_widget_show (box2);
6512
6513
6514       adjustment = gtk_adjustment_new (0.0, 0.0, 101.0, 0.1, 1.0, 1.0);
6515
6516       scale = gtk_hscale_new (GTK_ADJUSTMENT (adjustment));
6517       gtk_widget_set_size_request (GTK_WIDGET (scale), 150, -1);
6518       gtk_range_set_update_policy (GTK_RANGE (scale), GTK_UPDATE_DELAYED);
6519       gtk_scale_set_digits (GTK_SCALE (scale), 1);
6520       gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE);
6521       gtk_box_pack_start (GTK_BOX (box2), scale, TRUE, TRUE, 0);
6522       gtk_widget_show (scale);
6523
6524       scrollbar = gtk_hscrollbar_new (GTK_ADJUSTMENT (adjustment));
6525       gtk_range_set_update_policy (GTK_RANGE (scrollbar), 
6526                                    GTK_UPDATE_CONTINUOUS);
6527       gtk_box_pack_start (GTK_BOX (box2), scrollbar, TRUE, TRUE, 0);
6528       gtk_widget_show (scrollbar);
6529
6530       scale = gtk_hscale_new (GTK_ADJUSTMENT (adjustment));
6531       gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE);
6532       g_signal_connect (scale,
6533                         "format_value",
6534                         G_CALLBACK (reformat_value),
6535                         NULL);
6536       gtk_box_pack_start (GTK_BOX (box2), scale, TRUE, TRUE, 0);
6537       gtk_widget_show (scale);
6538       
6539       hbox = gtk_hbox_new (FALSE, 0);
6540
6541       scale = gtk_vscale_new (GTK_ADJUSTMENT (adjustment));
6542       gtk_widget_set_size_request (scale, -1, 200);
6543       gtk_scale_set_digits (GTK_SCALE (scale), 2);
6544       gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE);
6545       gtk_box_pack_start (GTK_BOX (hbox), scale, TRUE, TRUE, 0);
6546       gtk_widget_show (scale);
6547
6548       scale = gtk_vscale_new (GTK_ADJUSTMENT (adjustment));
6549       gtk_widget_set_size_request (scale, -1, 200);
6550       gtk_scale_set_digits (GTK_SCALE (scale), 2);
6551       gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE);
6552       gtk_range_set_inverted (GTK_RANGE (scale), TRUE);
6553       gtk_box_pack_start (GTK_BOX (hbox), scale, TRUE, TRUE, 0);
6554       gtk_widget_show (scale);
6555
6556       scale = gtk_vscale_new (GTK_ADJUSTMENT (adjustment));
6557       gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE);
6558       g_signal_connect (scale,
6559                         "format_value",
6560                         G_CALLBACK (reformat_value),
6561                         NULL);
6562       gtk_box_pack_start (GTK_BOX (hbox), scale, TRUE, TRUE, 0);
6563       gtk_widget_show (scale);
6564
6565       
6566       gtk_box_pack_start (GTK_BOX (box2), hbox, TRUE, TRUE, 0);
6567       gtk_widget_show (hbox);
6568       
6569       separator = gtk_hseparator_new ();
6570       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
6571       gtk_widget_show (separator);
6572
6573
6574       box2 = gtk_vbox_new (FALSE, 10);
6575       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
6576       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
6577       gtk_widget_show (box2);
6578
6579
6580       button = gtk_button_new_with_label ("close");
6581       g_signal_connect_swapped (button, "clicked",
6582                                 G_CALLBACK (gtk_widget_destroy),
6583                                 window);
6584       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
6585       gtk_widget_set_can_default (button, TRUE);
6586       gtk_widget_grab_default (button);
6587       gtk_widget_show (button);
6588     }
6589
6590   if (!gtk_widget_get_visible (window))
6591     gtk_widget_show (window);
6592   else
6593     gtk_widget_destroy (window);
6594 }
6595
6596 /*
6597  * GtkRulers
6598  */
6599
6600 void
6601 create_rulers (GtkWidget *widget)
6602 {
6603   static GtkWidget *window = NULL;
6604   GtkWidget *table;
6605   GtkWidget *ruler;
6606
6607   if (!window)
6608     {
6609       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6610
6611       gtk_window_set_screen (GTK_WINDOW (window),
6612                              gtk_widget_get_screen (widget));
6613
6614       g_object_set (window, "allow_shrink", TRUE, "allow_grow", TRUE, NULL);
6615
6616       g_signal_connect (window, "destroy",
6617                         G_CALLBACK (gtk_widget_destroyed),
6618                         &window);
6619
6620       gtk_window_set_title (GTK_WINDOW (window), "rulers");
6621       gtk_widget_set_size_request (window, 300, 300);
6622       gtk_widget_set_events (window, 
6623                              GDK_POINTER_MOTION_MASK 
6624                              | GDK_POINTER_MOTION_HINT_MASK);
6625       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
6626
6627       table = gtk_table_new (2, 2, FALSE);
6628       gtk_container_add (GTK_CONTAINER (window), table);
6629       gtk_widget_show (table);
6630
6631       ruler = gtk_hruler_new ();
6632       gtk_ruler_set_metric (GTK_RULER (ruler), GTK_CENTIMETERS);
6633       gtk_ruler_set_range (GTK_RULER (ruler), 100, 0, 0, 20);
6634
6635       g_signal_connect_swapped (window, 
6636                                 "motion_notify_event",
6637                                 G_CALLBACK (GTK_WIDGET_GET_CLASS (ruler)->motion_notify_event),
6638                                 ruler);
6639       
6640       gtk_table_attach (GTK_TABLE (table), ruler, 1, 2, 0, 1,
6641                         GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
6642       gtk_widget_show (ruler);
6643
6644
6645       ruler = gtk_vruler_new ();
6646       gtk_ruler_set_range (GTK_RULER (ruler), 5, 15, 0, 20);
6647
6648       g_signal_connect_swapped (window, 
6649                                 "motion_notify_event",
6650                                 G_CALLBACK (GTK_WIDGET_GET_CLASS (ruler)->motion_notify_event),
6651                                 ruler);
6652       
6653       gtk_table_attach (GTK_TABLE (table), ruler, 0, 1, 1, 2,
6654                         GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
6655       gtk_widget_show (ruler);
6656     }
6657
6658   if (!gtk_widget_get_visible (window))
6659     gtk_widget_show (window);
6660   else
6661     gtk_widget_destroy (window);
6662 }
6663
6664 static void
6665 text_toggle_editable (GtkWidget *checkbutton,
6666                        GtkWidget *text)
6667 {
6668    gtk_text_set_editable(GTK_TEXT(text),
6669                           GTK_TOGGLE_BUTTON(checkbutton)->active);
6670 }
6671
6672 static void
6673 text_toggle_word_wrap (GtkWidget *checkbutton,
6674                        GtkWidget *text)
6675 {
6676    gtk_text_set_word_wrap(GTK_TEXT(text),
6677                           GTK_TOGGLE_BUTTON(checkbutton)->active);
6678 }
6679
6680 struct {
6681   GdkColor color;
6682   gchar *name;
6683 } text_colors[] = {
6684  { { 0, 0x0000, 0x0000, 0x0000 }, "black" },
6685  { { 0, 0xFFFF, 0xFFFF, 0xFFFF }, "white" },
6686  { { 0, 0xFFFF, 0x0000, 0x0000 }, "red" },
6687  { { 0, 0x0000, 0xFFFF, 0x0000 }, "green" },
6688  { { 0, 0x0000, 0x0000, 0xFFFF }, "blue" }, 
6689  { { 0, 0x0000, 0xFFFF, 0xFFFF }, "cyan" },
6690  { { 0, 0xFFFF, 0x0000, 0xFFFF }, "magenta" },
6691  { { 0, 0xFFFF, 0xFFFF, 0x0000 }, "yellow" }
6692 };
6693
6694 int ntext_colors = sizeof(text_colors) / sizeof(text_colors[0]);
6695
6696 /*
6697  * GtkNotebook
6698  */
6699
6700 GdkPixbuf *book_open;
6701 GdkPixbuf *book_closed;
6702 GtkWidget *sample_notebook;
6703
6704 static void
6705 set_page_image (GtkNotebook *notebook, gint page_num, GdkPixbuf *pixbuf)
6706 {
6707   GtkWidget *page_widget;
6708   GtkWidget *pixwid;
6709
6710   page_widget = gtk_notebook_get_nth_page (notebook, page_num);
6711
6712   pixwid = g_object_get_data (G_OBJECT (page_widget), "tab_pixmap");
6713   gtk_image_set_from_pixbuf (GTK_IMAGE (pixwid), pixbuf);
6714   
6715   pixwid = g_object_get_data (G_OBJECT (page_widget), "menu_pixmap");
6716   gtk_image_set_from_pixbuf (GTK_IMAGE (pixwid), pixbuf);
6717 }
6718
6719 static void
6720 page_switch (GtkWidget *widget, GtkNotebookPage *page, gint page_num)
6721 {
6722   GtkNotebook *notebook = GTK_NOTEBOOK (widget);
6723   gint old_page_num = gtk_notebook_get_current_page (notebook);
6724  
6725   if (page_num == old_page_num)
6726     return;
6727
6728   set_page_image (notebook, page_num, book_open);
6729
6730   if (old_page_num != -1)
6731     set_page_image (notebook, old_page_num, book_closed);
6732 }
6733
6734 static void
6735 tab_fill (GtkToggleButton *button, GtkWidget *child)
6736 {
6737   gboolean expand;
6738   GtkPackType pack_type;
6739
6740   gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (sample_notebook), child,
6741                                         &expand, NULL, &pack_type);
6742   gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (sample_notebook), child,
6743                                       expand, button->active, pack_type);
6744 }
6745
6746 static void
6747 tab_expand (GtkToggleButton *button, GtkWidget *child)
6748 {
6749   gboolean fill;
6750   GtkPackType pack_type;
6751
6752   gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (sample_notebook), child,
6753                                         NULL, &fill, &pack_type);
6754   gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (sample_notebook), child,
6755                                       button->active, fill, pack_type);
6756 }
6757
6758 static void
6759 tab_pack (GtkToggleButton *button, GtkWidget *child)
6760           
6761
6762   gboolean expand;
6763   gboolean fill;
6764
6765   gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (sample_notebook), child,
6766                                         &expand, &fill, NULL);
6767   gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (sample_notebook), child,
6768                                       expand, fill, button->active);
6769 }
6770
6771 static void
6772 create_pages (GtkNotebook *notebook, gint start, gint end)
6773 {
6774   GtkWidget *child = NULL;
6775   GtkWidget *button;
6776   GtkWidget *label;
6777   GtkWidget *hbox;
6778   GtkWidget *vbox;
6779   GtkWidget *label_box;
6780   GtkWidget *menu_box;
6781   GtkWidget *pixwid;
6782   gint i;
6783   char buffer[32];
6784   char accel_buffer[32];
6785
6786   for (i = start; i <= end; i++)
6787     {
6788       sprintf (buffer, "Page %d", i);
6789       sprintf (accel_buffer, "Page _%d", i);
6790
6791       child = gtk_frame_new (buffer);
6792       gtk_container_set_border_width (GTK_CONTAINER (child), 10);
6793
6794       vbox = gtk_vbox_new (TRUE,0);
6795       gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
6796       gtk_container_add (GTK_CONTAINER (child), vbox);
6797
6798       hbox = gtk_hbox_new (TRUE,0);
6799       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 5);
6800
6801       button = gtk_check_button_new_with_label ("Fill Tab");
6802       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
6803       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
6804       g_signal_connect (button, "toggled",
6805                         G_CALLBACK (tab_fill), child);
6806
6807       button = gtk_check_button_new_with_label ("Expand Tab");
6808       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
6809       g_signal_connect (button, "toggled",
6810                         G_CALLBACK (tab_expand), child);
6811
6812       button = gtk_check_button_new_with_label ("Pack end");
6813       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
6814       g_signal_connect (button, "toggled",
6815                         G_CALLBACK (tab_pack), child);
6816
6817       button = gtk_button_new_with_label ("Hide Page");
6818       gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 5);
6819       g_signal_connect_swapped (button, "clicked",
6820                                 G_CALLBACK (gtk_widget_hide),
6821                                 child);
6822
6823       gtk_widget_show_all (child);
6824
6825       label_box = gtk_hbox_new (FALSE, 0);
6826       pixwid = gtk_image_new_from_pixbuf (book_closed);
6827       g_object_set_data (G_OBJECT (child), "tab_pixmap", pixwid);
6828                            
6829       gtk_box_pack_start (GTK_BOX (label_box), pixwid, FALSE, TRUE, 0);
6830       gtk_misc_set_padding (GTK_MISC (pixwid), 3, 1);
6831       label = gtk_label_new_with_mnemonic (accel_buffer);
6832       gtk_box_pack_start (GTK_BOX (label_box), label, FALSE, TRUE, 0);
6833       gtk_widget_show_all (label_box);
6834       
6835                                        
6836       menu_box = gtk_hbox_new (FALSE, 0);
6837       pixwid = gtk_image_new_from_pixbuf (book_closed);
6838       g_object_set_data (G_OBJECT (child), "menu_pixmap", pixwid);
6839       
6840       gtk_box_pack_start (GTK_BOX (menu_box), pixwid, FALSE, TRUE, 0);
6841       gtk_misc_set_padding (GTK_MISC (pixwid), 3, 1);
6842       label = gtk_label_new (buffer);
6843       gtk_box_pack_start (GTK_BOX (menu_box), label, FALSE, TRUE, 0);
6844       gtk_widget_show_all (menu_box);
6845
6846       gtk_notebook_append_page_menu (notebook, child, label_box, menu_box);
6847     }
6848 }
6849
6850 static void
6851 rotate_notebook (GtkButton   *button,
6852                  GtkNotebook *notebook)
6853 {
6854   gtk_notebook_set_tab_pos (notebook, (notebook->tab_pos + 1) % 4);
6855 }
6856
6857 static void
6858 show_all_pages (GtkButton   *button,
6859                 GtkNotebook *notebook)
6860 {  
6861   gtk_container_foreach (GTK_CONTAINER (notebook),
6862                          (GtkCallback) gtk_widget_show, NULL);
6863 }
6864
6865 static void
6866 notebook_type_changed (GtkWidget *optionmenu,
6867                        gpointer   data)
6868 {
6869   GtkNotebook *notebook;
6870   gint i, c;
6871
6872   enum {
6873     STANDARD,
6874     NOTABS,
6875     BORDERLESS,
6876     SCROLLABLE
6877   };
6878
6879   notebook = GTK_NOTEBOOK (data);
6880
6881   c = gtk_combo_box_get_active (GTK_COMBO_BOX (optionmenu));
6882
6883   switch (c)
6884     {
6885     case STANDARD:
6886       /* standard notebook */
6887       gtk_notebook_set_show_tabs (notebook, TRUE);
6888       gtk_notebook_set_show_border (notebook, TRUE);
6889       gtk_notebook_set_scrollable (notebook, FALSE);
6890       break;
6891
6892     case NOTABS:
6893       /* notabs notebook */
6894       gtk_notebook_set_show_tabs (notebook, FALSE);
6895       gtk_notebook_set_show_border (notebook, TRUE);
6896       break;
6897
6898     case BORDERLESS:
6899       /* borderless */
6900       gtk_notebook_set_show_tabs (notebook, FALSE);
6901       gtk_notebook_set_show_border (notebook, FALSE);
6902       break;
6903
6904     case SCROLLABLE:  
6905       /* scrollable */
6906       gtk_notebook_set_show_tabs (notebook, TRUE);
6907       gtk_notebook_set_show_border (notebook, TRUE);
6908       gtk_notebook_set_scrollable (notebook, TRUE);
6909       if (g_list_length (notebook->children) == 5)
6910         create_pages (notebook, 6, 15);
6911       
6912       return;
6913       break;
6914     }
6915   
6916   if (g_list_length (notebook->children) == 15)
6917     for (i = 0; i < 10; i++)
6918       gtk_notebook_remove_page (notebook, 5);
6919 }
6920
6921 static void
6922 notebook_popup (GtkToggleButton *button,
6923                 GtkNotebook     *notebook)
6924 {
6925   if (button->active)
6926     gtk_notebook_popup_enable (notebook);
6927   else
6928     gtk_notebook_popup_disable (notebook);
6929 }
6930
6931 static void
6932 notebook_homogeneous (GtkToggleButton *button,
6933                       GtkNotebook     *notebook)
6934 {
6935   g_object_set (notebook, "homogeneous", button->active, NULL);
6936 }
6937
6938 static void
6939 create_notebook (GtkWidget *widget)
6940 {
6941   static GtkWidget *window = NULL;
6942   GtkWidget *box1;
6943   GtkWidget *box2;
6944   GtkWidget *button;
6945   GtkWidget *separator;
6946   GtkWidget *omenu;
6947   GtkWidget *label;
6948   GdkPixbuf *book_open_xpm;
6949   GdkPixbuf *book_closed_xpm;
6950
6951   static gchar *items[] =
6952   {
6953     "Standard",
6954     "No tabs",
6955     "Borderless",
6956     "Scrollable"
6957   };
6958   
6959   if (!window)
6960     {
6961       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6962       gtk_window_set_screen (GTK_WINDOW (window),
6963                              gtk_widget_get_screen (widget));
6964
6965       g_signal_connect (window, "destroy",
6966                         G_CALLBACK (gtk_widget_destroyed),
6967                         &window);
6968
6969       gtk_window_set_title (GTK_WINDOW (window), "notebook");
6970       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
6971
6972       box1 = gtk_vbox_new (FALSE, 0);
6973       gtk_container_add (GTK_CONTAINER (window), box1);
6974
6975       sample_notebook = gtk_notebook_new ();
6976       g_signal_connect (sample_notebook, "switch_page",
6977                         G_CALLBACK (page_switch), NULL);
6978       gtk_notebook_set_tab_pos (GTK_NOTEBOOK (sample_notebook), GTK_POS_TOP);
6979       gtk_box_pack_start (GTK_BOX (box1), sample_notebook, TRUE, TRUE, 0);
6980       gtk_container_set_border_width (GTK_CONTAINER (sample_notebook), 10);
6981
6982       gtk_widget_realize (sample_notebook);
6983
6984       if (!book_open)
6985         book_open = gdk_pixbuf_new_from_xpm_data ((const char **)book_open_xpm);
6986                                                   
6987       if (!book_closed)
6988         book_closed = gdk_pixbuf_new_from_xpm_data ((const char **)book_closed_xpm);
6989
6990       create_pages (GTK_NOTEBOOK (sample_notebook), 1, 5);
6991
6992       separator = gtk_hseparator_new ();
6993       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 10);
6994       
6995       box2 = gtk_hbox_new (FALSE, 5);
6996       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
6997       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
6998
6999       button = gtk_check_button_new_with_label ("popup menu");
7000       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, FALSE, 0);
7001       g_signal_connect (button, "clicked",
7002                         G_CALLBACK (notebook_popup),
7003                         sample_notebook);
7004
7005       button = gtk_check_button_new_with_label ("homogeneous tabs");
7006       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, FALSE, 0);
7007       g_signal_connect (button, "clicked",
7008                         G_CALLBACK (notebook_homogeneous),
7009                         sample_notebook);
7010
7011       box2 = gtk_hbox_new (FALSE, 5);
7012       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
7013       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
7014
7015       label = gtk_label_new ("Notebook Style :");
7016       gtk_box_pack_start (GTK_BOX (box2), label, FALSE, TRUE, 0);
7017
7018       omenu = build_option_menu (items, G_N_ELEMENTS (items), 0,
7019                                  notebook_type_changed,
7020                                  sample_notebook);
7021       gtk_box_pack_start (GTK_BOX (box2), omenu, FALSE, TRUE, 0);
7022
7023       button = gtk_button_new_with_label ("Show all Pages");
7024       gtk_box_pack_start (GTK_BOX (box2), button, FALSE, TRUE, 0);
7025       g_signal_connect (button, "clicked",
7026                         G_CALLBACK (show_all_pages), sample_notebook);
7027
7028       box2 = gtk_hbox_new (TRUE, 10);
7029       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
7030       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
7031
7032       button = gtk_button_new_with_label ("prev");
7033       g_signal_connect_swapped (button, "clicked",
7034                                 G_CALLBACK (gtk_notebook_prev_page),
7035                                 sample_notebook);
7036       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
7037
7038       button = gtk_button_new_with_label ("next");
7039       g_signal_connect_swapped (button, "clicked",
7040                                 G_CALLBACK (gtk_notebook_next_page),
7041                                 sample_notebook);
7042       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
7043
7044       button = gtk_button_new_with_label ("rotate");
7045       g_signal_connect (button, "clicked",
7046                         G_CALLBACK (rotate_notebook), sample_notebook);
7047       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
7048
7049       separator = gtk_hseparator_new ();
7050       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
7051
7052       button = gtk_button_new_with_label ("close");
7053       gtk_container_set_border_width (GTK_CONTAINER (button), 5);
7054       g_signal_connect_swapped (button, "clicked",
7055                                 G_CALLBACK (gtk_widget_destroy),
7056                                 window);
7057       gtk_box_pack_start (GTK_BOX (box1), button, FALSE, FALSE, 0);
7058       gtk_widget_set_can_default (button, TRUE);
7059       gtk_widget_grab_default (button);
7060     }
7061
7062   if (!gtk_widget_get_visible (window))
7063     gtk_widget_show_all (window);
7064   else
7065     gtk_widget_destroy (window);
7066 }
7067
7068 /*
7069  * GtkPanes
7070  */
7071
7072 void
7073 toggle_resize (GtkWidget *widget, GtkWidget *child)
7074 {
7075   GtkContainer *container = GTK_CONTAINER (gtk_widget_get_parent (child));
7076   GValue value = { 0, };
7077   g_value_init (&value, G_TYPE_BOOLEAN);
7078   gtk_container_child_get_property (container, child, "resize", &value);
7079   g_value_set_boolean (&value, !g_value_get_boolean (&value));
7080   gtk_container_child_set_property (container, child, "resize", &value);
7081 }
7082
7083 void
7084 toggle_shrink (GtkWidget *widget, GtkWidget *child)
7085 {
7086   GtkContainer *container = GTK_CONTAINER (gtk_widget_get_parent (child));
7087   GValue value = { 0, };
7088   g_value_init (&value, G_TYPE_BOOLEAN);
7089   gtk_container_child_get_property (container, child, "shrink", &value);
7090   g_value_set_boolean (&value, !g_value_get_boolean (&value));
7091   gtk_container_child_set_property (container, child, "shrink", &value);
7092 }
7093
7094 static void
7095 paned_props_clicked (GtkWidget *button,
7096                      GObject   *paned)
7097 {
7098   GtkWidget *window = create_prop_editor (paned, GTK_TYPE_PANED);
7099   
7100   gtk_window_set_title (GTK_WINDOW (window), "Paned Properties");
7101 }
7102
7103 GtkWidget *
7104 create_pane_options (GtkPaned    *paned,
7105                      const gchar *frame_label,
7106                      const gchar *label1,
7107                      const gchar *label2)
7108 {
7109   GtkWidget *frame;
7110   GtkWidget *table;
7111   GtkWidget *label;
7112   GtkWidget *button;
7113   GtkWidget *check_button;
7114   
7115   frame = gtk_frame_new (frame_label);
7116   gtk_container_set_border_width (GTK_CONTAINER (frame), 4);
7117   
7118   table = gtk_table_new (4, 2, 4);
7119   gtk_container_add (GTK_CONTAINER (frame), table);
7120   
7121   label = gtk_label_new (label1);
7122   gtk_table_attach_defaults (GTK_TABLE (table), label,
7123                              0, 1, 0, 1);
7124   
7125   check_button = gtk_check_button_new_with_label ("Resize");
7126   gtk_table_attach_defaults (GTK_TABLE (table), check_button,
7127                              0, 1, 1, 2);
7128   g_signal_connect (check_button, "toggled",
7129                     G_CALLBACK (toggle_resize),
7130                     paned->child1);
7131   
7132   check_button = gtk_check_button_new_with_label ("Shrink");
7133   gtk_table_attach_defaults (GTK_TABLE (table), check_button,
7134                              0, 1, 2, 3);
7135   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button),
7136                                TRUE);
7137   g_signal_connect (check_button, "toggled",
7138                     G_CALLBACK (toggle_shrink),
7139                     paned->child1);
7140   
7141   label = gtk_label_new (label2);
7142   gtk_table_attach_defaults (GTK_TABLE (table), label,
7143                              1, 2, 0, 1);
7144   
7145   check_button = gtk_check_button_new_with_label ("Resize");
7146   gtk_table_attach_defaults (GTK_TABLE (table), check_button,
7147                              1, 2, 1, 2);
7148   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button),
7149                                TRUE);
7150   g_signal_connect (check_button, "toggled",
7151                     G_CALLBACK (toggle_resize),
7152                     paned->child2);
7153   
7154   check_button = gtk_check_button_new_with_label ("Shrink");
7155   gtk_table_attach_defaults (GTK_TABLE (table), check_button,
7156                              1, 2, 2, 3);
7157   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button),
7158                                TRUE);
7159   g_signal_connect (check_button, "toggled",
7160                     G_CALLBACK (toggle_shrink),
7161                     paned->child2);
7162
7163   button = gtk_button_new_with_mnemonic ("_Properties");
7164   gtk_table_attach_defaults (GTK_TABLE (table), button,
7165                              0, 2, 3, 4);
7166   g_signal_connect (button, "clicked",
7167                     G_CALLBACK (paned_props_clicked),
7168                     paned);
7169
7170   return frame;
7171 }
7172
7173 void
7174 create_panes (GtkWidget *widget)
7175 {
7176   static GtkWidget *window = NULL;
7177   GtkWidget *frame;
7178   GtkWidget *hpaned;
7179   GtkWidget *vpaned;
7180   GtkWidget *button;
7181   GtkWidget *vbox;
7182
7183   if (!window)
7184     {
7185       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7186
7187       gtk_window_set_screen (GTK_WINDOW (window),
7188                              gtk_widget_get_screen (widget));
7189       
7190       g_signal_connect (window, "destroy",
7191                         G_CALLBACK (gtk_widget_destroyed),
7192                         &window);
7193
7194       gtk_window_set_title (GTK_WINDOW (window), "Panes");
7195       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
7196
7197       vbox = gtk_vbox_new (FALSE, 0);
7198       gtk_container_add (GTK_CONTAINER (window), vbox);
7199       
7200       vpaned = gtk_vpaned_new ();
7201       gtk_box_pack_start (GTK_BOX (vbox), vpaned, TRUE, TRUE, 0);
7202       gtk_container_set_border_width (GTK_CONTAINER(vpaned), 5);
7203
7204       hpaned = gtk_hpaned_new ();
7205       gtk_paned_add1 (GTK_PANED (vpaned), hpaned);
7206
7207       frame = gtk_frame_new (NULL);
7208       gtk_frame_set_shadow_type (GTK_FRAME(frame), GTK_SHADOW_IN);
7209       gtk_widget_set_size_request (frame, 60, 60);
7210       gtk_paned_add1 (GTK_PANED (hpaned), frame);
7211       
7212       button = gtk_button_new_with_label ("Hi there");
7213       gtk_container_add (GTK_CONTAINER(frame), button);
7214
7215       frame = gtk_frame_new (NULL);
7216       gtk_frame_set_shadow_type (GTK_FRAME(frame), GTK_SHADOW_IN);
7217       gtk_widget_set_size_request (frame, 80, 60);
7218       gtk_paned_add2 (GTK_PANED (hpaned), frame);
7219
7220       frame = gtk_frame_new (NULL);
7221       gtk_frame_set_shadow_type (GTK_FRAME(frame), GTK_SHADOW_IN);
7222       gtk_widget_set_size_request (frame, 60, 80);
7223       gtk_paned_add2 (GTK_PANED (vpaned), frame);
7224
7225       /* Now create toggle buttons to control sizing */
7226
7227       gtk_box_pack_start (GTK_BOX (vbox),
7228                           create_pane_options (GTK_PANED (hpaned),
7229                                                "Horizontal",
7230                                                "Left",
7231                                                "Right"),
7232                           FALSE, FALSE, 0);
7233
7234       gtk_box_pack_start (GTK_BOX (vbox),
7235                           create_pane_options (GTK_PANED (vpaned),
7236                                                "Vertical",
7237                                                "Top",
7238                                                "Bottom"),
7239                           FALSE, FALSE, 0);
7240
7241       gtk_widget_show_all (vbox);
7242     }
7243
7244   if (!gtk_widget_get_visible (window))
7245     gtk_widget_show (window);
7246   else
7247     gtk_widget_destroy (window);
7248 }
7249
7250 /*
7251  * Paned keyboard navigation
7252  */
7253
7254 static GtkWidget*
7255 paned_keyboard_window1 (GtkWidget *widget)
7256 {
7257   GtkWidget *window1;
7258   GtkWidget *hpaned1;
7259   GtkWidget *frame1;
7260   GtkWidget *vbox1;
7261   GtkWidget *button7;
7262   GtkWidget *button8;
7263   GtkWidget *button9;
7264   GtkWidget *vpaned1;
7265   GtkWidget *frame2;
7266   GtkWidget *frame5;
7267   GtkWidget *hbox1;
7268   GtkWidget *button5;
7269   GtkWidget *button6;
7270   GtkWidget *frame3;
7271   GtkWidget *frame4;
7272   GtkWidget *table1;
7273   GtkWidget *button1;
7274   GtkWidget *button2;
7275   GtkWidget *button3;
7276   GtkWidget *button4;
7277
7278   window1 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7279   gtk_window_set_title (GTK_WINDOW (window1), "Basic paned navigation");
7280   gtk_window_set_screen (GTK_WINDOW (window1), 
7281                          gtk_widget_get_screen (widget));
7282
7283   hpaned1 = gtk_hpaned_new ();
7284   gtk_container_add (GTK_CONTAINER (window1), hpaned1);
7285
7286   frame1 = gtk_frame_new (NULL);
7287   gtk_paned_pack1 (GTK_PANED (hpaned1), frame1, FALSE, TRUE);
7288   gtk_frame_set_shadow_type (GTK_FRAME (frame1), GTK_SHADOW_IN);
7289
7290   vbox1 = gtk_vbox_new (FALSE, 0);
7291   gtk_container_add (GTK_CONTAINER (frame1), vbox1);
7292
7293   button7 = gtk_button_new_with_label ("button7");
7294   gtk_box_pack_start (GTK_BOX (vbox1), button7, FALSE, FALSE, 0);
7295
7296   button8 = gtk_button_new_with_label ("button8");
7297   gtk_box_pack_start (GTK_BOX (vbox1), button8, FALSE, FALSE, 0);
7298
7299   button9 = gtk_button_new_with_label ("button9");
7300   gtk_box_pack_start (GTK_BOX (vbox1), button9, FALSE, FALSE, 0);
7301
7302   vpaned1 = gtk_vpaned_new ();
7303   gtk_paned_pack2 (GTK_PANED (hpaned1), vpaned1, TRUE, TRUE);
7304
7305   frame2 = gtk_frame_new (NULL);
7306   gtk_paned_pack1 (GTK_PANED (vpaned1), frame2, FALSE, TRUE);
7307   gtk_frame_set_shadow_type (GTK_FRAME (frame2), GTK_SHADOW_IN);
7308
7309   frame5 = gtk_frame_new (NULL);
7310   gtk_container_add (GTK_CONTAINER (frame2), frame5);
7311
7312   hbox1 = gtk_hbox_new (FALSE, 0);
7313   gtk_container_add (GTK_CONTAINER (frame5), hbox1);
7314
7315   button5 = gtk_button_new_with_label ("button5");
7316   gtk_box_pack_start (GTK_BOX (hbox1), button5, FALSE, FALSE, 0);
7317
7318   button6 = gtk_button_new_with_label ("button6");
7319   gtk_box_pack_start (GTK_BOX (hbox1), button6, FALSE, FALSE, 0);
7320
7321   frame3 = gtk_frame_new (NULL);
7322   gtk_paned_pack2 (GTK_PANED (vpaned1), frame3, TRUE, TRUE);
7323   gtk_frame_set_shadow_type (GTK_FRAME (frame3), GTK_SHADOW_IN);
7324
7325   frame4 = gtk_frame_new ("Buttons");
7326   gtk_container_add (GTK_CONTAINER (frame3), frame4);
7327   gtk_container_set_border_width (GTK_CONTAINER (frame4), 15);
7328
7329   table1 = gtk_table_new (2, 2, FALSE);
7330   gtk_container_add (GTK_CONTAINER (frame4), table1);
7331   gtk_container_set_border_width (GTK_CONTAINER (table1), 11);
7332
7333   button1 = gtk_button_new_with_label ("button1");
7334   gtk_table_attach (GTK_TABLE (table1), button1, 0, 1, 0, 1,
7335                     (GtkAttachOptions) (GTK_FILL),
7336                     (GtkAttachOptions) (0), 0, 0);
7337
7338   button2 = gtk_button_new_with_label ("button2");
7339   gtk_table_attach (GTK_TABLE (table1), button2, 1, 2, 0, 1,
7340                     (GtkAttachOptions) (GTK_FILL),
7341                     (GtkAttachOptions) (0), 0, 0);
7342
7343   button3 = gtk_button_new_with_label ("button3");
7344   gtk_table_attach (GTK_TABLE (table1), button3, 0, 1, 1, 2,
7345                     (GtkAttachOptions) (GTK_FILL),
7346                     (GtkAttachOptions) (0), 0, 0);
7347
7348   button4 = gtk_button_new_with_label ("button4");
7349   gtk_table_attach (GTK_TABLE (table1), button4, 1, 2, 1, 2,
7350                     (GtkAttachOptions) (GTK_FILL),
7351                     (GtkAttachOptions) (0), 0, 0);
7352
7353   return window1;
7354 }
7355
7356 static GtkWidget*
7357 paned_keyboard_window2 (GtkWidget *widget)
7358 {
7359   GtkWidget *window2;
7360   GtkWidget *hpaned2;
7361   GtkWidget *frame6;
7362   GtkWidget *button13;
7363   GtkWidget *hbox2;
7364   GtkWidget *vpaned2;
7365   GtkWidget *frame7;
7366   GtkWidget *button12;
7367   GtkWidget *frame8;
7368   GtkWidget *button11;
7369   GtkWidget *button10;
7370
7371   window2 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7372   gtk_window_set_title (GTK_WINDOW (window2), "\"button 10\" is not inside the horisontal pane");
7373
7374   gtk_window_set_screen (GTK_WINDOW (window2), 
7375                          gtk_widget_get_screen (widget));
7376
7377   hpaned2 = gtk_hpaned_new ();
7378   gtk_container_add (GTK_CONTAINER (window2), hpaned2);
7379
7380   frame6 = gtk_frame_new (NULL);
7381   gtk_paned_pack1 (GTK_PANED (hpaned2), frame6, FALSE, TRUE);
7382   gtk_frame_set_shadow_type (GTK_FRAME (frame6), GTK_SHADOW_IN);
7383
7384   button13 = gtk_button_new_with_label ("button13");
7385   gtk_container_add (GTK_CONTAINER (frame6), button13);
7386
7387   hbox2 = gtk_hbox_new (FALSE, 0);
7388   gtk_paned_pack2 (GTK_PANED (hpaned2), hbox2, TRUE, TRUE);
7389
7390   vpaned2 = gtk_vpaned_new ();
7391   gtk_box_pack_start (GTK_BOX (hbox2), vpaned2, TRUE, TRUE, 0);
7392
7393   frame7 = gtk_frame_new (NULL);
7394   gtk_paned_pack1 (GTK_PANED (vpaned2), frame7, FALSE, TRUE);
7395   gtk_frame_set_shadow_type (GTK_FRAME (frame7), GTK_SHADOW_IN);
7396
7397   button12 = gtk_button_new_with_label ("button12");
7398   gtk_container_add (GTK_CONTAINER (frame7), button12);
7399
7400   frame8 = gtk_frame_new (NULL);
7401   gtk_paned_pack2 (GTK_PANED (vpaned2), frame8, TRUE, TRUE);
7402   gtk_frame_set_shadow_type (GTK_FRAME (frame8), GTK_SHADOW_IN);
7403
7404   button11 = gtk_button_new_with_label ("button11");
7405   gtk_container_add (GTK_CONTAINER (frame8), button11);
7406
7407   button10 = gtk_button_new_with_label ("button10");
7408   gtk_box_pack_start (GTK_BOX (hbox2), button10, FALSE, FALSE, 0);
7409
7410   return window2;
7411 }
7412
7413 static GtkWidget*
7414 paned_keyboard_window3 (GtkWidget *widget)
7415 {
7416   GtkWidget *window3;
7417   GtkWidget *vbox2;
7418   GtkWidget *label1;
7419   GtkWidget *hpaned3;
7420   GtkWidget *frame9;
7421   GtkWidget *button14;
7422   GtkWidget *hpaned4;
7423   GtkWidget *frame10;
7424   GtkWidget *button15;
7425   GtkWidget *hpaned5;
7426   GtkWidget *frame11;
7427   GtkWidget *button16;
7428   GtkWidget *frame12;
7429   GtkWidget *button17;
7430
7431   window3 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7432   g_object_set_data (G_OBJECT (window3), "window3", window3);
7433   gtk_window_set_title (GTK_WINDOW (window3), "Nested panes");
7434
7435   gtk_window_set_screen (GTK_WINDOW (window3), 
7436                          gtk_widget_get_screen (widget));
7437   
7438
7439   vbox2 = gtk_vbox_new (FALSE, 0);
7440   gtk_container_add (GTK_CONTAINER (window3), vbox2);
7441
7442   label1 = gtk_label_new ("Three panes nested inside each other");
7443   gtk_box_pack_start (GTK_BOX (vbox2), label1, FALSE, FALSE, 0);
7444
7445   hpaned3 = gtk_hpaned_new ();
7446   gtk_box_pack_start (GTK_BOX (vbox2), hpaned3, TRUE, TRUE, 0);
7447
7448   frame9 = gtk_frame_new (NULL);
7449   gtk_paned_pack1 (GTK_PANED (hpaned3), frame9, FALSE, TRUE);
7450   gtk_frame_set_shadow_type (GTK_FRAME (frame9), GTK_SHADOW_IN);
7451
7452   button14 = gtk_button_new_with_label ("button14");
7453   gtk_container_add (GTK_CONTAINER (frame9), button14);
7454
7455   hpaned4 = gtk_hpaned_new ();
7456   gtk_paned_pack2 (GTK_PANED (hpaned3), hpaned4, TRUE, TRUE);
7457
7458   frame10 = gtk_frame_new (NULL);
7459   gtk_paned_pack1 (GTK_PANED (hpaned4), frame10, FALSE, TRUE);
7460   gtk_frame_set_shadow_type (GTK_FRAME (frame10), GTK_SHADOW_IN);
7461
7462   button15 = gtk_button_new_with_label ("button15");
7463   gtk_container_add (GTK_CONTAINER (frame10), button15);
7464
7465   hpaned5 = gtk_hpaned_new ();
7466   gtk_paned_pack2 (GTK_PANED (hpaned4), hpaned5, TRUE, TRUE);
7467
7468   frame11 = gtk_frame_new (NULL);
7469   gtk_paned_pack1 (GTK_PANED (hpaned5), frame11, FALSE, TRUE);
7470   gtk_frame_set_shadow_type (GTK_FRAME (frame11), GTK_SHADOW_IN);
7471
7472   button16 = gtk_button_new_with_label ("button16");
7473   gtk_container_add (GTK_CONTAINER (frame11), button16);
7474
7475   frame12 = gtk_frame_new (NULL);
7476   gtk_paned_pack2 (GTK_PANED (hpaned5), frame12, TRUE, TRUE);
7477   gtk_frame_set_shadow_type (GTK_FRAME (frame12), GTK_SHADOW_IN);
7478
7479   button17 = gtk_button_new_with_label ("button17");
7480   gtk_container_add (GTK_CONTAINER (frame12), button17);
7481
7482   return window3;
7483 }
7484
7485 static GtkWidget*
7486 paned_keyboard_window4 (GtkWidget *widget)
7487 {
7488   GtkWidget *window4;
7489   GtkWidget *vbox3;
7490   GtkWidget *label2;
7491   GtkWidget *hpaned6;
7492   GtkWidget *vpaned3;
7493   GtkWidget *button19;
7494   GtkWidget *button18;
7495   GtkWidget *hbox3;
7496   GtkWidget *vpaned4;
7497   GtkWidget *button21;
7498   GtkWidget *button20;
7499   GtkWidget *vpaned5;
7500   GtkWidget *button23;
7501   GtkWidget *button22;
7502   GtkWidget *vpaned6;
7503   GtkWidget *button25;
7504   GtkWidget *button24;
7505
7506   window4 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7507   g_object_set_data (G_OBJECT (window4), "window4", window4);
7508   gtk_window_set_title (GTK_WINDOW (window4), "window4");
7509
7510   gtk_window_set_screen (GTK_WINDOW (window4), 
7511                          gtk_widget_get_screen (widget));
7512
7513   vbox3 = gtk_vbox_new (FALSE, 0);
7514   gtk_container_add (GTK_CONTAINER (window4), vbox3);
7515
7516   label2 = gtk_label_new ("Widget tree:\n\nhpaned \n - vpaned\n - hbox\n    - vpaned\n    - vpaned\n    - vpaned\n");
7517   gtk_box_pack_start (GTK_BOX (vbox3), label2, FALSE, FALSE, 0);
7518   gtk_label_set_justify (GTK_LABEL (label2), GTK_JUSTIFY_LEFT);
7519
7520   hpaned6 = gtk_hpaned_new ();
7521   gtk_box_pack_start (GTK_BOX (vbox3), hpaned6, TRUE, TRUE, 0);
7522
7523   vpaned3 = gtk_vpaned_new ();
7524   gtk_paned_pack1 (GTK_PANED (hpaned6), vpaned3, FALSE, TRUE);
7525
7526   button19 = gtk_button_new_with_label ("button19");
7527   gtk_paned_pack1 (GTK_PANED (vpaned3), button19, FALSE, TRUE);
7528
7529   button18 = gtk_button_new_with_label ("button18");
7530   gtk_paned_pack2 (GTK_PANED (vpaned3), button18, TRUE, TRUE);
7531
7532   hbox3 = gtk_hbox_new (FALSE, 0);
7533   gtk_paned_pack2 (GTK_PANED (hpaned6), hbox3, TRUE, TRUE);
7534
7535   vpaned4 = gtk_vpaned_new ();
7536   gtk_box_pack_start (GTK_BOX (hbox3), vpaned4, TRUE, TRUE, 0);
7537
7538   button21 = gtk_button_new_with_label ("button21");
7539   gtk_paned_pack1 (GTK_PANED (vpaned4), button21, FALSE, TRUE);
7540
7541   button20 = gtk_button_new_with_label ("button20");
7542   gtk_paned_pack2 (GTK_PANED (vpaned4), button20, TRUE, TRUE);
7543
7544   vpaned5 = gtk_vpaned_new ();
7545   gtk_box_pack_start (GTK_BOX (hbox3), vpaned5, TRUE, TRUE, 0);
7546
7547   button23 = gtk_button_new_with_label ("button23");
7548   gtk_paned_pack1 (GTK_PANED (vpaned5), button23, FALSE, TRUE);
7549
7550   button22 = gtk_button_new_with_label ("button22");
7551   gtk_paned_pack2 (GTK_PANED (vpaned5), button22, TRUE, TRUE);
7552
7553   vpaned6 = gtk_vpaned_new ();
7554   gtk_box_pack_start (GTK_BOX (hbox3), vpaned6, TRUE, TRUE, 0);
7555
7556   button25 = gtk_button_new_with_label ("button25");
7557   gtk_paned_pack1 (GTK_PANED (vpaned6), button25, FALSE, TRUE);
7558
7559   button24 = gtk_button_new_with_label ("button24");
7560   gtk_paned_pack2 (GTK_PANED (vpaned6), button24, TRUE, TRUE);
7561
7562   return window4;
7563 }
7564
7565 static void
7566 create_paned_keyboard_navigation (GtkWidget *widget)
7567 {
7568   static GtkWidget *window1 = NULL;
7569   static GtkWidget *window2 = NULL;
7570   static GtkWidget *window3 = NULL;
7571   static GtkWidget *window4 = NULL;
7572
7573   if (window1 && 
7574      (gtk_widget_get_screen (window1) != gtk_widget_get_screen (widget)))
7575     {
7576       gtk_widget_destroy (window1);
7577       gtk_widget_destroy (window2);
7578       gtk_widget_destroy (window3);
7579       gtk_widget_destroy (window4);
7580     }
7581   
7582   if (!window1)
7583     {
7584       window1 = paned_keyboard_window1 (widget);
7585       g_signal_connect (window1, "destroy",
7586                         G_CALLBACK (gtk_widget_destroyed),
7587                         &window1);
7588     }
7589
7590   if (!window2)
7591     {
7592       window2 = paned_keyboard_window2 (widget);
7593       g_signal_connect (window2, "destroy",
7594                         G_CALLBACK (gtk_widget_destroyed),
7595                         &window2);
7596     }
7597
7598   if (!window3)
7599     {
7600       window3 = paned_keyboard_window3 (widget);
7601       g_signal_connect (window3, "destroy",
7602                         G_CALLBACK (gtk_widget_destroyed),
7603                         &window3);
7604     }
7605
7606   if (!window4)
7607     {
7608       window4 = paned_keyboard_window4 (widget);
7609       g_signal_connect (window4, "destroy",
7610                         G_CALLBACK (gtk_widget_destroyed),
7611                         &window4);
7612     }
7613
7614   if (gtk_widget_get_visible (window1))
7615     gtk_widget_destroy (GTK_WIDGET (window1));
7616   else
7617     gtk_widget_show_all (GTK_WIDGET (window1));
7618
7619   if (gtk_widget_get_visible (window2))
7620     gtk_widget_destroy (GTK_WIDGET (window2));
7621   else
7622     gtk_widget_show_all (GTK_WIDGET (window2));
7623
7624   if (gtk_widget_get_visible (window3))
7625     gtk_widget_destroy (GTK_WIDGET (window3));
7626   else
7627     gtk_widget_show_all (GTK_WIDGET (window3));
7628
7629   if (gtk_widget_get_visible (window4))
7630     gtk_widget_destroy (GTK_WIDGET (window4));
7631   else
7632     gtk_widget_show_all (GTK_WIDGET (window4));
7633 }
7634
7635
7636 /*
7637  * Shaped Windows
7638  */
7639
7640 typedef struct _cursoroffset {gint x,y;} CursorOffset;
7641
7642 static void
7643 shape_pressed (GtkWidget *widget, GdkEventButton *event)
7644 {
7645   CursorOffset *p;
7646
7647   /* ignore double and triple click */
7648   if (event->type != GDK_BUTTON_PRESS)
7649     return;
7650
7651   p = g_object_get_data (G_OBJECT (widget), "cursor_offset");
7652   p->x = (int) event->x;
7653   p->y = (int) event->y;
7654
7655   gtk_grab_add (widget);
7656   gdk_pointer_grab (widget->window, TRUE,
7657                     GDK_BUTTON_RELEASE_MASK |
7658                     GDK_BUTTON_MOTION_MASK |
7659                     GDK_POINTER_MOTION_HINT_MASK,
7660                     NULL, NULL, 0);
7661 }
7662
7663 static void
7664 shape_released (GtkWidget *widget)
7665 {
7666   gtk_grab_remove (widget);
7667   gdk_display_pointer_ungrab (gtk_widget_get_display (widget),
7668                               GDK_CURRENT_TIME);
7669 }
7670
7671 static void
7672 shape_motion (GtkWidget      *widget, 
7673               GdkEventMotion *event)
7674 {
7675   gint xp, yp;
7676   CursorOffset * p;
7677   GdkModifierType mask;
7678
7679   p = g_object_get_data (G_OBJECT (widget), "cursor_offset");
7680
7681   /*
7682    * Can't use event->x / event->y here 
7683    * because I need absolute coordinates.
7684    */
7685   gdk_window_get_pointer (NULL, &xp, &yp, &mask);
7686   gtk_widget_set_uposition (widget, xp  - p->x, yp  - p->y);
7687 }
7688
7689 GtkWidget *
7690 shape_create_icon (GdkScreen *screen,
7691                    char      *xpm_file,
7692                    gint       x,
7693                    gint       y,
7694                    gint       px,
7695                    gint       py,
7696                    gint       window_type)
7697 {
7698   GtkWidget *window;
7699   GtkWidget *pixmap;
7700   GtkWidget *fixed;
7701   CursorOffset* icon_pos;
7702   GdkGC* gc;
7703   GdkBitmap *gdk_pixmap_mask;
7704   GdkPixmap *gdk_pixmap;
7705   GtkStyle *style;
7706
7707   style = gtk_widget_get_default_style ();
7708   gc = style->black_gc; 
7709
7710   /*
7711    * GDK_WINDOW_TOPLEVEL works also, giving you a title border
7712    */
7713   window = gtk_window_new (window_type);
7714   gtk_window_set_screen (GTK_WINDOW (window), screen);
7715   
7716   fixed = gtk_fixed_new ();
7717   gtk_widget_set_size_request (fixed, 100, 100);
7718   gtk_container_add (GTK_CONTAINER (window), fixed);
7719   gtk_widget_show (fixed);
7720   
7721   gtk_widget_set_events (window, 
7722                          gtk_widget_get_events (window) |
7723                          GDK_BUTTON_MOTION_MASK |
7724                          GDK_POINTER_MOTION_HINT_MASK |
7725                          GDK_BUTTON_PRESS_MASK);
7726
7727   gtk_widget_realize (window);
7728   gdk_pixmap = gdk_pixmap_create_from_xpm (window->window, &gdk_pixmap_mask, 
7729                                            &style->bg[GTK_STATE_NORMAL],
7730                                            xpm_file);
7731
7732   pixmap = gtk_image_new_from_pixmap (gdk_pixmap, gdk_pixmap_mask);
7733   gtk_fixed_put (GTK_FIXED (fixed), pixmap, px,py);
7734   gtk_widget_show (pixmap);
7735   
7736   gtk_widget_shape_combine_mask (window, gdk_pixmap_mask, px, py);
7737   
7738   g_object_unref (gdk_pixmap_mask);
7739   g_object_unref (gdk_pixmap);
7740
7741   g_signal_connect (window, "button_press_event",
7742                     G_CALLBACK (shape_pressed), NULL);
7743   g_signal_connect (window, "button_release_event",
7744                     G_CALLBACK (shape_released), NULL);
7745   g_signal_connect (window, "motion_notify_event",
7746                     G_CALLBACK (shape_motion), NULL);
7747
7748   icon_pos = g_new (CursorOffset, 1);
7749   g_object_set_data (G_OBJECT (window), "cursor_offset", icon_pos);
7750
7751   gtk_widget_set_uposition (window, x, y);
7752   gtk_widget_show (window);
7753   
7754   return window;
7755 }
7756
7757 void 
7758 create_shapes (GtkWidget *widget)
7759 {
7760   /* Variables used by the Drag/Drop and Shape Window demos */
7761   static GtkWidget *modeller = NULL;
7762   static GtkWidget *sheets = NULL;
7763   static GtkWidget *rings = NULL;
7764   static GtkWidget *with_region = NULL;
7765   GdkScreen *screen = gtk_widget_get_screen (widget);
7766   
7767   if (!(file_exists ("Modeller.xpm") &&
7768         file_exists ("FilesQueue.xpm") &&
7769         file_exists ("3DRings.xpm")))
7770     return;
7771   
7772
7773   if (!modeller)
7774     {
7775       modeller = shape_create_icon (screen, "Modeller.xpm",
7776                                     440, 140, 0,0, GTK_WINDOW_POPUP);
7777
7778       g_signal_connect (modeller, "destroy",
7779                         G_CALLBACK (gtk_widget_destroyed),
7780                         &modeller);
7781     }
7782   else
7783     gtk_widget_destroy (modeller);
7784
7785   if (!sheets)
7786     {
7787       sheets = shape_create_icon (screen, "FilesQueue.xpm",
7788                                   580, 170, 0,0, GTK_WINDOW_POPUP);
7789
7790       g_signal_connect (sheets, "destroy",
7791                         G_CALLBACK (gtk_widget_destroyed),
7792                         &sheets);
7793
7794     }
7795   else
7796     gtk_widget_destroy (sheets);
7797
7798   if (!rings)
7799     {
7800       rings = shape_create_icon (screen, "3DRings.xpm",
7801                                  460, 270, 25,25, GTK_WINDOW_TOPLEVEL);
7802
7803       g_signal_connect (rings, "destroy",
7804                         G_CALLBACK (gtk_widget_destroyed),
7805                         &rings);
7806     }
7807   else
7808     gtk_widget_destroy (rings);
7809
7810   if (!with_region)
7811     {
7812       GdkRegion *region;
7813       gint x, y;
7814       
7815       with_region = shape_create_icon (screen, "3DRings.xpm",
7816                                        460, 270, 25,25, GTK_WINDOW_TOPLEVEL);
7817
7818       gtk_window_set_decorated (GTK_WINDOW (with_region), FALSE);
7819       
7820       g_signal_connect (with_region, "destroy",
7821                         G_CALLBACK (gtk_widget_destroyed),
7822                         &with_region);
7823
7824       /* reset shape from mask to a region */
7825       x = 0;
7826       y = 0;
7827       region = gdk_region_new ();
7828
7829       while (x < 460)
7830         {
7831           while (y < 270)
7832             {
7833               GdkRectangle rect;
7834               rect.x = x;
7835               rect.y = y;
7836               rect.width = 10;
7837               rect.height = 10;
7838
7839               gdk_region_union_with_rect (region, &rect);
7840               
7841               y += 20;
7842             }
7843           y = 0;
7844           x += 20;
7845         }
7846
7847       gdk_window_shape_combine_region (with_region->window,
7848                                        region,
7849                                        0, 0);
7850     }
7851   else
7852     gtk_widget_destroy (with_region);
7853 }
7854
7855 /*
7856  * WM Hints demo
7857  */
7858
7859 void
7860 create_wmhints (GtkWidget *widget)
7861 {
7862   static GtkWidget *window = NULL;
7863   GtkWidget *label;
7864   GtkWidget *separator;
7865   GtkWidget *button;
7866   GtkWidget *box1;
7867   GtkWidget *box2;
7868
7869   GdkBitmap *circles;
7870
7871   if (!window)
7872     {
7873       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7874
7875       gtk_window_set_screen (GTK_WINDOW (window),
7876                              gtk_widget_get_screen (widget));
7877       
7878       g_signal_connect (window, "destroy",
7879                         G_CALLBACK (gtk_widget_destroyed),
7880                         &window);
7881
7882       gtk_window_set_title (GTK_WINDOW (window), "WM Hints");
7883       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
7884
7885       gtk_widget_realize (window);
7886       
7887       circles = gdk_bitmap_create_from_data (window->window,
7888                                              (gchar *) circles_bits,
7889                                              circles_width,
7890                                              circles_height);
7891       gdk_window_set_icon (window->window, NULL,
7892                            circles, circles);
7893       
7894       gdk_window_set_icon_name (window->window, "WMHints Test Icon");
7895   
7896       gdk_window_set_decorations (window->window, GDK_DECOR_ALL | GDK_DECOR_MENU);
7897       gdk_window_set_functions (window->window, GDK_FUNC_ALL | GDK_FUNC_RESIZE);
7898       
7899       box1 = gtk_vbox_new (FALSE, 0);
7900       gtk_container_add (GTK_CONTAINER (window), box1);
7901       gtk_widget_show (box1);
7902
7903       label = gtk_label_new ("Try iconizing me!");
7904       gtk_widget_set_size_request (label, 150, 50);
7905       gtk_box_pack_start (GTK_BOX (box1), label, TRUE, TRUE, 0);
7906       gtk_widget_show (label);
7907
7908
7909       separator = gtk_hseparator_new ();
7910       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
7911       gtk_widget_show (separator);
7912
7913
7914       box2 = gtk_vbox_new (FALSE, 10);
7915       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
7916       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
7917       gtk_widget_show (box2);
7918
7919
7920       button = gtk_button_new_with_label ("close");
7921
7922       g_signal_connect_swapped (button, "clicked",
7923                                 G_CALLBACK (gtk_widget_destroy),
7924                                 window);
7925
7926       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
7927       gtk_widget_set_can_default (button, TRUE);
7928       gtk_widget_grab_default (button);
7929       gtk_widget_show (button);
7930     }
7931
7932   if (!gtk_widget_get_visible (window))
7933     gtk_widget_show (window);
7934   else
7935     gtk_widget_destroy (window);
7936 }
7937
7938
7939 /*
7940  * Window state tracking
7941  */
7942
7943 static gint
7944 window_state_callback (GtkWidget *widget,
7945                        GdkEventWindowState *event,
7946                        gpointer data)
7947 {
7948   GtkWidget *label = data;
7949   gchar *msg;
7950
7951   msg = g_strconcat (GTK_WINDOW (widget)->title, ": ",
7952                      (event->new_window_state & GDK_WINDOW_STATE_WITHDRAWN) ?
7953                      "withdrawn" : "not withdrawn", ", ",
7954                      (event->new_window_state & GDK_WINDOW_STATE_ICONIFIED) ?
7955                      "iconified" : "not iconified", ", ",
7956                      (event->new_window_state & GDK_WINDOW_STATE_STICKY) ?
7957                      "sticky" : "not sticky", ", ",
7958                      (event->new_window_state & GDK_WINDOW_STATE_MAXIMIZED) ?
7959                      "maximized" : "not maximized", ", ",
7960                      (event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN) ?
7961                      "fullscreen" : "not fullscreen",
7962                      (event->new_window_state & GDK_WINDOW_STATE_ABOVE) ?
7963                      "above" : "not above", ", ",
7964                      (event->new_window_state & GDK_WINDOW_STATE_BELOW) ?
7965                      "below" : "not below", ", ",
7966                      NULL);
7967   
7968   gtk_label_set_text (GTK_LABEL (label), msg);
7969
7970   g_free (msg);
7971
7972   return FALSE;
7973 }
7974
7975 static GtkWidget*
7976 tracking_label (GtkWidget *window)
7977 {
7978   GtkWidget *label;
7979   GtkWidget *hbox;
7980   GtkWidget *button;
7981
7982   hbox = gtk_hbox_new (FALSE, 5);
7983
7984   g_signal_connect_object (hbox,
7985                            "destroy",
7986                            G_CALLBACK (gtk_widget_destroy),
7987                            window,
7988                            G_CONNECT_SWAPPED);
7989   
7990   label = gtk_label_new ("<no window state events received>");
7991   gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
7992   gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
7993   
7994   g_signal_connect (window,
7995                     "window_state_event",
7996                     G_CALLBACK (window_state_callback),
7997                     label);
7998
7999   button = gtk_button_new_with_label ("Deiconify");
8000   g_signal_connect_object (button,
8001                            "clicked",
8002                            G_CALLBACK (gtk_window_deiconify),
8003                            window,
8004                            G_CONNECT_SWAPPED);
8005   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
8006
8007   button = gtk_button_new_with_label ("Iconify");
8008   g_signal_connect_object (button,
8009                            "clicked",
8010                            G_CALLBACK (gtk_window_iconify),
8011                            window,
8012                            G_CONNECT_SWAPPED);
8013   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
8014
8015   button = gtk_button_new_with_label ("Fullscreen");
8016   g_signal_connect_object (button,
8017                            "clicked",
8018                            G_CALLBACK (gtk_window_fullscreen),
8019                            window,
8020                            G_CONNECT_SWAPPED);
8021   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
8022
8023   button = gtk_button_new_with_label ("Unfullscreen");
8024   g_signal_connect_object (button,
8025                            "clicked",
8026                            G_CALLBACK (gtk_window_unfullscreen),
8027                            window,
8028                            G_CONNECT_SWAPPED);
8029   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
8030   
8031   button = gtk_button_new_with_label ("Present");
8032   g_signal_connect_object (button,
8033                            "clicked",
8034                            G_CALLBACK (gtk_window_present),
8035                            window,
8036                            G_CONNECT_SWAPPED);
8037   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
8038
8039   button = gtk_button_new_with_label ("Show");
8040   g_signal_connect_object (button,
8041                            "clicked",
8042                            G_CALLBACK (gtk_widget_show),
8043                            window,
8044                            G_CONNECT_SWAPPED);
8045   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
8046   
8047   gtk_widget_show_all (hbox);
8048   
8049   return hbox;
8050 }
8051
8052 void
8053 keep_window_above (GtkToggleButton *togglebutton, gpointer data)
8054 {
8055   GtkWidget *button = g_object_get_data (G_OBJECT (togglebutton), "radio");
8056
8057   gtk_window_set_keep_above (GTK_WINDOW (data),
8058                              gtk_toggle_button_get_active (togglebutton));
8059
8060   if (gtk_toggle_button_get_active (togglebutton))
8061     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE);
8062 }
8063
8064 void
8065 keep_window_below (GtkToggleButton *togglebutton, gpointer data)
8066 {
8067   GtkWidget *button = g_object_get_data (G_OBJECT (togglebutton), "radio");
8068
8069   gtk_window_set_keep_below (GTK_WINDOW (data),
8070                              gtk_toggle_button_get_active (togglebutton));
8071
8072   if (gtk_toggle_button_get_active (togglebutton))
8073     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE);
8074 }
8075
8076
8077 static GtkWidget*
8078 get_state_controls (GtkWidget *window)
8079 {
8080   GtkWidget *vbox;
8081   GtkWidget *button;
8082   GtkWidget *button_above;
8083   GtkWidget *button_below;
8084
8085   vbox = gtk_vbox_new (FALSE, 0);
8086   
8087   button = gtk_button_new_with_label ("Stick");
8088   g_signal_connect_object (button,
8089                            "clicked",
8090                            G_CALLBACK (gtk_window_stick),
8091                            window,
8092                            G_CONNECT_SWAPPED);
8093   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8094
8095   button = gtk_button_new_with_label ("Unstick");
8096   g_signal_connect_object (button,
8097                            "clicked",
8098                            G_CALLBACK (gtk_window_unstick),
8099                            window,
8100                            G_CONNECT_SWAPPED);
8101   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8102   
8103   button = gtk_button_new_with_label ("Maximize");
8104   g_signal_connect_object (button,
8105                            "clicked",
8106                            G_CALLBACK (gtk_window_maximize),
8107                            window,
8108                            G_CONNECT_SWAPPED);
8109   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8110
8111   button = gtk_button_new_with_label ("Unmaximize");
8112   g_signal_connect_object (button,
8113                            "clicked",
8114                            G_CALLBACK (gtk_window_unmaximize),
8115                            window,
8116                            G_CONNECT_SWAPPED);
8117   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8118
8119   button = gtk_button_new_with_label ("Iconify");
8120   g_signal_connect_object (button,
8121                            "clicked",
8122                            G_CALLBACK (gtk_window_iconify),
8123                            window,
8124                            G_CONNECT_SWAPPED);
8125   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8126
8127   button = gtk_button_new_with_label ("Fullscreen");
8128   g_signal_connect_object (button,
8129                            "clicked",
8130                            G_CALLBACK (gtk_window_fullscreen),
8131                            window,
8132                            G_CONNECT_SWAPPED);
8133   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8134
8135   button = gtk_button_new_with_label ("Unfullscreen");
8136   g_signal_connect_object (button,
8137                            "clicked",
8138                            G_CALLBACK (gtk_window_unfullscreen),
8139                            window,
8140                            G_CONNECT_SWAPPED);
8141   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8142
8143   button_above = gtk_toggle_button_new_with_label ("Keep above");
8144   g_signal_connect (button_above,
8145                     "toggled",
8146                     G_CALLBACK (keep_window_above),
8147                     window);
8148   gtk_box_pack_start (GTK_BOX (vbox), button_above, FALSE, FALSE, 0);
8149
8150   button_below = gtk_toggle_button_new_with_label ("Keep below");
8151   g_signal_connect (button_below,
8152                     "toggled",
8153                     G_CALLBACK (keep_window_below),
8154                     window);
8155   gtk_box_pack_start (GTK_BOX (vbox), button_below, FALSE, FALSE, 0);
8156
8157   g_object_set_data (G_OBJECT (button_above), "radio", button_below);
8158   g_object_set_data (G_OBJECT (button_below), "radio", button_above);
8159
8160   button = gtk_button_new_with_label ("Hide (withdraw)");
8161   g_signal_connect_object (button,
8162                            "clicked",
8163                            G_CALLBACK (gtk_widget_hide),
8164                            window,
8165                            G_CONNECT_SWAPPED);
8166   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8167   
8168   gtk_widget_show_all (vbox);
8169
8170   return vbox;
8171 }
8172
8173 void
8174 create_window_states (GtkWidget *widget)
8175 {
8176   static GtkWidget *window = NULL;
8177   GtkWidget *label;
8178   GtkWidget *box1;
8179   GtkWidget *iconified;
8180   GtkWidget *normal;
8181   GtkWidget *controls;
8182
8183   if (!window)
8184     {
8185       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8186       gtk_window_set_screen (GTK_WINDOW (window),
8187                              gtk_widget_get_screen (widget));
8188
8189       g_signal_connect (window, "destroy",
8190                         G_CALLBACK (gtk_widget_destroyed),
8191                         &window);
8192
8193       gtk_window_set_title (GTK_WINDOW (window), "Window states");
8194       
8195       box1 = gtk_vbox_new (FALSE, 0);
8196       gtk_container_add (GTK_CONTAINER (window), box1);
8197
8198       iconified = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8199
8200       gtk_window_set_screen (GTK_WINDOW (iconified),
8201                              gtk_widget_get_screen (widget));
8202       
8203       g_signal_connect_object (iconified, "destroy",
8204                                G_CALLBACK (gtk_widget_destroy),
8205                                window,
8206                                G_CONNECT_SWAPPED);
8207       gtk_window_iconify (GTK_WINDOW (iconified));
8208       gtk_window_set_title (GTK_WINDOW (iconified), "Iconified initially");
8209       controls = get_state_controls (iconified);
8210       gtk_container_add (GTK_CONTAINER (iconified), controls);
8211       
8212       normal = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8213
8214       gtk_window_set_screen (GTK_WINDOW (normal),
8215                              gtk_widget_get_screen (widget));
8216       
8217       g_signal_connect_object (normal, "destroy",
8218                                G_CALLBACK (gtk_widget_destroy),
8219                                window,
8220                                G_CONNECT_SWAPPED);
8221       
8222       gtk_window_set_title (GTK_WINDOW (normal), "Deiconified initially");
8223       controls = get_state_controls (normal);
8224       gtk_container_add (GTK_CONTAINER (normal), controls);
8225       
8226       label = tracking_label (iconified);
8227       gtk_container_add (GTK_CONTAINER (box1), label);
8228
8229       label = tracking_label (normal);
8230       gtk_container_add (GTK_CONTAINER (box1), label);
8231
8232       gtk_widget_show_all (iconified);
8233       gtk_widget_show_all (normal);
8234       gtk_widget_show_all (box1);
8235     }
8236
8237   if (!gtk_widget_get_visible (window))
8238     gtk_widget_show (window);
8239   else
8240     gtk_widget_destroy (window);
8241 }
8242
8243 /*
8244  * Window sizing
8245  */
8246
8247 static gint
8248 configure_event_callback (GtkWidget *widget,
8249                           GdkEventConfigure *event,
8250                           gpointer data)
8251 {
8252   GtkWidget *label = data;
8253   gchar *msg;
8254   gint x, y;
8255   
8256   gtk_window_get_position (GTK_WINDOW (widget), &x, &y);
8257   
8258   msg = g_strdup_printf ("event: %d,%d  %d x %d\n"
8259                          "position: %d, %d",
8260                          event->x, event->y, event->width, event->height,
8261                          x, y);
8262   
8263   gtk_label_set_text (GTK_LABEL (label), msg);
8264
8265   g_free (msg);
8266
8267   return FALSE;
8268 }
8269
8270 static void
8271 get_ints (GtkWidget *window,
8272           gint      *a,
8273           gint      *b)
8274 {
8275   GtkWidget *spin1;
8276   GtkWidget *spin2;
8277
8278   spin1 = g_object_get_data (G_OBJECT (window), "spin1");
8279   spin2 = g_object_get_data (G_OBJECT (window), "spin2");
8280
8281   *a = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (spin1));
8282   *b = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (spin2));
8283 }
8284
8285 static void
8286 set_size_callback (GtkWidget *widget,
8287                    gpointer   data)
8288 {
8289   gint w, h;
8290   
8291   get_ints (data, &w, &h);
8292
8293   gtk_window_resize (GTK_WINDOW (g_object_get_data (data, "target")), w, h);
8294 }
8295
8296 static void
8297 unset_default_size_callback (GtkWidget *widget,
8298                              gpointer   data)
8299 {
8300   gtk_window_set_default_size (g_object_get_data (data, "target"),
8301                                -1, -1);
8302 }
8303
8304 static void
8305 set_default_size_callback (GtkWidget *widget,
8306                            gpointer   data)
8307 {
8308   gint w, h;
8309   
8310   get_ints (data, &w, &h);
8311
8312   gtk_window_set_default_size (g_object_get_data (data, "target"),
8313                                w, h);
8314 }
8315
8316 static void
8317 unset_size_request_callback (GtkWidget *widget,
8318                              gpointer   data)
8319 {
8320   gtk_widget_set_size_request (g_object_get_data (data, "target"),
8321                                -1, -1);
8322 }
8323
8324 static void
8325 set_size_request_callback (GtkWidget *widget,
8326                            gpointer   data)
8327 {
8328   gint w, h;
8329   
8330   get_ints (data, &w, &h);
8331
8332   gtk_widget_set_size_request (g_object_get_data (data, "target"),
8333                                w, h);
8334 }
8335
8336 static void
8337 set_location_callback (GtkWidget *widget,
8338                        gpointer   data)
8339 {
8340   gint x, y;
8341   
8342   get_ints (data, &x, &y);
8343
8344   gtk_window_move (g_object_get_data (data, "target"), x, y);
8345 }
8346
8347 static void
8348 move_to_position_callback (GtkWidget *widget,
8349                            gpointer   data)
8350 {
8351   gint x, y;
8352   GtkWindow *window;
8353
8354   window = g_object_get_data (data, "target");
8355   
8356   gtk_window_get_position (window, &x, &y);
8357
8358   gtk_window_move (window, x, y);
8359 }
8360
8361 static void
8362 set_geometry_callback (GtkWidget *entry,
8363                        gpointer   data)
8364 {
8365   gchar *text;
8366   GtkWindow *target;
8367
8368   target = GTK_WINDOW (g_object_get_data (G_OBJECT (data), "target"));
8369   
8370   text = gtk_editable_get_chars (GTK_EDITABLE (entry), 0, -1);
8371
8372   if (!gtk_window_parse_geometry (target, text))
8373     g_print ("Bad geometry string '%s'\n", text);
8374
8375   g_free (text);
8376 }
8377
8378 static void
8379 allow_shrink_callback (GtkWidget *widget,
8380                        gpointer   data)
8381 {
8382   g_object_set (g_object_get_data (data, "target"),
8383                 "allow_shrink",
8384                 GTK_TOGGLE_BUTTON (widget)->active,
8385                 NULL);
8386 }
8387
8388 static void
8389 allow_grow_callback (GtkWidget *widget,
8390                      gpointer   data)
8391 {
8392   g_object_set (g_object_get_data (data, "target"),
8393                 "allow_grow",
8394                 GTK_TOGGLE_BUTTON (widget)->active,
8395                 NULL);
8396 }
8397
8398 static void
8399 gravity_selected (GtkWidget *widget,
8400                   gpointer   data)
8401 {
8402   gtk_window_set_gravity (GTK_WINDOW (g_object_get_data (data, "target")),
8403                           gtk_combo_box_get_active (GTK_COMBO_BOX (widget)) + GDK_GRAVITY_NORTH_WEST);
8404 }
8405
8406 static void
8407 pos_selected (GtkWidget *widget,
8408               gpointer   data)
8409 {
8410   gtk_window_set_position (GTK_WINDOW (g_object_get_data (data, "target")),
8411                            gtk_combo_box_get_active (GTK_COMBO_BOX (widget)) + GTK_WIN_POS_NONE);
8412 }
8413
8414 static void
8415 move_gravity_window_to_current_position (GtkWidget *widget,
8416                                          gpointer   data)
8417 {
8418   gint x, y;
8419   GtkWindow *window;
8420
8421   window = GTK_WINDOW (data);    
8422   
8423   gtk_window_get_position (window, &x, &y);
8424
8425   gtk_window_move (window, x, y);
8426 }
8427
8428 static void
8429 get_screen_corner (GtkWindow *window,
8430                    gint      *x,
8431                    gint      *y)
8432 {
8433   int w, h;
8434   GdkScreen * screen = gtk_window_get_screen (window);
8435   
8436   gtk_window_get_size (GTK_WINDOW (window), &w, &h);
8437
8438   switch (gtk_window_get_gravity (window))
8439     {
8440     case GDK_GRAVITY_SOUTH_EAST:
8441       *x = gdk_screen_get_width (screen) - w;
8442       *y = gdk_screen_get_height (screen) - h;
8443       break;
8444
8445     case GDK_GRAVITY_NORTH_EAST:
8446       *x = gdk_screen_get_width (screen) - w;
8447       *y = 0;
8448       break;
8449
8450     case GDK_GRAVITY_SOUTH_WEST:
8451       *x = 0;
8452       *y = gdk_screen_get_height (screen) - h;
8453       break;
8454
8455     case GDK_GRAVITY_NORTH_WEST:
8456       *x = 0;
8457       *y = 0;
8458       break;
8459       
8460     case GDK_GRAVITY_SOUTH:
8461       *x = (gdk_screen_get_width (screen) - w) / 2;
8462       *y = gdk_screen_get_height (screen) - h;
8463       break;
8464
8465     case GDK_GRAVITY_NORTH:
8466       *x = (gdk_screen_get_width (screen) - w) / 2;
8467       *y = 0;
8468       break;
8469
8470     case GDK_GRAVITY_WEST:
8471       *x = 0;
8472       *y = (gdk_screen_get_height (screen) - h) / 2;
8473       break;
8474
8475     case GDK_GRAVITY_EAST:
8476       *x = gdk_screen_get_width (screen) - w;
8477       *y = (gdk_screen_get_height (screen) - h) / 2;
8478       break;
8479
8480     case GDK_GRAVITY_CENTER:
8481       *x = (gdk_screen_get_width (screen) - w) / 2;
8482       *y = (gdk_screen_get_height (screen) - h) / 2;
8483       break;
8484
8485     case GDK_GRAVITY_STATIC:
8486       /* pick some random numbers */
8487       *x = 350;
8488       *y = 350;
8489       break;
8490
8491     default:
8492       g_assert_not_reached ();
8493       break;
8494     }
8495 }
8496
8497 static void
8498 move_gravity_window_to_starting_position (GtkWidget *widget,
8499                                           gpointer   data)
8500 {
8501   gint x, y;
8502   GtkWindow *window;
8503
8504   window = GTK_WINDOW (data);    
8505   
8506   get_screen_corner (window,
8507                      &x, &y);
8508   
8509   gtk_window_move (window, x, y);
8510 }
8511
8512 static GtkWidget*
8513 make_gravity_window (GtkWidget   *destroy_with,
8514                      GdkGravity   gravity,
8515                      const gchar *title)
8516 {
8517   GtkWidget *window;
8518   GtkWidget *button;
8519   GtkWidget *vbox;
8520   int x, y;
8521   
8522   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8523
8524   gtk_window_set_screen (GTK_WINDOW (window),
8525                          gtk_widget_get_screen (destroy_with));
8526
8527   vbox = gtk_vbox_new (FALSE, 0);
8528   gtk_widget_show (vbox);
8529   
8530   gtk_container_add (GTK_CONTAINER (window), vbox);
8531   gtk_window_set_title (GTK_WINDOW (window), title);
8532   gtk_window_set_gravity (GTK_WINDOW (window), gravity);
8533
8534   g_signal_connect_object (destroy_with,
8535                            "destroy",
8536                            G_CALLBACK (gtk_widget_destroy),
8537                            window,
8538                            G_CONNECT_SWAPPED);
8539
8540   
8541   button = gtk_button_new_with_mnemonic ("_Move to current position");
8542
8543   g_signal_connect (button, "clicked",
8544                     G_CALLBACK (move_gravity_window_to_current_position),
8545                     window);
8546
8547   gtk_container_add (GTK_CONTAINER (vbox), button);
8548   gtk_widget_show (button);
8549
8550   button = gtk_button_new_with_mnemonic ("Move to _starting position");
8551
8552   g_signal_connect (button, "clicked",
8553                     G_CALLBACK (move_gravity_window_to_starting_position),
8554                     window);
8555
8556   gtk_container_add (GTK_CONTAINER (vbox), button);
8557   gtk_widget_show (button);
8558   
8559   /* Pretend this is the result of --geometry.
8560    * DO NOT COPY THIS CODE unless you are setting --geometry results,
8561    * and in that case you probably should just use gtk_window_parse_geometry().
8562    * AGAIN, DO NOT SET GDK_HINT_USER_POS! It violates the ICCCM unless
8563    * you are parsing --geometry or equivalent.
8564    */
8565   gtk_window_set_geometry_hints (GTK_WINDOW (window),
8566                                  NULL, NULL,
8567                                  GDK_HINT_USER_POS);
8568
8569   gtk_window_set_default_size (GTK_WINDOW (window),
8570                                200, 200);
8571
8572   get_screen_corner (GTK_WINDOW (window), &x, &y);
8573   
8574   gtk_window_move (GTK_WINDOW (window),
8575                    x, y);
8576   
8577   return window;
8578 }
8579
8580 static void
8581 do_gravity_test (GtkWidget *widget,
8582                  gpointer   data)
8583 {
8584   GtkWidget *destroy_with = data;
8585   GtkWidget *window;
8586   
8587   /* We put a window at each gravity point on the screen. */
8588   window = make_gravity_window (destroy_with, GDK_GRAVITY_NORTH_WEST,
8589                                 "NorthWest");
8590   gtk_widget_show (window);
8591   
8592   window = make_gravity_window (destroy_with, GDK_GRAVITY_SOUTH_EAST,
8593                                 "SouthEast");
8594   gtk_widget_show (window);
8595
8596   window = make_gravity_window (destroy_with, GDK_GRAVITY_NORTH_EAST,
8597                                 "NorthEast");
8598   gtk_widget_show (window);
8599
8600   window = make_gravity_window (destroy_with, GDK_GRAVITY_SOUTH_WEST,
8601                                 "SouthWest");
8602   gtk_widget_show (window);
8603
8604   window = make_gravity_window (destroy_with, GDK_GRAVITY_SOUTH,
8605                                 "South");
8606   gtk_widget_show (window);
8607
8608   window = make_gravity_window (destroy_with, GDK_GRAVITY_NORTH,
8609                                 "North");
8610   gtk_widget_show (window);
8611
8612   
8613   window = make_gravity_window (destroy_with, GDK_GRAVITY_WEST,
8614                                 "West");
8615   gtk_widget_show (window);
8616
8617     
8618   window = make_gravity_window (destroy_with, GDK_GRAVITY_EAST,
8619                                 "East");
8620   gtk_widget_show (window);
8621
8622   window = make_gravity_window (destroy_with, GDK_GRAVITY_CENTER,
8623                                 "Center");
8624   gtk_widget_show (window);
8625
8626   window = make_gravity_window (destroy_with, GDK_GRAVITY_STATIC,
8627                                 "Static");
8628   gtk_widget_show (window);
8629 }
8630
8631 static GtkWidget*
8632 window_controls (GtkWidget *window)
8633 {
8634   GtkWidget *control_window;
8635   GtkWidget *label;
8636   GtkWidget *vbox;
8637   GtkWidget *button;
8638   GtkWidget *spin;
8639   GtkAdjustment *adj;
8640   GtkWidget *entry;
8641   GtkWidget *om;
8642   gint i;
8643   
8644   control_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8645
8646   gtk_window_set_screen (GTK_WINDOW (control_window),
8647                          gtk_widget_get_screen (window));
8648
8649   gtk_window_set_title (GTK_WINDOW (control_window), "Size controls");
8650   
8651   g_object_set_data (G_OBJECT (control_window),
8652                      "target",
8653                      window);
8654   
8655   g_signal_connect_object (control_window,
8656                            "destroy",
8657                            G_CALLBACK (gtk_widget_destroy),
8658                            window,
8659                            G_CONNECT_SWAPPED);
8660
8661   vbox = gtk_vbox_new (FALSE, 5);
8662   
8663   gtk_container_add (GTK_CONTAINER (control_window), vbox);
8664   
8665   label = gtk_label_new ("<no configure events>");
8666   gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
8667   
8668   g_signal_connect (window,
8669                     "configure_event",
8670                     G_CALLBACK (configure_event_callback),
8671                     label);
8672
8673   adj = (GtkAdjustment *) gtk_adjustment_new (10.0, -2000.0, 2000.0, 1.0,
8674                                               5.0, 0.0);
8675   spin = gtk_spin_button_new (adj, 0, 0);
8676
8677   gtk_box_pack_start (GTK_BOX (vbox), spin, FALSE, FALSE, 0);
8678
8679   g_object_set_data (G_OBJECT (control_window), "spin1", spin);
8680
8681   adj = (GtkAdjustment *) gtk_adjustment_new (10.0, -2000.0, 2000.0, 1.0,
8682                                               5.0, 0.0);
8683   spin = gtk_spin_button_new (adj, 0, 0);
8684
8685   gtk_box_pack_start (GTK_BOX (vbox), spin, FALSE, FALSE, 0);
8686
8687   g_object_set_data (G_OBJECT (control_window), "spin2", spin);
8688
8689   entry = gtk_entry_new ();
8690   gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
8691
8692   g_signal_connect (entry, "changed",
8693                     G_CALLBACK (set_geometry_callback),
8694                     control_window);
8695
8696   button = gtk_button_new_with_label ("Show gravity test windows");
8697   g_signal_connect_swapped (button,
8698                             "clicked",
8699                             G_CALLBACK (do_gravity_test),
8700                             control_window);
8701   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8702
8703   button = gtk_button_new_with_label ("Reshow with initial size");
8704   g_signal_connect_object (button,
8705                            "clicked",
8706                            G_CALLBACK (gtk_window_reshow_with_initial_size),
8707                            window,
8708                            G_CONNECT_SWAPPED);
8709   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8710   
8711   button = gtk_button_new_with_label ("Queue resize");
8712   g_signal_connect_object (button,
8713                            "clicked",
8714                            G_CALLBACK (gtk_widget_queue_resize),
8715                            window,
8716                            G_CONNECT_SWAPPED);
8717   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8718   
8719   button = gtk_button_new_with_label ("Resize");
8720   g_signal_connect (button,
8721                     "clicked",
8722                     G_CALLBACK (set_size_callback),
8723                     control_window);
8724   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8725
8726   button = gtk_button_new_with_label ("Set default size");
8727   g_signal_connect (button,
8728                     "clicked",
8729                     G_CALLBACK (set_default_size_callback),
8730                     control_window);
8731   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8732
8733   button = gtk_button_new_with_label ("Unset default size");
8734   g_signal_connect (button,
8735                     "clicked",
8736                     G_CALLBACK (unset_default_size_callback),
8737                     control_window);
8738   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8739   
8740   button = gtk_button_new_with_label ("Set size request");
8741   g_signal_connect (button,
8742                     "clicked",
8743                     G_CALLBACK (set_size_request_callback),
8744                     control_window);
8745   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8746
8747   button = gtk_button_new_with_label ("Unset size request");
8748   g_signal_connect (button,
8749                     "clicked",
8750                     G_CALLBACK (unset_size_request_callback),
8751                     control_window);
8752   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8753   
8754   button = gtk_button_new_with_label ("Move");
8755   g_signal_connect (button,
8756                     "clicked",
8757                     G_CALLBACK (set_location_callback),
8758                     control_window);
8759   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8760
8761   button = gtk_button_new_with_label ("Move to current position");
8762   g_signal_connect (button,
8763                     "clicked",
8764                     G_CALLBACK (move_to_position_callback),
8765                     control_window);
8766   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8767   
8768   button = gtk_check_button_new_with_label ("Allow shrink");
8769   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE);
8770   g_signal_connect (button,
8771                     "toggled",
8772                     G_CALLBACK (allow_shrink_callback),
8773                     control_window);
8774   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8775
8776   button = gtk_check_button_new_with_label ("Allow grow");
8777   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
8778   g_signal_connect (button,
8779                     "toggled",
8780                     G_CALLBACK (allow_grow_callback),
8781                     control_window);
8782   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8783   
8784   button = gtk_button_new_with_mnemonic ("_Show");
8785   g_signal_connect_object (button,
8786                            "clicked",
8787                            G_CALLBACK (gtk_widget_show),
8788                            window,
8789                            G_CONNECT_SWAPPED);
8790   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8791
8792   button = gtk_button_new_with_mnemonic ("_Hide");
8793   g_signal_connect_object (button,
8794                            "clicked",
8795                            G_CALLBACK (gtk_widget_hide),
8796                            window,
8797                            G_CONNECT_SWAPPED);
8798   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8799   
8800   om = gtk_combo_box_new_text ();
8801   i = 0;
8802   while (i < 10)
8803     {
8804       static gchar *names[] = {
8805         "GDK_GRAVITY_NORTH_WEST",
8806         "GDK_GRAVITY_NORTH",
8807         "GDK_GRAVITY_NORTH_EAST",
8808         "GDK_GRAVITY_WEST",
8809         "GDK_GRAVITY_CENTER",
8810         "GDK_GRAVITY_EAST",
8811         "GDK_GRAVITY_SOUTH_WEST",
8812         "GDK_GRAVITY_SOUTH",
8813         "GDK_GRAVITY_SOUTH_EAST",
8814         "GDK_GRAVITY_STATIC",
8815         NULL
8816       };
8817
8818       g_assert (names[i]);
8819       gtk_combo_box_append_text (GTK_COMBO_BOX (om), names[i]);
8820
8821       ++i;
8822     }
8823   
8824   g_signal_connect (om,
8825                     "changed",
8826                     G_CALLBACK (gravity_selected),
8827                     control_window);
8828
8829   gtk_box_pack_end (GTK_BOX (vbox), om, FALSE, FALSE, 0);
8830
8831
8832   om = gtk_combo_box_new_text ();
8833   i = 0;
8834   while (i < 5)
8835     {
8836       static gchar *names[] = {
8837         "GTK_WIN_POS_NONE",
8838         "GTK_WIN_POS_CENTER",
8839         "GTK_WIN_POS_MOUSE",
8840         "GTK_WIN_POS_CENTER_ALWAYS",
8841         "GTK_WIN_POS_CENTER_ON_PARENT",
8842         NULL
8843       };
8844
8845       g_assert (names[i]);
8846       gtk_combo_box_append_text (GTK_COMBO_BOX (om), names[i]);
8847
8848       ++i;
8849     }
8850
8851   g_signal_connect (om,
8852                     "changed",
8853                     G_CALLBACK (pos_selected),
8854                     control_window);
8855
8856   gtk_box_pack_end (GTK_BOX (vbox), om, FALSE, FALSE, 0);
8857   
8858   gtk_widget_show_all (vbox);
8859   
8860   return control_window;
8861 }
8862
8863 void
8864 create_window_sizing (GtkWidget *widget)
8865 {
8866   static GtkWidget *window = NULL;
8867   static GtkWidget *target_window = NULL;
8868
8869   if (!target_window)
8870     {
8871       GtkWidget *label;
8872       
8873       target_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8874       gtk_window_set_screen (GTK_WINDOW (target_window),
8875                              gtk_widget_get_screen (widget));
8876       label = gtk_label_new (NULL);
8877       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");
8878       gtk_container_add (GTK_CONTAINER (target_window), label);
8879       gtk_widget_show (label);
8880       
8881       g_signal_connect (target_window, "destroy",
8882                         G_CALLBACK (gtk_widget_destroyed),
8883                         &target_window);
8884
8885       window = window_controls (target_window);
8886       
8887       g_signal_connect (window, "destroy",
8888                         G_CALLBACK (gtk_widget_destroyed),
8889                         &window);
8890       
8891       gtk_window_set_title (GTK_WINDOW (target_window), "Window to size");
8892     }
8893
8894   /* don't show target window by default, we want to allow testing
8895    * of behavior on first show.
8896    */
8897   
8898   if (!gtk_widget_get_visible (window))
8899     gtk_widget_show (window);
8900   else
8901     gtk_widget_destroy (window);
8902 }
8903
8904 /*
8905  * GtkProgressBar
8906  */
8907
8908 typedef struct _ProgressData {
8909   GtkWidget *window;
8910   GtkWidget *pbar;
8911   GtkWidget *block_spin;
8912   GtkWidget *x_align_spin;
8913   GtkWidget *y_align_spin;
8914   GtkWidget *step_spin;
8915   GtkWidget *act_blocks_spin;
8916   GtkWidget *label;
8917   GtkWidget *omenu1;
8918   GtkWidget *elmenu;
8919   GtkWidget *omenu2;
8920   GtkWidget *entry;
8921   int timer;
8922   gboolean activity;
8923 } ProgressData;
8924
8925 gboolean
8926 progress_timeout (gpointer data)
8927 {
8928   ProgressData *pdata = data;
8929   gdouble new_val;
8930
8931   if (pdata->activity)
8932     {
8933       gtk_progress_bar_pulse (GTK_PROGRESS_BAR (pdata->pbar));
8934       return TRUE;
8935     }
8936
8937   new_val = gtk_progress_bar_get_fraction (GTK_PROGRESS_BAR (pdata->pbar)) + 0.01;
8938   if (new_val > 1.00)
8939     new_val = 0.00;
8940
8941   gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (pdata->pbar), new_val);
8942
8943   return TRUE;
8944 }
8945
8946 static void
8947 destroy_progress (GtkWidget     *widget,
8948                   ProgressData **pdata)
8949 {
8950   g_source_remove ((*pdata)->timer);
8951   (*pdata)->timer = 0;
8952   (*pdata)->window = NULL;
8953   g_free (*pdata);
8954   *pdata = NULL;
8955 }
8956
8957 static void
8958 progressbar_toggle_orientation (GtkWidget *widget, gpointer data)
8959 {
8960   ProgressData *pdata;
8961   gint i;
8962
8963   pdata = (ProgressData *) data;
8964
8965   if (!gtk_widget_get_mapped (widget))
8966     return;
8967
8968   i = gtk_combo_box_get_active (GTK_COMBO_BOX (widget));
8969
8970   gtk_progress_bar_set_orientation (GTK_PROGRESS_BAR (pdata->pbar),
8971                                     (GtkProgressBarOrientation) i);
8972 }
8973
8974 static void
8975 toggle_show_text (GtkWidget *widget, ProgressData *pdata)
8976 {
8977   gtk_progress_set_show_text (GTK_PROGRESS (pdata->pbar),
8978                               GTK_TOGGLE_BUTTON (widget)->active);
8979   gtk_widget_set_sensitive (pdata->entry, GTK_TOGGLE_BUTTON (widget)->active);
8980 }
8981
8982 static void
8983 progressbar_toggle_ellipsize (GtkWidget *widget,
8984                               gpointer   data)
8985 {
8986   ProgressData *pdata = data;
8987   if (gtk_widget_is_drawable (widget))
8988     {
8989       gint i = gtk_combo_box_get_active (GTK_COMBO_BOX (widget));
8990       gtk_progress_bar_set_ellipsize (GTK_PROGRESS_BAR (pdata->pbar), i);
8991     }
8992 }
8993
8994 static void
8995 progress_value_changed (GtkAdjustment *adj, ProgressData *pdata)
8996 {
8997   char buf[20];
8998
8999   if (GTK_PROGRESS (pdata->pbar)->activity_mode)
9000     sprintf (buf, "???");
9001   else
9002     sprintf (buf, "%.0f%%", 100 *
9003       gtk_progress_bar_get_fraction (GTK_PROGRESS_BAR (pdata->pbar)));
9004   gtk_label_set_text (GTK_LABEL (pdata->label), buf);
9005 }
9006
9007 static void
9008 adjust_align (GtkAdjustment *adj, ProgressData *pdata)
9009 {
9010   gtk_progress_set_text_alignment (GTK_PROGRESS (pdata->pbar),
9011          gtk_spin_button_get_value (GTK_SPIN_BUTTON (pdata->x_align_spin)),
9012          gtk_spin_button_get_value (GTK_SPIN_BUTTON (pdata->y_align_spin)));
9013 }
9014
9015 static void
9016 toggle_activity_mode (GtkWidget *widget, ProgressData *pdata)
9017 {
9018   pdata->activity = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
9019 }
9020
9021 static void
9022 entry_changed (GtkWidget *widget, ProgressData *pdata)
9023 {
9024   gtk_progress_bar_set_text (GTK_PROGRESS_BAR (pdata->pbar),
9025                           gtk_entry_get_text (GTK_ENTRY (pdata->entry)));
9026 }
9027
9028 void
9029 create_progress_bar (GtkWidget *widget)
9030 {
9031   GtkWidget *button;
9032   GtkWidget *vbox;
9033   GtkWidget *vbox2;
9034   GtkWidget *hbox;
9035   GtkWidget *check;
9036   GtkWidget *frame;
9037   GtkWidget *tab;
9038   GtkWidget *label;
9039   GtkWidget *align;
9040   GtkAdjustment *adj;
9041   static ProgressData *pdata = NULL;
9042
9043   static gchar *items1[] =
9044   {
9045     "Left-Right",
9046     "Right-Left",
9047     "Bottom-Top",
9048     "Top-Bottom"
9049   };
9050
9051     static char *ellipsize_items[] = {
9052     "None",     // PANGO_ELLIPSIZE_NONE,
9053     "Start",    // PANGO_ELLIPSIZE_START,
9054     "Middle",   // PANGO_ELLIPSIZE_MIDDLE,
9055     "End",      // PANGO_ELLIPSIZE_END
9056   };
9057   
9058   if (!pdata)
9059     pdata = g_new0 (ProgressData, 1);
9060
9061   if (!pdata->window)
9062     {
9063       pdata->window = gtk_dialog_new ();
9064
9065       gtk_window_set_screen (GTK_WINDOW (pdata->window),
9066                              gtk_widget_get_screen (widget));
9067
9068       gtk_window_set_resizable (GTK_WINDOW (pdata->window), TRUE);
9069
9070       g_signal_connect (pdata->window, "destroy",
9071                         G_CALLBACK (destroy_progress),
9072                         &pdata);
9073
9074       pdata->timer = 0;
9075
9076       gtk_window_set_title (GTK_WINDOW (pdata->window), "GtkProgressBar");
9077       gtk_container_set_border_width (GTK_CONTAINER (pdata->window), 0);
9078
9079       vbox = gtk_vbox_new (FALSE, 5);
9080       gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
9081       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (pdata->window)->vbox), 
9082                           vbox, FALSE, TRUE, 0);
9083
9084       frame = gtk_frame_new ("Progress");
9085       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
9086
9087       vbox2 = gtk_vbox_new (FALSE, 5);
9088       gtk_container_add (GTK_CONTAINER (frame), vbox2);
9089
9090       align = gtk_alignment_new (0.5, 0.5, 0, 0);
9091       gtk_box_pack_start (GTK_BOX (vbox2), align, FALSE, FALSE, 5);
9092
9093       adj = (GtkAdjustment *) gtk_adjustment_new (0, 1, 300, 0, 0, 0);
9094       g_signal_connect (adj, "value_changed",
9095                         G_CALLBACK (progress_value_changed), pdata);
9096
9097       pdata->pbar = g_object_new (GTK_TYPE_PROGRESS_BAR,
9098                                     "adjustment", adj,
9099                                     "ellipsize", PANGO_ELLIPSIZE_MIDDLE,
9100                                     NULL);
9101       gtk_progress_bar_set_text (GTK_PROGRESS_BAR (pdata->pbar),
9102                                       "%v from [%l,%u] (=%p%%)");
9103       gtk_container_add (GTK_CONTAINER (align), pdata->pbar);
9104       pdata->timer = g_timeout_add (100, (GSourceFunc)progress_timeout, pdata);
9105
9106       align = gtk_alignment_new (0.5, 0.5, 0, 0);
9107       gtk_box_pack_start (GTK_BOX (vbox2), align, FALSE, FALSE, 5);
9108
9109       hbox = gtk_hbox_new (FALSE, 5);
9110       gtk_container_add (GTK_CONTAINER (align), hbox);
9111       label = gtk_label_new ("Label updated by user :"); 
9112       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
9113       pdata->label = gtk_label_new ("");
9114       gtk_box_pack_start (GTK_BOX (hbox), pdata->label, FALSE, TRUE, 0);
9115
9116       frame = gtk_frame_new ("Options");
9117       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
9118
9119       vbox2 = gtk_vbox_new (FALSE, 5);
9120       gtk_container_add (GTK_CONTAINER (frame), vbox2);
9121
9122       tab = gtk_table_new (7, 2, FALSE);
9123       gtk_box_pack_start (GTK_BOX (vbox2), tab, FALSE, TRUE, 0);
9124
9125       label = gtk_label_new ("Orientation :");
9126       gtk_table_attach (GTK_TABLE (tab), label, 0, 1, 0, 1,
9127                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
9128                         5, 5);
9129       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
9130
9131       pdata->omenu1 = build_option_menu (items1, 4, 0,
9132                                          progressbar_toggle_orientation,
9133                                          pdata);
9134       hbox = gtk_hbox_new (FALSE, 0);
9135       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 0, 1,
9136                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
9137                         5, 5);
9138       gtk_box_pack_start (GTK_BOX (hbox), pdata->omenu1, TRUE, TRUE, 0);
9139       
9140       check = gtk_check_button_new_with_label ("Show text");
9141       g_signal_connect (check, "clicked",
9142                         G_CALLBACK (toggle_show_text),
9143                         pdata);
9144       gtk_table_attach (GTK_TABLE (tab), check, 0, 1, 1, 2,
9145                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
9146                         5, 5);
9147
9148       hbox = gtk_hbox_new (FALSE, 0);
9149       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 1, 2,
9150                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
9151                         5, 5);
9152
9153       label = gtk_label_new ("Format : ");
9154       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
9155
9156       pdata->entry = gtk_entry_new ();
9157       g_signal_connect (pdata->entry, "changed",
9158                         G_CALLBACK (entry_changed),
9159                         pdata);
9160       gtk_box_pack_start (GTK_BOX (hbox), pdata->entry, TRUE, TRUE, 0);
9161       gtk_entry_set_text (GTK_ENTRY (pdata->entry), "%v from [%l,%u] (=%p%%)");
9162       gtk_widget_set_size_request (pdata->entry, 100, -1);
9163       gtk_widget_set_sensitive (pdata->entry, FALSE);
9164
9165       label = gtk_label_new ("Text align :");
9166       gtk_table_attach (GTK_TABLE (tab), label, 0, 1, 2, 3,
9167                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
9168                         5, 5);
9169       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
9170
9171       hbox = gtk_hbox_new (FALSE, 0);
9172       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 2, 3,
9173                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
9174                         5, 5);
9175
9176       label = gtk_label_new ("x :");
9177       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 5);
9178       
9179       adj = (GtkAdjustment *) gtk_adjustment_new (0.5, 0, 1, 0.1, 0.1, 0);
9180       pdata->x_align_spin = gtk_spin_button_new (adj, 0, 1);
9181       g_signal_connect (adj, "value_changed",
9182                         G_CALLBACK (adjust_align), pdata);
9183       gtk_box_pack_start (GTK_BOX (hbox), pdata->x_align_spin, FALSE, TRUE, 0);
9184       gtk_widget_set_sensitive (pdata->x_align_spin, FALSE);
9185
9186       label = gtk_label_new ("y :");
9187       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 5);
9188
9189       adj = (GtkAdjustment *) gtk_adjustment_new (0.5, 0, 1, 0.1, 0.1, 0);
9190       pdata->y_align_spin = gtk_spin_button_new (adj, 0, 1);
9191       g_signal_connect (adj, "value_changed",
9192                         G_CALLBACK (adjust_align), pdata);
9193       gtk_box_pack_start (GTK_BOX (hbox), pdata->y_align_spin, FALSE, TRUE, 0);
9194       gtk_widget_set_sensitive (pdata->y_align_spin, FALSE);
9195
9196       label = gtk_label_new ("Ellipsize text :");
9197       gtk_table_attach (GTK_TABLE (tab), label, 0, 1, 10, 11,
9198                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
9199                         5, 5);
9200       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
9201       pdata->elmenu = build_option_menu (ellipsize_items,
9202                                          sizeof (ellipsize_items) / sizeof (ellipsize_items[0]),
9203                                          2, // PANGO_ELLIPSIZE_MIDDLE
9204                                          progressbar_toggle_ellipsize,
9205                                          pdata);
9206       hbox = gtk_hbox_new (FALSE, 0);
9207       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 10, 11,
9208                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
9209                         5, 5);
9210       gtk_box_pack_start (GTK_BOX (hbox), pdata->elmenu, TRUE, TRUE, 0);
9211
9212       check = gtk_check_button_new_with_label ("Activity mode");
9213       g_signal_connect (check, "clicked",
9214                         G_CALLBACK (toggle_activity_mode), pdata);
9215       gtk_table_attach (GTK_TABLE (tab), check, 0, 1, 15, 16,
9216                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
9217                         5, 5);
9218
9219       button = gtk_button_new_with_label ("close");
9220       g_signal_connect_swapped (button, "clicked",
9221                                 G_CALLBACK (gtk_widget_destroy),
9222                                 pdata->window);
9223       gtk_widget_set_can_default (button, TRUE);
9224       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (pdata->window)->action_area), 
9225                           button, TRUE, TRUE, 0);
9226       gtk_widget_grab_default (button);
9227     }
9228
9229   if (!gtk_widget_get_visible (pdata->window))
9230     gtk_widget_show_all (pdata->window);
9231   else
9232     gtk_widget_destroy (pdata->window);
9233 }
9234
9235 /*
9236  * Properties
9237  */
9238
9239 typedef struct {
9240   int x;
9241   int y;
9242   gboolean found;
9243   gboolean first;
9244   GtkWidget *res_widget;
9245 } FindWidgetData;
9246
9247 static void
9248 find_widget (GtkWidget *widget, FindWidgetData *data)
9249 {
9250   GtkAllocation new_allocation;
9251   gint x_offset = 0;
9252   gint y_offset = 0;
9253
9254   new_allocation = widget->allocation;
9255
9256   if (data->found || !gtk_widget_get_mapped (widget))
9257     return;
9258
9259   /* Note that in the following code, we only count the
9260    * position as being inside a WINDOW widget if it is inside
9261    * widget->window; points that are outside of widget->window
9262    * but within the allocation are not counted. This is consistent
9263    * with the way we highlight drag targets.
9264    */
9265   if (gtk_widget_get_has_window (widget))
9266     {
9267       new_allocation.x = 0;
9268       new_allocation.y = 0;
9269     }
9270   
9271   if (widget->parent && !data->first)
9272     {
9273       GdkWindow *window = widget->window;
9274       while (window != widget->parent->window)
9275         {
9276           gint tx, ty, twidth, theight;
9277           gdk_drawable_get_size (window, &twidth, &theight);
9278
9279           if (new_allocation.x < 0)
9280             {
9281               new_allocation.width += new_allocation.x;
9282               new_allocation.x = 0;
9283             }
9284           if (new_allocation.y < 0)
9285             {
9286               new_allocation.height += new_allocation.y;
9287               new_allocation.y = 0;
9288             }
9289           if (new_allocation.x + new_allocation.width > twidth)
9290             new_allocation.width = twidth - new_allocation.x;
9291           if (new_allocation.y + new_allocation.height > theight)
9292             new_allocation.height = theight - new_allocation.y;
9293
9294           gdk_window_get_position (window, &tx, &ty);
9295           new_allocation.x += tx;
9296           x_offset += tx;
9297           new_allocation.y += ty;
9298           y_offset += ty;
9299           
9300           window = gdk_window_get_parent (window);
9301         }
9302     }
9303
9304   if ((data->x >= new_allocation.x) && (data->y >= new_allocation.y) &&
9305       (data->x < new_allocation.x + new_allocation.width) && 
9306       (data->y < new_allocation.y + new_allocation.height))
9307     {
9308       /* First, check if the drag is in a valid drop site in
9309        * one of our children 
9310        */
9311       if (GTK_IS_CONTAINER (widget))
9312         {
9313           FindWidgetData new_data = *data;
9314           
9315           new_data.x -= x_offset;
9316           new_data.y -= y_offset;
9317           new_data.found = FALSE;
9318           new_data.first = FALSE;
9319           
9320           gtk_container_forall (GTK_CONTAINER (widget),
9321                                 (GtkCallback)find_widget,
9322                                 &new_data);
9323           
9324           data->found = new_data.found;
9325           if (data->found)
9326             data->res_widget = new_data.res_widget;
9327         }
9328
9329       /* If not, and this widget is registered as a drop site, check to
9330        * emit "drag_motion" to check if we are actually in
9331        * a drop site.
9332        */
9333       if (!data->found)
9334         {
9335           data->found = TRUE;
9336           data->res_widget = widget;
9337         }
9338     }
9339 }
9340
9341 static GtkWidget *
9342 find_widget_at_pointer (GdkDisplay *display)
9343 {
9344   GtkWidget *widget = NULL;
9345   GdkWindow *pointer_window;
9346   gint x, y;
9347   FindWidgetData data;
9348  
9349  pointer_window = gdk_display_get_window_at_pointer (display, NULL, NULL);
9350  
9351  if (pointer_window)
9352    {
9353      gpointer widget_ptr;
9354
9355      gdk_window_get_user_data (pointer_window, &widget_ptr);
9356      widget = widget_ptr;
9357    }
9358
9359  if (widget)
9360    {
9361      gdk_window_get_pointer (widget->window,
9362                              &x, &y, NULL);
9363      
9364      data.x = x;
9365      data.y = y;
9366      data.found = FALSE;
9367      data.first = TRUE;
9368
9369      find_widget (widget, &data);
9370      if (data.found)
9371        return data.res_widget;
9372      return widget;
9373    }
9374  return NULL;
9375 }
9376
9377 struct PropertiesData {
9378   GtkWidget **window;
9379   GdkCursor *cursor;
9380   gboolean in_query;
9381   gint handler;
9382 };
9383
9384 static void
9385 destroy_properties (GtkWidget             *widget,
9386                     struct PropertiesData *data)
9387 {
9388   if (data->window)
9389     {
9390       *data->window = NULL;
9391       data->window = NULL;
9392     }
9393
9394   if (data->cursor)
9395     {
9396       gdk_cursor_unref (data->cursor);
9397       data->cursor = NULL;
9398     }
9399
9400   if (data->handler)
9401     {
9402       g_signal_handler_disconnect (widget, data->handler);
9403       data->handler = 0;
9404     }
9405
9406   g_free (data);
9407 }
9408
9409 static gint
9410 property_query_event (GtkWidget        *widget,
9411                       GdkEvent         *event,
9412                       struct PropertiesData *data)
9413 {
9414   GtkWidget *res_widget = NULL;
9415
9416   if (!data->in_query)
9417     return FALSE;
9418   
9419   if (event->type == GDK_BUTTON_RELEASE)
9420     {
9421       gtk_grab_remove (widget);
9422       gdk_display_pointer_ungrab (gtk_widget_get_display (widget),
9423                                   GDK_CURRENT_TIME);
9424       
9425       res_widget = find_widget_at_pointer (gtk_widget_get_display (widget));
9426       if (res_widget)
9427         {
9428           g_object_set_data (G_OBJECT (res_widget), "prop-editor-screen",
9429                              gtk_widget_get_screen (widget));
9430           create_prop_editor (G_OBJECT (res_widget), 0);
9431         }
9432
9433       data->in_query = FALSE;
9434     }
9435   return FALSE;
9436 }
9437
9438
9439 static void
9440 query_properties (GtkButton *button,
9441                   struct PropertiesData *data)
9442 {
9443   gint failure;
9444
9445   g_signal_connect (button, "event",
9446                     G_CALLBACK (property_query_event), data);
9447
9448
9449   if (!data->cursor)
9450     data->cursor = gdk_cursor_new_for_display (gtk_widget_get_display (GTK_WIDGET (button)),
9451                                                GDK_TARGET);
9452   
9453   failure = gdk_pointer_grab (GTK_WIDGET (button)->window,
9454                               TRUE,
9455                               GDK_BUTTON_RELEASE_MASK,
9456                               NULL,
9457                               data->cursor,
9458                               GDK_CURRENT_TIME);
9459
9460   gtk_grab_add (GTK_WIDGET (button));
9461
9462   data->in_query = TRUE;
9463 }
9464
9465 static void
9466 create_properties (GtkWidget *widget)
9467 {
9468   static GtkWidget *window = NULL;
9469   GtkWidget *button;
9470   GtkWidget *vbox;
9471   GtkWidget *label;
9472   struct PropertiesData *data;
9473
9474   data = g_new (struct PropertiesData, 1);
9475   data->window = &window;
9476   data->in_query = FALSE;
9477   data->cursor = NULL;
9478   data->handler = 0;
9479
9480   if (!window)
9481     {
9482       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9483
9484       gtk_window_set_screen (GTK_WINDOW (window),
9485                              gtk_widget_get_screen (widget));      
9486
9487       data->handler = g_signal_connect (window, "destroy",
9488                                         G_CALLBACK (destroy_properties),
9489                                         data);
9490
9491       gtk_window_set_title (GTK_WINDOW (window), "test properties");
9492       gtk_container_set_border_width (GTK_CONTAINER (window), 10);
9493
9494       vbox = gtk_vbox_new (FALSE, 1);
9495       gtk_container_add (GTK_CONTAINER (window), vbox);
9496             
9497       label = gtk_label_new ("This is just a dumb test to test properties.\nIf you need a generic module, get GLE.");
9498       gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
9499       
9500       button = gtk_button_new_with_label ("Query properties");
9501       gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
9502       g_signal_connect (button, "clicked",
9503                         G_CALLBACK (query_properties),
9504                         data);
9505     }
9506
9507   if (!gtk_widget_get_visible (window))
9508     gtk_widget_show_all (window);
9509   else
9510     gtk_widget_destroy (window);
9511   
9512 }
9513
9514 struct SnapshotData {
9515   GtkWidget *toplevel_button;
9516   GtkWidget **window;
9517   GdkCursor *cursor;
9518   gboolean in_query;
9519   gboolean is_toplevel;
9520   gint handler;
9521 };
9522
9523 static void
9524 destroy_snapshot_data (GtkWidget             *widget,
9525                        struct SnapshotData *data)
9526 {
9527   if (*data->window)
9528     *data->window = NULL;
9529   
9530   if (data->cursor)
9531     {
9532       gdk_cursor_unref (data->cursor);
9533       data->cursor = NULL;
9534     }
9535
9536   if (data->handler)
9537     {
9538       g_signal_handler_disconnect (widget, data->handler);
9539       data->handler = 0;
9540     }
9541
9542   g_free (data);
9543 }
9544
9545 static gint
9546 snapshot_widget_event (GtkWidget               *widget,
9547                        GdkEvent        *event,
9548                        struct SnapshotData *data)
9549 {
9550   GtkWidget *res_widget = NULL;
9551
9552   if (!data->in_query)
9553     return FALSE;
9554   
9555   if (event->type == GDK_BUTTON_RELEASE)
9556     {
9557       gtk_grab_remove (widget);
9558       gdk_display_pointer_ungrab (gtk_widget_get_display (widget),
9559                                   GDK_CURRENT_TIME);
9560       
9561       res_widget = find_widget_at_pointer (gtk_widget_get_display (widget));
9562       if (data->is_toplevel && res_widget)
9563         res_widget = gtk_widget_get_toplevel (res_widget);
9564       if (res_widget)
9565         {
9566           GdkPixmap *pixmap;
9567           GtkWidget *window, *image;
9568
9569           window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9570           pixmap = gtk_widget_get_snapshot (res_widget, NULL);
9571           gtk_widget_realize (window);
9572           if (gdk_drawable_get_depth (window->window) != gdk_drawable_get_depth (pixmap))
9573             {
9574               /* this branch is needed to convert ARGB -> RGB */
9575               int width, height;
9576               GdkPixbuf *pixbuf;
9577               gdk_drawable_get_size (pixmap, &width, &height);
9578               pixbuf = gdk_pixbuf_get_from_drawable (NULL, pixmap,
9579                                                      gtk_widget_get_colormap (res_widget),
9580                                                      0, 0,
9581                                                      0, 0,
9582                                                      width, height);
9583               image = gtk_image_new_from_pixbuf (pixbuf);
9584               g_object_unref (pixbuf);
9585             }
9586           else
9587             image = gtk_image_new_from_pixmap (pixmap, NULL);
9588           gtk_container_add (GTK_CONTAINER (window), image);
9589           g_object_unref (pixmap);
9590           gtk_widget_show_all (window);
9591         }
9592
9593       data->in_query = FALSE;
9594     }
9595   return FALSE;
9596 }
9597
9598
9599 static void
9600 snapshot_widget (GtkButton *button,
9601                  struct SnapshotData *data)
9602 {
9603   gint failure;
9604
9605   g_signal_connect (button, "event",
9606                     G_CALLBACK (snapshot_widget_event), data);
9607
9608   data->is_toplevel = GTK_WIDGET (button) == data->toplevel_button;
9609   
9610   if (!data->cursor)
9611     data->cursor = gdk_cursor_new_for_display (gtk_widget_get_display (GTK_WIDGET (button)),
9612                                                GDK_TARGET);
9613   
9614   failure = gdk_pointer_grab (GTK_WIDGET (button)->window,
9615                               TRUE,
9616                               GDK_BUTTON_RELEASE_MASK,
9617                               NULL,
9618                               data->cursor,
9619                               GDK_CURRENT_TIME);
9620
9621   gtk_grab_add (GTK_WIDGET (button));
9622
9623   data->in_query = TRUE;
9624 }
9625
9626 static void
9627 create_snapshot (GtkWidget *widget)
9628 {
9629   static GtkWidget *window = NULL;
9630   GtkWidget *button;
9631   GtkWidget *vbox;
9632   struct SnapshotData *data;
9633
9634   data = g_new (struct SnapshotData, 1);
9635   data->window = &window;
9636   data->in_query = FALSE;
9637   data->cursor = NULL;
9638   data->handler = 0;
9639
9640   if (!window)
9641     {
9642       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9643
9644       gtk_window_set_screen (GTK_WINDOW (window),
9645                              gtk_widget_get_screen (widget));      
9646
9647       data->handler = g_signal_connect (window, "destroy",
9648                                         G_CALLBACK (destroy_snapshot_data),
9649                                         data);
9650
9651       gtk_window_set_title (GTK_WINDOW (window), "test snapshot");
9652       gtk_container_set_border_width (GTK_CONTAINER (window), 10);
9653
9654       vbox = gtk_vbox_new (FALSE, 1);
9655       gtk_container_add (GTK_CONTAINER (window), vbox);
9656             
9657       button = gtk_button_new_with_label ("Snapshot widget");
9658       gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
9659       g_signal_connect (button, "clicked",
9660                         G_CALLBACK (snapshot_widget),
9661                         data);
9662       
9663       button = gtk_button_new_with_label ("Snapshot toplevel");
9664       data->toplevel_button = button;
9665       gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
9666       g_signal_connect (button, "clicked",
9667                         G_CALLBACK (snapshot_widget),
9668                         data);
9669     }
9670
9671   if (!gtk_widget_get_visible (window))
9672     gtk_widget_show_all (window);
9673   else
9674     gtk_widget_destroy (window);
9675   
9676 }
9677
9678 /*
9679  * Selection Test
9680  */
9681
9682 void
9683 selection_test_received (GtkWidget        *tree_view,
9684                          GtkSelectionData *data)
9685 {
9686   GtkTreeModel *model;
9687   GtkListStore *store;
9688   GdkAtom *atoms;
9689   int i, l;
9690
9691   if (data->length < 0)
9692     {
9693       g_print ("Selection retrieval failed\n");
9694       return;
9695     }
9696   if (data->type != GDK_SELECTION_TYPE_ATOM)
9697     {
9698       g_print ("Selection \"TARGETS\" was not returned as atoms!\n");
9699       return;
9700     }
9701
9702   /* Clear out any current list items */
9703
9704   model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree_view));
9705   store = GTK_LIST_STORE (model);
9706   gtk_list_store_clear (store);
9707
9708   /* Add new items to list */
9709
9710   atoms = (GdkAtom *)data->data;
9711
9712   l = data->length / sizeof (GdkAtom);
9713   for (i = 0; i < l; i++)
9714     {
9715       char *name;
9716       GtkTreeIter iter;
9717
9718       name = gdk_atom_name (atoms[i]);
9719       if (name != NULL)
9720         {
9721           gtk_list_store_insert_with_values (store, &iter, i, 0, name, -1);
9722           g_free (name);
9723         }
9724       else
9725        gtk_list_store_insert_with_values (store, &iter, i, 0,  "(bad atom)", -1);
9726     }
9727
9728   return;
9729 }
9730
9731 void
9732 selection_test_get_targets (GtkWidget *widget, GtkWidget *tree_view)
9733 {
9734   static GdkAtom targets_atom = GDK_NONE;
9735
9736   if (targets_atom == GDK_NONE)
9737     targets_atom = gdk_atom_intern ("TARGETS", FALSE);
9738
9739   gtk_selection_convert (tree_view, GDK_SELECTION_PRIMARY, targets_atom,
9740                          GDK_CURRENT_TIME);
9741 }
9742
9743 void
9744 create_selection_test (GtkWidget *widget)
9745 {
9746   static GtkWidget *window = NULL;
9747   GtkWidget *button;
9748   GtkWidget *vbox;
9749   GtkWidget *scrolled_win;
9750   GtkListStore* store;
9751   GtkWidget *tree_view;
9752   GtkTreeViewColumn *column;
9753   GtkCellRenderer *renderer;
9754   GtkWidget *label;
9755
9756   if (!window)
9757     {
9758       window = gtk_dialog_new ();
9759       
9760       gtk_window_set_screen (GTK_WINDOW (window),
9761                              gtk_widget_get_screen (widget));
9762
9763       g_signal_connect (window, "destroy",
9764                         G_CALLBACK (gtk_widget_destroyed),
9765                         &window);
9766
9767       gtk_window_set_title (GTK_WINDOW (window), "Selection Test");
9768       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
9769
9770       /* Create the list */
9771
9772       vbox = gtk_vbox_new (FALSE, 5);
9773       gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
9774       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), vbox,
9775                           TRUE, TRUE, 0);
9776
9777       label = gtk_label_new ("Gets available targets for current selection");
9778       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
9779
9780       scrolled_win = gtk_scrolled_window_new (NULL, NULL);
9781       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
9782                                       GTK_POLICY_AUTOMATIC, 
9783                                       GTK_POLICY_AUTOMATIC);
9784       gtk_box_pack_start (GTK_BOX (vbox), scrolled_win, TRUE, TRUE, 0);
9785       gtk_widget_set_size_request (scrolled_win, 100, 200);
9786
9787       store = gtk_list_store_new (1, G_TYPE_STRING);
9788       tree_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store));
9789       gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_win), tree_view);
9790
9791       renderer = gtk_cell_renderer_text_new ();
9792       column = gtk_tree_view_column_new_with_attributes ("Target", renderer,
9793                                                          "text", 0, NULL);
9794       gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), column);
9795
9796       g_signal_connect (tree_view, "selection_received",
9797                         G_CALLBACK (selection_test_received), NULL);
9798
9799       /* .. And create some buttons */
9800       button = gtk_button_new_with_label ("Get Targets");
9801       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area),
9802                           button, TRUE, TRUE, 0);
9803
9804       g_signal_connect (button, "clicked",
9805                         G_CALLBACK (selection_test_get_targets), tree_view);
9806
9807       button = gtk_button_new_with_label ("Quit");
9808       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area),
9809                           button, TRUE, TRUE, 0);
9810
9811       g_signal_connect_swapped (button, "clicked",
9812                                 G_CALLBACK (gtk_widget_destroy),
9813                                 window);
9814     }
9815
9816   if (!gtk_widget_get_visible (window))
9817     gtk_widget_show_all (window);
9818   else
9819     gtk_widget_destroy (window);
9820 }
9821
9822 /*
9823  * Test scrolling
9824  */
9825
9826 static int scroll_test_pos = 0.0;
9827
9828 static gint
9829 scroll_test_expose (GtkWidget *widget, GdkEventExpose *event,
9830                     GtkAdjustment *adj)
9831 {
9832   gint i,j;
9833   gint imin, imax, jmin, jmax;
9834   
9835   imin = (event->area.x) / 10;
9836   imax = (event->area.x + event->area.width + 9) / 10;
9837
9838   jmin = ((int)adj->value + event->area.y) / 10;
9839   jmax = ((int)adj->value + event->area.y + event->area.height + 9) / 10;
9840
9841   gdk_window_clear_area (widget->window,
9842                          event->area.x, event->area.y,
9843                          event->area.width, event->area.height);
9844
9845   for (i=imin; i<imax; i++)
9846     for (j=jmin; j<jmax; j++)
9847       if ((i+j) % 2)
9848         gdk_draw_rectangle (widget->window, 
9849                             widget->style->black_gc,
9850                             TRUE,
9851                             10*i, 10*j - (int)adj->value, 1+i%10, 1+j%10);
9852
9853   return TRUE;
9854 }
9855
9856 static gint
9857 scroll_test_scroll (GtkWidget *widget, GdkEventScroll *event,
9858                     GtkAdjustment *adj)
9859 {
9860   gdouble new_value = adj->value + ((event->direction == GDK_SCROLL_UP) ?
9861                                     -adj->page_increment / 2:
9862                                     adj->page_increment / 2);
9863   new_value = CLAMP (new_value, adj->lower, adj->upper - adj->page_size);
9864   gtk_adjustment_set_value (adj, new_value);  
9865   
9866   return TRUE;
9867 }
9868
9869 static void
9870 scroll_test_configure (GtkWidget *widget, GdkEventConfigure *event,
9871                        GtkAdjustment *adj)
9872 {
9873   adj->page_increment = 0.9 * widget->allocation.height;
9874   adj->page_size = widget->allocation.height;
9875
9876   g_signal_emit_by_name (adj, "changed");
9877 }
9878
9879 static void
9880 scroll_test_adjustment_changed (GtkAdjustment *adj, GtkWidget *widget)
9881 {
9882   /* gint source_min = (int)adj->value - scroll_test_pos; */
9883   gint dy;
9884
9885   dy = scroll_test_pos - (int)adj->value;
9886   scroll_test_pos = adj->value;
9887
9888   if (!gtk_widget_is_drawable (widget))
9889     return;
9890   gdk_window_scroll (widget->window, 0, dy);
9891   gdk_window_process_updates (widget->window, FALSE);
9892 }
9893
9894
9895 void
9896 create_scroll_test (GtkWidget *widget)
9897 {
9898   static GtkWidget *window = NULL;
9899   GtkWidget *hbox;
9900   GtkWidget *drawing_area;
9901   GtkWidget *scrollbar;
9902   GtkWidget *button;
9903   GtkAdjustment *adj;
9904   GdkGeometry geometry;
9905   GdkWindowHints geometry_mask;
9906
9907   if (!window)
9908     {
9909       window = gtk_dialog_new ();
9910
9911       gtk_window_set_screen (GTK_WINDOW (window),
9912                              gtk_widget_get_screen (widget));
9913
9914       g_signal_connect (window, "destroy",
9915                         G_CALLBACK (gtk_widget_destroyed),
9916                         &window);
9917
9918       gtk_window_set_title (GTK_WINDOW (window), "Scroll Test");
9919       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
9920
9921       hbox = gtk_hbox_new (FALSE, 0);
9922       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), hbox,
9923                           TRUE, TRUE, 0);
9924       gtk_widget_show (hbox);
9925
9926       drawing_area = gtk_drawing_area_new ();
9927       gtk_widget_set_size_request (drawing_area, 200, 200);
9928       gtk_box_pack_start (GTK_BOX (hbox), drawing_area, TRUE, TRUE, 0);
9929       gtk_widget_show (drawing_area);
9930
9931       gtk_widget_set_events (drawing_area, GDK_EXPOSURE_MASK | GDK_SCROLL_MASK);
9932
9933       adj = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 1000.0, 1.0, 180.0, 200.0));
9934       scroll_test_pos = 0.0;
9935
9936       scrollbar = gtk_vscrollbar_new (adj);
9937       gtk_box_pack_start (GTK_BOX (hbox), scrollbar, FALSE, FALSE, 0);
9938       gtk_widget_show (scrollbar);
9939
9940       g_signal_connect (drawing_area, "expose_event",
9941                         G_CALLBACK (scroll_test_expose), adj);
9942       g_signal_connect (drawing_area, "configure_event",
9943                         G_CALLBACK (scroll_test_configure), adj);
9944       g_signal_connect (drawing_area, "scroll_event",
9945                         G_CALLBACK (scroll_test_scroll), adj);
9946       
9947       g_signal_connect (adj, "value_changed",
9948                         G_CALLBACK (scroll_test_adjustment_changed),
9949                         drawing_area);
9950       
9951       /* .. And create some buttons */
9952
9953       button = gtk_button_new_with_label ("Quit");
9954       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area),
9955                           button, TRUE, TRUE, 0);
9956
9957       g_signal_connect_swapped (button, "clicked",
9958                                 G_CALLBACK (gtk_widget_destroy),
9959                                 window);
9960       gtk_widget_show (button);
9961
9962       /* Set up gridded geometry */
9963
9964       geometry_mask = GDK_HINT_MIN_SIZE | 
9965                        GDK_HINT_BASE_SIZE | 
9966                        GDK_HINT_RESIZE_INC;
9967
9968       geometry.min_width = 20;
9969       geometry.min_height = 20;
9970       geometry.base_width = 0;
9971       geometry.base_height = 0;
9972       geometry.width_inc = 10;
9973       geometry.height_inc = 10;
9974       
9975       gtk_window_set_geometry_hints (GTK_WINDOW (window),
9976                                drawing_area, &geometry, geometry_mask);
9977     }
9978
9979   if (!gtk_widget_get_visible (window))
9980     gtk_widget_show (window);
9981   else
9982     gtk_widget_destroy (window);
9983 }
9984
9985 /*
9986  * Timeout Test
9987  */
9988
9989 static int timer = 0;
9990
9991 gint
9992 timeout_test (GtkWidget *label)
9993 {
9994   static int count = 0;
9995   static char buffer[32];
9996
9997   sprintf (buffer, "count: %d", ++count);
9998   gtk_label_set_text (GTK_LABEL (label), buffer);
9999
10000   return TRUE;
10001 }
10002
10003 void
10004 start_timeout_test (GtkWidget *widget,
10005                     GtkWidget *label)
10006 {
10007   if (!timer)
10008     {
10009       timer = g_timeout_add (100, (GSourceFunc)timeout_test, label);
10010     }
10011 }
10012
10013 void
10014 stop_timeout_test (GtkWidget *widget,
10015                    gpointer   data)
10016 {
10017   if (timer)
10018     {
10019       g_source_remove (timer);
10020       timer = 0;
10021     }
10022 }
10023
10024 void
10025 destroy_timeout_test (GtkWidget  *widget,
10026                       GtkWidget **window)
10027 {
10028   stop_timeout_test (NULL, NULL);
10029
10030   *window = NULL;
10031 }
10032
10033 void
10034 create_timeout_test (GtkWidget *widget)
10035 {
10036   static GtkWidget *window = NULL;
10037   GtkWidget *button;
10038   GtkWidget *label;
10039
10040   if (!window)
10041     {
10042       window = gtk_dialog_new ();
10043
10044       gtk_window_set_screen (GTK_WINDOW (window),
10045                              gtk_widget_get_screen (widget));
10046
10047       g_signal_connect (window, "destroy",
10048                         G_CALLBACK (destroy_timeout_test),
10049                         &window);
10050
10051       gtk_window_set_title (GTK_WINDOW (window), "Timeout Test");
10052       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
10053
10054       label = gtk_label_new ("count: 0");
10055       gtk_misc_set_padding (GTK_MISC (label), 10, 10);
10056       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
10057                           label, TRUE, TRUE, 0);
10058       gtk_widget_show (label);
10059
10060       button = gtk_button_new_with_label ("close");
10061       g_signal_connect_swapped (button, "clicked",
10062                                 G_CALLBACK (gtk_widget_destroy),
10063                                 window);
10064       gtk_widget_set_can_default (button, TRUE);
10065       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
10066                           button, TRUE, TRUE, 0);
10067       gtk_widget_grab_default (button);
10068       gtk_widget_show (button);
10069
10070       button = gtk_button_new_with_label ("start");
10071       g_signal_connect (button, "clicked",
10072                         G_CALLBACK(start_timeout_test),
10073                         label);
10074       gtk_widget_set_can_default (button, TRUE);
10075       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
10076                           button, TRUE, TRUE, 0);
10077       gtk_widget_show (button);
10078
10079       button = gtk_button_new_with_label ("stop");
10080       g_signal_connect (button, "clicked",
10081                         G_CALLBACK (stop_timeout_test),
10082                         NULL);
10083       gtk_widget_set_can_default (button, TRUE);
10084       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
10085                           button, TRUE, TRUE, 0);
10086       gtk_widget_show (button);
10087     }
10088
10089   if (!gtk_widget_get_visible (window))
10090     gtk_widget_show (window);
10091   else
10092     gtk_widget_destroy (window);
10093 }
10094
10095 /*
10096  * Idle Test
10097  */
10098
10099 static int idle_id = 0;
10100
10101 static gint
10102 idle_test (GtkWidget *label)
10103 {
10104   static int count = 0;
10105   static char buffer[32];
10106
10107   sprintf (buffer, "count: %d", ++count);
10108   gtk_label_set_text (GTK_LABEL (label), buffer);
10109
10110   return TRUE;
10111 }
10112
10113 static void
10114 start_idle_test (GtkWidget *widget,
10115                  GtkWidget *label)
10116 {
10117   if (!idle_id)
10118     {
10119       idle_id = g_idle_add ((GSourceFunc) idle_test, label);
10120     }
10121 }
10122
10123 static void
10124 stop_idle_test (GtkWidget *widget,
10125                 gpointer   data)
10126 {
10127   if (idle_id)
10128     {
10129       g_source_remove (idle_id);
10130       idle_id = 0;
10131     }
10132 }
10133
10134 static void
10135 destroy_idle_test (GtkWidget  *widget,
10136                    GtkWidget **window)
10137 {
10138   stop_idle_test (NULL, NULL);
10139
10140   *window = NULL;
10141 }
10142
10143 static void
10144 toggle_idle_container (GObject *button,
10145                        GtkContainer *container)
10146 {
10147   gtk_container_set_resize_mode (container, GPOINTER_TO_INT (g_object_get_data (button, "user_data")));
10148 }
10149
10150 static void
10151 create_idle_test (GtkWidget *widget)
10152 {
10153   static GtkWidget *window = NULL;
10154   GtkWidget *button;
10155   GtkWidget *label;
10156   GtkWidget *container;
10157
10158   if (!window)
10159     {
10160       GtkWidget *button2;
10161       GtkWidget *frame;
10162       GtkWidget *box;
10163
10164       window = gtk_dialog_new ();
10165
10166       gtk_window_set_screen (GTK_WINDOW (window),
10167                              gtk_widget_get_screen (widget));
10168
10169       g_signal_connect (window, "destroy",
10170                         G_CALLBACK (destroy_idle_test),
10171                         &window);
10172
10173       gtk_window_set_title (GTK_WINDOW (window), "Idle Test");
10174       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
10175
10176       label = gtk_label_new ("count: 0");
10177       gtk_misc_set_padding (GTK_MISC (label), 10, 10);
10178       gtk_widget_show (label);
10179       
10180       container =
10181         g_object_new (GTK_TYPE_HBOX,
10182                         "visible", TRUE,
10183                         /* "GtkContainer::child", g_object_new (GTK_TYPE_HBOX,
10184                          * "GtkWidget::visible", TRUE,
10185                          */
10186                          "child", label,
10187                         /* NULL), */
10188                         NULL);
10189       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
10190                           container, TRUE, TRUE, 0);
10191
10192       frame =
10193         g_object_new (GTK_TYPE_FRAME,
10194                         "border_width", 5,
10195                         "label", "Label Container",
10196                         "visible", TRUE,
10197                         "parent", GTK_DIALOG (window)->vbox,
10198                         NULL);
10199       box =
10200         g_object_new (GTK_TYPE_VBOX,
10201                         "visible", TRUE,
10202                         "parent", frame,
10203                         NULL);
10204       button =
10205         g_object_connect (g_object_new (GTK_TYPE_RADIO_BUTTON,
10206                                           "label", "Resize-Parent",
10207                                           "user_data", (void*)GTK_RESIZE_PARENT,
10208                                           "visible", TRUE,
10209                                           "parent", box,
10210                                           NULL),
10211                           "signal::clicked", toggle_idle_container, container,
10212                           NULL);
10213       button = g_object_new (GTK_TYPE_RADIO_BUTTON,
10214                                "label", "Resize-Queue",
10215                                "user_data", (void*)GTK_RESIZE_QUEUE,
10216                                "group", button,
10217                                "visible", TRUE,
10218                                "parent", box,
10219                                NULL);
10220       g_object_connect (button,
10221                         "signal::clicked", toggle_idle_container, container,
10222                         NULL);
10223       button2 = g_object_new (GTK_TYPE_RADIO_BUTTON,
10224                                 "label", "Resize-Immediate",
10225                                 "user_data", (void*)GTK_RESIZE_IMMEDIATE,
10226                                 NULL);
10227       g_object_connect (button2,
10228                         "signal::clicked", toggle_idle_container, container,
10229                         NULL);
10230       g_object_set (button2,
10231                     "group", button,
10232                     "visible", TRUE,
10233                     "parent", box,
10234                     NULL);
10235
10236       button = gtk_button_new_with_label ("close");
10237       g_signal_connect_swapped (button, "clicked",
10238                                 G_CALLBACK (gtk_widget_destroy),
10239                                 window);
10240       gtk_widget_set_can_default (button, TRUE);
10241       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
10242                           button, TRUE, TRUE, 0);
10243       gtk_widget_grab_default (button);
10244       gtk_widget_show (button);
10245
10246       button = gtk_button_new_with_label ("start");
10247       g_signal_connect (button, "clicked",
10248                         G_CALLBACK (start_idle_test),
10249                         label);
10250       gtk_widget_set_can_default (button, TRUE);
10251       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
10252                           button, TRUE, TRUE, 0);
10253       gtk_widget_show (button);
10254
10255       button = gtk_button_new_with_label ("stop");
10256       g_signal_connect (button, "clicked",
10257                         G_CALLBACK (stop_idle_test),
10258                         NULL);
10259       gtk_widget_set_can_default (button, TRUE);
10260       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
10261                           button, TRUE, TRUE, 0);
10262       gtk_widget_show (button);
10263     }
10264
10265   if (!gtk_widget_get_visible (window))
10266     gtk_widget_show (window);
10267   else
10268     gtk_widget_destroy (window);
10269 }
10270
10271 /*
10272  * rc file test
10273  */
10274
10275 void
10276 reload_all_rc_files (void)
10277 {
10278   static GdkAtom atom_rcfiles = GDK_NONE;
10279
10280   GdkEvent *send_event = gdk_event_new (GDK_CLIENT_EVENT);
10281   int i;
10282   
10283   if (!atom_rcfiles)
10284     atom_rcfiles = gdk_atom_intern("_GTK_READ_RCFILES", FALSE);
10285
10286   for(i = 0; i < 5; i++)
10287     send_event->client.data.l[i] = 0;
10288   send_event->client.data_format = 32;
10289   send_event->client.message_type = atom_rcfiles;
10290   gdk_event_send_clientmessage_toall (send_event);
10291
10292   gdk_event_free (send_event);
10293 }
10294
10295 void
10296 create_rc_file (GtkWidget *widget)
10297 {
10298   static GtkWidget *window = NULL;
10299   GtkWidget *button;
10300   GtkWidget *frame;
10301   GtkWidget *vbox;
10302   GtkWidget *label;
10303
10304   if (!window)
10305     {
10306       window = gtk_dialog_new ();
10307
10308       gtk_window_set_screen (GTK_WINDOW (window),
10309                              gtk_widget_get_screen (widget));
10310
10311       g_signal_connect (window, "destroy",
10312                         G_CALLBACK (gtk_widget_destroyed),
10313                         &window);
10314
10315       frame = gtk_aspect_frame_new ("Testing RC file prioritization", 0.5, 0.5, 0.0, TRUE);
10316       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), frame, FALSE, FALSE, 0);
10317
10318       vbox = gtk_vbox_new (FALSE, 0);
10319       gtk_container_add (GTK_CONTAINER (frame), vbox);
10320       
10321       label = gtk_label_new ("This label should be red");
10322       gtk_widget_set_name (label, "testgtk-red-label");
10323       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
10324
10325       label = gtk_label_new ("This label should be green");
10326       gtk_widget_set_name (label, "testgtk-green-label");
10327       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
10328
10329       label = gtk_label_new ("This label should be blue");
10330       gtk_widget_set_name (label, "testgtk-blue-label");
10331       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
10332
10333       gtk_window_set_title (GTK_WINDOW (window), "Reload Rc file");
10334       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
10335
10336       button = gtk_button_new_with_label ("Reload");
10337       g_signal_connect (button, "clicked",
10338                         G_CALLBACK (gtk_rc_reparse_all), NULL);
10339       gtk_widget_set_can_default (button, TRUE);
10340       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
10341                           button, TRUE, TRUE, 0);
10342       gtk_widget_grab_default (button);
10343
10344       button = gtk_button_new_with_label ("Reload All");
10345       g_signal_connect (button, "clicked",
10346                         G_CALLBACK (reload_all_rc_files), NULL);
10347       gtk_widget_set_can_default (button, TRUE);
10348       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
10349                           button, TRUE, TRUE, 0);
10350
10351       button = gtk_button_new_with_label ("Close");
10352       g_signal_connect_swapped (button, "clicked",
10353                                 G_CALLBACK (gtk_widget_destroy),
10354                                 window);
10355       gtk_widget_set_can_default (button, TRUE);
10356       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
10357                           button, TRUE, TRUE, 0);
10358     }
10359
10360   if (!gtk_widget_get_visible (window))
10361     gtk_widget_show_all (window);
10362   else
10363     gtk_widget_destroy (window);
10364 }
10365
10366 /*
10367  * Test of recursive mainloop
10368  */
10369
10370 void
10371 mainloop_destroyed (GtkWidget *w, GtkWidget **window)
10372 {
10373   *window = NULL;
10374   gtk_main_quit ();
10375 }
10376
10377 void
10378 create_mainloop (GtkWidget *widget)
10379 {
10380   static GtkWidget *window = NULL;
10381   GtkWidget *label;
10382   GtkWidget *button;
10383
10384   if (!window)
10385     {
10386       window = gtk_dialog_new ();
10387
10388       gtk_window_set_screen (GTK_WINDOW (window),
10389                              gtk_widget_get_screen (widget));
10390
10391       gtk_window_set_title (GTK_WINDOW (window), "Test Main Loop");
10392
10393       g_signal_connect (window, "destroy",
10394                         G_CALLBACK (mainloop_destroyed),
10395                         &window);
10396
10397       label = gtk_label_new ("In recursive main loop...");
10398       gtk_misc_set_padding (GTK_MISC(label), 20, 20);
10399
10400       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), label,
10401                           TRUE, TRUE, 0);
10402       gtk_widget_show (label);
10403
10404       button = gtk_button_new_with_label ("Leave");
10405       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), button, 
10406                           FALSE, TRUE, 0);
10407
10408       g_signal_connect_swapped (button, "clicked",
10409                                 G_CALLBACK (gtk_widget_destroy),
10410                                 window);
10411
10412       gtk_widget_set_can_default (button, TRUE);
10413       gtk_widget_grab_default (button);
10414
10415       gtk_widget_show (button);
10416     }
10417
10418   if (!gtk_widget_get_visible (window))
10419     {
10420       gtk_widget_show (window);
10421
10422       g_print ("create_mainloop: start\n");
10423       gtk_main ();
10424       g_print ("create_mainloop: done\n");
10425     }
10426   else
10427     gtk_widget_destroy (window);
10428 }
10429
10430 gboolean
10431 layout_expose_handler (GtkWidget *widget, GdkEventExpose *event)
10432 {
10433   GtkLayout *layout;
10434
10435   gint i,j;
10436   gint imin, imax, jmin, jmax;
10437
10438   layout = GTK_LAYOUT (widget);
10439
10440   if (event->window != layout->bin_window)
10441     return FALSE;
10442   
10443   imin = (event->area.x) / 10;
10444   imax = (event->area.x + event->area.width + 9) / 10;
10445
10446   jmin = (event->area.y) / 10;
10447   jmax = (event->area.y + event->area.height + 9) / 10;
10448
10449   for (i=imin; i<imax; i++)
10450     for (j=jmin; j<jmax; j++)
10451       if ((i+j) % 2)
10452         gdk_draw_rectangle (layout->bin_window,
10453                             widget->style->black_gc,
10454                             TRUE,
10455                             10*i, 10*j, 
10456                             1+i%10, 1+j%10);
10457   
10458   return FALSE;
10459 }
10460
10461 void create_layout (GtkWidget *widget)
10462 {
10463   static GtkWidget *window = NULL;
10464   GtkWidget *layout;
10465   GtkWidget *scrolledwindow;
10466   GtkWidget *button;
10467
10468   if (!window)
10469     {
10470       gchar buf[16];
10471
10472       gint i, j;
10473       
10474       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
10475       gtk_window_set_screen (GTK_WINDOW (window),
10476                              gtk_widget_get_screen (widget));
10477
10478       g_signal_connect (window, "destroy",
10479                         G_CALLBACK (gtk_widget_destroyed),
10480                         &window);
10481
10482       gtk_window_set_title (GTK_WINDOW (window), "Layout");
10483       gtk_widget_set_size_request (window, 200, 200);
10484
10485       scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
10486       gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolledwindow),
10487                                            GTK_SHADOW_IN);
10488       gtk_scrolled_window_set_placement (GTK_SCROLLED_WINDOW (scrolledwindow),
10489                                          GTK_CORNER_TOP_RIGHT);
10490
10491       gtk_container_add (GTK_CONTAINER (window), scrolledwindow);
10492       
10493       layout = gtk_layout_new (NULL, NULL);
10494       gtk_container_add (GTK_CONTAINER (scrolledwindow), layout);
10495
10496       /* We set step sizes here since GtkLayout does not set
10497        * them itself.
10498        */
10499       GTK_LAYOUT (layout)->hadjustment->step_increment = 10.0;
10500       GTK_LAYOUT (layout)->vadjustment->step_increment = 10.0;
10501       
10502       gtk_widget_set_events (layout, GDK_EXPOSURE_MASK);
10503       g_signal_connect (layout, "expose_event",
10504                         G_CALLBACK (layout_expose_handler), NULL);
10505       
10506       gtk_layout_set_size (GTK_LAYOUT (layout), 1600, 128000);
10507       
10508       for (i=0 ; i < 16 ; i++)
10509         for (j=0 ; j < 16 ; j++)
10510           {
10511             sprintf(buf, "Button %d, %d", i, j);
10512             if ((i + j) % 2)
10513               button = gtk_button_new_with_label (buf);
10514             else
10515               button = gtk_label_new (buf);
10516
10517             gtk_layout_put (GTK_LAYOUT (layout), button,
10518                             j*100, i*100);
10519           }
10520
10521       for (i=16; i < 1280; i++)
10522         {
10523           sprintf(buf, "Button %d, %d", i, 0);
10524           if (i % 2)
10525             button = gtk_button_new_with_label (buf);
10526           else
10527             button = gtk_label_new (buf);
10528
10529           gtk_layout_put (GTK_LAYOUT (layout), button,
10530                           0, i*100);
10531         }
10532     }
10533
10534   if (!gtk_widget_get_visible (window))
10535     gtk_widget_show_all (window);
10536   else
10537     gtk_widget_destroy (window);
10538 }
10539
10540 void
10541 create_styles (GtkWidget *widget)
10542 {
10543   static GtkWidget *window = NULL;
10544   GtkWidget *label;
10545   GtkWidget *button;
10546   GtkWidget *entry;
10547   GtkWidget *vbox;
10548   static GdkColor red =    { 0, 0xffff, 0,      0      };
10549   static GdkColor green =  { 0, 0,      0xffff, 0      };
10550   static GdkColor blue =   { 0, 0,      0,      0xffff };
10551   static GdkColor yellow = { 0, 0xffff, 0xffff, 0      };
10552   static GdkColor cyan =   { 0, 0     , 0xffff, 0xffff };
10553   PangoFontDescription *font_desc;
10554
10555   GtkRcStyle *rc_style;
10556
10557   if (!window)
10558     {
10559       window = gtk_dialog_new ();
10560       gtk_window_set_screen (GTK_WINDOW (window),
10561                              gtk_widget_get_screen (widget));
10562      
10563       g_signal_connect (window, "destroy",
10564                         G_CALLBACK (gtk_widget_destroyed),
10565                         &window);
10566
10567       
10568       button = gtk_button_new_with_label ("Close");
10569       g_signal_connect_swapped (button, "clicked",
10570                                 G_CALLBACK (gtk_widget_destroy),
10571                                 window);
10572       gtk_widget_set_can_default (button, TRUE);
10573       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
10574                           button, TRUE, TRUE, 0);
10575       gtk_widget_show (button);
10576
10577       vbox = gtk_vbox_new (FALSE, 5);
10578       gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
10579       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), vbox, FALSE, FALSE, 0);
10580       
10581       label = gtk_label_new ("Font:");
10582       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
10583       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
10584
10585       font_desc = pango_font_description_from_string ("Helvetica,Sans Oblique 18");
10586
10587       button = gtk_button_new_with_label ("Some Text");
10588       gtk_widget_modify_font (GTK_BIN (button)->child, font_desc);
10589       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
10590
10591       label = gtk_label_new ("Foreground:");
10592       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
10593       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
10594
10595       button = gtk_button_new_with_label ("Some Text");
10596       gtk_widget_modify_fg (GTK_BIN (button)->child, GTK_STATE_NORMAL, &red);
10597       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
10598
10599       label = gtk_label_new ("Background:");
10600       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
10601       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
10602
10603       button = gtk_button_new_with_label ("Some Text");
10604       gtk_widget_modify_bg (button, GTK_STATE_NORMAL, &green);
10605       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
10606
10607       label = gtk_label_new ("Text:");
10608       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
10609       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
10610
10611       entry = gtk_entry_new ();
10612       gtk_entry_set_text (GTK_ENTRY (entry), "Some Text");
10613       gtk_widget_modify_text (entry, GTK_STATE_NORMAL, &blue);
10614       gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
10615
10616       label = gtk_label_new ("Base:");
10617       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
10618       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
10619
10620       entry = gtk_entry_new ();
10621       gtk_entry_set_text (GTK_ENTRY (entry), "Some Text");
10622       gtk_widget_modify_base (entry, GTK_STATE_NORMAL, &yellow);
10623       gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
10624
10625       label = gtk_label_new ("Cursor:");
10626       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
10627       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
10628
10629       entry = gtk_entry_new ();
10630       gtk_entry_set_text (GTK_ENTRY (entry), "Some Text");
10631       gtk_widget_modify_cursor (entry, &red, &red);
10632       gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
10633
10634       label = gtk_label_new ("Multiple:");
10635       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
10636       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
10637
10638       button = gtk_button_new_with_label ("Some Text");
10639
10640       rc_style = gtk_rc_style_new ();
10641
10642       rc_style->font_desc = pango_font_description_copy (font_desc);
10643       rc_style->color_flags[GTK_STATE_NORMAL] = GTK_RC_FG | GTK_RC_BG;
10644       rc_style->color_flags[GTK_STATE_PRELIGHT] = GTK_RC_FG | GTK_RC_BG;
10645       rc_style->color_flags[GTK_STATE_ACTIVE] = GTK_RC_FG | GTK_RC_BG;
10646       rc_style->fg[GTK_STATE_NORMAL] = yellow;
10647       rc_style->bg[GTK_STATE_NORMAL] = blue;
10648       rc_style->fg[GTK_STATE_PRELIGHT] = blue;
10649       rc_style->bg[GTK_STATE_PRELIGHT] = yellow;
10650       rc_style->fg[GTK_STATE_ACTIVE] = red;
10651       rc_style->bg[GTK_STATE_ACTIVE] = cyan;
10652       rc_style->xthickness = 5;
10653       rc_style->ythickness = 5;
10654
10655       gtk_widget_modify_style (button, rc_style);
10656       gtk_widget_modify_style (GTK_BIN (button)->child, rc_style);
10657
10658       g_object_unref (rc_style);
10659       
10660       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
10661     }
10662   
10663   if (!gtk_widget_get_visible (window))
10664     gtk_widget_show_all (window);
10665   else
10666     gtk_widget_destroy (window);
10667 }
10668
10669 /*
10670  * Main Window and Exit
10671  */
10672
10673 void
10674 do_exit (GtkWidget *widget, GtkWidget *window)
10675 {
10676   gtk_widget_destroy (window);
10677   gtk_main_quit ();
10678 }
10679
10680 struct {
10681   char *label;
10682   void (*func) (GtkWidget *widget);
10683   gboolean do_not_benchmark;
10684 } buttons[] =
10685 {
10686   { "alpha window", create_alpha_window },
10687   { "big windows", create_big_windows },
10688   { "button box", create_button_box },
10689   { "buttons", create_buttons },
10690   { "check buttons", create_check_buttons },
10691   { "color selection", create_color_selection },
10692   { "composited window", create_composited_window },
10693   { "cursors", create_cursors },
10694   { "dialog", create_dialog },
10695   { "display & screen", create_display_screen, TRUE },
10696   { "entry", create_entry },
10697   { "event box", create_event_box },
10698   { "event watcher", create_event_watcher },
10699   { "expander", create_expander },
10700   { "flipping", create_flipping },
10701   { "focus", create_focus },
10702   { "font selection", create_font_selection },
10703   { "gridded geometry", create_gridded_geometry },
10704   { "handle box", create_handle_box },
10705   { "image from drawable", create_get_image },
10706   { "image", create_image },
10707   { "key lookup", create_key_lookup },
10708   { "labels", create_labels },
10709   { "layout", create_layout },
10710   { "menus", create_menus },
10711   { "message dialog", create_message_dialog },
10712   { "modal window", create_modal_window, TRUE },
10713   { "notebook", create_notebook },
10714   { "panes", create_panes },
10715   { "paned keyboard", create_paned_keyboard_navigation },
10716   { "pixmap", create_pixmap },
10717   { "progress bar", create_progress_bar },
10718   { "properties", create_properties },
10719   { "radio buttons", create_radio_buttons },
10720   { "range controls", create_range_controls },
10721   { "rc file", create_rc_file },
10722   { "reparent", create_reparent },
10723   { "resize grips", create_resize_grips },
10724   { "rotated label", create_rotated_label },
10725   { "rotated text", create_rotated_text },
10726   { "rulers", create_rulers },
10727   { "saved position", create_saved_position },
10728   { "scrolled windows", create_scrolled_windows },
10729   { "shapes", create_shapes },
10730   { "size groups", create_size_groups },
10731   { "snapshot", create_snapshot },
10732   { "spinbutton", create_spins },
10733   { "statusbar", create_statusbar },
10734   { "styles", create_styles },
10735   { "test idle", create_idle_test },
10736   { "test mainloop", create_mainloop, TRUE },
10737   { "test scrolling", create_scroll_test },
10738   { "test selection", create_selection_test },
10739   { "test timeout", create_timeout_test },
10740   { "toggle buttons", create_toggle_buttons },
10741   { "toolbar", create_toolbar },
10742   { "tooltips", create_tooltips },
10743   { "WM hints", create_wmhints },
10744   { "window sizing", create_window_sizing },
10745   { "window states", create_window_states }
10746 };
10747 int nbuttons = sizeof (buttons) / sizeof (buttons[0]);
10748
10749 void
10750 create_main_window (void)
10751 {
10752   GtkWidget *window;
10753   GtkWidget *box1;
10754   GtkWidget *box2;
10755   GtkWidget *scrolled_window;
10756   GtkWidget *button;
10757   GtkWidget *label;
10758   gchar buffer[64];
10759   GtkWidget *separator;
10760   GdkGeometry geometry;
10761   int i;
10762
10763   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
10764   gtk_widget_set_name (window, "main window");
10765   gtk_widget_set_uposition (window, 50, 20);
10766   gtk_window_set_default_size (GTK_WINDOW (window), -1, 400);
10767
10768   geometry.min_width = -1;
10769   geometry.min_height = -1;
10770   geometry.max_width = -1;
10771   geometry.max_height = G_MAXSHORT;
10772   gtk_window_set_geometry_hints (GTK_WINDOW (window), NULL,
10773                                  &geometry,
10774                                  GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE);
10775
10776   g_signal_connect (window, "destroy",
10777                     G_CALLBACK (gtk_main_quit),
10778                     NULL);
10779   g_signal_connect (window, "delete-event",
10780                     G_CALLBACK (gtk_false),
10781                     NULL);
10782
10783   box1 = gtk_vbox_new (FALSE, 0);
10784   gtk_container_add (GTK_CONTAINER (window), box1);
10785
10786   if (gtk_micro_version > 0)
10787     sprintf (buffer,
10788              "Gtk+ v%d.%d.%d",
10789              gtk_major_version,
10790              gtk_minor_version,
10791              gtk_micro_version);
10792   else
10793     sprintf (buffer,
10794              "Gtk+ v%d.%d",
10795              gtk_major_version,
10796              gtk_minor_version);
10797
10798   label = gtk_label_new (buffer);
10799   gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);
10800   gtk_widget_set_name (label, "testgtk-version-label");
10801
10802   scrolled_window = gtk_scrolled_window_new (NULL, NULL);
10803   gtk_container_set_border_width (GTK_CONTAINER (scrolled_window), 10);
10804   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
10805                                   GTK_POLICY_NEVER, 
10806                                   GTK_POLICY_AUTOMATIC);
10807   gtk_box_pack_start (GTK_BOX (box1), scrolled_window, TRUE, TRUE, 0);
10808
10809   box2 = gtk_vbox_new (FALSE, 0);
10810   gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
10811   gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_window), box2);
10812   gtk_container_set_focus_vadjustment (GTK_CONTAINER (box2),
10813                                        gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (scrolled_window)));
10814   gtk_widget_show (box2);
10815
10816   for (i = 0; i < nbuttons; i++)
10817     {
10818       button = gtk_button_new_with_label (buttons[i].label);
10819       if (buttons[i].func)
10820         g_signal_connect (button, 
10821                           "clicked", 
10822                           G_CALLBACK(buttons[i].func),
10823                           NULL);
10824       else
10825         gtk_widget_set_sensitive (button, FALSE);
10826       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
10827     }
10828
10829   separator = gtk_hseparator_new ();
10830   gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
10831
10832   box2 = gtk_vbox_new (FALSE, 10);
10833   gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
10834   gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
10835
10836   button = gtk_button_new_with_mnemonic ("_Close");
10837   g_signal_connect (button, "clicked",
10838                     G_CALLBACK (do_exit),
10839                     window);
10840   gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
10841   gtk_widget_set_can_default (button, TRUE);
10842   gtk_widget_grab_default (button);
10843
10844   gtk_widget_show_all (window);
10845 }
10846
10847 static void
10848 test_init (void)
10849 {
10850   if (g_file_test ("../gdk-pixbuf/libpixbufloader-pnm.la",
10851                    G_FILE_TEST_EXISTS))
10852     {
10853       g_setenv ("GDK_PIXBUF_MODULE_FILE", "../gdk-pixbuf/gdk-pixbuf.loaders", TRUE);
10854       g_setenv ("GTK_IM_MODULE_FILE", "../modules/input/gtk.immodules", TRUE);
10855     }
10856 }
10857
10858 static char *
10859 pad (const char *str, int to)
10860 {
10861   static char buf[256];
10862   int len = strlen (str);
10863   int i;
10864
10865   for (i = 0; i < to; i++)
10866     buf[i] = ' ';
10867
10868   buf[to] = '\0';
10869
10870   memcpy (buf, str, len);
10871
10872   return buf;
10873 }
10874
10875 static void
10876 bench_iteration (GtkWidget *widget, void (* fn) (GtkWidget *widget))
10877 {
10878   fn (widget); /* on */
10879   while (g_main_context_iteration (NULL, FALSE));
10880   fn (widget); /* off */
10881   while (g_main_context_iteration (NULL, FALSE));
10882 }
10883
10884 void
10885 do_real_bench (GtkWidget *widget, void (* fn) (GtkWidget *widget), char *name, int num)
10886 {
10887   GTimeVal tv0, tv1;
10888   double dt_first;
10889   double dt;
10890   int n;
10891   static gboolean printed_headers = FALSE;
10892
10893   if (!printed_headers) {
10894     g_print ("Test                 Iters      First      Other\n");
10895     g_print ("-------------------- ----- ---------- ----------\n");
10896     printed_headers = TRUE;
10897   }
10898
10899   g_get_current_time (&tv0);
10900   bench_iteration (widget, fn); 
10901   g_get_current_time (&tv1);
10902
10903   dt_first = ((double)tv1.tv_sec - tv0.tv_sec) * 1000.0
10904         + (tv1.tv_usec - tv0.tv_usec) / 1000.0;
10905
10906   g_get_current_time (&tv0);
10907   for (n = 0; n < num - 1; n++)
10908     bench_iteration (widget, fn); 
10909   g_get_current_time (&tv1);
10910   dt = ((double)tv1.tv_sec - tv0.tv_sec) * 1000.0
10911         + (tv1.tv_usec - tv0.tv_usec) / 1000.0;
10912
10913   g_print ("%s %5d ", pad (name, 20), num);
10914   if (num > 1)
10915     g_print ("%10.1f %10.1f\n", dt_first, dt/(num-1));
10916   else
10917     g_print ("%10.1f\n", dt_first);
10918 }
10919
10920 void
10921 do_bench (char* what, int num)
10922 {
10923   int i;
10924   GtkWidget *widget;
10925   void (* fn) (GtkWidget *widget);
10926   fn = NULL;
10927   widget = gtk_window_new (GTK_WINDOW_TOPLEVEL);
10928
10929   if (g_ascii_strcasecmp (what, "ALL") == 0)
10930     {
10931       for (i = 0; i < nbuttons; i++)
10932         {
10933           if (!buttons[i].do_not_benchmark)
10934             do_real_bench (widget, buttons[i].func, buttons[i].label, num);
10935         }
10936
10937       return;
10938     }
10939   else
10940     {
10941       for (i = 0; i < nbuttons; i++)
10942         {
10943           if (strcmp (buttons[i].label, what) == 0)
10944             {
10945               fn = buttons[i].func;
10946               break;
10947             }
10948         }
10949       
10950       if (!fn)
10951         g_print ("Can't bench: \"%s\" not found.\n", what);
10952       else
10953         do_real_bench (widget, fn, buttons[i].label, num);
10954     }
10955 }
10956
10957 void 
10958 usage (void)
10959 {
10960   fprintf (stderr, "Usage: testgtk [--bench ALL|<bench>[:<count>]]\n");
10961   exit (1);
10962 }
10963
10964 int
10965 main (int argc, char *argv[])
10966 {
10967   GtkBindingSet *binding_set;
10968   int i;
10969   gboolean done_benchmarks = FALSE;
10970
10971   srand (time (NULL));
10972
10973   test_init ();
10974
10975   /* Check to see if we are being run from the correct
10976    * directory.
10977    */
10978   if (file_exists ("testgtkrc"))
10979     gtk_rc_add_default_file ("testgtkrc");
10980   else if (file_exists ("tests/testgtkrc"))
10981     gtk_rc_add_default_file ("tests/testgtkrc");
10982   else
10983     g_warning ("Couldn't find file \"testgtkrc\".");
10984
10985   g_set_application_name ("GTK+ Test Program");
10986
10987   gtk_init (&argc, &argv);
10988
10989   gtk_accelerator_set_default_mod_mask (GDK_SHIFT_MASK |
10990                                         GDK_CONTROL_MASK |
10991                                         GDK_MOD1_MASK | 
10992                                         GDK_META_MASK |
10993                                         GDK_SUPER_MASK |
10994                                         GDK_HYPER_MASK |
10995                                         GDK_MOD4_MASK);
10996   /*  benchmarking
10997    */
10998   for (i = 1; i < argc; i++)
10999     {
11000       if (strncmp (argv[i], "--bench", strlen("--bench")) == 0)
11001         {
11002           int num = 1;
11003           char *nextarg;
11004           char *what;
11005           char *count;
11006           
11007           nextarg = strchr (argv[i], '=');
11008           if (nextarg)
11009             nextarg++;
11010           else
11011             {
11012               i++;
11013               if (i == argc)
11014                 usage ();
11015               nextarg = argv[i];
11016             }
11017
11018           count = strchr (nextarg, ':');
11019           if (count)
11020             {
11021               what = g_strndup (nextarg, count - nextarg);
11022               count++;
11023               num = atoi (count);
11024               if (num <= 0)
11025                 usage ();
11026             }
11027           else
11028             what = g_strdup (nextarg);
11029
11030           do_bench (what, num ? num : 1);
11031           done_benchmarks = TRUE;
11032         }
11033       else
11034         usage ();
11035     }
11036   if (done_benchmarks)
11037     return 0;
11038
11039   /* bindings test
11040    */
11041   binding_set = gtk_binding_set_by_class (g_type_class_ref (GTK_TYPE_WIDGET));
11042   gtk_binding_entry_add_signal (binding_set,
11043                                 '9', GDK_CONTROL_MASK | GDK_RELEASE_MASK,
11044                                 "debug_msg",
11045                                 1,
11046                                 G_TYPE_STRING, "GtkWidgetClass <ctrl><release>9 test");
11047   
11048   /* We use gtk_rc_parse_string() here so we can make sure it works across theme
11049    * changes
11050    */
11051
11052   gtk_rc_parse_string ("style \"testgtk-version-label\" { "
11053                        "   fg[NORMAL] = \"#ff0000\"\n"
11054                        "   font = \"Sans 18\"\n"
11055                        "}\n"
11056                        "widget \"*.testgtk-version-label\" style \"testgtk-version-label\"");
11057   
11058   create_main_window ();
11059
11060   gtk_main ();
11061
11062   if (1)
11063     {
11064       while (g_main_context_pending (NULL))
11065         g_main_context_iteration (NULL, FALSE);
11066 #if 0
11067       sleep (1);
11068       while (g_main_context_pending (NULL))
11069         g_main_context_iteration (NULL, FALSE);
11070 #endif
11071     }
11072   return 0;
11073 }