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