]> Pileus Git - ~andy/gtk/blob - tests/testgtk.c
11ad77267782525e73f1a4597aef577ff24ebb66
[~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 *options_hbox;
7007       GtkWidget *check_button;
7008       
7009       window = gtk_color_selection_dialog_new ("color selection dialog");
7010       gtk_window_set_screen (GTK_WINDOW (window), 
7011                              gtk_widget_get_screen (widget));
7012                              
7013       gtk_widget_show (GTK_COLOR_SELECTION_DIALOG (window)->help_button);
7014
7015       gtk_window_set_position (GTK_WINDOW (window), GTK_WIN_POS_MOUSE);
7016
7017       g_signal_connect (window, "destroy",
7018                         G_CALLBACK(gtk_widget_destroyed),
7019                         &window);
7020
7021       options_hbox = gtk_hbox_new (FALSE, 0);
7022       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), options_hbox, FALSE, FALSE, 0);
7023       gtk_container_set_border_width (GTK_CONTAINER (options_hbox), 10);
7024       
7025       check_button = gtk_check_button_new_with_label ("Show Opacity");
7026       gtk_box_pack_start (GTK_BOX (options_hbox), check_button, FALSE, FALSE, 0);
7027       g_signal_connect (check_button, "toggled",
7028                         G_CALLBACK (opacity_toggled_cb), window);
7029
7030       check_button = gtk_check_button_new_with_label ("Show Palette");
7031       gtk_box_pack_end (GTK_BOX (options_hbox), check_button, FALSE, FALSE, 0);
7032       g_signal_connect (check_button, "toggled",
7033                         G_CALLBACK (palette_toggled_cb), window);
7034
7035       g_signal_connect (GTK_COLOR_SELECTION_DIALOG (window)->colorsel,
7036                         "color_changed",
7037                         G_CALLBACK (color_selection_changed),
7038                         window);
7039
7040       g_signal_connect (GTK_COLOR_SELECTION_DIALOG (window)->ok_button,
7041                         "clicked",
7042                         G_CALLBACK (color_selection_ok),
7043                         window);
7044
7045       g_signal_connect_swapped (GTK_COLOR_SELECTION_DIALOG (window)->cancel_button,
7046                                 "clicked",
7047                                 G_CALLBACK (gtk_widget_destroy),
7048                                 window);
7049     }
7050
7051   if (!GTK_WIDGET_VISIBLE (window))
7052     gtk_widget_show_all (window);
7053   else
7054     gtk_widget_destroy (window);
7055 }
7056
7057 /*
7058  * GtkFileSelection
7059  */
7060
7061 void
7062 show_fileops (GtkWidget        *widget,
7063               GtkFileSelection *fs)
7064 {
7065   gboolean show_ops;
7066
7067   show_ops = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
7068
7069   if (show_ops)
7070     gtk_file_selection_show_fileop_buttons (fs);
7071   else
7072     gtk_file_selection_hide_fileop_buttons (fs);
7073 }
7074
7075 void
7076 select_multiple (GtkWidget        *widget,
7077                  GtkFileSelection *fs)
7078 {
7079   gboolean select_multiple;
7080
7081   select_multiple = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
7082   gtk_file_selection_set_select_multiple (fs, select_multiple);
7083 }
7084
7085 void
7086 file_selection_ok (GtkFileSelection *fs)
7087 {
7088   int i;
7089   gchar **selections;
7090
7091   selections = gtk_file_selection_get_selections (fs);
7092
7093   for (i = 0; selections[i] != NULL; i++)
7094     g_print ("%s\n", selections[i]);
7095
7096   g_strfreev (selections);
7097
7098   gtk_widget_destroy (GTK_WIDGET (fs));
7099 }
7100
7101 void
7102 create_file_selection (GtkWidget *widget)
7103 {
7104   static GtkWidget *window = NULL;
7105   GtkWidget *button;
7106
7107   if (!window)
7108     {
7109       window = gtk_file_selection_new ("file selection dialog");
7110       gtk_window_set_screen (GTK_WINDOW (window),
7111                              gtk_widget_get_screen (widget));
7112
7113       gtk_file_selection_hide_fileop_buttons (GTK_FILE_SELECTION (window));
7114
7115       gtk_window_set_position (GTK_WINDOW (window), GTK_WIN_POS_MOUSE);
7116
7117       g_signal_connect (window, "destroy",
7118                         G_CALLBACK (gtk_widget_destroyed),
7119                         &window);
7120
7121       g_signal_connect_swapped (GTK_FILE_SELECTION (window)->ok_button,
7122                                 "clicked",
7123                                 G_CALLBACK (file_selection_ok),
7124                                 window);
7125       g_signal_connect_swapped (GTK_FILE_SELECTION (window)->cancel_button,
7126                                 "clicked",
7127                                 G_CALLBACK (gtk_widget_destroy),
7128                                 window);
7129       
7130       button = gtk_check_button_new_with_label ("Show Fileops");
7131       g_signal_connect (button, "toggled",
7132                         G_CALLBACK (show_fileops),
7133                         window);
7134       gtk_box_pack_start (GTK_BOX (GTK_FILE_SELECTION (window)->action_area), 
7135                           button, FALSE, FALSE, 0);
7136       gtk_widget_show (button);
7137
7138       button = gtk_check_button_new_with_label ("Select Multiple");
7139       g_signal_connect (button, "clicked",
7140                         G_CALLBACK (select_multiple),
7141                         window);
7142       gtk_box_pack_start (GTK_BOX (GTK_FILE_SELECTION (window)->action_area), 
7143                           button, FALSE, FALSE, 0);
7144       gtk_widget_show (button);
7145     }
7146   
7147   if (!GTK_WIDGET_VISIBLE (window))
7148     gtk_widget_show (window);
7149   else
7150     gtk_widget_destroy (window);
7151 }
7152
7153 void
7154 flipping_toggled_cb (GtkWidget *widget, gpointer data)
7155 {
7156   int state = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
7157   int new_direction = state ? GTK_TEXT_DIR_RTL : GTK_TEXT_DIR_LTR;
7158
7159   gtk_widget_set_default_direction (new_direction);
7160 }
7161
7162 static void
7163 set_direction_recurse (GtkWidget *widget,
7164                        gpointer   data)
7165 {
7166   GtkTextDirection *dir = data;
7167   
7168   gtk_widget_set_direction (widget, *dir);
7169   if (GTK_IS_CONTAINER (widget))
7170     gtk_container_foreach (GTK_CONTAINER (widget),
7171                            set_direction_recurse,
7172                            data);
7173 }
7174
7175 static GtkWidget *
7176 create_forward_back (const char       *title,
7177                      GtkTextDirection  text_dir)
7178 {
7179   GtkWidget *frame = gtk_frame_new (title);
7180   GtkWidget *bbox = gtk_hbutton_box_new ();
7181   GtkWidget *back_button = gtk_button_new_from_stock (GTK_STOCK_GO_BACK);
7182   GtkWidget *forward_button = gtk_button_new_from_stock (GTK_STOCK_GO_FORWARD);
7183
7184   gtk_container_set_border_width (GTK_CONTAINER (bbox), 5);
7185   
7186   gtk_container_add (GTK_CONTAINER (frame), bbox);
7187   gtk_container_add (GTK_CONTAINER (bbox), back_button);
7188   gtk_container_add (GTK_CONTAINER (bbox), forward_button);
7189
7190   set_direction_recurse (frame, &text_dir);
7191
7192   return frame;
7193 }
7194
7195 void
7196 create_flipping (GtkWidget *widget)
7197 {
7198   static GtkWidget *window = NULL;
7199   GtkWidget *check_button, *button;
7200
7201   if (!window)
7202     {
7203       window = gtk_dialog_new ();
7204
7205       gtk_window_set_screen (GTK_WINDOW (window),
7206                              gtk_widget_get_screen (widget));
7207
7208       g_signal_connect (window, "destroy",
7209                         G_CALLBACK (gtk_widget_destroyed),
7210                         &window);
7211
7212       gtk_window_set_title (GTK_WINDOW (window), "Bidirectional Flipping");
7213
7214       check_button = gtk_check_button_new_with_label ("Right-to-left global direction");
7215       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
7216                           check_button, TRUE, TRUE, 0);
7217
7218       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
7219                           create_forward_back ("Default", GTK_TEXT_DIR_NONE),
7220                           TRUE, TRUE, 0);
7221
7222       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
7223                           create_forward_back ("Left-to-Right", GTK_TEXT_DIR_LTR),
7224                           TRUE, TRUE, 0);
7225
7226       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
7227                           create_forward_back ("Right-to-Left", GTK_TEXT_DIR_RTL),
7228                           TRUE, TRUE, 0);
7229
7230       if (gtk_widget_get_default_direction () == GTK_TEXT_DIR_RTL)
7231         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button), TRUE);
7232
7233       g_signal_connect (check_button, "toggled",
7234                         G_CALLBACK (flipping_toggled_cb), FALSE);
7235
7236       gtk_container_set_border_width (GTK_CONTAINER (check_button), 10);
7237       
7238       button = gtk_button_new_with_label ("Close");
7239       g_signal_connect_swapped (button, "clicked",
7240                                 G_CALLBACK (gtk_widget_destroy), window);
7241       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
7242                           button, TRUE, TRUE, 0);
7243     }
7244   
7245   if (!GTK_WIDGET_VISIBLE (window))
7246     gtk_widget_show_all (window);
7247   else
7248     gtk_widget_destroy (window);
7249 }
7250
7251 /*
7252  * Focus test
7253  */
7254
7255 static GtkWidget*
7256 make_focus_table (GList **list)
7257 {
7258   GtkWidget *table;
7259   gint i, j;
7260   
7261   table = gtk_table_new (5, 5, FALSE);
7262
7263   i = 0;
7264   j = 0;
7265
7266   while (i < 5)
7267     {
7268       j = 0;
7269       while (j < 5)
7270         {
7271           GtkWidget *widget;
7272           
7273           if ((i + j) % 2)
7274             widget = gtk_entry_new ();
7275           else
7276             widget = gtk_button_new_with_label ("Foo");
7277
7278           *list = g_list_prepend (*list, widget);
7279           
7280           gtk_table_attach (GTK_TABLE (table),
7281                             widget,
7282                             i, i + 1,
7283                             j, j + 1,
7284                             GTK_EXPAND | GTK_FILL,
7285                             GTK_EXPAND | GTK_FILL,
7286                             5, 5);
7287           
7288           ++j;
7289         }
7290
7291       ++i;
7292     }
7293
7294   *list = g_list_reverse (*list);
7295   
7296   return table;
7297 }
7298
7299 static void
7300 create_focus (GtkWidget *widget)
7301 {
7302   static GtkWidget *window = NULL;
7303   
7304   if (!window)
7305     {
7306       GtkWidget *table;
7307       GtkWidget *frame;
7308       GList *list = NULL;
7309       
7310       window = gtk_dialog_new_with_buttons ("Keyboard focus navigation",
7311                                             NULL, 0,
7312                                             GTK_STOCK_CLOSE,
7313                                             GTK_RESPONSE_NONE,
7314                                             NULL);
7315
7316       gtk_window_set_screen (GTK_WINDOW (window),
7317                              gtk_widget_get_screen (widget));
7318
7319       g_signal_connect (window, "destroy",
7320                         G_CALLBACK (gtk_widget_destroyed),
7321                         &window);
7322
7323       g_signal_connect (window, "response",
7324                         G_CALLBACK (gtk_widget_destroy),
7325                         NULL);
7326       
7327       gtk_window_set_title (GTK_WINDOW (window), "Keyboard Focus Navigation");
7328
7329       frame = gtk_frame_new ("Weird tab focus chain");
7330
7331       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
7332                           frame, TRUE, TRUE, 0);
7333       
7334       table = make_focus_table (&list);
7335
7336       gtk_container_add (GTK_CONTAINER (frame), table);
7337
7338       gtk_container_set_focus_chain (GTK_CONTAINER (table),
7339                                      list);
7340
7341       g_list_free (list);
7342       
7343       frame = gtk_frame_new ("Default tab focus chain");
7344
7345       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
7346                           frame, TRUE, TRUE, 0);
7347
7348       list = NULL;
7349       table = make_focus_table (&list);
7350
7351       g_list_free (list);
7352       
7353       gtk_container_add (GTK_CONTAINER (frame), table);      
7354     }
7355   
7356   if (!GTK_WIDGET_VISIBLE (window))
7357     gtk_widget_show_all (window);
7358   else
7359     gtk_widget_destroy (window);
7360 }
7361
7362 /*
7363  * GtkFontSelection
7364  */
7365
7366 void
7367 font_selection_ok (GtkWidget              *w,
7368                    GtkFontSelectionDialog *fs)
7369 {
7370   gchar *s = gtk_font_selection_dialog_get_font_name (fs);
7371
7372   g_print ("%s\n", s);
7373   g_free (s);
7374   gtk_widget_destroy (GTK_WIDGET (fs));
7375 }
7376
7377 void
7378 create_font_selection (GtkWidget *widget)
7379 {
7380   static GtkWidget *window = NULL;
7381
7382   if (!window)
7383     {
7384       window = gtk_font_selection_dialog_new ("Font Selection Dialog");
7385       
7386       gtk_window_set_screen (GTK_WINDOW (window),
7387                              gtk_widget_get_screen (widget));
7388
7389       gtk_window_set_position (GTK_WINDOW (window), GTK_WIN_POS_MOUSE);
7390
7391       g_signal_connect (window, "destroy",
7392                         G_CALLBACK (gtk_widget_destroyed),
7393                         &window);
7394
7395       g_signal_connect (GTK_FONT_SELECTION_DIALOG (window)->ok_button,
7396                         "clicked", G_CALLBACK (font_selection_ok),
7397                         GTK_FONT_SELECTION_DIALOG (window));
7398       g_signal_connect_swapped (GTK_FONT_SELECTION_DIALOG (window)->cancel_button,
7399                                 "clicked", G_CALLBACK (gtk_widget_destroy),
7400                                 window);
7401     }
7402   
7403   if (!GTK_WIDGET_VISIBLE (window))
7404     gtk_widget_show (window);
7405   else
7406     gtk_widget_destroy (window);
7407 }
7408
7409 /*
7410  * GtkDialog
7411  */
7412
7413 static GtkWidget *dialog_window = NULL;
7414
7415 static void
7416 label_toggle (GtkWidget  *widget,
7417               GtkWidget **label)
7418 {
7419   if (!(*label))
7420     {
7421       *label = gtk_label_new ("Dialog Test");
7422       g_signal_connect (*label,
7423                         "destroy",
7424                         G_CALLBACK (gtk_widget_destroyed),
7425                         label);
7426       gtk_misc_set_padding (GTK_MISC (*label), 10, 10);
7427       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog_window)->vbox), 
7428                           *label, TRUE, TRUE, 0);
7429       gtk_widget_show (*label);
7430     }
7431   else
7432     gtk_widget_destroy (*label);
7433 }
7434
7435 #define RESPONSE_TOGGLE_SEPARATOR 1
7436
7437 static void
7438 print_response (GtkWidget *dialog,
7439                 gint       response_id,
7440                 gpointer   data)
7441 {
7442   g_print ("response signal received (%d)\n", response_id);
7443
7444   if (response_id == RESPONSE_TOGGLE_SEPARATOR)
7445     {
7446       gtk_dialog_set_has_separator (GTK_DIALOG (dialog),
7447                                     !gtk_dialog_get_has_separator (GTK_DIALOG (dialog)));
7448     }
7449 }
7450
7451 static void
7452 create_dialog (GtkWidget *widget)
7453 {
7454   static GtkWidget *label;
7455   GtkWidget *button;
7456
7457   if (!dialog_window)
7458     {
7459       /* This is a terrible example; it's much simpler to create
7460        * dialogs than this. Don't use testgtk for example code,
7461        * use gtk-demo ;-)
7462        */
7463       
7464       dialog_window = gtk_dialog_new ();
7465       gtk_window_set_screen (GTK_WINDOW (dialog_window),
7466                              gtk_widget_get_screen (widget));
7467
7468       g_signal_connect (dialog_window,
7469                         "response",
7470                         G_CALLBACK (print_response),
7471                         NULL);
7472       
7473       g_signal_connect (dialog_window, "destroy",
7474                         G_CALLBACK (gtk_widget_destroyed),
7475                         &dialog_window);
7476
7477       gtk_window_set_title (GTK_WINDOW (dialog_window), "GtkDialog");
7478       gtk_container_set_border_width (GTK_CONTAINER (dialog_window), 0);
7479
7480       button = gtk_button_new_with_label ("OK");
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_grab_default (button);
7485       gtk_widget_show (button);
7486
7487       button = gtk_button_new_with_label ("Toggle");
7488       g_signal_connect (button, "clicked",
7489                         G_CALLBACK (label_toggle),
7490                         &label);
7491       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
7492       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog_window)->action_area),
7493                           button, TRUE, TRUE, 0);
7494       gtk_widget_show (button);
7495
7496       label = NULL;
7497       
7498       button = gtk_button_new_with_label ("Separator");
7499
7500       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
7501
7502       gtk_dialog_add_action_widget (GTK_DIALOG (dialog_window),
7503                                     button,
7504                                     RESPONSE_TOGGLE_SEPARATOR);
7505       gtk_widget_show (button);
7506     }
7507
7508   if (!GTK_WIDGET_VISIBLE (dialog_window))
7509     gtk_widget_show (dialog_window);
7510   else
7511     gtk_widget_destroy (dialog_window);
7512 }
7513
7514 /* Display & Screen test 
7515  */
7516
7517 typedef struct 
7518
7519   GtkEntry *entry;
7520   GtkWidget *radio_dpy;
7521   GtkWidget *toplevel; 
7522   GtkWidget *dialog_window;
7523   GList *valid_display_list;
7524 } ScreenDisplaySelection;
7525
7526 static gint
7527 display_name_cmp (gconstpointer a,
7528                   gconstpointer b)
7529 {
7530   return g_ascii_strcasecmp (a,b);
7531 }
7532
7533 static void
7534 screen_display_check (GtkWidget *widget, ScreenDisplaySelection *data)
7535 {
7536   char *display_name;
7537   GdkDisplay *display = gtk_widget_get_display (widget);
7538   GtkWidget *dialog;
7539   GdkScreen *new_screen = NULL;
7540   GdkScreen *current_screen = gtk_widget_get_screen (widget);
7541   
7542   if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (data->radio_dpy)))
7543     {
7544       display_name = g_strdup (gtk_entry_get_text (data->entry));
7545       display = gdk_display_open (display_name);
7546       
7547       if (!display)
7548         {
7549           dialog = gtk_message_dialog_new (GTK_WINDOW (gtk_widget_get_toplevel (widget)),
7550                                            GTK_DIALOG_DESTROY_WITH_PARENT,
7551                                            GTK_MESSAGE_ERROR,
7552                                            GTK_BUTTONS_OK,
7553                                            "The display :\n%s\ncannot be opened",
7554                                            display_name);
7555           gtk_window_set_screen (GTK_WINDOW (dialog), current_screen);
7556           gtk_widget_show (dialog);
7557           g_signal_connect (dialog, "response",
7558                             G_CALLBACK (gtk_widget_destroy),
7559                             NULL);
7560         }
7561       else
7562         {
7563           if (!g_list_find_custom (data->valid_display_list, 
7564                                    display_name,
7565                                    display_name_cmp))
7566             data->valid_display_list = g_list_append (data->valid_display_list,
7567                                                       display_name);
7568           
7569           new_screen = gdk_display_get_default_screen (display);
7570         }
7571     }
7572   else
7573     {
7574       gint number_of_screens = gdk_display_get_n_screens (display);
7575       gint screen_num = gdk_screen_get_number (current_screen);
7576       if ((screen_num +1) < number_of_screens)
7577         new_screen = gdk_display_get_screen (display, screen_num + 1);
7578       else
7579         new_screen = gdk_display_get_screen (display, 0);
7580     }
7581   
7582   if (new_screen) 
7583     {
7584       gtk_window_set_screen (GTK_WINDOW (data->toplevel), new_screen);
7585       gtk_widget_destroy (data->dialog_window);
7586     }
7587 }
7588
7589 void
7590 screen_display_destroy_diag (GtkWidget *widget, GtkWidget *data)
7591 {
7592   gtk_widget_destroy (data);
7593 }
7594
7595 void
7596 create_display_screen (GtkWidget *widget)
7597 {
7598   GtkWidget *table, *frame, *window, *combo_dpy, *vbox;
7599   GtkWidget *radio_dpy, *radio_scr, *applyb, *cancelb;
7600   GtkWidget *bbox;
7601   ScreenDisplaySelection *scr_dpy_data;
7602   GdkScreen *screen = gtk_widget_get_screen (widget);
7603   static GList *valid_display_list = NULL;
7604   
7605   GdkDisplay *display = gdk_screen_get_display (screen);
7606
7607   window = gtk_widget_new (gtk_window_get_type (),
7608                            "screen", screen,
7609                            "user_data", NULL,
7610                            "type", GTK_WINDOW_TOPLEVEL,
7611                            "title",
7612                            "Screen or Display selection",
7613                            "border_width", 10, NULL);
7614   g_signal_connect (window, "destroy", 
7615                     G_CALLBACK (gtk_widget_destroy), NULL);
7616
7617   vbox = gtk_vbox_new (FALSE, 3);
7618   gtk_container_add (GTK_CONTAINER (window), vbox);
7619   
7620   frame = gtk_frame_new ("Select screen or display");
7621   gtk_container_add (GTK_CONTAINER (vbox), frame);
7622   
7623   table = gtk_table_new (2, 2, TRUE);
7624   gtk_table_set_row_spacings (GTK_TABLE (table), 3);
7625   gtk_table_set_col_spacings (GTK_TABLE (table), 3);
7626
7627   gtk_container_add (GTK_CONTAINER (frame), table);
7628
7629   radio_dpy = gtk_radio_button_new_with_label (NULL, "move to another X display");
7630   if (gdk_display_get_n_screens(display) > 1)
7631     radio_scr = gtk_radio_button_new_with_label 
7632     (gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio_dpy)), "move to next screen");
7633   else
7634     {    
7635       radio_scr = gtk_radio_button_new_with_label 
7636         (gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio_dpy)), 
7637          "only one screen on the current display");
7638       gtk_widget_set_sensitive (radio_scr, FALSE);
7639     }
7640   combo_dpy = gtk_combo_new ();
7641   if (!valid_display_list)
7642     valid_display_list = g_list_append (valid_display_list, "diabolo:0.0");
7643     
7644   gtk_combo_set_popdown_strings (GTK_COMBO (combo_dpy), valid_display_list);
7645     
7646   gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (combo_dpy)->entry), 
7647                       "<hostname>:<X Server Num>.<Screen Num>");
7648
7649   gtk_table_attach_defaults (GTK_TABLE (table), radio_dpy, 0, 1, 0, 1);
7650   gtk_table_attach_defaults (GTK_TABLE (table), radio_scr, 0, 1, 1, 2);
7651   gtk_table_attach_defaults (GTK_TABLE (table), combo_dpy, 1, 2, 0, 1);
7652
7653   bbox = gtk_hbutton_box_new ();
7654   applyb = gtk_button_new_from_stock (GTK_STOCK_APPLY);
7655   cancelb = gtk_button_new_from_stock (GTK_STOCK_CANCEL);
7656   
7657   gtk_container_add (GTK_CONTAINER (vbox), bbox);
7658
7659   gtk_container_add (GTK_CONTAINER (bbox), applyb);
7660   gtk_container_add (GTK_CONTAINER (bbox), cancelb);
7661
7662   scr_dpy_data = g_new0 (ScreenDisplaySelection, 1);
7663
7664   scr_dpy_data->entry = GTK_ENTRY (GTK_COMBO (combo_dpy)->entry);
7665   scr_dpy_data->radio_dpy = radio_dpy;
7666   scr_dpy_data->toplevel = gtk_widget_get_toplevel (widget);
7667   scr_dpy_data->dialog_window = window;
7668   scr_dpy_data->valid_display_list = valid_display_list;
7669
7670   g_signal_connect (cancelb, "clicked", 
7671                     G_CALLBACK (screen_display_destroy_diag), window);
7672   g_signal_connect (applyb, "clicked", 
7673                     G_CALLBACK (screen_display_check), scr_dpy_data);
7674   gtk_widget_show_all (window);
7675 }
7676
7677 /* Event Watcher
7678  */
7679 static gboolean event_watcher_enter_id = 0;
7680 static gboolean event_watcher_leave_id = 0;
7681
7682 static gboolean
7683 event_watcher (GSignalInvocationHint *ihint,
7684                guint                  n_param_values,
7685                const GValue          *param_values,
7686                gpointer               data)
7687 {
7688   g_print ("Watch: \"%s\" emitted for %s\n",
7689            g_signal_name (ihint->signal_id),
7690            G_OBJECT_TYPE_NAME (g_value_get_object (param_values + 0)));
7691
7692   return TRUE;
7693 }
7694
7695 static void
7696 event_watcher_down (void)
7697 {
7698   if (event_watcher_enter_id)
7699     {
7700       guint signal_id;
7701
7702       signal_id = g_signal_lookup ("enter_notify_event", GTK_TYPE_WIDGET);
7703       g_signal_remove_emission_hook (signal_id, event_watcher_enter_id);
7704       event_watcher_enter_id = 0;
7705       signal_id = g_signal_lookup ("leave_notify_event", GTK_TYPE_WIDGET);
7706       g_signal_remove_emission_hook (signal_id, event_watcher_leave_id);
7707       event_watcher_leave_id = 0;
7708     }
7709 }
7710
7711 static void
7712 event_watcher_toggle (void)
7713 {
7714   if (event_watcher_enter_id)
7715     event_watcher_down ();
7716   else
7717     {
7718       guint signal_id;
7719
7720       signal_id = g_signal_lookup ("enter_notify_event", GTK_TYPE_WIDGET);
7721       event_watcher_enter_id = g_signal_add_emission_hook (signal_id, 0, event_watcher, NULL, NULL);
7722       signal_id = g_signal_lookup ("leave_notify_event", GTK_TYPE_WIDGET);
7723       event_watcher_leave_id = g_signal_add_emission_hook (signal_id, 0, event_watcher, NULL, NULL);
7724     }
7725 }
7726
7727 static void
7728 create_event_watcher (GtkWidget *widget)
7729 {
7730   GtkWidget *button;
7731
7732   if (!dialog_window)
7733     {
7734       dialog_window = gtk_dialog_new ();
7735       gtk_window_set_screen (GTK_WINDOW (dialog_window),
7736                              gtk_widget_get_screen (widget));
7737
7738       g_signal_connect (dialog_window, "destroy",
7739                         G_CALLBACK (gtk_widget_destroyed),
7740                         &dialog_window);
7741       g_signal_connect (dialog_window, "destroy",
7742                         G_CALLBACK (event_watcher_down),
7743                         NULL);
7744
7745       gtk_window_set_title (GTK_WINDOW (dialog_window), "Event Watcher");
7746       gtk_container_set_border_width (GTK_CONTAINER (dialog_window), 0);
7747       gtk_widget_set_size_request (dialog_window, 200, 110);
7748
7749       button = gtk_toggle_button_new_with_label ("Activate Watch");
7750       g_signal_connect (button, "clicked",
7751                         G_CALLBACK (event_watcher_toggle),
7752                         NULL);
7753       gtk_container_set_border_width (GTK_CONTAINER (button), 10);
7754       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog_window)->vbox), 
7755                           button, TRUE, TRUE, 0);
7756       gtk_widget_show (button);
7757
7758       button = gtk_button_new_with_label ("Close");
7759       g_signal_connect_swapped (button, "clicked",
7760                                 G_CALLBACK (gtk_widget_destroy),
7761                                 dialog_window);
7762       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
7763       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog_window)->action_area),
7764                           button, TRUE, TRUE, 0);
7765       gtk_widget_grab_default (button);
7766       gtk_widget_show (button);
7767     }
7768
7769   if (!GTK_WIDGET_VISIBLE (dialog_window))
7770     gtk_widget_show (dialog_window);
7771   else
7772     gtk_widget_destroy (dialog_window);
7773 }
7774
7775 /*
7776  * GtkRange
7777  */
7778
7779 static gchar*
7780 reformat_value (GtkScale *scale,
7781                 gdouble   value)
7782 {
7783   return g_strdup_printf ("-->%0.*g<--",
7784                           gtk_scale_get_digits (scale), value);
7785 }
7786
7787 static void
7788 create_range_controls (GtkWidget *widget)
7789 {
7790   static GtkWidget *window = NULL;
7791   GtkWidget *box1;
7792   GtkWidget *box2;
7793   GtkWidget *button;
7794   GtkWidget *scrollbar;
7795   GtkWidget *scale;
7796   GtkWidget *separator;
7797   GtkObject *adjustment;
7798   GtkWidget *hbox;
7799
7800   if (!window)
7801     {
7802       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7803
7804       gtk_window_set_screen (GTK_WINDOW (window),
7805                              gtk_widget_get_screen (widget));
7806
7807       g_signal_connect (window, "destroy",
7808                         G_CALLBACK (gtk_widget_destroyed),
7809                         &window);
7810
7811       gtk_window_set_title (GTK_WINDOW (window), "range controls");
7812       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
7813
7814
7815       box1 = gtk_vbox_new (FALSE, 0);
7816       gtk_container_add (GTK_CONTAINER (window), box1);
7817       gtk_widget_show (box1);
7818
7819
7820       box2 = gtk_vbox_new (FALSE, 10);
7821       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
7822       gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
7823       gtk_widget_show (box2);
7824
7825
7826       adjustment = gtk_adjustment_new (0.0, 0.0, 101.0, 0.1, 1.0, 1.0);
7827
7828       scale = gtk_hscale_new (GTK_ADJUSTMENT (adjustment));
7829       gtk_widget_set_size_request (GTK_WIDGET (scale), 150, -1);
7830       gtk_range_set_update_policy (GTK_RANGE (scale), GTK_UPDATE_DELAYED);
7831       gtk_scale_set_digits (GTK_SCALE (scale), 1);
7832       gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE);
7833       gtk_box_pack_start (GTK_BOX (box2), scale, TRUE, TRUE, 0);
7834       gtk_widget_show (scale);
7835
7836       scrollbar = gtk_hscrollbar_new (GTK_ADJUSTMENT (adjustment));
7837       gtk_range_set_update_policy (GTK_RANGE (scrollbar), 
7838                                    GTK_UPDATE_CONTINUOUS);
7839       gtk_box_pack_start (GTK_BOX (box2), scrollbar, TRUE, TRUE, 0);
7840       gtk_widget_show (scrollbar);
7841
7842       scale = gtk_hscale_new (GTK_ADJUSTMENT (adjustment));
7843       gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE);
7844       g_signal_connect (scale,
7845                         "format_value",
7846                         G_CALLBACK (reformat_value),
7847                         NULL);
7848       gtk_box_pack_start (GTK_BOX (box2), scale, TRUE, TRUE, 0);
7849       gtk_widget_show (scale);
7850       
7851       hbox = gtk_hbox_new (FALSE, 0);
7852
7853       scale = gtk_vscale_new (GTK_ADJUSTMENT (adjustment));
7854       gtk_widget_set_size_request (scale, -1, 200);
7855       gtk_scale_set_digits (GTK_SCALE (scale), 2);
7856       gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE);
7857       gtk_box_pack_start (GTK_BOX (hbox), scale, TRUE, TRUE, 0);
7858       gtk_widget_show (scale);
7859
7860       scale = gtk_vscale_new (GTK_ADJUSTMENT (adjustment));
7861       gtk_widget_set_size_request (scale, -1, 200);
7862       gtk_scale_set_digits (GTK_SCALE (scale), 2);
7863       gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE);
7864       gtk_range_set_inverted (GTK_RANGE (scale), TRUE);
7865       gtk_box_pack_start (GTK_BOX (hbox), scale, TRUE, TRUE, 0);
7866       gtk_widget_show (scale);
7867
7868       scale = gtk_vscale_new (GTK_ADJUSTMENT (adjustment));
7869       gtk_scale_set_draw_value (GTK_SCALE (scale), TRUE);
7870       g_signal_connect (scale,
7871                         "format_value",
7872                         G_CALLBACK (reformat_value),
7873                         NULL);
7874       gtk_box_pack_start (GTK_BOX (hbox), scale, TRUE, TRUE, 0);
7875       gtk_widget_show (scale);
7876
7877       
7878       gtk_box_pack_start (GTK_BOX (box2), hbox, TRUE, TRUE, 0);
7879       gtk_widget_show (hbox);
7880       
7881       separator = gtk_hseparator_new ();
7882       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
7883       gtk_widget_show (separator);
7884
7885
7886       box2 = gtk_vbox_new (FALSE, 10);
7887       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
7888       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
7889       gtk_widget_show (box2);
7890
7891
7892       button = gtk_button_new_with_label ("close");
7893       g_signal_connect_swapped (button, "clicked",
7894                                 G_CALLBACK (gtk_widget_destroy),
7895                                 window);
7896       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
7897       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
7898       gtk_widget_grab_default (button);
7899       gtk_widget_show (button);
7900     }
7901
7902   if (!GTK_WIDGET_VISIBLE (window))
7903     gtk_widget_show (window);
7904   else
7905     gtk_widget_destroy (window);
7906 }
7907
7908 /*
7909  * GtkRulers
7910  */
7911
7912 void
7913 create_rulers (GtkWidget *widget)
7914 {
7915   static GtkWidget *window = NULL;
7916   GtkWidget *table;
7917   GtkWidget *ruler;
7918
7919   if (!window)
7920     {
7921       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
7922
7923       gtk_window_set_screen (GTK_WINDOW (window),
7924                              gtk_widget_get_screen (widget));
7925
7926       g_object_set (window, "allow_shrink", TRUE, "allow_grow", TRUE, NULL);
7927
7928       g_signal_connect (window, "destroy",
7929                         G_CALLBACK (gtk_widget_destroyed),
7930                         &window);
7931
7932       gtk_window_set_title (GTK_WINDOW (window), "rulers");
7933       gtk_widget_set_size_request (window, 300, 300);
7934       gtk_widget_set_events (window, 
7935                              GDK_POINTER_MOTION_MASK 
7936                              | GDK_POINTER_MOTION_HINT_MASK);
7937       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
7938
7939       table = gtk_table_new (2, 2, FALSE);
7940       gtk_container_add (GTK_CONTAINER (window), table);
7941       gtk_widget_show (table);
7942
7943       ruler = gtk_hruler_new ();
7944       gtk_ruler_set_metric (GTK_RULER (ruler), GTK_CENTIMETERS);
7945       gtk_ruler_set_range (GTK_RULER (ruler), 100, 0, 0, 20);
7946
7947       g_signal_connect_swapped (window, 
7948                                 "motion_notify_event",
7949                                 G_CALLBACK (GTK_WIDGET_GET_CLASS (ruler)->motion_notify_event),
7950                                 ruler);
7951       
7952       gtk_table_attach (GTK_TABLE (table), ruler, 1, 2, 0, 1,
7953                         GTK_EXPAND | GTK_FILL, GTK_FILL, 0, 0);
7954       gtk_widget_show (ruler);
7955
7956
7957       ruler = gtk_vruler_new ();
7958       gtk_ruler_set_range (GTK_RULER (ruler), 5, 15, 0, 20);
7959
7960       g_signal_connect_swapped (window, 
7961                                 "motion_notify_event",
7962                                 G_CALLBACK (GTK_WIDGET_GET_CLASS (ruler)->motion_notify_event),
7963                                 ruler);
7964       
7965       gtk_table_attach (GTK_TABLE (table), ruler, 0, 1, 1, 2,
7966                         GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);
7967       gtk_widget_show (ruler);
7968     }
7969
7970   if (!GTK_WIDGET_VISIBLE (window))
7971     gtk_widget_show (window);
7972   else
7973     gtk_widget_destroy (window);
7974 }
7975
7976 static void
7977 text_toggle_editable (GtkWidget *checkbutton,
7978                        GtkWidget *text)
7979 {
7980    gtk_text_set_editable(GTK_TEXT(text),
7981                           GTK_TOGGLE_BUTTON(checkbutton)->active);
7982 }
7983
7984 static void
7985 text_toggle_word_wrap (GtkWidget *checkbutton,
7986                        GtkWidget *text)
7987 {
7988    gtk_text_set_word_wrap(GTK_TEXT(text),
7989                           GTK_TOGGLE_BUTTON(checkbutton)->active);
7990 }
7991
7992 struct {
7993   GdkColor color;
7994   gchar *name;
7995 } text_colors[] = {
7996  { { 0, 0x0000, 0x0000, 0x0000 }, "black" },
7997  { { 0, 0xFFFF, 0xFFFF, 0xFFFF }, "white" },
7998  { { 0, 0xFFFF, 0x0000, 0x0000 }, "red" },
7999  { { 0, 0x0000, 0xFFFF, 0x0000 }, "green" },
8000  { { 0, 0x0000, 0x0000, 0xFFFF }, "blue" }, 
8001  { { 0, 0x0000, 0xFFFF, 0xFFFF }, "cyan" },
8002  { { 0, 0xFFFF, 0x0000, 0xFFFF }, "magenta" },
8003  { { 0, 0xFFFF, 0xFFFF, 0x0000 }, "yellow" }
8004 };
8005
8006 int ntext_colors = sizeof(text_colors) / sizeof(text_colors[0]);
8007
8008 /*
8009  * GtkText
8010  */
8011 void
8012 text_insert_random (GtkWidget *w, GtkText *text)
8013 {
8014   int i;
8015   char c;
8016    for (i=0; i<10; i++)
8017     {
8018       c = 'A' + rand() % ('Z' - 'A');
8019       gtk_text_set_point (text, rand() % gtk_text_get_length (text));
8020       gtk_text_insert (text, NULL, NULL, NULL, &c, 1);
8021     }
8022 }
8023
8024 void
8025 create_text (GtkWidget *widget)
8026 {
8027   int i, j;
8028
8029   static GtkWidget *window = NULL;
8030   GtkWidget *box1;
8031   GtkWidget *box2;
8032   GtkWidget *hbox;
8033   GtkWidget *button;
8034   GtkWidget *check;
8035   GtkWidget *separator;
8036   GtkWidget *scrolled_window;
8037   GtkWidget *text;
8038
8039   FILE *infile;
8040
8041   if (!window)
8042     {
8043       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8044       gtk_window_set_screen (GTK_WINDOW (window),
8045                              gtk_widget_get_screen (widget));
8046
8047       gtk_widget_set_name (window, "text window");
8048       g_object_set (window, "allow_shrink", TRUE, "allow_grow", TRUE, NULL);
8049       gtk_widget_set_size_request (window, 500, 500);
8050
8051       g_signal_connect (window, "destroy",
8052                         G_CALLBACK (gtk_widget_destroyed),
8053                         &window);
8054
8055       gtk_window_set_title (GTK_WINDOW (window), "test");
8056       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
8057
8058
8059       box1 = gtk_vbox_new (FALSE, 0);
8060       gtk_container_add (GTK_CONTAINER (window), box1);
8061       gtk_widget_show (box1);
8062
8063
8064       box2 = gtk_vbox_new (FALSE, 10);
8065       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
8066       gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
8067       gtk_widget_show (box2);
8068
8069
8070       scrolled_window = gtk_scrolled_window_new (NULL, NULL);
8071       gtk_box_pack_start (GTK_BOX (box2), scrolled_window, TRUE, TRUE, 0);
8072       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
8073                                       GTK_POLICY_NEVER,
8074                                       GTK_POLICY_ALWAYS);
8075       gtk_widget_show (scrolled_window);
8076
8077       text = gtk_text_new (NULL, NULL);
8078       gtk_text_set_editable (GTK_TEXT (text), TRUE);
8079       gtk_container_add (GTK_CONTAINER (scrolled_window), text);
8080       gtk_widget_grab_focus (text);
8081       gtk_widget_show (text);
8082
8083
8084       gtk_text_freeze (GTK_TEXT (text));
8085
8086       for (i=0; i<ntext_colors; i++)
8087         {
8088           gtk_text_insert (GTK_TEXT (text), NULL, NULL, NULL, 
8089                            text_colors[i].name, -1);
8090           gtk_text_insert (GTK_TEXT (text), NULL, NULL, NULL, "\t", -1);
8091
8092           for (j=0; j<ntext_colors; j++)
8093             {
8094               gtk_text_insert (GTK_TEXT (text), NULL,
8095                                &text_colors[j].color, &text_colors[i].color,
8096                                "XYZ", -1);
8097             }
8098           gtk_text_insert (GTK_TEXT (text), NULL, NULL, NULL, "\n", -1);
8099         }
8100
8101       infile = fopen("testgtk.c", "r");
8102       
8103       if (infile)
8104         {
8105           char *buffer;
8106           int nbytes_read, nbytes_alloc;
8107           
8108           nbytes_read = 0;
8109           nbytes_alloc = 1024;
8110           buffer = g_new (char, nbytes_alloc);
8111           while (1)
8112             {
8113               int len;
8114               if (nbytes_alloc < nbytes_read + 1024)
8115                 {
8116                   nbytes_alloc *= 2;
8117                   buffer = g_realloc (buffer, nbytes_alloc);
8118                 }
8119               len = fread (buffer + nbytes_read, 1, 1024, infile);
8120               nbytes_read += len;
8121               if (len < 1024)
8122                 break;
8123             }
8124           
8125           gtk_text_insert (GTK_TEXT (text), NULL, NULL,
8126                            NULL, buffer, nbytes_read);
8127           g_free(buffer);
8128           fclose (infile);
8129         }
8130       
8131       gtk_text_thaw (GTK_TEXT (text));
8132
8133       hbox = gtk_hbutton_box_new ();
8134       gtk_box_pack_start (GTK_BOX (box2), hbox, FALSE, FALSE, 0);
8135       gtk_widget_show (hbox);
8136
8137       check = gtk_check_button_new_with_label("Editable");
8138       gtk_box_pack_start (GTK_BOX (hbox), check, FALSE, FALSE, 0);
8139       g_signal_connect (check, "toggled",
8140                         G_CALLBACK (text_toggle_editable), text);
8141       gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), TRUE);
8142       gtk_widget_show (check);
8143
8144       check = gtk_check_button_new_with_label("Wrap Words");
8145       gtk_box_pack_start (GTK_BOX (hbox), check, FALSE, TRUE, 0);
8146       g_signal_connect (check, "toggled",
8147                         G_CALLBACK (text_toggle_word_wrap), text);
8148       gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), FALSE);
8149       gtk_widget_show (check);
8150
8151       separator = gtk_hseparator_new ();
8152       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
8153       gtk_widget_show (separator);
8154
8155
8156       box2 = gtk_vbox_new (FALSE, 10);
8157       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
8158       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
8159       gtk_widget_show (box2);
8160
8161
8162       button = gtk_button_new_with_label ("insert random");
8163       g_signal_connect (button, "clicked",
8164                         G_CALLBACK (text_insert_random),
8165                         text);
8166       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
8167       gtk_widget_show (button);
8168
8169       button = gtk_button_new_with_label ("close");
8170       g_signal_connect_swapped (button, "clicked",
8171                                 G_CALLBACK (gtk_widget_destroy),
8172                                 window);
8173       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
8174       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
8175       gtk_widget_grab_default (button);
8176       gtk_widget_show (button);
8177     }
8178
8179   if (!GTK_WIDGET_VISIBLE (window))
8180     gtk_widget_show (window);
8181   else
8182     gtk_widget_destroy (window);
8183 }
8184
8185 /*
8186  * GtkNotebook
8187  */
8188
8189 GdkPixbuf *book_open;
8190 GdkPixbuf *book_closed;
8191 GtkWidget *sample_notebook;
8192
8193 static void
8194 set_page_image (GtkNotebook *notebook, gint page_num, GdkPixbuf *pixbuf)
8195 {
8196   GtkWidget *page_widget;
8197   GtkWidget *pixwid;
8198
8199   page_widget = gtk_notebook_get_nth_page (notebook, page_num);
8200
8201   pixwid = g_object_get_data (G_OBJECT (page_widget), "tab_pixmap");
8202   gtk_image_set_from_pixbuf (GTK_IMAGE (pixwid), pixbuf);
8203   
8204   pixwid = g_object_get_data (G_OBJECT (page_widget), "menu_pixmap");
8205   gtk_image_set_from_pixbuf (GTK_IMAGE (pixwid), pixbuf);
8206 }
8207
8208 static void
8209 page_switch (GtkWidget *widget, GtkNotebookPage *page, gint page_num)
8210 {
8211   GtkNotebook *notebook = GTK_NOTEBOOK (widget);
8212   gint old_page_num = gtk_notebook_get_current_page (notebook);
8213  
8214   if (page_num == old_page_num)
8215     return;
8216
8217   set_page_image (notebook, page_num, book_open);
8218
8219   if (old_page_num != -1)
8220     set_page_image (notebook, old_page_num, book_closed);
8221 }
8222
8223 static void
8224 tab_fill (GtkToggleButton *button, GtkWidget *child)
8225 {
8226   gboolean expand;
8227   GtkPackType pack_type;
8228
8229   gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (sample_notebook), child,
8230                                         &expand, NULL, &pack_type);
8231   gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (sample_notebook), child,
8232                                       expand, button->active, pack_type);
8233 }
8234
8235 static void
8236 tab_expand (GtkToggleButton *button, GtkWidget *child)
8237 {
8238   gboolean fill;
8239   GtkPackType pack_type;
8240
8241   gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (sample_notebook), child,
8242                                         NULL, &fill, &pack_type);
8243   gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (sample_notebook), child,
8244                                       button->active, fill, pack_type);
8245 }
8246
8247 static void
8248 tab_pack (GtkToggleButton *button, GtkWidget *child)
8249           
8250
8251   gboolean expand;
8252   gboolean fill;
8253
8254   gtk_notebook_query_tab_label_packing (GTK_NOTEBOOK (sample_notebook), child,
8255                                         &expand, &fill, NULL);
8256   gtk_notebook_set_tab_label_packing (GTK_NOTEBOOK (sample_notebook), child,
8257                                       expand, fill, button->active);
8258 }
8259
8260 static void
8261 create_pages (GtkNotebook *notebook, gint start, gint end)
8262 {
8263   GtkWidget *child = NULL;
8264   GtkWidget *button;
8265   GtkWidget *label;
8266   GtkWidget *hbox;
8267   GtkWidget *vbox;
8268   GtkWidget *label_box;
8269   GtkWidget *menu_box;
8270   GtkWidget *pixwid;
8271   gint i;
8272   char buffer[32];
8273   char accel_buffer[32];
8274
8275   for (i = start; i <= end; i++)
8276     {
8277       sprintf (buffer, "Page %d", i);
8278       sprintf (accel_buffer, "Page _%d", i);
8279
8280       child = gtk_frame_new (buffer);
8281       gtk_container_set_border_width (GTK_CONTAINER (child), 10);
8282
8283       vbox = gtk_vbox_new (TRUE,0);
8284       gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
8285       gtk_container_add (GTK_CONTAINER (child), vbox);
8286
8287       hbox = gtk_hbox_new (TRUE,0);
8288       gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 5);
8289
8290       button = gtk_check_button_new_with_label ("Fill Tab");
8291       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
8292       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
8293       g_signal_connect (button, "toggled",
8294                         G_CALLBACK (tab_fill), child);
8295
8296       button = gtk_check_button_new_with_label ("Expand Tab");
8297       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
8298       g_signal_connect (button, "toggled",
8299                         G_CALLBACK (tab_expand), child);
8300
8301       button = gtk_check_button_new_with_label ("Pack end");
8302       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 5);
8303       g_signal_connect (button, "toggled",
8304                         G_CALLBACK (tab_pack), child);
8305
8306       button = gtk_button_new_with_label ("Hide Page");
8307       gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 5);
8308       g_signal_connect_swapped (button, "clicked",
8309                                 G_CALLBACK (gtk_widget_hide),
8310                                 child);
8311
8312       gtk_widget_show_all (child);
8313
8314       label_box = gtk_hbox_new (FALSE, 0);
8315       pixwid = gtk_image_new_from_pixbuf (book_closed);
8316       g_object_set_data (G_OBJECT (child), "tab_pixmap", pixwid);
8317                            
8318       gtk_box_pack_start (GTK_BOX (label_box), pixwid, FALSE, TRUE, 0);
8319       gtk_misc_set_padding (GTK_MISC (pixwid), 3, 1);
8320       label = gtk_label_new_with_mnemonic (accel_buffer);
8321       gtk_box_pack_start (GTK_BOX (label_box), label, FALSE, TRUE, 0);
8322       gtk_widget_show_all (label_box);
8323       
8324                                        
8325       menu_box = gtk_hbox_new (FALSE, 0);
8326       pixwid = gtk_image_new_from_pixbuf (book_closed);
8327       g_object_set_data (G_OBJECT (child), "menu_pixmap", pixwid);
8328       
8329       gtk_box_pack_start (GTK_BOX (menu_box), pixwid, FALSE, TRUE, 0);
8330       gtk_misc_set_padding (GTK_MISC (pixwid), 3, 1);
8331       label = gtk_label_new (buffer);
8332       gtk_box_pack_start (GTK_BOX (menu_box), label, FALSE, TRUE, 0);
8333       gtk_widget_show_all (menu_box);
8334
8335       gtk_notebook_append_page_menu (notebook, child, label_box, menu_box);
8336     }
8337 }
8338
8339 static void
8340 rotate_notebook (GtkButton   *button,
8341                  GtkNotebook *notebook)
8342 {
8343   gtk_notebook_set_tab_pos (notebook, (notebook->tab_pos + 1) % 4);
8344 }
8345
8346 static void
8347 show_all_pages (GtkButton   *button,
8348                 GtkNotebook *notebook)
8349 {  
8350   gtk_container_foreach (GTK_CONTAINER (notebook),
8351                          (GtkCallback) gtk_widget_show, NULL);
8352 }
8353
8354 static void
8355 notebook_type_changed (GtkWidget *optionmenu,
8356                        gpointer   data)
8357 {
8358   GtkNotebook *notebook;
8359   gint i, c;
8360
8361   enum {
8362     STANDARD,
8363     NOTABS,
8364     BORDERLESS,
8365     SCROLLABLE
8366   };
8367
8368   notebook = GTK_NOTEBOOK (data);
8369
8370   c = gtk_option_menu_get_history (GTK_OPTION_MENU (optionmenu));
8371
8372   switch (c)
8373     {
8374     case STANDARD:
8375       /* standard notebook */
8376       gtk_notebook_set_show_tabs (notebook, TRUE);
8377       gtk_notebook_set_show_border (notebook, TRUE);
8378       gtk_notebook_set_scrollable (notebook, FALSE);
8379       break;
8380
8381     case NOTABS:
8382       /* notabs notebook */
8383       gtk_notebook_set_show_tabs (notebook, FALSE);
8384       gtk_notebook_set_show_border (notebook, TRUE);
8385       break;
8386
8387     case BORDERLESS:
8388       /* borderless */
8389       gtk_notebook_set_show_tabs (notebook, FALSE);
8390       gtk_notebook_set_show_border (notebook, FALSE);
8391       break;
8392
8393     case SCROLLABLE:  
8394       /* scrollable */
8395       gtk_notebook_set_show_tabs (notebook, TRUE);
8396       gtk_notebook_set_show_border (notebook, TRUE);
8397       gtk_notebook_set_scrollable (notebook, TRUE);
8398       if (g_list_length (notebook->children) == 5)
8399         create_pages (notebook, 6, 15);
8400       
8401       return;
8402       break;
8403     }
8404   
8405   if (g_list_length (notebook->children) == 15)
8406     for (i = 0; i < 10; i++)
8407       gtk_notebook_remove_page (notebook, 5);
8408 }
8409
8410 static void
8411 notebook_popup (GtkToggleButton *button,
8412                 GtkNotebook     *notebook)
8413 {
8414   if (button->active)
8415     gtk_notebook_popup_enable (notebook);
8416   else
8417     gtk_notebook_popup_disable (notebook);
8418 }
8419
8420 static void
8421 notebook_homogeneous (GtkToggleButton *button,
8422                       GtkNotebook     *notebook)
8423 {
8424   g_object_set (notebook, "homogeneous", button->active, NULL);
8425 }
8426
8427 static void
8428 create_notebook (GtkWidget *widget)
8429 {
8430   static GtkWidget *window = NULL;
8431   GtkWidget *box1;
8432   GtkWidget *box2;
8433   GtkWidget *button;
8434   GtkWidget *separator;
8435   GtkWidget *omenu;
8436   GtkWidget *label;
8437
8438   static gchar *items[] =
8439   {
8440     "Standard",
8441     "No tabs",
8442     "Borderless",
8443     "Scrollable"
8444   };
8445   
8446   if (!window)
8447     {
8448       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8449       gtk_window_set_screen (GTK_WINDOW (window),
8450                              gtk_widget_get_screen (widget));
8451
8452       g_signal_connect (window, "destroy",
8453                         G_CALLBACK (gtk_widget_destroyed),
8454                         &window);
8455
8456       gtk_window_set_title (GTK_WINDOW (window), "notebook");
8457       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
8458
8459       box1 = gtk_vbox_new (FALSE, 0);
8460       gtk_container_add (GTK_CONTAINER (window), box1);
8461
8462       sample_notebook = gtk_notebook_new ();
8463       g_signal_connect (sample_notebook, "switch_page",
8464                         G_CALLBACK (page_switch), NULL);
8465       gtk_notebook_set_tab_pos (GTK_NOTEBOOK (sample_notebook), GTK_POS_TOP);
8466       gtk_box_pack_start (GTK_BOX (box1), sample_notebook, TRUE, TRUE, 0);
8467       gtk_container_set_border_width (GTK_CONTAINER (sample_notebook), 10);
8468
8469       gtk_widget_realize (sample_notebook);
8470
8471       if (!book_open)
8472         book_open = gdk_pixbuf_new_from_xpm_data ((const char **)book_open_xpm);
8473                                                   
8474       if (!book_closed)
8475         book_closed = gdk_pixbuf_new_from_xpm_data ((const char **)book_closed_xpm);
8476
8477       create_pages (GTK_NOTEBOOK (sample_notebook), 1, 5);
8478
8479       separator = gtk_hseparator_new ();
8480       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 10);
8481       
8482       box2 = gtk_hbox_new (FALSE, 5);
8483       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
8484       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
8485
8486       button = gtk_check_button_new_with_label ("popup menu");
8487       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, FALSE, 0);
8488       g_signal_connect (button, "clicked",
8489                         G_CALLBACK (notebook_popup),
8490                         sample_notebook);
8491
8492       button = gtk_check_button_new_with_label ("homogeneous tabs");
8493       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, FALSE, 0);
8494       g_signal_connect (button, "clicked",
8495                         G_CALLBACK (notebook_homogeneous),
8496                         sample_notebook);
8497
8498       box2 = gtk_hbox_new (FALSE, 5);
8499       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
8500       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
8501
8502       label = gtk_label_new ("Notebook Style :");
8503       gtk_box_pack_start (GTK_BOX (box2), label, FALSE, TRUE, 0);
8504
8505       omenu = build_option_menu (items, G_N_ELEMENTS (items), 0,
8506                                  notebook_type_changed,
8507                                  sample_notebook);
8508       gtk_box_pack_start (GTK_BOX (box2), omenu, FALSE, TRUE, 0);
8509
8510       button = gtk_button_new_with_label ("Show all Pages");
8511       gtk_box_pack_start (GTK_BOX (box2), button, FALSE, TRUE, 0);
8512       g_signal_connect (button, "clicked",
8513                         G_CALLBACK (show_all_pages), sample_notebook);
8514
8515       box2 = gtk_hbox_new (TRUE, 10);
8516       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
8517       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
8518
8519       button = gtk_button_new_with_label ("prev");
8520       g_signal_connect_swapped (button, "clicked",
8521                                 G_CALLBACK (gtk_notebook_prev_page),
8522                                 sample_notebook);
8523       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
8524
8525       button = gtk_button_new_with_label ("next");
8526       g_signal_connect_swapped (button, "clicked",
8527                                 G_CALLBACK (gtk_notebook_next_page),
8528                                 sample_notebook);
8529       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
8530
8531       button = gtk_button_new_with_label ("rotate");
8532       g_signal_connect (button, "clicked",
8533                         G_CALLBACK (rotate_notebook), sample_notebook);
8534       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
8535
8536       separator = gtk_hseparator_new ();
8537       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 5);
8538
8539       button = gtk_button_new_with_label ("close");
8540       gtk_container_set_border_width (GTK_CONTAINER (button), 5);
8541       g_signal_connect_swapped (button, "clicked",
8542                                 G_CALLBACK (gtk_widget_destroy),
8543                                 window);
8544       gtk_box_pack_start (GTK_BOX (box1), button, FALSE, FALSE, 0);
8545       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
8546       gtk_widget_grab_default (button);
8547     }
8548
8549   if (!GTK_WIDGET_VISIBLE (window))
8550     gtk_widget_show_all (window);
8551   else
8552     gtk_widget_destroy (window);
8553 }
8554
8555 /*
8556  * GtkPanes
8557  */
8558
8559 void
8560 toggle_resize (GtkWidget *widget, GtkWidget *child)
8561 {
8562   GtkPaned *paned = GTK_PANED (child->parent);
8563   gboolean is_child1 = (child == paned->child1);
8564   gboolean resize, shrink;
8565
8566   resize = is_child1 ? paned->child1_resize : paned->child2_resize;
8567   shrink = is_child1 ? paned->child1_shrink : paned->child2_shrink;
8568
8569   gtk_widget_ref (child);
8570   gtk_container_remove (GTK_CONTAINER (child->parent), child);
8571   if (is_child1)
8572     gtk_paned_pack1 (paned, child, !resize, shrink);
8573   else
8574     gtk_paned_pack2 (paned, child, !resize, shrink);
8575   gtk_widget_unref (child);
8576 }
8577
8578 void
8579 toggle_shrink (GtkWidget *widget, GtkWidget *child)
8580 {
8581   GtkPaned *paned = GTK_PANED (child->parent);
8582   gboolean is_child1 = (child == paned->child1);
8583   gboolean resize, shrink;
8584
8585   resize = is_child1 ? paned->child1_resize : paned->child2_resize;
8586   shrink = is_child1 ? paned->child1_shrink : paned->child2_shrink;
8587
8588   gtk_widget_ref (child);
8589   gtk_container_remove (GTK_CONTAINER (child->parent), child);
8590   if (is_child1)
8591     gtk_paned_pack1 (paned, child, resize, !shrink);
8592   else
8593     gtk_paned_pack2 (paned, child, resize, !shrink);
8594   gtk_widget_unref (child);
8595 }
8596
8597 static void
8598 paned_props_clicked (GtkWidget *button,
8599                      GObject   *paned)
8600 {
8601   GtkWidget *window = create_prop_editor (paned, GTK_TYPE_PANED);
8602   
8603   gtk_window_set_title (GTK_WINDOW (window), "Paned Properties");
8604 }
8605
8606 GtkWidget *
8607 create_pane_options (GtkPaned    *paned,
8608                      const gchar *frame_label,
8609                      const gchar *label1,
8610                      const gchar *label2)
8611 {
8612   GtkWidget *frame;
8613   GtkWidget *table;
8614   GtkWidget *label;
8615   GtkWidget *button;
8616   GtkWidget *check_button;
8617   
8618   frame = gtk_frame_new (frame_label);
8619   gtk_container_set_border_width (GTK_CONTAINER (frame), 4);
8620   
8621   table = gtk_table_new (4, 2, 4);
8622   gtk_container_add (GTK_CONTAINER (frame), table);
8623   
8624   label = gtk_label_new (label1);
8625   gtk_table_attach_defaults (GTK_TABLE (table), label,
8626                              0, 1, 0, 1);
8627   
8628   check_button = gtk_check_button_new_with_label ("Resize");
8629   gtk_table_attach_defaults (GTK_TABLE (table), check_button,
8630                              0, 1, 1, 2);
8631   g_signal_connect (check_button, "toggled",
8632                     G_CALLBACK (toggle_resize),
8633                     paned->child1);
8634   
8635   check_button = gtk_check_button_new_with_label ("Shrink");
8636   gtk_table_attach_defaults (GTK_TABLE (table), check_button,
8637                              0, 1, 2, 3);
8638   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button),
8639                                TRUE);
8640   g_signal_connect (check_button, "toggled",
8641                     G_CALLBACK (toggle_shrink),
8642                     paned->child1);
8643   
8644   label = gtk_label_new (label2);
8645   gtk_table_attach_defaults (GTK_TABLE (table), label,
8646                              1, 2, 0, 1);
8647   
8648   check_button = gtk_check_button_new_with_label ("Resize");
8649   gtk_table_attach_defaults (GTK_TABLE (table), check_button,
8650                              1, 2, 1, 2);
8651   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button),
8652                                TRUE);
8653   g_signal_connect (check_button, "toggled",
8654                     G_CALLBACK (toggle_resize),
8655                     paned->child2);
8656   
8657   check_button = gtk_check_button_new_with_label ("Shrink");
8658   gtk_table_attach_defaults (GTK_TABLE (table), check_button,
8659                              1, 2, 2, 3);
8660   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check_button),
8661                                TRUE);
8662   g_signal_connect (check_button, "toggled",
8663                     G_CALLBACK (toggle_shrink),
8664                     paned->child2);
8665
8666   button = gtk_button_new_with_mnemonic ("_Properties");
8667   gtk_table_attach_defaults (GTK_TABLE (table), button,
8668                              0, 2, 3, 4);
8669   g_signal_connect (button, "clicked",
8670                     G_CALLBACK (paned_props_clicked),
8671                     paned);
8672
8673   return frame;
8674 }
8675
8676 void
8677 create_panes (GtkWidget *widget)
8678 {
8679   static GtkWidget *window = NULL;
8680   GtkWidget *frame;
8681   GtkWidget *hpaned;
8682   GtkWidget *vpaned;
8683   GtkWidget *button;
8684   GtkWidget *vbox;
8685
8686   if (!window)
8687     {
8688       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8689
8690       gtk_window_set_screen (GTK_WINDOW (window),
8691                              gtk_widget_get_screen (widget));
8692       
8693       g_signal_connect (window, "destroy",
8694                         G_CALLBACK (gtk_widget_destroyed),
8695                         &window);
8696
8697       gtk_window_set_title (GTK_WINDOW (window), "Panes");
8698       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
8699
8700       vbox = gtk_vbox_new (FALSE, 0);
8701       gtk_container_add (GTK_CONTAINER (window), vbox);
8702       
8703       vpaned = gtk_vpaned_new ();
8704       gtk_box_pack_start (GTK_BOX (vbox), vpaned, TRUE, TRUE, 0);
8705       gtk_container_set_border_width (GTK_CONTAINER(vpaned), 5);
8706
8707       hpaned = gtk_hpaned_new ();
8708       gtk_paned_add1 (GTK_PANED (vpaned), hpaned);
8709
8710       frame = gtk_frame_new (NULL);
8711       gtk_frame_set_shadow_type (GTK_FRAME(frame), GTK_SHADOW_IN);
8712       gtk_widget_set_size_request (frame, 60, 60);
8713       gtk_paned_add1 (GTK_PANED (hpaned), frame);
8714       
8715       button = gtk_button_new_with_label ("Hi there");
8716       gtk_container_add (GTK_CONTAINER(frame), button);
8717
8718       frame = gtk_frame_new (NULL);
8719       gtk_frame_set_shadow_type (GTK_FRAME(frame), GTK_SHADOW_IN);
8720       gtk_widget_set_size_request (frame, 80, 60);
8721       gtk_paned_add2 (GTK_PANED (hpaned), frame);
8722
8723       frame = gtk_frame_new (NULL);
8724       gtk_frame_set_shadow_type (GTK_FRAME(frame), GTK_SHADOW_IN);
8725       gtk_widget_set_size_request (frame, 60, 80);
8726       gtk_paned_add2 (GTK_PANED (vpaned), frame);
8727
8728       /* Now create toggle buttons to control sizing */
8729
8730       gtk_box_pack_start (GTK_BOX (vbox),
8731                           create_pane_options (GTK_PANED (hpaned),
8732                                                "Horizontal",
8733                                                "Left",
8734                                                "Right"),
8735                           FALSE, FALSE, 0);
8736
8737       gtk_box_pack_start (GTK_BOX (vbox),
8738                           create_pane_options (GTK_PANED (vpaned),
8739                                                "Vertical",
8740                                                "Top",
8741                                                "Bottom"),
8742                           FALSE, FALSE, 0);
8743
8744       gtk_widget_show_all (vbox);
8745     }
8746
8747   if (!GTK_WIDGET_VISIBLE (window))
8748     gtk_widget_show (window);
8749   else
8750     gtk_widget_destroy (window);
8751 }
8752
8753 /*
8754  * Paned keyboard navigation
8755  */
8756
8757 static GtkWidget*
8758 paned_keyboard_window1 (GtkWidget *widget)
8759 {
8760   GtkWidget *window1;
8761   GtkWidget *hpaned1;
8762   GtkWidget *frame1;
8763   GtkWidget *vbox1;
8764   GtkWidget *button7;
8765   GtkWidget *button8;
8766   GtkWidget *button9;
8767   GtkWidget *vpaned1;
8768   GtkWidget *frame2;
8769   GtkWidget *frame5;
8770   GtkWidget *hbox1;
8771   GtkWidget *button5;
8772   GtkWidget *button6;
8773   GtkWidget *frame3;
8774   GtkWidget *frame4;
8775   GtkWidget *table1;
8776   GtkWidget *button1;
8777   GtkWidget *button2;
8778   GtkWidget *button3;
8779   GtkWidget *button4;
8780
8781   window1 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8782   gtk_window_set_title (GTK_WINDOW (window1), "Basic paned navigation");
8783   gtk_window_set_screen (GTK_WINDOW (window1), 
8784                          gtk_widget_get_screen (widget));
8785
8786   hpaned1 = gtk_hpaned_new ();
8787   gtk_container_add (GTK_CONTAINER (window1), hpaned1);
8788
8789   frame1 = gtk_frame_new (NULL);
8790   gtk_paned_pack1 (GTK_PANED (hpaned1), frame1, FALSE, TRUE);
8791   gtk_frame_set_shadow_type (GTK_FRAME (frame1), GTK_SHADOW_IN);
8792
8793   vbox1 = gtk_vbox_new (FALSE, 0);
8794   gtk_container_add (GTK_CONTAINER (frame1), vbox1);
8795
8796   button7 = gtk_button_new_with_label ("button7");
8797   gtk_box_pack_start (GTK_BOX (vbox1), button7, FALSE, FALSE, 0);
8798
8799   button8 = gtk_button_new_with_label ("button8");
8800   gtk_box_pack_start (GTK_BOX (vbox1), button8, FALSE, FALSE, 0);
8801
8802   button9 = gtk_button_new_with_label ("button9");
8803   gtk_box_pack_start (GTK_BOX (vbox1), button9, FALSE, FALSE, 0);
8804
8805   vpaned1 = gtk_vpaned_new ();
8806   gtk_paned_pack2 (GTK_PANED (hpaned1), vpaned1, TRUE, TRUE);
8807
8808   frame2 = gtk_frame_new (NULL);
8809   gtk_paned_pack1 (GTK_PANED (vpaned1), frame2, FALSE, TRUE);
8810   gtk_frame_set_shadow_type (GTK_FRAME (frame2), GTK_SHADOW_IN);
8811
8812   frame5 = gtk_frame_new (NULL);
8813   gtk_container_add (GTK_CONTAINER (frame2), frame5);
8814
8815   hbox1 = gtk_hbox_new (FALSE, 0);
8816   gtk_container_add (GTK_CONTAINER (frame5), hbox1);
8817
8818   button5 = gtk_button_new_with_label ("button5");
8819   gtk_box_pack_start (GTK_BOX (hbox1), button5, FALSE, FALSE, 0);
8820
8821   button6 = gtk_button_new_with_label ("button6");
8822   gtk_box_pack_start (GTK_BOX (hbox1), button6, FALSE, FALSE, 0);
8823
8824   frame3 = gtk_frame_new (NULL);
8825   gtk_paned_pack2 (GTK_PANED (vpaned1), frame3, TRUE, TRUE);
8826   gtk_frame_set_shadow_type (GTK_FRAME (frame3), GTK_SHADOW_IN);
8827
8828   frame4 = gtk_frame_new ("Buttons");
8829   gtk_container_add (GTK_CONTAINER (frame3), frame4);
8830   gtk_container_set_border_width (GTK_CONTAINER (frame4), 15);
8831
8832   table1 = gtk_table_new (2, 2, FALSE);
8833   gtk_container_add (GTK_CONTAINER (frame4), table1);
8834   gtk_container_set_border_width (GTK_CONTAINER (table1), 11);
8835
8836   button1 = gtk_button_new_with_label ("button1");
8837   gtk_table_attach (GTK_TABLE (table1), button1, 0, 1, 0, 1,
8838                     (GtkAttachOptions) (GTK_FILL),
8839                     (GtkAttachOptions) (0), 0, 0);
8840
8841   button2 = gtk_button_new_with_label ("button2");
8842   gtk_table_attach (GTK_TABLE (table1), button2, 1, 2, 0, 1,
8843                     (GtkAttachOptions) (GTK_FILL),
8844                     (GtkAttachOptions) (0), 0, 0);
8845
8846   button3 = gtk_button_new_with_label ("button3");
8847   gtk_table_attach (GTK_TABLE (table1), button3, 0, 1, 1, 2,
8848                     (GtkAttachOptions) (GTK_FILL),
8849                     (GtkAttachOptions) (0), 0, 0);
8850
8851   button4 = gtk_button_new_with_label ("button4");
8852   gtk_table_attach (GTK_TABLE (table1), button4, 1, 2, 1, 2,
8853                     (GtkAttachOptions) (GTK_FILL),
8854                     (GtkAttachOptions) (0), 0, 0);
8855
8856   return window1;
8857 }
8858
8859 static GtkWidget*
8860 paned_keyboard_window2 (GtkWidget *widget)
8861 {
8862   GtkWidget *window2;
8863   GtkWidget *hpaned2;
8864   GtkWidget *frame6;
8865   GtkWidget *button13;
8866   GtkWidget *hbox2;
8867   GtkWidget *vpaned2;
8868   GtkWidget *frame7;
8869   GtkWidget *button12;
8870   GtkWidget *frame8;
8871   GtkWidget *button11;
8872   GtkWidget *button10;
8873
8874   window2 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8875   gtk_window_set_title (GTK_WINDOW (window2), "\"button 10\" is not inside the horisontal pane");
8876
8877   gtk_window_set_screen (GTK_WINDOW (window2), 
8878                          gtk_widget_get_screen (widget));
8879
8880   hpaned2 = gtk_hpaned_new ();
8881   gtk_container_add (GTK_CONTAINER (window2), hpaned2);
8882
8883   frame6 = gtk_frame_new (NULL);
8884   gtk_paned_pack1 (GTK_PANED (hpaned2), frame6, FALSE, TRUE);
8885   gtk_frame_set_shadow_type (GTK_FRAME (frame6), GTK_SHADOW_IN);
8886
8887   button13 = gtk_button_new_with_label ("button13");
8888   gtk_container_add (GTK_CONTAINER (frame6), button13);
8889
8890   hbox2 = gtk_hbox_new (FALSE, 0);
8891   gtk_paned_pack2 (GTK_PANED (hpaned2), hbox2, TRUE, TRUE);
8892
8893   vpaned2 = gtk_vpaned_new ();
8894   gtk_box_pack_start (GTK_BOX (hbox2), vpaned2, TRUE, TRUE, 0);
8895
8896   frame7 = gtk_frame_new (NULL);
8897   gtk_paned_pack1 (GTK_PANED (vpaned2), frame7, FALSE, TRUE);
8898   gtk_frame_set_shadow_type (GTK_FRAME (frame7), GTK_SHADOW_IN);
8899
8900   button12 = gtk_button_new_with_label ("button12");
8901   gtk_container_add (GTK_CONTAINER (frame7), button12);
8902
8903   frame8 = gtk_frame_new (NULL);
8904   gtk_paned_pack2 (GTK_PANED (vpaned2), frame8, TRUE, TRUE);
8905   gtk_frame_set_shadow_type (GTK_FRAME (frame8), GTK_SHADOW_IN);
8906
8907   button11 = gtk_button_new_with_label ("button11");
8908   gtk_container_add (GTK_CONTAINER (frame8), button11);
8909
8910   button10 = gtk_button_new_with_label ("button10");
8911   gtk_box_pack_start (GTK_BOX (hbox2), button10, FALSE, FALSE, 0);
8912
8913   return window2;
8914 }
8915
8916 static GtkWidget*
8917 paned_keyboard_window3 (GtkWidget *widget)
8918 {
8919   GtkWidget *window3;
8920   GtkWidget *vbox2;
8921   GtkWidget *label1;
8922   GtkWidget *hpaned3;
8923   GtkWidget *frame9;
8924   GtkWidget *button14;
8925   GtkWidget *hpaned4;
8926   GtkWidget *frame10;
8927   GtkWidget *button15;
8928   GtkWidget *hpaned5;
8929   GtkWidget *frame11;
8930   GtkWidget *button16;
8931   GtkWidget *frame12;
8932   GtkWidget *button17;
8933
8934   window3 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
8935   g_object_set_data (G_OBJECT (window3), "window3", window3);
8936   gtk_window_set_title (GTK_WINDOW (window3), "Nested panes");
8937
8938   gtk_window_set_screen (GTK_WINDOW (window3), 
8939                          gtk_widget_get_screen (widget));
8940   
8941
8942   vbox2 = gtk_vbox_new (FALSE, 0);
8943   gtk_container_add (GTK_CONTAINER (window3), vbox2);
8944
8945   label1 = gtk_label_new ("Three panes nested inside each other");
8946   gtk_box_pack_start (GTK_BOX (vbox2), label1, FALSE, FALSE, 0);
8947
8948   hpaned3 = gtk_hpaned_new ();
8949   gtk_box_pack_start (GTK_BOX (vbox2), hpaned3, TRUE, TRUE, 0);
8950
8951   frame9 = gtk_frame_new (NULL);
8952   gtk_paned_pack1 (GTK_PANED (hpaned3), frame9, FALSE, TRUE);
8953   gtk_frame_set_shadow_type (GTK_FRAME (frame9), GTK_SHADOW_IN);
8954
8955   button14 = gtk_button_new_with_label ("button14");
8956   gtk_container_add (GTK_CONTAINER (frame9), button14);
8957
8958   hpaned4 = gtk_hpaned_new ();
8959   gtk_paned_pack2 (GTK_PANED (hpaned3), hpaned4, TRUE, TRUE);
8960
8961   frame10 = gtk_frame_new (NULL);
8962   gtk_paned_pack1 (GTK_PANED (hpaned4), frame10, FALSE, TRUE);
8963   gtk_frame_set_shadow_type (GTK_FRAME (frame10), GTK_SHADOW_IN);
8964
8965   button15 = gtk_button_new_with_label ("button15");
8966   gtk_container_add (GTK_CONTAINER (frame10), button15);
8967
8968   hpaned5 = gtk_hpaned_new ();
8969   gtk_paned_pack2 (GTK_PANED (hpaned4), hpaned5, TRUE, TRUE);
8970
8971   frame11 = gtk_frame_new (NULL);
8972   gtk_paned_pack1 (GTK_PANED (hpaned5), frame11, FALSE, TRUE);
8973   gtk_frame_set_shadow_type (GTK_FRAME (frame11), GTK_SHADOW_IN);
8974
8975   button16 = gtk_button_new_with_label ("button16");
8976   gtk_container_add (GTK_CONTAINER (frame11), button16);
8977
8978   frame12 = gtk_frame_new (NULL);
8979   gtk_paned_pack2 (GTK_PANED (hpaned5), frame12, TRUE, TRUE);
8980   gtk_frame_set_shadow_type (GTK_FRAME (frame12), GTK_SHADOW_IN);
8981
8982   button17 = gtk_button_new_with_label ("button17");
8983   gtk_container_add (GTK_CONTAINER (frame12), button17);
8984
8985   return window3;
8986 }
8987
8988 static GtkWidget*
8989 paned_keyboard_window4 (GtkWidget *widget)
8990 {
8991   GtkWidget *window4;
8992   GtkWidget *vbox3;
8993   GtkWidget *label2;
8994   GtkWidget *hpaned6;
8995   GtkWidget *vpaned3;
8996   GtkWidget *button19;
8997   GtkWidget *button18;
8998   GtkWidget *hbox3;
8999   GtkWidget *vpaned4;
9000   GtkWidget *button21;
9001   GtkWidget *button20;
9002   GtkWidget *vpaned5;
9003   GtkWidget *button23;
9004   GtkWidget *button22;
9005   GtkWidget *vpaned6;
9006   GtkWidget *button25;
9007   GtkWidget *button24;
9008
9009   window4 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9010   g_object_set_data (G_OBJECT (window4), "window4", window4);
9011   gtk_window_set_title (GTK_WINDOW (window4), "window4");
9012
9013   gtk_window_set_screen (GTK_WINDOW (window4), 
9014                          gtk_widget_get_screen (widget));
9015
9016   vbox3 = gtk_vbox_new (FALSE, 0);
9017   gtk_container_add (GTK_CONTAINER (window4), vbox3);
9018
9019   label2 = gtk_label_new ("Widget tree:\n\nhpaned \n - vpaned\n - hbox\n    - vpaned\n    - vpaned\n    - vpaned\n");
9020   gtk_box_pack_start (GTK_BOX (vbox3), label2, FALSE, FALSE, 0);
9021   gtk_label_set_justify (GTK_LABEL (label2), GTK_JUSTIFY_LEFT);
9022
9023   hpaned6 = gtk_hpaned_new ();
9024   gtk_box_pack_start (GTK_BOX (vbox3), hpaned6, TRUE, TRUE, 0);
9025
9026   vpaned3 = gtk_vpaned_new ();
9027   gtk_paned_pack1 (GTK_PANED (hpaned6), vpaned3, FALSE, TRUE);
9028
9029   button19 = gtk_button_new_with_label ("button19");
9030   gtk_paned_pack1 (GTK_PANED (vpaned3), button19, FALSE, TRUE);
9031
9032   button18 = gtk_button_new_with_label ("button18");
9033   gtk_paned_pack2 (GTK_PANED (vpaned3), button18, TRUE, TRUE);
9034
9035   hbox3 = gtk_hbox_new (FALSE, 0);
9036   gtk_paned_pack2 (GTK_PANED (hpaned6), hbox3, TRUE, TRUE);
9037
9038   vpaned4 = gtk_vpaned_new ();
9039   gtk_box_pack_start (GTK_BOX (hbox3), vpaned4, TRUE, TRUE, 0);
9040
9041   button21 = gtk_button_new_with_label ("button21");
9042   gtk_paned_pack1 (GTK_PANED (vpaned4), button21, FALSE, TRUE);
9043
9044   button20 = gtk_button_new_with_label ("button20");
9045   gtk_paned_pack2 (GTK_PANED (vpaned4), button20, TRUE, TRUE);
9046
9047   vpaned5 = gtk_vpaned_new ();
9048   gtk_box_pack_start (GTK_BOX (hbox3), vpaned5, TRUE, TRUE, 0);
9049
9050   button23 = gtk_button_new_with_label ("button23");
9051   gtk_paned_pack1 (GTK_PANED (vpaned5), button23, FALSE, TRUE);
9052
9053   button22 = gtk_button_new_with_label ("button22");
9054   gtk_paned_pack2 (GTK_PANED (vpaned5), button22, TRUE, TRUE);
9055
9056   vpaned6 = gtk_vpaned_new ();
9057   gtk_box_pack_start (GTK_BOX (hbox3), vpaned6, TRUE, TRUE, 0);
9058
9059   button25 = gtk_button_new_with_label ("button25");
9060   gtk_paned_pack1 (GTK_PANED (vpaned6), button25, FALSE, TRUE);
9061
9062   button24 = gtk_button_new_with_label ("button24");
9063   gtk_paned_pack2 (GTK_PANED (vpaned6), button24, TRUE, TRUE);
9064
9065   return window4;
9066 }
9067
9068 static void
9069 create_paned_keyboard_navigation (GtkWidget *widget)
9070 {
9071   static GtkWidget *window1 = NULL;
9072   static GtkWidget *window2 = NULL;
9073   static GtkWidget *window3 = NULL;
9074   static GtkWidget *window4 = NULL;
9075
9076   if (window1 && 
9077      (gtk_widget_get_screen (window1) != gtk_widget_get_screen (widget)))
9078     {
9079       gtk_widget_destroy (window1);
9080       gtk_widget_destroy (window2);
9081       gtk_widget_destroy (window3);
9082       gtk_widget_destroy (window4);
9083     }
9084   
9085   if (!window1)
9086     {
9087       window1 = paned_keyboard_window1 (widget);
9088       g_signal_connect (window1, "destroy",
9089                         G_CALLBACK (gtk_widget_destroyed),
9090                         &window1);
9091     }
9092
9093   if (!window2)
9094     {
9095       window2 = paned_keyboard_window2 (widget);
9096       g_signal_connect (window2, "destroy",
9097                         G_CALLBACK (gtk_widget_destroyed),
9098                         &window2);
9099     }
9100
9101   if (!window3)
9102     {
9103       window3 = paned_keyboard_window3 (widget);
9104       g_signal_connect (window3, "destroy",
9105                         G_CALLBACK (gtk_widget_destroyed),
9106                         &window3);
9107     }
9108
9109   if (!window4)
9110     {
9111       window4 = paned_keyboard_window4 (widget);
9112       g_signal_connect (window4, "destroy",
9113                         G_CALLBACK (gtk_widget_destroyed),
9114                         &window4);
9115     }
9116
9117   if (GTK_WIDGET_VISIBLE (window1))
9118     gtk_widget_destroy (GTK_WIDGET (window1));
9119   else
9120     gtk_widget_show_all (GTK_WIDGET (window1));
9121
9122   if (GTK_WIDGET_VISIBLE (window2))
9123     gtk_widget_destroy (GTK_WIDGET (window2));
9124   else
9125     gtk_widget_show_all (GTK_WIDGET (window2));
9126
9127   if (GTK_WIDGET_VISIBLE (window3))
9128     gtk_widget_destroy (GTK_WIDGET (window3));
9129   else
9130     gtk_widget_show_all (GTK_WIDGET (window3));
9131
9132   if (GTK_WIDGET_VISIBLE (window4))
9133     gtk_widget_destroy (GTK_WIDGET (window4));
9134   else
9135     gtk_widget_show_all (GTK_WIDGET (window4));
9136 }
9137
9138
9139 /*
9140  * Shaped Windows
9141  */
9142
9143 typedef struct _cursoroffset {gint x,y;} CursorOffset;
9144
9145 static void
9146 shape_pressed (GtkWidget *widget, GdkEventButton *event)
9147 {
9148   CursorOffset *p;
9149
9150   /* ignore double and triple click */
9151   if (event->type != GDK_BUTTON_PRESS)
9152     return;
9153
9154   p = g_object_get_data (G_OBJECT (widget), "cursor_offset");
9155   p->x = (int) event->x;
9156   p->y = (int) event->y;
9157
9158   gtk_grab_add (widget);
9159   gdk_pointer_grab (widget->window, TRUE,
9160                     GDK_BUTTON_RELEASE_MASK |
9161                     GDK_BUTTON_MOTION_MASK |
9162                     GDK_POINTER_MOTION_HINT_MASK,
9163                     NULL, NULL, 0);
9164 }
9165
9166 static void
9167 shape_released (GtkWidget *widget)
9168 {
9169   gtk_grab_remove (widget);
9170   gdk_display_pointer_ungrab (gtk_widget_get_display (widget),
9171                               GDK_CURRENT_TIME);
9172 }
9173
9174 static void
9175 shape_motion (GtkWidget      *widget, 
9176               GdkEventMotion *event)
9177 {
9178   gint xp, yp;
9179   CursorOffset * p;
9180   GdkModifierType mask;
9181
9182   p = g_object_get_data (G_OBJECT (widget), "cursor_offset");
9183
9184   /*
9185    * Can't use event->x / event->y here 
9186    * because I need absolute coordinates.
9187    */
9188   gdk_window_get_pointer (NULL, &xp, &yp, &mask);
9189   gtk_widget_set_uposition (widget, xp  - p->x, yp  - p->y);
9190 }
9191
9192 GtkWidget *
9193 shape_create_icon (GdkScreen *screen,
9194                    char      *xpm_file,
9195                    gint       x,
9196                    gint       y,
9197                    gint       px,
9198                    gint       py,
9199                    gint       window_type)
9200 {
9201   GtkWidget *window;
9202   GtkWidget *pixmap;
9203   GtkWidget *fixed;
9204   CursorOffset* icon_pos;
9205   GdkGC* gc;
9206   GdkBitmap *gdk_pixmap_mask;
9207   GdkPixmap *gdk_pixmap;
9208   GtkStyle *style;
9209
9210   style = gtk_widget_get_default_style ();
9211   gc = style->black_gc; 
9212
9213   /*
9214    * GDK_WINDOW_TOPLEVEL works also, giving you a title border
9215    */
9216   window = gtk_window_new (window_type);
9217   gtk_window_set_screen (GTK_WINDOW (window), screen);
9218   
9219   fixed = gtk_fixed_new ();
9220   gtk_widget_set_size_request (fixed, 100, 100);
9221   gtk_container_add (GTK_CONTAINER (window), fixed);
9222   gtk_widget_show (fixed);
9223   
9224   gtk_widget_set_events (window, 
9225                          gtk_widget_get_events (window) |
9226                          GDK_BUTTON_MOTION_MASK |
9227                          GDK_POINTER_MOTION_HINT_MASK |
9228                          GDK_BUTTON_PRESS_MASK);
9229
9230   gtk_widget_realize (window);
9231   gdk_pixmap = gdk_pixmap_create_from_xpm (window->window, &gdk_pixmap_mask, 
9232                                            &style->bg[GTK_STATE_NORMAL],
9233                                            xpm_file);
9234
9235   pixmap = gtk_image_new_from_pixmap (gdk_pixmap, gdk_pixmap_mask);
9236   gtk_fixed_put (GTK_FIXED (fixed), pixmap, px,py);
9237   gtk_widget_show (pixmap);
9238   
9239   gtk_widget_shape_combine_mask (window, gdk_pixmap_mask, px, py);
9240   
9241   g_object_unref (gdk_pixmap_mask);
9242   g_object_unref (gdk_pixmap);
9243
9244   g_signal_connect (window, "button_press_event",
9245                     G_CALLBACK (shape_pressed), NULL);
9246   g_signal_connect (window, "button_release_event",
9247                     G_CALLBACK (shape_released), NULL);
9248   g_signal_connect (window, "motion_notify_event",
9249                     G_CALLBACK (shape_motion), NULL);
9250
9251   icon_pos = g_new (CursorOffset, 1);
9252   g_object_set_data (G_OBJECT (window), "cursor_offset", icon_pos);
9253
9254   gtk_widget_set_uposition (window, x, y);
9255   gtk_widget_show (window);
9256   
9257   return window;
9258 }
9259
9260 void 
9261 create_shapes (GtkWidget *widget)
9262 {
9263   /* Variables used by the Drag/Drop and Shape Window demos */
9264   static GtkWidget *modeller = NULL;
9265   static GtkWidget *sheets = NULL;
9266   static GtkWidget *rings = NULL;
9267   static GtkWidget *with_region = NULL;
9268   GdkScreen *screen = gtk_widget_get_screen (widget);
9269   
9270   if (!(file_exists ("Modeller.xpm") &&
9271         file_exists ("FilesQueue.xpm") &&
9272         file_exists ("3DRings.xpm")))
9273     return;
9274   
9275
9276   if (!modeller)
9277     {
9278       modeller = shape_create_icon (screen, "Modeller.xpm",
9279                                     440, 140, 0,0, GTK_WINDOW_POPUP);
9280
9281       g_signal_connect (modeller, "destroy",
9282                         G_CALLBACK (gtk_widget_destroyed),
9283                         &modeller);
9284     }
9285   else
9286     gtk_widget_destroy (modeller);
9287
9288   if (!sheets)
9289     {
9290       sheets = shape_create_icon (screen, "FilesQueue.xpm",
9291                                   580, 170, 0,0, GTK_WINDOW_POPUP);
9292
9293       g_signal_connect (sheets, "destroy",
9294                         G_CALLBACK (gtk_widget_destroyed),
9295                         &sheets);
9296
9297     }
9298   else
9299     gtk_widget_destroy (sheets);
9300
9301   if (!rings)
9302     {
9303       rings = shape_create_icon (screen, "3DRings.xpm",
9304                                  460, 270, 25,25, GTK_WINDOW_TOPLEVEL);
9305
9306       g_signal_connect (rings, "destroy",
9307                         G_CALLBACK (gtk_widget_destroyed),
9308                         &rings);
9309     }
9310   else
9311     gtk_widget_destroy (rings);
9312
9313   if (!with_region)
9314     {
9315       GdkRegion *region;
9316       gint x, y;
9317       
9318       with_region = shape_create_icon (screen, "3DRings.xpm",
9319                                        460, 270, 25,25, GTK_WINDOW_TOPLEVEL);
9320
9321       gtk_window_set_decorated (GTK_WINDOW (with_region), FALSE);
9322       
9323       g_signal_connect (with_region, "destroy",
9324                         G_CALLBACK (gtk_widget_destroyed),
9325                         &with_region);
9326
9327       /* reset shape from mask to a region */
9328       x = 0;
9329       y = 0;
9330       region = gdk_region_new ();
9331
9332       while (x < 460)
9333         {
9334           while (y < 270)
9335             {
9336               GdkRectangle rect;
9337               rect.x = x;
9338               rect.y = y;
9339               rect.width = 10;
9340               rect.height = 10;
9341
9342               gdk_region_union_with_rect (region, &rect);
9343               
9344               y += 20;
9345             }
9346           y = 0;
9347           x += 20;
9348         }
9349
9350       gdk_window_shape_combine_region (with_region->window,
9351                                        region,
9352                                        0, 0);
9353     }
9354   else
9355     gtk_widget_destroy (with_region);
9356 }
9357
9358 /*
9359  * WM Hints demo
9360  */
9361
9362 void
9363 create_wmhints (GtkWidget *widget)
9364 {
9365   static GtkWidget *window = NULL;
9366   GtkWidget *label;
9367   GtkWidget *separator;
9368   GtkWidget *button;
9369   GtkWidget *box1;
9370   GtkWidget *box2;
9371
9372   GdkBitmap *circles;
9373
9374   if (!window)
9375     {
9376       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9377
9378       gtk_window_set_screen (GTK_WINDOW (window),
9379                              gtk_widget_get_screen (widget));
9380       
9381       g_signal_connect (window, "destroy",
9382                         G_CALLBACK (gtk_widget_destroyed),
9383                         &window);
9384
9385       gtk_window_set_title (GTK_WINDOW (window), "WM Hints");
9386       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
9387
9388       gtk_widget_realize (window);
9389       
9390       circles = gdk_bitmap_create_from_data (window->window,
9391                                              circles_bits,
9392                                              circles_width,
9393                                              circles_height);
9394       gdk_window_set_icon (window->window, NULL,
9395                            circles, circles);
9396       
9397       gdk_window_set_icon_name (window->window, "WMHints Test Icon");
9398   
9399       gdk_window_set_decorations (window->window, GDK_DECOR_ALL | GDK_DECOR_MENU);
9400       gdk_window_set_functions (window->window, GDK_FUNC_ALL | GDK_FUNC_RESIZE);
9401       
9402       box1 = gtk_vbox_new (FALSE, 0);
9403       gtk_container_add (GTK_CONTAINER (window), box1);
9404       gtk_widget_show (box1);
9405
9406       label = gtk_label_new ("Try iconizing me!");
9407       gtk_widget_set_size_request (label, 150, 50);
9408       gtk_box_pack_start (GTK_BOX (box1), label, TRUE, TRUE, 0);
9409       gtk_widget_show (label);
9410
9411
9412       separator = gtk_hseparator_new ();
9413       gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
9414       gtk_widget_show (separator);
9415
9416
9417       box2 = gtk_vbox_new (FALSE, 10);
9418       gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
9419       gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
9420       gtk_widget_show (box2);
9421
9422
9423       button = gtk_button_new_with_label ("close");
9424
9425       g_signal_connect_swapped (button, "clicked",
9426                                 G_CALLBACK (gtk_widget_destroy),
9427                                 window);
9428
9429       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
9430       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
9431       gtk_widget_grab_default (button);
9432       gtk_widget_show (button);
9433     }
9434
9435   if (!GTK_WIDGET_VISIBLE (window))
9436     gtk_widget_show (window);
9437   else
9438     gtk_widget_destroy (window);
9439 }
9440
9441
9442 /*
9443  * Window state tracking
9444  */
9445
9446 static gint
9447 window_state_callback (GtkWidget *widget,
9448                        GdkEventWindowState *event,
9449                        gpointer data)
9450 {
9451   GtkWidget *label = data;
9452   gchar *msg;
9453
9454   msg = g_strconcat (GTK_WINDOW (widget)->title, ": ",
9455                      (event->new_window_state & GDK_WINDOW_STATE_WITHDRAWN) ?
9456                      "withdrawn" : "not withdrawn", ", ",
9457                      (event->new_window_state & GDK_WINDOW_STATE_ICONIFIED) ?
9458                      "iconified" : "not iconified", ", ",
9459                      (event->new_window_state & GDK_WINDOW_STATE_STICKY) ?
9460                      "sticky" : "not sticky", ", ",
9461                      (event->new_window_state & GDK_WINDOW_STATE_MAXIMIZED) ?
9462                      "maximized" : "not maximized", ", ",
9463                      (event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN) ?
9464                      "fullscreen" : "not fullscreen",
9465                      NULL);
9466   
9467   gtk_label_set_text (GTK_LABEL (label), msg);
9468
9469   g_free (msg);
9470
9471   return FALSE;
9472 }
9473
9474 static GtkWidget*
9475 tracking_label (GtkWidget *window)
9476 {
9477   GtkWidget *label;
9478   GtkWidget *hbox;
9479   GtkWidget *button;
9480
9481   hbox = gtk_hbox_new (FALSE, 5);
9482
9483   g_signal_connect_object (hbox,
9484                            "destroy",
9485                            G_CALLBACK (gtk_widget_destroy),
9486                            window,
9487                            G_CONNECT_SWAPPED);
9488   
9489   label = gtk_label_new ("<no window state events received>");
9490   gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
9491   gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
9492   
9493   g_signal_connect (window,
9494                     "window_state_event",
9495                     G_CALLBACK (window_state_callback),
9496                     label);
9497
9498   button = gtk_button_new_with_label ("Deiconify");
9499   g_signal_connect_object (button,
9500                            "clicked",
9501                            G_CALLBACK (gtk_window_deiconify),
9502                            window,
9503                            G_CONNECT_SWAPPED);
9504   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
9505
9506   button = gtk_button_new_with_label ("Iconify");
9507   g_signal_connect_object (button,
9508                            "clicked",
9509                            G_CALLBACK (gtk_window_iconify),
9510                            window,
9511                            G_CONNECT_SWAPPED);
9512   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
9513
9514   button = gtk_button_new_with_label ("Fullscreen");
9515   g_signal_connect_object (button,
9516                            "clicked",
9517                            G_CALLBACK (gtk_window_fullscreen),
9518                            window,
9519                            G_CONNECT_SWAPPED);
9520   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
9521
9522   button = gtk_button_new_with_label ("Unfullscreen");
9523   g_signal_connect_object (button,
9524                            "clicked",
9525                            G_CALLBACK (gtk_window_unfullscreen),
9526                            window,
9527                            G_CONNECT_SWAPPED);
9528   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
9529   
9530   button = gtk_button_new_with_label ("Present");
9531   g_signal_connect_object (button,
9532                            "clicked",
9533                            G_CALLBACK (gtk_window_present),
9534                            window,
9535                            G_CONNECT_SWAPPED);
9536   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
9537
9538   button = gtk_button_new_with_label ("Show");
9539   g_signal_connect_object (button,
9540                            "clicked",
9541                            G_CALLBACK (gtk_widget_show),
9542                            window,
9543                            G_CONNECT_SWAPPED);
9544   gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0);
9545   
9546   gtk_widget_show_all (hbox);
9547   
9548   return hbox;
9549 }
9550
9551 static GtkWidget*
9552 get_state_controls (GtkWidget *window)
9553 {
9554   GtkWidget *vbox;
9555   GtkWidget *button;
9556
9557   vbox = gtk_vbox_new (FALSE, 0);
9558   
9559   button = gtk_button_new_with_label ("Stick");
9560   g_signal_connect_object (button,
9561                            "clicked",
9562                            G_CALLBACK (gtk_window_stick),
9563                            window,
9564                            G_CONNECT_SWAPPED);
9565   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
9566
9567   button = gtk_button_new_with_label ("Unstick");
9568   g_signal_connect_object (button,
9569                            "clicked",
9570                            G_CALLBACK (gtk_window_unstick),
9571                            window,
9572                            G_CONNECT_SWAPPED);
9573   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
9574   
9575   button = gtk_button_new_with_label ("Maximize");
9576   g_signal_connect_object (button,
9577                            "clicked",
9578                            G_CALLBACK (gtk_window_maximize),
9579                            window,
9580                            G_CONNECT_SWAPPED);
9581   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
9582
9583   button = gtk_button_new_with_label ("Unmaximize");
9584   g_signal_connect_object (button,
9585                            "clicked",
9586                            G_CALLBACK (gtk_window_unmaximize),
9587                            window,
9588                            G_CONNECT_SWAPPED);
9589   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
9590
9591   button = gtk_button_new_with_label ("Iconify");
9592   g_signal_connect_object (button,
9593                            "clicked",
9594                            G_CALLBACK (gtk_window_iconify),
9595                            window,
9596                            G_CONNECT_SWAPPED);
9597   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
9598
9599   button = gtk_button_new_with_label ("Fullscreen");
9600   g_signal_connect_object (button,
9601                            "clicked",
9602                            G_CALLBACK (gtk_window_fullscreen),
9603                            window,
9604                            G_CONNECT_SWAPPED);
9605   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
9606
9607   button = gtk_button_new_with_label ("Unfullscreen");
9608   g_signal_connect_object (button,
9609                            "clicked",
9610                            G_CALLBACK (gtk_window_unfullscreen),
9611                            window,
9612                            G_CONNECT_SWAPPED);
9613   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
9614   
9615   button = gtk_button_new_with_label ("Hide (withdraw)");
9616   g_signal_connect_object (button,
9617                            "clicked",
9618                            G_CALLBACK (gtk_widget_hide),
9619                            window,
9620                            G_CONNECT_SWAPPED);
9621   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
9622   
9623   gtk_widget_show_all (vbox);
9624
9625   return vbox;
9626 }
9627
9628 void
9629 create_window_states (GtkWidget *widget)
9630 {
9631   static GtkWidget *window = NULL;
9632   GtkWidget *label;
9633   GtkWidget *box1;
9634   GtkWidget *iconified;
9635   GtkWidget *normal;
9636   GtkWidget *controls;
9637
9638   if (!window)
9639     {
9640       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9641       gtk_window_set_screen (GTK_WINDOW (window),
9642                              gtk_widget_get_screen (widget));
9643
9644       g_signal_connect (window, "destroy",
9645                         G_CALLBACK (gtk_widget_destroyed),
9646                         &window);
9647
9648       gtk_window_set_title (GTK_WINDOW (window), "Window states");
9649       
9650       box1 = gtk_vbox_new (FALSE, 0);
9651       gtk_container_add (GTK_CONTAINER (window), box1);
9652
9653       iconified = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9654
9655       gtk_window_set_screen (GTK_WINDOW (iconified),
9656                              gtk_widget_get_screen (widget));
9657       
9658       g_signal_connect_object (iconified, "destroy",
9659                                G_CALLBACK (gtk_widget_destroy),
9660                                window,
9661                                G_CONNECT_SWAPPED);
9662       gtk_window_iconify (GTK_WINDOW (iconified));
9663       gtk_window_set_title (GTK_WINDOW (iconified), "Iconified initially");
9664       controls = get_state_controls (iconified);
9665       gtk_container_add (GTK_CONTAINER (iconified), controls);
9666       
9667       normal = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9668
9669       gtk_window_set_screen (GTK_WINDOW (normal),
9670                              gtk_widget_get_screen (widget));
9671       
9672       g_signal_connect_object (normal, "destroy",
9673                                G_CALLBACK (gtk_widget_destroy),
9674                                window,
9675                                G_CONNECT_SWAPPED);
9676       
9677       gtk_window_set_title (GTK_WINDOW (normal), "Deiconified initially");
9678       controls = get_state_controls (normal);
9679       gtk_container_add (GTK_CONTAINER (normal), controls);
9680       
9681       label = tracking_label (iconified);
9682       gtk_container_add (GTK_CONTAINER (box1), label);
9683
9684       label = tracking_label (normal);
9685       gtk_container_add (GTK_CONTAINER (box1), label);
9686
9687       gtk_widget_show_all (iconified);
9688       gtk_widget_show_all (normal);
9689       gtk_widget_show_all (box1);
9690     }
9691
9692   if (!GTK_WIDGET_VISIBLE (window))
9693     gtk_widget_show (window);
9694   else
9695     gtk_widget_destroy (window);
9696 }
9697
9698 /*
9699  * Window sizing
9700  */
9701
9702 static gint
9703 configure_event_callback (GtkWidget *widget,
9704                           GdkEventConfigure *event,
9705                           gpointer data)
9706 {
9707   GtkWidget *label = data;
9708   gchar *msg;
9709   gint x, y;
9710   
9711   gtk_window_get_position (GTK_WINDOW (widget), &x, &y);
9712   
9713   msg = g_strdup_printf ("event: %d,%d  %d x %d\n"
9714                          "position: %d, %d",
9715                          event->x, event->y, event->width, event->height,
9716                          x, y);
9717   
9718   gtk_label_set_text (GTK_LABEL (label), msg);
9719
9720   g_free (msg);
9721
9722   return FALSE;
9723 }
9724
9725 static void
9726 get_ints (GtkWidget *window,
9727           gint      *a,
9728           gint      *b)
9729 {
9730   GtkWidget *spin1;
9731   GtkWidget *spin2;
9732
9733   spin1 = g_object_get_data (G_OBJECT (window), "spin1");
9734   spin2 = g_object_get_data (G_OBJECT (window), "spin2");
9735
9736   *a = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (spin1));
9737   *b = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (spin2));
9738 }
9739
9740 static void
9741 set_size_callback (GtkWidget *widget,
9742                    gpointer   data)
9743 {
9744   gint w, h;
9745   
9746   get_ints (data, &w, &h);
9747
9748   gtk_window_resize (GTK_WINDOW (g_object_get_data (data, "target")), w, h);
9749 }
9750
9751 static void
9752 unset_default_size_callback (GtkWidget *widget,
9753                              gpointer   data)
9754 {
9755   gtk_window_set_default_size (g_object_get_data (data, "target"),
9756                                -1, -1);
9757 }
9758
9759 static void
9760 set_default_size_callback (GtkWidget *widget,
9761                            gpointer   data)
9762 {
9763   gint w, h;
9764   
9765   get_ints (data, &w, &h);
9766
9767   gtk_window_set_default_size (g_object_get_data (data, "target"),
9768                                w, h);
9769 }
9770
9771 static void
9772 unset_size_request_callback (GtkWidget *widget,
9773                              gpointer   data)
9774 {
9775   gtk_widget_set_size_request (g_object_get_data (data, "target"),
9776                                -1, -1);
9777 }
9778
9779 static void
9780 set_size_request_callback (GtkWidget *widget,
9781                            gpointer   data)
9782 {
9783   gint w, h;
9784   
9785   get_ints (data, &w, &h);
9786
9787   gtk_widget_set_size_request (g_object_get_data (data, "target"),
9788                                w, h);
9789 }
9790
9791 static void
9792 set_location_callback (GtkWidget *widget,
9793                        gpointer   data)
9794 {
9795   gint x, y;
9796   
9797   get_ints (data, &x, &y);
9798
9799   gtk_window_move (g_object_get_data (data, "target"), x, y);
9800 }
9801
9802 static void
9803 move_to_position_callback (GtkWidget *widget,
9804                            gpointer   data)
9805 {
9806   gint x, y;
9807   GtkWindow *window;
9808
9809   window = g_object_get_data (data, "target");
9810   
9811   gtk_window_get_position (window, &x, &y);
9812
9813   gtk_window_move (window, x, y);
9814 }
9815
9816 static void
9817 set_geometry_callback (GtkWidget *entry,
9818                        gpointer   data)
9819 {
9820   gchar *text;
9821   GtkWindow *target;
9822
9823   target = GTK_WINDOW (g_object_get_data (G_OBJECT (data), "target"));
9824   
9825   text = gtk_editable_get_chars (GTK_EDITABLE (entry), 0, -1);
9826
9827   if (!gtk_window_parse_geometry (target, text))
9828     g_print ("Bad geometry string '%s'\n", text);
9829
9830   g_free (text);
9831 }
9832
9833 static void
9834 allow_shrink_callback (GtkWidget *widget,
9835                        gpointer   data)
9836 {
9837   g_object_set (g_object_get_data (data, "target"),
9838                 "allow_shrink",
9839                 GTK_TOGGLE_BUTTON (widget)->active,
9840                 NULL);
9841 }
9842
9843 static void
9844 allow_grow_callback (GtkWidget *widget,
9845                      gpointer   data)
9846 {
9847   g_object_set (g_object_get_data (data, "target"),
9848                 "allow_grow",
9849                 GTK_TOGGLE_BUTTON (widget)->active,
9850                 NULL);
9851 }
9852
9853 static void
9854 gravity_selected (GtkWidget *widget,
9855                   gpointer   data)
9856 {
9857   gtk_window_set_gravity (GTK_WINDOW (g_object_get_data (data, "target")),
9858                           gtk_option_menu_get_history (GTK_OPTION_MENU (widget)) + GDK_GRAVITY_NORTH_WEST);
9859 }
9860
9861 static void
9862 pos_selected (GtkWidget *widget,
9863               gpointer   data)
9864 {
9865   gtk_window_set_position (GTK_WINDOW (g_object_get_data (data, "target")),
9866                            gtk_option_menu_get_history (GTK_OPTION_MENU (widget)) + GTK_WIN_POS_NONE);
9867 }
9868
9869 static void
9870 move_gravity_window_to_current_position (GtkWidget *widget,
9871                                          gpointer   data)
9872 {
9873   gint x, y;
9874   GtkWindow *window;
9875
9876   window = GTK_WINDOW (data);    
9877   
9878   gtk_window_get_position (window, &x, &y);
9879
9880   gtk_window_move (window, x, y);
9881 }
9882
9883 static void
9884 get_screen_corner (GtkWindow *window,
9885                    gint      *x,
9886                    gint      *y)
9887 {
9888   int w, h;
9889   GdkScreen * screen = gtk_window_get_screen (window);
9890   
9891   gtk_window_get_size (GTK_WINDOW (window), &w, &h);
9892
9893   switch (gtk_window_get_gravity (window))
9894     {
9895     case GDK_GRAVITY_SOUTH_EAST:
9896       *x = gdk_screen_get_width (screen) - w;
9897       *y = gdk_screen_get_height (screen) - h;
9898       break;
9899
9900     case GDK_GRAVITY_NORTH_EAST:
9901       *x = gdk_screen_get_width (screen) - w;
9902       *y = 0;
9903       break;
9904
9905     case GDK_GRAVITY_SOUTH_WEST:
9906       *x = 0;
9907       *y = gdk_screen_get_height (screen) - h;
9908       break;
9909
9910     case GDK_GRAVITY_NORTH_WEST:
9911       *x = 0;
9912       *y = 0;
9913       break;
9914       
9915     case GDK_GRAVITY_SOUTH:
9916       *x = (gdk_screen_get_width (screen) - w) / 2;
9917       *y = gdk_screen_get_height (screen) - h;
9918       break;
9919
9920     case GDK_GRAVITY_NORTH:
9921       *x = (gdk_screen_get_width (screen) - w) / 2;
9922       *y = 0;
9923       break;
9924
9925     case GDK_GRAVITY_WEST:
9926       *x = 0;
9927       *y = (gdk_screen_get_height (screen) - h) / 2;
9928       break;
9929
9930     case GDK_GRAVITY_EAST:
9931       *x = gdk_screen_get_width (screen) - w;
9932       *y = (gdk_screen_get_height (screen) - h) / 2;
9933       break;
9934
9935     case GDK_GRAVITY_CENTER:
9936       *x = (gdk_screen_get_width (screen) - w) / 2;
9937       *y = (gdk_screen_get_height (screen) - h) / 2;
9938       break;
9939
9940     case GDK_GRAVITY_STATIC:
9941       /* pick some random numbers */
9942       *x = 350;
9943       *y = 350;
9944       break;
9945
9946     default:
9947       g_assert_not_reached ();
9948       break;
9949     }
9950 }
9951
9952 static void
9953 move_gravity_window_to_starting_position (GtkWidget *widget,
9954                                           gpointer   data)
9955 {
9956   gint x, y;
9957   GtkWindow *window;
9958
9959   window = GTK_WINDOW (data);    
9960   
9961   get_screen_corner (window,
9962                      &x, &y);
9963   
9964   gtk_window_move (window, x, y);
9965 }
9966
9967 static GtkWidget*
9968 make_gravity_window (GtkWidget   *destroy_with,
9969                      GdkGravity   gravity,
9970                      const gchar *title)
9971 {
9972   GtkWidget *window;
9973   GtkWidget *button;
9974   GtkWidget *vbox;
9975   int x, y;
9976   
9977   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
9978
9979   gtk_window_set_screen (GTK_WINDOW (window),
9980                          gtk_widget_get_screen (destroy_with));
9981
9982   vbox = gtk_vbox_new (FALSE, 0);
9983   gtk_widget_show (vbox);
9984   
9985   gtk_container_add (GTK_CONTAINER (window), vbox);
9986   gtk_window_set_title (GTK_WINDOW (window), title);
9987   gtk_window_set_gravity (GTK_WINDOW (window), gravity);
9988
9989   g_signal_connect_object (destroy_with,
9990                            "destroy",
9991                            G_CALLBACK (gtk_widget_destroy),
9992                            window,
9993                            G_CONNECT_SWAPPED);
9994
9995   
9996   button = gtk_button_new_with_mnemonic ("_Move to current position");
9997
9998   g_signal_connect (button, "clicked",
9999                     G_CALLBACK (move_gravity_window_to_current_position),
10000                     window);
10001
10002   gtk_container_add (GTK_CONTAINER (vbox), button);
10003   gtk_widget_show (button);
10004
10005   button = gtk_button_new_with_mnemonic ("Move to _starting position");
10006
10007   g_signal_connect (button, "clicked",
10008                     G_CALLBACK (move_gravity_window_to_starting_position),
10009                     window);
10010
10011   gtk_container_add (GTK_CONTAINER (vbox), button);
10012   gtk_widget_show (button);
10013   
10014   /* Pretend this is the result of --geometry.
10015    * DO NOT COPY THIS CODE unless you are setting --geometry results,
10016    * and in that case you probably should just use gtk_window_parse_geometry().
10017    * AGAIN, DO NOT SET GDK_HINT_USER_POS! It violates the ICCCM unless
10018    * you are parsing --geometry or equivalent.
10019    */
10020   gtk_window_set_geometry_hints (GTK_WINDOW (window),
10021                                  NULL, NULL,
10022                                  GDK_HINT_USER_POS);
10023
10024   gtk_window_set_default_size (GTK_WINDOW (window),
10025                                200, 200);
10026
10027   get_screen_corner (GTK_WINDOW (window), &x, &y);
10028   
10029   gtk_window_move (GTK_WINDOW (window),
10030                    x, y);
10031   
10032   return window;
10033 }
10034
10035 static void
10036 do_gravity_test (GtkWidget *widget,
10037                  gpointer   data)
10038 {
10039   GtkWidget *destroy_with = data;
10040   GtkWidget *window;
10041   
10042   /* We put a window at each gravity point on the screen. */
10043   window = make_gravity_window (destroy_with, GDK_GRAVITY_NORTH_WEST,
10044                                 "NorthWest");
10045   gtk_widget_show (window);
10046   
10047   window = make_gravity_window (destroy_with, GDK_GRAVITY_SOUTH_EAST,
10048                                 "SouthEast");
10049   gtk_widget_show (window);
10050
10051   window = make_gravity_window (destroy_with, GDK_GRAVITY_NORTH_EAST,
10052                                 "NorthEast");
10053   gtk_widget_show (window);
10054
10055   window = make_gravity_window (destroy_with, GDK_GRAVITY_SOUTH_WEST,
10056                                 "SouthWest");
10057   gtk_widget_show (window);
10058
10059   window = make_gravity_window (destroy_with, GDK_GRAVITY_SOUTH,
10060                                 "South");
10061   gtk_widget_show (window);
10062
10063   window = make_gravity_window (destroy_with, GDK_GRAVITY_NORTH,
10064                                 "North");
10065   gtk_widget_show (window);
10066
10067   
10068   window = make_gravity_window (destroy_with, GDK_GRAVITY_WEST,
10069                                 "West");
10070   gtk_widget_show (window);
10071
10072     
10073   window = make_gravity_window (destroy_with, GDK_GRAVITY_EAST,
10074                                 "East");
10075   gtk_widget_show (window);
10076
10077   window = make_gravity_window (destroy_with, GDK_GRAVITY_CENTER,
10078                                 "Center");
10079   gtk_widget_show (window);
10080
10081   window = make_gravity_window (destroy_with, GDK_GRAVITY_STATIC,
10082                                 "Static");
10083   gtk_widget_show (window);
10084 }
10085
10086 static GtkWidget*
10087 window_controls (GtkWidget *window)
10088 {
10089   GtkWidget *control_window;
10090   GtkWidget *label;
10091   GtkWidget *vbox;
10092   GtkWidget *button;
10093   GtkWidget *spin;
10094   GtkAdjustment *adj;
10095   GtkWidget *entry;
10096   GtkWidget *om;
10097   GtkWidget *menu;
10098   gint i;
10099   
10100   control_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
10101
10102   gtk_window_set_screen (GTK_WINDOW (control_window),
10103                          gtk_widget_get_screen (window));
10104
10105   gtk_window_set_title (GTK_WINDOW (control_window), "Size controls");
10106   
10107   g_object_set_data (G_OBJECT (control_window),
10108                      "target",
10109                      window);
10110   
10111   g_signal_connect_object (control_window,
10112                            "destroy",
10113                            G_CALLBACK (gtk_widget_destroy),
10114                            window,
10115                            G_CONNECT_SWAPPED);
10116
10117   vbox = gtk_vbox_new (FALSE, 5);
10118   
10119   gtk_container_add (GTK_CONTAINER (control_window), vbox);
10120   
10121   label = gtk_label_new ("<no configure events>");
10122   gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
10123   
10124   g_signal_connect (window,
10125                     "configure_event",
10126                     G_CALLBACK (configure_event_callback),
10127                     label);
10128
10129   adj = (GtkAdjustment *) gtk_adjustment_new (10.0, -2000.0, 2000.0, 1.0,
10130                                               5.0, 0.0);
10131   spin = gtk_spin_button_new (adj, 0, 0);
10132
10133   gtk_box_pack_start (GTK_BOX (vbox), spin, FALSE, FALSE, 0);
10134
10135   g_object_set_data (G_OBJECT (control_window), "spin1", spin);
10136
10137   adj = (GtkAdjustment *) gtk_adjustment_new (10.0, -2000.0, 2000.0, 1.0,
10138                                               5.0, 0.0);
10139   spin = gtk_spin_button_new (adj, 0, 0);
10140
10141   gtk_box_pack_start (GTK_BOX (vbox), spin, FALSE, FALSE, 0);
10142
10143   g_object_set_data (G_OBJECT (control_window), "spin2", spin);
10144
10145   entry = gtk_entry_new ();
10146   gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
10147
10148   g_signal_connect (entry, "changed",
10149                     G_CALLBACK (set_geometry_callback),
10150                     control_window);
10151
10152   button = gtk_button_new_with_label ("Show gravity test windows");
10153   g_signal_connect_swapped (button,
10154                             "clicked",
10155                             G_CALLBACK (do_gravity_test),
10156                             control_window);
10157   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
10158
10159   button = gtk_button_new_with_label ("Reshow with initial size");
10160   g_signal_connect_object (button,
10161                            "clicked",
10162                            G_CALLBACK (gtk_window_reshow_with_initial_size),
10163                            window,
10164                            G_CONNECT_SWAPPED);
10165   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
10166   
10167   button = gtk_button_new_with_label ("Queue resize");
10168   g_signal_connect_object (button,
10169                            "clicked",
10170                            G_CALLBACK (gtk_widget_queue_resize),
10171                            window,
10172                            G_CONNECT_SWAPPED);
10173   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
10174   
10175   button = gtk_button_new_with_label ("Resize");
10176   g_signal_connect (button,
10177                     "clicked",
10178                     G_CALLBACK (set_size_callback),
10179                     control_window);
10180   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
10181
10182   button = gtk_button_new_with_label ("Set default size");
10183   g_signal_connect (button,
10184                     "clicked",
10185                     G_CALLBACK (set_default_size_callback),
10186                     control_window);
10187   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
10188
10189   button = gtk_button_new_with_label ("Unset default size");
10190   g_signal_connect (button,
10191                     "clicked",
10192                     G_CALLBACK (unset_default_size_callback),
10193                     control_window);
10194   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
10195   
10196   button = gtk_button_new_with_label ("Set size request");
10197   g_signal_connect (button,
10198                     "clicked",
10199                     G_CALLBACK (set_size_request_callback),
10200                     control_window);
10201   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
10202
10203   button = gtk_button_new_with_label ("Unset size request");
10204   g_signal_connect (button,
10205                     "clicked",
10206                     G_CALLBACK (unset_size_request_callback),
10207                     control_window);
10208   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
10209   
10210   button = gtk_button_new_with_label ("Move");
10211   g_signal_connect (button,
10212                     "clicked",
10213                     G_CALLBACK (set_location_callback),
10214                     control_window);
10215   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
10216
10217   button = gtk_button_new_with_label ("Move to current position");
10218   g_signal_connect (button,
10219                     "clicked",
10220                     G_CALLBACK (move_to_position_callback),
10221                     control_window);
10222   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
10223   
10224   button = gtk_check_button_new_with_label ("Allow shrink");
10225   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE);
10226   g_signal_connect (button,
10227                     "toggled",
10228                     G_CALLBACK (allow_shrink_callback),
10229                     control_window);
10230   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
10231
10232   button = gtk_check_button_new_with_label ("Allow grow");
10233   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
10234   g_signal_connect (button,
10235                     "toggled",
10236                     G_CALLBACK (allow_grow_callback),
10237                     control_window);
10238   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
10239   
10240   button = gtk_button_new_with_mnemonic ("_Show");
10241   g_signal_connect_object (button,
10242                            "clicked",
10243                            G_CALLBACK (gtk_widget_show),
10244                            window,
10245                            G_CONNECT_SWAPPED);
10246   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
10247
10248   button = gtk_button_new_with_mnemonic ("_Hide");
10249   g_signal_connect_object (button,
10250                            "clicked",
10251                            G_CALLBACK (gtk_widget_hide),
10252                            window,
10253                            G_CONNECT_SWAPPED);
10254   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
10255   
10256   menu = gtk_menu_new ();
10257   
10258   i = 0;
10259   while (i < 10)
10260     {
10261       GtkWidget *mi;
10262       static gchar *names[] = {
10263         "GDK_GRAVITY_NORTH_WEST",
10264         "GDK_GRAVITY_NORTH",
10265         "GDK_GRAVITY_NORTH_EAST",
10266         "GDK_GRAVITY_WEST",
10267         "GDK_GRAVITY_CENTER",
10268         "GDK_GRAVITY_EAST",
10269         "GDK_GRAVITY_SOUTH_WEST",
10270         "GDK_GRAVITY_SOUTH",
10271         "GDK_GRAVITY_SOUTH_EAST",
10272         "GDK_GRAVITY_STATIC",
10273         NULL
10274       };
10275
10276       g_assert (names[i]);
10277       
10278       mi = gtk_menu_item_new_with_label (names[i]);
10279
10280       gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
10281
10282       ++i;
10283     }
10284   
10285   gtk_widget_show_all (menu);
10286   
10287   om = gtk_option_menu_new ();
10288   gtk_option_menu_set_menu (GTK_OPTION_MENU (om), menu);
10289   
10290
10291   g_signal_connect (om,
10292                     "changed",
10293                     G_CALLBACK (gravity_selected),
10294                     control_window);
10295
10296   gtk_box_pack_end (GTK_BOX (vbox), om, FALSE, FALSE, 0);
10297
10298
10299   menu = gtk_menu_new ();
10300   
10301   i = 0;
10302   while (i < 5)
10303     {
10304       GtkWidget *mi;
10305       static gchar *names[] = {
10306         "GTK_WIN_POS_NONE",
10307         "GTK_WIN_POS_CENTER",
10308         "GTK_WIN_POS_MOUSE",
10309         "GTK_WIN_POS_CENTER_ALWAYS",
10310         "GTK_WIN_POS_CENTER_ON_PARENT",
10311         NULL
10312       };
10313
10314       g_assert (names[i]);
10315       
10316       mi = gtk_menu_item_new_with_label (names[i]);
10317
10318       gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
10319
10320       ++i;
10321     }
10322   
10323   gtk_widget_show_all (menu);
10324   
10325   om = gtk_option_menu_new ();
10326   gtk_option_menu_set_menu (GTK_OPTION_MENU (om), menu);
10327   
10328
10329   g_signal_connect (om,
10330                     "changed",
10331                     G_CALLBACK (pos_selected),
10332                     control_window);
10333
10334   gtk_box_pack_end (GTK_BOX (vbox), om, FALSE, FALSE, 0);
10335   
10336   gtk_widget_show_all (vbox);
10337   
10338   return control_window;
10339 }
10340
10341 void
10342 create_window_sizing (GtkWidget *widget)
10343 {
10344   static GtkWidget *window = NULL;
10345   static GtkWidget *target_window = NULL;
10346
10347   if (!target_window)
10348     {
10349       GtkWidget *label;
10350       
10351       target_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
10352       gtk_window_set_screen (GTK_WINDOW (target_window),
10353                              gtk_widget_get_screen (widget));
10354       label = gtk_label_new (NULL);
10355       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");
10356       gtk_container_add (GTK_CONTAINER (target_window), label);
10357       gtk_widget_show (label);
10358       
10359       g_signal_connect (target_window, "destroy",
10360                         G_CALLBACK (gtk_widget_destroyed),
10361                         &target_window);
10362
10363       window = window_controls (target_window);
10364       
10365       g_signal_connect (window, "destroy",
10366                         G_CALLBACK (gtk_widget_destroyed),
10367                         &window);
10368       
10369       gtk_window_set_title (GTK_WINDOW (target_window), "Window to size");
10370     }
10371
10372   /* don't show target window by default, we want to allow testing
10373    * of behavior on first show.
10374    */
10375   
10376   if (!GTK_WIDGET_VISIBLE (window))
10377     gtk_widget_show (window);
10378   else
10379     gtk_widget_destroy (window);
10380 }
10381
10382 /*
10383  * GtkProgressBar
10384  */
10385
10386 typedef struct _ProgressData {
10387   GtkWidget *window;
10388   GtkWidget *pbar;
10389   GtkWidget *block_spin;
10390   GtkWidget *x_align_spin;
10391   GtkWidget *y_align_spin;
10392   GtkWidget *step_spin;
10393   GtkWidget *act_blocks_spin;
10394   GtkWidget *label;
10395   GtkWidget *omenu1;
10396   GtkWidget *omenu2;
10397   GtkWidget *entry;
10398   int timer;
10399 } ProgressData;
10400
10401 gint
10402 progress_timeout (gpointer data)
10403 {
10404   gdouble new_val;
10405   GtkAdjustment *adj;
10406
10407   adj = GTK_PROGRESS (data)->adjustment;
10408
10409   new_val = adj->value + 1;
10410   if (new_val > adj->upper)
10411     new_val = adj->lower;
10412
10413   gtk_progress_set_value (GTK_PROGRESS (data), new_val);
10414
10415   return TRUE;
10416 }
10417
10418 static void
10419 destroy_progress (GtkWidget     *widget,
10420                   ProgressData **pdata)
10421 {
10422   gtk_timeout_remove ((*pdata)->timer);
10423   (*pdata)->timer = 0;
10424   (*pdata)->window = NULL;
10425   g_free (*pdata);
10426   *pdata = NULL;
10427 }
10428
10429 static void
10430 progressbar_toggle_orientation (GtkWidget *widget, gpointer data)
10431 {
10432   ProgressData *pdata;
10433   gint i;
10434
10435   pdata = (ProgressData *) data;
10436
10437   if (!GTK_WIDGET_MAPPED (widget))
10438     return;
10439
10440   i = gtk_option_menu_get_history (GTK_OPTION_MENU (widget));
10441
10442   gtk_progress_bar_set_orientation (GTK_PROGRESS_BAR (pdata->pbar),
10443                                     (GtkProgressBarOrientation) i);
10444 }
10445
10446 static void
10447 toggle_show_text (GtkWidget *widget, ProgressData *pdata)
10448 {
10449   gtk_progress_set_show_text (GTK_PROGRESS (pdata->pbar),
10450                               GTK_TOGGLE_BUTTON (widget)->active);
10451   gtk_widget_set_sensitive (pdata->entry, GTK_TOGGLE_BUTTON (widget)->active);
10452   gtk_widget_set_sensitive (pdata->x_align_spin,
10453                             GTK_TOGGLE_BUTTON (widget)->active);
10454   gtk_widget_set_sensitive (pdata->y_align_spin,
10455                             GTK_TOGGLE_BUTTON (widget)->active);
10456 }
10457
10458 static void
10459 progressbar_toggle_bar_style (GtkWidget *widget, gpointer data)
10460 {
10461   ProgressData *pdata;
10462   gint i;
10463
10464   pdata = (ProgressData *) data;
10465
10466   if (!GTK_WIDGET_MAPPED (widget))
10467     return;
10468
10469   i = gtk_option_menu_get_history (GTK_OPTION_MENU (widget));
10470
10471   if (i == 1)
10472     gtk_widget_set_sensitive (pdata->block_spin, TRUE);
10473   else
10474     gtk_widget_set_sensitive (pdata->block_spin, FALSE);
10475   
10476   gtk_progress_bar_set_bar_style (GTK_PROGRESS_BAR (pdata->pbar),
10477                                   (GtkProgressBarStyle) i);
10478 }
10479
10480 static void
10481 progress_value_changed (GtkAdjustment *adj, ProgressData *pdata)
10482 {
10483   char buf[20];
10484
10485   if (GTK_PROGRESS (pdata->pbar)->activity_mode)
10486     sprintf (buf, "???");
10487   else
10488     sprintf (buf, "%.0f%%", 100 *
10489              gtk_progress_get_current_percentage (GTK_PROGRESS (pdata->pbar)));
10490   gtk_label_set_text (GTK_LABEL (pdata->label), buf);
10491 }
10492
10493 static void
10494 adjust_blocks (GtkAdjustment *adj, ProgressData *pdata)
10495 {
10496   gtk_progress_set_percentage (GTK_PROGRESS (pdata->pbar), 0);
10497   gtk_progress_bar_set_discrete_blocks (GTK_PROGRESS_BAR (pdata->pbar),
10498      gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (pdata->block_spin)));
10499 }
10500
10501 static void
10502 adjust_step (GtkAdjustment *adj, ProgressData *pdata)
10503 {
10504   gtk_progress_bar_set_activity_step (GTK_PROGRESS_BAR (pdata->pbar),
10505      gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (pdata->step_spin)));
10506 }
10507
10508 static void
10509 adjust_act_blocks (GtkAdjustment *adj, ProgressData *pdata)
10510 {
10511   gtk_progress_bar_set_activity_blocks (GTK_PROGRESS_BAR (pdata->pbar),
10512                gtk_spin_button_get_value_as_int 
10513                       (GTK_SPIN_BUTTON (pdata->act_blocks_spin)));
10514 }
10515
10516 static void
10517 adjust_align (GtkAdjustment *adj, ProgressData *pdata)
10518 {
10519   gtk_progress_set_text_alignment (GTK_PROGRESS (pdata->pbar),
10520          gtk_spin_button_get_value (GTK_SPIN_BUTTON (pdata->x_align_spin)),
10521          gtk_spin_button_get_value (GTK_SPIN_BUTTON (pdata->y_align_spin)));
10522 }
10523
10524 static void
10525 toggle_activity_mode (GtkWidget *widget, ProgressData *pdata)
10526 {
10527   gtk_progress_set_activity_mode (GTK_PROGRESS (pdata->pbar),
10528                                   GTK_TOGGLE_BUTTON (widget)->active);
10529   gtk_widget_set_sensitive (pdata->step_spin, 
10530                             GTK_TOGGLE_BUTTON (widget)->active);
10531   gtk_widget_set_sensitive (pdata->act_blocks_spin, 
10532                             GTK_TOGGLE_BUTTON (widget)->active);
10533 }
10534
10535 static void
10536 entry_changed (GtkWidget *widget, ProgressData *pdata)
10537 {
10538   gtk_progress_set_format_string (GTK_PROGRESS (pdata->pbar),
10539                           gtk_entry_get_text (GTK_ENTRY (pdata->entry)));
10540 }
10541
10542 void
10543 create_progress_bar (GtkWidget *widget)
10544 {
10545   GtkWidget *button;
10546   GtkWidget *vbox;
10547   GtkWidget *vbox2;
10548   GtkWidget *hbox;
10549   GtkWidget *check;
10550   GtkWidget *frame;
10551   GtkWidget *tab;
10552   GtkWidget *label;
10553   GtkWidget *align;
10554   GtkAdjustment *adj;
10555   static ProgressData *pdata = NULL;
10556
10557   static gchar *items1[] =
10558   {
10559     "Left-Right",
10560     "Right-Left",
10561     "Bottom-Top",
10562     "Top-Bottom"
10563   };
10564
10565   static gchar *items2[] =
10566   {
10567     "Continuous",
10568     "Discrete"
10569   };
10570   
10571   if (!pdata)
10572     pdata = g_new0 (ProgressData, 1);
10573
10574   if (!pdata->window)
10575     {
10576       pdata->window = gtk_dialog_new ();
10577
10578       gtk_window_set_screen (GTK_WINDOW (pdata->window),
10579                              gtk_widget_get_screen (widget));
10580
10581       gtk_window_set_resizable (GTK_WINDOW (pdata->window), FALSE);
10582
10583       g_signal_connect (pdata->window, "destroy",
10584                         G_CALLBACK (destroy_progress),
10585                         &pdata);
10586
10587       pdata->timer = 0;
10588
10589       gtk_window_set_title (GTK_WINDOW (pdata->window), "GtkProgressBar");
10590       gtk_container_set_border_width (GTK_CONTAINER (pdata->window), 0);
10591
10592       vbox = gtk_vbox_new (FALSE, 5);
10593       gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
10594       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (pdata->window)->vbox), 
10595                           vbox, FALSE, TRUE, 0);
10596
10597       frame = gtk_frame_new ("Progress");
10598       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
10599
10600       vbox2 = gtk_vbox_new (FALSE, 5);
10601       gtk_container_add (GTK_CONTAINER (frame), vbox2);
10602
10603       align = gtk_alignment_new (0.5, 0.5, 0, 0);
10604       gtk_box_pack_start (GTK_BOX (vbox2), align, FALSE, FALSE, 5);
10605
10606       adj = (GtkAdjustment *) gtk_adjustment_new (0, 1, 300, 0, 0, 0);
10607       g_signal_connect (adj, "value_changed",
10608                         G_CALLBACK (progress_value_changed), pdata);
10609
10610       pdata->pbar = gtk_widget_new (GTK_TYPE_PROGRESS_BAR,
10611                                     "adjustment", adj,
10612                                     NULL);
10613       gtk_progress_set_format_string (GTK_PROGRESS (pdata->pbar),
10614                                       "%v from [%l,%u] (=%p%%)");
10615       gtk_container_add (GTK_CONTAINER (align), pdata->pbar);
10616       pdata->timer = gtk_timeout_add (100, progress_timeout, pdata->pbar);
10617
10618       align = gtk_alignment_new (0.5, 0.5, 0, 0);
10619       gtk_box_pack_start (GTK_BOX (vbox2), align, FALSE, FALSE, 5);
10620
10621       hbox = gtk_hbox_new (FALSE, 5);
10622       gtk_container_add (GTK_CONTAINER (align), hbox);
10623       label = gtk_label_new ("Label updated by user :"); 
10624       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
10625       pdata->label = gtk_label_new ("");
10626       gtk_box_pack_start (GTK_BOX (hbox), pdata->label, FALSE, TRUE, 0);
10627
10628       frame = gtk_frame_new ("Options");
10629       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, TRUE, 0);
10630
10631       vbox2 = gtk_vbox_new (FALSE, 5);
10632       gtk_container_add (GTK_CONTAINER (frame), vbox2);
10633
10634       tab = gtk_table_new (7, 2, FALSE);
10635       gtk_box_pack_start (GTK_BOX (vbox2), tab, FALSE, TRUE, 0);
10636
10637       label = gtk_label_new ("Orientation :");
10638       gtk_table_attach (GTK_TABLE (tab), label, 0, 1, 0, 1,
10639                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
10640                         5, 5);
10641       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
10642
10643       pdata->omenu1 = build_option_menu (items1, 4, 0,
10644                                          progressbar_toggle_orientation,
10645                                          pdata);
10646       hbox = gtk_hbox_new (FALSE, 0);
10647       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 0, 1,
10648                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
10649                         5, 5);
10650       gtk_box_pack_start (GTK_BOX (hbox), pdata->omenu1, TRUE, TRUE, 0);
10651       
10652       check = gtk_check_button_new_with_label ("Show text");
10653       g_signal_connect (check, "clicked",
10654                         G_CALLBACK (toggle_show_text),
10655                         pdata);
10656       gtk_table_attach (GTK_TABLE (tab), check, 0, 1, 1, 2,
10657                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
10658                         5, 5);
10659
10660       hbox = gtk_hbox_new (FALSE, 0);
10661       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 1, 2,
10662                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
10663                         5, 5);
10664
10665       label = gtk_label_new ("Format : ");
10666       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
10667
10668       pdata->entry = gtk_entry_new ();
10669       g_signal_connect (pdata->entry, "changed",
10670                         G_CALLBACK (entry_changed),
10671                         pdata);
10672       gtk_box_pack_start (GTK_BOX (hbox), pdata->entry, TRUE, TRUE, 0);
10673       gtk_entry_set_text (GTK_ENTRY (pdata->entry), "%v from [%l,%u] (=%p%%)");
10674       gtk_widget_set_size_request (pdata->entry, 100, -1);
10675       gtk_widget_set_sensitive (pdata->entry, FALSE);
10676
10677       label = gtk_label_new ("Text align :");
10678       gtk_table_attach (GTK_TABLE (tab), label, 0, 1, 2, 3,
10679                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
10680                         5, 5);
10681       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
10682
10683       hbox = gtk_hbox_new (FALSE, 0);
10684       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 2, 3,
10685                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
10686                         5, 5);
10687
10688       label = gtk_label_new ("x :");
10689       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 5);
10690       
10691       adj = (GtkAdjustment *) gtk_adjustment_new (0.5, 0, 1, 0.1, 0.1, 0);
10692       pdata->x_align_spin = gtk_spin_button_new (adj, 0, 1);
10693       g_signal_connect (adj, "value_changed",
10694                         G_CALLBACK (adjust_align), pdata);
10695       gtk_box_pack_start (GTK_BOX (hbox), pdata->x_align_spin, FALSE, TRUE, 0);
10696       gtk_widget_set_sensitive (pdata->x_align_spin, FALSE);
10697
10698       label = gtk_label_new ("y :");
10699       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 5);
10700
10701       adj = (GtkAdjustment *) gtk_adjustment_new (0.5, 0, 1, 0.1, 0.1, 0);
10702       pdata->y_align_spin = gtk_spin_button_new (adj, 0, 1);
10703       g_signal_connect (adj, "value_changed",
10704                         G_CALLBACK (adjust_align), pdata);
10705       gtk_box_pack_start (GTK_BOX (hbox), pdata->y_align_spin, FALSE, TRUE, 0);
10706       gtk_widget_set_sensitive (pdata->y_align_spin, FALSE);
10707
10708       label = gtk_label_new ("Bar Style :");
10709       gtk_table_attach (GTK_TABLE (tab), label, 0, 1, 3, 4,
10710                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
10711                         5, 5);
10712       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
10713
10714       pdata->omenu2 = build_option_menu (items2, 2, 0,
10715                                          progressbar_toggle_bar_style,
10716                                          pdata);
10717       hbox = gtk_hbox_new (FALSE, 0);
10718       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 3, 4,
10719                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
10720                         5, 5);
10721       gtk_box_pack_start (GTK_BOX (hbox), pdata->omenu2, TRUE, TRUE, 0);
10722
10723       label = gtk_label_new ("Block count :");
10724       gtk_table_attach (GTK_TABLE (tab), label, 0, 1, 4, 5,
10725                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
10726                         5, 5);
10727       gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
10728
10729       hbox = gtk_hbox_new (FALSE, 0);
10730       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 4, 5,
10731                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
10732                         5, 5);
10733       adj = (GtkAdjustment *) gtk_adjustment_new (10, 2, 20, 1, 5, 0);
10734       pdata->block_spin = gtk_spin_button_new (adj, 0, 0);
10735       g_signal_connect (adj, "value_changed",
10736                         G_CALLBACK (adjust_blocks), pdata);
10737       gtk_box_pack_start (GTK_BOX (hbox), pdata->block_spin, FALSE, TRUE, 0);
10738       gtk_widget_set_sensitive (pdata->block_spin, FALSE);
10739
10740       check = gtk_check_button_new_with_label ("Activity mode");
10741       g_signal_connect (check, "clicked",
10742                         G_CALLBACK (toggle_activity_mode), pdata);
10743       gtk_table_attach (GTK_TABLE (tab), check, 0, 1, 5, 6,
10744                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
10745                         5, 5);
10746
10747       hbox = gtk_hbox_new (FALSE, 0);
10748       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 5, 6,
10749                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
10750                         5, 5);
10751       label = gtk_label_new ("Step size : ");
10752       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
10753       adj = (GtkAdjustment *) gtk_adjustment_new (3, 1, 20, 1, 5, 0);
10754       pdata->step_spin = gtk_spin_button_new (adj, 0, 0);
10755       g_signal_connect (adj, "value_changed",
10756                         G_CALLBACK (adjust_step), pdata);
10757       gtk_box_pack_start (GTK_BOX (hbox), pdata->step_spin, FALSE, TRUE, 0);
10758       gtk_widget_set_sensitive (pdata->step_spin, FALSE);
10759
10760       hbox = gtk_hbox_new (FALSE, 0);
10761       gtk_table_attach (GTK_TABLE (tab), hbox, 1, 2, 6, 7,
10762                         GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
10763                         5, 5);
10764       label = gtk_label_new ("Blocks :     ");
10765       gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, TRUE, 0);
10766       adj = (GtkAdjustment *) gtk_adjustment_new (5, 2, 10, 1, 5, 0);
10767       pdata->act_blocks_spin = gtk_spin_button_new (adj, 0, 0);
10768       g_signal_connect (adj, "value_changed",
10769                         G_CALLBACK (adjust_act_blocks), pdata);
10770       gtk_box_pack_start (GTK_BOX (hbox), pdata->act_blocks_spin, FALSE, TRUE,
10771                           0);
10772       gtk_widget_set_sensitive (pdata->act_blocks_spin, FALSE);
10773
10774       button = gtk_button_new_with_label ("close");
10775       g_signal_connect_swapped (button, "clicked",
10776                                 G_CALLBACK (gtk_widget_destroy),
10777                                 pdata->window);
10778       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
10779       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (pdata->window)->action_area), 
10780                           button, TRUE, TRUE, 0);
10781       gtk_widget_grab_default (button);
10782     }
10783
10784   if (!GTK_WIDGET_VISIBLE (pdata->window))
10785     gtk_widget_show_all (pdata->window);
10786   else
10787     gtk_widget_destroy (pdata->window);
10788 }
10789
10790 /*
10791  * Properties
10792  */
10793
10794 typedef struct {
10795   int x;
10796   int y;
10797   gboolean found;
10798   gboolean first;
10799   GtkWidget *res_widget;
10800 } FindWidgetData;
10801
10802 static void
10803 find_widget (GtkWidget *widget, FindWidgetData *data)
10804 {
10805   GtkAllocation new_allocation;
10806   gint x_offset = 0;
10807   gint y_offset = 0;
10808
10809   new_allocation = widget->allocation;
10810
10811   if (data->found || !GTK_WIDGET_MAPPED (widget))
10812     return;
10813
10814   /* Note that in the following code, we only count the
10815    * position as being inside a WINDOW widget if it is inside
10816    * widget->window; points that are outside of widget->window
10817    * but within the allocation are not counted. This is consistent
10818    * with the way we highlight drag targets.
10819    */
10820   if (!GTK_WIDGET_NO_WINDOW (widget))
10821     {
10822       new_allocation.x = 0;
10823       new_allocation.y = 0;
10824     }
10825   
10826   if (widget->parent && !data->first)
10827     {
10828       GdkWindow *window = widget->window;
10829       while (window != widget->parent->window)
10830         {
10831           gint tx, ty, twidth, theight;
10832           gdk_drawable_get_size (window, &twidth, &theight);
10833
10834           if (new_allocation.x < 0)
10835             {
10836               new_allocation.width += new_allocation.x;
10837               new_allocation.x = 0;
10838             }
10839           if (new_allocation.y < 0)
10840             {
10841               new_allocation.height += new_allocation.y;
10842               new_allocation.y = 0;
10843             }
10844           if (new_allocation.x + new_allocation.width > twidth)
10845             new_allocation.width = twidth - new_allocation.x;
10846           if (new_allocation.y + new_allocation.height > theight)
10847             new_allocation.height = theight - new_allocation.y;
10848
10849           gdk_window_get_position (window, &tx, &ty);
10850           new_allocation.x += tx;
10851           x_offset += tx;
10852           new_allocation.y += ty;
10853           y_offset += ty;
10854           
10855           window = gdk_window_get_parent (window);
10856         }
10857     }
10858
10859   if ((data->x >= new_allocation.x) && (data->y >= new_allocation.y) &&
10860       (data->x < new_allocation.x + new_allocation.width) && 
10861       (data->y < new_allocation.y + new_allocation.height))
10862     {
10863       /* First, check if the drag is in a valid drop site in
10864        * one of our children 
10865        */
10866       if (GTK_IS_CONTAINER (widget))
10867         {
10868           FindWidgetData new_data = *data;
10869           
10870           new_data.x -= x_offset;
10871           new_data.y -= y_offset;
10872           new_data.found = FALSE;
10873           new_data.first = FALSE;
10874           
10875           gtk_container_forall (GTK_CONTAINER (widget),
10876                                 (GtkCallback)find_widget,
10877                                 &new_data);
10878           
10879           data->found = new_data.found;
10880           if (data->found)
10881             data->res_widget = new_data.res_widget;
10882         }
10883
10884       /* If not, and this widget is registered as a drop site, check to
10885        * emit "drag_motion" to check if we are actually in
10886        * a drop site.
10887        */
10888       if (!data->found)
10889         {
10890           data->found = TRUE;
10891           data->res_widget = widget;
10892         }
10893     }
10894 }
10895
10896 static GtkWidget *
10897 find_widget_at_pointer (GdkDisplay *display)
10898 {
10899   GtkWidget *widget = NULL;
10900   GdkWindow *pointer_window;
10901   gint x, y;
10902   FindWidgetData data;
10903  
10904  pointer_window = gdk_display_get_window_at_pointer (display, NULL, NULL);
10905  
10906  if (pointer_window)
10907    gdk_window_get_user_data (pointer_window, (gpointer*) &widget);
10908
10909  if (widget)
10910    {
10911      gdk_window_get_pointer (widget->window,
10912                              &x, &y, NULL);
10913      
10914      data.x = x;
10915      data.y = y;
10916      data.found = FALSE;
10917      data.first = TRUE;
10918
10919      find_widget (widget, &data);
10920      if (data.found)
10921        return data.res_widget;
10922      return widget;
10923    }
10924  return NULL;
10925 }
10926
10927 struct PropertiesData {
10928   GtkWidget **window;
10929   GdkCursor *cursor;
10930   gboolean in_query;
10931   gint handler;
10932 };
10933
10934 static void
10935 destroy_properties (GtkWidget             *widget,
10936                     struct PropertiesData *data)
10937 {
10938   if (data->window)
10939     {
10940       *data->window = NULL;
10941       data->window = NULL;
10942     }
10943
10944   if (data->cursor)
10945     {
10946       gdk_cursor_unref (data->cursor);
10947       data->cursor = NULL;
10948     }
10949
10950   if (data->handler)
10951     {
10952       g_signal_handler_disconnect (widget, data->handler);
10953       data->handler = 0;
10954     }
10955
10956   g_free (data);
10957 }
10958
10959 static gint
10960 property_query_event (GtkWidget        *widget,
10961                       GdkEvent         *event,
10962                       struct PropertiesData *data)
10963 {
10964   GtkWidget *res_widget = NULL;
10965
10966   if (!data->in_query)
10967     return FALSE;
10968   
10969   if (event->type == GDK_BUTTON_RELEASE)
10970     {
10971       gtk_grab_remove (widget);
10972       gdk_display_pointer_ungrab (gtk_widget_get_display (widget),
10973                                   GDK_CURRENT_TIME);
10974       
10975       res_widget = find_widget_at_pointer (gtk_widget_get_display (widget));
10976       if (res_widget)
10977         {
10978           g_object_set_data (G_OBJECT (res_widget), "prop-editor-screen",
10979                              gtk_widget_get_screen (widget));
10980           create_prop_editor (G_OBJECT (res_widget), 0);
10981         }
10982
10983       data->in_query = FALSE;
10984     }
10985   return FALSE;
10986 }
10987
10988
10989 static void
10990 query_properties (GtkButton *button,
10991                   struct PropertiesData *data)
10992 {
10993   gint failure;
10994
10995   g_signal_connect (button, "event",
10996                     G_CALLBACK (property_query_event), data);
10997
10998
10999   if (!data->cursor)
11000     data->cursor = gdk_cursor_new_for_display (gtk_widget_get_display (GTK_WIDGET (button)),
11001                                                GDK_TARGET);
11002   
11003   failure = gdk_pointer_grab (GTK_WIDGET (button)->window,
11004                               TRUE,
11005                               GDK_BUTTON_RELEASE_MASK,
11006                               NULL,
11007                               data->cursor,
11008                               GDK_CURRENT_TIME);
11009
11010   gtk_grab_add (GTK_WIDGET (button));
11011
11012   data->in_query = TRUE;
11013 }
11014
11015 static void
11016 create_properties (GtkWidget *widget)
11017 {
11018   static GtkWidget *window = NULL;
11019   GtkWidget *button;
11020   GtkWidget *vbox;
11021   GtkWidget *label;
11022   struct PropertiesData *data;
11023
11024   data = g_new (struct PropertiesData, 1);
11025   data->window = &window;
11026   data->in_query = FALSE;
11027   data->cursor = NULL;
11028   data->handler = 0;
11029
11030   if (!window)
11031     {
11032       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
11033
11034       gtk_window_set_screen (GTK_WINDOW (window),
11035                              gtk_widget_get_screen (widget));      
11036
11037       data->handler = g_signal_connect (window, "destroy",
11038                                         G_CALLBACK (destroy_properties),
11039                                         data);
11040
11041       gtk_window_set_title (GTK_WINDOW (window), "test properties");
11042       gtk_container_set_border_width (GTK_CONTAINER (window), 10);
11043
11044       vbox = gtk_vbox_new (FALSE, 1);
11045       gtk_container_add (GTK_CONTAINER (window), vbox);
11046             
11047       label = gtk_label_new ("This is just a dumb test to test properties.\nIf you need a generic module, get GLE.");
11048       gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
11049       
11050       button = gtk_button_new_with_label ("Query properties");
11051       gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
11052       g_signal_connect (button, "clicked",
11053                         G_CALLBACK (query_properties),
11054                         data);
11055     }
11056
11057   if (!GTK_WIDGET_VISIBLE (window))
11058     gtk_widget_show_all (window);
11059   else
11060     gtk_widget_destroy (window);
11061   
11062 }
11063
11064
11065 /*
11066  * Color Preview
11067  */
11068
11069 static int color_idle = 0;
11070
11071 gint
11072 color_idle_func (GtkWidget *preview)
11073 {
11074   static int count = 1;
11075   guchar buf[768];
11076   int i, j, k;
11077
11078   for (i = 0; i < 256; i++)
11079     {
11080       for (j = 0, k = 0; j < 256; j++)
11081         {
11082           buf[k+0] = i + count;
11083           buf[k+1] = 0;
11084           buf[k+2] = j + count;
11085           k += 3;
11086         }
11087
11088       gtk_preview_draw_row (GTK_PREVIEW (preview), buf, 0, i, 256);
11089     }
11090
11091   count += 1;
11092
11093   gtk_widget_queue_draw (preview);
11094   gdk_window_process_updates (preview->window, TRUE);
11095
11096   return TRUE;
11097 }
11098
11099 static void
11100 color_preview_destroy (GtkWidget  *widget,
11101                        GtkWidget **window)
11102 {
11103   gtk_idle_remove (color_idle);
11104   color_idle = 0;
11105
11106   *window = NULL;
11107 }
11108
11109 void
11110 create_color_preview (GtkWidget *widget)
11111 {
11112   static GtkWidget *window = NULL;
11113   GtkWidget *preview;
11114   guchar buf[768];
11115   int i, j, k;
11116
11117   if (!window)
11118     {
11119       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
11120       
11121       gtk_window_set_screen (GTK_WINDOW (window),
11122                              gtk_widget_get_screen (widget));
11123
11124       g_signal_connect (window, "destroy",
11125                         G_CALLBACK (color_preview_destroy),
11126                         &window);
11127
11128       gtk_window_set_title (GTK_WINDOW (window), "test");
11129       gtk_container_set_border_width (GTK_CONTAINER (window), 10);
11130
11131       preview = gtk_preview_new (GTK_PREVIEW_COLOR);
11132       gtk_preview_size (GTK_PREVIEW (preview), 256, 256);
11133       gtk_container_add (GTK_CONTAINER (window), preview);
11134
11135       for (i = 0; i < 256; i++)
11136         {
11137           for (j = 0, k = 0; j < 256; j++)
11138             {
11139               buf[k+0] = i;
11140               buf[k+1] = 0;
11141               buf[k+2] = j;
11142               k += 3;
11143             }
11144
11145           gtk_preview_draw_row (GTK_PREVIEW (preview), buf, 0, i, 256);
11146         }
11147
11148       color_idle = gtk_idle_add ((GtkFunction) color_idle_func, preview);
11149     }
11150
11151   if (!GTK_WIDGET_VISIBLE (window))
11152     gtk_widget_show_all (window);
11153   else
11154     gtk_widget_destroy (window);
11155 }
11156
11157 /*
11158  * Gray Preview
11159  */
11160
11161 static int gray_idle = 0;
11162
11163 gint
11164 gray_idle_func (GtkWidget *preview)
11165 {
11166   static int count = 1;
11167   guchar buf[256];
11168   int i, j;
11169
11170   for (i = 0; i < 256; i++)
11171     {
11172       for (j = 0; j < 256; j++)
11173         buf[j] = i + j + count;
11174
11175       gtk_preview_draw_row (GTK_PREVIEW (preview), buf, 0, i, 256);
11176     }
11177
11178   count += 1;
11179
11180   gtk_widget_draw (preview, NULL);
11181
11182   return TRUE;
11183 }
11184
11185 static void
11186 gray_preview_destroy (GtkWidget  *widget,
11187                       GtkWidget **window)
11188 {
11189   gtk_idle_remove (gray_idle);
11190   gray_idle = 0;
11191
11192   *window = NULL;
11193 }
11194
11195 void
11196 create_gray_preview (GtkWidget *widget)
11197 {
11198   static GtkWidget *window = NULL;
11199   GtkWidget *preview;
11200   guchar buf[256];
11201   int i, j;
11202
11203   if (!window)
11204     {
11205       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
11206
11207       gtk_window_set_screen (GTK_WINDOW (window),
11208                              gtk_widget_get_screen (widget));
11209
11210       g_signal_connect (window, "destroy",
11211                         G_CALLBACK (gray_preview_destroy),
11212                         &window);
11213
11214       gtk_window_set_title (GTK_WINDOW (window), "test");
11215       gtk_container_set_border_width (GTK_CONTAINER (window), 10);
11216
11217       preview = gtk_preview_new (GTK_PREVIEW_GRAYSCALE);
11218       gtk_preview_size (GTK_PREVIEW (preview), 256, 256);
11219       gtk_container_add (GTK_CONTAINER (window), preview);
11220
11221       for (i = 0; i < 256; i++)
11222         {
11223           for (j = 0; j < 256; j++)
11224             buf[j] = i + j;
11225
11226           gtk_preview_draw_row (GTK_PREVIEW (preview), buf, 0, i, 256);
11227         }
11228
11229       gray_idle = gtk_idle_add ((GtkFunction) gray_idle_func, preview);
11230     }
11231
11232   if (!GTK_WIDGET_VISIBLE (window))
11233     gtk_widget_show_all (window);
11234   else
11235     gtk_widget_destroy (window);
11236 }
11237
11238
11239 /*
11240  * Selection Test
11241  */
11242
11243 void
11244 selection_test_received (GtkWidget *list, GtkSelectionData *data)
11245 {
11246   GdkAtom *atoms;
11247   GtkWidget *list_item;
11248   GList *item_list;
11249   int i, l;
11250
11251   if (data->length < 0)
11252     {
11253       g_print ("Selection retrieval failed\n");
11254       return;
11255     }
11256   if (data->type != GDK_SELECTION_TYPE_ATOM)
11257     {
11258       g_print ("Selection \"TARGETS\" was not returned as atoms!\n");
11259       return;
11260     }
11261
11262   /* Clear out any current list items */
11263
11264   gtk_list_clear_items (GTK_LIST(list), 0, -1);
11265
11266   /* Add new items to list */
11267
11268   atoms = (GdkAtom *)data->data;
11269
11270   item_list = NULL;
11271   l = data->length / sizeof (GdkAtom);
11272   for (i = 0; i < l; i++)
11273     {
11274       char *name;
11275       name = gdk_atom_name (atoms[i]);
11276       if (name != NULL)
11277         {
11278           list_item = gtk_list_item_new_with_label (name);
11279           g_free (name);
11280         }
11281       else
11282         list_item = gtk_list_item_new_with_label ("(bad atom)");
11283
11284       gtk_widget_show (list_item);
11285       item_list = g_list_append (item_list, list_item);
11286     }
11287
11288   gtk_list_append_items (GTK_LIST (list), item_list);
11289
11290   return;
11291 }
11292
11293 void
11294 selection_test_get_targets (GtkWidget *widget, GtkWidget *list)
11295 {
11296   static GdkAtom targets_atom = GDK_NONE;
11297
11298   if (targets_atom == GDK_NONE)
11299     targets_atom = gdk_atom_intern ("TARGETS", FALSE);
11300
11301   gtk_selection_convert (list, GDK_SELECTION_PRIMARY, targets_atom,
11302                          GDK_CURRENT_TIME);
11303 }
11304
11305 void
11306 create_selection_test (GtkWidget *widget)
11307 {
11308   static GtkWidget *window = NULL;
11309   GtkWidget *button;
11310   GtkWidget *vbox;
11311   GtkWidget *scrolled_win;
11312   GtkWidget *list;
11313   GtkWidget *label;
11314
11315   if (!window)
11316     {
11317       window = gtk_dialog_new ();
11318       
11319       gtk_window_set_screen (GTK_WINDOW (window),
11320                              gtk_widget_get_screen (widget));
11321
11322       g_signal_connect (window, "destroy",
11323                         G_CALLBACK (gtk_widget_destroyed),
11324                         &window);
11325
11326       gtk_window_set_title (GTK_WINDOW (window), "Selection Test");
11327       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
11328
11329       /* Create the list */
11330
11331       vbox = gtk_vbox_new (FALSE, 5);
11332       gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
11333       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), vbox,
11334                           TRUE, TRUE, 0);
11335
11336       label = gtk_label_new ("Gets available targets for current selection");
11337       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
11338
11339       scrolled_win = gtk_scrolled_window_new (NULL, NULL);
11340       gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
11341                                       GTK_POLICY_AUTOMATIC, 
11342                                       GTK_POLICY_AUTOMATIC);
11343       gtk_box_pack_start (GTK_BOX (vbox), scrolled_win, TRUE, TRUE, 0);
11344       gtk_widget_set_size_request (scrolled_win, 100, 200);
11345
11346       list = gtk_list_new ();
11347       gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_win), list);
11348
11349       g_signal_connect (list, "selection_received",
11350                         G_CALLBACK (selection_test_received), NULL);
11351
11352       /* .. And create some buttons */
11353       button = gtk_button_new_with_label ("Get Targets");
11354       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area),
11355                           button, TRUE, TRUE, 0);
11356
11357       g_signal_connect (button, "clicked",
11358                         G_CALLBACK (selection_test_get_targets), list);
11359
11360       button = gtk_button_new_with_label ("Quit");
11361       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area),
11362                           button, TRUE, TRUE, 0);
11363
11364       g_signal_connect_swapped (button, "clicked",
11365                                 G_CALLBACK (gtk_widget_destroy),
11366                                 window);
11367     }
11368
11369   if (!GTK_WIDGET_VISIBLE (window))
11370     gtk_widget_show_all (window);
11371   else
11372     gtk_widget_destroy (window);
11373 }
11374
11375 /*
11376  * Gamma Curve
11377  */
11378
11379 void
11380 create_gamma_curve (GtkWidget *widget)
11381 {
11382   static GtkWidget *window = NULL, *curve;
11383   static int count = 0;
11384   gfloat vec[256];
11385   gint max;
11386   gint i;
11387   
11388   if (!window)
11389     {
11390       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
11391       gtk_window_set_screen (GTK_WINDOW (window),
11392                              gtk_widget_get_screen (widget));
11393
11394       gtk_window_set_title (GTK_WINDOW (window), "test");
11395       gtk_container_set_border_width (GTK_CONTAINER (window), 10);
11396
11397       g_signal_connect (window, "destroy",
11398                         G_CALLBACK(gtk_widget_destroyed),
11399                         &window);
11400
11401       curve = gtk_gamma_curve_new ();
11402       gtk_container_add (GTK_CONTAINER (window), curve);
11403       gtk_widget_show (curve);
11404     }
11405
11406   max = 127 + (count % 2)*128;
11407   gtk_curve_set_range (GTK_CURVE (GTK_GAMMA_CURVE (curve)->curve),
11408                        0, max, 0, max);
11409   for (i = 0; i < max; ++i)
11410     vec[i] = (127 / sqrt (max)) * sqrt (i);
11411   gtk_curve_set_vector (GTK_CURVE (GTK_GAMMA_CURVE (curve)->curve),
11412                         max, vec);
11413
11414   if (!GTK_WIDGET_VISIBLE (window))
11415     gtk_widget_show (window);
11416   else if (count % 4 == 3)
11417     {
11418       gtk_widget_destroy (window);
11419       window = NULL;
11420     }
11421
11422   ++count;
11423 }
11424
11425 /*
11426  * Test scrolling
11427  */
11428
11429 static int scroll_test_pos = 0.0;
11430
11431 static gint
11432 scroll_test_expose (GtkWidget *widget, GdkEventExpose *event,
11433                     GtkAdjustment *adj)
11434 {
11435   gint i,j;
11436   gint imin, imax, jmin, jmax;
11437   
11438   imin = (event->area.x) / 10;
11439   imax = (event->area.x + event->area.width + 9) / 10;
11440
11441   jmin = ((int)adj->value + event->area.y) / 10;
11442   jmax = ((int)adj->value + event->area.y + event->area.height + 9) / 10;
11443
11444   gdk_window_clear_area (widget->window,
11445                          event->area.x, event->area.y,
11446                          event->area.width, event->area.height);
11447
11448   for (i=imin; i<imax; i++)
11449     for (j=jmin; j<jmax; j++)
11450       if ((i+j) % 2)
11451         gdk_draw_rectangle (widget->window, 
11452                             widget->style->black_gc,
11453                             TRUE,
11454                             10*i, 10*j - (int)adj->value, 1+i%10, 1+j%10);
11455
11456   return TRUE;
11457 }
11458
11459 static gint
11460 scroll_test_scroll (GtkWidget *widget, GdkEventScroll *event,
11461                     GtkAdjustment *adj)
11462 {
11463   gdouble new_value = adj->value + ((event->direction == GDK_SCROLL_UP) ?
11464                                     -adj->page_increment / 2:
11465                                     adj->page_increment / 2);
11466   new_value = CLAMP (new_value, adj->lower, adj->upper - adj->page_size);
11467   gtk_adjustment_set_value (adj, new_value);  
11468   
11469   return TRUE;
11470 }
11471
11472 static void
11473 scroll_test_configure (GtkWidget *widget, GdkEventConfigure *event,
11474                        GtkAdjustment *adj)
11475 {
11476   adj->page_increment = 0.9 * widget->allocation.height;
11477   adj->page_size = widget->allocation.height;
11478
11479   g_signal_emit_by_name (adj, "changed");
11480 }
11481
11482 static void
11483 scroll_test_adjustment_changed (GtkAdjustment *adj, GtkWidget *widget)
11484 {
11485   /* gint source_min = (int)adj->value - scroll_test_pos; */
11486   gint dy;
11487
11488   dy = scroll_test_pos - (int)adj->value;
11489   scroll_test_pos = adj->value;
11490
11491   if (!GTK_WIDGET_DRAWABLE (widget))
11492     return;
11493   gdk_window_scroll (widget->window, 0, dy);
11494   gdk_window_process_updates (widget->window, FALSE);
11495 }
11496
11497
11498 void
11499 create_scroll_test (GtkWidget *widget)
11500 {
11501   static GtkWidget *window = NULL;
11502   GtkWidget *hbox;
11503   GtkWidget *drawing_area;
11504   GtkWidget *scrollbar;
11505   GtkWidget *button;
11506   GtkAdjustment *adj;
11507   GdkGeometry geometry;
11508   GdkWindowHints geometry_mask;
11509
11510   if (!window)
11511     {
11512       window = gtk_dialog_new ();
11513
11514       gtk_window_set_screen (GTK_WINDOW (window),
11515                              gtk_widget_get_screen (widget));
11516
11517       g_signal_connect (window, "destroy",
11518                         G_CALLBACK (gtk_widget_destroyed),
11519                         &window);
11520
11521       gtk_window_set_title (GTK_WINDOW (window), "Scroll Test");
11522       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
11523
11524       hbox = gtk_hbox_new (FALSE, 0);
11525       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), hbox,
11526                           TRUE, TRUE, 0);
11527       gtk_widget_show (hbox);
11528
11529       drawing_area = gtk_drawing_area_new ();
11530       gtk_widget_set_size_request (drawing_area, 200, 200);
11531       gtk_box_pack_start (GTK_BOX (hbox), drawing_area, TRUE, TRUE, 0);
11532       gtk_widget_show (drawing_area);
11533
11534       gtk_widget_set_events (drawing_area, GDK_EXPOSURE_MASK | GDK_SCROLL_MASK);
11535
11536       adj = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 1000.0, 1.0, 180.0, 200.0));
11537       scroll_test_pos = 0.0;
11538
11539       scrollbar = gtk_vscrollbar_new (adj);
11540       gtk_box_pack_start (GTK_BOX (hbox), scrollbar, FALSE, FALSE, 0);
11541       gtk_widget_show (scrollbar);
11542
11543       g_signal_connect (drawing_area, "expose_event",
11544                         G_CALLBACK (scroll_test_expose), adj);
11545       g_signal_connect (drawing_area, "configure_event",
11546                         G_CALLBACK (scroll_test_configure), adj);
11547       g_signal_connect (drawing_area, "scroll_event",
11548                         G_CALLBACK (scroll_test_scroll), adj);
11549       
11550       g_signal_connect (adj, "value_changed",
11551                         G_CALLBACK (scroll_test_adjustment_changed),
11552                         drawing_area);
11553       
11554       /* .. And create some buttons */
11555
11556       button = gtk_button_new_with_label ("Quit");
11557       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area),
11558                           button, TRUE, TRUE, 0);
11559
11560       g_signal_connect_swapped (button, "clicked",
11561                                 G_CALLBACK (gtk_widget_destroy),
11562                                 window);
11563       gtk_widget_show (button);
11564
11565       /* Set up gridded geometry */
11566
11567       geometry_mask = GDK_HINT_MIN_SIZE | 
11568                        GDK_HINT_BASE_SIZE | 
11569                        GDK_HINT_RESIZE_INC;
11570
11571       geometry.min_width = 20;
11572       geometry.min_height = 20;
11573       geometry.base_width = 0;
11574       geometry.base_height = 0;
11575       geometry.width_inc = 10;
11576       geometry.height_inc = 10;
11577       
11578       gtk_window_set_geometry_hints (GTK_WINDOW (window),
11579                                drawing_area, &geometry, geometry_mask);
11580     }
11581
11582   if (!GTK_WIDGET_VISIBLE (window))
11583     gtk_widget_show (window);
11584   else
11585     gtk_widget_destroy (window);
11586 }
11587
11588 /*
11589  * Timeout Test
11590  */
11591
11592 static int timer = 0;
11593
11594 gint
11595 timeout_test (GtkWidget *label)
11596 {
11597   static int count = 0;
11598   static char buffer[32];
11599
11600   sprintf (buffer, "count: %d", ++count);
11601   gtk_label_set_text (GTK_LABEL (label), buffer);
11602
11603   return TRUE;
11604 }
11605
11606 void
11607 start_timeout_test (GtkWidget *widget,
11608                     GtkWidget *label)
11609 {
11610   if (!timer)
11611     {
11612       timer = gtk_timeout_add (100, (GtkFunction) timeout_test, label);
11613     }
11614 }
11615
11616 void
11617 stop_timeout_test (GtkWidget *widget,
11618                    gpointer   data)
11619 {
11620   if (timer)
11621     {
11622       gtk_timeout_remove (timer);
11623       timer = 0;
11624     }
11625 }
11626
11627 void
11628 destroy_timeout_test (GtkWidget  *widget,
11629                       GtkWidget **window)
11630 {
11631   stop_timeout_test (NULL, NULL);
11632
11633   *window = NULL;
11634 }
11635
11636 void
11637 create_timeout_test (GtkWidget *widget)
11638 {
11639   static GtkWidget *window = NULL;
11640   GtkWidget *button;
11641   GtkWidget *label;
11642
11643   if (!window)
11644     {
11645       window = gtk_dialog_new ();
11646
11647       gtk_window_set_screen (GTK_WINDOW (window),
11648                              gtk_widget_get_screen (widget));
11649
11650       g_signal_connect (window, "destroy",
11651                         G_CALLBACK (destroy_timeout_test),
11652                         &window);
11653
11654       gtk_window_set_title (GTK_WINDOW (window), "Timeout Test");
11655       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
11656
11657       label = gtk_label_new ("count: 0");
11658       gtk_misc_set_padding (GTK_MISC (label), 10, 10);
11659       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
11660                           label, TRUE, TRUE, 0);
11661       gtk_widget_show (label);
11662
11663       button = gtk_button_new_with_label ("close");
11664       g_signal_connect_swapped (button, "clicked",
11665                                 G_CALLBACK (gtk_widget_destroy),
11666                                 window);
11667       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
11668       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
11669                           button, TRUE, TRUE, 0);
11670       gtk_widget_grab_default (button);
11671       gtk_widget_show (button);
11672
11673       button = gtk_button_new_with_label ("start");
11674       g_signal_connect (button, "clicked",
11675                         G_CALLBACK(start_timeout_test),
11676                         label);
11677       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
11678       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
11679                           button, TRUE, TRUE, 0);
11680       gtk_widget_show (button);
11681
11682       button = gtk_button_new_with_label ("stop");
11683       g_signal_connect (button, "clicked",
11684                         G_CALLBACK (stop_timeout_test),
11685                         NULL);
11686       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
11687       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
11688                           button, TRUE, TRUE, 0);
11689       gtk_widget_show (button);
11690     }
11691
11692   if (!GTK_WIDGET_VISIBLE (window))
11693     gtk_widget_show (window);
11694   else
11695     gtk_widget_destroy (window);
11696 }
11697
11698 /*
11699  * Idle Test
11700  */
11701
11702 static int idle_id = 0;
11703
11704 static gint
11705 idle_test (GtkWidget *label)
11706 {
11707   static int count = 0;
11708   static char buffer[32];
11709
11710   sprintf (buffer, "count: %d", ++count);
11711   gtk_label_set_text (GTK_LABEL (label), buffer);
11712
11713   return TRUE;
11714 }
11715
11716 static void
11717 start_idle_test (GtkWidget *widget,
11718                  GtkWidget *label)
11719 {
11720   if (!idle_id)
11721     {
11722       idle_id = gtk_idle_add ((GtkFunction) idle_test, label);
11723     }
11724 }
11725
11726 static void
11727 stop_idle_test (GtkWidget *widget,
11728                 gpointer   data)
11729 {
11730   if (idle_id)
11731     {
11732       gtk_idle_remove (idle_id);
11733       idle_id = 0;
11734     }
11735 }
11736
11737 static void
11738 destroy_idle_test (GtkWidget  *widget,
11739                    GtkWidget **window)
11740 {
11741   stop_idle_test (NULL, NULL);
11742
11743   *window = NULL;
11744 }
11745
11746 static void
11747 toggle_idle_container (GObject *button,
11748                        GtkContainer *container)
11749 {
11750   gtk_container_set_resize_mode (container, GPOINTER_TO_INT (g_object_get_data (button, "user_data")));
11751 }
11752
11753 static void
11754 create_idle_test (GtkWidget *widget)
11755 {
11756   static GtkWidget *window = NULL;
11757   GtkWidget *button;
11758   GtkWidget *label;
11759   GtkWidget *container;
11760
11761   if (!window)
11762     {
11763       GtkWidget *button2;
11764       GtkWidget *frame;
11765       GtkWidget *box;
11766
11767       window = gtk_dialog_new ();
11768
11769       gtk_window_set_screen (GTK_WINDOW (window),
11770                              gtk_widget_get_screen (widget));
11771
11772       g_signal_connect (window, "destroy",
11773                         G_CALLBACK (destroy_idle_test),
11774                         &window);
11775
11776       gtk_window_set_title (GTK_WINDOW (window), "Idle Test");
11777       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
11778
11779       label = gtk_label_new ("count: 0");
11780       gtk_misc_set_padding (GTK_MISC (label), 10, 10);
11781       gtk_widget_show (label);
11782       
11783       container =
11784         gtk_widget_new (GTK_TYPE_HBOX,
11785                         "visible", TRUE,
11786                         /* "GtkContainer::child", gtk_widget_new (GTK_TYPE_HBOX,
11787                          * "GtkWidget::visible", TRUE,
11788                          */
11789                          "child", label,
11790                         /* NULL), */
11791                         NULL);
11792       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), 
11793                           container, TRUE, TRUE, 0);
11794
11795       frame =
11796         gtk_widget_new (GTK_TYPE_FRAME,
11797                         "border_width", 5,
11798                         "label", "Label Container",
11799                         "visible", TRUE,
11800                         "parent", GTK_DIALOG (window)->vbox,
11801                         NULL);
11802       box =
11803         gtk_widget_new (GTK_TYPE_VBOX,
11804                         "visible", TRUE,
11805                         "parent", frame,
11806                         NULL);
11807       button =
11808         g_object_connect (gtk_widget_new (GTK_TYPE_RADIO_BUTTON,
11809                                           "label", "Resize-Parent",
11810                                           "user_data", (void*)GTK_RESIZE_PARENT,
11811                                           "visible", TRUE,
11812                                           "parent", box,
11813                                           NULL),
11814                           "signal::clicked", toggle_idle_container, container,
11815                           NULL);
11816       button = gtk_widget_new (GTK_TYPE_RADIO_BUTTON,
11817                                "label", "Resize-Queue",
11818                                "user_data", (void*)GTK_RESIZE_QUEUE,
11819                                "group", button,
11820                                "visible", TRUE,
11821                                "parent", box,
11822                                NULL);
11823       g_object_connect (button,
11824                         "signal::clicked", toggle_idle_container, container,
11825                         NULL);
11826       button2 = gtk_widget_new (GTK_TYPE_RADIO_BUTTON,
11827                                 "label", "Resize-Immediate",
11828                                 "user_data", (void*)GTK_RESIZE_IMMEDIATE,
11829                                 NULL);
11830       g_object_connect (button2,
11831                         "signal::clicked", toggle_idle_container, container,
11832                         NULL);
11833       g_object_set (button2,
11834                     "group", button,
11835                     "visible", TRUE,
11836                     "parent", box,
11837                     NULL);
11838
11839       button = gtk_button_new_with_label ("close");
11840       g_signal_connect_swapped (button, "clicked",
11841                                 G_CALLBACK (gtk_widget_destroy),
11842                                 window);
11843       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
11844       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
11845                           button, TRUE, TRUE, 0);
11846       gtk_widget_grab_default (button);
11847       gtk_widget_show (button);
11848
11849       button = gtk_button_new_with_label ("start");
11850       g_signal_connect (button, "clicked",
11851                         G_CALLBACK (start_idle_test),
11852                         label);
11853       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
11854       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
11855                           button, TRUE, TRUE, 0);
11856       gtk_widget_show (button);
11857
11858       button = gtk_button_new_with_label ("stop");
11859       g_signal_connect (button, "clicked",
11860                         G_CALLBACK (stop_idle_test),
11861                         NULL);
11862       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
11863       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
11864                           button, TRUE, TRUE, 0);
11865       gtk_widget_show (button);
11866     }
11867
11868   if (!GTK_WIDGET_VISIBLE (window))
11869     gtk_widget_show (window);
11870   else
11871     gtk_widget_destroy (window);
11872 }
11873
11874 /*
11875  * rc file test
11876  */
11877
11878 void
11879 reload_all_rc_files (void)
11880 {
11881   static GdkAtom atom_rcfiles = GDK_NONE;
11882
11883   GdkEvent *send_event = gdk_event_new (GDK_CLIENT_EVENT);
11884   int i;
11885   
11886   if (!atom_rcfiles)
11887     atom_rcfiles = gdk_atom_intern("_GTK_READ_RCFILES", FALSE);
11888
11889   for(i = 0; i < 5; i++)
11890     send_event->client.data.l[i] = 0;
11891   send_event->client.data_format = 32;
11892   send_event->client.message_type = atom_rcfiles;
11893   gdk_event_send_clientmessage_toall (send_event);
11894
11895   gdk_event_free (send_event);
11896 }
11897
11898 void
11899 create_rc_file (GtkWidget *widget)
11900 {
11901   static GtkWidget *window = NULL;
11902   GtkWidget *button;
11903   GtkWidget *frame;
11904   GtkWidget *vbox;
11905   GtkWidget *label;
11906
11907   if (!window)
11908     {
11909       window = gtk_dialog_new ();
11910
11911       gtk_window_set_screen (GTK_WINDOW (window),
11912                              gtk_widget_get_screen (widget));
11913
11914       g_signal_connect (window, "destroy",
11915                         G_CALLBACK (gtk_widget_destroyed),
11916                         &window);
11917
11918       frame = gtk_aspect_frame_new ("Testing RC file prioritization", 0.5, 0.5, 0.0, TRUE);
11919       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), frame, FALSE, FALSE, 0);
11920
11921       vbox = gtk_vbox_new (FALSE, 0);
11922       gtk_container_add (GTK_CONTAINER (frame), vbox);
11923       
11924       label = gtk_label_new ("This label should be red");
11925       gtk_widget_set_name (label, "testgtk-red-label");
11926       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
11927
11928       label = gtk_label_new ("This label should be green");
11929       gtk_widget_set_name (label, "testgtk-green-label");
11930       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
11931
11932       label = gtk_label_new ("This label should be blue");
11933       gtk_widget_set_name (label, "testgtk-blue-label");
11934       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
11935
11936       gtk_window_set_title (GTK_WINDOW (window), "Reload Rc file");
11937       gtk_container_set_border_width (GTK_CONTAINER (window), 0);
11938
11939       button = gtk_button_new_with_label ("Reload");
11940       g_signal_connect (button, "clicked",
11941                         G_CALLBACK (gtk_rc_reparse_all), NULL);
11942       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
11943       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
11944                           button, TRUE, TRUE, 0);
11945       gtk_widget_grab_default (button);
11946
11947       button = gtk_button_new_with_label ("Reload All");
11948       g_signal_connect (button, "clicked",
11949                         G_CALLBACK (reload_all_rc_files), NULL);
11950       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
11951       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
11952                           button, TRUE, TRUE, 0);
11953
11954       button = gtk_button_new_with_label ("Close");
11955       g_signal_connect_swapped (button, "clicked",
11956                                 G_CALLBACK (gtk_widget_destroy),
11957                                 window);
11958       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
11959       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
11960                           button, TRUE, TRUE, 0);
11961     }
11962
11963   if (!GTK_WIDGET_VISIBLE (window))
11964     gtk_widget_show_all (window);
11965   else
11966     gtk_widget_destroy (window);
11967 }
11968
11969 /*
11970  * Test of recursive mainloop
11971  */
11972
11973 void
11974 mainloop_destroyed (GtkWidget *w, GtkWidget **window)
11975 {
11976   *window = NULL;
11977   gtk_main_quit ();
11978 }
11979
11980 void
11981 create_mainloop (GtkWidget *widget)
11982 {
11983   static GtkWidget *window = NULL;
11984   GtkWidget *label;
11985   GtkWidget *button;
11986
11987   if (!window)
11988     {
11989       window = gtk_dialog_new ();
11990
11991       gtk_window_set_screen (GTK_WINDOW (window),
11992                              gtk_widget_get_screen (widget));
11993
11994       gtk_window_set_title (GTK_WINDOW (window), "Test Main Loop");
11995
11996       g_signal_connect (window, "destroy",
11997                         G_CALLBACK (mainloop_destroyed),
11998                         &window);
11999
12000       label = gtk_label_new ("In recursive main loop...");
12001       gtk_misc_set_padding (GTK_MISC(label), 20, 20);
12002
12003       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), label,
12004                           TRUE, TRUE, 0);
12005       gtk_widget_show (label);
12006
12007       button = gtk_button_new_with_label ("Leave");
12008       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), button, 
12009                           FALSE, TRUE, 0);
12010
12011       g_signal_connect_swapped (button, "clicked",
12012                                 G_CALLBACK (gtk_widget_destroy),
12013                                 window);
12014
12015       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
12016       gtk_widget_grab_default (button);
12017
12018       gtk_widget_show (button);
12019     }
12020
12021   if (!GTK_WIDGET_VISIBLE (window))
12022     {
12023       gtk_widget_show (window);
12024
12025       g_print ("create_mainloop: start\n");
12026       gtk_main ();
12027       g_print ("create_mainloop: done\n");
12028     }
12029   else
12030     gtk_widget_destroy (window);
12031 }
12032
12033 gboolean
12034 layout_expose_handler (GtkWidget *widget, GdkEventExpose *event)
12035 {
12036   GtkLayout *layout;
12037
12038   gint i,j;
12039   gint imin, imax, jmin, jmax;
12040
12041   layout = GTK_LAYOUT (widget);
12042
12043   if (event->window != layout->bin_window)
12044     return FALSE;
12045   
12046   imin = (event->area.x) / 10;
12047   imax = (event->area.x + event->area.width + 9) / 10;
12048
12049   jmin = (event->area.y) / 10;
12050   jmax = (event->area.y + event->area.height + 9) / 10;
12051
12052   for (i=imin; i<imax; i++)
12053     for (j=jmin; j<jmax; j++)
12054       if ((i+j) % 2)
12055         gdk_draw_rectangle (layout->bin_window,
12056                             widget->style->black_gc,
12057                             TRUE,
12058                             10*i, 10*j, 
12059                             1+i%10, 1+j%10);
12060   
12061   return FALSE;
12062 }
12063
12064 void create_layout (GtkWidget *widget)
12065 {
12066   static GtkWidget *window = NULL;
12067   GtkWidget *layout;
12068   GtkWidget *scrolledwindow;
12069   GtkWidget *button;
12070
12071   if (!window)
12072     {
12073       gchar buf[16];
12074
12075       gint i, j;
12076       
12077       window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
12078       gtk_window_set_screen (GTK_WINDOW (window),
12079                              gtk_widget_get_screen (widget));
12080
12081       g_signal_connect (window, "destroy",
12082                         G_CALLBACK (gtk_widget_destroyed),
12083                         &window);
12084
12085       gtk_window_set_title (GTK_WINDOW (window), "Layout");
12086       gtk_widget_set_size_request (window, 200, 200);
12087
12088       scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
12089       gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolledwindow),
12090                                            GTK_SHADOW_IN);
12091       gtk_scrolled_window_set_placement (GTK_SCROLLED_WINDOW (scrolledwindow),
12092                                          GTK_CORNER_TOP_RIGHT);
12093
12094       gtk_container_add (GTK_CONTAINER (window), scrolledwindow);
12095       
12096       layout = gtk_layout_new (NULL, NULL);
12097       gtk_container_add (GTK_CONTAINER (scrolledwindow), layout);
12098
12099       /* We set step sizes here since GtkLayout does not set
12100        * them itself.
12101        */
12102       GTK_LAYOUT (layout)->hadjustment->step_increment = 10.0;
12103       GTK_LAYOUT (layout)->vadjustment->step_increment = 10.0;
12104       
12105       gtk_widget_set_events (layout, GDK_EXPOSURE_MASK);
12106       g_signal_connect (layout, "expose_event",
12107                         G_CALLBACK (layout_expose_handler), NULL);
12108       
12109       gtk_layout_set_size (GTK_LAYOUT (layout), 1600, 128000);
12110       
12111       for (i=0 ; i < 16 ; i++)
12112         for (j=0 ; j < 16 ; j++)
12113           {
12114             sprintf(buf, "Button %d, %d", i, j);
12115             if ((i + j) % 2)
12116               button = gtk_button_new_with_label (buf);
12117             else
12118               button = gtk_label_new (buf);
12119
12120             gtk_layout_put (GTK_LAYOUT (layout), button,
12121                             j*100, i*100);
12122           }
12123
12124       for (i=16; i < 1280; i++)
12125         {
12126           sprintf(buf, "Button %d, %d", i, 0);
12127           if (i % 2)
12128             button = gtk_button_new_with_label (buf);
12129           else
12130             button = gtk_label_new (buf);
12131
12132           gtk_layout_put (GTK_LAYOUT (layout), button,
12133                           0, i*100);
12134         }
12135     }
12136
12137   if (!GTK_WIDGET_VISIBLE (window))
12138     gtk_widget_show_all (window);
12139   else
12140     gtk_widget_destroy (window);
12141 }
12142
12143 void
12144 create_styles (GtkWidget *widget)
12145 {
12146   static GtkWidget *window = NULL;
12147   GtkWidget *label;
12148   GtkWidget *button;
12149   GtkWidget *entry;
12150   GtkWidget *vbox;
12151   static GdkColor red =    { 0, 0xffff, 0,      0      };
12152   static GdkColor green =  { 0, 0,      0xffff, 0      };
12153   static GdkColor blue =   { 0, 0,      0,      0xffff };
12154   static GdkColor yellow = { 0, 0xffff, 0xffff, 0      };
12155   static GdkColor cyan =   { 0, 0     , 0xffff, 0xffff };
12156   PangoFontDescription *font_desc;
12157
12158   GtkRcStyle *rc_style;
12159
12160   if (!window)
12161     {
12162       window = gtk_dialog_new ();
12163       gtk_window_set_screen (GTK_WINDOW (window),
12164                              gtk_widget_get_screen (widget));
12165      
12166       g_signal_connect (window, "destroy",
12167                         G_CALLBACK (gtk_widget_destroyed),
12168                         &window);
12169
12170       
12171       button = gtk_button_new_with_label ("Close");
12172       g_signal_connect_swapped (button, "clicked",
12173                                 G_CALLBACK (gtk_widget_destroy),
12174                                 window);
12175       GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
12176       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->action_area), 
12177                           button, TRUE, TRUE, 0);
12178       gtk_widget_show (button);
12179
12180       vbox = gtk_vbox_new (FALSE, 5);
12181       gtk_container_set_border_width (GTK_CONTAINER (vbox), 10);
12182       gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), vbox, FALSE, FALSE, 0);
12183       
12184       label = gtk_label_new ("Font:");
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       font_desc = pango_font_description_from_string ("Helvetica,Sans Oblique 18");
12189
12190       button = gtk_button_new_with_label ("Some Text");
12191       gtk_widget_modify_font (GTK_BIN (button)->child, font_desc);
12192       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
12193
12194       label = gtk_label_new ("Foreground:");
12195       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
12196       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
12197
12198       button = gtk_button_new_with_label ("Some Text");
12199       gtk_widget_modify_fg (GTK_BIN (button)->child, GTK_STATE_NORMAL, &red);
12200       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
12201
12202       label = gtk_label_new ("Background:");
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       gtk_widget_modify_bg (button, GTK_STATE_NORMAL, &green);
12208       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
12209
12210       label = gtk_label_new ("Text:");
12211       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
12212       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
12213
12214       entry = gtk_entry_new ();
12215       gtk_entry_set_text (GTK_ENTRY (entry), "Some Text");
12216       gtk_widget_modify_text (entry, GTK_STATE_NORMAL, &blue);
12217       gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
12218
12219       label = gtk_label_new ("Base:");
12220       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
12221       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
12222
12223       entry = gtk_entry_new ();
12224       gtk_entry_set_text (GTK_ENTRY (entry), "Some Text");
12225       gtk_widget_modify_base (entry, GTK_STATE_NORMAL, &yellow);
12226       gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
12227
12228       label = gtk_label_new ("Multiple:");
12229       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
12230       gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
12231
12232       button = gtk_button_new_with_label ("Some Text");
12233
12234       rc_style = gtk_rc_style_new ();
12235
12236       rc_style->font_desc = pango_font_description_copy (font_desc);
12237       rc_style->color_flags[GTK_STATE_NORMAL] = GTK_RC_FG | GTK_RC_BG;
12238       rc_style->color_flags[GTK_STATE_PRELIGHT] = GTK_RC_FG | GTK_RC_BG;
12239       rc_style->color_flags[GTK_STATE_ACTIVE] = GTK_RC_FG | GTK_RC_BG;
12240       rc_style->fg[GTK_STATE_NORMAL] = yellow;
12241       rc_style->bg[GTK_STATE_NORMAL] = blue;
12242       rc_style->fg[GTK_STATE_PRELIGHT] = blue;
12243       rc_style->bg[GTK_STATE_PRELIGHT] = yellow;
12244       rc_style->fg[GTK_STATE_ACTIVE] = red;
12245       rc_style->bg[GTK_STATE_ACTIVE] = cyan;
12246       rc_style->xthickness = 5;
12247       rc_style->ythickness = 5;
12248
12249       gtk_widget_modify_style (button, rc_style);
12250       gtk_widget_modify_style (GTK_BIN (button)->child, rc_style);
12251
12252       g_object_unref (rc_style);
12253       
12254       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
12255     }
12256   
12257   if (!GTK_WIDGET_VISIBLE (window))
12258     gtk_widget_show_all (window);
12259   else
12260     gtk_widget_destroy (window);
12261 }
12262
12263 /*
12264  * Main Window and Exit
12265  */
12266
12267 void
12268 do_exit (GtkWidget *widget, GtkWidget *window)
12269 {
12270   gtk_widget_destroy (window);
12271   gtk_main_quit ();
12272 }
12273
12274 struct {
12275   char *label;
12276   void (*func) (GtkWidget *widget);
12277   gboolean do_not_benchmark;
12278 } buttons[] =
12279 {
12280   { "big windows", create_big_windows },
12281   { "button box", create_button_box },
12282   { "buttons", create_buttons },
12283   { "check buttons", create_check_buttons },
12284   { "clist", create_clist},
12285   { "color selection", create_color_selection },
12286   { "ctree", create_ctree },
12287   { "cursors", create_cursors },
12288   { "dialog", create_dialog },
12289   { "display & screen", create_display_screen },
12290   { "entry", create_entry },
12291   { "event watcher", create_event_watcher },
12292   { "file selection", create_file_selection },
12293   { "flipping", create_flipping },
12294   { "focus", create_focus },
12295   { "font selection", create_font_selection },
12296   { "gamma curve", create_gamma_curve, TRUE },
12297   { "gridded geometry", create_gridded_geometry, TRUE },
12298   { "handle box", create_handle_box },
12299   { "image from drawable", create_get_image },
12300   { "image", create_image },
12301   { "item factory", create_item_factory },
12302   { "key lookup", create_key_lookup },
12303   { "labels", create_labels },
12304   { "layout", create_layout },
12305   { "list", create_list },
12306   { "menus", create_menus },
12307   { "message dialog", create_message_dialog },
12308   { "modal window", create_modal_window, TRUE },
12309   { "notebook", create_notebook },
12310   { "panes", create_panes },
12311   { "paned keyboard", create_paned_keyboard_navigation },
12312   { "pixmap", create_pixmap },
12313   { "preview color", create_color_preview, TRUE },
12314   { "preview gray", create_gray_preview, TRUE },
12315   { "progress bar", create_progress_bar },
12316   { "properties", create_properties },
12317   { "radio buttons", create_radio_buttons },
12318   { "range controls", create_range_controls },
12319   { "rc file", create_rc_file },
12320   { "reparent", create_reparent },
12321   { "resize grips", create_resize_grips },
12322   { "rulers", create_rulers },
12323   { "saved position", create_saved_position },
12324   { "scrolled windows", create_scrolled_windows },
12325   { "shapes", create_shapes },
12326   { "size groups", create_size_groups },
12327   { "spinbutton", create_spins },
12328   { "statusbar", create_statusbar },
12329   { "styles", create_styles },
12330   { "test idle", create_idle_test },
12331   { "test mainloop", create_mainloop, TRUE },
12332   { "test scrolling", create_scroll_test },
12333   { "test selection", create_selection_test },
12334   { "test timeout", create_timeout_test },
12335   { "text", create_text },
12336   { "toggle buttons", create_toggle_buttons },
12337   { "toolbar", create_toolbar },
12338   { "tooltips", create_tooltips },
12339   { "tree", create_tree_mode_window},
12340   { "WM hints", create_wmhints },
12341   { "window sizing", create_window_sizing },
12342   { "window states", create_window_states }
12343 };
12344 int nbuttons = sizeof (buttons) / sizeof (buttons[0]);
12345
12346 void
12347 create_main_window (void)
12348 {
12349   GtkWidget *window;
12350   GtkWidget *box1;
12351   GtkWidget *box2;
12352   GtkWidget *scrolled_window;
12353   GtkWidget *button;
12354   GtkWidget *label;
12355   gchar buffer[64];
12356   GtkWidget *separator;
12357   GdkGeometry geometry;
12358   int i;
12359
12360   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
12361   gtk_widget_set_name (window, "main window");
12362   gtk_widget_set_uposition (window, 20, 20);
12363   gtk_window_set_default_size (GTK_WINDOW (window), -1, 400);
12364
12365   geometry.min_width = -1;
12366   geometry.min_height = -1;
12367   geometry.max_width = -1;
12368   geometry.max_height = G_MAXSHORT;
12369   gtk_window_set_geometry_hints (GTK_WINDOW (window), NULL,
12370                                  &geometry,
12371                                  GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE);
12372
12373   g_signal_connect (window, "destroy",
12374                     G_CALLBACK (gtk_main_quit),
12375                     NULL);
12376   g_signal_connect (window, "delete-event",
12377                     G_CALLBACK (gtk_false),
12378                     NULL);
12379
12380   box1 = gtk_vbox_new (FALSE, 0);
12381   gtk_container_add (GTK_CONTAINER (window), box1);
12382
12383   if (gtk_micro_version > 0)
12384     sprintf (buffer,
12385              "Gtk+ v%d.%d.%d",
12386              gtk_major_version,
12387              gtk_minor_version,
12388              gtk_micro_version);
12389   else
12390     sprintf (buffer,
12391              "Gtk+ v%d.%d",
12392              gtk_major_version,
12393              gtk_minor_version);
12394
12395   label = gtk_label_new (buffer);
12396   gtk_box_pack_start (GTK_BOX (box1), label, FALSE, FALSE, 0);
12397   gtk_widget_set_name (label, "testgtk-version-label");
12398
12399   scrolled_window = gtk_scrolled_window_new (NULL, NULL);
12400   gtk_container_set_border_width (GTK_CONTAINER (scrolled_window), 10);
12401   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
12402                                   GTK_POLICY_NEVER, 
12403                                   GTK_POLICY_AUTOMATIC);
12404   gtk_box_pack_start (GTK_BOX (box1), scrolled_window, TRUE, TRUE, 0);
12405
12406   box2 = gtk_vbox_new (FALSE, 0);
12407   gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
12408   gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled_window), box2);
12409   gtk_container_set_focus_vadjustment (GTK_CONTAINER (box2),
12410                                        gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (scrolled_window)));
12411   gtk_widget_show (box2);
12412
12413   for (i = 0; i < nbuttons; i++)
12414     {
12415       button = gtk_button_new_with_label (buttons[i].label);
12416       if (buttons[i].func)
12417         g_signal_connect (button, 
12418                           "clicked", 
12419                           G_CALLBACK(buttons[i].func),
12420                           NULL);
12421       else
12422         gtk_widget_set_sensitive (button, FALSE);
12423       gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
12424     }
12425
12426   separator = gtk_hseparator_new ();
12427   gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
12428
12429   box2 = gtk_vbox_new (FALSE, 10);
12430   gtk_container_set_border_width (GTK_CONTAINER (box2), 10);
12431   gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
12432
12433   button = gtk_button_new_with_mnemonic ("_Close");
12434   g_signal_connect (button, "clicked",
12435                     G_CALLBACK (do_exit),
12436                     window);
12437   gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
12438   GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
12439   gtk_widget_grab_default (button);
12440
12441   gtk_widget_show_all (window);
12442 }
12443
12444 static void
12445 test_init ()
12446 {
12447   if (g_file_test ("../gdk-pixbuf/libpixbufloader-pnm.la",
12448                    G_FILE_TEST_EXISTS))
12449     {
12450       putenv ("GDK_PIXBUF_MODULE_FILE=../gdk-pixbuf/gdk-pixbuf.loaders");
12451       putenv ("GTK_IM_MODULE_FILE=../modules/input/gtk.immodules");
12452     }
12453 }
12454
12455 static char *
12456 pad (const char *str, int to)
12457 {
12458   static char buf[256];
12459   int len = strlen (str);
12460   int i;
12461
12462   for (i = 0; i < to; i++)
12463     buf[i] = ' ';
12464
12465   buf[to] = '\0';
12466
12467   memcpy (buf, str, len);
12468
12469   return buf;
12470 }
12471
12472 static void
12473 bench_iteration (GtkWidget *widget, void (* fn) (GtkWidget *widget))
12474 {
12475   fn (widget); /* on */
12476   while (g_main_context_iteration (NULL, FALSE));
12477   fn (widget); /* off */
12478   while (g_main_context_iteration (NULL, FALSE));
12479 }
12480
12481 void
12482 do_real_bench (GtkWidget *widget, void (* fn) (GtkWidget *widget), char *name, int num)
12483 {
12484   GTimeVal tv0, tv1;
12485   double dt_first;
12486   double dt;
12487   int n;
12488   static gboolean printed_headers = FALSE;
12489
12490   if (!printed_headers) {
12491     g_print ("Test                 Iters      First      Other\n");
12492     g_print ("-------------------- ----- ---------- ----------\n");
12493     printed_headers = TRUE;
12494   }
12495
12496   g_get_current_time (&tv0);
12497   bench_iteration (widget, fn); 
12498   g_get_current_time (&tv1);
12499
12500   dt_first = ((double)tv1.tv_sec - tv0.tv_sec) * 1000.0
12501         + (tv1.tv_usec - tv0.tv_usec) / 1000.0;
12502
12503   g_get_current_time (&tv0);
12504   for (n = 0; n < num - 1; n++)
12505     bench_iteration (widget, fn); 
12506   g_get_current_time (&tv1);
12507   dt = ((double)tv1.tv_sec - tv0.tv_sec) * 1000.0
12508         + (tv1.tv_usec - tv0.tv_usec) / 1000.0;
12509
12510   g_print ("%s %5d ", pad (name, 20), num);
12511   if (num > 1)
12512     g_print ("%10.1f %10.1f\n", dt_first, dt/(num-1));
12513   else
12514     g_print ("%10.1f\n", dt_first);
12515 }
12516
12517 void
12518 do_bench (char* what, int num)
12519 {
12520   int i;
12521   GtkWidget *widget;
12522   void (* fn) (GtkWidget *widget);
12523   fn = NULL;
12524   widget = gtk_window_new (GTK_WINDOW_TOPLEVEL);
12525
12526   if (g_ascii_strcasecmp (what, "ALL") == 0)
12527     {
12528       for (i = 0; i < nbuttons; i++)
12529         {
12530           if (!buttons[i].do_not_benchmark)
12531             do_real_bench (widget, buttons[i].func, buttons[i].label, num);
12532         }
12533
12534       return;
12535     }
12536   else
12537     {
12538       for (i = 0; i < nbuttons; i++)
12539         {
12540           if (strcmp (buttons[i].label, what) == 0)
12541             {
12542               fn = buttons[i].func;
12543               break;
12544             }
12545         }
12546       
12547       if (!fn)
12548         g_print ("Can't bench: \"%s\" not found.\n", what);
12549       else
12550         do_real_bench (widget, fn, buttons[i].label, num);
12551     }
12552 }
12553
12554 void 
12555 usage (void)
12556 {
12557   fprintf (stderr, "Usage: testgtk [--bench ALL|<bench>[:<count>]]\n");
12558   exit (1);
12559 }
12560
12561 int
12562 main (int argc, char *argv[])
12563 {
12564   GtkBindingSet *binding_set;
12565   int i;
12566   gboolean done_benchmarks = FALSE;
12567
12568   srand (time (NULL));
12569
12570   test_init ();
12571
12572   /* Check to see if we are being run from the correct
12573    * directory.
12574    */
12575   if (file_exists ("testgtkrc"))
12576     gtk_rc_add_default_file ("testgtkrc");
12577
12578   g_set_application_name ("GTK+ Test Program");
12579
12580   gtk_init (&argc, &argv);
12581
12582   /*  benchmarking
12583    */
12584   for (i = 1; i < argc; i++)
12585     {
12586       if (strncmp (argv[i], "--bench", strlen("--bench")) == 0)
12587         {
12588           int num = 1;
12589           char *nextarg;
12590           char *what;
12591           char *count;
12592           
12593           nextarg = strchr (argv[i], '=');
12594           if (nextarg)
12595             nextarg++;
12596           else
12597             {
12598               i++;
12599               if (i == argc)
12600                 usage ();
12601               nextarg = argv[i];
12602             }
12603
12604           count = strchr (nextarg, ':');
12605           if (count)
12606             {
12607               what = g_strndup (nextarg, count - nextarg);
12608               count++;
12609               num = atoi (count);
12610               if (num <= 0)
12611                 usage ();
12612             }
12613           else
12614             what = g_strdup (nextarg);
12615
12616           do_bench (what, num ? num : 1);
12617           done_benchmarks = TRUE;
12618         }
12619       else
12620         usage ();
12621     }
12622   if (done_benchmarks)
12623     return 0;
12624
12625   /* bindings test
12626    */
12627   binding_set = gtk_binding_set_by_class (gtk_type_class (GTK_TYPE_WIDGET));
12628   gtk_binding_entry_add_signal (binding_set,
12629                                 '9', GDK_CONTROL_MASK | GDK_RELEASE_MASK,
12630                                 "debug_msg",
12631                                 1,
12632                                 G_TYPE_STRING, "GtkWidgetClass <ctrl><release>9 test");
12633   
12634   /* We use gtk_rc_parse_string() here so we can make sure it works across theme
12635    * changes
12636    */
12637
12638   gtk_rc_parse_string ("style \"testgtk-version-label\" { "
12639                        "   fg[NORMAL] = \"#ff0000\"\n"
12640                        "   font = \"Sans 18\"\n"
12641                        "}\n"
12642                        "widget \"*.testgtk-version-label\" style \"testgtk-version-label\"");
12643   
12644   create_main_window ();
12645
12646   gtk_main ();
12647
12648   if (1)
12649     {
12650       while (g_main_context_pending (NULL))
12651         g_main_context_iteration (NULL, FALSE);
12652 #if 0
12653       sleep (1);
12654       while (g_main_context_pending (NULL))
12655         g_main_context_iteration (NULL, FALSE);
12656 #endif
12657     }
12658   return 0;
12659 }