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