]> Pileus Git - ~andy/gtk/blob - tests/testwindows.c
tests: Make editing window look more beautiful
[~andy/gtk] / tests / testwindows.c
1 #include <gtk/gtk.h>
2 #ifdef GDK_WINDOWING_X11
3 #include <X11/Xlib.h>
4 #endif
5
6 static GtkWidget *darea;
7 static GtkTreeStore *window_store = NULL;
8 static GtkWidget *treeview;
9
10 static void update_store (void);
11
12 static GtkWidget *main_window;
13
14
15 GdkWindow *
16 create_window (GdkWindow *parent,
17                int x, int y, int w, int h,
18                GdkColor *color)
19 {
20   GdkWindowAttr attributes;
21   gint attributes_mask;
22   GdkWindow *window;
23   GdkColor *bg;
24
25   attributes.x = x;
26   attributes.y = y;
27   attributes.width = w;
28   attributes.height = h;
29   attributes.window_type = GDK_WINDOW_CHILD;
30   attributes.event_mask = GDK_STRUCTURE_MASK
31                         | GDK_BUTTON_MOTION_MASK
32                         | GDK_BUTTON_PRESS_MASK
33                         | GDK_BUTTON_RELEASE_MASK
34                         | GDK_EXPOSURE_MASK
35                         | GDK_ENTER_NOTIFY_MASK
36                         | GDK_LEAVE_NOTIFY_MASK;
37   attributes.wclass = GDK_INPUT_OUTPUT;
38       
39   attributes_mask = GDK_WA_X | GDK_WA_Y;
40       
41   window = gdk_window_new (parent, &attributes, attributes_mask);
42   gdk_window_set_user_data (window, darea);
43
44   bg = g_new (GdkColor, 1);
45   if (color)
46     *bg = *color;
47   else
48     {
49       bg->red = g_random_int_range (0, 0xffff);
50       bg->blue = g_random_int_range (0, 0xffff);
51       bg->green = g_random_int_range (0, 0xffff);;
52     }
53   
54   gdk_window_set_background (window, bg);
55   g_object_set_data_full (G_OBJECT (window), "color", bg, g_free);
56   
57   gdk_window_show (window);
58   
59   return window;
60 }
61
62 static void
63 add_window_cb (GtkTreeModel      *model,
64                GtkTreePath       *path,
65                GtkTreeIter       *iter,
66                gpointer           data)
67 {
68   GList **selected = data;
69   GdkWindow *window;
70
71   gtk_tree_model_get (GTK_TREE_MODEL (window_store),
72                       iter,
73                       0, &window,
74                       -1);
75
76   *selected = g_list_prepend (*selected, window);
77 }
78
79 static GList *
80 get_selected_windows (void)
81 {
82   GtkTreeSelection *sel;
83   GList *selected;
84
85   sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
86
87   selected = NULL;
88   gtk_tree_selection_selected_foreach (sel, add_window_cb, &selected);
89   
90   return selected;
91 }
92
93 static gboolean
94 find_window_helper (GtkTreeModel *model,
95                     GdkWindow *window,
96                     GtkTreeIter *iter,
97                     GtkTreeIter *selected_iter)
98 {
99   GtkTreeIter child_iter;
100   GdkWindow *w;
101
102   do
103     {
104       gtk_tree_model_get (model, iter,
105                           0, &w,
106                           -1);
107       if (w == window)
108         {
109           *selected_iter = *iter;
110           return TRUE;
111         }
112       
113       if (gtk_tree_model_iter_children (model,
114                                         &child_iter,
115                                         iter))
116         {
117           if (find_window_helper (model, window, &child_iter, selected_iter))
118             return TRUE;
119         }
120     } while (gtk_tree_model_iter_next (model, iter));
121
122   return FALSE;
123 }
124
125 static gboolean
126 find_window (GdkWindow *window,
127              GtkTreeIter *window_iter)
128 {
129   GtkTreeIter iter;
130
131   if (!gtk_tree_model_get_iter_first  (GTK_TREE_MODEL (window_store), &iter))
132     return FALSE;
133
134   return find_window_helper (GTK_TREE_MODEL (window_store),
135                              window,
136                              &iter,
137                              window_iter);
138 }
139
140 static void
141 toggle_selection_window (GdkWindow *window)
142 {
143   GtkTreeSelection *selection;
144   GtkTreeIter iter;
145
146   selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
147
148   if (window != NULL &&
149       find_window (window, &iter))
150     {
151       if (gtk_tree_selection_iter_is_selected (selection, &iter))
152         gtk_tree_selection_unselect_iter (selection,  &iter);
153       else
154         gtk_tree_selection_select_iter (selection,  &iter);
155     }
156 }
157
158 static void
159 unselect_windows (void)
160 {
161   GtkTreeSelection *selection;
162
163   selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
164   
165   gtk_tree_selection_unselect_all (selection);
166 }
167
168
169 static void
170 select_window (GdkWindow *window)
171 {
172   GtkTreeSelection *selection;
173   GtkTreeIter iter;
174
175   selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
176
177   if (window != NULL &&
178       find_window (window, &iter))
179     gtk_tree_selection_select_iter (selection,  &iter);
180 }
181
182 static void
183 select_windows (GList *windows)
184 {
185   GtkTreeSelection *selection;
186   GtkTreeIter iter;
187   GList *l;
188
189   selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
190   gtk_tree_selection_unselect_all (selection);
191   
192   for (l = windows; l != NULL; l = l->next)
193     {
194       if (find_window (l->data, &iter))
195         gtk_tree_selection_select_iter (selection,  &iter);
196     }
197 }
198
199 static void
200 add_window_clicked (GtkWidget *button, 
201                     gpointer data)
202 {
203   GdkWindow *parent;
204   GList *l;
205
206   l = get_selected_windows ();
207   if (l != NULL)
208     parent = l->data;
209   else
210     parent = gtk_widget_get_window (darea);
211
212   g_list_free (l);
213   
214   create_window (parent, 10, 10, 100, 100, NULL);
215   update_store ();
216 }
217
218 static void
219 remove_window_clicked (GtkWidget *button, 
220                        gpointer data)
221 {
222   GList *l, *selected;
223
224   selected = get_selected_windows ();
225
226   for (l = selected; l != NULL; l = l->next)
227     gdk_window_destroy (l->data);
228
229   g_list_free (selected);
230
231   update_store ();
232 }
233
234 static void save_children (GString *s, GdkWindow *window);
235
236 static void
237 save_window (GString *s,
238              GdkWindow *window)
239 {
240   gint x, y;
241   GdkColor *color;
242
243   gdk_window_get_position (window, &x, &y);
244   color = g_object_get_data (G_OBJECT (window), "color");
245   
246   g_string_append_printf (s, "%d,%d %dx%d (%d,%d,%d) %d %d\n",
247                           x, y,
248                           gdk_window_get_width (window),
249                           gdk_window_get_height (window),
250                           color->red, color->green, color->blue,
251                           gdk_window_has_native (window),
252                           g_list_length (gdk_window_peek_children (window)));
253
254   save_children (s, window);
255 }
256
257
258 static void
259 save_children (GString *s,
260                GdkWindow *window)
261 {
262   GList *l;
263   GdkWindow *child;
264
265   for (l = g_list_reverse (gdk_window_peek_children (window));
266        l != NULL;
267        l = l->next)
268     {
269       child = l->data;
270
271       save_window (s, child);
272     }
273 }
274
275
276 static void
277 save_clicked (GtkWidget *button, 
278               gpointer data)
279 {
280   GString *s;
281   GtkWidget *dialog;
282   GFile *file;
283
284   s = g_string_new ("");
285
286   save_children (s, gtk_widget_get_window (darea));
287
288   dialog = gtk_file_chooser_dialog_new ("Filename for window data",
289                                         NULL,
290                                         GTK_FILE_CHOOSER_ACTION_SAVE,
291                                         GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
292                                         GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
293                                         NULL);
294   
295   gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE);
296   
297   if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
298     {
299       file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
300
301       g_file_replace_contents (file,
302                                s->str, s->len,
303                                NULL, FALSE,
304                                0, NULL, NULL, NULL);
305
306       g_object_unref (file);
307     }
308
309   gtk_widget_destroy (dialog);
310   g_string_free (s, TRUE);
311 }
312
313 static void
314 destroy_children (GdkWindow *window)
315 {
316   GList *l;
317   GdkWindow *child;
318
319   for (l = gdk_window_peek_children (window);
320        l != NULL;
321        l = l->next)
322     {
323       child = l->data;
324       
325       destroy_children (child);
326       gdk_window_destroy (child);
327     }
328 }
329
330 static char **
331 parse_window (GdkWindow *parent, char **lines)
332 {
333   int x, y, w, h, r, g, b, native, n_children;
334   GdkWindow *window;
335   GdkColor color;
336   int i;
337
338   if (*lines == NULL)
339     return lines;
340   
341   if (sscanf(*lines, "%d,%d %dx%d (%d,%d,%d) %d %d",
342              &x, &y, &w, &h, &r, &g, &b, &native, &n_children) == 9)
343     {
344       lines++;
345       color.red = r;
346       color.green = g;
347       color.blue = b;
348       window = create_window (parent, x, y, w, h, &color);
349       if (native)
350         gdk_window_ensure_native (window);
351       
352       for (i = 0; i < n_children; i++)
353         lines = parse_window (window, lines);
354     }
355   else
356     lines++;
357   
358   return lines;
359 }
360   
361 static void
362 load_file (GFile *file)
363 {
364   GdkWindow *window;
365   char *data;
366   char **lines, **l;
367   
368   if (g_file_load_contents (file, NULL, &data, NULL, NULL, NULL))
369     {
370       window = gtk_widget_get_window (darea);
371
372       destroy_children (window);
373
374       lines = g_strsplit (data, "\n", -1);
375
376       l = lines;
377       while (*l != NULL)
378         l = parse_window (window, l);
379     }
380
381   update_store ();
382 }
383
384 static void
385 move_window_clicked (GtkWidget *button, 
386                      gpointer data)
387 {
388   GdkWindow *window;
389   GtkDirectionType direction;
390   GList *selected, *l;
391   gint x, y;
392
393   direction = GPOINTER_TO_INT (data);
394     
395   selected = get_selected_windows ();
396
397   for (l = selected; l != NULL; l = l->next)
398     {
399       window = l->data;
400       
401       gdk_window_get_position (window, &x, &y);
402       
403       switch (direction) {
404       case GTK_DIR_UP:
405         y -= 10;
406         break;
407       case GTK_DIR_DOWN:
408         y += 10;
409         break;
410       case GTK_DIR_LEFT:
411         x -= 10;
412         break;
413       case GTK_DIR_RIGHT:
414         x += 10;
415         break;
416       default:
417         break;
418       }
419
420       gdk_window_move (window, x, y);
421     }
422
423   g_list_free (selected);
424 }
425
426 static void
427 manual_clicked (GtkWidget *button, 
428                 gpointer data)
429 {
430   GdkWindow *window;
431   GList *selected, *l;
432   int x, y, w, h;
433   GtkWidget *dialog, *table, *label, *xspin, *yspin, *wspin, *hspin;
434   
435
436   selected = get_selected_windows ();
437
438   if (selected == NULL)
439     return;
440
441   gdk_window_get_position (selected->data, &x, &y);
442   w = gdk_window_get_width (selected->data);
443   h = gdk_window_get_height (selected->data);
444
445   dialog = gtk_dialog_new_with_buttons ("Select new position and size",
446                                         GTK_WINDOW (main_window),
447                                         GTK_DIALOG_MODAL,
448                                         GTK_STOCK_OK, GTK_RESPONSE_OK,
449                                         NULL);
450   
451
452   table = gtk_table_new (2, 4, TRUE);
453   gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))),
454                       table,
455                       FALSE, FALSE,
456                       2);
457
458   
459   label = gtk_label_new ("x:");
460   gtk_widget_set_halign (label, GTK_ALIGN_START);
461   gtk_table_attach_defaults (GTK_TABLE (table),
462                              label,
463                              0, 1,
464                              0, 1);
465   label = gtk_label_new ("y:");
466   gtk_widget_set_halign (label, GTK_ALIGN_START);
467   gtk_table_attach_defaults (GTK_TABLE (table),
468                              label,
469                              0, 1,
470                              1, 2);
471   label = gtk_label_new ("width:");
472   gtk_widget_set_halign (label, GTK_ALIGN_START);
473   gtk_table_attach_defaults (GTK_TABLE (table),
474                              label,
475                              0, 1,
476                              2, 3);
477   label = gtk_label_new ("height:");
478   gtk_widget_set_halign (label, GTK_ALIGN_START);
479   gtk_table_attach_defaults (GTK_TABLE (table),
480                              label,
481                              0, 1,
482                              3, 4);
483
484   xspin = gtk_spin_button_new_with_range (G_MININT, G_MAXINT, 1);
485   gtk_widget_set_hexpand (xspin, TRUE);
486   gtk_spin_button_set_value (GTK_SPIN_BUTTON (xspin), x);
487   gtk_table_attach_defaults (GTK_TABLE (table),
488                              xspin,
489                              1, 2,
490                              0, 1);
491   yspin = gtk_spin_button_new_with_range (G_MININT, G_MAXINT, 1);
492   gtk_widget_set_hexpand (yspin, TRUE);
493   gtk_spin_button_set_value (GTK_SPIN_BUTTON (yspin), y);
494   gtk_table_attach_defaults (GTK_TABLE (table),
495                              yspin,
496                              1, 2,
497                              1, 2);
498   wspin = gtk_spin_button_new_with_range (G_MININT, G_MAXINT, 1);
499   gtk_widget_set_hexpand (wspin, TRUE);
500   gtk_spin_button_set_value (GTK_SPIN_BUTTON (wspin), w);
501   gtk_table_attach_defaults (GTK_TABLE (table),
502                              wspin,
503                              1, 2,
504                              2, 3);
505   hspin = gtk_spin_button_new_with_range (G_MININT, G_MAXINT, 1);
506   gtk_widget_set_hexpand (hspin, TRUE);
507   gtk_spin_button_set_value (GTK_SPIN_BUTTON (hspin), h);
508   gtk_table_attach_defaults (GTK_TABLE (table),
509                              hspin,
510                              1, 2,
511                              3, 4);
512   
513   gtk_widget_show_all (dialog);
514   
515   gtk_dialog_run (GTK_DIALOG (dialog));
516
517   x = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (xspin));
518   y = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (yspin));
519   w = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (wspin));
520   h = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (hspin));
521
522   gtk_widget_destroy (dialog);
523   
524   for (l = selected; l != NULL; l = l->next)
525     {
526       window = l->data;
527       
528       gdk_window_move_resize (window, x, y, w, h);
529     }
530
531   g_list_free (selected);
532 }
533
534 static void
535 restack_clicked (GtkWidget *button,
536                  gpointer data)
537 {
538   GList *selected;
539
540   selected = get_selected_windows ();
541
542   if (g_list_length (selected) != 2)
543     {
544       g_warning ("select two windows");
545     }
546
547   gdk_window_restack (selected->data,
548                       selected->next->data,
549                       GPOINTER_TO_INT (data));
550
551   g_list_free (selected);
552
553   update_store ();
554 }
555
556 static void
557 scroll_window_clicked (GtkWidget *button, 
558                        gpointer data)
559 {
560   GdkWindow *window;
561   GtkDirectionType direction;
562   GList *selected, *l;
563   gint dx, dy;
564
565   direction = GPOINTER_TO_INT (data);
566     
567   selected = get_selected_windows ();
568
569   dx = 0; dy = 0;
570   switch (direction) {
571   case GTK_DIR_UP:
572     dy = 10;
573     break;
574   case GTK_DIR_DOWN:
575     dy = -10;
576     break;
577   case GTK_DIR_LEFT:
578     dx = 10;
579     break;
580   case GTK_DIR_RIGHT:
581     dx = -10;
582     break;
583   default:
584     break;
585   }
586   
587   for (l = selected; l != NULL; l = l->next)
588     {
589       window = l->data;
590
591       gdk_window_scroll (window, dx, dy);
592     }
593
594   g_list_free (selected);
595 }
596
597
598 static void
599 raise_window_clicked (GtkWidget *button, 
600                       gpointer data)
601 {
602   GList *selected, *l;
603   GdkWindow *window;
604     
605   selected = get_selected_windows ();
606
607   for (l = selected; l != NULL; l = l->next)
608     {
609       window = l->data;
610       
611       gdk_window_raise (window);
612     }
613
614   g_list_free (selected);
615   
616   update_store ();
617 }
618
619 static void
620 lower_window_clicked (GtkWidget *button, 
621                       gpointer data)
622 {
623   GList *selected, *l;
624   GdkWindow *window;
625     
626   selected = get_selected_windows ();
627
628   for (l = selected; l != NULL; l = l->next)
629     {
630       window = l->data;
631       
632       gdk_window_lower (window);
633     }
634
635   g_list_free (selected);
636   
637   update_store ();
638 }
639
640
641 static void
642 smaller_window_clicked (GtkWidget *button, 
643                         gpointer data)
644 {
645   GList *selected, *l;
646   GdkWindow *window;
647   int w, h;
648
649   selected = get_selected_windows ();
650
651   for (l = selected; l != NULL; l = l->next)
652     {
653       window = l->data;
654       
655       w = gdk_window_get_width (window) - 10;
656       h = gdk_window_get_height (window) - 10;
657       if (w < 1)
658         w = 1;
659       if (h < 1)
660         h = 1;
661       
662       gdk_window_resize (window, w, h);
663     }
664
665   g_list_free (selected);
666 }
667
668 static void
669 larger_window_clicked (GtkWidget *button, 
670                         gpointer data)
671 {
672   GList *selected, *l;
673   GdkWindow *window;
674   int w, h;
675
676   selected = get_selected_windows ();
677
678   for (l = selected; l != NULL; l = l->next)
679     {
680       window = l->data;
681       
682       w = gdk_window_get_width (window) + 10;
683       h = gdk_window_get_height (window) + 10;
684       
685       gdk_window_resize (window, w, h);
686     }
687
688   g_list_free (selected);
689 }
690
691 static void
692 native_window_clicked (GtkWidget *button, 
693                         gpointer data)
694 {
695   GList *selected, *l;
696   GdkWindow *window;
697
698   selected = get_selected_windows ();
699
700   for (l = selected; l != NULL; l = l->next)
701     {
702       window = l->data;
703       
704       gdk_window_ensure_native (window);
705     }
706   
707   g_list_free (selected);
708   
709   update_store ();
710 }
711
712 static gboolean
713 darea_button_release_event (GtkWidget *widget,
714                             GdkEventButton *event)
715 {
716   if ((event->state & GDK_CONTROL_MASK) != 0)
717     {
718       toggle_selection_window (event->window);
719     }
720   else
721     {
722       unselect_windows ();
723       select_window (event->window);
724     }
725     
726   return TRUE;
727 }
728
729 static void
730 render_window_cell (GtkTreeViewColumn *tree_column,
731                     GtkCellRenderer   *cell,
732                     GtkTreeModel      *tree_model,
733                     GtkTreeIter       *iter,
734                     gpointer           data)
735 {
736   GdkWindow *window;
737   char *name;
738
739   gtk_tree_model_get (GTK_TREE_MODEL (window_store),
740                       iter,
741                       0, &window,
742                       -1);
743
744   if (gdk_window_has_native (window))
745       name = g_strdup_printf ("%p (native)", window);
746   else
747       name = g_strdup_printf ("%p", window);
748
749   g_object_set (cell,
750                 "text", name,
751                 NULL);
752 }
753
754 static void
755 add_children (GtkTreeStore *store,
756               GdkWindow *window,
757               GtkTreeIter *window_iter)
758 {
759   GList *l;
760   GtkTreeIter child_iter;
761
762   for (l = gdk_window_peek_children (window);
763        l != NULL;
764        l = l->next)
765     {
766       gtk_tree_store_append (store, &child_iter, window_iter);
767       gtk_tree_store_set (store, &child_iter,
768                           0, l->data,
769                           -1);
770
771       add_children (store, l->data, &child_iter);
772     }
773 }
774
775 static void
776 update_store (void)
777 {
778   GList *selected;
779
780   selected = get_selected_windows ();
781
782   gtk_tree_store_clear (window_store);
783
784   add_children (window_store, gtk_widget_get_window (darea), NULL);
785   gtk_tree_view_expand_all (GTK_TREE_VIEW (treeview));
786
787   select_windows (selected);
788   g_list_free (selected);
789 }
790
791
792 int
793 main (int argc, char **argv)
794 {
795   GtkWidget *window, *vbox, *hbox, *frame;
796   GtkWidget *button, *scrolled, *table;
797   GtkTreeViewColumn *column;
798   GtkCellRenderer *renderer;
799   GdkRGBA black = {0,0,0,1};
800   GFile *file;
801   
802   gtk_init (&argc, &argv);
803
804   main_window = window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
805   gtk_container_set_border_width (GTK_CONTAINER (window), 0);
806
807   g_signal_connect (G_OBJECT (window), "delete-event", gtk_main_quit, NULL);
808
809   hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 5);
810   gtk_container_add (GTK_CONTAINER (window), hbox);
811   gtk_widget_show (hbox);
812
813   frame = gtk_frame_new ("GdkWindows");
814   gtk_box_pack_start (GTK_BOX (hbox),
815                       frame,
816                       FALSE, FALSE,
817                       5);
818   gtk_widget_show (frame);
819
820   darea =  gtk_drawing_area_new ();
821   /*gtk_widget_set_double_buffered (darea, FALSE);*/
822   gtk_widget_add_events (darea, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);
823   gtk_widget_set_size_request (darea, 500, 500);
824   g_signal_connect (darea, "button_release_event", 
825                     G_CALLBACK (darea_button_release_event), 
826                     NULL);
827
828   
829   gtk_container_add (GTK_CONTAINER (frame), darea);
830   gtk_widget_realize (darea);
831   gtk_widget_show (darea);
832   gtk_widget_override_background_color (darea, 0, &black);
833
834
835   vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
836   gtk_box_pack_start (GTK_BOX (hbox),
837                       vbox,
838                       FALSE, FALSE,
839                       5);
840   gtk_widget_show (vbox);
841
842   window_store = gtk_tree_store_new (1, GDK_TYPE_WINDOW);
843   
844   treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL (window_store));
845   gtk_tree_selection_set_mode (gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview)),
846                                GTK_SELECTION_MULTIPLE);
847   column = gtk_tree_view_column_new ();
848   gtk_tree_view_column_set_title (column, "Window");
849   renderer = gtk_cell_renderer_text_new ();
850   gtk_tree_view_column_pack_start (column, renderer, TRUE);
851   gtk_tree_view_column_set_cell_data_func (column,
852                                            renderer,
853                                            render_window_cell,
854                                            NULL, NULL);
855
856   gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
857
858
859   scrolled = gtk_scrolled_window_new (NULL, NULL);
860   gtk_widget_set_size_request (scrolled, 200, 400);
861   gtk_container_add (GTK_CONTAINER (scrolled), treeview);
862   gtk_box_pack_start (GTK_BOX (vbox),
863                       scrolled,
864                       FALSE, FALSE,
865                       5);
866   gtk_widget_show (scrolled);
867   gtk_widget_show (treeview);
868   
869   table = gtk_table_new (5, 4, TRUE);
870   gtk_box_pack_start (GTK_BOX (vbox),
871                       table,
872                       FALSE, FALSE,
873                       2);
874   gtk_widget_show (table);
875
876   button = gtk_button_new ();
877   gtk_button_set_image (GTK_BUTTON (button),
878                         gtk_image_new_from_stock (GTK_STOCK_GO_BACK,
879                                                   GTK_ICON_SIZE_BUTTON));
880   g_signal_connect (button, "clicked", 
881                     G_CALLBACK (move_window_clicked), 
882                     GINT_TO_POINTER (GTK_DIR_LEFT));
883   gtk_table_attach_defaults (GTK_TABLE (table),
884                              button,
885                              0, 1,
886                              1, 2);
887   gtk_widget_show (button);
888
889   button = gtk_button_new ();
890   gtk_button_set_image (GTK_BUTTON (button),
891                         gtk_image_new_from_stock (GTK_STOCK_GO_UP,
892                                                   GTK_ICON_SIZE_BUTTON));
893   g_signal_connect (button, "clicked", 
894                     G_CALLBACK (move_window_clicked), 
895                     GINT_TO_POINTER (GTK_DIR_UP));
896   gtk_table_attach_defaults (GTK_TABLE (table),
897                              button,
898                              1, 2,
899                              0, 1);
900   gtk_widget_show (button);
901
902   button = gtk_button_new ();
903   gtk_button_set_image (GTK_BUTTON (button),
904                         gtk_image_new_from_stock (GTK_STOCK_GO_FORWARD,
905                                                   GTK_ICON_SIZE_BUTTON));
906   g_signal_connect (button, "clicked", 
907                     G_CALLBACK (move_window_clicked), 
908                     GINT_TO_POINTER (GTK_DIR_RIGHT));
909   gtk_table_attach_defaults (GTK_TABLE (table),
910                              button,
911                              2, 3,
912                              1, 2);
913   gtk_widget_show (button);
914
915   button = gtk_button_new ();
916   gtk_button_set_image (GTK_BUTTON (button),
917                         gtk_image_new_from_stock (GTK_STOCK_GO_DOWN,
918                                                   GTK_ICON_SIZE_BUTTON));
919   g_signal_connect (button, "clicked", 
920                     G_CALLBACK (move_window_clicked), 
921                     GINT_TO_POINTER (GTK_DIR_DOWN));
922   gtk_table_attach_defaults (GTK_TABLE (table),
923                              button,
924                              1, 2,
925                              2, 3);
926   gtk_widget_show (button);
927
928
929   button = gtk_button_new_with_label ("Raise");
930   g_signal_connect (button, "clicked", 
931                     G_CALLBACK (raise_window_clicked), 
932                     NULL);
933   gtk_table_attach_defaults (GTK_TABLE (table),
934                              button,
935                              0, 1,
936                              0, 1);
937   gtk_widget_show (button);
938
939   button = gtk_button_new_with_label ("Lower");
940   g_signal_connect (button, "clicked", 
941                     G_CALLBACK (lower_window_clicked), 
942                     NULL);
943   gtk_table_attach_defaults (GTK_TABLE (table),
944                              button,
945                              0, 1,
946                              2, 3);
947   gtk_widget_show (button);
948
949
950   button = gtk_button_new_with_label ("Smaller");
951   g_signal_connect (button, "clicked", 
952                     G_CALLBACK (smaller_window_clicked), 
953                     NULL);
954   gtk_table_attach_defaults (GTK_TABLE (table),
955                              button,
956                              2, 3,
957                              0, 1);
958   gtk_widget_show (button);
959
960   button = gtk_button_new_with_label ("Larger");
961   g_signal_connect (button, "clicked", 
962                     G_CALLBACK (larger_window_clicked), 
963                     NULL);
964   gtk_table_attach_defaults (GTK_TABLE (table),
965                              button,
966                              2, 3,
967                              2, 3);
968   gtk_widget_show (button);
969
970   button = gtk_button_new_with_label ("Native");
971   g_signal_connect (button, "clicked", 
972                     G_CALLBACK (native_window_clicked), 
973                     NULL);
974   gtk_table_attach_defaults (GTK_TABLE (table),
975                              button,
976                              1, 2,
977                              1, 2);
978   gtk_widget_show (button);
979
980
981   button = gtk_button_new_with_label ("scroll");
982   gtk_button_set_image (GTK_BUTTON (button),
983                         gtk_image_new_from_stock (GTK_STOCK_GO_UP,
984                                                   GTK_ICON_SIZE_BUTTON));
985   g_signal_connect (button, "clicked", 
986                     G_CALLBACK (scroll_window_clicked), 
987                     GINT_TO_POINTER (GTK_DIR_UP));
988   gtk_table_attach_defaults (GTK_TABLE (table),
989                              button,
990                              3, 4,
991                              0, 1);
992   gtk_widget_show (button);
993
994   button = gtk_button_new_with_label ("scroll");
995   gtk_button_set_image (GTK_BUTTON (button),
996                         gtk_image_new_from_stock (GTK_STOCK_GO_DOWN,
997                                                   GTK_ICON_SIZE_BUTTON));
998   g_signal_connect (button, "clicked", 
999                     G_CALLBACK (scroll_window_clicked), 
1000                     GINT_TO_POINTER (GTK_DIR_DOWN));
1001   gtk_table_attach_defaults (GTK_TABLE (table),
1002                              button,
1003                              3, 4,
1004                              1, 2);
1005   gtk_widget_show (button);
1006
1007   button = gtk_button_new_with_label ("Manual");
1008   g_signal_connect (button, "clicked", 
1009                     G_CALLBACK (manual_clicked),
1010                     NULL);
1011   gtk_table_attach_defaults (GTK_TABLE (table),
1012                              button,
1013                              3, 4,
1014                              2, 3);
1015   gtk_widget_show (button);
1016
1017   button = gtk_button_new_with_label ("Restack above");
1018   g_signal_connect (button, "clicked",
1019                     G_CALLBACK (restack_clicked),
1020                     GINT_TO_POINTER (1));
1021   gtk_table_attach_defaults (GTK_TABLE (table),
1022                              button,
1023                              2, 3,
1024                              3, 4);
1025   gtk_widget_show (button);
1026
1027   button = gtk_button_new_with_label ("Restack below");
1028   g_signal_connect (button, "clicked",
1029                     G_CALLBACK (restack_clicked),
1030                     0);
1031   gtk_table_attach_defaults (GTK_TABLE (table),
1032                              button,
1033                              3, 4,
1034                              3, 4);
1035   gtk_widget_show (button);
1036
1037   button = gtk_button_new_with_label ("Add window");
1038   gtk_box_pack_start (GTK_BOX (vbox),
1039                       button,
1040                       FALSE, FALSE,
1041                       2);
1042   gtk_widget_show (button);
1043   g_signal_connect (button, "clicked", 
1044                     G_CALLBACK (add_window_clicked), 
1045                     NULL);
1046   
1047   button = gtk_button_new_with_label ("Remove window");
1048   gtk_box_pack_start (GTK_BOX (vbox),
1049                       button,
1050                       FALSE, FALSE,
1051                       2);
1052   gtk_widget_show (button);
1053   g_signal_connect (button, "clicked", 
1054                     G_CALLBACK (remove_window_clicked), 
1055                     NULL);
1056
1057   button = gtk_button_new_with_label ("Save");
1058   gtk_box_pack_start (GTK_BOX (vbox),
1059                       button,
1060                       FALSE, FALSE,
1061                       2);
1062   gtk_widget_show (button);
1063   g_signal_connect (button, "clicked", 
1064                     G_CALLBACK (save_clicked), 
1065                     NULL);
1066
1067   gtk_widget_show (window);
1068
1069   if (argc == 2)
1070     {
1071       file = g_file_new_for_commandline_arg (argv[1]);
1072       load_file (file);
1073       g_object_unref (file);
1074     }
1075   
1076   gtk_main ();
1077
1078   return 0;
1079 }