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