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