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