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