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