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