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