]> Pileus Git - ~andy/gtk/blob - tests/testgtk.c
Don't use gtk_widget_set_uposition/size 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_size_request (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 struct {
6656   GdkColor color;
6657   gchar *name;
6658 } text_colors[] = {
6659  { { 0, 0x0000, 0x0000, 0x0000 }, "black" },
6660  { { 0, 0xFFFF, 0xFFFF, 0xFFFF }, "white" },
6661  { { 0, 0xFFFF, 0x0000, 0x0000 }, "red" },
6662  { { 0, 0x0000, 0xFFFF, 0x0000 }, "green" },
6663  { { 0, 0x0000, 0x0000, 0xFFFF }, "blue" }, 
6664  { { 0, 0x0000, 0xFFFF, 0xFFFF }, "cyan" },
6665  { { 0, 0xFFFF, 0x0000, 0xFFFF }, "magenta" },
6666  { { 0, 0xFFFF, 0xFFFF, 0x0000 }, "yellow" }
6667 };
6668
6669 int ntext_colors = sizeof(text_colors) / sizeof(text_colors[0]);
6670
6671 /*
6672  * GtkNotebook
6673  */
6674
6675 GdkPixbuf *book_open;
6676 GdkPixbuf *book_closed;
6677 GtkWidget *sample_notebook;
6678
6679 static void
6680 set_page_image (GtkNotebook *notebook, gint page_num, GdkPixbuf *pixbuf)
6681 {
6682   GtkWidget *page_widget;
6683   GtkWidget *pixwid;
6684
6685   page_widget = gtk_notebook_get_nth_page (notebook, page_num);
6686
6687   pixwid = g_object_get_data (G_OBJECT (page_widget), "tab_pixmap");
6688   gtk_image_set_from_pixbuf (GTK_IMAGE (pixwid), pixbuf);
6689   
6690   pixwid = g_object_get_data (G_OBJECT (page_widget), "menu_pixmap");
6691   gtk_image_set_from_pixbuf (GTK_IMAGE (pixwid), pixbuf);
6692 }
6693
6694 static void
6695 page_switch (GtkWidget *widget, GtkNotebookPage *page, gint page_num)
6696 {
6697   GtkNotebook *notebook = GTK_NOTEBOOK (widget);
6698   gint old_page_num = gtk_notebook_get_current_page (notebook);
6699  
6700   if (page_num == old_page_num)
6701     return;
6702
6703   set_page_image (notebook, page_num, book_open);
6704
6705   if (old_page_num != -1)
6706     set_page_image (notebook, old_page_num, book_closed);
6707 }
6708
6709 static void
6710 tab_fill (GtkToggleButton *button, GtkWidget *child)
6711 {
6712   gboolean expand;
6713   GtkPackType pack_type;
6714
6715   gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (sample_notebook), child,
6716                                         &expand, NULL, &pack_type);
6717   gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (sample_notebook), child,
6718                                       expand, button->active, pack_type);
6719 }
6720
6721 static void
6722 tab_expand (GtkToggleButton *button, GtkWidget *child)
6723 {
6724   gboolean fill;
6725   GtkPackType pack_type;
6726
6727   gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (sample_notebook), child,
6728                                         NULL, &fill, &pack_type);
6729   gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (sample_notebook), child,
6730                                       button->active, fill, pack_type);
6731 }
6732
6733 static void
6734 tab_pack (GtkToggleButton *button, GtkWidget *child)
6735           
6736
6737   gboolean expand;
6738   gboolean fill;
6739
6740   gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (sample_notebook), child,
6741                                         &expand, &fill, NULL);
6742   gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (sample_notebook), child,
6743                                       expand, fill, button->active);
6744 }
6745
6746 static void
6747 create_pages (GtkNotebook *notebook, gint start, gint end)
6748 {
6749   GtkWidget *child = NULL;
6750   GtkWidget *button;
6751   GtkWidget *label;
6752   GtkWidget *hbox;
6753   GtkWidget *vbox;
6754   GtkWidget *label_box;
6755   GtkWidget *menu_box;
6756   GtkWidget *pixwid;
6757   gint i;
6758   char buffer[32];
6759   char accel_buffer[32];
6760
6761   for (i = start; i <= end; i++)
6762     {
6763       sprintf (buffer, "Page %d", i);
6764       sprintf (accel_buffer, "Page _%d", i);
6765
6766       child = gtk_frame_new (buffer);
6767       gtk_container_set_border_width (GTK_CONTAINER (child), 10);
6768
6769       vbox = gtk_vbox_new (TRUE,0);
6770       gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
6771       gtk_container_add (GTK_CONTAINER (child), vbox);
6772
6773       hbox = gtk_hbox_new (TRUE,0);
6774       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 5);
6775
6776       button = gtk_check_button_new_with_label ("Fill Tab");
6777       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
6778       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
6779       g_signal_connect (button, "toggled",
6780                         G_CALLBACK (tab_fill), child);
6781
6782       button = gtk_check_button_new_with_label ("Expand Tab");
6783       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
6784       g_signal_connect (button, "toggled",
6785                         G_CALLBACK (tab_expand), child);
6786
6787       button = gtk_check_button_new_with_label ("Pack end");
6788       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
6789       g_signal_connect (button, "toggled",
6790                         G_CALLBACK (tab_pack), child);
6791
6792       button = gtk_button_new_with_label ("Hide Page");
6793       gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 5);
6794       g_signal_connect_swapped (button, "clicked",
6795                                 G_CALLBACK (gtk_widget_hide),
6796                                 child);
6797
6798       gtk_widget_show_all (child);
6799
6800       label_box = gtk_hbox_new (FALSE, 0);
6801       pixwid = gtk_image_new_from_pixbuf (book_closed);
6802       g_object_set_data (G_OBJECT (child), "tab_pixmap", pixwid);
6803                            
6804       gtk_box_pack_start (GTK_BOX (label_box), pixwid, FALSE, TRUE, 0);
6805       gtk_misc_set_padding (GTK_MISC (pixwid), 3, 1);
6806       label = gtk_label_new_with_mnemonic (accel_buffer);
6807       gtk_box_pack_start (GTK_BOX (label_box), label, FALSE, TRUE, 0);
6808       gtk_widget_show_all (label_box);
6809       
6810                                        
6811       menu_box = gtk_hbox_new (FALSE, 0);
6812       pixwid = gtk_image_new_from_pixbuf (book_closed);
6813       g_object_set_data (G_OBJECT (child), "menu_pixmap", pixwid);
6814       
6815       gtk_box_pack_start (GTK_BOX (menu_box), pixwid, FALSE, TRUE, 0);
6816       gtk_misc_set_padding (GTK_MISC (pixwid), 3, 1);
6817       label = gtk_label_new (buffer);
6818       gtk_box_pack_start (GTK_BOX (menu_box), label, FALSE, TRUE, 0);
6819       gtk_widget_show_all (menu_box);
6820
6821       gtk_notebook_append_page_menu (notebook, child, label_box, menu_box);
6822     }
6823 }
6824
6825 static void
6826 rotate_notebook (GtkButton   *button,
6827                  GtkNotebook *notebook)
6828 {
6829   gtk_notebook_set_tab_pos (notebook, (notebook->tab_pos + 1) % 4);
6830 }
6831
6832 static void
6833 show_all_pages (GtkButton   *button,
6834                 GtkNotebook *notebook)
6835 {  
6836   gtk_container_foreach (GTK_CONTAINER (notebook),
6837                          (GtkCallback) gtk_widget_show, NULL);
6838 }
6839
6840 static void
6841 notebook_type_changed (GtkWidget *optionmenu,
6842                        gpointer   data)
6843 {
6844   GtkNotebook *notebook;
6845   gint i, c;
6846
6847   enum {
6848     STANDARD,
6849     NOTABS,
6850     BORDERLESS,
6851     SCROLLABLE
6852   };
6853
6854   notebook = GTK_NOTEBOOK (data);
6855
6856   c = gtk_combo_box_get_active (GTK_COMBO_BOX (optionmenu));
6857
6858   switch (c)
6859     {
6860     case STANDARD:
6861       /* standard notebook */
6862       gtk_notebook_set_show_tabs (notebook, TRUE);
6863       gtk_notebook_set_show_border (notebook, TRUE);
6864       gtk_notebook_set_scrollable (notebook, FALSE);
6865       break;
6866
6867     case NOTABS:
6868       /* notabs notebook */
6869       gtk_notebook_set_show_tabs (notebook, FALSE);
6870       gtk_notebook_set_show_border (notebook, TRUE);
6871       break;
6872
6873     case BORDERLESS:
6874       /* borderless */
6875       gtk_notebook_set_show_tabs (notebook, FALSE);
6876       gtk_notebook_set_show_border (notebook, FALSE);
6877       break;
6878
6879     case SCROLLABLE:  
6880       /* scrollable */
6881       gtk_notebook_set_show_tabs (notebook, TRUE);
6882       gtk_notebook_set_show_border (notebook, TRUE);
6883       gtk_notebook_set_scrollable (notebook, TRUE);
6884       if (g_list_length (notebook->children) == 5)
6885         create_pages (notebook, 6, 15);
6886       
6887       return;
6888       break;
6889     }
6890   
6891   if (g_list_length (notebook->children) == 15)
6892     for (i = 0; i < 10; i++)
6893       gtk_notebook_remove_page (notebook, 5);
6894 }
6895
6896 static void
6897 notebook_popup (GtkToggleButton *button,
6898                 GtkNotebook     *notebook)
6899 {
6900   if (button->active)
6901     gtk_notebook_popup_enable (notebook);
6902   else
6903     gtk_notebook_popup_disable (notebook);
6904 }
6905
6906 static void
6907 notebook_homogeneous (GtkToggleButton *button,
6908                       GtkNotebook     *notebook)
6909 {
6910   g_object_set (notebook, "homogeneous", button->active, NULL);
6911 }
6912
6913 static void
6914 create_notebook (GtkWidget *widget)
6915 {
6916   static GtkWidget *window = NULL;
6917   GtkWidget *box1;
6918   GtkWidget *box2;
6919   GtkWidget *button;
6920   GtkWidget *separator;
6921   GtkWidget *omenu;
6922   GtkWidget *label;
6923   GdkPixbuf *book_open_xpm;
6924   GdkPixbuf *book_closed_xpm;
6925
6926   static gchar *items[] =
6927   {
6928     "Standard",
6929     "No tabs",
6930     "Borderless",
6931     "Scrollable"
6932   };
6933   
6934   if (!window)
6935     {
6936       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
6937       gtk_window_set_screen (GTK_WINDOW (window),
6938                              gtk_widget_get_screen (widget));
6939
6940       g_signal_connect (window, "destroy",
6941                         G_CALLBACK (gtk_widget_destroyed),
6942                         &window);
6943
6944       gtk_window_set_title (GTK_WINDOW (window), "notebook");
6945       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
6946
6947       box1 = gtk_vbox_new (FALSE, 0);
6948       gtk_container_add (GTK_CONTAINER (window), box1);
6949
6950       sample_notebook = gtk_notebook_new ();
6951       g_signal_connect (sample_notebook, "switch_page",
6952                         G_CALLBACK (page_switch), NULL);
6953       gtk_notebook_set_tab_pos (GTK_NOTEBOOK (sample_notebook), GTK_POS_TOP);
6954       gtk_box_pack_start (GTK_BOX (box1), sample_notebook, TRUE, TRUE, 0);
6955       gtk_container_set_border_width (GTK_CONTAINER (sample_notebook), 10);
6956
6957       gtk_widget_realize (sample_notebook);
6958
6959       if (!book_open)
6960         book_open = gdk_pixbuf_new_from_xpm_data ((const char **)book_open_xpm);
6961                                                   
6962       if (!book_closed)
6963         book_closed = gdk_pixbuf_new_from_xpm_data ((const char **)book_closed_xpm);
6964
6965       create_pages (GTK_NOTEBOOK (sample_notebook), 1, 5);
6966
6967       separator = gtk_hseparator_new ();
6968       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 10);
6969       
6970       box2 = gtk_hbox_new (FALSE, 5);
6971       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
6972       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
6973
6974       button = gtk_check_button_new_with_label ("popup menu");
6975       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, FALSE, 0);
6976       g_signal_connect (button, "clicked",
6977                         G_CALLBACK (notebook_popup),
6978                         sample_notebook);
6979
6980       button = gtk_check_button_new_with_label ("homogeneous tabs");
6981       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, FALSE, 0);
6982       g_signal_connect (button, "clicked",
6983                         G_CALLBACK (notebook_homogeneous),
6984                         sample_notebook);
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       label = gtk_label_new ("Notebook Style :");
6991       gtk_box_pack_start (GTK_BOX (box2), label, FALSE, TRUE, 0);
6992
6993       omenu = build_option_menu (items, G_N_ELEMENTS (items), 0,
6994                                  notebook_type_changed,
6995                                  sample_notebook);
6996       gtk_box_pack_start (GTK_BOX (box2), omenu, FALSE, TRUE, 0);
6997
6998       button = gtk_button_new_with_label ("Show all Pages");
6999       gtk_box_pack_start (GTK_BOX (box2), button, FALSE, TRUE, 0);
7000       g_signal_connect (button, "clicked",
7001                         G_CALLBACK (show_all_pages), sample_notebook);
7002
7003       box2 = gtk_hbox_new (TRUE, 10);
7004       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
7005       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
7006
7007       button = gtk_button_new_with_label ("prev");
7008       g_signal_connect_swapped (button, "clicked",
7009                                 G_CALLBACK (gtk_notebook_prev_page),
7010                                 sample_notebook);
7011       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
7012
7013       button = gtk_button_new_with_label ("next");
7014       g_signal_connect_swapped (button, "clicked",
7015                                 G_CALLBACK (gtk_notebook_next_page),
7016                                 sample_notebook);
7017       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
7018
7019       button = gtk_button_new_with_label ("rotate");
7020       g_signal_connect (button, "clicked",
7021                         G_CALLBACK (rotate_notebook), sample_notebook);
7022       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
7023
7024       separator = gtk_hseparator_new ();
7025       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
7026
7027       button = gtk_button_new_with_label ("close");
7028       gtk_container_set_border_width (GTK_CONTAINER (button), 5);
7029       g_signal_connect_swapped (button, "clicked",
7030                                 G_CALLBACK (gtk_widget_destroy),
7031                                 window);
7032       gtk_box_pack_start (GTK_BOX (box1), button, FALSE, FALSE, 0);
7033       gtk_widget_set_can_default (button, TRUE);
7034       gtk_widget_grab_default (button);
7035     }
7036
7037   if (!gtk_widget_get_visible (window))
7038     gtk_widget_show_all (window);
7039   else
7040     gtk_widget_destroy (window);
7041 }
7042
7043 /*
7044  * GtkPanes
7045  */
7046
7047 void
7048 toggle_resize (GtkWidget *widget, GtkWidget *child)
7049 {
7050   GtkContainer *container = GTK_CONTAINER (gtk_widget_get_parent (child));
7051   GValue value = { 0, };
7052   g_value_init (&value, G_TYPE_BOOLEAN);
7053   gtk_container_child_get_property (container, child, "resize", &value);
7054   g_value_set_boolean (&value, !g_value_get_boolean (&value));
7055   gtk_container_child_set_property (container, child, "resize", &value);
7056 }
7057
7058 void
7059 toggle_shrink (GtkWidget *widget, GtkWidget *child)
7060 {
7061   GtkContainer *container = GTK_CONTAINER (gtk_widget_get_parent (child));
7062   GValue value = { 0, };
7063   g_value_init (&value, G_TYPE_BOOLEAN);
7064   gtk_container_child_get_property (container, child, "shrink", &value);
7065   g_value_set_boolean (&value, !g_value_get_boolean (&value));
7066   gtk_container_child_set_property (container, child, "shrink", &value);
7067 }
7068
7069 static void
7070 paned_props_clicked (GtkWidget *button,
7071                      GObject   *paned)
7072 {
7073   GtkWidget *window = create_prop_editor (paned, GTK_TYPE_PANED);
7074   
7075   gtk_window_set_title (GTK_WINDOW (window), "Paned Properties");
7076 }
7077
7078 GtkWidget *
7079 create_pane_options (GtkPaned    *paned,
7080                      const gchar *frame_label,
7081                      const gchar *label1,
7082                      const gchar *label2)
7083 {
7084   GtkWidget *frame;
7085   GtkWidget *table;
7086   GtkWidget *label;
7087   GtkWidget *button;
7088   GtkWidget *check_button;
7089   
7090   frame = gtk_frame_new (frame_label);
7091   gtk_container_set_border_width (GTK_CONTAINER (frame), 4);
7092   
7093   table = gtk_table_new (4, 2, 4);
7094   gtk_container_add (GTK_CONTAINER (frame), table);
7095   
7096   label = gtk_label_new (label1);
7097   gtk_table_attach_defaults (GTK_TABLE (table), label,
7098                              0, 1, 0, 1);
7099   
7100   check_button = gtk_check_button_new_with_label ("Resize");
7101   gtk_table_attach_defaults (GTK_TABLE (table), check_button,
7102                              0, 1, 1, 2);
7103   g_signal_connect (check_button, "toggled",
7104                     G_CALLBACK (toggle_resize),
7105                     paned->child1);
7106   
7107   check_button = gtk_check_button_new_with_label ("Shrink");
7108   gtk_table_attach_defaults (GTK_TABLE (table), check_button,
7109                              0, 1, 2, 3);
7110   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button),
7111                                TRUE);
7112   g_signal_connect (check_button, "toggled",
7113                     G_CALLBACK (toggle_shrink),
7114                     paned->child1);
7115   
7116   label = gtk_label_new (label2);
7117   gtk_table_attach_defaults (GTK_TABLE (table), label,
7118                              1, 2, 0, 1);
7119   
7120   check_button = gtk_check_button_new_with_label ("Resize");
7121   gtk_table_attach_defaults (GTK_TABLE (table), check_button,
7122                              1, 2, 1, 2);
7123   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button),
7124                                TRUE);
7125   g_signal_connect (check_button, "toggled",
7126                     G_CALLBACK (toggle_resize),
7127                     paned->child2);
7128   
7129   check_button = gtk_check_button_new_with_label ("Shrink");
7130   gtk_table_attach_defaults (GTK_TABLE (table), check_button,
7131                              1, 2, 2, 3);
7132   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button),
7133                                TRUE);
7134   g_signal_connect (check_button, "toggled",
7135                     G_CALLBACK (toggle_shrink),
7136                     paned->child2);
7137
7138   button = gtk_button_new_with_mnemonic ("_Properties");
7139   gtk_table_attach_defaults (GTK_TABLE (table), button,
7140                              0, 2, 3, 4);
7141   g_signal_connect (button, "clicked",
7142                     G_CALLBACK (paned_props_clicked),
7143                     paned);
7144
7145   return frame;
7146 }
7147
7148 void
7149 create_panes (GtkWidget *widget)
7150 {
7151   static GtkWidget *window = NULL;
7152   GtkWidget *frame;
7153   GtkWidget *hpaned;
7154   GtkWidget *vpaned;
7155   GtkWidget *button;
7156   GtkWidget *vbox;
7157
7158   if (!window)
7159     {
7160       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7161
7162       gtk_window_set_screen (GTK_WINDOW (window),
7163                              gtk_widget_get_screen (widget));
7164       
7165       g_signal_connect (window, "destroy",
7166                         G_CALLBACK (gtk_widget_destroyed),
7167                         &window);
7168
7169       gtk_window_set_title (GTK_WINDOW (window), "Panes");
7170       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
7171
7172       vbox = gtk_vbox_new (FALSE, 0);
7173       gtk_container_add (GTK_CONTAINER (window), vbox);
7174       
7175       vpaned = gtk_vpaned_new ();
7176       gtk_box_pack_start (GTK_BOX (vbox), vpaned, TRUE, TRUE, 0);
7177       gtk_container_set_border_width (GTK_CONTAINER(vpaned), 5);
7178
7179       hpaned = gtk_hpaned_new ();
7180       gtk_paned_add1 (GTK_PANED (vpaned), hpaned);
7181
7182       frame = gtk_frame_new (NULL);
7183       gtk_frame_set_shadow_type (GTK_FRAME(frame), GTK_SHADOW_IN);
7184       gtk_widget_set_size_request (frame, 60, 60);
7185       gtk_paned_add1 (GTK_PANED (hpaned), frame);
7186       
7187       button = gtk_button_new_with_label ("Hi there");
7188       gtk_container_add (GTK_CONTAINER(frame), button);
7189
7190       frame = gtk_frame_new (NULL);
7191       gtk_frame_set_shadow_type (GTK_FRAME(frame), GTK_SHADOW_IN);
7192       gtk_widget_set_size_request (frame, 80, 60);
7193       gtk_paned_add2 (GTK_PANED (hpaned), frame);
7194
7195       frame = gtk_frame_new (NULL);
7196       gtk_frame_set_shadow_type (GTK_FRAME(frame), GTK_SHADOW_IN);
7197       gtk_widget_set_size_request (frame, 60, 80);
7198       gtk_paned_add2 (GTK_PANED (vpaned), frame);
7199
7200       /* Now create toggle buttons to control sizing */
7201
7202       gtk_box_pack_start (GTK_BOX (vbox),
7203                           create_pane_options (GTK_PANED (hpaned),
7204                                                "Horizontal",
7205                                                "Left",
7206                                                "Right"),
7207                           FALSE, FALSE, 0);
7208
7209       gtk_box_pack_start (GTK_BOX (vbox),
7210                           create_pane_options (GTK_PANED (vpaned),
7211                                                "Vertical",
7212                                                "Top",
7213                                                "Bottom"),
7214                           FALSE, FALSE, 0);
7215
7216       gtk_widget_show_all (vbox);
7217     }
7218
7219   if (!gtk_widget_get_visible (window))
7220     gtk_widget_show (window);
7221   else
7222     gtk_widget_destroy (window);
7223 }
7224
7225 /*
7226  * Paned keyboard navigation
7227  */
7228
7229 static GtkWidget*
7230 paned_keyboard_window1 (GtkWidget *widget)
7231 {
7232   GtkWidget *window1;
7233   GtkWidget *hpaned1;
7234   GtkWidget *frame1;
7235   GtkWidget *vbox1;
7236   GtkWidget *button7;
7237   GtkWidget *button8;
7238   GtkWidget *button9;
7239   GtkWidget *vpaned1;
7240   GtkWidget *frame2;
7241   GtkWidget *frame5;
7242   GtkWidget *hbox1;
7243   GtkWidget *button5;
7244   GtkWidget *button6;
7245   GtkWidget *frame3;
7246   GtkWidget *frame4;
7247   GtkWidget *table1;
7248   GtkWidget *button1;
7249   GtkWidget *button2;
7250   GtkWidget *button3;
7251   GtkWidget *button4;
7252
7253   window1 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7254   gtk_window_set_title (GTK_WINDOW (window1), "Basic paned navigation");
7255   gtk_window_set_screen (GTK_WINDOW (window1), 
7256                          gtk_widget_get_screen (widget));
7257
7258   hpaned1 = gtk_hpaned_new ();
7259   gtk_container_add (GTK_CONTAINER (window1), hpaned1);
7260
7261   frame1 = gtk_frame_new (NULL);
7262   gtk_paned_pack1 (GTK_PANED (hpaned1), frame1, FALSE, TRUE);
7263   gtk_frame_set_shadow_type (GTK_FRAME (frame1), GTK_SHADOW_IN);
7264
7265   vbox1 = gtk_vbox_new (FALSE, 0);
7266   gtk_container_add (GTK_CONTAINER (frame1), vbox1);
7267
7268   button7 = gtk_button_new_with_label ("button7");
7269   gtk_box_pack_start (GTK_BOX (vbox1), button7, FALSE, FALSE, 0);
7270
7271   button8 = gtk_button_new_with_label ("button8");
7272   gtk_box_pack_start (GTK_BOX (vbox1), button8, FALSE, FALSE, 0);
7273
7274   button9 = gtk_button_new_with_label ("button9");
7275   gtk_box_pack_start (GTK_BOX (vbox1), button9, FALSE, FALSE, 0);
7276
7277   vpaned1 = gtk_vpaned_new ();
7278   gtk_paned_pack2 (GTK_PANED (hpaned1), vpaned1, TRUE, TRUE);
7279
7280   frame2 = gtk_frame_new (NULL);
7281   gtk_paned_pack1 (GTK_PANED (vpaned1), frame2, FALSE, TRUE);
7282   gtk_frame_set_shadow_type (GTK_FRAME (frame2), GTK_SHADOW_IN);
7283
7284   frame5 = gtk_frame_new (NULL);
7285   gtk_container_add (GTK_CONTAINER (frame2), frame5);
7286
7287   hbox1 = gtk_hbox_new (FALSE, 0);
7288   gtk_container_add (GTK_CONTAINER (frame5), hbox1);
7289
7290   button5 = gtk_button_new_with_label ("button5");
7291   gtk_box_pack_start (GTK_BOX (hbox1), button5, FALSE, FALSE, 0);
7292
7293   button6 = gtk_button_new_with_label ("button6");
7294   gtk_box_pack_start (GTK_BOX (hbox1), button6, FALSE, FALSE, 0);
7295
7296   frame3 = gtk_frame_new (NULL);
7297   gtk_paned_pack2 (GTK_PANED (vpaned1), frame3, TRUE, TRUE);
7298   gtk_frame_set_shadow_type (GTK_FRAME (frame3), GTK_SHADOW_IN);
7299
7300   frame4 = gtk_frame_new ("Buttons");
7301   gtk_container_add (GTK_CONTAINER (frame3), frame4);
7302   gtk_container_set_border_width (GTK_CONTAINER (frame4), 15);
7303
7304   table1 = gtk_table_new (2, 2, FALSE);
7305   gtk_container_add (GTK_CONTAINER (frame4), table1);
7306   gtk_container_set_border_width (GTK_CONTAINER (table1), 11);
7307
7308   button1 = gtk_button_new_with_label ("button1");
7309   gtk_table_attach (GTK_TABLE (table1), button1, 0, 1, 0, 1,
7310                     (GtkAttachOptions) (GTK_FILL),
7311                     (GtkAttachOptions) (0), 0, 0);
7312
7313   button2 = gtk_button_new_with_label ("button2");
7314   gtk_table_attach (GTK_TABLE (table1), button2, 1, 2, 0, 1,
7315                     (GtkAttachOptions) (GTK_FILL),
7316                     (GtkAttachOptions) (0), 0, 0);
7317
7318   button3 = gtk_button_new_with_label ("button3");
7319   gtk_table_attach (GTK_TABLE (table1), button3, 0, 1, 1, 2,
7320                     (GtkAttachOptions) (GTK_FILL),
7321                     (GtkAttachOptions) (0), 0, 0);
7322
7323   button4 = gtk_button_new_with_label ("button4");
7324   gtk_table_attach (GTK_TABLE (table1), button4, 1, 2, 1, 2,
7325                     (GtkAttachOptions) (GTK_FILL),
7326                     (GtkAttachOptions) (0), 0, 0);
7327
7328   return window1;
7329 }
7330
7331 static GtkWidget*
7332 paned_keyboard_window2 (GtkWidget *widget)
7333 {
7334   GtkWidget *window2;
7335   GtkWidget *hpaned2;
7336   GtkWidget *frame6;
7337   GtkWidget *button13;
7338   GtkWidget *hbox2;
7339   GtkWidget *vpaned2;
7340   GtkWidget *frame7;
7341   GtkWidget *button12;
7342   GtkWidget *frame8;
7343   GtkWidget *button11;
7344   GtkWidget *button10;
7345
7346   window2 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7347   gtk_window_set_title (GTK_WINDOW (window2), "\"button 10\" is not inside the horisontal pane");
7348
7349   gtk_window_set_screen (GTK_WINDOW (window2), 
7350                          gtk_widget_get_screen (widget));
7351
7352   hpaned2 = gtk_hpaned_new ();
7353   gtk_container_add (GTK_CONTAINER (window2), hpaned2);
7354
7355   frame6 = gtk_frame_new (NULL);
7356   gtk_paned_pack1 (GTK_PANED (hpaned2), frame6, FALSE, TRUE);
7357   gtk_frame_set_shadow_type (GTK_FRAME (frame6), GTK_SHADOW_IN);
7358
7359   button13 = gtk_button_new_with_label ("button13");
7360   gtk_container_add (GTK_CONTAINER (frame6), button13);
7361
7362   hbox2 = gtk_hbox_new (FALSE, 0);
7363   gtk_paned_pack2 (GTK_PANED (hpaned2), hbox2, TRUE, TRUE);
7364
7365   vpaned2 = gtk_vpaned_new ();
7366   gtk_box_pack_start (GTK_BOX (hbox2), vpaned2, TRUE, TRUE, 0);
7367
7368   frame7 = gtk_frame_new (NULL);
7369   gtk_paned_pack1 (GTK_PANED (vpaned2), frame7, FALSE, TRUE);
7370   gtk_frame_set_shadow_type (GTK_FRAME (frame7), GTK_SHADOW_IN);
7371
7372   button12 = gtk_button_new_with_label ("button12");
7373   gtk_container_add (GTK_CONTAINER (frame7), button12);
7374
7375   frame8 = gtk_frame_new (NULL);
7376   gtk_paned_pack2 (GTK_PANED (vpaned2), frame8, TRUE, TRUE);
7377   gtk_frame_set_shadow_type (GTK_FRAME (frame8), GTK_SHADOW_IN);
7378
7379   button11 = gtk_button_new_with_label ("button11");
7380   gtk_container_add (GTK_CONTAINER (frame8), button11);
7381
7382   button10 = gtk_button_new_with_label ("button10");
7383   gtk_box_pack_start (GTK_BOX (hbox2), button10, FALSE, FALSE, 0);
7384
7385   return window2;
7386 }
7387
7388 static GtkWidget*
7389 paned_keyboard_window3 (GtkWidget *widget)
7390 {
7391   GtkWidget *window3;
7392   GtkWidget *vbox2;
7393   GtkWidget *label1;
7394   GtkWidget *hpaned3;
7395   GtkWidget *frame9;
7396   GtkWidget *button14;
7397   GtkWidget *hpaned4;
7398   GtkWidget *frame10;
7399   GtkWidget *button15;
7400   GtkWidget *hpaned5;
7401   GtkWidget *frame11;
7402   GtkWidget *button16;
7403   GtkWidget *frame12;
7404   GtkWidget *button17;
7405
7406   window3 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7407   g_object_set_data (G_OBJECT (window3), "window3", window3);
7408   gtk_window_set_title (GTK_WINDOW (window3), "Nested panes");
7409
7410   gtk_window_set_screen (GTK_WINDOW (window3), 
7411                          gtk_widget_get_screen (widget));
7412   
7413
7414   vbox2 = gtk_vbox_new (FALSE, 0);
7415   gtk_container_add (GTK_CONTAINER (window3), vbox2);
7416
7417   label1 = gtk_label_new ("Three panes nested inside each other");
7418   gtk_box_pack_start (GTK_BOX (vbox2), label1, FALSE, FALSE, 0);
7419
7420   hpaned3 = gtk_hpaned_new ();
7421   gtk_box_pack_start (GTK_BOX (vbox2), hpaned3, TRUE, TRUE, 0);
7422
7423   frame9 = gtk_frame_new (NULL);
7424   gtk_paned_pack1 (GTK_PANED (hpaned3), frame9, FALSE, TRUE);
7425   gtk_frame_set_shadow_type (GTK_FRAME (frame9), GTK_SHADOW_IN);
7426
7427   button14 = gtk_button_new_with_label ("button14");
7428   gtk_container_add (GTK_CONTAINER (frame9), button14);
7429
7430   hpaned4 = gtk_hpaned_new ();
7431   gtk_paned_pack2 (GTK_PANED (hpaned3), hpaned4, TRUE, TRUE);
7432
7433   frame10 = gtk_frame_new (NULL);
7434   gtk_paned_pack1 (GTK_PANED (hpaned4), frame10, FALSE, TRUE);
7435   gtk_frame_set_shadow_type (GTK_FRAME (frame10), GTK_SHADOW_IN);
7436
7437   button15 = gtk_button_new_with_label ("button15");
7438   gtk_container_add (GTK_CONTAINER (frame10), button15);
7439
7440   hpaned5 = gtk_hpaned_new ();
7441   gtk_paned_pack2 (GTK_PANED (hpaned4), hpaned5, TRUE, TRUE);
7442
7443   frame11 = gtk_frame_new (NULL);
7444   gtk_paned_pack1 (GTK_PANED (hpaned5), frame11, FALSE, TRUE);
7445   gtk_frame_set_shadow_type (GTK_FRAME (frame11), GTK_SHADOW_IN);
7446
7447   button16 = gtk_button_new_with_label ("button16");
7448   gtk_container_add (GTK_CONTAINER (frame11), button16);
7449
7450   frame12 = gtk_frame_new (NULL);
7451   gtk_paned_pack2 (GTK_PANED (hpaned5), frame12, TRUE, TRUE);
7452   gtk_frame_set_shadow_type (GTK_FRAME (frame12), GTK_SHADOW_IN);
7453
7454   button17 = gtk_button_new_with_label ("button17");
7455   gtk_container_add (GTK_CONTAINER (frame12), button17);
7456
7457   return window3;
7458 }
7459
7460 static GtkWidget*
7461 paned_keyboard_window4 (GtkWidget *widget)
7462 {
7463   GtkWidget *window4;
7464   GtkWidget *vbox3;
7465   GtkWidget *label2;
7466   GtkWidget *hpaned6;
7467   GtkWidget *vpaned3;
7468   GtkWidget *button19;
7469   GtkWidget *button18;
7470   GtkWidget *hbox3;
7471   GtkWidget *vpaned4;
7472   GtkWidget *button21;
7473   GtkWidget *button20;
7474   GtkWidget *vpaned5;
7475   GtkWidget *button23;
7476   GtkWidget *button22;
7477   GtkWidget *vpaned6;
7478   GtkWidget *button25;
7479   GtkWidget *button24;
7480
7481   window4 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7482   g_object_set_data (G_OBJECT (window4), "window4", window4);
7483   gtk_window_set_title (GTK_WINDOW (window4), "window4");
7484
7485   gtk_window_set_screen (GTK_WINDOW (window4), 
7486                          gtk_widget_get_screen (widget));
7487
7488   vbox3 = gtk_vbox_new (FALSE, 0);
7489   gtk_container_add (GTK_CONTAINER (window4), vbox3);
7490
7491   label2 = gtk_label_new ("Widget tree:\n\nhpaned \n - vpaned\n - hbox\n    - vpaned\n    - vpaned\n    - vpaned\n");
7492   gtk_box_pack_start (GTK_BOX (vbox3), label2, FALSE, FALSE, 0);
7493   gtk_label_set_justify (GTK_LABEL (label2), GTK_JUSTIFY_LEFT);
7494
7495   hpaned6 = gtk_hpaned_new ();
7496   gtk_box_pack_start (GTK_BOX (vbox3), hpaned6, TRUE, TRUE, 0);
7497
7498   vpaned3 = gtk_vpaned_new ();
7499   gtk_paned_pack1 (GTK_PANED (hpaned6), vpaned3, FALSE, TRUE);
7500
7501   button19 = gtk_button_new_with_label ("button19");
7502   gtk_paned_pack1 (GTK_PANED (vpaned3), button19, FALSE, TRUE);
7503
7504   button18 = gtk_button_new_with_label ("button18");
7505   gtk_paned_pack2 (GTK_PANED (vpaned3), button18, TRUE, TRUE);
7506
7507   hbox3 = gtk_hbox_new (FALSE, 0);
7508   gtk_paned_pack2 (GTK_PANED (hpaned6), hbox3, TRUE, TRUE);
7509
7510   vpaned4 = gtk_vpaned_new ();
7511   gtk_box_pack_start (GTK_BOX (hbox3), vpaned4, TRUE, TRUE, 0);
7512
7513   button21 = gtk_button_new_with_label ("button21");
7514   gtk_paned_pack1 (GTK_PANED (vpaned4), button21, FALSE, TRUE);
7515
7516   button20 = gtk_button_new_with_label ("button20");
7517   gtk_paned_pack2 (GTK_PANED (vpaned4), button20, TRUE, TRUE);
7518
7519   vpaned5 = gtk_vpaned_new ();
7520   gtk_box_pack_start (GTK_BOX (hbox3), vpaned5, TRUE, TRUE, 0);
7521
7522   button23 = gtk_button_new_with_label ("button23");
7523   gtk_paned_pack1 (GTK_PANED (vpaned5), button23, FALSE, TRUE);
7524
7525   button22 = gtk_button_new_with_label ("button22");
7526   gtk_paned_pack2 (GTK_PANED (vpaned5), button22, TRUE, TRUE);
7527
7528   vpaned6 = gtk_vpaned_new ();
7529   gtk_box_pack_start (GTK_BOX (hbox3), vpaned6, TRUE, TRUE, 0);
7530
7531   button25 = gtk_button_new_with_label ("button25");
7532   gtk_paned_pack1 (GTK_PANED (vpaned6), button25, FALSE, TRUE);
7533
7534   button24 = gtk_button_new_with_label ("button24");
7535   gtk_paned_pack2 (GTK_PANED (vpaned6), button24, TRUE, TRUE);
7536
7537   return window4;
7538 }
7539
7540 static void
7541 create_paned_keyboard_navigation (GtkWidget *widget)
7542 {
7543   static GtkWidget *window1 = NULL;
7544   static GtkWidget *window2 = NULL;
7545   static GtkWidget *window3 = NULL;
7546   static GtkWidget *window4 = NULL;
7547
7548   if (window1 && 
7549      (gtk_widget_get_screen (window1) != gtk_widget_get_screen (widget)))
7550     {
7551       gtk_widget_destroy (window1);
7552       gtk_widget_destroy (window2);
7553       gtk_widget_destroy (window3);
7554       gtk_widget_destroy (window4);
7555     }
7556   
7557   if (!window1)
7558     {
7559       window1 = paned_keyboard_window1 (widget);
7560       g_signal_connect (window1, "destroy",
7561                         G_CALLBACK (gtk_widget_destroyed),
7562                         &window1);
7563     }
7564
7565   if (!window2)
7566     {
7567       window2 = paned_keyboard_window2 (widget);
7568       g_signal_connect (window2, "destroy",
7569                         G_CALLBACK (gtk_widget_destroyed),
7570                         &window2);
7571     }
7572
7573   if (!window3)
7574     {
7575       window3 = paned_keyboard_window3 (widget);
7576       g_signal_connect (window3, "destroy",
7577                         G_CALLBACK (gtk_widget_destroyed),
7578                         &window3);
7579     }
7580
7581   if (!window4)
7582     {
7583       window4 = paned_keyboard_window4 (widget);
7584       g_signal_connect (window4, "destroy",
7585                         G_CALLBACK (gtk_widget_destroyed),
7586                         &window4);
7587     }
7588
7589   if (gtk_widget_get_visible (window1))
7590     gtk_widget_destroy (GTK_WIDGET (window1));
7591   else
7592     gtk_widget_show_all (GTK_WIDGET (window1));
7593
7594   if (gtk_widget_get_visible (window2))
7595     gtk_widget_destroy (GTK_WIDGET (window2));
7596   else
7597     gtk_widget_show_all (GTK_WIDGET (window2));
7598
7599   if (gtk_widget_get_visible (window3))
7600     gtk_widget_destroy (GTK_WIDGET (window3));
7601   else
7602     gtk_widget_show_all (GTK_WIDGET (window3));
7603
7604   if (gtk_widget_get_visible (window4))
7605     gtk_widget_destroy (GTK_WIDGET (window4));
7606   else
7607     gtk_widget_show_all (GTK_WIDGET (window4));
7608 }
7609
7610
7611 /*
7612  * Shaped Windows
7613  */
7614
7615 typedef struct _cursoroffset {gint x,y;} CursorOffset;
7616
7617 static void
7618 shape_pressed (GtkWidget *widget, GdkEventButton *event)
7619 {
7620   CursorOffset *p;
7621
7622   /* ignore double and triple click */
7623   if (event->type != GDK_BUTTON_PRESS)
7624     return;
7625
7626   p = g_object_get_data (G_OBJECT (widget), "cursor_offset");
7627   p->x = (int) event->x;
7628   p->y = (int) event->y;
7629
7630   gtk_grab_add (widget);
7631   gdk_pointer_grab (widget->window, TRUE,
7632                     GDK_BUTTON_RELEASE_MASK |
7633                     GDK_BUTTON_MOTION_MASK |
7634                     GDK_POINTER_MOTION_HINT_MASK,
7635                     NULL, NULL, 0);
7636 }
7637
7638 static void
7639 shape_released (GtkWidget *widget)
7640 {
7641   gtk_grab_remove (widget);
7642   gdk_display_pointer_ungrab (gtk_widget_get_display (widget),
7643                               GDK_CURRENT_TIME);
7644 }
7645
7646 static void
7647 shape_motion (GtkWidget      *widget, 
7648               GdkEventMotion *event)
7649 {
7650   gint xp, yp;
7651   CursorOffset * p;
7652   GdkModifierType mask;
7653
7654   p = g_object_get_data (G_OBJECT (widget), "cursor_offset");
7655
7656   /*
7657    * Can't use event->x / event->y here 
7658    * because I need absolute coordinates.
7659    */
7660   gdk_window_get_pointer (NULL, &xp, &yp, &mask);
7661   gtk_window_move (GTK_WINDOW (widget), xp  - p->x, yp  - p->y);
7662 }
7663
7664 GtkWidget *
7665 shape_create_icon (GdkScreen *screen,
7666                    char      *xpm_file,
7667                    gint       x,
7668                    gint       y,
7669                    gint       px,
7670                    gint       py,
7671                    gint       window_type)
7672 {
7673   GtkWidget *window;
7674   GtkWidget *pixmap;
7675   GtkWidget *fixed;
7676   CursorOffset* icon_pos;
7677   GdkGC* gc;
7678   GdkBitmap *gdk_pixmap_mask;
7679   GdkPixmap *gdk_pixmap;
7680   GtkStyle *style;
7681
7682   style = gtk_widget_get_default_style ();
7683   gc = style->black_gc; 
7684
7685   /*
7686    * GDK_WINDOW_TOPLEVEL works also, giving you a title border
7687    */
7688   window = gtk_window_new (window_type);
7689   gtk_window_set_screen (GTK_WINDOW (window), screen);
7690   
7691   fixed = gtk_fixed_new ();
7692   gtk_widget_set_size_request (fixed, 100, 100);
7693   gtk_container_add (GTK_CONTAINER (window), fixed);
7694   gtk_widget_show (fixed);
7695   
7696   gtk_widget_set_events (window, 
7697                          gtk_widget_get_events (window) |
7698                          GDK_BUTTON_MOTION_MASK |
7699                          GDK_POINTER_MOTION_HINT_MASK |
7700                          GDK_BUTTON_PRESS_MASK);
7701
7702   gtk_widget_realize (window);
7703   gdk_pixmap = gdk_pixmap_create_from_xpm (window->window, &gdk_pixmap_mask, 
7704                                            &style->bg[GTK_STATE_NORMAL],
7705                                            xpm_file);
7706
7707   pixmap = gtk_image_new_from_pixmap (gdk_pixmap, gdk_pixmap_mask);
7708   gtk_fixed_put (GTK_FIXED (fixed), pixmap, px,py);
7709   gtk_widget_show (pixmap);
7710   
7711   gtk_widget_shape_combine_mask (window, gdk_pixmap_mask, px, py);
7712   
7713   g_object_unref (gdk_pixmap_mask);
7714   g_object_unref (gdk_pixmap);
7715
7716   g_signal_connect (window, "button_press_event",
7717                     G_CALLBACK (shape_pressed), NULL);
7718   g_signal_connect (window, "button_release_event",
7719                     G_CALLBACK (shape_released), NULL);
7720   g_signal_connect (window, "motion_notify_event",
7721                     G_CALLBACK (shape_motion), NULL);
7722
7723   icon_pos = g_new (CursorOffset, 1);
7724   g_object_set_data (G_OBJECT (window), "cursor_offset", icon_pos);
7725
7726   gtk_window_move (GTK_WINDOW (window), x, y);
7727   gtk_widget_show (window);
7728   
7729   return window;
7730 }
7731
7732 void 
7733 create_shapes (GtkWidget *widget)
7734 {
7735   /* Variables used by the Drag/Drop and Shape Window demos */
7736   static GtkWidget *modeller = NULL;
7737   static GtkWidget *sheets = NULL;
7738   static GtkWidget *rings = NULL;
7739   static GtkWidget *with_region = NULL;
7740   GdkScreen *screen = gtk_widget_get_screen (widget);
7741   
7742   if (!(file_exists ("Modeller.xpm") &&
7743         file_exists ("FilesQueue.xpm") &&
7744         file_exists ("3DRings.xpm")))
7745     return;
7746   
7747
7748   if (!modeller)
7749     {
7750       modeller = shape_create_icon (screen, "Modeller.xpm",
7751                                     440, 140, 0,0, GTK_WINDOW_POPUP);
7752
7753       g_signal_connect (modeller, "destroy",
7754                         G_CALLBACK (gtk_widget_destroyed),
7755                         &modeller);
7756     }
7757   else
7758     gtk_widget_destroy (modeller);
7759
7760   if (!sheets)
7761     {
7762       sheets = shape_create_icon (screen, "FilesQueue.xpm",
7763                                   580, 170, 0,0, GTK_WINDOW_POPUP);
7764
7765       g_signal_connect (sheets, "destroy",
7766                         G_CALLBACK (gtk_widget_destroyed),
7767                         &sheets);
7768
7769     }
7770   else
7771     gtk_widget_destroy (sheets);
7772
7773   if (!rings)
7774     {
7775       rings = shape_create_icon (screen, "3DRings.xpm",
7776                                  460, 270, 25,25, GTK_WINDOW_TOPLEVEL);
7777
7778       g_signal_connect (rings, "destroy",
7779                         G_CALLBACK (gtk_widget_destroyed),
7780                         &rings);
7781     }
7782   else
7783     gtk_widget_destroy (rings);
7784
7785   if (!with_region)
7786     {
7787       GdkRegion *region;
7788       gint x, y;
7789       
7790       with_region = shape_create_icon (screen, "3DRings.xpm",
7791                                        460, 270, 25,25, GTK_WINDOW_TOPLEVEL);
7792
7793       gtk_window_set_decorated (GTK_WINDOW (with_region), FALSE);
7794       
7795       g_signal_connect (with_region, "destroy",
7796                         G_CALLBACK (gtk_widget_destroyed),
7797                         &with_region);
7798
7799       /* reset shape from mask to a region */
7800       x = 0;
7801       y = 0;
7802       region = gdk_region_new ();
7803
7804       while (x < 460)
7805         {
7806           while (y < 270)
7807             {
7808               GdkRectangle rect;
7809               rect.x = x;
7810               rect.y = y;
7811               rect.width = 10;
7812               rect.height = 10;
7813
7814               gdk_region_union_with_rect (region, &rect);
7815               
7816               y += 20;
7817             }
7818           y = 0;
7819           x += 20;
7820         }
7821
7822       gdk_window_shape_combine_region (with_region->window,
7823                                        region,
7824                                        0, 0);
7825     }
7826   else
7827     gtk_widget_destroy (with_region);
7828 }
7829
7830 /*
7831  * WM Hints demo
7832  */
7833
7834 void
7835 create_wmhints (GtkWidget *widget)
7836 {
7837   static GtkWidget *window = NULL;
7838   GtkWidget *label;
7839   GtkWidget *separator;
7840   GtkWidget *button;
7841   GtkWidget *box1;
7842   GtkWidget *box2;
7843
7844   GdkBitmap *circles;
7845
7846   if (!window)
7847     {
7848       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7849
7850       gtk_window_set_screen (GTK_WINDOW (window),
7851                              gtk_widget_get_screen (widget));
7852       
7853       g_signal_connect (window, "destroy",
7854                         G_CALLBACK (gtk_widget_destroyed),
7855                         &window);
7856
7857       gtk_window_set_title (GTK_WINDOW (window), "WM Hints");
7858       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
7859
7860       gtk_widget_realize (window);
7861       
7862       circles = gdk_bitmap_create_from_data (window->window,
7863                                              (gchar *) circles_bits,
7864                                              circles_width,
7865                                              circles_height);
7866       gdk_window_set_icon (window->window, NULL,
7867                            circles, circles);
7868       
7869       gdk_window_set_icon_name (window->window, "WMHints Test Icon");
7870   
7871       gdk_window_set_decorations (window->window, GDK_DECOR_ALL | GDK_DECOR_MENU);
7872       gdk_window_set_functions (window->window, GDK_FUNC_ALL | GDK_FUNC_RESIZE);
7873       
7874       box1 = gtk_vbox_new (FALSE, 0);
7875       gtk_container_add (GTK_CONTAINER (window), box1);
7876       gtk_widget_show (box1);
7877
7878       label = gtk_label_new ("Try iconizing me!");
7879       gtk_widget_set_size_request (label, 150, 50);
7880       gtk_box_pack_start (GTK_BOX (box1), label, TRUE, TRUE, 0);
7881       gtk_widget_show (label);
7882
7883
7884       separator = gtk_hseparator_new ();
7885       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
7886       gtk_widget_show (separator);
7887
7888
7889       box2 = gtk_vbox_new (FALSE, 10);
7890       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
7891       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
7892       gtk_widget_show (box2);
7893
7894
7895       button = gtk_button_new_with_label ("close");
7896
7897       g_signal_connect_swapped (button, "clicked",
7898                                 G_CALLBACK (gtk_widget_destroy),
7899                                 window);
7900
7901       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
7902       gtk_widget_set_can_default (button, TRUE);
7903       gtk_widget_grab_default (button);
7904       gtk_widget_show (button);
7905     }
7906
7907   if (!gtk_widget_get_visible (window))
7908     gtk_widget_show (window);
7909   else
7910     gtk_widget_destroy (window);
7911 }
7912
7913
7914 /*
7915  * Window state tracking
7916  */
7917
7918 static gint
7919 window_state_callback (GtkWidget *widget,
7920                        GdkEventWindowState *event,
7921                        gpointer data)
7922 {
7923   GtkWidget *label = data;
7924   gchar *msg;
7925
7926   msg = g_strconcat (GTK_WINDOW (widget)->title, ": ",
7927                      (event->new_window_state & GDK_WINDOW_STATE_WITHDRAWN) ?
7928                      "withdrawn" : "not withdrawn", ", ",
7929                      (event->new_window_state & GDK_WINDOW_STATE_ICONIFIED) ?
7930                      "iconified" : "not iconified", ", ",
7931                      (event->new_window_state & GDK_WINDOW_STATE_STICKY) ?
7932                      "sticky" : "not sticky", ", ",
7933                      (event->new_window_state & GDK_WINDOW_STATE_MAXIMIZED) ?
7934                      "maximized" : "not maximized", ", ",
7935                      (event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN) ?
7936                      "fullscreen" : "not fullscreen",
7937                      (event->new_window_state & GDK_WINDOW_STATE_ABOVE) ?
7938                      "above" : "not above", ", ",
7939                      (event->new_window_state & GDK_WINDOW_STATE_BELOW) ?
7940                      "below" : "not below", ", ",
7941                      NULL);
7942   
7943   gtk_label_set_text (GTK_LABEL (label), msg);
7944
7945   g_free (msg);
7946
7947   return FALSE;
7948 }
7949
7950 static GtkWidget*
7951 tracking_label (GtkWidget *window)
7952 {
7953   GtkWidget *label;
7954   GtkWidget *hbox;
7955   GtkWidget *button;
7956
7957   hbox = gtk_hbox_new (FALSE, 5);
7958
7959   g_signal_connect_object (hbox,
7960                            "destroy",
7961                            G_CALLBACK (gtk_widget_destroy),
7962                            window,
7963                            G_CONNECT_SWAPPED);
7964   
7965   label = gtk_label_new ("<no window state events received>");
7966   gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
7967   gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
7968   
7969   g_signal_connect (window,
7970                     "window_state_event",
7971                     G_CALLBACK (window_state_callback),
7972                     label);
7973
7974   button = gtk_button_new_with_label ("Deiconify");
7975   g_signal_connect_object (button,
7976                            "clicked",
7977                            G_CALLBACK (gtk_window_deiconify),
7978                            window,
7979                            G_CONNECT_SWAPPED);
7980   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
7981
7982   button = gtk_button_new_with_label ("Iconify");
7983   g_signal_connect_object (button,
7984                            "clicked",
7985                            G_CALLBACK (gtk_window_iconify),
7986                            window,
7987                            G_CONNECT_SWAPPED);
7988   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
7989
7990   button = gtk_button_new_with_label ("Fullscreen");
7991   g_signal_connect_object (button,
7992                            "clicked",
7993                            G_CALLBACK (gtk_window_fullscreen),
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 ("Unfullscreen");
7999   g_signal_connect_object (button,
8000                            "clicked",
8001                            G_CALLBACK (gtk_window_unfullscreen),
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 ("Present");
8007   g_signal_connect_object (button,
8008                            "clicked",
8009                            G_CALLBACK (gtk_window_present),
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 ("Show");
8015   g_signal_connect_object (button,
8016                            "clicked",
8017                            G_CALLBACK (gtk_widget_show),
8018                            window,
8019                            G_CONNECT_SWAPPED);
8020   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
8021   
8022   gtk_widget_show_all (hbox);
8023   
8024   return hbox;
8025 }
8026
8027 void
8028 keep_window_above (GtkToggleButton *togglebutton, gpointer data)
8029 {
8030   GtkWidget *button = g_object_get_data (G_OBJECT (togglebutton), "radio");
8031
8032   gtk_window_set_keep_above (GTK_WINDOW (data),
8033                              gtk_toggle_button_get_active (togglebutton));
8034
8035   if (gtk_toggle_button_get_active (togglebutton))
8036     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE);
8037 }
8038
8039 void
8040 keep_window_below (GtkToggleButton *togglebutton, gpointer data)
8041 {
8042   GtkWidget *button = g_object_get_data (G_OBJECT (togglebutton), "radio");
8043
8044   gtk_window_set_keep_below (GTK_WINDOW (data),
8045                              gtk_toggle_button_get_active (togglebutton));
8046
8047   if (gtk_toggle_button_get_active (togglebutton))
8048     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE);
8049 }
8050
8051
8052 static GtkWidget*
8053 get_state_controls (GtkWidget *window)
8054 {
8055   GtkWidget *vbox;
8056   GtkWidget *button;
8057   GtkWidget *button_above;
8058   GtkWidget *button_below;
8059
8060   vbox = gtk_vbox_new (FALSE, 0);
8061   
8062   button = gtk_button_new_with_label ("Stick");
8063   g_signal_connect_object (button,
8064                            "clicked",
8065                            G_CALLBACK (gtk_window_stick),
8066                            window,
8067                            G_CONNECT_SWAPPED);
8068   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8069
8070   button = gtk_button_new_with_label ("Unstick");
8071   g_signal_connect_object (button,
8072                            "clicked",
8073                            G_CALLBACK (gtk_window_unstick),
8074                            window,
8075                            G_CONNECT_SWAPPED);
8076   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8077   
8078   button = gtk_button_new_with_label ("Maximize");
8079   g_signal_connect_object (button,
8080                            "clicked",
8081                            G_CALLBACK (gtk_window_maximize),
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 ("Unmaximize");
8087   g_signal_connect_object (button,
8088                            "clicked",
8089                            G_CALLBACK (gtk_window_unmaximize),
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 ("Iconify");
8095   g_signal_connect_object (button,
8096                            "clicked",
8097                            G_CALLBACK (gtk_window_iconify),
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 ("Fullscreen");
8103   g_signal_connect_object (button,
8104                            "clicked",
8105                            G_CALLBACK (gtk_window_fullscreen),
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 ("Unfullscreen");
8111   g_signal_connect_object (button,
8112                            "clicked",
8113                            G_CALLBACK (gtk_window_unfullscreen),
8114                            window,
8115                            G_CONNECT_SWAPPED);
8116   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8117
8118   button_above = gtk_toggle_button_new_with_label ("Keep above");
8119   g_signal_connect (button_above,
8120                     "toggled",
8121                     G_CALLBACK (keep_window_above),
8122                     window);
8123   gtk_box_pack_start (GTK_BOX (vbox), button_above, FALSE, FALSE, 0);
8124
8125   button_below = gtk_toggle_button_new_with_label ("Keep below");
8126   g_signal_connect (button_below,
8127                     "toggled",
8128                     G_CALLBACK (keep_window_below),
8129                     window);
8130   gtk_box_pack_start (GTK_BOX (vbox), button_below, FALSE, FALSE, 0);
8131
8132   g_object_set_data (G_OBJECT (button_above), "radio", button_below);
8133   g_object_set_data (G_OBJECT (button_below), "radio", button_above);
8134
8135   button = gtk_button_new_with_label ("Hide (withdraw)");
8136   g_signal_connect_object (button,
8137                            "clicked",
8138                            G_CALLBACK (gtk_widget_hide),
8139                            window,
8140                            G_CONNECT_SWAPPED);
8141   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8142   
8143   gtk_widget_show_all (vbox);
8144
8145   return vbox;
8146 }
8147
8148 void
8149 create_window_states (GtkWidget *widget)
8150 {
8151   static GtkWidget *window = NULL;
8152   GtkWidget *label;
8153   GtkWidget *box1;
8154   GtkWidget *iconified;
8155   GtkWidget *normal;
8156   GtkWidget *controls;
8157
8158   if (!window)
8159     {
8160       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8161       gtk_window_set_screen (GTK_WINDOW (window),
8162                              gtk_widget_get_screen (widget));
8163
8164       g_signal_connect (window, "destroy",
8165                         G_CALLBACK (gtk_widget_destroyed),
8166                         &window);
8167
8168       gtk_window_set_title (GTK_WINDOW (window), "Window states");
8169       
8170       box1 = gtk_vbox_new (FALSE, 0);
8171       gtk_container_add (GTK_CONTAINER (window), box1);
8172
8173       iconified = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8174
8175       gtk_window_set_screen (GTK_WINDOW (iconified),
8176                              gtk_widget_get_screen (widget));
8177       
8178       g_signal_connect_object (iconified, "destroy",
8179                                G_CALLBACK (gtk_widget_destroy),
8180                                window,
8181                                G_CONNECT_SWAPPED);
8182       gtk_window_iconify (GTK_WINDOW (iconified));
8183       gtk_window_set_title (GTK_WINDOW (iconified), "Iconified initially");
8184       controls = get_state_controls (iconified);
8185       gtk_container_add (GTK_CONTAINER (iconified), controls);
8186       
8187       normal = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8188
8189       gtk_window_set_screen (GTK_WINDOW (normal),
8190                              gtk_widget_get_screen (widget));
8191       
8192       g_signal_connect_object (normal, "destroy",
8193                                G_CALLBACK (gtk_widget_destroy),
8194                                window,
8195                                G_CONNECT_SWAPPED);
8196       
8197       gtk_window_set_title (GTK_WINDOW (normal), "Deiconified initially");
8198       controls = get_state_controls (normal);
8199       gtk_container_add (GTK_CONTAINER (normal), controls);
8200       
8201       label = tracking_label (iconified);
8202       gtk_container_add (GTK_CONTAINER (box1), label);
8203
8204       label = tracking_label (normal);
8205       gtk_container_add (GTK_CONTAINER (box1), label);
8206
8207       gtk_widget_show_all (iconified);
8208       gtk_widget_show_all (normal);
8209       gtk_widget_show_all (box1);
8210     }
8211
8212   if (!gtk_widget_get_visible (window))
8213     gtk_widget_show (window);
8214   else
8215     gtk_widget_destroy (window);
8216 }
8217
8218 /*
8219  * Window sizing
8220  */
8221
8222 static gint
8223 configure_event_callback (GtkWidget *widget,
8224                           GdkEventConfigure *event,
8225                           gpointer data)
8226 {
8227   GtkWidget *label = data;
8228   gchar *msg;
8229   gint x, y;
8230   
8231   gtk_window_get_position (GTK_WINDOW (widget), &x, &y);
8232   
8233   msg = g_strdup_printf ("event: %d,%d  %d x %d\n"
8234                          "position: %d, %d",
8235                          event->x, event->y, event->width, event->height,
8236                          x, y);
8237   
8238   gtk_label_set_text (GTK_LABEL (label), msg);
8239
8240   g_free (msg);
8241
8242   return FALSE;
8243 }
8244
8245 static void
8246 get_ints (GtkWidget *window,
8247           gint      *a,
8248           gint      *b)
8249 {
8250   GtkWidget *spin1;
8251   GtkWidget *spin2;
8252
8253   spin1 = g_object_get_data (G_OBJECT (window), "spin1");
8254   spin2 = g_object_get_data (G_OBJECT (window), "spin2");
8255
8256   *a = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (spin1));
8257   *b = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (spin2));
8258 }
8259
8260 static void
8261 set_size_callback (GtkWidget *widget,
8262                    gpointer   data)
8263 {
8264   gint w, h;
8265   
8266   get_ints (data, &w, &h);
8267
8268   gtk_window_resize (GTK_WINDOW (g_object_get_data (data, "target")), w, h);
8269 }
8270
8271 static void
8272 unset_default_size_callback (GtkWidget *widget,
8273                              gpointer   data)
8274 {
8275   gtk_window_set_default_size (g_object_get_data (data, "target"),
8276                                -1, -1);
8277 }
8278
8279 static void
8280 set_default_size_callback (GtkWidget *widget,
8281                            gpointer   data)
8282 {
8283   gint w, h;
8284   
8285   get_ints (data, &w, &h);
8286
8287   gtk_window_set_default_size (g_object_get_data (data, "target"),
8288                                w, h);
8289 }
8290
8291 static void
8292 unset_size_request_callback (GtkWidget *widget,
8293                              gpointer   data)
8294 {
8295   gtk_widget_set_size_request (g_object_get_data (data, "target"),
8296                                -1, -1);
8297 }
8298
8299 static void
8300 set_size_request_callback (GtkWidget *widget,
8301                            gpointer   data)
8302 {
8303   gint w, h;
8304   
8305   get_ints (data, &w, &h);
8306
8307   gtk_widget_set_size_request (g_object_get_data (data, "target"),
8308                                w, h);
8309 }
8310
8311 static void
8312 set_location_callback (GtkWidget *widget,
8313                        gpointer   data)
8314 {
8315   gint x, y;
8316   
8317   get_ints (data, &x, &y);
8318
8319   gtk_window_move (g_object_get_data (data, "target"), x, y);
8320 }
8321
8322 static void
8323 move_to_position_callback (GtkWidget *widget,
8324                            gpointer   data)
8325 {
8326   gint x, y;
8327   GtkWindow *window;
8328
8329   window = g_object_get_data (data, "target");
8330   
8331   gtk_window_get_position (window, &x, &y);
8332
8333   gtk_window_move (window, x, y);
8334 }
8335
8336 static void
8337 set_geometry_callback (GtkWidget *entry,
8338                        gpointer   data)
8339 {
8340   gchar *text;
8341   GtkWindow *target;
8342
8343   target = GTK_WINDOW (g_object_get_data (G_OBJECT (data), "target"));
8344   
8345   text = gtk_editable_get_chars (GTK_EDITABLE (entry), 0, -1);
8346
8347   if (!gtk_window_parse_geometry (target, text))
8348     g_print ("Bad geometry string '%s'\n", text);
8349
8350   g_free (text);
8351 }
8352
8353 static void
8354 allow_shrink_callback (GtkWidget *widget,
8355                        gpointer   data)
8356 {
8357   g_object_set (g_object_get_data (data, "target"),
8358                 "allow_shrink",
8359                 GTK_TOGGLE_BUTTON (widget)->active,
8360                 NULL);
8361 }
8362
8363 static void
8364 allow_grow_callback (GtkWidget *widget,
8365                      gpointer   data)
8366 {
8367   g_object_set (g_object_get_data (data, "target"),
8368                 "allow_grow",
8369                 GTK_TOGGLE_BUTTON (widget)->active,
8370                 NULL);
8371 }
8372
8373 static void
8374 gravity_selected (GtkWidget *widget,
8375                   gpointer   data)
8376 {
8377   gtk_window_set_gravity (GTK_WINDOW (g_object_get_data (data, "target")),
8378                           gtk_combo_box_get_active (GTK_COMBO_BOX (widget)) + GDK_GRAVITY_NORTH_WEST);
8379 }
8380
8381 static void
8382 pos_selected (GtkWidget *widget,
8383               gpointer   data)
8384 {
8385   gtk_window_set_position (GTK_WINDOW (g_object_get_data (data, "target")),
8386                            gtk_combo_box_get_active (GTK_COMBO_BOX (widget)) + GTK_WIN_POS_NONE);
8387 }
8388
8389 static void
8390 move_gravity_window_to_current_position (GtkWidget *widget,
8391                                          gpointer   data)
8392 {
8393   gint x, y;
8394   GtkWindow *window;
8395
8396   window = GTK_WINDOW (data);    
8397   
8398   gtk_window_get_position (window, &x, &y);
8399
8400   gtk_window_move (window, x, y);
8401 }
8402
8403 static void
8404 get_screen_corner (GtkWindow *window,
8405                    gint      *x,
8406                    gint      *y)
8407 {
8408   int w, h;
8409   GdkScreen * screen = gtk_window_get_screen (window);
8410   
8411   gtk_window_get_size (GTK_WINDOW (window), &w, &h);
8412
8413   switch (gtk_window_get_gravity (window))
8414     {
8415     case GDK_GRAVITY_SOUTH_EAST:
8416       *x = gdk_screen_get_width (screen) - w;
8417       *y = gdk_screen_get_height (screen) - h;
8418       break;
8419
8420     case GDK_GRAVITY_NORTH_EAST:
8421       *x = gdk_screen_get_width (screen) - w;
8422       *y = 0;
8423       break;
8424
8425     case GDK_GRAVITY_SOUTH_WEST:
8426       *x = 0;
8427       *y = gdk_screen_get_height (screen) - h;
8428       break;
8429
8430     case GDK_GRAVITY_NORTH_WEST:
8431       *x = 0;
8432       *y = 0;
8433       break;
8434       
8435     case GDK_GRAVITY_SOUTH:
8436       *x = (gdk_screen_get_width (screen) - w) / 2;
8437       *y = gdk_screen_get_height (screen) - h;
8438       break;
8439
8440     case GDK_GRAVITY_NORTH:
8441       *x = (gdk_screen_get_width (screen) - w) / 2;
8442       *y = 0;
8443       break;
8444
8445     case GDK_GRAVITY_WEST:
8446       *x = 0;
8447       *y = (gdk_screen_get_height (screen) - h) / 2;
8448       break;
8449
8450     case GDK_GRAVITY_EAST:
8451       *x = gdk_screen_get_width (screen) - w;
8452       *y = (gdk_screen_get_height (screen) - h) / 2;
8453       break;
8454
8455     case GDK_GRAVITY_CENTER:
8456       *x = (gdk_screen_get_width (screen) - w) / 2;
8457       *y = (gdk_screen_get_height (screen) - h) / 2;
8458       break;
8459
8460     case GDK_GRAVITY_STATIC:
8461       /* pick some random numbers */
8462       *x = 350;
8463       *y = 350;
8464       break;
8465
8466     default:
8467       g_assert_not_reached ();
8468       break;
8469     }
8470 }
8471
8472 static void
8473 move_gravity_window_to_starting_position (GtkWidget *widget,
8474                                           gpointer   data)
8475 {
8476   gint x, y;
8477   GtkWindow *window;
8478
8479   window = GTK_WINDOW (data);    
8480   
8481   get_screen_corner (window,
8482                      &x, &y);
8483   
8484   gtk_window_move (window, x, y);
8485 }
8486
8487 static GtkWidget*
8488 make_gravity_window (GtkWidget   *destroy_with,
8489                      GdkGravity   gravity,
8490                      const gchar *title)
8491 {
8492   GtkWidget *window;
8493   GtkWidget *button;
8494   GtkWidget *vbox;
8495   int x, y;
8496   
8497   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8498
8499   gtk_window_set_screen (GTK_WINDOW (window),
8500                          gtk_widget_get_screen (destroy_with));
8501
8502   vbox = gtk_vbox_new (FALSE, 0);
8503   gtk_widget_show (vbox);
8504   
8505   gtk_container_add (GTK_CONTAINER (window), vbox);
8506   gtk_window_set_title (GTK_WINDOW (window), title);
8507   gtk_window_set_gravity (GTK_WINDOW (window), gravity);
8508
8509   g_signal_connect_object (destroy_with,
8510                            "destroy",
8511                            G_CALLBACK (gtk_widget_destroy),
8512                            window,
8513                            G_CONNECT_SWAPPED);
8514
8515   
8516   button = gtk_button_new_with_mnemonic ("_Move to current position");
8517
8518   g_signal_connect (button, "clicked",
8519                     G_CALLBACK (move_gravity_window_to_current_position),
8520                     window);
8521
8522   gtk_container_add (GTK_CONTAINER (vbox), button);
8523   gtk_widget_show (button);
8524
8525   button = gtk_button_new_with_mnemonic ("Move to _starting position");
8526
8527   g_signal_connect (button, "clicked",
8528                     G_CALLBACK (move_gravity_window_to_starting_position),
8529                     window);
8530
8531   gtk_container_add (GTK_CONTAINER (vbox), button);
8532   gtk_widget_show (button);
8533   
8534   /* Pretend this is the result of --geometry.
8535    * DO NOT COPY THIS CODE unless you are setting --geometry results,
8536    * and in that case you probably should just use gtk_window_parse_geometry().
8537    * AGAIN, DO NOT SET GDK_HINT_USER_POS! It violates the ICCCM unless
8538    * you are parsing --geometry or equivalent.
8539    */
8540   gtk_window_set_geometry_hints (GTK_WINDOW (window),
8541                                  NULL, NULL,
8542                                  GDK_HINT_USER_POS);
8543
8544   gtk_window_set_default_size (GTK_WINDOW (window),
8545                                200, 200);
8546
8547   get_screen_corner (GTK_WINDOW (window), &x, &y);
8548   
8549   gtk_window_move (GTK_WINDOW (window),
8550                    x, y);
8551   
8552   return window;
8553 }
8554
8555 static void
8556 do_gravity_test (GtkWidget *widget,
8557                  gpointer   data)
8558 {
8559   GtkWidget *destroy_with = data;
8560   GtkWidget *window;
8561   
8562   /* We put a window at each gravity point on the screen. */
8563   window = make_gravity_window (destroy_with, GDK_GRAVITY_NORTH_WEST,
8564                                 "NorthWest");
8565   gtk_widget_show (window);
8566   
8567   window = make_gravity_window (destroy_with, GDK_GRAVITY_SOUTH_EAST,
8568                                 "SouthEast");
8569   gtk_widget_show (window);
8570
8571   window = make_gravity_window (destroy_with, GDK_GRAVITY_NORTH_EAST,
8572                                 "NorthEast");
8573   gtk_widget_show (window);
8574
8575   window = make_gravity_window (destroy_with, GDK_GRAVITY_SOUTH_WEST,
8576                                 "SouthWest");
8577   gtk_widget_show (window);
8578
8579   window = make_gravity_window (destroy_with, GDK_GRAVITY_SOUTH,
8580                                 "South");
8581   gtk_widget_show (window);
8582
8583   window = make_gravity_window (destroy_with, GDK_GRAVITY_NORTH,
8584                                 "North");
8585   gtk_widget_show (window);
8586
8587   
8588   window = make_gravity_window (destroy_with, GDK_GRAVITY_WEST,
8589                                 "West");
8590   gtk_widget_show (window);
8591
8592     
8593   window = make_gravity_window (destroy_with, GDK_GRAVITY_EAST,
8594                                 "East");
8595   gtk_widget_show (window);
8596
8597   window = make_gravity_window (destroy_with, GDK_GRAVITY_CENTER,
8598                                 "Center");
8599   gtk_widget_show (window);
8600
8601   window = make_gravity_window (destroy_with, GDK_GRAVITY_STATIC,
8602                                 "Static");
8603   gtk_widget_show (window);
8604 }
8605
8606 static GtkWidget*
8607 window_controls (GtkWidget *window)
8608 {
8609   GtkWidget *control_window;
8610   GtkWidget *label;
8611   GtkWidget *vbox;
8612   GtkWidget *button;
8613   GtkWidget *spin;
8614   GtkAdjustment *adj;
8615   GtkWidget *entry;
8616   GtkWidget *om;
8617   gint i;
8618   
8619   control_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8620
8621   gtk_window_set_screen (GTK_WINDOW (control_window),
8622                          gtk_widget_get_screen (window));
8623
8624   gtk_window_set_title (GTK_WINDOW (control_window), "Size controls");
8625   
8626   g_object_set_data (G_OBJECT (control_window),
8627                      "target",
8628                      window);
8629   
8630   g_signal_connect_object (control_window,
8631                            "destroy",
8632                            G_CALLBACK (gtk_widget_destroy),
8633                            window,
8634                            G_CONNECT_SWAPPED);
8635
8636   vbox = gtk_vbox_new (FALSE, 5);
8637   
8638   gtk_container_add (GTK_CONTAINER (control_window), vbox);
8639   
8640   label = gtk_label_new ("<no configure events>");
8641   gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
8642   
8643   g_signal_connect (window,
8644                     "configure_event",
8645                     G_CALLBACK (configure_event_callback),
8646                     label);
8647
8648   adj = (GtkAdjustment *) gtk_adjustment_new (10.0, -2000.0, 2000.0, 1.0,
8649                                               5.0, 0.0);
8650   spin = gtk_spin_button_new (adj, 0, 0);
8651
8652   gtk_box_pack_start (GTK_BOX (vbox), spin, FALSE, FALSE, 0);
8653
8654   g_object_set_data (G_OBJECT (control_window), "spin1", spin);
8655
8656   adj = (GtkAdjustment *) gtk_adjustment_new (10.0, -2000.0, 2000.0, 1.0,
8657                                               5.0, 0.0);
8658   spin = gtk_spin_button_new (adj, 0, 0);
8659
8660   gtk_box_pack_start (GTK_BOX (vbox), spin, FALSE, FALSE, 0);
8661
8662   g_object_set_data (G_OBJECT (control_window), "spin2", spin);
8663
8664   entry = gtk_entry_new ();
8665   gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
8666
8667   g_signal_connect (entry, "changed",
8668                     G_CALLBACK (set_geometry_callback),
8669                     control_window);
8670
8671   button = gtk_button_new_with_label ("Show gravity test windows");
8672   g_signal_connect_swapped (button,
8673                             "clicked",
8674                             G_CALLBACK (do_gravity_test),
8675                             control_window);
8676   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8677
8678   button = gtk_button_new_with_label ("Reshow with initial size");
8679   g_signal_connect_object (button,
8680                            "clicked",
8681                            G_CALLBACK (gtk_window_reshow_with_initial_size),
8682                            window,
8683                            G_CONNECT_SWAPPED);
8684   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8685   
8686   button = gtk_button_new_with_label ("Queue resize");
8687   g_signal_connect_object (button,
8688                            "clicked",
8689                            G_CALLBACK (gtk_widget_queue_resize),
8690                            window,
8691                            G_CONNECT_SWAPPED);
8692   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8693   
8694   button = gtk_button_new_with_label ("Resize");
8695   g_signal_connect (button,
8696                     "clicked",
8697                     G_CALLBACK (set_size_callback),
8698                     control_window);
8699   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8700
8701   button = gtk_button_new_with_label ("Set default size");
8702   g_signal_connect (button,
8703                     "clicked",
8704                     G_CALLBACK (set_default_size_callback),
8705                     control_window);
8706   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8707
8708   button = gtk_button_new_with_label ("Unset default size");
8709   g_signal_connect (button,
8710                     "clicked",
8711                     G_CALLBACK (unset_default_size_callback),
8712                     control_window);
8713   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8714   
8715   button = gtk_button_new_with_label ("Set size request");
8716   g_signal_connect (button,
8717                     "clicked",
8718                     G_CALLBACK (set_size_request_callback),
8719                     control_window);
8720   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8721
8722   button = gtk_button_new_with_label ("Unset size request");
8723   g_signal_connect (button,
8724                     "clicked",
8725                     G_CALLBACK (unset_size_request_callback),
8726                     control_window);
8727   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8728   
8729   button = gtk_button_new_with_label ("Move");
8730   g_signal_connect (button,
8731                     "clicked",
8732                     G_CALLBACK (set_location_callback),
8733                     control_window);
8734   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8735
8736   button = gtk_button_new_with_label ("Move to current position");
8737   g_signal_connect (button,
8738                     "clicked",
8739                     G_CALLBACK (move_to_position_callback),
8740                     control_window);
8741   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8742   
8743   button = gtk_check_button_new_with_label ("Allow shrink");
8744   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE);
8745   g_signal_connect (button,
8746                     "toggled",
8747                     G_CALLBACK (allow_shrink_callback),
8748                     control_window);
8749   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8750
8751   button = gtk_check_button_new_with_label ("Allow grow");
8752   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
8753   g_signal_connect (button,
8754                     "toggled",
8755                     G_CALLBACK (allow_grow_callback),
8756                     control_window);
8757   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8758   
8759   button = gtk_button_new_with_mnemonic ("_Show");
8760   g_signal_connect_object (button,
8761                            "clicked",
8762                            G_CALLBACK (gtk_widget_show),
8763                            window,
8764                            G_CONNECT_SWAPPED);
8765   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8766
8767   button = gtk_button_new_with_mnemonic ("_Hide");
8768   g_signal_connect_object (button,
8769                            "clicked",
8770                            G_CALLBACK (gtk_widget_hide),
8771                            window,
8772                            G_CONNECT_SWAPPED);
8773   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
8774   
8775   om = gtk_combo_box_new_text ();
8776   i = 0;
8777   while (i < 10)
8778     {
8779       static gchar *names[] = {
8780         "GDK_GRAVITY_NORTH_WEST",
8781         "GDK_GRAVITY_NORTH",
8782         "GDK_GRAVITY_NORTH_EAST",
8783         "GDK_GRAVITY_WEST",
8784         "GDK_GRAVITY_CENTER",
8785         "GDK_GRAVITY_EAST",
8786         "GDK_GRAVITY_SOUTH_WEST",
8787         "GDK_GRAVITY_SOUTH",
8788         "GDK_GRAVITY_SOUTH_EAST",
8789         "GDK_GRAVITY_STATIC",
8790         NULL
8791       };
8792
8793       g_assert (names[i]);
8794       gtk_combo_box_append_text (GTK_COMBO_BOX (om), names[i]);
8795
8796       ++i;
8797     }
8798   
8799   g_signal_connect (om,
8800                     "changed",
8801                     G_CALLBACK (gravity_selected),
8802                     control_window);
8803
8804   gtk_box_pack_end (GTK_BOX (vbox), om, FALSE, FALSE, 0);
8805
8806
8807   om = gtk_combo_box_new_text ();
8808   i = 0;
8809   while (i < 5)
8810     {
8811       static gchar *names[] = {
8812         "GTK_WIN_POS_NONE",
8813         "GTK_WIN_POS_CENTER",
8814         "GTK_WIN_POS_MOUSE",
8815         "GTK_WIN_POS_CENTER_ALWAYS",
8816         "GTK_WIN_POS_CENTER_ON_PARENT",
8817         NULL
8818       };
8819
8820       g_assert (names[i]);
8821       gtk_combo_box_append_text (GTK_COMBO_BOX (om), names[i]);
8822
8823       ++i;
8824     }
8825
8826   g_signal_connect (om,
8827                     "changed",
8828                     G_CALLBACK (pos_selected),
8829                     control_window);
8830
8831   gtk_box_pack_end (GTK_BOX (vbox), om, FALSE, FALSE, 0);
8832   
8833   gtk_widget_show_all (vbox);
8834   
8835   return control_window;
8836 }
8837
8838 void
8839 create_window_sizing (GtkWidget *widget)
8840 {
8841   static GtkWidget *window = NULL;
8842   static GtkWidget *target_window = NULL;
8843
8844   if (!target_window)
8845     {
8846       GtkWidget *label;
8847       
8848       target_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8849       gtk_window_set_screen (GTK_WINDOW (target_window),
8850                              gtk_widget_get_screen (widget));
8851       label = gtk_label_new (NULL);
8852       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");
8853       gtk_container_add (GTK_CONTAINER (target_window), label);
8854       gtk_widget_show (label);
8855       
8856       g_signal_connect (target_window, "destroy",
8857                         G_CALLBACK (gtk_widget_destroyed),
8858                         &target_window);
8859
8860       window = window_controls (target_window);
8861       
8862       g_signal_connect (window, "destroy",
8863                         G_CALLBACK (gtk_widget_destroyed),
8864                         &window);
8865       
8866       gtk_window_set_title (GTK_WINDOW (target_window), "Window to size");
8867     }
8868
8869   /* don't show target window by default, we want to allow testing
8870    * of behavior on first show.
8871    */
8872   
8873   if (!gtk_widget_get_visible (window))
8874     gtk_widget_show (window);
8875   else
8876     gtk_widget_destroy (window);
8877 }
8878
8879 /*
8880  * GtkProgressBar
8881  */
8882
8883 typedef struct _ProgressData {
8884   GtkWidget *window;
8885   GtkWidget *pbar;
8886   GtkWidget *block_spin;
8887   GtkWidget *x_align_spin;
8888   GtkWidget *y_align_spin;
8889   GtkWidget *step_spin;
8890   GtkWidget *act_blocks_spin;
8891   GtkWidget *label;
8892   GtkWidget *omenu1;
8893   GtkWidget *elmenu;
8894   GtkWidget *omenu2;
8895   GtkWidget *entry;
8896   int timer;
8897   gboolean activity;
8898 } ProgressData;
8899
8900 gboolean
8901 progress_timeout (gpointer data)
8902 {
8903   ProgressData *pdata = data;
8904   gdouble new_val;
8905
8906   if (pdata->activity)
8907     {
8908       gtk_progress_bar_pulse (GTK_PROGRESS_BAR (pdata->pbar));
8909       return TRUE;
8910     }
8911
8912   new_val = gtk_progress_bar_get_fraction (GTK_PROGRESS_BAR (pdata->pbar)) + 0.01;
8913   if (new_val > 1.00)
8914     new_val = 0.00;
8915
8916   gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (pdata->pbar), new_val);
8917
8918   return TRUE;
8919 }
8920
8921 static void
8922 destroy_progress (GtkWidget     *widget,
8923                   ProgressData **pdata)
8924 {
8925   g_source_remove ((*pdata)->timer);
8926   (*pdata)->timer = 0;
8927   (*pdata)->window = NULL;
8928   g_free (*pdata);
8929   *pdata = NULL;
8930 }
8931
8932 static void
8933 progressbar_toggle_orientation (GtkWidget *widget, gpointer data)
8934 {
8935   ProgressData *pdata;
8936   gint i;
8937
8938   pdata = (ProgressData *) data;
8939
8940   if (!gtk_widget_get_mapped (widget))
8941     return;
8942
8943   i = gtk_combo_box_get_active (GTK_COMBO_BOX (widget));
8944
8945   gtk_progress_bar_set_orientation (GTK_PROGRESS_BAR (pdata->pbar),
8946                                     (GtkProgressBarOrientation) i);
8947 }
8948
8949 static void
8950 toggle_show_text (GtkWidget *widget, ProgressData *pdata)
8951 {
8952   gtk_progress_set_show_text (GTK_PROGRESS (pdata->pbar),
8953                               GTK_TOGGLE_BUTTON (widget)->active);
8954   gtk_widget_set_sensitive (pdata->entry, GTK_TOGGLE_BUTTON (widget)->active);
8955 }
8956
8957 static void
8958 progressbar_toggle_ellipsize (GtkWidget *widget,
8959                               gpointer   data)
8960 {
8961   ProgressData *pdata = data;
8962   if (gtk_widget_is_drawable (widget))
8963     {
8964       gint i = gtk_combo_box_get_active (GTK_COMBO_BOX (widget));
8965       gtk_progress_bar_set_ellipsize (GTK_PROGRESS_BAR (pdata->pbar), i);
8966     }
8967 }
8968
8969 static void
8970 progress_value_changed (GtkAdjustment *adj, ProgressData *pdata)
8971 {
8972   char buf[20];
8973
8974   if (GTK_PROGRESS (pdata->pbar)->activity_mode)
8975     sprintf (buf, "???");
8976   else
8977     sprintf (buf, "%.0f%%", 100 *
8978       gtk_progress_bar_get_fraction (GTK_PROGRESS_BAR (pdata->pbar)));
8979   gtk_label_set_text (GTK_LABEL (pdata->label), buf);
8980 }
8981
8982 static void
8983 adjust_align (GtkAdjustment *adj, ProgressData *pdata)
8984 {
8985   gtk_progress_set_text_alignment (GTK_PROGRESS (pdata->pbar),
8986          gtk_spin_button_get_value (GTK_SPIN_BUTTON (pdata->x_align_spin)),
8987          gtk_spin_button_get_value (GTK_SPIN_BUTTON (pdata->y_align_spin)));
8988 }
8989
8990 static void
8991 toggle_activity_mode (GtkWidget *widget, ProgressData *pdata)
8992 {
8993   pdata->activity = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
8994 }
8995
8996 static void
8997 entry_changed (GtkWidget *widget, ProgressData *pdata)
8998 {
8999   gtk_progress_bar_set_text (GTK_PROGRESS_BAR (pdata->pbar),
9000                           gtk_entry_get_text (GTK_ENTRY (pdata->entry)));
9001 }
9002
9003 void
9004 create_progress_bar (GtkWidget *widget)
9005 {
9006   GtkWidget *button;
9007   GtkWidget *vbox;
9008   GtkWidget *vbox2;
9009   GtkWidget *hbox;
9010   GtkWidget *check;
9011   GtkWidget *frame;
9012   GtkWidget *tab;
9013   GtkWidget *label;
9014   GtkWidget *align;
9015   GtkAdjustment *adj;
9016   static ProgressData *pdata = NULL;
9017
9018   static gchar *items1[] =
9019   {
9020     "Left-Right",
9021     "Right-Left",
9022     "Bottom-Top",
9023     "Top-Bottom"
9024   };
9025
9026     static char *ellipsize_items[] = {
9027     "None",     // PANGO_ELLIPSIZE_NONE,
9028     "Start",    // PANGO_ELLIPSIZE_START,
9029     "Middle",   // PANGO_ELLIPSIZE_MIDDLE,
9030     "End",      // PANGO_ELLIPSIZE_END
9031   };
9032   
9033   if (!pdata)
9034     pdata = g_new0 (ProgressData, 1);
9035
9036   if (!pdata->window)
9037     {
9038       pdata->window = gtk_dialog_new ();
9039
9040       gtk_window_set_screen (GTK_WINDOW (pdata->window),
9041                              gtk_widget_get_screen (widget));
9042
9043       gtk_window_set_resizable (GTK_WINDOW (pdata->window), TRUE);
9044
9045       g_signal_connect (pdata->window, "destroy",
9046                         G_CALLBACK (destroy_progress),
9047                         &pdata);
9048
9049       pdata->timer = 0;
9050
9051       gtk_window_set_title (GTK_WINDOW (pdata->window), "GtkProgressBar");
9052       gtk_container_set_border_width (GTK_CONTAINER (pdata->window), 0);
9053
9054       vbox = gtk_vbox_new (FALSE, 5);
9055       gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
9056       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (pdata->window)->vbox), 
9057                           vbox, FALSE, TRUE, 0);
9058
9059       frame = gtk_frame_new ("Progress");
9060       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
9061
9062       vbox2 = gtk_vbox_new (FALSE, 5);
9063       gtk_container_add (GTK_CONTAINER (frame), vbox2);
9064
9065       align = gtk_alignment_new (0.5, 0.5, 0, 0);
9066       gtk_box_pack_start (GTK_BOX (vbox2), align, FALSE, FALSE, 5);
9067
9068       adj = (GtkAdjustment *) gtk_adjustment_new (0, 1, 300, 0, 0, 0);
9069       g_signal_connect (adj, "value_changed",
9070                         G_CALLBACK (progress_value_changed), pdata);
9071
9072       pdata->pbar = g_object_new (GTK_TYPE_PROGRESS_BAR,
9073                                     "adjustment", adj,
9074                                     "ellipsize", PANGO_ELLIPSIZE_MIDDLE,
9075                                     NULL);
9076       gtk_progress_bar_set_text (GTK_PROGRESS_BAR (pdata->pbar),
9077                                       "%v from [%l,%u] (=%p%%)");
9078       gtk_container_add (GTK_CONTAINER (align), pdata->pbar);
9079       pdata->timer = g_timeout_add (100, (GSourceFunc)progress_timeout, pdata);
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       hbox = gtk_hbox_new (FALSE, 5);
9085       gtk_container_add (GTK_CONTAINER (align), hbox);
9086       label = gtk_label_new ("Label updated by user :"); 
9087       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
9088       pdata->label = gtk_label_new ("");
9089       gtk_box_pack_start (GTK_BOX (hbox), pdata->label, FALSE, TRUE, 0);
9090
9091       frame = gtk_frame_new ("Options");
9092       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
9093
9094       vbox2 = gtk_vbox_new (FALSE, 5);
9095       gtk_container_add (GTK_CONTAINER (frame), vbox2);
9096
9097       tab = gtk_table_new (7, 2, FALSE);
9098       gtk_box_pack_start (GTK_BOX (vbox2), tab, FALSE, TRUE, 0);
9099
9100       label = gtk_label_new ("Orientation :");
9101       gtk_table_attach (GTK_TABLE (tab), label, 0, 1, 0, 1,
9102                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
9103                         5, 5);
9104       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
9105
9106       pdata->omenu1 = build_option_menu (items1, 4, 0,
9107                                          progressbar_toggle_orientation,
9108                                          pdata);
9109       hbox = gtk_hbox_new (FALSE, 0);
9110       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 0, 1,
9111                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
9112                         5, 5);
9113       gtk_box_pack_start (GTK_BOX (hbox), pdata->omenu1, TRUE, TRUE, 0);
9114       
9115       check = gtk_check_button_new_with_label ("Show text");
9116       g_signal_connect (check, "clicked",
9117                         G_CALLBACK (toggle_show_text),
9118                         pdata);
9119       gtk_table_attach (GTK_TABLE (tab), check, 0, 1, 1, 2,
9120                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
9121                         5, 5);
9122
9123       hbox = gtk_hbox_new (FALSE, 0);
9124       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 1, 2,
9125                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
9126                         5, 5);
9127
9128       label = gtk_label_new ("Format : ");
9129       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
9130
9131       pdata->entry = gtk_entry_new ();
9132       g_signal_connect (pdata->entry, "changed",
9133                         G_CALLBACK (entry_changed),
9134                         pdata);
9135       gtk_box_pack_start (GTK_BOX (hbox), pdata->entry, TRUE, TRUE, 0);
9136       gtk_entry_set_text (GTK_ENTRY (pdata->entry), "%v from [%l,%u] (=%p%%)");
9137       gtk_widget_set_size_request (pdata->entry, 100, -1);
9138       gtk_widget_set_sensitive (pdata->entry, FALSE);
9139
9140       label = gtk_label_new ("Text align :");
9141       gtk_table_attach (GTK_TABLE (tab), label, 0, 1, 2, 3,
9142                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
9143                         5, 5);
9144       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
9145
9146       hbox = gtk_hbox_new (FALSE, 0);
9147       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 2, 3,
9148                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
9149                         5, 5);
9150
9151       label = gtk_label_new ("x :");
9152       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 5);
9153       
9154       adj = (GtkAdjustment *) gtk_adjustment_new (0.5, 0, 1, 0.1, 0.1, 0);
9155       pdata->x_align_spin = gtk_spin_button_new (adj, 0, 1);
9156       g_signal_connect (adj, "value_changed",
9157                         G_CALLBACK (adjust_align), pdata);
9158       gtk_box_pack_start (GTK_BOX (hbox), pdata->x_align_spin, FALSE, TRUE, 0);
9159       gtk_widget_set_sensitive (pdata->x_align_spin, FALSE);
9160
9161       label = gtk_label_new ("y :");
9162       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 5);
9163
9164       adj = (GtkAdjustment *) gtk_adjustment_new (0.5, 0, 1, 0.1, 0.1, 0);
9165       pdata->y_align_spin = gtk_spin_button_new (adj, 0, 1);
9166       g_signal_connect (adj, "value_changed",
9167                         G_CALLBACK (adjust_align), pdata);
9168       gtk_box_pack_start (GTK_BOX (hbox), pdata->y_align_spin, FALSE, TRUE, 0);
9169       gtk_widget_set_sensitive (pdata->y_align_spin, FALSE);
9170
9171       label = gtk_label_new ("Ellipsize text :");
9172       gtk_table_attach (GTK_TABLE (tab), label, 0, 1, 10, 11,
9173                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
9174                         5, 5);
9175       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
9176       pdata->elmenu = build_option_menu (ellipsize_items,
9177                                          sizeof (ellipsize_items) / sizeof (ellipsize_items[0]),
9178                                          2, // PANGO_ELLIPSIZE_MIDDLE
9179                                          progressbar_toggle_ellipsize,
9180                                          pdata);
9181       hbox = gtk_hbox_new (FALSE, 0);
9182       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 10, 11,
9183                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
9184                         5, 5);
9185       gtk_box_pack_start (GTK_BOX (hbox), pdata->elmenu, TRUE, TRUE, 0);
9186
9187       check = gtk_check_button_new_with_label ("Activity mode");
9188       g_signal_connect (check, "clicked",
9189                         G_CALLBACK (toggle_activity_mode), pdata);
9190       gtk_table_attach (GTK_TABLE (tab), check, 0, 1, 15, 16,
9191                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
9192                         5, 5);
9193
9194       button = gtk_button_new_with_label ("close");
9195       g_signal_connect_swapped (button, "clicked",
9196                                 G_CALLBACK (gtk_widget_destroy),
9197                                 pdata->window);
9198       gtk_widget_set_can_default (button, TRUE);
9199       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (pdata->window)->action_area), 
9200                           button, TRUE, TRUE, 0);
9201       gtk_widget_grab_default (button);
9202     }
9203
9204   if (!gtk_widget_get_visible (pdata->window))
9205     gtk_widget_show_all (pdata->window);
9206   else
9207     gtk_widget_destroy (pdata->window);
9208 }
9209
9210 /*
9211  * Properties
9212  */
9213
9214 typedef struct {
9215   int x;
9216   int y;
9217   gboolean found;
9218   gboolean first;
9219   GtkWidget *res_widget;
9220 } FindWidgetData;
9221
9222 static void
9223 find_widget (GtkWidget *widget, FindWidgetData *data)
9224 {
9225   GtkAllocation new_allocation;
9226   gint x_offset = 0;
9227   gint y_offset = 0;
9228
9229   new_allocation = widget->allocation;
9230
9231   if (data->found || !gtk_widget_get_mapped (widget))
9232     return;
9233
9234   /* Note that in the following code, we only count the
9235    * position as being inside a WINDOW widget if it is inside
9236    * widget->window; points that are outside of widget->window
9237    * but within the allocation are not counted. This is consistent
9238    * with the way we highlight drag targets.
9239    */
9240   if (gtk_widget_get_has_window (widget))
9241     {
9242       new_allocation.x = 0;
9243       new_allocation.y = 0;
9244     }
9245   
9246   if (widget->parent && !data->first)
9247     {
9248       GdkWindow *window = widget->window;
9249       while (window != widget->parent->window)
9250         {
9251           gint tx, ty, twidth, theight;
9252           gdk_drawable_get_size (window, &twidth, &theight);
9253
9254           if (new_allocation.x < 0)
9255             {
9256               new_allocation.width += new_allocation.x;
9257               new_allocation.x = 0;
9258             }
9259           if (new_allocation.y < 0)
9260             {
9261               new_allocation.height += new_allocation.y;
9262               new_allocation.y = 0;
9263             }
9264           if (new_allocation.x + new_allocation.width > twidth)
9265             new_allocation.width = twidth - new_allocation.x;
9266           if (new_allocation.y + new_allocation.height > theight)
9267             new_allocation.height = theight - new_allocation.y;
9268
9269           gdk_window_get_position (window, &tx, &ty);
9270           new_allocation.x += tx;
9271           x_offset += tx;
9272           new_allocation.y += ty;
9273           y_offset += ty;
9274           
9275           window = gdk_window_get_parent (window);
9276         }
9277     }
9278
9279   if ((data->x >= new_allocation.x) && (data->y >= new_allocation.y) &&
9280       (data->x < new_allocation.x + new_allocation.width) && 
9281       (data->y < new_allocation.y + new_allocation.height))
9282     {
9283       /* First, check if the drag is in a valid drop site in
9284        * one of our children 
9285        */
9286       if (GTK_IS_CONTAINER (widget))
9287         {
9288           FindWidgetData new_data = *data;
9289           
9290           new_data.x -= x_offset;
9291           new_data.y -= y_offset;
9292           new_data.found = FALSE;
9293           new_data.first = FALSE;
9294           
9295           gtk_container_forall (GTK_CONTAINER (widget),
9296                                 (GtkCallback)find_widget,
9297                                 &new_data);
9298           
9299           data->found = new_data.found;
9300           if (data->found)
9301             data->res_widget = new_data.res_widget;
9302         }
9303
9304       /* If not, and this widget is registered as a drop site, check to
9305        * emit "drag_motion" to check if we are actually in
9306        * a drop site.
9307        */
9308       if (!data->found)
9309         {
9310           data->found = TRUE;
9311           data->res_widget = widget;
9312         }
9313     }
9314 }
9315
9316 static GtkWidget *
9317 find_widget_at_pointer (GdkDisplay *display)
9318 {
9319   GtkWidget *widget = NULL;
9320   GdkWindow *pointer_window;
9321   gint x, y;
9322   FindWidgetData data;
9323  
9324  pointer_window = gdk_display_get_window_at_pointer (display, NULL, NULL);
9325  
9326  if (pointer_window)
9327    {
9328      gpointer widget_ptr;
9329
9330      gdk_window_get_user_data (pointer_window, &widget_ptr);
9331      widget = widget_ptr;
9332    }
9333
9334  if (widget)
9335    {
9336      gdk_window_get_pointer (widget->window,
9337                              &x, &y, NULL);
9338      
9339      data.x = x;
9340      data.y = y;
9341      data.found = FALSE;
9342      data.first = TRUE;
9343
9344      find_widget (widget, &data);
9345      if (data.found)
9346        return data.res_widget;
9347      return widget;
9348    }
9349  return NULL;
9350 }
9351
9352 struct PropertiesData {
9353   GtkWidget **window;
9354   GdkCursor *cursor;
9355   gboolean in_query;
9356   gint handler;
9357 };
9358
9359 static void
9360 destroy_properties (GtkWidget             *widget,
9361                     struct PropertiesData *data)
9362 {
9363   if (data->window)
9364     {
9365       *data->window = NULL;
9366       data->window = NULL;
9367     }
9368
9369   if (data->cursor)
9370     {
9371       gdk_cursor_unref (data->cursor);
9372       data->cursor = NULL;
9373     }
9374
9375   if (data->handler)
9376     {
9377       g_signal_handler_disconnect (widget, data->handler);
9378       data->handler = 0;
9379     }
9380
9381   g_free (data);
9382 }
9383
9384 static gint
9385 property_query_event (GtkWidget        *widget,
9386                       GdkEvent         *event,
9387                       struct PropertiesData *data)
9388 {
9389   GtkWidget *res_widget = NULL;
9390
9391   if (!data->in_query)
9392     return FALSE;
9393   
9394   if (event->type == GDK_BUTTON_RELEASE)
9395     {
9396       gtk_grab_remove (widget);
9397       gdk_display_pointer_ungrab (gtk_widget_get_display (widget),
9398                                   GDK_CURRENT_TIME);
9399       
9400       res_widget = find_widget_at_pointer (gtk_widget_get_display (widget));
9401       if (res_widget)
9402         {
9403           g_object_set_data (G_OBJECT (res_widget), "prop-editor-screen",
9404                              gtk_widget_get_screen (widget));
9405           create_prop_editor (G_OBJECT (res_widget), 0);
9406         }
9407
9408       data->in_query = FALSE;
9409     }
9410   return FALSE;
9411 }
9412
9413
9414 static void
9415 query_properties (GtkButton *button,
9416                   struct PropertiesData *data)
9417 {
9418   gint failure;
9419
9420   g_signal_connect (button, "event",
9421                     G_CALLBACK (property_query_event), data);
9422
9423
9424   if (!data->cursor)
9425     data->cursor = gdk_cursor_new_for_display (gtk_widget_get_display (GTK_WIDGET (button)),
9426                                                GDK_TARGET);
9427   
9428   failure = gdk_pointer_grab (GTK_WIDGET (button)->window,
9429                               TRUE,
9430                               GDK_BUTTON_RELEASE_MASK,
9431                               NULL,
9432                               data->cursor,
9433                               GDK_CURRENT_TIME);
9434
9435   gtk_grab_add (GTK_WIDGET (button));
9436
9437   data->in_query = TRUE;
9438 }
9439
9440 static void
9441 create_properties (GtkWidget *widget)
9442 {
9443   static GtkWidget *window = NULL;
9444   GtkWidget *button;
9445   GtkWidget *vbox;
9446   GtkWidget *label;
9447   struct PropertiesData *data;
9448
9449   data = g_new (struct PropertiesData, 1);
9450   data->window = &window;
9451   data->in_query = FALSE;
9452   data->cursor = NULL;
9453   data->handler = 0;
9454
9455   if (!window)
9456     {
9457       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9458
9459       gtk_window_set_screen (GTK_WINDOW (window),
9460                              gtk_widget_get_screen (widget));      
9461
9462       data->handler = g_signal_connect (window, "destroy",
9463                                         G_CALLBACK (destroy_properties),
9464                                         data);
9465
9466       gtk_window_set_title (GTK_WINDOW (window), "test properties");
9467       gtk_container_set_border_width (GTK_CONTAINER (window), 10);
9468
9469       vbox = gtk_vbox_new (FALSE, 1);
9470       gtk_container_add (GTK_CONTAINER (window), vbox);
9471             
9472       label = gtk_label_new ("This is just a dumb test to test properties.\nIf you need a generic module, get GLE.");
9473       gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
9474       
9475       button = gtk_button_new_with_label ("Query properties");
9476       gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
9477       g_signal_connect (button, "clicked",
9478                         G_CALLBACK (query_properties),
9479                         data);
9480     }
9481
9482   if (!gtk_widget_get_visible (window))
9483     gtk_widget_show_all (window);
9484   else
9485     gtk_widget_destroy (window);
9486   
9487 }
9488
9489 struct SnapshotData {
9490   GtkWidget *toplevel_button;
9491   GtkWidget **window;
9492   GdkCursor *cursor;
9493   gboolean in_query;
9494   gboolean is_toplevel;
9495   gint handler;
9496 };
9497
9498 static void
9499 destroy_snapshot_data (GtkWidget             *widget,
9500                        struct SnapshotData *data)
9501 {
9502   if (*data->window)
9503     *data->window = NULL;
9504   
9505   if (data->cursor)
9506     {
9507       gdk_cursor_unref (data->cursor);
9508       data->cursor = NULL;
9509     }
9510
9511   if (data->handler)
9512     {
9513       g_signal_handler_disconnect (widget, data->handler);
9514       data->handler = 0;
9515     }
9516
9517   g_free (data);
9518 }
9519
9520 static gint
9521 snapshot_widget_event (GtkWidget               *widget,
9522                        GdkEvent        *event,
9523                        struct SnapshotData *data)
9524 {
9525   GtkWidget *res_widget = NULL;
9526
9527   if (!data->in_query)
9528     return FALSE;
9529   
9530   if (event->type == GDK_BUTTON_RELEASE)
9531     {
9532       gtk_grab_remove (widget);
9533       gdk_display_pointer_ungrab (gtk_widget_get_display (widget),
9534                                   GDK_CURRENT_TIME);
9535       
9536       res_widget = find_widget_at_pointer (gtk_widget_get_display (widget));
9537       if (data->is_toplevel && res_widget)
9538         res_widget = gtk_widget_get_toplevel (res_widget);
9539       if (res_widget)
9540         {
9541           GdkPixmap *pixmap;
9542           GtkWidget *window, *image;
9543
9544           window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9545           pixmap = gtk_widget_get_snapshot (res_widget, NULL);
9546           gtk_widget_realize (window);
9547           if (gdk_drawable_get_depth (window->window) != gdk_drawable_get_depth (pixmap))
9548             {
9549               /* this branch is needed to convert ARGB -> RGB */
9550               int width, height;
9551               GdkPixbuf *pixbuf;
9552               gdk_drawable_get_size (pixmap, &width, &height);
9553               pixbuf = gdk_pixbuf_get_from_drawable (NULL, pixmap,
9554                                                      gtk_widget_get_colormap (res_widget),
9555                                                      0, 0,
9556                                                      0, 0,
9557                                                      width, height);
9558               image = gtk_image_new_from_pixbuf (pixbuf);
9559               g_object_unref (pixbuf);
9560             }
9561           else
9562             image = gtk_image_new_from_pixmap (pixmap, NULL);
9563           gtk_container_add (GTK_CONTAINER (window), image);
9564           g_object_unref (pixmap);
9565           gtk_widget_show_all (window);
9566         }
9567
9568       data->in_query = FALSE;
9569     }
9570   return FALSE;
9571 }
9572
9573
9574 static void
9575 snapshot_widget (GtkButton *button,
9576                  struct SnapshotData *data)
9577 {
9578   gint failure;
9579
9580   g_signal_connect (button, "event",
9581                     G_CALLBACK (snapshot_widget_event), data);
9582
9583   data->is_toplevel = GTK_WIDGET (button) == data->toplevel_button;
9584   
9585   if (!data->cursor)
9586     data->cursor = gdk_cursor_new_for_display (gtk_widget_get_display (GTK_WIDGET (button)),
9587                                                GDK_TARGET);
9588   
9589   failure = gdk_pointer_grab (GTK_WIDGET (button)->window,
9590                               TRUE,
9591                               GDK_BUTTON_RELEASE_MASK,
9592                               NULL,
9593                               data->cursor,
9594                               GDK_CURRENT_TIME);
9595
9596   gtk_grab_add (GTK_WIDGET (button));
9597
9598   data->in_query = TRUE;
9599 }
9600
9601 static void
9602 create_snapshot (GtkWidget *widget)
9603 {
9604   static GtkWidget *window = NULL;
9605   GtkWidget *button;
9606   GtkWidget *vbox;
9607   struct SnapshotData *data;
9608
9609   data = g_new (struct SnapshotData, 1);
9610   data->window = &window;
9611   data->in_query = FALSE;
9612   data->cursor = NULL;
9613   data->handler = 0;
9614
9615   if (!window)
9616     {
9617       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9618
9619       gtk_window_set_screen (GTK_WINDOW (window),
9620                              gtk_widget_get_screen (widget));      
9621
9622       data->handler = g_signal_connect (window, "destroy",
9623                                         G_CALLBACK (destroy_snapshot_data),
9624                                         data);
9625
9626       gtk_window_set_title (GTK_WINDOW (window), "test snapshot");
9627       gtk_container_set_border_width (GTK_CONTAINER (window), 10);
9628
9629       vbox = gtk_vbox_new (FALSE, 1);
9630       gtk_container_add (GTK_CONTAINER (window), vbox);
9631             
9632       button = gtk_button_new_with_label ("Snapshot widget");
9633       gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
9634       g_signal_connect (button, "clicked",
9635                         G_CALLBACK (snapshot_widget),
9636                         data);
9637       
9638       button = gtk_button_new_with_label ("Snapshot toplevel");
9639       data->toplevel_button = button;
9640       gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
9641       g_signal_connect (button, "clicked",
9642                         G_CALLBACK (snapshot_widget),
9643                         data);
9644     }
9645
9646   if (!gtk_widget_get_visible (window))
9647     gtk_widget_show_all (window);
9648   else
9649     gtk_widget_destroy (window);
9650   
9651 }
9652
9653 /*
9654  * Selection Test
9655  */
9656
9657 void
9658 selection_test_received (GtkWidget        *tree_view,
9659                          GtkSelectionData *data)
9660 {
9661   GtkTreeModel *model;
9662   GtkListStore *store;
9663   GdkAtom *atoms;
9664   int i, l;
9665
9666   if (data->length < 0)
9667     {
9668       g_print ("Selection retrieval failed\n");
9669       return;
9670     }
9671   if (data->type != GDK_SELECTION_TYPE_ATOM)
9672     {
9673       g_print ("Selection \"TARGETS\" was not returned as atoms!\n");
9674       return;
9675     }
9676
9677   /* Clear out any current list items */
9678
9679   model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree_view));
9680   store = GTK_LIST_STORE (model);
9681   gtk_list_store_clear (store);
9682
9683   /* Add new items to list */
9684
9685   atoms = (GdkAtom *)data->data;
9686
9687   l = data->length / sizeof (GdkAtom);
9688   for (i = 0; i < l; i++)
9689     {
9690       char *name;
9691       GtkTreeIter iter;
9692
9693       name = gdk_atom_name (atoms[i]);
9694       if (name != NULL)
9695         {
9696           gtk_list_store_insert_with_values (store, &iter, i, 0, name, -1);
9697           g_free (name);
9698         }
9699       else
9700        gtk_list_store_insert_with_values (store, &iter, i, 0,  "(bad atom)", -1);
9701     }
9702
9703   return;
9704 }
9705
9706 void
9707 selection_test_get_targets (GtkWidget *widget, GtkWidget *tree_view)
9708 {
9709   static GdkAtom targets_atom = GDK_NONE;
9710
9711   if (targets_atom == GDK_NONE)
9712     targets_atom = gdk_atom_intern ("TARGETS", FALSE);
9713
9714   gtk_selection_convert (tree_view, GDK_SELECTION_PRIMARY, targets_atom,
9715                          GDK_CURRENT_TIME);
9716 }
9717
9718 void
9719 create_selection_test (GtkWidget *widget)
9720 {
9721   static GtkWidget *window = NULL;
9722   GtkWidget *button;
9723   GtkWidget *vbox;
9724   GtkWidget *scrolled_win;
9725   GtkListStore* store;
9726   GtkWidget *tree_view;
9727   GtkTreeViewColumn *column;
9728   GtkCellRenderer *renderer;
9729   GtkWidget *label;
9730
9731   if (!window)
9732     {
9733       window = gtk_dialog_new ();
9734       
9735       gtk_window_set_screen (GTK_WINDOW (window),
9736                              gtk_widget_get_screen (widget));
9737
9738       g_signal_connect (window, "destroy",
9739                         G_CALLBACK (gtk_widget_destroyed),
9740                         &window);
9741
9742       gtk_window_set_title (GTK_WINDOW (window), "Selection Test");
9743       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
9744
9745       /* Create the list */
9746
9747       vbox = gtk_vbox_new (FALSE, 5);
9748       gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
9749       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), vbox,
9750                           TRUE, TRUE, 0);
9751
9752       label = gtk_label_new ("Gets available targets for current selection");
9753       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
9754
9755       scrolled_win = gtk_scrolled_window_new (NULL, NULL);
9756       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
9757                                       GTK_POLICY_AUTOMATIC, 
9758                                       GTK_POLICY_AUTOMATIC);
9759       gtk_box_pack_start (GTK_BOX (vbox), scrolled_win, TRUE, TRUE, 0);
9760       gtk_widget_set_size_request (scrolled_win, 100, 200);
9761
9762       store = gtk_list_store_new (1, G_TYPE_STRING);
9763       tree_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store));
9764       gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_win), tree_view);
9765
9766       renderer = gtk_cell_renderer_text_new ();
9767       column = gtk_tree_view_column_new_with_attributes ("Target", renderer,
9768                                                          "text", 0, NULL);
9769       gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), column);
9770
9771       g_signal_connect (tree_view, "selection_received",
9772                         G_CALLBACK (selection_test_received), NULL);
9773
9774       /* .. And create some buttons */
9775       button = gtk_button_new_with_label ("Get Targets");
9776       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area),
9777                           button, TRUE, TRUE, 0);
9778
9779       g_signal_connect (button, "clicked",
9780                         G_CALLBACK (selection_test_get_targets), tree_view);
9781
9782       button = gtk_button_new_with_label ("Quit");
9783       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area),
9784                           button, TRUE, TRUE, 0);
9785
9786       g_signal_connect_swapped (button, "clicked",
9787                                 G_CALLBACK (gtk_widget_destroy),
9788                                 window);
9789     }
9790
9791   if (!gtk_widget_get_visible (window))
9792     gtk_widget_show_all (window);
9793   else
9794     gtk_widget_destroy (window);
9795 }
9796
9797 /*
9798  * Test scrolling
9799  */
9800
9801 static int scroll_test_pos = 0.0;
9802
9803 static gint
9804 scroll_test_expose (GtkWidget *widget, GdkEventExpose *event,
9805                     GtkAdjustment *adj)
9806 {
9807   gint i,j;
9808   gint imin, imax, jmin, jmax;
9809   
9810   imin = (event->area.x) / 10;
9811   imax = (event->area.x + event->area.width + 9) / 10;
9812
9813   jmin = ((int)adj->value + event->area.y) / 10;
9814   jmax = ((int)adj->value + event->area.y + event->area.height + 9) / 10;
9815
9816   gdk_window_clear_area (widget->window,
9817                          event->area.x, event->area.y,
9818                          event->area.width, event->area.height);
9819
9820   for (i=imin; i<imax; i++)
9821     for (j=jmin; j<jmax; j++)
9822       if ((i+j) % 2)
9823         gdk_draw_rectangle (widget->window, 
9824                             widget->style->black_gc,
9825                             TRUE,
9826                             10*i, 10*j - (int)adj->value, 1+i%10, 1+j%10);
9827
9828   return TRUE;
9829 }
9830
9831 static gint
9832 scroll_test_scroll (GtkWidget *widget, GdkEventScroll *event,
9833                     GtkAdjustment *adj)
9834 {
9835   gdouble new_value = adj->value + ((event->direction == GDK_SCROLL_UP) ?
9836                                     -adj->page_increment / 2:
9837                                     adj->page_increment / 2);
9838   new_value = CLAMP (new_value, adj->lower, adj->upper - adj->page_size);
9839   gtk_adjustment_set_value (adj, new_value);  
9840   
9841   return TRUE;
9842 }
9843
9844 static void
9845 scroll_test_configure (GtkWidget *widget, GdkEventConfigure *event,
9846                        GtkAdjustment *adj)
9847 {
9848   adj->page_increment = 0.9 * widget->allocation.height;
9849   adj->page_size = widget->allocation.height;
9850
9851   g_signal_emit_by_name (adj, "changed");
9852 }
9853
9854 static void
9855 scroll_test_adjustment_changed (GtkAdjustment *adj, GtkWidget *widget)
9856 {
9857   /* gint source_min = (int)adj->value - scroll_test_pos; */
9858   gint dy;
9859
9860   dy = scroll_test_pos - (int)adj->value;
9861   scroll_test_pos = adj->value;
9862
9863   if (!gtk_widget_is_drawable (widget))
9864     return;
9865   gdk_window_scroll (widget->window, 0, dy);
9866   gdk_window_process_updates (widget->window, FALSE);
9867 }
9868
9869
9870 void
9871 create_scroll_test (GtkWidget *widget)
9872 {
9873   static GtkWidget *window = NULL;
9874   GtkWidget *hbox;
9875   GtkWidget *drawing_area;
9876   GtkWidget *scrollbar;
9877   GtkWidget *button;
9878   GtkAdjustment *adj;
9879   GdkGeometry geometry;
9880   GdkWindowHints geometry_mask;
9881
9882   if (!window)
9883     {
9884       window = gtk_dialog_new ();
9885
9886       gtk_window_set_screen (GTK_WINDOW (window),
9887                              gtk_widget_get_screen (widget));
9888
9889       g_signal_connect (window, "destroy",
9890                         G_CALLBACK (gtk_widget_destroyed),
9891                         &window);
9892
9893       gtk_window_set_title (GTK_WINDOW (window), "Scroll Test");
9894       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
9895
9896       hbox = gtk_hbox_new (FALSE, 0);
9897       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), hbox,
9898                           TRUE, TRUE, 0);
9899       gtk_widget_show (hbox);
9900
9901       drawing_area = gtk_drawing_area_new ();
9902       gtk_widget_set_size_request (drawing_area, 200, 200);
9903       gtk_box_pack_start (GTK_BOX (hbox), drawing_area, TRUE, TRUE, 0);
9904       gtk_widget_show (drawing_area);
9905
9906       gtk_widget_set_events (drawing_area, GDK_EXPOSURE_MASK | GDK_SCROLL_MASK);
9907
9908       adj = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 1000.0, 1.0, 180.0, 200.0));
9909       scroll_test_pos = 0.0;
9910
9911       scrollbar = gtk_vscrollbar_new (adj);
9912       gtk_box_pack_start (GTK_BOX (hbox), scrollbar, FALSE, FALSE, 0);
9913       gtk_widget_show (scrollbar);
9914
9915       g_signal_connect (drawing_area, "expose_event",
9916                         G_CALLBACK (scroll_test_expose), adj);
9917       g_signal_connect (drawing_area, "configure_event",
9918                         G_CALLBACK (scroll_test_configure), adj);
9919       g_signal_connect (drawing_area, "scroll_event",
9920                         G_CALLBACK (scroll_test_scroll), adj);
9921       
9922       g_signal_connect (adj, "value_changed",
9923                         G_CALLBACK (scroll_test_adjustment_changed),
9924                         drawing_area);
9925       
9926       /* .. And create some buttons */
9927
9928       button = gtk_button_new_with_label ("Quit");
9929       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area),
9930                           button, TRUE, TRUE, 0);
9931
9932       g_signal_connect_swapped (button, "clicked",
9933                                 G_CALLBACK (gtk_widget_destroy),
9934                                 window);
9935       gtk_widget_show (button);
9936
9937       /* Set up gridded geometry */
9938
9939       geometry_mask = GDK_HINT_MIN_SIZE | 
9940                        GDK_HINT_BASE_SIZE | 
9941                        GDK_HINT_RESIZE_INC;
9942
9943       geometry.min_width = 20;
9944       geometry.min_height = 20;
9945       geometry.base_width = 0;
9946       geometry.base_height = 0;
9947       geometry.width_inc = 10;
9948       geometry.height_inc = 10;
9949       
9950       gtk_window_set_geometry_hints (GTK_WINDOW (window),
9951                                drawing_area, &geometry, geometry_mask);
9952     }
9953
9954   if (!gtk_widget_get_visible (window))
9955     gtk_widget_show (window);
9956   else
9957     gtk_widget_destroy (window);
9958 }
9959
9960 /*
9961  * Timeout Test
9962  */
9963
9964 static int timer = 0;
9965
9966 gint
9967 timeout_test (GtkWidget *label)
9968 {
9969   static int count = 0;
9970   static char buffer[32];
9971
9972   sprintf (buffer, "count: %d", ++count);
9973   gtk_label_set_text (GTK_LABEL (label), buffer);
9974
9975   return TRUE;
9976 }
9977
9978 void
9979 start_timeout_test (GtkWidget *widget,
9980                     GtkWidget *label)
9981 {
9982   if (!timer)
9983     {
9984       timer = g_timeout_add (100, (GSourceFunc)timeout_test, label);
9985     }
9986 }
9987
9988 void
9989 stop_timeout_test (GtkWidget *widget,
9990                    gpointer   data)
9991 {
9992   if (timer)
9993     {
9994       g_source_remove (timer);
9995       timer = 0;
9996     }
9997 }
9998
9999 void
10000 destroy_timeout_test (GtkWidget  *widget,
10001                       GtkWidget **window)
10002 {
10003   stop_timeout_test (NULL, NULL);
10004
10005   *window = NULL;
10006 }
10007
10008 void
10009 create_timeout_test (GtkWidget *widget)
10010 {
10011   static GtkWidget *window = NULL;
10012   GtkWidget *button;
10013   GtkWidget *label;
10014
10015   if (!window)
10016     {
10017       window = gtk_dialog_new ();
10018
10019       gtk_window_set_screen (GTK_WINDOW (window),
10020                              gtk_widget_get_screen (widget));
10021
10022       g_signal_connect (window, "destroy",
10023                         G_CALLBACK (destroy_timeout_test),
10024                         &window);
10025
10026       gtk_window_set_title (GTK_WINDOW (window), "Timeout Test");
10027       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
10028
10029       label = gtk_label_new ("count: 0");
10030       gtk_misc_set_padding (GTK_MISC (label), 10, 10);
10031       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
10032                           label, TRUE, TRUE, 0);
10033       gtk_widget_show (label);
10034
10035       button = gtk_button_new_with_label ("close");
10036       g_signal_connect_swapped (button, "clicked",
10037                                 G_CALLBACK (gtk_widget_destroy),
10038                                 window);
10039       gtk_widget_set_can_default (button, TRUE);
10040       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
10041                           button, TRUE, TRUE, 0);
10042       gtk_widget_grab_default (button);
10043       gtk_widget_show (button);
10044
10045       button = gtk_button_new_with_label ("start");
10046       g_signal_connect (button, "clicked",
10047                         G_CALLBACK(start_timeout_test),
10048                         label);
10049       gtk_widget_set_can_default (button, TRUE);
10050       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
10051                           button, TRUE, TRUE, 0);
10052       gtk_widget_show (button);
10053
10054       button = gtk_button_new_with_label ("stop");
10055       g_signal_connect (button, "clicked",
10056                         G_CALLBACK (stop_timeout_test),
10057                         NULL);
10058       gtk_widget_set_can_default (button, TRUE);
10059       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
10060                           button, TRUE, TRUE, 0);
10061       gtk_widget_show (button);
10062     }
10063
10064   if (!gtk_widget_get_visible (window))
10065     gtk_widget_show (window);
10066   else
10067     gtk_widget_destroy (window);
10068 }
10069
10070 /*
10071  * Idle Test
10072  */
10073
10074 static int idle_id = 0;
10075
10076 static gint
10077 idle_test (GtkWidget *label)
10078 {
10079   static int count = 0;
10080   static char buffer[32];
10081
10082   sprintf (buffer, "count: %d", ++count);
10083   gtk_label_set_text (GTK_LABEL (label), buffer);
10084
10085   return TRUE;
10086 }
10087
10088 static void
10089 start_idle_test (GtkWidget *widget,
10090                  GtkWidget *label)
10091 {
10092   if (!idle_id)
10093     {
10094       idle_id = g_idle_add ((GSourceFunc) idle_test, label);
10095     }
10096 }
10097
10098 static void
10099 stop_idle_test (GtkWidget *widget,
10100                 gpointer   data)
10101 {
10102   if (idle_id)
10103     {
10104       g_source_remove (idle_id);
10105       idle_id = 0;
10106     }
10107 }
10108
10109 static void
10110 destroy_idle_test (GtkWidget  *widget,
10111                    GtkWidget **window)
10112 {
10113   stop_idle_test (NULL, NULL);
10114
10115   *window = NULL;
10116 }
10117
10118 static void
10119 toggle_idle_container (GObject *button,
10120                        GtkContainer *container)
10121 {
10122   gtk_container_set_resize_mode (container, GPOINTER_TO_INT (g_object_get_data (button, "user_data")));
10123 }
10124
10125 static void
10126 create_idle_test (GtkWidget *widget)
10127 {
10128   static GtkWidget *window = NULL;
10129   GtkWidget *button;
10130   GtkWidget *label;
10131   GtkWidget *container;
10132
10133   if (!window)
10134     {
10135       GtkWidget *button2;
10136       GtkWidget *frame;
10137       GtkWidget *box;
10138
10139       window = gtk_dialog_new ();
10140
10141       gtk_window_set_screen (GTK_WINDOW (window),
10142                              gtk_widget_get_screen (widget));
10143
10144       g_signal_connect (window, "destroy",
10145                         G_CALLBACK (destroy_idle_test),
10146                         &window);
10147
10148       gtk_window_set_title (GTK_WINDOW (window), "Idle Test");
10149       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
10150
10151       label = gtk_label_new ("count: 0");
10152       gtk_misc_set_padding (GTK_MISC (label), 10, 10);
10153       gtk_widget_show (label);
10154       
10155       container =
10156         g_object_new (GTK_TYPE_HBOX,
10157                         "visible", TRUE,
10158                         /* "GtkContainer::child", g_object_new (GTK_TYPE_HBOX,
10159                          * "GtkWidget::visible", TRUE,
10160                          */
10161                          "child", label,
10162                         /* NULL), */
10163                         NULL);
10164       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
10165                           container, TRUE, TRUE, 0);
10166
10167       frame =
10168         g_object_new (GTK_TYPE_FRAME,
10169                         "border_width", 5,
10170                         "label", "Label Container",
10171                         "visible", TRUE,
10172                         "parent", GTK_DIALOG (window)->vbox,
10173                         NULL);
10174       box =
10175         g_object_new (GTK_TYPE_VBOX,
10176                         "visible", TRUE,
10177                         "parent", frame,
10178                         NULL);
10179       button =
10180         g_object_connect (g_object_new (GTK_TYPE_RADIO_BUTTON,
10181                                           "label", "Resize-Parent",
10182                                           "user_data", (void*)GTK_RESIZE_PARENT,
10183                                           "visible", TRUE,
10184                                           "parent", box,
10185                                           NULL),
10186                           "signal::clicked", toggle_idle_container, container,
10187                           NULL);
10188       button = g_object_new (GTK_TYPE_RADIO_BUTTON,
10189                                "label", "Resize-Queue",
10190                                "user_data", (void*)GTK_RESIZE_QUEUE,
10191                                "group", button,
10192                                "visible", TRUE,
10193                                "parent", box,
10194                                NULL);
10195       g_object_connect (button,
10196                         "signal::clicked", toggle_idle_container, container,
10197                         NULL);
10198       button2 = g_object_new (GTK_TYPE_RADIO_BUTTON,
10199                                 "label", "Resize-Immediate",
10200                                 "user_data", (void*)GTK_RESIZE_IMMEDIATE,
10201                                 NULL);
10202       g_object_connect (button2,
10203                         "signal::clicked", toggle_idle_container, container,
10204                         NULL);
10205       g_object_set (button2,
10206                     "group", button,
10207                     "visible", TRUE,
10208                     "parent", box,
10209                     NULL);
10210
10211       button = gtk_button_new_with_label ("close");
10212       g_signal_connect_swapped (button, "clicked",
10213                                 G_CALLBACK (gtk_widget_destroy),
10214                                 window);
10215       gtk_widget_set_can_default (button, TRUE);
10216       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
10217                           button, TRUE, TRUE, 0);
10218       gtk_widget_grab_default (button);
10219       gtk_widget_show (button);
10220
10221       button = gtk_button_new_with_label ("start");
10222       g_signal_connect (button, "clicked",
10223                         G_CALLBACK (start_idle_test),
10224                         label);
10225       gtk_widget_set_can_default (button, TRUE);
10226       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
10227                           button, TRUE, TRUE, 0);
10228       gtk_widget_show (button);
10229
10230       button = gtk_button_new_with_label ("stop");
10231       g_signal_connect (button, "clicked",
10232                         G_CALLBACK (stop_idle_test),
10233                         NULL);
10234       gtk_widget_set_can_default (button, TRUE);
10235       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
10236                           button, TRUE, TRUE, 0);
10237       gtk_widget_show (button);
10238     }
10239
10240   if (!gtk_widget_get_visible (window))
10241     gtk_widget_show (window);
10242   else
10243     gtk_widget_destroy (window);
10244 }
10245
10246 /*
10247  * rc file test
10248  */
10249
10250 void
10251 reload_all_rc_files (void)
10252 {
10253   static GdkAtom atom_rcfiles = GDK_NONE;
10254
10255   GdkEvent *send_event = gdk_event_new (GDK_CLIENT_EVENT);
10256   int i;
10257   
10258   if (!atom_rcfiles)
10259     atom_rcfiles = gdk_atom_intern("_GTK_READ_RCFILES", FALSE);
10260
10261   for(i = 0; i < 5; i++)
10262     send_event->client.data.l[i] = 0;
10263   send_event->client.data_format = 32;
10264   send_event->client.message_type = atom_rcfiles;
10265   gdk_event_send_clientmessage_toall (send_event);
10266
10267   gdk_event_free (send_event);
10268 }
10269
10270 void
10271 create_rc_file (GtkWidget *widget)
10272 {
10273   static GtkWidget *window = NULL;
10274   GtkWidget *button;
10275   GtkWidget *frame;
10276   GtkWidget *vbox;
10277   GtkWidget *label;
10278
10279   if (!window)
10280     {
10281       window = gtk_dialog_new ();
10282
10283       gtk_window_set_screen (GTK_WINDOW (window),
10284                              gtk_widget_get_screen (widget));
10285
10286       g_signal_connect (window, "destroy",
10287                         G_CALLBACK (gtk_widget_destroyed),
10288                         &window);
10289
10290       frame = gtk_aspect_frame_new ("Testing RC file prioritization", 0.5, 0.5, 0.0, TRUE);
10291       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), frame, FALSE, FALSE, 0);
10292
10293       vbox = gtk_vbox_new (FALSE, 0);
10294       gtk_container_add (GTK_CONTAINER (frame), vbox);
10295       
10296       label = gtk_label_new ("This label should be red");
10297       gtk_widget_set_name (label, "testgtk-red-label");
10298       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
10299
10300       label = gtk_label_new ("This label should be green");
10301       gtk_widget_set_name (label, "testgtk-green-label");
10302       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
10303
10304       label = gtk_label_new ("This label should be blue");
10305       gtk_widget_set_name (label, "testgtk-blue-label");
10306       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
10307
10308       gtk_window_set_title (GTK_WINDOW (window), "Reload Rc file");
10309       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
10310
10311       button = gtk_button_new_with_label ("Reload");
10312       g_signal_connect (button, "clicked",
10313                         G_CALLBACK (gtk_rc_reparse_all), NULL);
10314       gtk_widget_set_can_default (button, TRUE);
10315       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
10316                           button, TRUE, TRUE, 0);
10317       gtk_widget_grab_default (button);
10318
10319       button = gtk_button_new_with_label ("Reload All");
10320       g_signal_connect (button, "clicked",
10321                         G_CALLBACK (reload_all_rc_files), NULL);
10322       gtk_widget_set_can_default (button, TRUE);
10323       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
10324                           button, TRUE, TRUE, 0);
10325
10326       button = gtk_button_new_with_label ("Close");
10327       g_signal_connect_swapped (button, "clicked",
10328                                 G_CALLBACK (gtk_widget_destroy),
10329                                 window);
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     }
10334
10335   if (!gtk_widget_get_visible (window))
10336     gtk_widget_show_all (window);
10337   else
10338     gtk_widget_destroy (window);
10339 }
10340
10341 /*
10342  * Test of recursive mainloop
10343  */
10344
10345 void
10346 mainloop_destroyed (GtkWidget *w, GtkWidget **window)
10347 {
10348   *window = NULL;
10349   gtk_main_quit ();
10350 }
10351
10352 void
10353 create_mainloop (GtkWidget *widget)
10354 {
10355   static GtkWidget *window = NULL;
10356   GtkWidget *label;
10357   GtkWidget *button;
10358
10359   if (!window)
10360     {
10361       window = gtk_dialog_new ();
10362
10363       gtk_window_set_screen (GTK_WINDOW (window),
10364                              gtk_widget_get_screen (widget));
10365
10366       gtk_window_set_title (GTK_WINDOW (window), "Test Main Loop");
10367
10368       g_signal_connect (window, "destroy",
10369                         G_CALLBACK (mainloop_destroyed),
10370                         &window);
10371
10372       label = gtk_label_new ("In recursive main loop...");
10373       gtk_misc_set_padding (GTK_MISC(label), 20, 20);
10374
10375       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), label,
10376                           TRUE, TRUE, 0);
10377       gtk_widget_show (label);
10378
10379       button = gtk_button_new_with_label ("Leave");
10380       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), button, 
10381                           FALSE, TRUE, 0);
10382
10383       g_signal_connect_swapped (button, "clicked",
10384                                 G_CALLBACK (gtk_widget_destroy),
10385                                 window);
10386
10387       gtk_widget_set_can_default (button, TRUE);
10388       gtk_widget_grab_default (button);
10389
10390       gtk_widget_show (button);
10391     }
10392
10393   if (!gtk_widget_get_visible (window))
10394     {
10395       gtk_widget_show (window);
10396
10397       g_print ("create_mainloop: start\n");
10398       gtk_main ();
10399       g_print ("create_mainloop: done\n");
10400     }
10401   else
10402     gtk_widget_destroy (window);
10403 }
10404
10405 gboolean
10406 layout_expose_handler (GtkWidget *widget, GdkEventExpose *event)
10407 {
10408   GtkLayout *layout;
10409
10410   gint i,j;
10411   gint imin, imax, jmin, jmax;
10412
10413   layout = GTK_LAYOUT (widget);
10414
10415   if (event->window != layout->bin_window)
10416     return FALSE;
10417   
10418   imin = (event->area.x) / 10;
10419   imax = (event->area.x + event->area.width + 9) / 10;
10420
10421   jmin = (event->area.y) / 10;
10422   jmax = (event->area.y + event->area.height + 9) / 10;
10423
10424   for (i=imin; i<imax; i++)
10425     for (j=jmin; j<jmax; j++)
10426       if ((i+j) % 2)
10427         gdk_draw_rectangle (layout->bin_window,
10428                             widget->style->black_gc,
10429                             TRUE,
10430                             10*i, 10*j, 
10431                             1+i%10, 1+j%10);
10432   
10433   return FALSE;
10434 }
10435
10436 void create_layout (GtkWidget *widget)
10437 {
10438   static GtkWidget *window = NULL;
10439   GtkWidget *layout;
10440   GtkWidget *scrolledwindow;
10441   GtkWidget *button;
10442
10443   if (!window)
10444     {
10445       gchar buf[16];
10446
10447       gint i, j;
10448       
10449       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
10450       gtk_window_set_screen (GTK_WINDOW (window),
10451                              gtk_widget_get_screen (widget));
10452
10453       g_signal_connect (window, "destroy",
10454                         G_CALLBACK (gtk_widget_destroyed),
10455                         &window);
10456
10457       gtk_window_set_title (GTK_WINDOW (window), "Layout");
10458       gtk_widget_set_size_request (window, 200, 200);
10459
10460       scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
10461       gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolledwindow),
10462                                            GTK_SHADOW_IN);
10463       gtk_scrolled_window_set_placement (GTK_SCROLLED_WINDOW (scrolledwindow),
10464                                          GTK_CORNER_TOP_RIGHT);
10465
10466       gtk_container_add (GTK_CONTAINER (window), scrolledwindow);
10467       
10468       layout = gtk_layout_new (NULL, NULL);
10469       gtk_container_add (GTK_CONTAINER (scrolledwindow), layout);
10470
10471       /* We set step sizes here since GtkLayout does not set
10472        * them itself.
10473        */
10474       GTK_LAYOUT (layout)->hadjustment->step_increment = 10.0;
10475       GTK_LAYOUT (layout)->vadjustment->step_increment = 10.0;
10476       
10477       gtk_widget_set_events (layout, GDK_EXPOSURE_MASK);
10478       g_signal_connect (layout, "expose_event",
10479                         G_CALLBACK (layout_expose_handler), NULL);
10480       
10481       gtk_layout_set_size (GTK_LAYOUT (layout), 1600, 128000);
10482       
10483       for (i=0 ; i < 16 ; i++)
10484         for (j=0 ; j < 16 ; j++)
10485           {
10486             sprintf(buf, "Button %d, %d", i, j);
10487             if ((i + j) % 2)
10488               button = gtk_button_new_with_label (buf);
10489             else
10490               button = gtk_label_new (buf);
10491
10492             gtk_layout_put (GTK_LAYOUT (layout), button,
10493                             j*100, i*100);
10494           }
10495
10496       for (i=16; i < 1280; i++)
10497         {
10498           sprintf(buf, "Button %d, %d", i, 0);
10499           if (i % 2)
10500             button = gtk_button_new_with_label (buf);
10501           else
10502             button = gtk_label_new (buf);
10503
10504           gtk_layout_put (GTK_LAYOUT (layout), button,
10505                           0, i*100);
10506         }
10507     }
10508
10509   if (!gtk_widget_get_visible (window))
10510     gtk_widget_show_all (window);
10511   else
10512     gtk_widget_destroy (window);
10513 }
10514
10515 void
10516 create_styles (GtkWidget *widget)
10517 {
10518   static GtkWidget *window = NULL;
10519   GtkWidget *label;
10520   GtkWidget *button;
10521   GtkWidget *entry;
10522   GtkWidget *vbox;
10523   static GdkColor red =    { 0, 0xffff, 0,      0      };
10524   static GdkColor green =  { 0, 0,      0xffff, 0      };
10525   static GdkColor blue =   { 0, 0,      0,      0xffff };
10526   static GdkColor yellow = { 0, 0xffff, 0xffff, 0      };
10527   static GdkColor cyan =   { 0, 0     , 0xffff, 0xffff };
10528   PangoFontDescription *font_desc;
10529
10530   GtkRcStyle *rc_style;
10531
10532   if (!window)
10533     {
10534       window = gtk_dialog_new ();
10535       gtk_window_set_screen (GTK_WINDOW (window),
10536                              gtk_widget_get_screen (widget));
10537      
10538       g_signal_connect (window, "destroy",
10539                         G_CALLBACK (gtk_widget_destroyed),
10540                         &window);
10541
10542       
10543       button = gtk_button_new_with_label ("Close");
10544       g_signal_connect_swapped (button, "clicked",
10545                                 G_CALLBACK (gtk_widget_destroy),
10546                                 window);
10547       gtk_widget_set_can_default (button, TRUE);
10548       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
10549                           button, TRUE, TRUE, 0);
10550       gtk_widget_show (button);
10551
10552       vbox = gtk_vbox_new (FALSE, 5);
10553       gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
10554       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), vbox, FALSE, FALSE, 0);
10555       
10556       label = gtk_label_new ("Font:");
10557       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
10558       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
10559
10560       font_desc = pango_font_description_from_string ("Helvetica,Sans Oblique 18");
10561
10562       button = gtk_button_new_with_label ("Some Text");
10563       gtk_widget_modify_font (GTK_BIN (button)->child, font_desc);
10564       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
10565
10566       label = gtk_label_new ("Foreground:");
10567       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
10568       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
10569
10570       button = gtk_button_new_with_label ("Some Text");
10571       gtk_widget_modify_fg (GTK_BIN (button)->child, GTK_STATE_NORMAL, &red);
10572       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
10573
10574       label = gtk_label_new ("Background:");
10575       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
10576       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
10577
10578       button = gtk_button_new_with_label ("Some Text");
10579       gtk_widget_modify_bg (button, GTK_STATE_NORMAL, &green);
10580       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
10581
10582       label = gtk_label_new ("Text:");
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       entry = gtk_entry_new ();
10587       gtk_entry_set_text (GTK_ENTRY (entry), "Some Text");
10588       gtk_widget_modify_text (entry, GTK_STATE_NORMAL, &blue);
10589       gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
10590
10591       label = gtk_label_new ("Base:");
10592       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
10593       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
10594
10595       entry = gtk_entry_new ();
10596       gtk_entry_set_text (GTK_ENTRY (entry), "Some Text");
10597       gtk_widget_modify_base (entry, GTK_STATE_NORMAL, &yellow);
10598       gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
10599
10600       label = gtk_label_new ("Cursor:");
10601       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
10602       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
10603
10604       entry = gtk_entry_new ();
10605       gtk_entry_set_text (GTK_ENTRY (entry), "Some Text");
10606       gtk_widget_modify_cursor (entry, &red, &red);
10607       gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
10608
10609       label = gtk_label_new ("Multiple:");
10610       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
10611       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
10612
10613       button = gtk_button_new_with_label ("Some Text");
10614
10615       rc_style = gtk_rc_style_new ();
10616
10617       rc_style->font_desc = pango_font_description_copy (font_desc);
10618       rc_style->color_flags[GTK_STATE_NORMAL] = GTK_RC_FG | GTK_RC_BG;
10619       rc_style->color_flags[GTK_STATE_PRELIGHT] = GTK_RC_FG | GTK_RC_BG;
10620       rc_style->color_flags[GTK_STATE_ACTIVE] = GTK_RC_FG | GTK_RC_BG;
10621       rc_style->fg[GTK_STATE_NORMAL] = yellow;
10622       rc_style->bg[GTK_STATE_NORMAL] = blue;
10623       rc_style->fg[GTK_STATE_PRELIGHT] = blue;
10624       rc_style->bg[GTK_STATE_PRELIGHT] = yellow;
10625       rc_style->fg[GTK_STATE_ACTIVE] = red;
10626       rc_style->bg[GTK_STATE_ACTIVE] = cyan;
10627       rc_style->xthickness = 5;
10628       rc_style->ythickness = 5;
10629
10630       gtk_widget_modify_style (button, rc_style);
10631       gtk_widget_modify_style (GTK_BIN (button)->child, rc_style);
10632
10633       g_object_unref (rc_style);
10634       
10635       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
10636     }
10637   
10638   if (!gtk_widget_get_visible (window))
10639     gtk_widget_show_all (window);
10640   else
10641     gtk_widget_destroy (window);
10642 }
10643
10644 /*
10645  * Main Window and Exit
10646  */
10647
10648 void
10649 do_exit (GtkWidget *widget, GtkWidget *window)
10650 {
10651   gtk_widget_destroy (window);
10652   gtk_main_quit ();
10653 }
10654
10655 struct {
10656   char *label;
10657   void (*func) (GtkWidget *widget);
10658   gboolean do_not_benchmark;
10659 } buttons[] =
10660 {
10661   { "alpha window", create_alpha_window },
10662   { "big windows", create_big_windows },
10663   { "button box", create_button_box },
10664   { "buttons", create_buttons },
10665   { "check buttons", create_check_buttons },
10666   { "color selection", create_color_selection },
10667   { "composited window", create_composited_window },
10668   { "cursors", create_cursors },
10669   { "dialog", create_dialog },
10670   { "display & screen", create_display_screen, TRUE },
10671   { "entry", create_entry },
10672   { "event box", create_event_box },
10673   { "event watcher", create_event_watcher },
10674   { "expander", create_expander },
10675   { "flipping", create_flipping },
10676   { "focus", create_focus },
10677   { "font selection", create_font_selection },
10678   { "gridded geometry", create_gridded_geometry },
10679   { "handle box", create_handle_box },
10680   { "image from drawable", create_get_image },
10681   { "image", create_image },
10682   { "key lookup", create_key_lookup },
10683   { "labels", create_labels },
10684   { "layout", create_layout },
10685   { "menus", create_menus },
10686   { "message dialog", create_message_dialog },
10687   { "modal window", create_modal_window, TRUE },
10688   { "notebook", create_notebook },
10689   { "panes", create_panes },
10690   { "paned keyboard", create_paned_keyboard_navigation },
10691   { "pixmap", create_pixmap },
10692   { "progress bar", create_progress_bar },
10693   { "properties", create_properties },
10694   { "radio buttons", create_radio_buttons },
10695   { "range controls", create_range_controls },
10696   { "rc file", create_rc_file },
10697   { "reparent", create_reparent },
10698   { "resize grips", create_resize_grips },
10699   { "rotated label", create_rotated_label },
10700   { "rotated text", create_rotated_text },
10701   { "rulers", create_rulers },
10702   { "saved position", create_saved_position },
10703   { "scrolled windows", create_scrolled_windows },
10704   { "shapes", create_shapes },
10705   { "size groups", create_size_groups },
10706   { "snapshot", create_snapshot },
10707   { "spinbutton", create_spins },
10708   { "statusbar", create_statusbar },
10709   { "styles", create_styles },
10710   { "test idle", create_idle_test },
10711   { "test mainloop", create_mainloop, TRUE },
10712   { "test scrolling", create_scroll_test },
10713   { "test selection", create_selection_test },
10714   { "test timeout", create_timeout_test },
10715   { "toggle buttons", create_toggle_buttons },
10716   { "toolbar", create_toolbar },
10717   { "tooltips", create_tooltips },
10718   { "WM hints", create_wmhints },
10719   { "window sizing", create_window_sizing },
10720   { "window states", create_window_states }
10721 };
10722 int nbuttons = sizeof (buttons) / sizeof (buttons[0]);
10723
10724 void
10725 create_main_window (void)
10726 {
10727   GtkWidget *window;
10728   GtkWidget *box1;
10729   GtkWidget *box2;
10730   GtkWidget *scrolled_window;
10731   GtkWidget *button;
10732   GtkWidget *label;
10733   gchar buffer[64];
10734   GtkWidget *separator;
10735   GdkGeometry geometry;
10736   int i;
10737
10738   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
10739   gtk_widget_set_name (window, "main window");
10740   gtk_window_move (GTK_WINDOW (window), 50, 20);
10741   gtk_window_set_default_size (GTK_WINDOW (window), -1, 400);
10742
10743   geometry.min_width = -1;
10744   geometry.min_height = -1;
10745   geometry.max_width = -1;
10746   geometry.max_height = G_MAXSHORT;
10747   gtk_window_set_geometry_hints (GTK_WINDOW (window), NULL,
10748                                  &geometry,
10749                                  GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE);
10750
10751   g_signal_connect (window, "destroy",
10752                     G_CALLBACK (gtk_main_quit),
10753                     NULL);
10754   g_signal_connect (window, "delete-event",
10755                     G_CALLBACK (gtk_false),
10756                     NULL);
10757
10758   box1 = gtk_vbox_new (FALSE, 0);
10759   gtk_container_add (GTK_CONTAINER (window), box1);
10760
10761   if (gtk_micro_version > 0)
10762     sprintf (buffer,
10763              "Gtk+ v%d.%d.%d",
10764              gtk_major_version,
10765              gtk_minor_version,
10766              gtk_micro_version);
10767   else
10768     sprintf (buffer,
10769              "Gtk+ v%d.%d",
10770              gtk_major_version,
10771              gtk_minor_version);
10772
10773   label = gtk_label_new (buffer);
10774   gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);
10775   gtk_widget_set_name (label, "testgtk-version-label");
10776
10777   scrolled_window = gtk_scrolled_window_new (NULL, NULL);
10778   gtk_container_set_border_width (GTK_CONTAINER (scrolled_window), 10);
10779   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
10780                                   GTK_POLICY_NEVER, 
10781                                   GTK_POLICY_AUTOMATIC);
10782   gtk_box_pack_start (GTK_BOX (box1), scrolled_window, TRUE, TRUE, 0);
10783
10784   box2 = gtk_vbox_new (FALSE, 0);
10785   gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
10786   gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_window), box2);
10787   gtk_container_set_focus_vadjustment (GTK_CONTAINER (box2),
10788                                        gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (scrolled_window)));
10789   gtk_widget_show (box2);
10790
10791   for (i = 0; i < nbuttons; i++)
10792     {
10793       button = gtk_button_new_with_label (buttons[i].label);
10794       if (buttons[i].func)
10795         g_signal_connect (button, 
10796                           "clicked", 
10797                           G_CALLBACK(buttons[i].func),
10798                           NULL);
10799       else
10800         gtk_widget_set_sensitive (button, FALSE);
10801       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
10802     }
10803
10804   separator = gtk_hseparator_new ();
10805   gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
10806
10807   box2 = gtk_vbox_new (FALSE, 10);
10808   gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
10809   gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
10810
10811   button = gtk_button_new_with_mnemonic ("_Close");
10812   g_signal_connect (button, "clicked",
10813                     G_CALLBACK (do_exit),
10814                     window);
10815   gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
10816   gtk_widget_set_can_default (button, TRUE);
10817   gtk_widget_grab_default (button);
10818
10819   gtk_widget_show_all (window);
10820 }
10821
10822 static void
10823 test_init (void)
10824 {
10825   if (g_file_test ("../gdk-pixbuf/libpixbufloader-pnm.la",
10826                    G_FILE_TEST_EXISTS))
10827     {
10828       g_setenv ("GDK_PIXBUF_MODULE_FILE", "../gdk-pixbuf/gdk-pixbuf.loaders", TRUE);
10829       g_setenv ("GTK_IM_MODULE_FILE", "../modules/input/gtk.immodules", TRUE);
10830     }
10831 }
10832
10833 static char *
10834 pad (const char *str, int to)
10835 {
10836   static char buf[256];
10837   int len = strlen (str);
10838   int i;
10839
10840   for (i = 0; i < to; i++)
10841     buf[i] = ' ';
10842
10843   buf[to] = '\0';
10844
10845   memcpy (buf, str, len);
10846
10847   return buf;
10848 }
10849
10850 static void
10851 bench_iteration (GtkWidget *widget, void (* fn) (GtkWidget *widget))
10852 {
10853   fn (widget); /* on */
10854   while (g_main_context_iteration (NULL, FALSE));
10855   fn (widget); /* off */
10856   while (g_main_context_iteration (NULL, FALSE));
10857 }
10858
10859 void
10860 do_real_bench (GtkWidget *widget, void (* fn) (GtkWidget *widget), char *name, int num)
10861 {
10862   GTimeVal tv0, tv1;
10863   double dt_first;
10864   double dt;
10865   int n;
10866   static gboolean printed_headers = FALSE;
10867
10868   if (!printed_headers) {
10869     g_print ("Test                 Iters      First      Other\n");
10870     g_print ("-------------------- ----- ---------- ----------\n");
10871     printed_headers = TRUE;
10872   }
10873
10874   g_get_current_time (&tv0);
10875   bench_iteration (widget, fn); 
10876   g_get_current_time (&tv1);
10877
10878   dt_first = ((double)tv1.tv_sec - tv0.tv_sec) * 1000.0
10879         + (tv1.tv_usec - tv0.tv_usec) / 1000.0;
10880
10881   g_get_current_time (&tv0);
10882   for (n = 0; n < num - 1; n++)
10883     bench_iteration (widget, fn); 
10884   g_get_current_time (&tv1);
10885   dt = ((double)tv1.tv_sec - tv0.tv_sec) * 1000.0
10886         + (tv1.tv_usec - tv0.tv_usec) / 1000.0;
10887
10888   g_print ("%s %5d ", pad (name, 20), num);
10889   if (num > 1)
10890     g_print ("%10.1f %10.1f\n", dt_first, dt/(num-1));
10891   else
10892     g_print ("%10.1f\n", dt_first);
10893 }
10894
10895 void
10896 do_bench (char* what, int num)
10897 {
10898   int i;
10899   GtkWidget *widget;
10900   void (* fn) (GtkWidget *widget);
10901   fn = NULL;
10902   widget = gtk_window_new (GTK_WINDOW_TOPLEVEL);
10903
10904   if (g_ascii_strcasecmp (what, "ALL") == 0)
10905     {
10906       for (i = 0; i < nbuttons; i++)
10907         {
10908           if (!buttons[i].do_not_benchmark)
10909             do_real_bench (widget, buttons[i].func, buttons[i].label, num);
10910         }
10911
10912       return;
10913     }
10914   else
10915     {
10916       for (i = 0; i < nbuttons; i++)
10917         {
10918           if (strcmp (buttons[i].label, what) == 0)
10919             {
10920               fn = buttons[i].func;
10921               break;
10922             }
10923         }
10924       
10925       if (!fn)
10926         g_print ("Can't bench: \"%s\" not found.\n", what);
10927       else
10928         do_real_bench (widget, fn, buttons[i].label, num);
10929     }
10930 }
10931
10932 void 
10933 usage (void)
10934 {
10935   fprintf (stderr, "Usage: testgtk [--bench ALL|<bench>[:<count>]]\n");
10936   exit (1);
10937 }
10938
10939 int
10940 main (int argc, char *argv[])
10941 {
10942   GtkBindingSet *binding_set;
10943   int i;
10944   gboolean done_benchmarks = FALSE;
10945
10946   srand (time (NULL));
10947
10948   test_init ();
10949
10950   /* Check to see if we are being run from the correct
10951    * directory.
10952    */
10953   if (file_exists ("testgtkrc"))
10954     gtk_rc_add_default_file ("testgtkrc");
10955   else if (file_exists ("tests/testgtkrc"))
10956     gtk_rc_add_default_file ("tests/testgtkrc");
10957   else
10958     g_warning ("Couldn't find file \"testgtkrc\".");
10959
10960   g_set_application_name ("GTK+ Test Program");
10961
10962   gtk_init (&argc, &argv);
10963
10964   gtk_accelerator_set_default_mod_mask (GDK_SHIFT_MASK |
10965                                         GDK_CONTROL_MASK |
10966                                         GDK_MOD1_MASK | 
10967                                         GDK_META_MASK |
10968                                         GDK_SUPER_MASK |
10969                                         GDK_HYPER_MASK |
10970                                         GDK_MOD4_MASK);
10971   /*  benchmarking
10972    */
10973   for (i = 1; i < argc; i++)
10974     {
10975       if (strncmp (argv[i], "--bench", strlen("--bench")) == 0)
10976         {
10977           int num = 1;
10978           char *nextarg;
10979           char *what;
10980           char *count;
10981           
10982           nextarg = strchr (argv[i], '=');
10983           if (nextarg)
10984             nextarg++;
10985           else
10986             {
10987               i++;
10988               if (i == argc)
10989                 usage ();
10990               nextarg = argv[i];
10991             }
10992
10993           count = strchr (nextarg, ':');
10994           if (count)
10995             {
10996               what = g_strndup (nextarg, count - nextarg);
10997               count++;
10998               num = atoi (count);
10999               if (num <= 0)
11000                 usage ();
11001             }
11002           else
11003             what = g_strdup (nextarg);
11004
11005           do_bench (what, num ? num : 1);
11006           done_benchmarks = TRUE;
11007         }
11008       else
11009         usage ();
11010     }
11011   if (done_benchmarks)
11012     return 0;
11013
11014   /* bindings test
11015    */
11016   binding_set = gtk_binding_set_by_class (g_type_class_ref (GTK_TYPE_WIDGET));
11017   gtk_binding_entry_add_signal (binding_set,
11018                                 '9', GDK_CONTROL_MASK | GDK_RELEASE_MASK,
11019                                 "debug_msg",
11020                                 1,
11021                                 G_TYPE_STRING, "GtkWidgetClass <ctrl><release>9 test");
11022   
11023   /* We use gtk_rc_parse_string() here so we can make sure it works across theme
11024    * changes
11025    */
11026
11027   gtk_rc_parse_string ("style \"testgtk-version-label\" { "
11028                        "   fg[NORMAL] = \"#ff0000\"\n"
11029                        "   font = \"Sans 18\"\n"
11030                        "}\n"
11031                        "widget \"*.testgtk-version-label\" style \"testgtk-version-label\"");
11032   
11033   create_main_window ();
11034
11035   gtk_main ();
11036
11037   if (1)
11038     {
11039       while (g_main_context_pending (NULL))
11040         g_main_context_iteration (NULL, FALSE);
11041 #if 0
11042       sleep (1);
11043       while (g_main_context_pending (NULL))
11044         g_main_context_iteration (NULL, FALSE);
11045 #endif
11046     }
11047   return 0;
11048 }