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