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