]> Pileus Git - ~andy/gtk/blob - tests/testgtk.c
88c6ef1bd5825742385fa1da59bdb05b24ea74ee
[~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   GtkWidget *combo;
6208   GtkWidget *entry;
6209   GtkWidget *radio_dpy;
6210   GtkWidget *toplevel;
6211   GtkWidget *dialog_window;
6212 } ScreenDisplaySelection;
6213
6214 static void
6215 screen_display_check (GtkWidget *widget, ScreenDisplaySelection *data)
6216 {
6217   const gchar *display_name;
6218   GdkDisplay *display = gtk_widget_get_display (widget);
6219   GtkWidget *dialog;
6220   GdkScreen *new_screen = NULL;
6221   GdkScreen *current_screen = gtk_widget_get_screen (widget);
6222   
6223   if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (data->radio_dpy)))
6224     {
6225       display_name = gtk_entry_get_text (GTK_ENTRY (data->entry));
6226       display = gdk_display_open (display_name);
6227       
6228       if (!display)
6229         {
6230           dialog = gtk_message_dialog_new (GTK_WINDOW (gtk_widget_get_toplevel (widget)),
6231                                            GTK_DIALOG_DESTROY_WITH_PARENT,
6232                                            GTK_MESSAGE_ERROR,
6233                                            GTK_BUTTONS_OK,
6234                                            "The display :\n%s\ncannot be opened",
6235                                            display_name);
6236           gtk_window_set_screen (GTK_WINDOW (dialog), current_screen);
6237           gtk_widget_show (dialog);
6238           g_signal_connect (dialog, "response",
6239                             G_CALLBACK (gtk_widget_destroy),
6240                             NULL);
6241         }
6242       else
6243         {
6244           GtkTreeModel *model = gtk_combo_box_get_model (GTK_COMBO_BOX (data->combo));
6245           gint i = 0;
6246           GtkTreeIter iter;
6247           gboolean found = FALSE;
6248           while (gtk_tree_model_iter_nth_child (model, &iter, NULL, i++))
6249             {
6250               gchar *name;
6251               gtk_tree_model_get (model, &iter, 0, &name, -1);
6252               found = !g_ascii_strcasecmp (display_name, name);
6253               g_free (name);
6254
6255               if (found)
6256                 break;
6257             }
6258           if (!found)
6259             gtk_combo_box_append_text (GTK_COMBO_BOX (data->combo), display_name);
6260           new_screen = gdk_display_get_default_screen (display);
6261         }
6262     }
6263   else
6264     {
6265       gint number_of_screens = gdk_display_get_n_screens (display);
6266       gint screen_num = gdk_screen_get_number (current_screen);
6267       if ((screen_num +1) < number_of_screens)
6268         new_screen = gdk_display_get_screen (display, screen_num + 1);
6269       else
6270         new_screen = gdk_display_get_screen (display, 0);
6271     }
6272   
6273   if (new_screen) 
6274     {
6275       gtk_window_set_screen (GTK_WINDOW (data->toplevel), new_screen);
6276       gtk_widget_destroy (data->dialog_window);
6277     }
6278 }
6279
6280 void
6281 screen_display_destroy_diag (GtkWidget *widget, GtkWidget *data)
6282 {
6283   gtk_widget_destroy (data);
6284 }
6285
6286 void
6287 create_display_screen (GtkWidget *widget)
6288 {
6289   GtkWidget *table, *frame, *window, *combo_dpy, *vbox;
6290   GtkWidget *radio_dpy, *radio_scr, *applyb, *cancelb;
6291   GtkWidget *bbox;
6292   ScreenDisplaySelection *scr_dpy_data;
6293   GdkScreen *screen = gtk_widget_get_screen (widget);
6294   GdkDisplay *display = gdk_screen_get_display (screen);
6295
6296   window = g_object_new (gtk_window_get_type (),
6297                            "screen", screen,
6298                            "user_data", NULL,
6299                            "type", GTK_WINDOW_TOPLEVEL,
6300                            "title",
6301                            "Screen or Display selection",
6302                            "border_width", 10, NULL);
6303   g_signal_connect (window, "destroy", 
6304                     G_CALLBACK (gtk_widget_destroy), NULL);
6305
6306   vbox = gtk_vbox_new (FALSE, 3);
6307   gtk_container_add (GTK_CONTAINER (window), vbox);
6308   
6309   frame = gtk_frame_new ("Select screen or display");
6310   gtk_container_add (GTK_CONTAINER (vbox), frame);
6311   
6312   table = gtk_table_new (2, 2, TRUE);
6313   gtk_table_set_row_spacings (GTK_TABLE (table), 3);
6314   gtk_table_set_col_spacings (GTK_TABLE (table), 3);
6315
6316   gtk_container_add (GTK_CONTAINER (frame), table);
6317
6318   radio_dpy = gtk_radio_button_new_with_label (NULL, "move to another X display");
6319   if (gdk_display_get_n_screens(display) > 1)
6320     radio_scr = gtk_radio_button_new_with_label 
6321     (gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio_dpy)), "move to next screen");
6322   else
6323     {    
6324       radio_scr = gtk_radio_button_new_with_label 
6325         (gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio_dpy)), 
6326          "only one screen on the current display");
6327       gtk_widget_set_sensitive (radio_scr, FALSE);
6328     }
6329   combo_dpy = gtk_combo_box_new_text ();
6330   gtk_combo_box_append_text (GTK_COMBO_BOX (combo_dpy), "diabolo:0.0");
6331   gtk_entry_set_text (GTK_ENTRY (gtk_bin_get_child (GTK_BIN (combo_dpy))),
6332                       "<hostname>:<X Server Num>.<Screen Num>");
6333
6334   gtk_table_attach_defaults (GTK_TABLE (table), radio_dpy, 0, 1, 0, 1);
6335   gtk_table_attach_defaults (GTK_TABLE (table), radio_scr, 0, 1, 1, 2);
6336   gtk_table_attach_defaults (GTK_TABLE (table), combo_dpy, 1, 2, 0, 1);
6337
6338   bbox = gtk_hbutton_box_new ();
6339   applyb = gtk_button_new_from_stock (GTK_STOCK_APPLY);
6340   cancelb = gtk_button_new_from_stock (GTK_STOCK_CANCEL);
6341   
6342   gtk_container_add (GTK_CONTAINER (vbox), bbox);
6343
6344   gtk_container_add (GTK_CONTAINER (bbox), applyb);
6345   gtk_container_add (GTK_CONTAINER (bbox), cancelb);
6346
6347   scr_dpy_data = g_new0 (ScreenDisplaySelection, 1);
6348
6349   scr_dpy_data->entry = gtk_bin_get_child (GTK_BIN (combo_dpy));
6350   scr_dpy_data->radio_dpy = radio_dpy;
6351   scr_dpy_data->toplevel = gtk_widget_get_toplevel (widget);
6352   scr_dpy_data->dialog_window = window;
6353
6354   g_signal_connect (cancelb, "clicked", 
6355                     G_CALLBACK (screen_display_destroy_diag), window);
6356   g_signal_connect (applyb, "clicked", 
6357                     G_CALLBACK (screen_display_check), scr_dpy_data);
6358   gtk_widget_show_all (window);
6359 }
6360
6361 /* Event Watcher
6362  */
6363 static gboolean event_watcher_enter_id = 0;
6364 static gboolean event_watcher_leave_id = 0;
6365
6366 static gboolean
6367 event_watcher (GSignalInvocationHint *ihint,
6368                guint                  n_param_values,
6369                const GValue          *param_values,
6370                gpointer               data)
6371 {
6372   g_print ("Watch: \"%s\" emitted for %s\n",
6373            g_signal_name (ihint->signal_id),
6374            G_OBJECT_TYPE_NAME (g_value_get_object (param_values + 0)));
6375
6376   return TRUE;
6377 }
6378
6379 static void
6380 event_watcher_down (void)
6381 {
6382   if (event_watcher_enter_id)
6383     {
6384       guint signal_id;
6385
6386       signal_id = g_signal_lookup ("enter_notify_event", GTK_TYPE_WIDGET);
6387       g_signal_remove_emission_hook (signal_id, event_watcher_enter_id);
6388       event_watcher_enter_id = 0;
6389       signal_id = g_signal_lookup ("leave_notify_event", GTK_TYPE_WIDGET);
6390       g_signal_remove_emission_hook (signal_id, event_watcher_leave_id);
6391       event_watcher_leave_id = 0;
6392     }
6393 }
6394
6395 static void
6396 event_watcher_toggle (void)
6397 {
6398   if (event_watcher_enter_id)
6399     event_watcher_down ();
6400   else
6401     {
6402       guint signal_id;
6403
6404       signal_id = g_signal_lookup ("enter_notify_event", GTK_TYPE_WIDGET);
6405       event_watcher_enter_id = g_signal_add_emission_hook (signal_id, 0, event_watcher, NULL, NULL);
6406       signal_id = g_signal_lookup ("leave_notify_event", GTK_TYPE_WIDGET);
6407       event_watcher_leave_id = g_signal_add_emission_hook (signal_id, 0, event_watcher, NULL, NULL);
6408     }
6409 }
6410
6411 static void
6412 create_event_watcher (GtkWidget *widget)
6413 {
6414   GtkWidget *button;
6415
6416   if (!dialog_window)
6417     {
6418       dialog_window = gtk_dialog_new ();
6419       gtk_window_set_screen (GTK_WINDOW (dialog_window),
6420                              gtk_widget_get_screen (widget));
6421
6422       g_signal_connect (dialog_window, "destroy",
6423                         G_CALLBACK (gtk_widget_destroyed),
6424                         &dialog_window);
6425       g_signal_connect (dialog_window, "destroy",
6426                         G_CALLBACK (event_watcher_down),
6427                         NULL);
6428
6429       gtk_window_set_title (GTK_WINDOW (dialog_window), "Event Watcher");
6430       gtk_container_set_border_width (GTK_CONTAINER (dialog_window), 0);
6431       gtk_widget_set_size_request (dialog_window, 200, 110);
6432
6433       button = gtk_toggle_button_new_with_label ("Activate Watch");
6434       g_signal_connect (button, "clicked",
6435                         G_CALLBACK (event_watcher_toggle),
6436                         NULL);
6437       gtk_container_set_border_width (GTK_CONTAINER (button), 10);
6438       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog_window)->vbox), 
6439                           button, TRUE, TRUE, 0);
6440       gtk_widget_show (button);
6441
6442       button = gtk_button_new_with_label ("Close");
6443       g_signal_connect_swapped (button, "clicked",
6444                                 G_CALLBACK (gtk_widget_destroy),
6445                                 dialog_window);
6446       gtk_widget_set_can_default (button, TRUE);
6447       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog_window)->action_area),
6448                           button, TRUE, TRUE, 0);
6449       gtk_widget_grab_default (button);
6450       gtk_widget_show (button);
6451     }
6452
6453   if (!gtk_widget_get_visible (dialog_window))
6454     gtk_widget_show (dialog_window);
6455   else
6456     gtk_widget_destroy (dialog_window);
6457 }
6458
6459 /*
6460  * GtkRange
6461  */
6462
6463 static gchar*
6464 reformat_value (GtkScale *scale,
6465                 gdouble   value)
6466 {
6467   return g_strdup_printf ("-->%0.*g<--",
6468                           gtk_scale_get_digits (scale), value);
6469 }
6470
6471 static void
6472 create_range_controls (GtkWidget *widget)
6473 {
6474   static GtkWidget *window = NULL;
6475   GtkWidget *box1;
6476   GtkWidget *box2;
6477   GtkWidget *button;
6478   GtkWidget *scrollbar;
6479   GtkWidget *scale;
6480   GtkWidget *separator;
6481   GtkObject *adjustment;
6482   GtkWidget *hbox;
6483
6484   if (!window)
6485     {
6486       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6487
6488       gtk_window_set_screen (GTK_WINDOW (window),
6489                              gtk_widget_get_screen (widget));
6490
6491       g_signal_connect (window, "destroy",
6492                         G_CALLBACK (gtk_widget_destroyed),
6493                         &window);
6494
6495       gtk_window_set_title (GTK_WINDOW (window), "range controls");
6496       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
6497
6498
6499       box1 = gtk_vbox_new (FALSE, 0);
6500       gtk_container_add (GTK_CONTAINER (window), box1);
6501       gtk_widget_show (box1);
6502
6503
6504       box2 = gtk_vbox_new (FALSE, 10);
6505       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
6506       gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
6507       gtk_widget_show (box2);
6508
6509
6510       adjustment = gtk_adjustment_new (0.0, 0.0, 101.0, 0.1, 1.0, 1.0);
6511
6512       scale = gtk_hscale_new (GTK_ADJUSTMENT (adjustment));
6513       gtk_widget_set_size_request (GTK_WIDGET (scale), 150, -1);
6514       gtk_range_set_update_policy (GTK_RANGE (scale), GTK_UPDATE_DELAYED);
6515       gtk_scale_set_digits (GTK_SCALE (scale), 1);
6516       gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE);
6517       gtk_box_pack_start (GTK_BOX (box2), scale, TRUE, TRUE, 0);
6518       gtk_widget_show (scale);
6519
6520       scrollbar = gtk_hscrollbar_new (GTK_ADJUSTMENT (adjustment));
6521       gtk_range_set_update_policy (GTK_RANGE (scrollbar), 
6522                                    GTK_UPDATE_CONTINUOUS);
6523       gtk_box_pack_start (GTK_BOX (box2), scrollbar, TRUE, TRUE, 0);
6524       gtk_widget_show (scrollbar);
6525
6526       scale = gtk_hscale_new (GTK_ADJUSTMENT (adjustment));
6527       gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE);
6528       g_signal_connect (scale,
6529                         "format_value",
6530                         G_CALLBACK (reformat_value),
6531                         NULL);
6532       gtk_box_pack_start (GTK_BOX (box2), scale, TRUE, TRUE, 0);
6533       gtk_widget_show (scale);
6534       
6535       hbox = gtk_hbox_new (FALSE, 0);
6536
6537       scale = gtk_vscale_new (GTK_ADJUSTMENT (adjustment));
6538       gtk_widget_set_size_request (scale, -1, 200);
6539       gtk_scale_set_digits (GTK_SCALE (scale), 2);
6540       gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE);
6541       gtk_box_pack_start (GTK_BOX (hbox), scale, TRUE, TRUE, 0);
6542       gtk_widget_show (scale);
6543
6544       scale = gtk_vscale_new (GTK_ADJUSTMENT (adjustment));
6545       gtk_widget_set_size_request (scale, -1, 200);
6546       gtk_scale_set_digits (GTK_SCALE (scale), 2);
6547       gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE);
6548       gtk_range_set_inverted (GTK_RANGE (scale), TRUE);
6549       gtk_box_pack_start (GTK_BOX (hbox), scale, TRUE, TRUE, 0);
6550       gtk_widget_show (scale);
6551
6552       scale = gtk_vscale_new (GTK_ADJUSTMENT (adjustment));
6553       gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE);
6554       g_signal_connect (scale,
6555                         "format_value",
6556                         G_CALLBACK (reformat_value),
6557                         NULL);
6558       gtk_box_pack_start (GTK_BOX (hbox), scale, TRUE, TRUE, 0);
6559       gtk_widget_show (scale);
6560
6561       
6562       gtk_box_pack_start (GTK_BOX (box2), hbox, TRUE, TRUE, 0);
6563       gtk_widget_show (hbox);
6564       
6565       separator = gtk_hseparator_new ();
6566       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
6567       gtk_widget_show (separator);
6568
6569
6570       box2 = gtk_vbox_new (FALSE, 10);
6571       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
6572       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
6573       gtk_widget_show (box2);
6574
6575
6576       button = gtk_button_new_with_label ("close");
6577       g_signal_connect_swapped (button, "clicked",
6578                                 G_CALLBACK (gtk_widget_destroy),
6579                                 window);
6580       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
6581       gtk_widget_set_can_default (button, TRUE);
6582       gtk_widget_grab_default (button);
6583       gtk_widget_show (button);
6584     }
6585
6586   if (!gtk_widget_get_visible (window))
6587     gtk_widget_show (window);
6588   else
6589     gtk_widget_destroy (window);
6590 }
6591
6592 /*
6593  * GtkRulers
6594  */
6595
6596 void
6597 create_rulers (GtkWidget *widget)
6598 {
6599   static GtkWidget *window = NULL;
6600   GtkWidget *table;
6601   GtkWidget *ruler;
6602
6603   if (!window)
6604     {
6605       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6606
6607       gtk_window_set_screen (GTK_WINDOW (window),
6608                              gtk_widget_get_screen (widget));
6609
6610       g_object_set (window, "allow_shrink", TRUE, "allow_grow", TRUE, NULL);
6611
6612       g_signal_connect (window, "destroy",
6613                         G_CALLBACK (gtk_widget_destroyed),
6614                         &window);
6615
6616       gtk_window_set_title (GTK_WINDOW (window), "rulers");
6617       gtk_widget_set_size_request (window, 300, 300);
6618       gtk_widget_set_events (window, 
6619                              GDK_POINTER_MOTION_MASK 
6620                              | GDK_POINTER_MOTION_HINT_MASK);
6621       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
6622
6623       table = gtk_table_new (2, 2, FALSE);
6624       gtk_container_add (GTK_CONTAINER (window), table);
6625       gtk_widget_show (table);
6626
6627       ruler = gtk_hruler_new ();
6628       gtk_ruler_set_metric (GTK_RULER (ruler), GTK_CENTIMETERS);
6629       gtk_ruler_set_range (GTK_RULER (ruler), 100, 0, 0, 20);
6630
6631       g_signal_connect_swapped (window, 
6632                                 "motion_notify_event",
6633                                 G_CALLBACK (GTK_WIDGET_GET_CLASS (ruler)->motion_notify_event),
6634                                 ruler);
6635       
6636       gtk_table_attach (GTK_TABLE (table), ruler, 1, 2, 0, 1,
6637                         GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
6638       gtk_widget_show (ruler);
6639
6640
6641       ruler = gtk_vruler_new ();
6642       gtk_ruler_set_range (GTK_RULER (ruler), 5, 15, 0, 20);
6643
6644       g_signal_connect_swapped (window, 
6645                                 "motion_notify_event",
6646                                 G_CALLBACK (GTK_WIDGET_GET_CLASS (ruler)->motion_notify_event),
6647                                 ruler);
6648       
6649       gtk_table_attach (GTK_TABLE (table), ruler, 0, 1, 1, 2,
6650                         GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
6651       gtk_widget_show (ruler);
6652     }
6653
6654   if (!gtk_widget_get_visible (window))
6655     gtk_widget_show (window);
6656   else
6657     gtk_widget_destroy (window);
6658 }
6659
6660 static void
6661 text_toggle_editable (GtkWidget *checkbutton,
6662                        GtkWidget *text)
6663 {
6664    gtk_text_set_editable(GTK_TEXT(text),
6665                           GTK_TOGGLE_BUTTON(checkbutton)->active);
6666 }
6667
6668 static void
6669 text_toggle_word_wrap (GtkWidget *checkbutton,
6670                        GtkWidget *text)
6671 {
6672    gtk_text_set_word_wrap(GTK_TEXT(text),
6673                           GTK_TOGGLE_BUTTON(checkbutton)->active);
6674 }
6675
6676 struct {
6677   GdkColor color;
6678   gchar *name;
6679 } text_colors[] = {
6680  { { 0, 0x0000, 0x0000, 0x0000 }, "black" },
6681  { { 0, 0xFFFF, 0xFFFF, 0xFFFF }, "white" },
6682  { { 0, 0xFFFF, 0x0000, 0x0000 }, "red" },
6683  { { 0, 0x0000, 0xFFFF, 0x0000 }, "green" },
6684  { { 0, 0x0000, 0x0000, 0xFFFF }, "blue" }, 
6685  { { 0, 0x0000, 0xFFFF, 0xFFFF }, "cyan" },
6686  { { 0, 0xFFFF, 0x0000, 0xFFFF }, "magenta" },
6687  { { 0, 0xFFFF, 0xFFFF, 0x0000 }, "yellow" }
6688 };
6689
6690 int ntext_colors = sizeof(text_colors) / sizeof(text_colors[0]);
6691
6692 /*
6693  * GtkNotebook
6694  */
6695
6696 GdkPixbuf *book_open;
6697 GdkPixbuf *book_closed;
6698 GtkWidget *sample_notebook;
6699
6700 static void
6701 set_page_image (GtkNotebook *notebook, gint page_num, GdkPixbuf *pixbuf)
6702 {
6703   GtkWidget *page_widget;
6704   GtkWidget *pixwid;
6705
6706   page_widget = gtk_notebook_get_nth_page (notebook, page_num);
6707
6708   pixwid = g_object_get_data (G_OBJECT (page_widget), "tab_pixmap");
6709   gtk_image_set_from_pixbuf (GTK_IMAGE (pixwid), pixbuf);
6710   
6711   pixwid = g_object_get_data (G_OBJECT (page_widget), "menu_pixmap");
6712   gtk_image_set_from_pixbuf (GTK_IMAGE (pixwid), pixbuf);
6713 }
6714
6715 static void
6716 page_switch (GtkWidget *widget, GtkNotebookPage *page, gint page_num)
6717 {
6718   GtkNotebook *notebook = GTK_NOTEBOOK (widget);
6719   gint old_page_num = gtk_notebook_get_current_page (notebook);
6720  
6721   if (page_num == old_page_num)
6722     return;
6723
6724   set_page_image (notebook, page_num, book_open);
6725
6726   if (old_page_num != -1)
6727     set_page_image (notebook, old_page_num, book_closed);
6728 }
6729
6730 static void
6731 tab_fill (GtkToggleButton *button, GtkWidget *child)
6732 {
6733   gboolean expand;
6734   GtkPackType pack_type;
6735
6736   gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (sample_notebook), child,
6737                                         &expand, NULL, &pack_type);
6738   gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (sample_notebook), child,
6739                                       expand, button->active, pack_type);
6740 }
6741
6742 static void
6743 tab_expand (GtkToggleButton *button, GtkWidget *child)
6744 {
6745   gboolean fill;
6746   GtkPackType pack_type;
6747
6748   gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (sample_notebook), child,
6749                                         NULL, &fill, &pack_type);
6750   gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (sample_notebook), child,
6751                                       button->active, fill, pack_type);
6752 }
6753
6754 static void
6755 tab_pack (GtkToggleButton *button, GtkWidget *child)
6756           
6757
6758   gboolean expand;
6759   gboolean fill;
6760
6761   gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (sample_notebook), child,
6762                                         &expand, &fill, NULL);
6763   gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (sample_notebook), child,
6764                                       expand, fill, button->active);
6765 }
6766
6767 static void
6768 create_pages (GtkNotebook *notebook, gint start, gint end)
6769 {
6770   GtkWidget *child = NULL;
6771   GtkWidget *button;
6772   GtkWidget *label;
6773   GtkWidget *hbox;
6774   GtkWidget *vbox;
6775   GtkWidget *label_box;
6776   GtkWidget *menu_box;
6777   GtkWidget *pixwid;
6778   gint i;
6779   char buffer[32];
6780   char accel_buffer[32];
6781
6782   for (i = start; i <= end; i++)
6783     {
6784       sprintf (buffer, "Page %d", i);
6785       sprintf (accel_buffer, "Page _%d", i);
6786
6787       child = gtk_frame_new (buffer);
6788       gtk_container_set_border_width (GTK_CONTAINER (child), 10);
6789
6790       vbox = gtk_vbox_new (TRUE,0);
6791       gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
6792       gtk_container_add (GTK_CONTAINER (child), vbox);
6793
6794       hbox = gtk_hbox_new (TRUE,0);
6795       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 5);
6796
6797       button = gtk_check_button_new_with_label ("Fill Tab");
6798       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
6799       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
6800       g_signal_connect (button, "toggled",
6801                         G_CALLBACK (tab_fill), child);
6802
6803       button = gtk_check_button_new_with_label ("Expand Tab");
6804       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
6805       g_signal_connect (button, "toggled",
6806                         G_CALLBACK (tab_expand), child);
6807
6808       button = gtk_check_button_new_with_label ("Pack end");
6809       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
6810       g_signal_connect (button, "toggled",
6811                         G_CALLBACK (tab_pack), child);
6812
6813       button = gtk_button_new_with_label ("Hide Page");
6814       gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 5);
6815       g_signal_connect_swapped (button, "clicked",
6816                                 G_CALLBACK (gtk_widget_hide),
6817                                 child);
6818
6819       gtk_widget_show_all (child);
6820
6821       label_box = gtk_hbox_new (FALSE, 0);
6822       pixwid = gtk_image_new_from_pixbuf (book_closed);
6823       g_object_set_data (G_OBJECT (child), "tab_pixmap", pixwid);
6824                            
6825       gtk_box_pack_start (GTK_BOX (label_box), pixwid, FALSE, TRUE, 0);
6826       gtk_misc_set_padding (GTK_MISC (pixwid), 3, 1);
6827       label = gtk_label_new_with_mnemonic (accel_buffer);
6828       gtk_box_pack_start (GTK_BOX (label_box), label, FALSE, TRUE, 0);
6829       gtk_widget_show_all (label_box);
6830       
6831                                        
6832       menu_box = gtk_hbox_new (FALSE, 0);
6833       pixwid = gtk_image_new_from_pixbuf (book_closed);
6834       g_object_set_data (G_OBJECT (child), "menu_pixmap", pixwid);
6835       
6836       gtk_box_pack_start (GTK_BOX (menu_box), pixwid, FALSE, TRUE, 0);
6837       gtk_misc_set_padding (GTK_MISC (pixwid), 3, 1);
6838       label = gtk_label_new (buffer);
6839       gtk_box_pack_start (GTK_BOX (menu_box), label, FALSE, TRUE, 0);
6840       gtk_widget_show_all (menu_box);
6841
6842       gtk_notebook_append_page_menu (notebook, child, label_box, menu_box);
6843     }
6844 }
6845
6846 static void
6847 rotate_notebook (GtkButton   *button,
6848                  GtkNotebook *notebook)
6849 {
6850   gtk_notebook_set_tab_pos (notebook, (notebook->tab_pos + 1) % 4);
6851 }
6852
6853 static void
6854 show_all_pages (GtkButton   *button,
6855                 GtkNotebook *notebook)
6856 {  
6857   gtk_container_foreach (GTK_CONTAINER (notebook),
6858                          (GtkCallback) gtk_widget_show, NULL);
6859 }
6860
6861 static void
6862 notebook_type_changed (GtkWidget *optionmenu,
6863                        gpointer   data)
6864 {
6865   GtkNotebook *notebook;
6866   gint i, c;
6867
6868   enum {
6869     STANDARD,
6870     NOTABS,
6871     BORDERLESS,
6872     SCROLLABLE
6873   };
6874
6875   notebook = GTK_NOTEBOOK (data);
6876
6877   c = gtk_combo_box_get_active (GTK_COMBO_BOX (optionmenu));
6878
6879   switch (c)
6880     {
6881     case STANDARD:
6882       /* standard notebook */
6883       gtk_notebook_set_show_tabs (notebook, TRUE);
6884       gtk_notebook_set_show_border (notebook, TRUE);
6885       gtk_notebook_set_scrollable (notebook, FALSE);
6886       break;
6887
6888     case NOTABS:
6889       /* notabs notebook */
6890       gtk_notebook_set_show_tabs (notebook, FALSE);
6891       gtk_notebook_set_show_border (notebook, TRUE);
6892       break;
6893
6894     case BORDERLESS:
6895       /* borderless */
6896       gtk_notebook_set_show_tabs (notebook, FALSE);
6897       gtk_notebook_set_show_border (notebook, FALSE);
6898       break;
6899
6900     case SCROLLABLE:  
6901       /* scrollable */
6902       gtk_notebook_set_show_tabs (notebook, TRUE);
6903       gtk_notebook_set_show_border (notebook, TRUE);
6904       gtk_notebook_set_scrollable (notebook, TRUE);
6905       if (g_list_length (notebook->children) == 5)
6906         create_pages (notebook, 6, 15);
6907       
6908       return;
6909       break;
6910     }
6911   
6912   if (g_list_length (notebook->children) == 15)
6913     for (i = 0; i < 10; i++)
6914       gtk_notebook_remove_page (notebook, 5);
6915 }
6916
6917 static void
6918 notebook_popup (GtkToggleButton *button,
6919                 GtkNotebook     *notebook)
6920 {
6921   if (button->active)
6922     gtk_notebook_popup_enable (notebook);
6923   else
6924     gtk_notebook_popup_disable (notebook);
6925 }
6926
6927 static void
6928 notebook_homogeneous (GtkToggleButton *button,
6929                       GtkNotebook     *notebook)
6930 {
6931   g_object_set (notebook, "homogeneous", button->active, NULL);
6932 }
6933
6934 static void
6935 create_notebook (GtkWidget *widget)
6936 {
6937   static GtkWidget *window = NULL;
6938   GtkWidget *box1;
6939   GtkWidget *box2;
6940   GtkWidget *button;
6941   GtkWidget *separator;
6942   GtkWidget *omenu;
6943   GtkWidget *label;
6944   GdkPixbuf *book_open_xpm;
6945   GdkPixbuf *book_closed_xpm;
6946
6947   static gchar *items[] =
6948   {
6949     "Standard",
6950     "No tabs",
6951     "Borderless",
6952     "Scrollable"
6953   };
6954   
6955   if (!window)
6956     {
6957       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6958       gtk_window_set_screen (GTK_WINDOW (window),
6959                              gtk_widget_get_screen (widget));
6960
6961       g_signal_connect (window, "destroy",
6962                         G_CALLBACK (gtk_widget_destroyed),
6963                         &window);
6964
6965       gtk_window_set_title (GTK_WINDOW (window), "notebook");
6966       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
6967
6968       box1 = gtk_vbox_new (FALSE, 0);
6969       gtk_container_add (GTK_CONTAINER (window), box1);
6970
6971       sample_notebook = gtk_notebook_new ();
6972       g_signal_connect (sample_notebook, "switch_page",
6973                         G_CALLBACK (page_switch), NULL);
6974       gtk_notebook_set_tab_pos (GTK_NOTEBOOK (sample_notebook), GTK_POS_TOP);
6975       gtk_box_pack_start (GTK_BOX (box1), sample_notebook, TRUE, TRUE, 0);
6976       gtk_container_set_border_width (GTK_CONTAINER (sample_notebook), 10);
6977
6978       gtk_widget_realize (sample_notebook);
6979
6980       if (!book_open)
6981         book_open = gdk_pixbuf_new_from_xpm_data ((const char **)book_open_xpm);
6982                                                   
6983       if (!book_closed)
6984         book_closed = gdk_pixbuf_new_from_xpm_data ((const char **)book_closed_xpm);
6985
6986       create_pages (GTK_NOTEBOOK (sample_notebook), 1, 5);
6987
6988       separator = gtk_hseparator_new ();
6989       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 10);
6990       
6991       box2 = gtk_hbox_new (FALSE, 5);
6992       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
6993       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
6994
6995       button = gtk_check_button_new_with_label ("popup menu");
6996       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, FALSE, 0);
6997       g_signal_connect (button, "clicked",
6998                         G_CALLBACK (notebook_popup),
6999                         sample_notebook);
7000
7001       button = gtk_check_button_new_with_label ("homogeneous tabs");
7002       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, FALSE, 0);
7003       g_signal_connect (button, "clicked",
7004                         G_CALLBACK (notebook_homogeneous),
7005                         sample_notebook);
7006
7007       box2 = gtk_hbox_new (FALSE, 5);
7008       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
7009       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
7010
7011       label = gtk_label_new ("Notebook Style :");
7012       gtk_box_pack_start (GTK_BOX (box2), label, FALSE, TRUE, 0);
7013
7014       omenu = build_option_menu (items, G_N_ELEMENTS (items), 0,
7015                                  notebook_type_changed,
7016                                  sample_notebook);
7017       gtk_box_pack_start (GTK_BOX (box2), omenu, FALSE, TRUE, 0);
7018
7019       button = gtk_button_new_with_label ("Show all Pages");
7020       gtk_box_pack_start (GTK_BOX (box2), button, FALSE, TRUE, 0);
7021       g_signal_connect (button, "clicked",
7022                         G_CALLBACK (show_all_pages), sample_notebook);
7023
7024       box2 = gtk_hbox_new (TRUE, 10);
7025       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
7026       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
7027
7028       button = gtk_button_new_with_label ("prev");
7029       g_signal_connect_swapped (button, "clicked",
7030                                 G_CALLBACK (gtk_notebook_prev_page),
7031                                 sample_notebook);
7032       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
7033
7034       button = gtk_button_new_with_label ("next");
7035       g_signal_connect_swapped (button, "clicked",
7036                                 G_CALLBACK (gtk_notebook_next_page),
7037                                 sample_notebook);
7038       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
7039
7040       button = gtk_button_new_with_label ("rotate");
7041       g_signal_connect (button, "clicked",
7042                         G_CALLBACK (rotate_notebook), sample_notebook);
7043       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
7044
7045       separator = gtk_hseparator_new ();
7046       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
7047
7048       button = gtk_button_new_with_label ("close");
7049       gtk_container_set_border_width (GTK_CONTAINER (button), 5);
7050       g_signal_connect_swapped (button, "clicked",
7051                                 G_CALLBACK (gtk_widget_destroy),
7052                                 window);
7053       gtk_box_pack_start (GTK_BOX (box1), button, FALSE, FALSE, 0);
7054       gtk_widget_set_can_default (button, TRUE);
7055       gtk_widget_grab_default (button);
7056     }
7057
7058   if (!gtk_widget_get_visible (window))
7059     gtk_widget_show_all (window);
7060   else
7061     gtk_widget_destroy (window);
7062 }
7063
7064 /*
7065  * GtkPanes
7066  */
7067
7068 void
7069 toggle_resize (GtkWidget *widget, GtkWidget *child)
7070 {
7071   GtkContainer *container = GTK_CONTAINER (gtk_widget_get_parent (child));
7072   GValue value = { 0, };
7073   g_value_init (&value, G_TYPE_BOOLEAN);
7074   gtk_container_child_get_property (container, child, "resize", &value);
7075   g_value_set_boolean (&value, !g_value_get_boolean (&value));
7076   gtk_container_child_set_property (container, child, "resize", &value);
7077 }
7078
7079 void
7080 toggle_shrink (GtkWidget *widget, GtkWidget *child)
7081 {
7082   GtkContainer *container = GTK_CONTAINER (gtk_widget_get_parent (child));
7083   GValue value = { 0, };
7084   g_value_init (&value, G_TYPE_BOOLEAN);
7085   gtk_container_child_get_property (container, child, "shrink", &value);
7086   g_value_set_boolean (&value, !g_value_get_boolean (&value));
7087   gtk_container_child_set_property (container, child, "shrink", &value);
7088 }
7089
7090 static void
7091 paned_props_clicked (GtkWidget *button,
7092                      GObject   *paned)
7093 {
7094   GtkWidget *window = create_prop_editor (paned, GTK_TYPE_PANED);
7095   
7096   gtk_window_set_title (GTK_WINDOW (window), "Paned Properties");
7097 }
7098
7099 GtkWidget *
7100 create_pane_options (GtkPaned    *paned,
7101                      const gchar *frame_label,
7102                      const gchar *label1,
7103                      const gchar *label2)
7104 {
7105   GtkWidget *frame;
7106   GtkWidget *table;
7107   GtkWidget *label;
7108   GtkWidget *button;
7109   GtkWidget *check_button;
7110   
7111   frame = gtk_frame_new (frame_label);
7112   gtk_container_set_border_width (GTK_CONTAINER (frame), 4);
7113   
7114   table = gtk_table_new (4, 2, 4);
7115   gtk_container_add (GTK_CONTAINER (frame), table);
7116   
7117   label = gtk_label_new (label1);
7118   gtk_table_attach_defaults (GTK_TABLE (table), label,
7119                              0, 1, 0, 1);
7120   
7121   check_button = gtk_check_button_new_with_label ("Resize");
7122   gtk_table_attach_defaults (GTK_TABLE (table), check_button,
7123                              0, 1, 1, 2);
7124   g_signal_connect (check_button, "toggled",
7125                     G_CALLBACK (toggle_resize),
7126                     paned->child1);
7127   
7128   check_button = gtk_check_button_new_with_label ("Shrink");
7129   gtk_table_attach_defaults (GTK_TABLE (table), check_button,
7130                              0, 1, 2, 3);
7131   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button),
7132                                TRUE);
7133   g_signal_connect (check_button, "toggled",
7134                     G_CALLBACK (toggle_shrink),
7135                     paned->child1);
7136   
7137   label = gtk_label_new (label2);
7138   gtk_table_attach_defaults (GTK_TABLE (table), label,
7139                              1, 2, 0, 1);
7140   
7141   check_button = gtk_check_button_new_with_label ("Resize");
7142   gtk_table_attach_defaults (GTK_TABLE (table), check_button,
7143                              1, 2, 1, 2);
7144   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button),
7145                                TRUE);
7146   g_signal_connect (check_button, "toggled",
7147                     G_CALLBACK (toggle_resize),
7148                     paned->child2);
7149   
7150   check_button = gtk_check_button_new_with_label ("Shrink");
7151   gtk_table_attach_defaults (GTK_TABLE (table), check_button,
7152                              1, 2, 2, 3);
7153   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button),
7154                                TRUE);
7155   g_signal_connect (check_button, "toggled",
7156                     G_CALLBACK (toggle_shrink),
7157                     paned->child2);
7158
7159   button = gtk_button_new_with_mnemonic ("_Properties");
7160   gtk_table_attach_defaults (GTK_TABLE (table), button,
7161                              0, 2, 3, 4);
7162   g_signal_connect (button, "clicked",
7163                     G_CALLBACK (paned_props_clicked),
7164                     paned);
7165
7166   return frame;
7167 }
7168
7169 void
7170 create_panes (GtkWidget *widget)
7171 {
7172   static GtkWidget *window = NULL;
7173   GtkWidget *frame;
7174   GtkWidget *hpaned;
7175   GtkWidget *vpaned;
7176   GtkWidget *button;
7177   GtkWidget *vbox;
7178
7179   if (!window)
7180     {
7181       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7182
7183       gtk_window_set_screen (GTK_WINDOW (window),
7184                              gtk_widget_get_screen (widget));
7185       
7186       g_signal_connect (window, "destroy",
7187                         G_CALLBACK (gtk_widget_destroyed),
7188                         &window);
7189
7190       gtk_window_set_title (GTK_WINDOW (window), "Panes");
7191       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
7192
7193       vbox = gtk_vbox_new (FALSE, 0);
7194       gtk_container_add (GTK_CONTAINER (window), vbox);
7195       
7196       vpaned = gtk_vpaned_new ();
7197       gtk_box_pack_start (GTK_BOX (vbox), vpaned, TRUE, TRUE, 0);
7198       gtk_container_set_border_width (GTK_CONTAINER(vpaned), 5);
7199
7200       hpaned = gtk_hpaned_new ();
7201       gtk_paned_add1 (GTK_PANED (vpaned), hpaned);
7202
7203       frame = gtk_frame_new (NULL);
7204       gtk_frame_set_shadow_type (GTK_FRAME(frame), GTK_SHADOW_IN);
7205       gtk_widget_set_size_request (frame, 60, 60);
7206       gtk_paned_add1 (GTK_PANED (hpaned), frame);
7207       
7208       button = gtk_button_new_with_label ("Hi there");
7209       gtk_container_add (GTK_CONTAINER(frame), button);
7210
7211       frame = gtk_frame_new (NULL);
7212       gtk_frame_set_shadow_type (GTK_FRAME(frame), GTK_SHADOW_IN);
7213       gtk_widget_set_size_request (frame, 80, 60);
7214       gtk_paned_add2 (GTK_PANED (hpaned), frame);
7215
7216       frame = gtk_frame_new (NULL);
7217       gtk_frame_set_shadow_type (GTK_FRAME(frame), GTK_SHADOW_IN);
7218       gtk_widget_set_size_request (frame, 60, 80);
7219       gtk_paned_add2 (GTK_PANED (vpaned), frame);
7220
7221       /* Now create toggle buttons to control sizing */
7222
7223       gtk_box_pack_start (GTK_BOX (vbox),
7224                           create_pane_options (GTK_PANED (hpaned),
7225                                                "Horizontal",
7226                                                "Left",
7227                                                "Right"),
7228                           FALSE, FALSE, 0);
7229
7230       gtk_box_pack_start (GTK_BOX (vbox),
7231                           create_pane_options (GTK_PANED (vpaned),
7232                                                "Vertical",
7233                                                "Top",
7234                                                "Bottom"),
7235                           FALSE, FALSE, 0);
7236
7237       gtk_widget_show_all (vbox);
7238     }
7239
7240   if (!gtk_widget_get_visible (window))
7241     gtk_widget_show (window);
7242   else
7243     gtk_widget_destroy (window);
7244 }
7245
7246 /*
7247  * Paned keyboard navigation
7248  */
7249
7250 static GtkWidget*
7251 paned_keyboard_window1 (GtkWidget *widget)
7252 {
7253   GtkWidget *window1;
7254   GtkWidget *hpaned1;
7255   GtkWidget *frame1;
7256   GtkWidget *vbox1;
7257   GtkWidget *button7;
7258   GtkWidget *button8;
7259   GtkWidget *button9;
7260   GtkWidget *vpaned1;
7261   GtkWidget *frame2;
7262   GtkWidget *frame5;
7263   GtkWidget *hbox1;
7264   GtkWidget *button5;
7265   GtkWidget *button6;
7266   GtkWidget *frame3;
7267   GtkWidget *frame4;
7268   GtkWidget *table1;
7269   GtkWidget *button1;
7270   GtkWidget *button2;
7271   GtkWidget *button3;
7272   GtkWidget *button4;
7273
7274   window1 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7275   gtk_window_set_title (GTK_WINDOW (window1), "Basic paned navigation");
7276   gtk_window_set_screen (GTK_WINDOW (window1), 
7277                          gtk_widget_get_screen (widget));
7278
7279   hpaned1 = gtk_hpaned_new ();
7280   gtk_container_add (GTK_CONTAINER (window1), hpaned1);
7281
7282   frame1 = gtk_frame_new (NULL);
7283   gtk_paned_pack1 (GTK_PANED (hpaned1), frame1, FALSE, TRUE);
7284   gtk_frame_set_shadow_type (GTK_FRAME (frame1), GTK_SHADOW_IN);
7285
7286   vbox1 = gtk_vbox_new (FALSE, 0);
7287   gtk_container_add (GTK_CONTAINER (frame1), vbox1);
7288
7289   button7 = gtk_button_new_with_label ("button7");
7290   gtk_box_pack_start (GTK_BOX (vbox1), button7, FALSE, FALSE, 0);
7291
7292   button8 = gtk_button_new_with_label ("button8");
7293   gtk_box_pack_start (GTK_BOX (vbox1), button8, FALSE, FALSE, 0);
7294
7295   button9 = gtk_button_new_with_label ("button9");
7296   gtk_box_pack_start (GTK_BOX (vbox1), button9, FALSE, FALSE, 0);
7297
7298   vpaned1 = gtk_vpaned_new ();
7299   gtk_paned_pack2 (GTK_PANED (hpaned1), vpaned1, TRUE, TRUE);
7300
7301   frame2 = gtk_frame_new (NULL);
7302   gtk_paned_pack1 (GTK_PANED (vpaned1), frame2, FALSE, TRUE);
7303   gtk_frame_set_shadow_type (GTK_FRAME (frame2), GTK_SHADOW_IN);
7304
7305   frame5 = gtk_frame_new (NULL);
7306   gtk_container_add (GTK_CONTAINER (frame2), frame5);
7307
7308   hbox1 = gtk_hbox_new (FALSE, 0);
7309   gtk_container_add (GTK_CONTAINER (frame5), hbox1);
7310
7311   button5 = gtk_button_new_with_label ("button5");
7312   gtk_box_pack_start (GTK_BOX (hbox1), button5, FALSE, FALSE, 0);
7313
7314   button6 = gtk_button_new_with_label ("button6");
7315   gtk_box_pack_start (GTK_BOX (hbox1), button6, FALSE, FALSE, 0);
7316
7317   frame3 = gtk_frame_new (NULL);
7318   gtk_paned_pack2 (GTK_PANED (vpaned1), frame3, TRUE, TRUE);
7319   gtk_frame_set_shadow_type (GTK_FRAME (frame3), GTK_SHADOW_IN);
7320
7321   frame4 = gtk_frame_new ("Buttons");
7322   gtk_container_add (GTK_CONTAINER (frame3), frame4);
7323   gtk_container_set_border_width (GTK_CONTAINER (frame4), 15);
7324
7325   table1 = gtk_table_new (2, 2, FALSE);
7326   gtk_container_add (GTK_CONTAINER (frame4), table1);
7327   gtk_container_set_border_width (GTK_CONTAINER (table1), 11);
7328
7329   button1 = gtk_button_new_with_label ("button1");
7330   gtk_table_attach (GTK_TABLE (table1), button1, 0, 1, 0, 1,
7331                     (GtkAttachOptions) (GTK_FILL),
7332                     (GtkAttachOptions) (0), 0, 0);
7333
7334   button2 = gtk_button_new_with_label ("button2");
7335   gtk_table_attach (GTK_TABLE (table1), button2, 1, 2, 0, 1,
7336                     (GtkAttachOptions) (GTK_FILL),
7337                     (GtkAttachOptions) (0), 0, 0);
7338
7339   button3 = gtk_button_new_with_label ("button3");
7340   gtk_table_attach (GTK_TABLE (table1), button3, 0, 1, 1, 2,
7341                     (GtkAttachOptions) (GTK_FILL),
7342                     (GtkAttachOptions) (0), 0, 0);
7343
7344   button4 = gtk_button_new_with_label ("button4");
7345   gtk_table_attach (GTK_TABLE (table1), button4, 1, 2, 1, 2,
7346                     (GtkAttachOptions) (GTK_FILL),
7347                     (GtkAttachOptions) (0), 0, 0);
7348
7349   return window1;
7350 }
7351
7352 static GtkWidget*
7353 paned_keyboard_window2 (GtkWidget *widget)
7354 {
7355   GtkWidget *window2;
7356   GtkWidget *hpaned2;
7357   GtkWidget *frame6;
7358   GtkWidget *button13;
7359   GtkWidget *hbox2;
7360   GtkWidget *vpaned2;
7361   GtkWidget *frame7;
7362   GtkWidget *button12;
7363   GtkWidget *frame8;
7364   GtkWidget *button11;
7365   GtkWidget *button10;
7366
7367   window2 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7368   gtk_window_set_title (GTK_WINDOW (window2), "\"button 10\" is not inside the horisontal pane");
7369
7370   gtk_window_set_screen (GTK_WINDOW (window2), 
7371                          gtk_widget_get_screen (widget));
7372
7373   hpaned2 = gtk_hpaned_new ();
7374   gtk_container_add (GTK_CONTAINER (window2), hpaned2);
7375
7376   frame6 = gtk_frame_new (NULL);
7377   gtk_paned_pack1 (GTK_PANED (hpaned2), frame6, FALSE, TRUE);
7378   gtk_frame_set_shadow_type (GTK_FRAME (frame6), GTK_SHADOW_IN);
7379
7380   button13 = gtk_button_new_with_label ("button13");
7381   gtk_container_add (GTK_CONTAINER (frame6), button13);
7382
7383   hbox2 = gtk_hbox_new (FALSE, 0);
7384   gtk_paned_pack2 (GTK_PANED (hpaned2), hbox2, TRUE, TRUE);
7385
7386   vpaned2 = gtk_vpaned_new ();
7387   gtk_box_pack_start (GTK_BOX (hbox2), vpaned2, TRUE, TRUE, 0);
7388
7389   frame7 = gtk_frame_new (NULL);
7390   gtk_paned_pack1 (GTK_PANED (vpaned2), frame7, FALSE, TRUE);
7391   gtk_frame_set_shadow_type (GTK_FRAME (frame7), GTK_SHADOW_IN);
7392
7393   button12 = gtk_button_new_with_label ("button12");
7394   gtk_container_add (GTK_CONTAINER (frame7), button12);
7395
7396   frame8 = gtk_frame_new (NULL);
7397   gtk_paned_pack2 (GTK_PANED (vpaned2), frame8, TRUE, TRUE);
7398   gtk_frame_set_shadow_type (GTK_FRAME (frame8), GTK_SHADOW_IN);
7399
7400   button11 = gtk_button_new_with_label ("button11");
7401   gtk_container_add (GTK_CONTAINER (frame8), button11);
7402
7403   button10 = gtk_button_new_with_label ("button10");
7404   gtk_box_pack_start (GTK_BOX (hbox2), button10, FALSE, FALSE, 0);
7405
7406   return window2;
7407 }
7408
7409 static GtkWidget*
7410 paned_keyboard_window3 (GtkWidget *widget)
7411 {
7412   GtkWidget *window3;
7413   GtkWidget *vbox2;
7414   GtkWidget *label1;
7415   GtkWidget *hpaned3;
7416   GtkWidget *frame9;
7417   GtkWidget *button14;
7418   GtkWidget *hpaned4;
7419   GtkWidget *frame10;
7420   GtkWidget *button15;
7421   GtkWidget *hpaned5;
7422   GtkWidget *frame11;
7423   GtkWidget *button16;
7424   GtkWidget *frame12;
7425   GtkWidget *button17;
7426
7427   window3 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7428   g_object_set_data (G_OBJECT (window3), "window3", window3);
7429   gtk_window_set_title (GTK_WINDOW (window3), "Nested panes");
7430
7431   gtk_window_set_screen (GTK_WINDOW (window3), 
7432                          gtk_widget_get_screen (widget));
7433   
7434
7435   vbox2 = gtk_vbox_new (FALSE, 0);
7436   gtk_container_add (GTK_CONTAINER (window3), vbox2);
7437
7438   label1 = gtk_label_new ("Three panes nested inside each other");
7439   gtk_box_pack_start (GTK_BOX (vbox2), label1, FALSE, FALSE, 0);
7440
7441   hpaned3 = gtk_hpaned_new ();
7442   gtk_box_pack_start (GTK_BOX (vbox2), hpaned3, TRUE, TRUE, 0);
7443
7444   frame9 = gtk_frame_new (NULL);
7445   gtk_paned_pack1 (GTK_PANED (hpaned3), frame9, FALSE, TRUE);
7446   gtk_frame_set_shadow_type (GTK_FRAME (frame9), GTK_SHADOW_IN);
7447
7448   button14 = gtk_button_new_with_label ("button14");
7449   gtk_container_add (GTK_CONTAINER (frame9), button14);
7450
7451   hpaned4 = gtk_hpaned_new ();
7452   gtk_paned_pack2 (GTK_PANED (hpaned3), hpaned4, TRUE, TRUE);
7453
7454   frame10 = gtk_frame_new (NULL);
7455   gtk_paned_pack1 (GTK_PANED (hpaned4), frame10, FALSE, TRUE);
7456   gtk_frame_set_shadow_type (GTK_FRAME (frame10), GTK_SHADOW_IN);
7457
7458   button15 = gtk_button_new_with_label ("button15");
7459   gtk_container_add (GTK_CONTAINER (frame10), button15);
7460
7461   hpaned5 = gtk_hpaned_new ();
7462   gtk_paned_pack2 (GTK_PANED (hpaned4), hpaned5, TRUE, TRUE);
7463
7464   frame11 = gtk_frame_new (NULL);
7465   gtk_paned_pack1 (GTK_PANED (hpaned5), frame11, FALSE, TRUE);
7466   gtk_frame_set_shadow_type (GTK_FRAME (frame11), GTK_SHADOW_IN);
7467
7468   button16 = gtk_button_new_with_label ("button16");
7469   gtk_container_add (GTK_CONTAINER (frame11), button16);
7470
7471   frame12 = gtk_frame_new (NULL);
7472   gtk_paned_pack2 (GTK_PANED (hpaned5), frame12, TRUE, TRUE);
7473   gtk_frame_set_shadow_type (GTK_FRAME (frame12), GTK_SHADOW_IN);
7474
7475   button17 = gtk_button_new_with_label ("button17");
7476   gtk_container_add (GTK_CONTAINER (frame12), button17);
7477
7478   return window3;
7479 }
7480
7481 static GtkWidget*
7482 paned_keyboard_window4 (GtkWidget *widget)
7483 {
7484   GtkWidget *window4;
7485   GtkWidget *vbox3;
7486   GtkWidget *label2;
7487   GtkWidget *hpaned6;
7488   GtkWidget *vpaned3;
7489   GtkWidget *button19;
7490   GtkWidget *button18;
7491   GtkWidget *hbox3;
7492   GtkWidget *vpaned4;
7493   GtkWidget *button21;
7494   GtkWidget *button20;
7495   GtkWidget *vpaned5;
7496   GtkWidget *button23;
7497   GtkWidget *button22;
7498   GtkWidget *vpaned6;
7499   GtkWidget *button25;
7500   GtkWidget *button24;
7501
7502   window4 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7503   g_object_set_data (G_OBJECT (window4), "window4", window4);
7504   gtk_window_set_title (GTK_WINDOW (window4), "window4");
7505
7506   gtk_window_set_screen (GTK_WINDOW (window4), 
7507                          gtk_widget_get_screen (widget));
7508
7509   vbox3 = gtk_vbox_new (FALSE, 0);
7510   gtk_container_add (GTK_CONTAINER (window4), vbox3);
7511
7512   label2 = gtk_label_new ("Widget tree:\n\nhpaned \n - vpaned\n - hbox\n    - vpaned\n    - vpaned\n    - vpaned\n");
7513   gtk_box_pack_start (GTK_BOX (vbox3), label2, FALSE, FALSE, 0);
7514   gtk_label_set_justify (GTK_LABEL (label2), GTK_JUSTIFY_LEFT);
7515
7516   hpaned6 = gtk_hpaned_new ();
7517   gtk_box_pack_start (GTK_BOX (vbox3), hpaned6, TRUE, TRUE, 0);
7518
7519   vpaned3 = gtk_vpaned_new ();
7520   gtk_paned_pack1 (GTK_PANED (hpaned6), vpaned3, FALSE, TRUE);
7521
7522   button19 = gtk_button_new_with_label ("button19");
7523   gtk_paned_pack1 (GTK_PANED (vpaned3), button19, FALSE, TRUE);
7524
7525   button18 = gtk_button_new_with_label ("button18");
7526   gtk_paned_pack2 (GTK_PANED (vpaned3), button18, TRUE, TRUE);
7527
7528   hbox3 = gtk_hbox_new (FALSE, 0);
7529   gtk_paned_pack2 (GTK_PANED (hpaned6), hbox3, TRUE, TRUE);
7530
7531   vpaned4 = gtk_vpaned_new ();
7532   gtk_box_pack_start (GTK_BOX (hbox3), vpaned4, TRUE, TRUE, 0);
7533
7534   button21 = gtk_button_new_with_label ("button21");
7535   gtk_paned_pack1 (GTK_PANED (vpaned4), button21, FALSE, TRUE);
7536
7537   button20 = gtk_button_new_with_label ("button20");
7538   gtk_paned_pack2 (GTK_PANED (vpaned4), button20, TRUE, TRUE);
7539
7540   vpaned5 = gtk_vpaned_new ();
7541   gtk_box_pack_start (GTK_BOX (hbox3), vpaned5, TRUE, TRUE, 0);
7542
7543   button23 = gtk_button_new_with_label ("button23");
7544   gtk_paned_pack1 (GTK_PANED (vpaned5), button23, FALSE, TRUE);
7545
7546   button22 = gtk_button_new_with_label ("button22");
7547   gtk_paned_pack2 (GTK_PANED (vpaned5), button22, TRUE, TRUE);
7548
7549   vpaned6 = gtk_vpaned_new ();
7550   gtk_box_pack_start (GTK_BOX (hbox3), vpaned6, TRUE, TRUE, 0);
7551
7552   button25 = gtk_button_new_with_label ("button25");
7553   gtk_paned_pack1 (GTK_PANED (vpaned6), button25, FALSE, TRUE);
7554
7555   button24 = gtk_button_new_with_label ("button24");
7556   gtk_paned_pack2 (GTK_PANED (vpaned6), button24, TRUE, TRUE);
7557
7558   return window4;
7559 }
7560
7561 static void
7562 create_paned_keyboard_navigation (GtkWidget *widget)
7563 {
7564   static GtkWidget *window1 = NULL;
7565   static GtkWidget *window2 = NULL;
7566   static GtkWidget *window3 = NULL;
7567   static GtkWidget *window4 = NULL;
7568
7569   if (window1 && 
7570      (gtk_widget_get_screen (window1) != gtk_widget_get_screen (widget)))
7571     {
7572       gtk_widget_destroy (window1);
7573       gtk_widget_destroy (window2);
7574       gtk_widget_destroy (window3);
7575       gtk_widget_destroy (window4);
7576     }
7577   
7578   if (!window1)
7579     {
7580       window1 = paned_keyboard_window1 (widget);
7581       g_signal_connect (window1, "destroy",
7582                         G_CALLBACK (gtk_widget_destroyed),
7583                         &window1);
7584     }
7585
7586   if (!window2)
7587     {
7588       window2 = paned_keyboard_window2 (widget);
7589       g_signal_connect (window2, "destroy",
7590                         G_CALLBACK (gtk_widget_destroyed),
7591                         &window2);
7592     }
7593
7594   if (!window3)
7595     {
7596       window3 = paned_keyboard_window3 (widget);
7597       g_signal_connect (window3, "destroy",
7598                         G_CALLBACK (gtk_widget_destroyed),
7599                         &window3);
7600     }
7601
7602   if (!window4)
7603     {
7604       window4 = paned_keyboard_window4 (widget);
7605       g_signal_connect (window4, "destroy",
7606                         G_CALLBACK (gtk_widget_destroyed),
7607                         &window4);
7608     }
7609
7610   if (gtk_widget_get_visible (window1))
7611     gtk_widget_destroy (GTK_WIDGET (window1));
7612   else
7613     gtk_widget_show_all (GTK_WIDGET (window1));
7614
7615   if (gtk_widget_get_visible (window2))
7616     gtk_widget_destroy (GTK_WIDGET (window2));
7617   else
7618     gtk_widget_show_all (GTK_WIDGET (window2));
7619
7620   if (gtk_widget_get_visible (window3))
7621     gtk_widget_destroy (GTK_WIDGET (window3));
7622   else
7623     gtk_widget_show_all (GTK_WIDGET (window3));
7624
7625   if (gtk_widget_get_visible (window4))
7626     gtk_widget_destroy (GTK_WIDGET (window4));
7627   else
7628     gtk_widget_show_all (GTK_WIDGET (window4));
7629 }
7630
7631
7632 /*
7633  * Shaped Windows
7634  */
7635
7636 typedef struct _cursoroffset {gint x,y;} CursorOffset;
7637
7638 static void
7639 shape_pressed (GtkWidget *widget, GdkEventButton *event)
7640 {
7641   CursorOffset *p;
7642
7643   /* ignore double and triple click */
7644   if (event->type != GDK_BUTTON_PRESS)
7645     return;
7646
7647   p = g_object_get_data (G_OBJECT (widget), "cursor_offset");
7648   p->x = (int) event->x;
7649   p->y = (int) event->y;
7650
7651   gtk_grab_add (widget);
7652   gdk_pointer_grab (widget->window, TRUE,
7653                     GDK_BUTTON_RELEASE_MASK |
7654                     GDK_BUTTON_MOTION_MASK |
7655                     GDK_POINTER_MOTION_HINT_MASK,
7656                     NULL, NULL, 0);
7657 }
7658
7659 static void
7660 shape_released (GtkWidget *widget)
7661 {
7662   gtk_grab_remove (widget);
7663   gdk_display_pointer_ungrab (gtk_widget_get_display (widget),
7664                               GDK_CURRENT_TIME);
7665 }
7666
7667 static void
7668 shape_motion (GtkWidget      *widget, 
7669               GdkEventMotion *event)
7670 {
7671   gint xp, yp;
7672   CursorOffset * p;
7673   GdkModifierType mask;
7674
7675   p = g_object_get_data (G_OBJECT (widget), "cursor_offset");
7676
7677   /*
7678    * Can't use event->x / event->y here 
7679    * because I need absolute coordinates.
7680    */
7681   gdk_window_get_pointer (NULL, &xp, &yp, &mask);
7682   gtk_widget_set_uposition (widget, xp  - p->x, yp  - p->y);
7683 }
7684
7685 GtkWidget *
7686 shape_create_icon (GdkScreen *screen,
7687                    char      *xpm_file,
7688                    gint       x,
7689                    gint       y,
7690                    gint       px,
7691                    gint       py,
7692                    gint       window_type)
7693 {
7694   GtkWidget *window;
7695   GtkWidget *pixmap;
7696   GtkWidget *fixed;
7697   CursorOffset* icon_pos;
7698   GdkGC* gc;
7699   GdkBitmap *gdk_pixmap_mask;
7700   GdkPixmap *gdk_pixmap;
7701   GtkStyle *style;
7702
7703   style = gtk_widget_get_default_style ();
7704   gc = style->black_gc; 
7705
7706   /*
7707    * GDK_WINDOW_TOPLEVEL works also, giving you a title border
7708    */
7709   window = gtk_window_new (window_type);
7710   gtk_window_set_screen (GTK_WINDOW (window), screen);
7711   
7712   fixed = gtk_fixed_new ();
7713   gtk_widget_set_size_request (fixed, 100, 100);
7714   gtk_container_add (GTK_CONTAINER (window), fixed);
7715   gtk_widget_show (fixed);
7716   
7717   gtk_widget_set_events (window, 
7718                          gtk_widget_get_events (window) |
7719                          GDK_BUTTON_MOTION_MASK |
7720                          GDK_POINTER_MOTION_HINT_MASK |
7721                          GDK_BUTTON_PRESS_MASK);
7722
7723   gtk_widget_realize (window);
7724   gdk_pixmap = gdk_pixmap_create_from_xpm (window->window, &gdk_pixmap_mask, 
7725                                            &style->bg[GTK_STATE_NORMAL],
7726                                            xpm_file);
7727
7728   pixmap = gtk_image_new_from_pixmap (gdk_pixmap, gdk_pixmap_mask);
7729   gtk_fixed_put (GTK_FIXED (fixed), pixmap, px,py);
7730   gtk_widget_show (pixmap);
7731   
7732   gtk_widget_shape_combine_mask (window, gdk_pixmap_mask, px, py);
7733   
7734   g_object_unref (gdk_pixmap_mask);
7735   g_object_unref (gdk_pixmap);
7736
7737   g_signal_connect (window, "button_press_event",
7738                     G_CALLBACK (shape_pressed), NULL);
7739   g_signal_connect (window, "button_release_event",
7740                     G_CALLBACK (shape_released), NULL);
7741   g_signal_connect (window, "motion_notify_event",
7742                     G_CALLBACK (shape_motion), NULL);
7743
7744   icon_pos = g_new (CursorOffset, 1);
7745   g_object_set_data (G_OBJECT (window), "cursor_offset", icon_pos);
7746
7747   gtk_widget_set_uposition (window, x, y);
7748   gtk_widget_show (window);
7749   
7750   return window;
7751 }
7752
7753 void 
7754 create_shapes (GtkWidget *widget)
7755 {
7756   /* Variables used by the Drag/Drop and Shape Window demos */
7757   static GtkWidget *modeller = NULL;
7758   static GtkWidget *sheets = NULL;
7759   static GtkWidget *rings = NULL;
7760   static GtkWidget *with_region = NULL;
7761   GdkScreen *screen = gtk_widget_get_screen (widget);
7762   
7763   if (!(file_exists ("Modeller.xpm") &&
7764         file_exists ("FilesQueue.xpm") &&
7765         file_exists ("3DRings.xpm")))
7766     return;
7767   
7768
7769   if (!modeller)
7770     {
7771       modeller = shape_create_icon (screen, "Modeller.xpm",
7772                                     440, 140, 0,0, GTK_WINDOW_POPUP);
7773
7774       g_signal_connect (modeller, "destroy",
7775                         G_CALLBACK (gtk_widget_destroyed),
7776                         &modeller);
7777     }
7778   else
7779     gtk_widget_destroy (modeller);
7780
7781   if (!sheets)
7782     {
7783       sheets = shape_create_icon (screen, "FilesQueue.xpm",
7784                                   580, 170, 0,0, GTK_WINDOW_POPUP);
7785
7786       g_signal_connect (sheets, "destroy",
7787                         G_CALLBACK (gtk_widget_destroyed),
7788                         &sheets);
7789
7790     }
7791   else
7792     gtk_widget_destroy (sheets);
7793
7794   if (!rings)
7795     {
7796       rings = shape_create_icon (screen, "3DRings.xpm",
7797                                  460, 270, 25,25, GTK_WINDOW_TOPLEVEL);
7798
7799       g_signal_connect (rings, "destroy",
7800                         G_CALLBACK (gtk_widget_destroyed),
7801                         &rings);
7802     }
7803   else
7804     gtk_widget_destroy (rings);
7805
7806   if (!with_region)
7807     {
7808       GdkRegion *region;
7809       gint x, y;
7810       
7811       with_region = shape_create_icon (screen, "3DRings.xpm",
7812                                        460, 270, 25,25, GTK_WINDOW_TOPLEVEL);
7813
7814       gtk_window_set_decorated (GTK_WINDOW (with_region), FALSE);
7815       
7816       g_signal_connect (with_region, "destroy",
7817                         G_CALLBACK (gtk_widget_destroyed),
7818                         &with_region);
7819
7820       /* reset shape from mask to a region */
7821       x = 0;
7822       y = 0;
7823       region = gdk_region_new ();
7824
7825       while (x < 460)
7826         {
7827           while (y < 270)
7828             {
7829               GdkRectangle rect;
7830               rect.x = x;
7831               rect.y = y;
7832               rect.width = 10;
7833               rect.height = 10;
7834
7835               gdk_region_union_with_rect (region, &rect);
7836               
7837               y += 20;
7838             }
7839           y = 0;
7840           x += 20;
7841         }
7842
7843       gdk_window_shape_combine_region (with_region->window,
7844                                        region,
7845                                        0, 0);
7846     }
7847   else
7848     gtk_widget_destroy (with_region);
7849 }
7850
7851 /*
7852  * WM Hints demo
7853  */
7854
7855 void
7856 create_wmhints (GtkWidget *widget)
7857 {
7858   static GtkWidget *window = NULL;
7859   GtkWidget *label;
7860   GtkWidget *separator;
7861   GtkWidget *button;
7862   GtkWidget *box1;
7863   GtkWidget *box2;
7864
7865   GdkBitmap *circles;
7866
7867   if (!window)
7868     {
7869       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7870
7871       gtk_window_set_screen (GTK_WINDOW (window),
7872                              gtk_widget_get_screen (widget));
7873       
7874       g_signal_connect (window, "destroy",
7875                         G_CALLBACK (gtk_widget_destroyed),
7876                         &window);
7877
7878       gtk_window_set_title (GTK_WINDOW (window), "WM Hints");
7879       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
7880
7881       gtk_widget_realize (window);
7882       
7883       circles = gdk_bitmap_create_from_data (window->window,
7884                                              (gchar *) circles_bits,
7885                                              circles_width,
7886                                              circles_height);
7887       gdk_window_set_icon (window->window, NULL,
7888                            circles, circles);
7889       
7890       gdk_window_set_icon_name (window->window, "WMHints Test Icon");
7891   
7892       gdk_window_set_decorations (window->window, GDK_DECOR_ALL | GDK_DECOR_MENU);
7893       gdk_window_set_functions (window->window, GDK_FUNC_ALL | GDK_FUNC_RESIZE);
7894       
7895       box1 = gtk_vbox_new (FALSE, 0);
7896       gtk_container_add (GTK_CONTAINER (window), box1);
7897       gtk_widget_show (box1);
7898
7899       label = gtk_label_new ("Try iconizing me!");
7900       gtk_widget_set_size_request (label, 150, 50);
7901       gtk_box_pack_start (GTK_BOX (box1), label, TRUE, TRUE, 0);
7902       gtk_widget_show (label);
7903
7904
7905       separator = gtk_hseparator_new ();
7906       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
7907       gtk_widget_show (separator);
7908
7909
7910       box2 = gtk_vbox_new (FALSE, 10);
7911       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
7912       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
7913       gtk_widget_show (box2);
7914
7915
7916       button = gtk_button_new_with_label ("close");
7917
7918       g_signal_connect_swapped (button, "clicked",
7919                                 G_CALLBACK (gtk_widget_destroy),
7920                                 window);
7921
7922       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
7923       gtk_widget_set_can_default (button, TRUE);
7924       gtk_widget_grab_default (button);
7925       gtk_widget_show (button);
7926     }
7927
7928   if (!gtk_widget_get_visible (window))
7929     gtk_widget_show (window);
7930   else
7931     gtk_widget_destroy (window);
7932 }
7933
7934
7935 /*
7936  * Window state tracking
7937  */
7938
7939 static gint
7940 window_state_callback (GtkWidget *widget,
7941                        GdkEventWindowState *event,
7942                        gpointer data)
7943 {
7944   GtkWidget *label = data;
7945   gchar *msg;
7946
7947   msg = g_strconcat (GTK_WINDOW (widget)->title, ": ",
7948                      (event->new_window_state & GDK_WINDOW_STATE_WITHDRAWN) ?
7949                      "withdrawn" : "not withdrawn", ", ",
7950                      (event->new_window_state & GDK_WINDOW_STATE_ICONIFIED) ?
7951                      "iconified" : "not iconified", ", ",
7952                      (event->new_window_state & GDK_WINDOW_STATE_STICKY) ?
7953                      "sticky" : "not sticky", ", ",
7954                      (event->new_window_state & GDK_WINDOW_STATE_MAXIMIZED) ?
7955                      "maximized" : "not maximized", ", ",
7956                      (event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN) ?
7957                      "fullscreen" : "not fullscreen",
7958                      (event->new_window_state & GDK_WINDOW_STATE_ABOVE) ?
7959                      "above" : "not above", ", ",
7960                      (event->new_window_state & GDK_WINDOW_STATE_BELOW) ?
7961                      "below" : "not below", ", ",
7962                      NULL);
7963   
7964   gtk_label_set_text (GTK_LABEL (label), msg);
7965
7966   g_free (msg);
7967
7968   return FALSE;
7969 }
7970
7971 static GtkWidget*
7972 tracking_label (GtkWidget *window)
7973 {
7974   GtkWidget *label;
7975   GtkWidget *hbox;
7976   GtkWidget *button;
7977
7978   hbox = gtk_hbox_new (FALSE, 5);
7979
7980   g_signal_connect_object (hbox,
7981                            "destroy",
7982                            G_CALLBACK (gtk_widget_destroy),
7983                            window,
7984                            G_CONNECT_SWAPPED);
7985   
7986   label = gtk_label_new ("<no window state events received>");
7987   gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
7988   gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
7989   
7990   g_signal_connect (window,
7991                     "window_state_event",
7992                     G_CALLBACK (window_state_callback),
7993                     label);
7994
7995   button = gtk_button_new_with_label ("Deiconify");
7996   g_signal_connect_object (button,
7997                            "clicked",
7998                            G_CALLBACK (gtk_window_deiconify),
7999                            window,
8000                            G_CONNECT_SWAPPED);
8001   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
8002
8003   button = gtk_button_new_with_label ("Iconify");
8004   g_signal_connect_object (button,
8005                            "clicked",
8006                            G_CALLBACK (gtk_window_iconify),
8007                            window,
8008                            G_CONNECT_SWAPPED);
8009   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
8010
8011   button = gtk_button_new_with_label ("Fullscreen");
8012   g_signal_connect_object (button,
8013                            "clicked",
8014                            G_CALLBACK (gtk_window_fullscreen),
8015                            window,
8016                            G_CONNECT_SWAPPED);
8017   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
8018
8019   button = gtk_button_new_with_label ("Unfullscreen");
8020   g_signal_connect_object (button,
8021                            "clicked",
8022                            G_CALLBACK (gtk_window_unfullscreen),
8023                            window,
8024                            G_CONNECT_SWAPPED);
8025   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
8026   
8027   button = gtk_button_new_with_label ("Present");
8028   g_signal_connect_object (button,
8029                            "clicked",
8030                            G_CALLBACK (gtk_window_present),
8031                            window,
8032                            G_CONNECT_SWAPPED);
8033   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
8034
8035   button = gtk_button_new_with_label ("Show");
8036   g_signal_connect_object (button,
8037                            "clicked",
8038                            G_CALLBACK (gtk_widget_show),
8039                            window,
8040                            G_CONNECT_SWAPPED);
8041   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
8042   
8043   gtk_widget_show_all (hbox);
8044   
8045   return hbox;
8046 }
8047
8048 void
8049 keep_window_above (GtkToggleButton *togglebutton, gpointer data)
8050 {
8051   GtkWidget *button = g_object_get_data (G_OBJECT (togglebutton), "radio");
8052
8053   gtk_window_set_keep_above (GTK_WINDOW (data),
8054                              gtk_toggle_button_get_active (togglebutton));
8055
8056   if (gtk_toggle_button_get_active (togglebutton))
8057     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE);
8058 }
8059
8060 void
8061 keep_window_below (GtkToggleButton *togglebutton, gpointer data)
8062 {
8063   GtkWidget *button = g_object_get_data (G_OBJECT (togglebutton), "radio");
8064
8065   gtk_window_set_keep_below (GTK_WINDOW (data),
8066                              gtk_toggle_button_get_active (togglebutton));
8067
8068   if (gtk_toggle_button_get_active (togglebutton))
8069     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE);
8070 }
8071
8072
8073 static GtkWidget*
8074 get_state_controls (GtkWidget *window)
8075 {
8076   GtkWidget *vbox;
8077   GtkWidget *button;
8078   GtkWidget *button_above;
8079   GtkWidget *button_below;
8080
8081   vbox = gtk_vbox_new (FALSE, 0);
8082   
8083   button = gtk_button_new_with_label ("Stick");
8084   g_signal_connect_object (button,
8085                            "clicked",
8086                            G_CALLBACK (gtk_window_stick),
8087                            window,
8088                            G_CONNECT_SWAPPED);
8089   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8090
8091   button = gtk_button_new_with_label ("Unstick");
8092   g_signal_connect_object (button,
8093                            "clicked",
8094                            G_CALLBACK (gtk_window_unstick),
8095                            window,
8096                            G_CONNECT_SWAPPED);
8097   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8098   
8099   button = gtk_button_new_with_label ("Maximize");
8100   g_signal_connect_object (button,
8101                            "clicked",
8102                            G_CALLBACK (gtk_window_maximize),
8103                            window,
8104                            G_CONNECT_SWAPPED);
8105   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8106
8107   button = gtk_button_new_with_label ("Unmaximize");
8108   g_signal_connect_object (button,
8109                            "clicked",
8110                            G_CALLBACK (gtk_window_unmaximize),
8111                            window,
8112                            G_CONNECT_SWAPPED);
8113   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8114
8115   button = gtk_button_new_with_label ("Iconify");
8116   g_signal_connect_object (button,
8117                            "clicked",
8118                            G_CALLBACK (gtk_window_iconify),
8119                            window,
8120                            G_CONNECT_SWAPPED);
8121   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8122
8123   button = gtk_button_new_with_label ("Fullscreen");
8124   g_signal_connect_object (button,
8125                            "clicked",
8126                            G_CALLBACK (gtk_window_fullscreen),
8127                            window,
8128                            G_CONNECT_SWAPPED);
8129   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8130
8131   button = gtk_button_new_with_label ("Unfullscreen");
8132   g_signal_connect_object (button,
8133                            "clicked",
8134                            G_CALLBACK (gtk_window_unfullscreen),
8135                            window,
8136                            G_CONNECT_SWAPPED);
8137   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8138
8139   button_above = gtk_toggle_button_new_with_label ("Keep above");
8140   g_signal_connect (button_above,
8141                     "toggled",
8142                     G_CALLBACK (keep_window_above),
8143                     window);
8144   gtk_box_pack_start (GTK_BOX (vbox), button_above, FALSE, FALSE, 0);
8145
8146   button_below = gtk_toggle_button_new_with_label ("Keep below");
8147   g_signal_connect (button_below,
8148                     "toggled",
8149                     G_CALLBACK (keep_window_below),
8150                     window);
8151   gtk_box_pack_start (GTK_BOX (vbox), button_below, FALSE, FALSE, 0);
8152
8153   g_object_set_data (G_OBJECT (button_above), "radio", button_below);
8154   g_object_set_data (G_OBJECT (button_below), "radio", button_above);
8155
8156   button = gtk_button_new_with_label ("Hide (withdraw)");
8157   g_signal_connect_object (button,
8158                            "clicked",
8159                            G_CALLBACK (gtk_widget_hide),
8160                            window,
8161                            G_CONNECT_SWAPPED);
8162   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8163   
8164   gtk_widget_show_all (vbox);
8165
8166   return vbox;
8167 }
8168
8169 void
8170 create_window_states (GtkWidget *widget)
8171 {
8172   static GtkWidget *window = NULL;
8173   GtkWidget *label;
8174   GtkWidget *box1;
8175   GtkWidget *iconified;
8176   GtkWidget *normal;
8177   GtkWidget *controls;
8178
8179   if (!window)
8180     {
8181       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8182       gtk_window_set_screen (GTK_WINDOW (window),
8183                              gtk_widget_get_screen (widget));
8184
8185       g_signal_connect (window, "destroy",
8186                         G_CALLBACK (gtk_widget_destroyed),
8187                         &window);
8188
8189       gtk_window_set_title (GTK_WINDOW (window), "Window states");
8190       
8191       box1 = gtk_vbox_new (FALSE, 0);
8192       gtk_container_add (GTK_CONTAINER (window), box1);
8193
8194       iconified = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8195
8196       gtk_window_set_screen (GTK_WINDOW (iconified),
8197                              gtk_widget_get_screen (widget));
8198       
8199       g_signal_connect_object (iconified, "destroy",
8200                                G_CALLBACK (gtk_widget_destroy),
8201                                window,
8202                                G_CONNECT_SWAPPED);
8203       gtk_window_iconify (GTK_WINDOW (iconified));
8204       gtk_window_set_title (GTK_WINDOW (iconified), "Iconified initially");
8205       controls = get_state_controls (iconified);
8206       gtk_container_add (GTK_CONTAINER (iconified), controls);
8207       
8208       normal = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8209
8210       gtk_window_set_screen (GTK_WINDOW (normal),
8211                              gtk_widget_get_screen (widget));
8212       
8213       g_signal_connect_object (normal, "destroy",
8214                                G_CALLBACK (gtk_widget_destroy),
8215                                window,
8216                                G_CONNECT_SWAPPED);
8217       
8218       gtk_window_set_title (GTK_WINDOW (normal), "Deiconified initially");
8219       controls = get_state_controls (normal);
8220       gtk_container_add (GTK_CONTAINER (normal), controls);
8221       
8222       label = tracking_label (iconified);
8223       gtk_container_add (GTK_CONTAINER (box1), label);
8224
8225       label = tracking_label (normal);
8226       gtk_container_add (GTK_CONTAINER (box1), label);
8227
8228       gtk_widget_show_all (iconified);
8229       gtk_widget_show_all (normal);
8230       gtk_widget_show_all (box1);
8231     }
8232
8233   if (!gtk_widget_get_visible (window))
8234     gtk_widget_show (window);
8235   else
8236     gtk_widget_destroy (window);
8237 }
8238
8239 /*
8240  * Window sizing
8241  */
8242
8243 static gint
8244 configure_event_callback (GtkWidget *widget,
8245                           GdkEventConfigure *event,
8246                           gpointer data)
8247 {
8248   GtkWidget *label = data;
8249   gchar *msg;
8250   gint x, y;
8251   
8252   gtk_window_get_position (GTK_WINDOW (widget), &x, &y);
8253   
8254   msg = g_strdup_printf ("event: %d,%d  %d x %d\n"
8255                          "position: %d, %d",
8256                          event->x, event->y, event->width, event->height,
8257                          x, y);
8258   
8259   gtk_label_set_text (GTK_LABEL (label), msg);
8260
8261   g_free (msg);
8262
8263   return FALSE;
8264 }
8265
8266 static void
8267 get_ints (GtkWidget *window,
8268           gint      *a,
8269           gint      *b)
8270 {
8271   GtkWidget *spin1;
8272   GtkWidget *spin2;
8273
8274   spin1 = g_object_get_data (G_OBJECT (window), "spin1");
8275   spin2 = g_object_get_data (G_OBJECT (window), "spin2");
8276
8277   *a = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (spin1));
8278   *b = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (spin2));
8279 }
8280
8281 static void
8282 set_size_callback (GtkWidget *widget,
8283                    gpointer   data)
8284 {
8285   gint w, h;
8286   
8287   get_ints (data, &w, &h);
8288
8289   gtk_window_resize (GTK_WINDOW (g_object_get_data (data, "target")), w, h);
8290 }
8291
8292 static void
8293 unset_default_size_callback (GtkWidget *widget,
8294                              gpointer   data)
8295 {
8296   gtk_window_set_default_size (g_object_get_data (data, "target"),
8297                                -1, -1);
8298 }
8299
8300 static void
8301 set_default_size_callback (GtkWidget *widget,
8302                            gpointer   data)
8303 {
8304   gint w, h;
8305   
8306   get_ints (data, &w, &h);
8307
8308   gtk_window_set_default_size (g_object_get_data (data, "target"),
8309                                w, h);
8310 }
8311
8312 static void
8313 unset_size_request_callback (GtkWidget *widget,
8314                              gpointer   data)
8315 {
8316   gtk_widget_set_size_request (g_object_get_data (data, "target"),
8317                                -1, -1);
8318 }
8319
8320 static void
8321 set_size_request_callback (GtkWidget *widget,
8322                            gpointer   data)
8323 {
8324   gint w, h;
8325   
8326   get_ints (data, &w, &h);
8327
8328   gtk_widget_set_size_request (g_object_get_data (data, "target"),
8329                                w, h);
8330 }
8331
8332 static void
8333 set_location_callback (GtkWidget *widget,
8334                        gpointer   data)
8335 {
8336   gint x, y;
8337   
8338   get_ints (data, &x, &y);
8339
8340   gtk_window_move (g_object_get_data (data, "target"), x, y);
8341 }
8342
8343 static void
8344 move_to_position_callback (GtkWidget *widget,
8345                            gpointer   data)
8346 {
8347   gint x, y;
8348   GtkWindow *window;
8349
8350   window = g_object_get_data (data, "target");
8351   
8352   gtk_window_get_position (window, &x, &y);
8353
8354   gtk_window_move (window, x, y);
8355 }
8356
8357 static void
8358 set_geometry_callback (GtkWidget *entry,
8359                        gpointer   data)
8360 {
8361   gchar *text;
8362   GtkWindow *target;
8363
8364   target = GTK_WINDOW (g_object_get_data (G_OBJECT (data), "target"));
8365   
8366   text = gtk_editable_get_chars (GTK_EDITABLE (entry), 0, -1);
8367
8368   if (!gtk_window_parse_geometry (target, text))
8369     g_print ("Bad geometry string '%s'\n", text);
8370
8371   g_free (text);
8372 }
8373
8374 static void
8375 allow_shrink_callback (GtkWidget *widget,
8376                        gpointer   data)
8377 {
8378   g_object_set (g_object_get_data (data, "target"),
8379                 "allow_shrink",
8380                 GTK_TOGGLE_BUTTON (widget)->active,
8381                 NULL);
8382 }
8383
8384 static void
8385 allow_grow_callback (GtkWidget *widget,
8386                      gpointer   data)
8387 {
8388   g_object_set (g_object_get_data (data, "target"),
8389                 "allow_grow",
8390                 GTK_TOGGLE_BUTTON (widget)->active,
8391                 NULL);
8392 }
8393
8394 static void
8395 gravity_selected (GtkWidget *widget,
8396                   gpointer   data)
8397 {
8398   gtk_window_set_gravity (GTK_WINDOW (g_object_get_data (data, "target")),
8399                           gtk_combo_box_get_active (GTK_COMBO_BOX (widget)) + GDK_GRAVITY_NORTH_WEST);
8400 }
8401
8402 static void
8403 pos_selected (GtkWidget *widget,
8404               gpointer   data)
8405 {
8406   gtk_window_set_position (GTK_WINDOW (g_object_get_data (data, "target")),
8407                            gtk_combo_box_get_active (GTK_COMBO_BOX (widget)) + GTK_WIN_POS_NONE);
8408 }
8409
8410 static void
8411 move_gravity_window_to_current_position (GtkWidget *widget,
8412                                          gpointer   data)
8413 {
8414   gint x, y;
8415   GtkWindow *window;
8416
8417   window = GTK_WINDOW (data);    
8418   
8419   gtk_window_get_position (window, &x, &y);
8420
8421   gtk_window_move (window, x, y);
8422 }
8423
8424 static void
8425 get_screen_corner (GtkWindow *window,
8426                    gint      *x,
8427                    gint      *y)
8428 {
8429   int w, h;
8430   GdkScreen * screen = gtk_window_get_screen (window);
8431   
8432   gtk_window_get_size (GTK_WINDOW (window), &w, &h);
8433
8434   switch (gtk_window_get_gravity (window))
8435     {
8436     case GDK_GRAVITY_SOUTH_EAST:
8437       *x = gdk_screen_get_width (screen) - w;
8438       *y = gdk_screen_get_height (screen) - h;
8439       break;
8440
8441     case GDK_GRAVITY_NORTH_EAST:
8442       *x = gdk_screen_get_width (screen) - w;
8443       *y = 0;
8444       break;
8445
8446     case GDK_GRAVITY_SOUTH_WEST:
8447       *x = 0;
8448       *y = gdk_screen_get_height (screen) - h;
8449       break;
8450
8451     case GDK_GRAVITY_NORTH_WEST:
8452       *x = 0;
8453       *y = 0;
8454       break;
8455       
8456     case GDK_GRAVITY_SOUTH:
8457       *x = (gdk_screen_get_width (screen) - w) / 2;
8458       *y = gdk_screen_get_height (screen) - h;
8459       break;
8460
8461     case GDK_GRAVITY_NORTH:
8462       *x = (gdk_screen_get_width (screen) - w) / 2;
8463       *y = 0;
8464       break;
8465
8466     case GDK_GRAVITY_WEST:
8467       *x = 0;
8468       *y = (gdk_screen_get_height (screen) - h) / 2;
8469       break;
8470
8471     case GDK_GRAVITY_EAST:
8472       *x = gdk_screen_get_width (screen) - w;
8473       *y = (gdk_screen_get_height (screen) - h) / 2;
8474       break;
8475
8476     case GDK_GRAVITY_CENTER:
8477       *x = (gdk_screen_get_width (screen) - w) / 2;
8478       *y = (gdk_screen_get_height (screen) - h) / 2;
8479       break;
8480
8481     case GDK_GRAVITY_STATIC:
8482       /* pick some random numbers */
8483       *x = 350;
8484       *y = 350;
8485       break;
8486
8487     default:
8488       g_assert_not_reached ();
8489       break;
8490     }
8491 }
8492
8493 static void
8494 move_gravity_window_to_starting_position (GtkWidget *widget,
8495                                           gpointer   data)
8496 {
8497   gint x, y;
8498   GtkWindow *window;
8499
8500   window = GTK_WINDOW (data);    
8501   
8502   get_screen_corner (window,
8503                      &x, &y);
8504   
8505   gtk_window_move (window, x, y);
8506 }
8507
8508 static GtkWidget*
8509 make_gravity_window (GtkWidget   *destroy_with,
8510                      GdkGravity   gravity,
8511                      const gchar *title)
8512 {
8513   GtkWidget *window;
8514   GtkWidget *button;
8515   GtkWidget *vbox;
8516   int x, y;
8517   
8518   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8519
8520   gtk_window_set_screen (GTK_WINDOW (window),
8521                          gtk_widget_get_screen (destroy_with));
8522
8523   vbox = gtk_vbox_new (FALSE, 0);
8524   gtk_widget_show (vbox);
8525   
8526   gtk_container_add (GTK_CONTAINER (window), vbox);
8527   gtk_window_set_title (GTK_WINDOW (window), title);
8528   gtk_window_set_gravity (GTK_WINDOW (window), gravity);
8529
8530   g_signal_connect_object (destroy_with,
8531                            "destroy",
8532                            G_CALLBACK (gtk_widget_destroy),
8533                            window,
8534                            G_CONNECT_SWAPPED);
8535
8536   
8537   button = gtk_button_new_with_mnemonic ("_Move to current position");
8538
8539   g_signal_connect (button, "clicked",
8540                     G_CALLBACK (move_gravity_window_to_current_position),
8541                     window);
8542
8543   gtk_container_add (GTK_CONTAINER (vbox), button);
8544   gtk_widget_show (button);
8545
8546   button = gtk_button_new_with_mnemonic ("Move to _starting position");
8547
8548   g_signal_connect (button, "clicked",
8549                     G_CALLBACK (move_gravity_window_to_starting_position),
8550                     window);
8551
8552   gtk_container_add (GTK_CONTAINER (vbox), button);
8553   gtk_widget_show (button);
8554   
8555   /* Pretend this is the result of --geometry.
8556    * DO NOT COPY THIS CODE unless you are setting --geometry results,
8557    * and in that case you probably should just use gtk_window_parse_geometry().
8558    * AGAIN, DO NOT SET GDK_HINT_USER_POS! It violates the ICCCM unless
8559    * you are parsing --geometry or equivalent.
8560    */
8561   gtk_window_set_geometry_hints (GTK_WINDOW (window),
8562                                  NULL, NULL,
8563                                  GDK_HINT_USER_POS);
8564
8565   gtk_window_set_default_size (GTK_WINDOW (window),
8566                                200, 200);
8567
8568   get_screen_corner (GTK_WINDOW (window), &x, &y);
8569   
8570   gtk_window_move (GTK_WINDOW (window),
8571                    x, y);
8572   
8573   return window;
8574 }
8575
8576 static void
8577 do_gravity_test (GtkWidget *widget,
8578                  gpointer   data)
8579 {
8580   GtkWidget *destroy_with = data;
8581   GtkWidget *window;
8582   
8583   /* We put a window at each gravity point on the screen. */
8584   window = make_gravity_window (destroy_with, GDK_GRAVITY_NORTH_WEST,
8585                                 "NorthWest");
8586   gtk_widget_show (window);
8587   
8588   window = make_gravity_window (destroy_with, GDK_GRAVITY_SOUTH_EAST,
8589                                 "SouthEast");
8590   gtk_widget_show (window);
8591
8592   window = make_gravity_window (destroy_with, GDK_GRAVITY_NORTH_EAST,
8593                                 "NorthEast");
8594   gtk_widget_show (window);
8595
8596   window = make_gravity_window (destroy_with, GDK_GRAVITY_SOUTH_WEST,
8597                                 "SouthWest");
8598   gtk_widget_show (window);
8599
8600   window = make_gravity_window (destroy_with, GDK_GRAVITY_SOUTH,
8601                                 "South");
8602   gtk_widget_show (window);
8603
8604   window = make_gravity_window (destroy_with, GDK_GRAVITY_NORTH,
8605                                 "North");
8606   gtk_widget_show (window);
8607
8608   
8609   window = make_gravity_window (destroy_with, GDK_GRAVITY_WEST,
8610                                 "West");
8611   gtk_widget_show (window);
8612
8613     
8614   window = make_gravity_window (destroy_with, GDK_GRAVITY_EAST,
8615                                 "East");
8616   gtk_widget_show (window);
8617
8618   window = make_gravity_window (destroy_with, GDK_GRAVITY_CENTER,
8619                                 "Center");
8620   gtk_widget_show (window);
8621
8622   window = make_gravity_window (destroy_with, GDK_GRAVITY_STATIC,
8623                                 "Static");
8624   gtk_widget_show (window);
8625 }
8626
8627 static GtkWidget*
8628 window_controls (GtkWidget *window)
8629 {
8630   GtkWidget *control_window;
8631   GtkWidget *label;
8632   GtkWidget *vbox;
8633   GtkWidget *button;
8634   GtkWidget *spin;
8635   GtkAdjustment *adj;
8636   GtkWidget *entry;
8637   GtkWidget *om;
8638   gint i;
8639   
8640   control_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8641
8642   gtk_window_set_screen (GTK_WINDOW (control_window),
8643                          gtk_widget_get_screen (window));
8644
8645   gtk_window_set_title (GTK_WINDOW (control_window), "Size controls");
8646   
8647   g_object_set_data (G_OBJECT (control_window),
8648                      "target",
8649                      window);
8650   
8651   g_signal_connect_object (control_window,
8652                            "destroy",
8653                            G_CALLBACK (gtk_widget_destroy),
8654                            window,
8655                            G_CONNECT_SWAPPED);
8656
8657   vbox = gtk_vbox_new (FALSE, 5);
8658   
8659   gtk_container_add (GTK_CONTAINER (control_window), vbox);
8660   
8661   label = gtk_label_new ("<no configure events>");
8662   gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
8663   
8664   g_signal_connect (window,
8665                     "configure_event",
8666                     G_CALLBACK (configure_event_callback),
8667                     label);
8668
8669   adj = (GtkAdjustment *) gtk_adjustment_new (10.0, -2000.0, 2000.0, 1.0,
8670                                               5.0, 0.0);
8671   spin = gtk_spin_button_new (adj, 0, 0);
8672
8673   gtk_box_pack_start (GTK_BOX (vbox), spin, FALSE, FALSE, 0);
8674
8675   g_object_set_data (G_OBJECT (control_window), "spin1", spin);
8676
8677   adj = (GtkAdjustment *) gtk_adjustment_new (10.0, -2000.0, 2000.0, 1.0,
8678                                               5.0, 0.0);
8679   spin = gtk_spin_button_new (adj, 0, 0);
8680
8681   gtk_box_pack_start (GTK_BOX (vbox), spin, FALSE, FALSE, 0);
8682
8683   g_object_set_data (G_OBJECT (control_window), "spin2", spin);
8684
8685   entry = gtk_entry_new ();
8686   gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
8687
8688   g_signal_connect (entry, "changed",
8689                     G_CALLBACK (set_geometry_callback),
8690                     control_window);
8691
8692   button = gtk_button_new_with_label ("Show gravity test windows");
8693   g_signal_connect_swapped (button,
8694                             "clicked",
8695                             G_CALLBACK (do_gravity_test),
8696                             control_window);
8697   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8698
8699   button = gtk_button_new_with_label ("Reshow with initial size");
8700   g_signal_connect_object (button,
8701                            "clicked",
8702                            G_CALLBACK (gtk_window_reshow_with_initial_size),
8703                            window,
8704                            G_CONNECT_SWAPPED);
8705   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8706   
8707   button = gtk_button_new_with_label ("Queue resize");
8708   g_signal_connect_object (button,
8709                            "clicked",
8710                            G_CALLBACK (gtk_widget_queue_resize),
8711                            window,
8712                            G_CONNECT_SWAPPED);
8713   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8714   
8715   button = gtk_button_new_with_label ("Resize");
8716   g_signal_connect (button,
8717                     "clicked",
8718                     G_CALLBACK (set_size_callback),
8719                     control_window);
8720   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8721
8722   button = gtk_button_new_with_label ("Set default size");
8723   g_signal_connect (button,
8724                     "clicked",
8725                     G_CALLBACK (set_default_size_callback),
8726                     control_window);
8727   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8728
8729   button = gtk_button_new_with_label ("Unset default size");
8730   g_signal_connect (button,
8731                     "clicked",
8732                     G_CALLBACK (unset_default_size_callback),
8733                     control_window);
8734   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8735   
8736   button = gtk_button_new_with_label ("Set size request");
8737   g_signal_connect (button,
8738                     "clicked",
8739                     G_CALLBACK (set_size_request_callback),
8740                     control_window);
8741   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8742
8743   button = gtk_button_new_with_label ("Unset size request");
8744   g_signal_connect (button,
8745                     "clicked",
8746                     G_CALLBACK (unset_size_request_callback),
8747                     control_window);
8748   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8749   
8750   button = gtk_button_new_with_label ("Move");
8751   g_signal_connect (button,
8752                     "clicked",
8753                     G_CALLBACK (set_location_callback),
8754                     control_window);
8755   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8756
8757   button = gtk_button_new_with_label ("Move to current position");
8758   g_signal_connect (button,
8759                     "clicked",
8760                     G_CALLBACK (move_to_position_callback),
8761                     control_window);
8762   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8763   
8764   button = gtk_check_button_new_with_label ("Allow shrink");
8765   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE);
8766   g_signal_connect (button,
8767                     "toggled",
8768                     G_CALLBACK (allow_shrink_callback),
8769                     control_window);
8770   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8771
8772   button = gtk_check_button_new_with_label ("Allow grow");
8773   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
8774   g_signal_connect (button,
8775                     "toggled",
8776                     G_CALLBACK (allow_grow_callback),
8777                     control_window);
8778   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8779   
8780   button = gtk_button_new_with_mnemonic ("_Show");
8781   g_signal_connect_object (button,
8782                            "clicked",
8783                            G_CALLBACK (gtk_widget_show),
8784                            window,
8785                            G_CONNECT_SWAPPED);
8786   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8787
8788   button = gtk_button_new_with_mnemonic ("_Hide");
8789   g_signal_connect_object (button,
8790                            "clicked",
8791                            G_CALLBACK (gtk_widget_hide),
8792                            window,
8793                            G_CONNECT_SWAPPED);
8794   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8795   
8796   om = gtk_combo_box_new_text ();
8797   i = 0;
8798   while (i < 10)
8799     {
8800       static gchar *names[] = {
8801         "GDK_GRAVITY_NORTH_WEST",
8802         "GDK_GRAVITY_NORTH",
8803         "GDK_GRAVITY_NORTH_EAST",
8804         "GDK_GRAVITY_WEST",
8805         "GDK_GRAVITY_CENTER",
8806         "GDK_GRAVITY_EAST",
8807         "GDK_GRAVITY_SOUTH_WEST",
8808         "GDK_GRAVITY_SOUTH",
8809         "GDK_GRAVITY_SOUTH_EAST",
8810         "GDK_GRAVITY_STATIC",
8811         NULL
8812       };
8813
8814       g_assert (names[i]);
8815       gtk_combo_box_append_text (GTK_COMBO_BOX (om), names[i]);
8816
8817       ++i;
8818     }
8819   
8820   g_signal_connect (om,
8821                     "changed",
8822                     G_CALLBACK (gravity_selected),
8823                     control_window);
8824
8825   gtk_box_pack_end (GTK_BOX (vbox), om, FALSE, FALSE, 0);
8826
8827
8828   om = gtk_combo_box_new_text ();
8829   i = 0;
8830   while (i < 5)
8831     {
8832       static gchar *names[] = {
8833         "GTK_WIN_POS_NONE",
8834         "GTK_WIN_POS_CENTER",
8835         "GTK_WIN_POS_MOUSE",
8836         "GTK_WIN_POS_CENTER_ALWAYS",
8837         "GTK_WIN_POS_CENTER_ON_PARENT",
8838         NULL
8839       };
8840
8841       g_assert (names[i]);
8842       gtk_combo_box_append_text (GTK_COMBO_BOX (om), names[i]);
8843
8844       ++i;
8845     }
8846
8847   g_signal_connect (om,
8848                     "changed",
8849                     G_CALLBACK (pos_selected),
8850                     control_window);
8851
8852   gtk_box_pack_end (GTK_BOX (vbox), om, FALSE, FALSE, 0);
8853   
8854   gtk_widget_show_all (vbox);
8855   
8856   return control_window;
8857 }
8858
8859 void
8860 create_window_sizing (GtkWidget *widget)
8861 {
8862   static GtkWidget *window = NULL;
8863   static GtkWidget *target_window = NULL;
8864
8865   if (!target_window)
8866     {
8867       GtkWidget *label;
8868       
8869       target_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8870       gtk_window_set_screen (GTK_WINDOW (target_window),
8871                              gtk_widget_get_screen (widget));
8872       label = gtk_label_new (NULL);
8873       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");
8874       gtk_container_add (GTK_CONTAINER (target_window), label);
8875       gtk_widget_show (label);
8876       
8877       g_signal_connect (target_window, "destroy",
8878                         G_CALLBACK (gtk_widget_destroyed),
8879                         &target_window);
8880
8881       window = window_controls (target_window);
8882       
8883       g_signal_connect (window, "destroy",
8884                         G_CALLBACK (gtk_widget_destroyed),
8885                         &window);
8886       
8887       gtk_window_set_title (GTK_WINDOW (target_window), "Window to size");
8888     }
8889
8890   /* don't show target window by default, we want to allow testing
8891    * of behavior on first show.
8892    */
8893   
8894   if (!gtk_widget_get_visible (window))
8895     gtk_widget_show (window);
8896   else
8897     gtk_widget_destroy (window);
8898 }
8899
8900 /*
8901  * GtkProgressBar
8902  */
8903
8904 typedef struct _ProgressData {
8905   GtkWidget *window;
8906   GtkWidget *pbar;
8907   GtkWidget *block_spin;
8908   GtkWidget *x_align_spin;
8909   GtkWidget *y_align_spin;
8910   GtkWidget *step_spin;
8911   GtkWidget *act_blocks_spin;
8912   GtkWidget *label;
8913   GtkWidget *omenu1;
8914   GtkWidget *elmenu;
8915   GtkWidget *omenu2;
8916   GtkWidget *entry;
8917   int timer;
8918   gboolean activity;
8919 } ProgressData;
8920
8921 gboolean
8922 progress_timeout (gpointer data)
8923 {
8924   ProgressData *pdata = data;
8925   gdouble new_val;
8926
8927   if (pdata->activity)
8928     {
8929       gtk_progress_bar_pulse (GTK_PROGRESS_BAR (pdata->pbar));
8930       return TRUE;
8931     }
8932
8933   new_val = gtk_progress_bar_get_fraction (GTK_PROGRESS_BAR (pdata->pbar)) + 0.01;
8934   if (new_val > 1.00)
8935     new_val = 0.00;
8936
8937   gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (pdata->pbar), new_val);
8938
8939   return TRUE;
8940 }
8941
8942 static void
8943 destroy_progress (GtkWidget     *widget,
8944                   ProgressData **pdata)
8945 {
8946   g_source_remove ((*pdata)->timer);
8947   (*pdata)->timer = 0;
8948   (*pdata)->window = NULL;
8949   g_free (*pdata);
8950   *pdata = NULL;
8951 }
8952
8953 static void
8954 progressbar_toggle_orientation (GtkWidget *widget, gpointer data)
8955 {
8956   ProgressData *pdata;
8957   gint i;
8958
8959   pdata = (ProgressData *) data;
8960
8961   if (!gtk_widget_get_mapped (widget))
8962     return;
8963
8964   i = gtk_combo_box_get_active (GTK_COMBO_BOX (widget));
8965
8966   gtk_progress_bar_set_orientation (GTK_PROGRESS_BAR (pdata->pbar),
8967                                     (GtkProgressBarOrientation) i);
8968 }
8969
8970 static void
8971 toggle_show_text (GtkWidget *widget, ProgressData *pdata)
8972 {
8973   gtk_progress_set_show_text (GTK_PROGRESS (pdata->pbar),
8974                               GTK_TOGGLE_BUTTON (widget)->active);
8975   gtk_widget_set_sensitive (pdata->entry, GTK_TOGGLE_BUTTON (widget)->active);
8976 }
8977
8978 static void
8979 progressbar_toggle_ellipsize (GtkWidget *widget,
8980                               gpointer   data)
8981 {
8982   ProgressData *pdata = data;
8983   if (gtk_widget_is_drawable (widget))
8984     {
8985       gint i = gtk_combo_box_get_active (GTK_COMBO_BOX (widget));
8986       gtk_progress_bar_set_ellipsize (GTK_PROGRESS_BAR (pdata->pbar), i);
8987     }
8988 }
8989
8990 static void
8991 progress_value_changed (GtkAdjustment *adj, ProgressData *pdata)
8992 {
8993   char buf[20];
8994
8995   if (GTK_PROGRESS (pdata->pbar)->activity_mode)
8996     sprintf (buf, "???");
8997   else
8998     sprintf (buf, "%.0f%%", 100 *
8999       gtk_progress_bar_get_fraction (GTK_PROGRESS_BAR (pdata->pbar)));
9000   gtk_label_set_text (GTK_LABEL (pdata->label), buf);
9001 }
9002
9003 static void
9004 adjust_align (GtkAdjustment *adj, ProgressData *pdata)
9005 {
9006   gtk_progress_set_text_alignment (GTK_PROGRESS (pdata->pbar),
9007          gtk_spin_button_get_value (GTK_SPIN_BUTTON (pdata->x_align_spin)),
9008          gtk_spin_button_get_value (GTK_SPIN_BUTTON (pdata->y_align_spin)));
9009 }
9010
9011 static void
9012 toggle_activity_mode (GtkWidget *widget, ProgressData *pdata)
9013 {
9014   pdata->activity = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
9015 }
9016
9017 static void
9018 entry_changed (GtkWidget *widget, ProgressData *pdata)
9019 {
9020   gtk_progress_bar_set_text (GTK_PROGRESS_BAR (pdata->pbar),
9021                           gtk_entry_get_text (GTK_ENTRY (pdata->entry)));
9022 }
9023
9024 void
9025 create_progress_bar (GtkWidget *widget)
9026 {
9027   GtkWidget *button;
9028   GtkWidget *vbox;
9029   GtkWidget *vbox2;
9030   GtkWidget *hbox;
9031   GtkWidget *check;
9032   GtkWidget *frame;
9033   GtkWidget *tab;
9034   GtkWidget *label;
9035   GtkWidget *align;
9036   GtkAdjustment *adj;
9037   static ProgressData *pdata = NULL;
9038
9039   static gchar *items1[] =
9040   {
9041     "Left-Right",
9042     "Right-Left",
9043     "Bottom-Top",
9044     "Top-Bottom"
9045   };
9046
9047     static char *ellipsize_items[] = {
9048     "None",     // PANGO_ELLIPSIZE_NONE,
9049     "Start",    // PANGO_ELLIPSIZE_START,
9050     "Middle",   // PANGO_ELLIPSIZE_MIDDLE,
9051     "End",      // PANGO_ELLIPSIZE_END
9052   };
9053   
9054   if (!pdata)
9055     pdata = g_new0 (ProgressData, 1);
9056
9057   if (!pdata->window)
9058     {
9059       pdata->window = gtk_dialog_new ();
9060
9061       gtk_window_set_screen (GTK_WINDOW (pdata->window),
9062                              gtk_widget_get_screen (widget));
9063
9064       gtk_window_set_resizable (GTK_WINDOW (pdata->window), TRUE);
9065
9066       g_signal_connect (pdata->window, "destroy",
9067                         G_CALLBACK (destroy_progress),
9068                         &pdata);
9069
9070       pdata->timer = 0;
9071
9072       gtk_window_set_title (GTK_WINDOW (pdata->window), "GtkProgressBar");
9073       gtk_container_set_border_width (GTK_CONTAINER (pdata->window), 0);
9074
9075       vbox = gtk_vbox_new (FALSE, 5);
9076       gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
9077       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (pdata->window)->vbox), 
9078                           vbox, FALSE, TRUE, 0);
9079
9080       frame = gtk_frame_new ("Progress");
9081       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
9082
9083       vbox2 = gtk_vbox_new (FALSE, 5);
9084       gtk_container_add (GTK_CONTAINER (frame), vbox2);
9085
9086       align = gtk_alignment_new (0.5, 0.5, 0, 0);
9087       gtk_box_pack_start (GTK_BOX (vbox2), align, FALSE, FALSE, 5);
9088
9089       adj = (GtkAdjustment *) gtk_adjustment_new (0, 1, 300, 0, 0, 0);
9090       g_signal_connect (adj, "value_changed",
9091                         G_CALLBACK (progress_value_changed), pdata);
9092
9093       pdata->pbar = g_object_new (GTK_TYPE_PROGRESS_BAR,
9094                                     "adjustment", adj,
9095                                     "ellipsize", PANGO_ELLIPSIZE_MIDDLE,
9096                                     NULL);
9097       gtk_progress_bar_set_text (GTK_PROGRESS_BAR (pdata->pbar),
9098                                       "%v from [%l,%u] (=%p%%)");
9099       gtk_container_add (GTK_CONTAINER (align), pdata->pbar);
9100       pdata->timer = g_timeout_add (100, (GSourceFunc)progress_timeout, pdata);
9101
9102       align = gtk_alignment_new (0.5, 0.5, 0, 0);
9103       gtk_box_pack_start (GTK_BOX (vbox2), align, FALSE, FALSE, 5);
9104
9105       hbox = gtk_hbox_new (FALSE, 5);
9106       gtk_container_add (GTK_CONTAINER (align), hbox);
9107       label = gtk_label_new ("Label updated by user :"); 
9108       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
9109       pdata->label = gtk_label_new ("");
9110       gtk_box_pack_start (GTK_BOX (hbox), pdata->label, FALSE, TRUE, 0);
9111
9112       frame = gtk_frame_new ("Options");
9113       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
9114
9115       vbox2 = gtk_vbox_new (FALSE, 5);
9116       gtk_container_add (GTK_CONTAINER (frame), vbox2);
9117
9118       tab = gtk_table_new (7, 2, FALSE);
9119       gtk_box_pack_start (GTK_BOX (vbox2), tab, FALSE, TRUE, 0);
9120
9121       label = gtk_label_new ("Orientation :");
9122       gtk_table_attach (GTK_TABLE (tab), label, 0, 1, 0, 1,
9123                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
9124                         5, 5);
9125       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
9126
9127       pdata->omenu1 = build_option_menu (items1, 4, 0,
9128                                          progressbar_toggle_orientation,
9129                                          pdata);
9130       hbox = gtk_hbox_new (FALSE, 0);
9131       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 0, 1,
9132                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
9133                         5, 5);
9134       gtk_box_pack_start (GTK_BOX (hbox), pdata->omenu1, TRUE, TRUE, 0);
9135       
9136       check = gtk_check_button_new_with_label ("Show text");
9137       g_signal_connect (check, "clicked",
9138                         G_CALLBACK (toggle_show_text),
9139                         pdata);
9140       gtk_table_attach (GTK_TABLE (tab), check, 0, 1, 1, 2,
9141                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
9142                         5, 5);
9143
9144       hbox = gtk_hbox_new (FALSE, 0);
9145       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 1, 2,
9146                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
9147                         5, 5);
9148
9149       label = gtk_label_new ("Format : ");
9150       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
9151
9152       pdata->entry = gtk_entry_new ();
9153       g_signal_connect (pdata->entry, "changed",
9154                         G_CALLBACK (entry_changed),
9155                         pdata);
9156       gtk_box_pack_start (GTK_BOX (hbox), pdata->entry, TRUE, TRUE, 0);
9157       gtk_entry_set_text (GTK_ENTRY (pdata->entry), "%v from [%l,%u] (=%p%%)");
9158       gtk_widget_set_size_request (pdata->entry, 100, -1);
9159       gtk_widget_set_sensitive (pdata->entry, FALSE);
9160
9161       label = gtk_label_new ("Text align :");
9162       gtk_table_attach (GTK_TABLE (tab), label, 0, 1, 2, 3,
9163                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
9164                         5, 5);
9165       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
9166
9167       hbox = gtk_hbox_new (FALSE, 0);
9168       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 2, 3,
9169                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
9170                         5, 5);
9171
9172       label = gtk_label_new ("x :");
9173       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 5);
9174       
9175       adj = (GtkAdjustment *) gtk_adjustment_new (0.5, 0, 1, 0.1, 0.1, 0);
9176       pdata->x_align_spin = gtk_spin_button_new (adj, 0, 1);
9177       g_signal_connect (adj, "value_changed",
9178                         G_CALLBACK (adjust_align), pdata);
9179       gtk_box_pack_start (GTK_BOX (hbox), pdata->x_align_spin, FALSE, TRUE, 0);
9180       gtk_widget_set_sensitive (pdata->x_align_spin, FALSE);
9181
9182       label = gtk_label_new ("y :");
9183       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 5);
9184
9185       adj = (GtkAdjustment *) gtk_adjustment_new (0.5, 0, 1, 0.1, 0.1, 0);
9186       pdata->y_align_spin = gtk_spin_button_new (adj, 0, 1);
9187       g_signal_connect (adj, "value_changed",
9188                         G_CALLBACK (adjust_align), pdata);
9189       gtk_box_pack_start (GTK_BOX (hbox), pdata->y_align_spin, FALSE, TRUE, 0);
9190       gtk_widget_set_sensitive (pdata->y_align_spin, FALSE);
9191
9192       label = gtk_label_new ("Ellipsize text :");
9193       gtk_table_attach (GTK_TABLE (tab), label, 0, 1, 10, 11,
9194                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
9195                         5, 5);
9196       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
9197       pdata->elmenu = build_option_menu (ellipsize_items,
9198                                          sizeof (ellipsize_items) / sizeof (ellipsize_items[0]),
9199                                          2, // PANGO_ELLIPSIZE_MIDDLE
9200                                          progressbar_toggle_ellipsize,
9201                                          pdata);
9202       hbox = gtk_hbox_new (FALSE, 0);
9203       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 10, 11,
9204                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
9205                         5, 5);
9206       gtk_box_pack_start (GTK_BOX (hbox), pdata->elmenu, TRUE, TRUE, 0);
9207
9208       check = gtk_check_button_new_with_label ("Activity mode");
9209       g_signal_connect (check, "clicked",
9210                         G_CALLBACK (toggle_activity_mode), pdata);
9211       gtk_table_attach (GTK_TABLE (tab), check, 0, 1, 15, 16,
9212                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
9213                         5, 5);
9214
9215       button = gtk_button_new_with_label ("close");
9216       g_signal_connect_swapped (button, "clicked",
9217                                 G_CALLBACK (gtk_widget_destroy),
9218                                 pdata->window);
9219       gtk_widget_set_can_default (button, TRUE);
9220       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (pdata->window)->action_area), 
9221                           button, TRUE, TRUE, 0);
9222       gtk_widget_grab_default (button);
9223     }
9224
9225   if (!gtk_widget_get_visible (pdata->window))
9226     gtk_widget_show_all (pdata->window);
9227   else
9228     gtk_widget_destroy (pdata->window);
9229 }
9230
9231 /*
9232  * Properties
9233  */
9234
9235 typedef struct {
9236   int x;
9237   int y;
9238   gboolean found;
9239   gboolean first;
9240   GtkWidget *res_widget;
9241 } FindWidgetData;
9242
9243 static void
9244 find_widget (GtkWidget *widget, FindWidgetData *data)
9245 {
9246   GtkAllocation new_allocation;
9247   gint x_offset = 0;
9248   gint y_offset = 0;
9249
9250   new_allocation = widget->allocation;
9251
9252   if (data->found || !gtk_widget_get_mapped (widget))
9253     return;
9254
9255   /* Note that in the following code, we only count the
9256    * position as being inside a WINDOW widget if it is inside
9257    * widget->window; points that are outside of widget->window
9258    * but within the allocation are not counted. This is consistent
9259    * with the way we highlight drag targets.
9260    */
9261   if (gtk_widget_get_has_window (widget))
9262     {
9263       new_allocation.x = 0;
9264       new_allocation.y = 0;
9265     }
9266   
9267   if (widget->parent && !data->first)
9268     {
9269       GdkWindow *window = widget->window;
9270       while (window != widget->parent->window)
9271         {
9272           gint tx, ty, twidth, theight;
9273           gdk_drawable_get_size (window, &twidth, &theight);
9274
9275           if (new_allocation.x < 0)
9276             {
9277               new_allocation.width += new_allocation.x;
9278               new_allocation.x = 0;
9279             }
9280           if (new_allocation.y < 0)
9281             {
9282               new_allocation.height += new_allocation.y;
9283               new_allocation.y = 0;
9284             }
9285           if (new_allocation.x + new_allocation.width > twidth)
9286             new_allocation.width = twidth - new_allocation.x;
9287           if (new_allocation.y + new_allocation.height > theight)
9288             new_allocation.height = theight - new_allocation.y;
9289
9290           gdk_window_get_position (window, &tx, &ty);
9291           new_allocation.x += tx;
9292           x_offset += tx;
9293           new_allocation.y += ty;
9294           y_offset += ty;
9295           
9296           window = gdk_window_get_parent (window);
9297         }
9298     }
9299
9300   if ((data->x >= new_allocation.x) && (data->y >= new_allocation.y) &&
9301       (data->x < new_allocation.x + new_allocation.width) && 
9302       (data->y < new_allocation.y + new_allocation.height))
9303     {
9304       /* First, check if the drag is in a valid drop site in
9305        * one of our children 
9306        */
9307       if (GTK_IS_CONTAINER (widget))
9308         {
9309           FindWidgetData new_data = *data;
9310           
9311           new_data.x -= x_offset;
9312           new_data.y -= y_offset;
9313           new_data.found = FALSE;
9314           new_data.first = FALSE;
9315           
9316           gtk_container_forall (GTK_CONTAINER (widget),
9317                                 (GtkCallback)find_widget,
9318                                 &new_data);
9319           
9320           data->found = new_data.found;
9321           if (data->found)
9322             data->res_widget = new_data.res_widget;
9323         }
9324
9325       /* If not, and this widget is registered as a drop site, check to
9326        * emit "drag_motion" to check if we are actually in
9327        * a drop site.
9328        */
9329       if (!data->found)
9330         {
9331           data->found = TRUE;
9332           data->res_widget = widget;
9333         }
9334     }
9335 }
9336
9337 static GtkWidget *
9338 find_widget_at_pointer (GdkDisplay *display)
9339 {
9340   GtkWidget *widget = NULL;
9341   GdkWindow *pointer_window;
9342   gint x, y;
9343   FindWidgetData data;
9344  
9345  pointer_window = gdk_display_get_window_at_pointer (display, NULL, NULL);
9346  
9347  if (pointer_window)
9348    {
9349      gpointer widget_ptr;
9350
9351      gdk_window_get_user_data (pointer_window, &widget_ptr);
9352      widget = widget_ptr;
9353    }
9354
9355  if (widget)
9356    {
9357      gdk_window_get_pointer (widget->window,
9358                              &x, &y, NULL);
9359      
9360      data.x = x;
9361      data.y = y;
9362      data.found = FALSE;
9363      data.first = TRUE;
9364
9365      find_widget (widget, &data);
9366      if (data.found)
9367        return data.res_widget;
9368      return widget;
9369    }
9370  return NULL;
9371 }
9372
9373 struct PropertiesData {
9374   GtkWidget **window;
9375   GdkCursor *cursor;
9376   gboolean in_query;
9377   gint handler;
9378 };
9379
9380 static void
9381 destroy_properties (GtkWidget             *widget,
9382                     struct PropertiesData *data)
9383 {
9384   if (data->window)
9385     {
9386       *data->window = NULL;
9387       data->window = NULL;
9388     }
9389
9390   if (data->cursor)
9391     {
9392       gdk_cursor_unref (data->cursor);
9393       data->cursor = NULL;
9394     }
9395
9396   if (data->handler)
9397     {
9398       g_signal_handler_disconnect (widget, data->handler);
9399       data->handler = 0;
9400     }
9401
9402   g_free (data);
9403 }
9404
9405 static gint
9406 property_query_event (GtkWidget        *widget,
9407                       GdkEvent         *event,
9408                       struct PropertiesData *data)
9409 {
9410   GtkWidget *res_widget = NULL;
9411
9412   if (!data->in_query)
9413     return FALSE;
9414   
9415   if (event->type == GDK_BUTTON_RELEASE)
9416     {
9417       gtk_grab_remove (widget);
9418       gdk_display_pointer_ungrab (gtk_widget_get_display (widget),
9419                                   GDK_CURRENT_TIME);
9420       
9421       res_widget = find_widget_at_pointer (gtk_widget_get_display (widget));
9422       if (res_widget)
9423         {
9424           g_object_set_data (G_OBJECT (res_widget), "prop-editor-screen",
9425                              gtk_widget_get_screen (widget));
9426           create_prop_editor (G_OBJECT (res_widget), 0);
9427         }
9428
9429       data->in_query = FALSE;
9430     }
9431   return FALSE;
9432 }
9433
9434
9435 static void
9436 query_properties (GtkButton *button,
9437                   struct PropertiesData *data)
9438 {
9439   gint failure;
9440
9441   g_signal_connect (button, "event",
9442                     G_CALLBACK (property_query_event), data);
9443
9444
9445   if (!data->cursor)
9446     data->cursor = gdk_cursor_new_for_display (gtk_widget_get_display (GTK_WIDGET (button)),
9447                                                GDK_TARGET);
9448   
9449   failure = gdk_pointer_grab (GTK_WIDGET (button)->window,
9450                               TRUE,
9451                               GDK_BUTTON_RELEASE_MASK,
9452                               NULL,
9453                               data->cursor,
9454                               GDK_CURRENT_TIME);
9455
9456   gtk_grab_add (GTK_WIDGET (button));
9457
9458   data->in_query = TRUE;
9459 }
9460
9461 static void
9462 create_properties (GtkWidget *widget)
9463 {
9464   static GtkWidget *window = NULL;
9465   GtkWidget *button;
9466   GtkWidget *vbox;
9467   GtkWidget *label;
9468   struct PropertiesData *data;
9469
9470   data = g_new (struct PropertiesData, 1);
9471   data->window = &window;
9472   data->in_query = FALSE;
9473   data->cursor = NULL;
9474   data->handler = 0;
9475
9476   if (!window)
9477     {
9478       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9479
9480       gtk_window_set_screen (GTK_WINDOW (window),
9481                              gtk_widget_get_screen (widget));      
9482
9483       data->handler = g_signal_connect (window, "destroy",
9484                                         G_CALLBACK (destroy_properties),
9485                                         data);
9486
9487       gtk_window_set_title (GTK_WINDOW (window), "test properties");
9488       gtk_container_set_border_width (GTK_CONTAINER (window), 10);
9489
9490       vbox = gtk_vbox_new (FALSE, 1);
9491       gtk_container_add (GTK_CONTAINER (window), vbox);
9492             
9493       label = gtk_label_new ("This is just a dumb test to test properties.\nIf you need a generic module, get GLE.");
9494       gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
9495       
9496       button = gtk_button_new_with_label ("Query properties");
9497       gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
9498       g_signal_connect (button, "clicked",
9499                         G_CALLBACK (query_properties),
9500                         data);
9501     }
9502
9503   if (!gtk_widget_get_visible (window))
9504     gtk_widget_show_all (window);
9505   else
9506     gtk_widget_destroy (window);
9507   
9508 }
9509
9510 struct SnapshotData {
9511   GtkWidget *toplevel_button;
9512   GtkWidget **window;
9513   GdkCursor *cursor;
9514   gboolean in_query;
9515   gboolean is_toplevel;
9516   gint handler;
9517 };
9518
9519 static void
9520 destroy_snapshot_data (GtkWidget             *widget,
9521                        struct SnapshotData *data)
9522 {
9523   if (*data->window)
9524     *data->window = NULL;
9525   
9526   if (data->cursor)
9527     {
9528       gdk_cursor_unref (data->cursor);
9529       data->cursor = NULL;
9530     }
9531
9532   if (data->handler)
9533     {
9534       g_signal_handler_disconnect (widget, data->handler);
9535       data->handler = 0;
9536     }
9537
9538   g_free (data);
9539 }
9540
9541 static gint
9542 snapshot_widget_event (GtkWidget               *widget,
9543                        GdkEvent        *event,
9544                        struct SnapshotData *data)
9545 {
9546   GtkWidget *res_widget = NULL;
9547
9548   if (!data->in_query)
9549     return FALSE;
9550   
9551   if (event->type == GDK_BUTTON_RELEASE)
9552     {
9553       gtk_grab_remove (widget);
9554       gdk_display_pointer_ungrab (gtk_widget_get_display (widget),
9555                                   GDK_CURRENT_TIME);
9556       
9557       res_widget = find_widget_at_pointer (gtk_widget_get_display (widget));
9558       if (data->is_toplevel && res_widget)
9559         res_widget = gtk_widget_get_toplevel (res_widget);
9560       if (res_widget)
9561         {
9562           GdkPixmap *pixmap;
9563           GtkWidget *window, *image;
9564
9565           window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9566           pixmap = gtk_widget_get_snapshot (res_widget, NULL);
9567           gtk_widget_realize (window);
9568           if (gdk_drawable_get_depth (window->window) != gdk_drawable_get_depth (pixmap))
9569             {
9570               /* this branch is needed to convert ARGB -> RGB */
9571               int width, height;
9572               GdkPixbuf *pixbuf;
9573               gdk_drawable_get_size (pixmap, &width, &height);
9574               pixbuf = gdk_pixbuf_get_from_drawable (NULL, pixmap,
9575                                                      gtk_widget_get_colormap (res_widget),
9576                                                      0, 0,
9577                                                      0, 0,
9578                                                      width, height);
9579               image = gtk_image_new_from_pixbuf (pixbuf);
9580               g_object_unref (pixbuf);
9581             }
9582           else
9583             image = gtk_image_new_from_pixmap (pixmap, NULL);
9584           gtk_container_add (GTK_CONTAINER (window), image);
9585           g_object_unref (pixmap);
9586           gtk_widget_show_all (window);
9587         }
9588
9589       data->in_query = FALSE;
9590     }
9591   return FALSE;
9592 }
9593
9594
9595 static void
9596 snapshot_widget (GtkButton *button,
9597                  struct SnapshotData *data)
9598 {
9599   gint failure;
9600
9601   g_signal_connect (button, "event",
9602                     G_CALLBACK (snapshot_widget_event), data);
9603
9604   data->is_toplevel = GTK_WIDGET (button) == data->toplevel_button;
9605   
9606   if (!data->cursor)
9607     data->cursor = gdk_cursor_new_for_display (gtk_widget_get_display (GTK_WIDGET (button)),
9608                                                GDK_TARGET);
9609   
9610   failure = gdk_pointer_grab (GTK_WIDGET (button)->window,
9611                               TRUE,
9612                               GDK_BUTTON_RELEASE_MASK,
9613                               NULL,
9614                               data->cursor,
9615                               GDK_CURRENT_TIME);
9616
9617   gtk_grab_add (GTK_WIDGET (button));
9618
9619   data->in_query = TRUE;
9620 }
9621
9622 static void
9623 create_snapshot (GtkWidget *widget)
9624 {
9625   static GtkWidget *window = NULL;
9626   GtkWidget *button;
9627   GtkWidget *vbox;
9628   struct SnapshotData *data;
9629
9630   data = g_new (struct SnapshotData, 1);
9631   data->window = &window;
9632   data->in_query = FALSE;
9633   data->cursor = NULL;
9634   data->handler = 0;
9635
9636   if (!window)
9637     {
9638       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9639
9640       gtk_window_set_screen (GTK_WINDOW (window),
9641                              gtk_widget_get_screen (widget));      
9642
9643       data->handler = g_signal_connect (window, "destroy",
9644                                         G_CALLBACK (destroy_snapshot_data),
9645                                         data);
9646
9647       gtk_window_set_title (GTK_WINDOW (window), "test snapshot");
9648       gtk_container_set_border_width (GTK_CONTAINER (window), 10);
9649
9650       vbox = gtk_vbox_new (FALSE, 1);
9651       gtk_container_add (GTK_CONTAINER (window), vbox);
9652             
9653       button = gtk_button_new_with_label ("Snapshot widget");
9654       gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
9655       g_signal_connect (button, "clicked",
9656                         G_CALLBACK (snapshot_widget),
9657                         data);
9658       
9659       button = gtk_button_new_with_label ("Snapshot toplevel");
9660       data->toplevel_button = button;
9661       gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
9662       g_signal_connect (button, "clicked",
9663                         G_CALLBACK (snapshot_widget),
9664                         data);
9665     }
9666
9667   if (!gtk_widget_get_visible (window))
9668     gtk_widget_show_all (window);
9669   else
9670     gtk_widget_destroy (window);
9671   
9672 }
9673
9674 /*
9675  * Selection Test
9676  */
9677
9678 void
9679 selection_test_received (GtkWidget        *tree_view,
9680                          GtkSelectionData *data)
9681 {
9682   GtkTreeModel *model;
9683   GtkListStore *store;
9684   GdkAtom *atoms;
9685   int i, l;
9686
9687   if (data->length < 0)
9688     {
9689       g_print ("Selection retrieval failed\n");
9690       return;
9691     }
9692   if (data->type != GDK_SELECTION_TYPE_ATOM)
9693     {
9694       g_print ("Selection \"TARGETS\" was not returned as atoms!\n");
9695       return;
9696     }
9697
9698   /* Clear out any current list items */
9699
9700   model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree_view));
9701   store = GTK_LIST_STORE (model);
9702   gtk_list_store_clear (store);
9703
9704   /* Add new items to list */
9705
9706   atoms = (GdkAtom *)data->data;
9707
9708   l = data->length / sizeof (GdkAtom);
9709   for (i = 0; i < l; i++)
9710     {
9711       char *name;
9712       GtkTreeIter iter;
9713
9714       name = gdk_atom_name (atoms[i]);
9715       if (name != NULL)
9716         {
9717           gtk_list_store_insert_with_values (store, &iter, i, 0, name, -1);
9718           g_free (name);
9719         }
9720       else
9721        gtk_list_store_insert_with_values (store, &iter, i, 0,  "(bad atom)", -1);
9722     }
9723
9724   return;
9725 }
9726
9727 void
9728 selection_test_get_targets (GtkWidget *widget, GtkWidget *tree_view)
9729 {
9730   static GdkAtom targets_atom = GDK_NONE;
9731
9732   if (targets_atom == GDK_NONE)
9733     targets_atom = gdk_atom_intern ("TARGETS", FALSE);
9734
9735   gtk_selection_convert (tree_view, GDK_SELECTION_PRIMARY, targets_atom,
9736                          GDK_CURRENT_TIME);
9737 }
9738
9739 void
9740 create_selection_test (GtkWidget *widget)
9741 {
9742   static GtkWidget *window = NULL;
9743   GtkWidget *button;
9744   GtkWidget *vbox;
9745   GtkWidget *scrolled_win;
9746   GtkListStore* store;
9747   GtkWidget *tree_view;
9748   GtkTreeViewColumn *column;
9749   GtkCellRenderer *renderer;
9750   GtkWidget *label;
9751
9752   if (!window)
9753     {
9754       window = gtk_dialog_new ();
9755       
9756       gtk_window_set_screen (GTK_WINDOW (window),
9757                              gtk_widget_get_screen (widget));
9758
9759       g_signal_connect (window, "destroy",
9760                         G_CALLBACK (gtk_widget_destroyed),
9761                         &window);
9762
9763       gtk_window_set_title (GTK_WINDOW (window), "Selection Test");
9764       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
9765
9766       /* Create the list */
9767
9768       vbox = gtk_vbox_new (FALSE, 5);
9769       gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
9770       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), vbox,
9771                           TRUE, TRUE, 0);
9772
9773       label = gtk_label_new ("Gets available targets for current selection");
9774       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
9775
9776       scrolled_win = gtk_scrolled_window_new (NULL, NULL);
9777       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
9778                                       GTK_POLICY_AUTOMATIC, 
9779                                       GTK_POLICY_AUTOMATIC);
9780       gtk_box_pack_start (GTK_BOX (vbox), scrolled_win, TRUE, TRUE, 0);
9781       gtk_widget_set_size_request (scrolled_win, 100, 200);
9782
9783       store = gtk_list_store_new (1, G_TYPE_STRING);
9784       tree_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store));
9785       gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_win), tree_view);
9786
9787       renderer = gtk_cell_renderer_text_new ();
9788       column = gtk_tree_view_column_new_with_attributes ("Target", renderer,
9789                                                          "text", 0, NULL);
9790       gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), column);
9791
9792       g_signal_connect (tree_view, "selection_received",
9793                         G_CALLBACK (selection_test_received), NULL);
9794
9795       /* .. And create some buttons */
9796       button = gtk_button_new_with_label ("Get Targets");
9797       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area),
9798                           button, TRUE, TRUE, 0);
9799
9800       g_signal_connect (button, "clicked",
9801                         G_CALLBACK (selection_test_get_targets), tree_view);
9802
9803       button = gtk_button_new_with_label ("Quit");
9804       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area),
9805                           button, TRUE, TRUE, 0);
9806
9807       g_signal_connect_swapped (button, "clicked",
9808                                 G_CALLBACK (gtk_widget_destroy),
9809                                 window);
9810     }
9811
9812   if (!gtk_widget_get_visible (window))
9813     gtk_widget_show_all (window);
9814   else
9815     gtk_widget_destroy (window);
9816 }
9817
9818 /*
9819  * Test scrolling
9820  */
9821
9822 static int scroll_test_pos = 0.0;
9823
9824 static gint
9825 scroll_test_expose (GtkWidget *widget, GdkEventExpose *event,
9826                     GtkAdjustment *adj)
9827 {
9828   gint i,j;
9829   gint imin, imax, jmin, jmax;
9830   
9831   imin = (event->area.x) / 10;
9832   imax = (event->area.x + event->area.width + 9) / 10;
9833
9834   jmin = ((int)adj->value + event->area.y) / 10;
9835   jmax = ((int)adj->value + event->area.y + event->area.height + 9) / 10;
9836
9837   gdk_window_clear_area (widget->window,
9838                          event->area.x, event->area.y,
9839                          event->area.width, event->area.height);
9840
9841   for (i=imin; i<imax; i++)
9842     for (j=jmin; j<jmax; j++)
9843       if ((i+j) % 2)
9844         gdk_draw_rectangle (widget->window, 
9845                             widget->style->black_gc,
9846                             TRUE,
9847                             10*i, 10*j - (int)adj->value, 1+i%10, 1+j%10);
9848
9849   return TRUE;
9850 }
9851
9852 static gint
9853 scroll_test_scroll (GtkWidget *widget, GdkEventScroll *event,
9854                     GtkAdjustment *adj)
9855 {
9856   gdouble new_value = adj->value + ((event->direction == GDK_SCROLL_UP) ?
9857                                     -adj->page_increment / 2:
9858                                     adj->page_increment / 2);
9859   new_value = CLAMP (new_value, adj->lower, adj->upper - adj->page_size);
9860   gtk_adjustment_set_value (adj, new_value);  
9861   
9862   return TRUE;
9863 }
9864
9865 static void
9866 scroll_test_configure (GtkWidget *widget, GdkEventConfigure *event,
9867                        GtkAdjustment *adj)
9868 {
9869   adj->page_increment = 0.9 * widget->allocation.height;
9870   adj->page_size = widget->allocation.height;
9871
9872   g_signal_emit_by_name (adj, "changed");
9873 }
9874
9875 static void
9876 scroll_test_adjustment_changed (GtkAdjustment *adj, GtkWidget *widget)
9877 {
9878   /* gint source_min = (int)adj->value - scroll_test_pos; */
9879   gint dy;
9880
9881   dy = scroll_test_pos - (int)adj->value;
9882   scroll_test_pos = adj->value;
9883
9884   if (!gtk_widget_is_drawable (widget))
9885     return;
9886   gdk_window_scroll (widget->window, 0, dy);
9887   gdk_window_process_updates (widget->window, FALSE);
9888 }
9889
9890
9891 void
9892 create_scroll_test (GtkWidget *widget)
9893 {
9894   static GtkWidget *window = NULL;
9895   GtkWidget *hbox;
9896   GtkWidget *drawing_area;
9897   GtkWidget *scrollbar;
9898   GtkWidget *button;
9899   GtkAdjustment *adj;
9900   GdkGeometry geometry;
9901   GdkWindowHints geometry_mask;
9902
9903   if (!window)
9904     {
9905       window = gtk_dialog_new ();
9906
9907       gtk_window_set_screen (GTK_WINDOW (window),
9908                              gtk_widget_get_screen (widget));
9909
9910       g_signal_connect (window, "destroy",
9911                         G_CALLBACK (gtk_widget_destroyed),
9912                         &window);
9913
9914       gtk_window_set_title (GTK_WINDOW (window), "Scroll Test");
9915       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
9916
9917       hbox = gtk_hbox_new (FALSE, 0);
9918       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), hbox,
9919                           TRUE, TRUE, 0);
9920       gtk_widget_show (hbox);
9921
9922       drawing_area = gtk_drawing_area_new ();
9923       gtk_widget_set_size_request (drawing_area, 200, 200);
9924       gtk_box_pack_start (GTK_BOX (hbox), drawing_area, TRUE, TRUE, 0);
9925       gtk_widget_show (drawing_area);
9926
9927       gtk_widget_set_events (drawing_area, GDK_EXPOSURE_MASK | GDK_SCROLL_MASK);
9928
9929       adj = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 1000.0, 1.0, 180.0, 200.0));
9930       scroll_test_pos = 0.0;
9931
9932       scrollbar = gtk_vscrollbar_new (adj);
9933       gtk_box_pack_start (GTK_BOX (hbox), scrollbar, FALSE, FALSE, 0);
9934       gtk_widget_show (scrollbar);
9935
9936       g_signal_connect (drawing_area, "expose_event",
9937                         G_CALLBACK (scroll_test_expose), adj);
9938       g_signal_connect (drawing_area, "configure_event",
9939                         G_CALLBACK (scroll_test_configure), adj);
9940       g_signal_connect (drawing_area, "scroll_event",
9941                         G_CALLBACK (scroll_test_scroll), adj);
9942       
9943       g_signal_connect (adj, "value_changed",
9944                         G_CALLBACK (scroll_test_adjustment_changed),
9945                         drawing_area);
9946       
9947       /* .. And create some buttons */
9948
9949       button = gtk_button_new_with_label ("Quit");
9950       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area),
9951                           button, TRUE, TRUE, 0);
9952
9953       g_signal_connect_swapped (button, "clicked",
9954                                 G_CALLBACK (gtk_widget_destroy),
9955                                 window);
9956       gtk_widget_show (button);
9957
9958       /* Set up gridded geometry */
9959
9960       geometry_mask = GDK_HINT_MIN_SIZE | 
9961                        GDK_HINT_BASE_SIZE | 
9962                        GDK_HINT_RESIZE_INC;
9963
9964       geometry.min_width = 20;
9965       geometry.min_height = 20;
9966       geometry.base_width = 0;
9967       geometry.base_height = 0;
9968       geometry.width_inc = 10;
9969       geometry.height_inc = 10;
9970       
9971       gtk_window_set_geometry_hints (GTK_WINDOW (window),
9972                                drawing_area, &geometry, geometry_mask);
9973     }
9974
9975   if (!gtk_widget_get_visible (window))
9976     gtk_widget_show (window);
9977   else
9978     gtk_widget_destroy (window);
9979 }
9980
9981 /*
9982  * Timeout Test
9983  */
9984
9985 static int timer = 0;
9986
9987 gint
9988 timeout_test (GtkWidget *label)
9989 {
9990   static int count = 0;
9991   static char buffer[32];
9992
9993   sprintf (buffer, "count: %d", ++count);
9994   gtk_label_set_text (GTK_LABEL (label), buffer);
9995
9996   return TRUE;
9997 }
9998
9999 void
10000 start_timeout_test (GtkWidget *widget,
10001                     GtkWidget *label)
10002 {
10003   if (!timer)
10004     {
10005       timer = g_timeout_add (100, (GSourceFunc)timeout_test, label);
10006     }
10007 }
10008
10009 void
10010 stop_timeout_test (GtkWidget *widget,
10011                    gpointer   data)
10012 {
10013   if (timer)
10014     {
10015       g_source_remove (timer);
10016       timer = 0;
10017     }
10018 }
10019
10020 void
10021 destroy_timeout_test (GtkWidget  *widget,
10022                       GtkWidget **window)
10023 {
10024   stop_timeout_test (NULL, NULL);
10025
10026   *window = NULL;
10027 }
10028
10029 void
10030 create_timeout_test (GtkWidget *widget)
10031 {
10032   static GtkWidget *window = NULL;
10033   GtkWidget *button;
10034   GtkWidget *label;
10035
10036   if (!window)
10037     {
10038       window = gtk_dialog_new ();
10039
10040       gtk_window_set_screen (GTK_WINDOW (window),
10041                              gtk_widget_get_screen (widget));
10042
10043       g_signal_connect (window, "destroy",
10044                         G_CALLBACK (destroy_timeout_test),
10045                         &window);
10046
10047       gtk_window_set_title (GTK_WINDOW (window), "Timeout Test");
10048       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
10049
10050       label = gtk_label_new ("count: 0");
10051       gtk_misc_set_padding (GTK_MISC (label), 10, 10);
10052       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
10053                           label, TRUE, TRUE, 0);
10054       gtk_widget_show (label);
10055
10056       button = gtk_button_new_with_label ("close");
10057       g_signal_connect_swapped (button, "clicked",
10058                                 G_CALLBACK (gtk_widget_destroy),
10059                                 window);
10060       gtk_widget_set_can_default (button, TRUE);
10061       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
10062                           button, TRUE, TRUE, 0);
10063       gtk_widget_grab_default (button);
10064       gtk_widget_show (button);
10065
10066       button = gtk_button_new_with_label ("start");
10067       g_signal_connect (button, "clicked",
10068                         G_CALLBACK(start_timeout_test),
10069                         label);
10070       gtk_widget_set_can_default (button, TRUE);
10071       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
10072                           button, TRUE, TRUE, 0);
10073       gtk_widget_show (button);
10074
10075       button = gtk_button_new_with_label ("stop");
10076       g_signal_connect (button, "clicked",
10077                         G_CALLBACK (stop_timeout_test),
10078                         NULL);
10079       gtk_widget_set_can_default (button, TRUE);
10080       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
10081                           button, TRUE, TRUE, 0);
10082       gtk_widget_show (button);
10083     }
10084
10085   if (!gtk_widget_get_visible (window))
10086     gtk_widget_show (window);
10087   else
10088     gtk_widget_destroy (window);
10089 }
10090
10091 /*
10092  * Idle Test
10093  */
10094
10095 static int idle_id = 0;
10096
10097 static gint
10098 idle_test (GtkWidget *label)
10099 {
10100   static int count = 0;
10101   static char buffer[32];
10102
10103   sprintf (buffer, "count: %d", ++count);
10104   gtk_label_set_text (GTK_LABEL (label), buffer);
10105
10106   return TRUE;
10107 }
10108
10109 static void
10110 start_idle_test (GtkWidget *widget,
10111                  GtkWidget *label)
10112 {
10113   if (!idle_id)
10114     {
10115       idle_id = g_idle_add ((GSourceFunc) idle_test, label);
10116     }
10117 }
10118
10119 static void
10120 stop_idle_test (GtkWidget *widget,
10121                 gpointer   data)
10122 {
10123   if (idle_id)
10124     {
10125       g_source_remove (idle_id);
10126       idle_id = 0;
10127     }
10128 }
10129
10130 static void
10131 destroy_idle_test (GtkWidget  *widget,
10132                    GtkWidget **window)
10133 {
10134   stop_idle_test (NULL, NULL);
10135
10136   *window = NULL;
10137 }
10138
10139 static void
10140 toggle_idle_container (GObject *button,
10141                        GtkContainer *container)
10142 {
10143   gtk_container_set_resize_mode (container, GPOINTER_TO_INT (g_object_get_data (button, "user_data")));
10144 }
10145
10146 static void
10147 create_idle_test (GtkWidget *widget)
10148 {
10149   static GtkWidget *window = NULL;
10150   GtkWidget *button;
10151   GtkWidget *label;
10152   GtkWidget *container;
10153
10154   if (!window)
10155     {
10156       GtkWidget *button2;
10157       GtkWidget *frame;
10158       GtkWidget *box;
10159
10160       window = gtk_dialog_new ();
10161
10162       gtk_window_set_screen (GTK_WINDOW (window),
10163                              gtk_widget_get_screen (widget));
10164
10165       g_signal_connect (window, "destroy",
10166                         G_CALLBACK (destroy_idle_test),
10167                         &window);
10168
10169       gtk_window_set_title (GTK_WINDOW (window), "Idle Test");
10170       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
10171
10172       label = gtk_label_new ("count: 0");
10173       gtk_misc_set_padding (GTK_MISC (label), 10, 10);
10174       gtk_widget_show (label);
10175       
10176       container =
10177         g_object_new (GTK_TYPE_HBOX,
10178                         "visible", TRUE,
10179                         /* "GtkContainer::child", g_object_new (GTK_TYPE_HBOX,
10180                          * "GtkWidget::visible", TRUE,
10181                          */
10182                          "child", label,
10183                         /* NULL), */
10184                         NULL);
10185       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
10186                           container, TRUE, TRUE, 0);
10187
10188       frame =
10189         g_object_new (GTK_TYPE_FRAME,
10190                         "border_width", 5,
10191                         "label", "Label Container",
10192                         "visible", TRUE,
10193                         "parent", GTK_DIALOG (window)->vbox,
10194                         NULL);
10195       box =
10196         g_object_new (GTK_TYPE_VBOX,
10197                         "visible", TRUE,
10198                         "parent", frame,
10199                         NULL);
10200       button =
10201         g_object_connect (g_object_new (GTK_TYPE_RADIO_BUTTON,
10202                                           "label", "Resize-Parent",
10203                                           "user_data", (void*)GTK_RESIZE_PARENT,
10204                                           "visible", TRUE,
10205                                           "parent", box,
10206                                           NULL),
10207                           "signal::clicked", toggle_idle_container, container,
10208                           NULL);
10209       button = g_object_new (GTK_TYPE_RADIO_BUTTON,
10210                                "label", "Resize-Queue",
10211                                "user_data", (void*)GTK_RESIZE_QUEUE,
10212                                "group", button,
10213                                "visible", TRUE,
10214                                "parent", box,
10215                                NULL);
10216       g_object_connect (button,
10217                         "signal::clicked", toggle_idle_container, container,
10218                         NULL);
10219       button2 = g_object_new (GTK_TYPE_RADIO_BUTTON,
10220                                 "label", "Resize-Immediate",
10221                                 "user_data", (void*)GTK_RESIZE_IMMEDIATE,
10222                                 NULL);
10223       g_object_connect (button2,
10224                         "signal::clicked", toggle_idle_container, container,
10225                         NULL);
10226       g_object_set (button2,
10227                     "group", button,
10228                     "visible", TRUE,
10229                     "parent", box,
10230                     NULL);
10231
10232       button = gtk_button_new_with_label ("close");
10233       g_signal_connect_swapped (button, "clicked",
10234                                 G_CALLBACK (gtk_widget_destroy),
10235                                 window);
10236       gtk_widget_set_can_default (button, TRUE);
10237       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
10238                           button, TRUE, TRUE, 0);
10239       gtk_widget_grab_default (button);
10240       gtk_widget_show (button);
10241
10242       button = gtk_button_new_with_label ("start");
10243       g_signal_connect (button, "clicked",
10244                         G_CALLBACK (start_idle_test),
10245                         label);
10246       gtk_widget_set_can_default (button, TRUE);
10247       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
10248                           button, TRUE, TRUE, 0);
10249       gtk_widget_show (button);
10250
10251       button = gtk_button_new_with_label ("stop");
10252       g_signal_connect (button, "clicked",
10253                         G_CALLBACK (stop_idle_test),
10254                         NULL);
10255       gtk_widget_set_can_default (button, TRUE);
10256       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
10257                           button, TRUE, TRUE, 0);
10258       gtk_widget_show (button);
10259     }
10260
10261   if (!gtk_widget_get_visible (window))
10262     gtk_widget_show (window);
10263   else
10264     gtk_widget_destroy (window);
10265 }
10266
10267 /*
10268  * rc file test
10269  */
10270
10271 void
10272 reload_all_rc_files (void)
10273 {
10274   static GdkAtom atom_rcfiles = GDK_NONE;
10275
10276   GdkEvent *send_event = gdk_event_new (GDK_CLIENT_EVENT);
10277   int i;
10278   
10279   if (!atom_rcfiles)
10280     atom_rcfiles = gdk_atom_intern("_GTK_READ_RCFILES", FALSE);
10281
10282   for(i = 0; i < 5; i++)
10283     send_event->client.data.l[i] = 0;
10284   send_event->client.data_format = 32;
10285   send_event->client.message_type = atom_rcfiles;
10286   gdk_event_send_clientmessage_toall (send_event);
10287
10288   gdk_event_free (send_event);
10289 }
10290
10291 void
10292 create_rc_file (GtkWidget *widget)
10293 {
10294   static GtkWidget *window = NULL;
10295   GtkWidget *button;
10296   GtkWidget *frame;
10297   GtkWidget *vbox;
10298   GtkWidget *label;
10299
10300   if (!window)
10301     {
10302       window = gtk_dialog_new ();
10303
10304       gtk_window_set_screen (GTK_WINDOW (window),
10305                              gtk_widget_get_screen (widget));
10306
10307       g_signal_connect (window, "destroy",
10308                         G_CALLBACK (gtk_widget_destroyed),
10309                         &window);
10310
10311       frame = gtk_aspect_frame_new ("Testing RC file prioritization", 0.5, 0.5, 0.0, TRUE);
10312       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), frame, FALSE, FALSE, 0);
10313
10314       vbox = gtk_vbox_new (FALSE, 0);
10315       gtk_container_add (GTK_CONTAINER (frame), vbox);
10316       
10317       label = gtk_label_new ("This label should be red");
10318       gtk_widget_set_name (label, "testgtk-red-label");
10319       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
10320
10321       label = gtk_label_new ("This label should be green");
10322       gtk_widget_set_name (label, "testgtk-green-label");
10323       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
10324
10325       label = gtk_label_new ("This label should be blue");
10326       gtk_widget_set_name (label, "testgtk-blue-label");
10327       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
10328
10329       gtk_window_set_title (GTK_WINDOW (window), "Reload Rc file");
10330       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
10331
10332       button = gtk_button_new_with_label ("Reload");
10333       g_signal_connect (button, "clicked",
10334                         G_CALLBACK (gtk_rc_reparse_all), NULL);
10335       gtk_widget_set_can_default (button, TRUE);
10336       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
10337                           button, TRUE, TRUE, 0);
10338       gtk_widget_grab_default (button);
10339
10340       button = gtk_button_new_with_label ("Reload All");
10341       g_signal_connect (button, "clicked",
10342                         G_CALLBACK (reload_all_rc_files), NULL);
10343       gtk_widget_set_can_default (button, TRUE);
10344       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
10345                           button, TRUE, TRUE, 0);
10346
10347       button = gtk_button_new_with_label ("Close");
10348       g_signal_connect_swapped (button, "clicked",
10349                                 G_CALLBACK (gtk_widget_destroy),
10350                                 window);
10351       gtk_widget_set_can_default (button, TRUE);
10352       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
10353                           button, TRUE, TRUE, 0);
10354     }
10355
10356   if (!gtk_widget_get_visible (window))
10357     gtk_widget_show_all (window);
10358   else
10359     gtk_widget_destroy (window);
10360 }
10361
10362 /*
10363  * Test of recursive mainloop
10364  */
10365
10366 void
10367 mainloop_destroyed (GtkWidget *w, GtkWidget **window)
10368 {
10369   *window = NULL;
10370   gtk_main_quit ();
10371 }
10372
10373 void
10374 create_mainloop (GtkWidget *widget)
10375 {
10376   static GtkWidget *window = NULL;
10377   GtkWidget *label;
10378   GtkWidget *button;
10379
10380   if (!window)
10381     {
10382       window = gtk_dialog_new ();
10383
10384       gtk_window_set_screen (GTK_WINDOW (window),
10385                              gtk_widget_get_screen (widget));
10386
10387       gtk_window_set_title (GTK_WINDOW (window), "Test Main Loop");
10388
10389       g_signal_connect (window, "destroy",
10390                         G_CALLBACK (mainloop_destroyed),
10391                         &window);
10392
10393       label = gtk_label_new ("In recursive main loop...");
10394       gtk_misc_set_padding (GTK_MISC(label), 20, 20);
10395
10396       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), label,
10397                           TRUE, TRUE, 0);
10398       gtk_widget_show (label);
10399
10400       button = gtk_button_new_with_label ("Leave");
10401       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), button, 
10402                           FALSE, TRUE, 0);
10403
10404       g_signal_connect_swapped (button, "clicked",
10405                                 G_CALLBACK (gtk_widget_destroy),
10406                                 window);
10407
10408       gtk_widget_set_can_default (button, TRUE);
10409       gtk_widget_grab_default (button);
10410
10411       gtk_widget_show (button);
10412     }
10413
10414   if (!gtk_widget_get_visible (window))
10415     {
10416       gtk_widget_show (window);
10417
10418       g_print ("create_mainloop: start\n");
10419       gtk_main ();
10420       g_print ("create_mainloop: done\n");
10421     }
10422   else
10423     gtk_widget_destroy (window);
10424 }
10425
10426 gboolean
10427 layout_expose_handler (GtkWidget *widget, GdkEventExpose *event)
10428 {
10429   GtkLayout *layout;
10430
10431   gint i,j;
10432   gint imin, imax, jmin, jmax;
10433
10434   layout = GTK_LAYOUT (widget);
10435
10436   if (event->window != layout->bin_window)
10437     return FALSE;
10438   
10439   imin = (event->area.x) / 10;
10440   imax = (event->area.x + event->area.width + 9) / 10;
10441
10442   jmin = (event->area.y) / 10;
10443   jmax = (event->area.y + event->area.height + 9) / 10;
10444
10445   for (i=imin; i<imax; i++)
10446     for (j=jmin; j<jmax; j++)
10447       if ((i+j) % 2)
10448         gdk_draw_rectangle (layout->bin_window,
10449                             widget->style->black_gc,
10450                             TRUE,
10451                             10*i, 10*j, 
10452                             1+i%10, 1+j%10);
10453   
10454   return FALSE;
10455 }
10456
10457 void create_layout (GtkWidget *widget)
10458 {
10459   static GtkWidget *window = NULL;
10460   GtkWidget *layout;
10461   GtkWidget *scrolledwindow;
10462   GtkWidget *button;
10463
10464   if (!window)
10465     {
10466       gchar buf[16];
10467
10468       gint i, j;
10469       
10470       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
10471       gtk_window_set_screen (GTK_WINDOW (window),
10472                              gtk_widget_get_screen (widget));
10473
10474       g_signal_connect (window, "destroy",
10475                         G_CALLBACK (gtk_widget_destroyed),
10476                         &window);
10477
10478       gtk_window_set_title (GTK_WINDOW (window), "Layout");
10479       gtk_widget_set_size_request (window, 200, 200);
10480
10481       scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
10482       gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolledwindow),
10483                                            GTK_SHADOW_IN);
10484       gtk_scrolled_window_set_placement (GTK_SCROLLED_WINDOW (scrolledwindow),
10485                                          GTK_CORNER_TOP_RIGHT);
10486
10487       gtk_container_add (GTK_CONTAINER (window), scrolledwindow);
10488       
10489       layout = gtk_layout_new (NULL, NULL);
10490       gtk_container_add (GTK_CONTAINER (scrolledwindow), layout);
10491
10492       /* We set step sizes here since GtkLayout does not set
10493        * them itself.
10494        */
10495       GTK_LAYOUT (layout)->hadjustment->step_increment = 10.0;
10496       GTK_LAYOUT (layout)->vadjustment->step_increment = 10.0;
10497       
10498       gtk_widget_set_events (layout, GDK_EXPOSURE_MASK);
10499       g_signal_connect (layout, "expose_event",
10500                         G_CALLBACK (layout_expose_handler), NULL);
10501       
10502       gtk_layout_set_size (GTK_LAYOUT (layout), 1600, 128000);
10503       
10504       for (i=0 ; i < 16 ; i++)
10505         for (j=0 ; j < 16 ; j++)
10506           {
10507             sprintf(buf, "Button %d, %d", i, j);
10508             if ((i + j) % 2)
10509               button = gtk_button_new_with_label (buf);
10510             else
10511               button = gtk_label_new (buf);
10512
10513             gtk_layout_put (GTK_LAYOUT (layout), button,
10514                             j*100, i*100);
10515           }
10516
10517       for (i=16; i < 1280; i++)
10518         {
10519           sprintf(buf, "Button %d, %d", i, 0);
10520           if (i % 2)
10521             button = gtk_button_new_with_label (buf);
10522           else
10523             button = gtk_label_new (buf);
10524
10525           gtk_layout_put (GTK_LAYOUT (layout), button,
10526                           0, i*100);
10527         }
10528     }
10529
10530   if (!gtk_widget_get_visible (window))
10531     gtk_widget_show_all (window);
10532   else
10533     gtk_widget_destroy (window);
10534 }
10535
10536 void
10537 create_styles (GtkWidget *widget)
10538 {
10539   static GtkWidget *window = NULL;
10540   GtkWidget *label;
10541   GtkWidget *button;
10542   GtkWidget *entry;
10543   GtkWidget *vbox;
10544   static GdkColor red =    { 0, 0xffff, 0,      0      };
10545   static GdkColor green =  { 0, 0,      0xffff, 0      };
10546   static GdkColor blue =   { 0, 0,      0,      0xffff };
10547   static GdkColor yellow = { 0, 0xffff, 0xffff, 0      };
10548   static GdkColor cyan =   { 0, 0     , 0xffff, 0xffff };
10549   PangoFontDescription *font_desc;
10550
10551   GtkRcStyle *rc_style;
10552
10553   if (!window)
10554     {
10555       window = gtk_dialog_new ();
10556       gtk_window_set_screen (GTK_WINDOW (window),
10557                              gtk_widget_get_screen (widget));
10558      
10559       g_signal_connect (window, "destroy",
10560                         G_CALLBACK (gtk_widget_destroyed),
10561                         &window);
10562
10563       
10564       button = gtk_button_new_with_label ("Close");
10565       g_signal_connect_swapped (button, "clicked",
10566                                 G_CALLBACK (gtk_widget_destroy),
10567                                 window);
10568       gtk_widget_set_can_default (button, TRUE);
10569       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
10570                           button, TRUE, TRUE, 0);
10571       gtk_widget_show (button);
10572
10573       vbox = gtk_vbox_new (FALSE, 5);
10574       gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
10575       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), vbox, FALSE, FALSE, 0);
10576       
10577       label = gtk_label_new ("Font:");
10578       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
10579       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
10580
10581       font_desc = pango_font_description_from_string ("Helvetica,Sans Oblique 18");
10582
10583       button = gtk_button_new_with_label ("Some Text");
10584       gtk_widget_modify_font (GTK_BIN (button)->child, font_desc);
10585       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
10586
10587       label = gtk_label_new ("Foreground:");
10588       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
10589       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
10590
10591       button = gtk_button_new_with_label ("Some Text");
10592       gtk_widget_modify_fg (GTK_BIN (button)->child, GTK_STATE_NORMAL, &red);
10593       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
10594
10595       label = gtk_label_new ("Background:");
10596       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
10597       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
10598
10599       button = gtk_button_new_with_label ("Some Text");
10600       gtk_widget_modify_bg (button, GTK_STATE_NORMAL, &green);
10601       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
10602
10603       label = gtk_label_new ("Text:");
10604       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
10605       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
10606
10607       entry = gtk_entry_new ();
10608       gtk_entry_set_text (GTK_ENTRY (entry), "Some Text");
10609       gtk_widget_modify_text (entry, GTK_STATE_NORMAL, &blue);
10610       gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
10611
10612       label = gtk_label_new ("Base:");
10613       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
10614       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
10615
10616       entry = gtk_entry_new ();
10617       gtk_entry_set_text (GTK_ENTRY (entry), "Some Text");
10618       gtk_widget_modify_base (entry, GTK_STATE_NORMAL, &yellow);
10619       gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
10620
10621       label = gtk_label_new ("Cursor:");
10622       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
10623       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
10624
10625       entry = gtk_entry_new ();
10626       gtk_entry_set_text (GTK_ENTRY (entry), "Some Text");
10627       gtk_widget_modify_cursor (entry, &red, &red);
10628       gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
10629
10630       label = gtk_label_new ("Multiple:");
10631       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
10632       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
10633
10634       button = gtk_button_new_with_label ("Some Text");
10635
10636       rc_style = gtk_rc_style_new ();
10637
10638       rc_style->font_desc = pango_font_description_copy (font_desc);
10639       rc_style->color_flags[GTK_STATE_NORMAL] = GTK_RC_FG | GTK_RC_BG;
10640       rc_style->color_flags[GTK_STATE_PRELIGHT] = GTK_RC_FG | GTK_RC_BG;
10641       rc_style->color_flags[GTK_STATE_ACTIVE] = GTK_RC_FG | GTK_RC_BG;
10642       rc_style->fg[GTK_STATE_NORMAL] = yellow;
10643       rc_style->bg[GTK_STATE_NORMAL] = blue;
10644       rc_style->fg[GTK_STATE_PRELIGHT] = blue;
10645       rc_style->bg[GTK_STATE_PRELIGHT] = yellow;
10646       rc_style->fg[GTK_STATE_ACTIVE] = red;
10647       rc_style->bg[GTK_STATE_ACTIVE] = cyan;
10648       rc_style->xthickness = 5;
10649       rc_style->ythickness = 5;
10650
10651       gtk_widget_modify_style (button, rc_style);
10652       gtk_widget_modify_style (GTK_BIN (button)->child, rc_style);
10653
10654       g_object_unref (rc_style);
10655       
10656       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
10657     }
10658   
10659   if (!gtk_widget_get_visible (window))
10660     gtk_widget_show_all (window);
10661   else
10662     gtk_widget_destroy (window);
10663 }
10664
10665 /*
10666  * Main Window and Exit
10667  */
10668
10669 void
10670 do_exit (GtkWidget *widget, GtkWidget *window)
10671 {
10672   gtk_widget_destroy (window);
10673   gtk_main_quit ();
10674 }
10675
10676 struct {
10677   char *label;
10678   void (*func) (GtkWidget *widget);
10679   gboolean do_not_benchmark;
10680 } buttons[] =
10681 {
10682   { "alpha window", create_alpha_window },
10683   { "big windows", create_big_windows },
10684   { "button box", create_button_box },
10685   { "buttons", create_buttons },
10686   { "check buttons", create_check_buttons },
10687   { "color selection", create_color_selection },
10688   { "composited window", create_composited_window },
10689   { "cursors", create_cursors },
10690   { "dialog", create_dialog },
10691   { "display & screen", create_display_screen, TRUE },
10692   { "entry", create_entry },
10693   { "event box", create_event_box },
10694   { "event watcher", create_event_watcher },
10695   { "expander", create_expander },
10696   { "flipping", create_flipping },
10697   { "focus", create_focus },
10698   { "font selection", create_font_selection },
10699   { "gridded geometry", create_gridded_geometry },
10700   { "handle box", create_handle_box },
10701   { "image from drawable", create_get_image },
10702   { "image", create_image },
10703   { "key lookup", create_key_lookup },
10704   { "labels", create_labels },
10705   { "layout", create_layout },
10706   { "menus", create_menus },
10707   { "message dialog", create_message_dialog },
10708   { "modal window", create_modal_window, TRUE },
10709   { "notebook", create_notebook },
10710   { "panes", create_panes },
10711   { "paned keyboard", create_paned_keyboard_navigation },
10712   { "pixmap", create_pixmap },
10713   { "progress bar", create_progress_bar },
10714   { "properties", create_properties },
10715   { "radio buttons", create_radio_buttons },
10716   { "range controls", create_range_controls },
10717   { "rc file", create_rc_file },
10718   { "reparent", create_reparent },
10719   { "resize grips", create_resize_grips },
10720   { "rotated label", create_rotated_label },
10721   { "rotated text", create_rotated_text },
10722   { "rulers", create_rulers },
10723   { "saved position", create_saved_position },
10724   { "scrolled windows", create_scrolled_windows },
10725   { "shapes", create_shapes },
10726   { "size groups", create_size_groups },
10727   { "snapshot", create_snapshot },
10728   { "spinbutton", create_spins },
10729   { "statusbar", create_statusbar },
10730   { "styles", create_styles },
10731   { "test idle", create_idle_test },
10732   { "test mainloop", create_mainloop, TRUE },
10733   { "test scrolling", create_scroll_test },
10734   { "test selection", create_selection_test },
10735   { "test timeout", create_timeout_test },
10736   { "toggle buttons", create_toggle_buttons },
10737   { "toolbar", create_toolbar },
10738   { "tooltips", create_tooltips },
10739   { "WM hints", create_wmhints },
10740   { "window sizing", create_window_sizing },
10741   { "window states", create_window_states }
10742 };
10743 int nbuttons = sizeof (buttons) / sizeof (buttons[0]);
10744
10745 void
10746 create_main_window (void)
10747 {
10748   GtkWidget *window;
10749   GtkWidget *box1;
10750   GtkWidget *box2;
10751   GtkWidget *scrolled_window;
10752   GtkWidget *button;
10753   GtkWidget *label;
10754   gchar buffer[64];
10755   GtkWidget *separator;
10756   GdkGeometry geometry;
10757   int i;
10758
10759   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
10760   gtk_widget_set_name (window, "main window");
10761   gtk_widget_set_uposition (window, 50, 20);
10762   gtk_window_set_default_size (GTK_WINDOW (window), -1, 400);
10763
10764   geometry.min_width = -1;
10765   geometry.min_height = -1;
10766   geometry.max_width = -1;
10767   geometry.max_height = G_MAXSHORT;
10768   gtk_window_set_geometry_hints (GTK_WINDOW (window), NULL,
10769                                  &geometry,
10770                                  GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE);
10771
10772   g_signal_connect (window, "destroy",
10773                     G_CALLBACK (gtk_main_quit),
10774                     NULL);
10775   g_signal_connect (window, "delete-event",
10776                     G_CALLBACK (gtk_false),
10777                     NULL);
10778
10779   box1 = gtk_vbox_new (FALSE, 0);
10780   gtk_container_add (GTK_CONTAINER (window), box1);
10781
10782   if (gtk_micro_version > 0)
10783     sprintf (buffer,
10784              "Gtk+ v%d.%d.%d",
10785              gtk_major_version,
10786              gtk_minor_version,
10787              gtk_micro_version);
10788   else
10789     sprintf (buffer,
10790              "Gtk+ v%d.%d",
10791              gtk_major_version,
10792              gtk_minor_version);
10793
10794   label = gtk_label_new (buffer);
10795   gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);
10796   gtk_widget_set_name (label, "testgtk-version-label");
10797
10798   scrolled_window = gtk_scrolled_window_new (NULL, NULL);
10799   gtk_container_set_border_width (GTK_CONTAINER (scrolled_window), 10);
10800   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
10801                                   GTK_POLICY_NEVER, 
10802                                   GTK_POLICY_AUTOMATIC);
10803   gtk_box_pack_start (GTK_BOX (box1), scrolled_window, TRUE, TRUE, 0);
10804
10805   box2 = gtk_vbox_new (FALSE, 0);
10806   gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
10807   gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_window), box2);
10808   gtk_container_set_focus_vadjustment (GTK_CONTAINER (box2),
10809                                        gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (scrolled_window)));
10810   gtk_widget_show (box2);
10811
10812   for (i = 0; i < nbuttons; i++)
10813     {
10814       button = gtk_button_new_with_label (buttons[i].label);
10815       if (buttons[i].func)
10816         g_signal_connect (button, 
10817                           "clicked", 
10818                           G_CALLBACK(buttons[i].func),
10819                           NULL);
10820       else
10821         gtk_widget_set_sensitive (button, FALSE);
10822       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
10823     }
10824
10825   separator = gtk_hseparator_new ();
10826   gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
10827
10828   box2 = gtk_vbox_new (FALSE, 10);
10829   gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
10830   gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
10831
10832   button = gtk_button_new_with_mnemonic ("_Close");
10833   g_signal_connect (button, "clicked",
10834                     G_CALLBACK (do_exit),
10835                     window);
10836   gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
10837   gtk_widget_set_can_default (button, TRUE);
10838   gtk_widget_grab_default (button);
10839
10840   gtk_widget_show_all (window);
10841 }
10842
10843 static void
10844 test_init (void)
10845 {
10846   if (g_file_test ("../gdk-pixbuf/libpixbufloader-pnm.la",
10847                    G_FILE_TEST_EXISTS))
10848     {
10849       g_setenv ("GDK_PIXBUF_MODULE_FILE", "../gdk-pixbuf/gdk-pixbuf.loaders", TRUE);
10850       g_setenv ("GTK_IM_MODULE_FILE", "../modules/input/gtk.immodules", TRUE);
10851     }
10852 }
10853
10854 static char *
10855 pad (const char *str, int to)
10856 {
10857   static char buf[256];
10858   int len = strlen (str);
10859   int i;
10860
10861   for (i = 0; i < to; i++)
10862     buf[i] = ' ';
10863
10864   buf[to] = '\0';
10865
10866   memcpy (buf, str, len);
10867
10868   return buf;
10869 }
10870
10871 static void
10872 bench_iteration (GtkWidget *widget, void (* fn) (GtkWidget *widget))
10873 {
10874   fn (widget); /* on */
10875   while (g_main_context_iteration (NULL, FALSE));
10876   fn (widget); /* off */
10877   while (g_main_context_iteration (NULL, FALSE));
10878 }
10879
10880 void
10881 do_real_bench (GtkWidget *widget, void (* fn) (GtkWidget *widget), char *name, int num)
10882 {
10883   GTimeVal tv0, tv1;
10884   double dt_first;
10885   double dt;
10886   int n;
10887   static gboolean printed_headers = FALSE;
10888
10889   if (!printed_headers) {
10890     g_print ("Test                 Iters      First      Other\n");
10891     g_print ("-------------------- ----- ---------- ----------\n");
10892     printed_headers = TRUE;
10893   }
10894
10895   g_get_current_time (&tv0);
10896   bench_iteration (widget, fn); 
10897   g_get_current_time (&tv1);
10898
10899   dt_first = ((double)tv1.tv_sec - tv0.tv_sec) * 1000.0
10900         + (tv1.tv_usec - tv0.tv_usec) / 1000.0;
10901
10902   g_get_current_time (&tv0);
10903   for (n = 0; n < num - 1; n++)
10904     bench_iteration (widget, fn); 
10905   g_get_current_time (&tv1);
10906   dt = ((double)tv1.tv_sec - tv0.tv_sec) * 1000.0
10907         + (tv1.tv_usec - tv0.tv_usec) / 1000.0;
10908
10909   g_print ("%s %5d ", pad (name, 20), num);
10910   if (num > 1)
10911     g_print ("%10.1f %10.1f\n", dt_first, dt/(num-1));
10912   else
10913     g_print ("%10.1f\n", dt_first);
10914 }
10915
10916 void
10917 do_bench (char* what, int num)
10918 {
10919   int i;
10920   GtkWidget *widget;
10921   void (* fn) (GtkWidget *widget);
10922   fn = NULL;
10923   widget = gtk_window_new (GTK_WINDOW_TOPLEVEL);
10924
10925   if (g_ascii_strcasecmp (what, "ALL") == 0)
10926     {
10927       for (i = 0; i < nbuttons; i++)
10928         {
10929           if (!buttons[i].do_not_benchmark)
10930             do_real_bench (widget, buttons[i].func, buttons[i].label, num);
10931         }
10932
10933       return;
10934     }
10935   else
10936     {
10937       for (i = 0; i < nbuttons; i++)
10938         {
10939           if (strcmp (buttons[i].label, what) == 0)
10940             {
10941               fn = buttons[i].func;
10942               break;
10943             }
10944         }
10945       
10946       if (!fn)
10947         g_print ("Can't bench: \"%s\" not found.\n", what);
10948       else
10949         do_real_bench (widget, fn, buttons[i].label, num);
10950     }
10951 }
10952
10953 void 
10954 usage (void)
10955 {
10956   fprintf (stderr, "Usage: testgtk [--bench ALL|<bench>[:<count>]]\n");
10957   exit (1);
10958 }
10959
10960 int
10961 main (int argc, char *argv[])
10962 {
10963   GtkBindingSet *binding_set;
10964   int i;
10965   gboolean done_benchmarks = FALSE;
10966
10967   srand (time (NULL));
10968
10969   test_init ();
10970
10971   /* Check to see if we are being run from the correct
10972    * directory.
10973    */
10974   if (file_exists ("testgtkrc"))
10975     gtk_rc_add_default_file ("testgtkrc");
10976   else if (file_exists ("tests/testgtkrc"))
10977     gtk_rc_add_default_file ("tests/testgtkrc");
10978   else
10979     g_warning ("Couldn't find file \"testgtkrc\".");
10980
10981   g_set_application_name ("GTK+ Test Program");
10982
10983   gtk_init (&argc, &argv);
10984
10985   gtk_accelerator_set_default_mod_mask (GDK_SHIFT_MASK |
10986                                         GDK_CONTROL_MASK |
10987                                         GDK_MOD1_MASK | 
10988                                         GDK_META_MASK |
10989                                         GDK_SUPER_MASK |
10990                                         GDK_HYPER_MASK |
10991                                         GDK_MOD4_MASK);
10992   /*  benchmarking
10993    */
10994   for (i = 1; i < argc; i++)
10995     {
10996       if (strncmp (argv[i], "--bench", strlen("--bench")) == 0)
10997         {
10998           int num = 1;
10999           char *nextarg;
11000           char *what;
11001           char *count;
11002           
11003           nextarg = strchr (argv[i], '=');
11004           if (nextarg)
11005             nextarg++;
11006           else
11007             {
11008               i++;
11009               if (i == argc)
11010                 usage ();
11011               nextarg = argv[i];
11012             }
11013
11014           count = strchr (nextarg, ':');
11015           if (count)
11016             {
11017               what = g_strndup (nextarg, count - nextarg);
11018               count++;
11019               num = atoi (count);
11020               if (num <= 0)
11021                 usage ();
11022             }
11023           else
11024             what = g_strdup (nextarg);
11025
11026           do_bench (what, num ? num : 1);
11027           done_benchmarks = TRUE;
11028         }
11029       else
11030         usage ();
11031     }
11032   if (done_benchmarks)
11033     return 0;
11034
11035   /* bindings test
11036    */
11037   binding_set = gtk_binding_set_by_class (g_type_class_ref (GTK_TYPE_WIDGET));
11038   gtk_binding_entry_add_signal (binding_set,
11039                                 '9', GDK_CONTROL_MASK | GDK_RELEASE_MASK,
11040                                 "debug_msg",
11041                                 1,
11042                                 G_TYPE_STRING, "GtkWidgetClass <ctrl><release>9 test");
11043   
11044   /* We use gtk_rc_parse_string() here so we can make sure it works across theme
11045    * changes
11046    */
11047
11048   gtk_rc_parse_string ("style \"testgtk-version-label\" { "
11049                        "   fg[NORMAL] = \"#ff0000\"\n"
11050                        "   font = \"Sans 18\"\n"
11051                        "}\n"
11052                        "widget \"*.testgtk-version-label\" style \"testgtk-version-label\"");
11053   
11054   create_main_window ();
11055
11056   gtk_main ();
11057
11058   if (1)
11059     {
11060       while (g_main_context_pending (NULL))
11061         g_main_context_iteration (NULL, FALSE);
11062 #if 0
11063       sleep (1);
11064       while (g_main_context_pending (NULL))
11065         g_main_context_iteration (NULL, FALSE);
11066 #endif
11067     }
11068   return 0;
11069 }