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