]> Pileus Git - ~andy/gtk/blob - tests/testmerge.c
stylecontext: Do invalidation on first resize container
[~andy/gtk] / tests / testmerge.c
1 /* testmerge.c
2  * Copyright (C) 2003 James Henstridge
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library 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  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library. If not, see <http://www.gnu.org/licenses/>.
16  */
17
18 #include "config.h"
19
20 #include <stdio.h>
21 #include <string.h>
22 #ifdef HAVE_UNISTD_H
23 #include <unistd.h>
24 #endif
25
26 #define GDK_DISABLE_DEPRECATION_WARNINGS
27
28 #include <gtk/gtk.h>
29
30 #ifndef STDOUT_FILENO
31 #define STDOUT_FILENO 1 
32 #endif
33
34 struct { const gchar *filename; guint merge_id; } merge_ids[] = {
35   { "merge-1.ui", 0 },
36   { "merge-2.ui", 0 },
37   { "merge-3.ui", 0 }
38 };
39
40 static void
41 dump_tree (GtkWidget    *button, 
42            GtkUIManager *merge)
43 {
44   gchar *dump;
45
46   dump = gtk_ui_manager_get_ui (merge);
47   g_message ("%s", dump);
48   g_free (dump);
49 }
50
51 static void
52 dump_accels (void)
53 {
54   gtk_accel_map_save_fd (STDOUT_FILENO);
55 }
56
57 static void
58 print_toplevel (GtkWidget *widget, gpointer user_data)
59 {
60   g_print ("%s\n", G_OBJECT_TYPE_NAME (widget));
61 }
62
63 static void
64 dump_toplevels (GtkWidget    *button, 
65                 GtkUIManager *merge)
66 {
67   GSList *toplevels;
68
69   toplevels = gtk_ui_manager_get_toplevels (merge, 
70                                             GTK_UI_MANAGER_MENUBAR |
71                                             GTK_UI_MANAGER_TOOLBAR |
72                                             GTK_UI_MANAGER_POPUP);
73
74   g_slist_foreach (toplevels, (GFunc) print_toplevel, NULL);
75   g_slist_free (toplevels);
76 }
77
78 static void
79 toggle_tearoffs (GtkWidget    *button, 
80                  GtkUIManager *merge)
81 {
82   gboolean add_tearoffs;
83
84   add_tearoffs = gtk_ui_manager_get_add_tearoffs (merge);
85   
86   gtk_ui_manager_set_add_tearoffs (merge, !add_tearoffs);
87 }
88
89 static gint
90 delayed_toggle_dynamic (GtkUIManager *merge)
91 {
92   GtkAction *dyn;
93   static GtkActionGroup *dynamic = NULL;
94   static guint merge_id = 0;
95
96   if (!dynamic)
97     {
98       dynamic = gtk_action_group_new ("dynamic");
99       gtk_ui_manager_insert_action_group (merge, dynamic, 0);
100       dyn = g_object_new (GTK_TYPE_ACTION,
101                           "name", "dyn1",
102                           "label", "Dynamic action 1",
103                           "stock_id", GTK_STOCK_COPY,
104                           NULL);
105       gtk_action_group_add_action (dynamic, dyn);
106       dyn = g_object_new (GTK_TYPE_ACTION,
107                           "name", "dyn2",
108                           "label", "Dynamic action 2",
109                           "stock_id", GTK_STOCK_EXECUTE,
110                           NULL);
111       gtk_action_group_add_action (dynamic, dyn);
112     }
113   
114   if (merge_id == 0)
115     {
116       merge_id = gtk_ui_manager_new_merge_id (merge);
117       gtk_ui_manager_add_ui (merge, merge_id, "/toolbar1/ToolbarPlaceholder", 
118                              "dyn1", "dyn1", 0, 0);
119       gtk_ui_manager_add_ui (merge, merge_id, "/toolbar1/ToolbarPlaceholder", 
120                              "dynsep", NULL, GTK_UI_MANAGER_SEPARATOR, 0);
121       gtk_ui_manager_add_ui (merge, merge_id, "/toolbar1/ToolbarPlaceholder", 
122                              "dyn2", "dyn2", 0, 0);
123
124       gtk_ui_manager_add_ui (merge, merge_id, "/menubar/EditMenu", 
125                              "dyn1menu", "dyn1", GTK_UI_MANAGER_MENU, 0);
126       gtk_ui_manager_add_ui (merge, merge_id, "/menubar/EditMenu/dyn1menu", 
127                              "dyn1", "dyn1", GTK_UI_MANAGER_MENUITEM, 0);
128       gtk_ui_manager_add_ui (merge, merge_id, "/menubar/EditMenu/dyn1menu/dyn1", 
129                              "dyn2", "dyn2", GTK_UI_MANAGER_AUTO, FALSE);
130     }
131   else 
132     {
133       gtk_ui_manager_remove_ui (merge, merge_id);
134       merge_id = 0;
135     }
136
137   return FALSE;
138 }
139
140 static void
141 toggle_dynamic (GtkWidget    *button, 
142                 GtkUIManager *merge)
143 {
144   gdk_threads_add_timeout (2000, (GSourceFunc)delayed_toggle_dynamic, merge);
145 }
146
147 static void
148 activate_action (GtkAction *action)
149 {
150   const gchar *name = gtk_action_get_name (action);
151   const gchar *typename = G_OBJECT_TYPE_NAME (action);
152
153   g_message ("Action %s (type=%s) activated", name, typename);
154 }
155
156 static void
157 toggle_action (GtkAction *action)
158 {
159   const gchar *name = gtk_action_get_name (action);
160   const gchar *typename = G_OBJECT_TYPE_NAME (action);
161
162   g_message ("ToggleAction %s (type=%s) toggled (active=%d)", name, typename,
163              gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)));
164 }
165
166
167 static void
168 radio_action_changed (GtkAction *action, GtkRadioAction *current)
169 {
170   g_message ("RadioAction %s (type=%s) activated (active=%d) (value %d)", 
171              gtk_action_get_name (GTK_ACTION (current)), 
172              G_OBJECT_TYPE_NAME (GTK_ACTION (current)),
173              gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (current)),
174              gtk_radio_action_get_current_value (current));
175 }
176
177 static GtkActionEntry entries[] = {
178   { "FileMenuAction", NULL, "_File" },
179   { "EditMenuAction", NULL, "_Edit" },
180   { "HelpMenuAction", NULL, "_Help" },
181   { "JustifyMenuAction", NULL, "_Justify" },
182   { "EmptyMenu1Action", NULL, "Empty 1" },
183   { "EmptyMenu2Action", NULL, "Empty 2" },
184   { "Test", NULL, "Test" },
185
186   { "QuitAction",  GTK_STOCK_QUIT,  NULL,     "<control>q", "Quit", G_CALLBACK (gtk_main_quit) },
187   { "NewAction",   GTK_STOCK_NEW,   NULL,     "<control>n", "Create something", G_CALLBACK (activate_action) },
188   { "New2Action",  GTK_STOCK_NEW,   NULL,     "<control>m", "Create something else", G_CALLBACK (activate_action) },
189   { "OpenAction",  GTK_STOCK_OPEN,  NULL,     NULL,         "Open it", G_CALLBACK (activate_action) },
190   { "CutAction",   GTK_STOCK_CUT,   NULL,     "<control>x", "Knive", G_CALLBACK (activate_action) },
191   { "CopyAction",  GTK_STOCK_COPY,  NULL,     "<control>c", "Copy", G_CALLBACK (activate_action) },
192   { "PasteAction", GTK_STOCK_PASTE, NULL,     "<control>v", "Paste", G_CALLBACK (activate_action) },
193   { "AboutAction", NULL,            "_About", NULL,         "About", G_CALLBACK (activate_action) },
194 };
195 static guint n_entries = G_N_ELEMENTS (entries);
196
197 static GtkToggleActionEntry toggle_entries[] = {
198   { "BoldAction",  GTK_STOCK_BOLD,  "_Bold",  "<control>b", "Make it bold", G_CALLBACK (toggle_action), 
199     TRUE },
200 };
201 static guint n_toggle_entries = G_N_ELEMENTS (toggle_entries);
202
203 enum {
204   JUSTIFY_LEFT,
205   JUSTIFY_CENTER,
206   JUSTIFY_RIGHT,
207   JUSTIFY_FILL
208 };
209
210 static GtkRadioActionEntry radio_entries[] = {
211   { "justify-left", GTK_STOCK_JUSTIFY_LEFT, NULL, "<control>L", 
212     "Left justify the text", JUSTIFY_LEFT },
213   { "justify-center", GTK_STOCK_JUSTIFY_CENTER, NULL, "<super>E",
214     "Center justify the text", JUSTIFY_CENTER },
215   { "justify-right", GTK_STOCK_JUSTIFY_RIGHT, NULL, "<hyper>R",
216     "Right justify the text", JUSTIFY_RIGHT },
217   { "justify-fill", GTK_STOCK_JUSTIFY_FILL, NULL, "<super><hyper>J",
218     "Fill justify the text", JUSTIFY_FILL },
219 };
220 static guint n_radio_entries = G_N_ELEMENTS (radio_entries);
221
222 static void
223 add_widget (GtkUIManager *merge, 
224             GtkWidget    *widget, 
225             GtkBox       *box)
226 {
227   gtk_box_pack_start (box, widget, FALSE, FALSE, 0);
228   gtk_widget_show (widget);
229 }
230
231 static void
232 toggle_merge (GtkWidget    *button, 
233               GtkUIManager *merge)
234 {
235   gint mergenum;
236
237   mergenum = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button), "mergenum"));
238
239   if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)))
240     {
241       GError *err = NULL;
242
243       g_message ("merging %s", merge_ids[mergenum].filename);
244       merge_ids[mergenum].merge_id =
245         gtk_ui_manager_add_ui_from_file (merge, merge_ids[mergenum].filename, &err);
246       if (err != NULL)
247         {
248           GtkWidget *dialog;
249
250           dialog = gtk_message_dialog_new (GTK_WINDOW (gtk_widget_get_toplevel (button)),
251                                            0, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK,
252                                            "could not merge %s: %s", merge_ids[mergenum].filename,
253                                            err->message);
254
255           g_signal_connect (dialog, "response", G_CALLBACK (gtk_widget_destroy), NULL);
256           gtk_widget_show (dialog);
257
258           g_clear_error (&err);
259         }
260     }
261   else
262     {
263       g_message ("unmerging %s (merge_id=%u)", merge_ids[mergenum].filename,
264                  merge_ids[mergenum].merge_id);
265       gtk_ui_manager_remove_ui (merge, merge_ids[mergenum].merge_id);
266     }
267 }
268
269 static void  
270 set_name_func (GtkTreeViewColumn *tree_column,
271                GtkCellRenderer   *cell,
272                GtkTreeModel      *tree_model,
273                GtkTreeIter       *iter,
274                gpointer           data)
275 {
276   GtkAction *action;
277   char *name;
278   
279   gtk_tree_model_get (tree_model, iter, 0, &action, -1);
280   g_object_get (action, "name", &name, NULL);
281   g_object_set (cell, "text", name, NULL);
282   g_free (name);
283   g_object_unref (action);
284 }
285
286 static void
287 set_sensitive_func (GtkTreeViewColumn *tree_column,
288                     GtkCellRenderer   *cell,
289                     GtkTreeModel      *tree_model,
290                     GtkTreeIter       *iter,
291                     gpointer           data)
292 {
293   GtkAction *action;
294   gboolean sensitive;
295   
296   gtk_tree_model_get (tree_model, iter, 0, &action, -1);
297   g_object_get (action, "sensitive", &sensitive, NULL);
298   g_object_set (cell, "active", sensitive, NULL);
299   g_object_unref (action);
300 }
301
302
303 static void
304 set_visible_func (GtkTreeViewColumn *tree_column,
305                   GtkCellRenderer   *cell,
306                   GtkTreeModel      *tree_model,
307                   GtkTreeIter       *iter,
308                   gpointer           data)
309 {
310   GtkAction *action;
311   gboolean visible;
312   
313   gtk_tree_model_get (tree_model, iter, 0, &action, -1);
314   g_object_get (action, "visible", &visible, NULL);
315   g_object_set (cell, "active", visible, NULL);
316   g_object_unref (action);
317 }
318
319 static void
320 sensitivity_toggled (GtkCellRendererToggle *cell, 
321                      const gchar           *path_str,
322                      GtkTreeModel          *model)
323 {
324   GtkTreePath *path;
325   GtkTreeIter iter;
326   GtkAction *action;
327   gboolean sensitive;
328
329   path = gtk_tree_path_new_from_string (path_str);
330   gtk_tree_model_get_iter (model, &iter, path);
331
332   gtk_tree_model_get (model, &iter, 0, &action, -1);
333   g_object_get (action, "sensitive", &sensitive, NULL);
334   g_object_set (action, "sensitive", !sensitive, NULL);
335   gtk_tree_model_row_changed (model, path, &iter);
336   gtk_tree_path_free (path);
337 }
338
339 static void
340 visibility_toggled (GtkCellRendererToggle *cell, 
341                     const gchar           *path_str, 
342                     GtkTreeModel          *model)
343 {
344   GtkTreePath *path;
345   GtkTreeIter iter;
346   GtkAction *action;
347   gboolean visible;
348
349   path = gtk_tree_path_new_from_string (path_str);
350   gtk_tree_model_get_iter (model, &iter, path);
351
352   gtk_tree_model_get (model, &iter, 0, &action, -1);
353   g_object_get (action, "visible", &visible, NULL);
354   g_object_set (action, "visible", !visible, NULL);
355   gtk_tree_model_row_changed (model, path, &iter);
356   gtk_tree_path_free (path);
357 }
358
359 static gint
360 iter_compare_func (GtkTreeModel *model, 
361                    GtkTreeIter  *a, 
362                    GtkTreeIter  *b,
363                    gpointer      user_data)
364 {
365   GValue a_value = G_VALUE_INIT, b_value = G_VALUE_INIT;
366   GtkAction *a_action, *b_action;
367   const gchar *a_name, *b_name;
368   gint retval = 0;
369
370   gtk_tree_model_get_value (model, a, 0, &a_value);
371   gtk_tree_model_get_value (model, b, 0, &b_value);
372   a_action = GTK_ACTION (g_value_get_object (&a_value));
373   b_action = GTK_ACTION (g_value_get_object (&b_value));
374
375   a_name = gtk_action_get_name (a_action);
376   b_name = gtk_action_get_name (b_action);
377   if (a_name == NULL && b_name == NULL) 
378     retval = 0;
379   else if (a_name == NULL)
380     retval = -1;
381   else if (b_name == NULL) 
382     retval = 1;
383   else 
384     retval = strcmp (a_name, b_name);
385
386   g_value_unset (&b_value);
387   g_value_unset (&a_value);
388
389   return retval;
390 }
391
392 static GtkWidget *
393 create_tree_view (GtkUIManager *merge)
394 {
395   GtkWidget *tree_view, *sw;
396   GtkListStore *store;
397   GList *p;
398   GtkCellRenderer *cell;
399   
400   store = gtk_list_store_new (1, GTK_TYPE_ACTION);
401   gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (store), 0,
402                                    iter_compare_func, NULL, NULL);
403   gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store), 0,
404                                         GTK_SORT_ASCENDING);
405   
406   for (p = gtk_ui_manager_get_action_groups (merge); p; p = p->next)
407     {
408       GList *actions, *l;
409
410       actions = gtk_action_group_list_actions (p->data);
411
412       for (l = actions; l; l = l->next)
413         {
414           GtkTreeIter iter;
415
416           gtk_list_store_append (store, &iter);
417           gtk_list_store_set (store, &iter, 0, l->data, -1);
418         }
419
420       g_list_free (actions);
421     }
422   
423   tree_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store));
424   g_object_unref (store);
425
426   gtk_tree_view_insert_column_with_data_func (GTK_TREE_VIEW (tree_view),
427                                               -1, "Action",
428                                               gtk_cell_renderer_text_new (),
429                                               set_name_func, NULL, NULL);
430
431   gtk_tree_view_column_set_sort_column_id (gtk_tree_view_get_column (GTK_TREE_VIEW (tree_view), 0), 0);
432
433   cell = gtk_cell_renderer_toggle_new ();
434   g_signal_connect (cell, "toggled", G_CALLBACK (sensitivity_toggled), store);
435   gtk_tree_view_insert_column_with_data_func (GTK_TREE_VIEW (tree_view),
436                                               -1, "Sensitive",
437                                               cell,
438                                               set_sensitive_func, NULL, NULL);
439
440   cell = gtk_cell_renderer_toggle_new ();
441   g_signal_connect (cell, "toggled", G_CALLBACK (visibility_toggled), store);
442   gtk_tree_view_insert_column_with_data_func (GTK_TREE_VIEW (tree_view),
443                                               -1, "Visible",
444                                               cell,
445                                               set_visible_func, NULL, NULL);
446
447   sw = gtk_scrolled_window_new (NULL, NULL);
448   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
449                                   GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
450   gtk_container_add (GTK_CONTAINER (sw), tree_view);
451   
452   return sw;
453 }
454
455 static gboolean
456 area_press (GtkWidget      *drawing_area,
457             GdkEventButton *event,
458             GtkUIManager   *merge)
459 {
460   gtk_widget_grab_focus (drawing_area);
461
462   if (gdk_event_triggers_context_menu ((GdkEvent *) event) &&
463       event->type == GDK_BUTTON_PRESS)
464     {
465       GtkWidget *menu = gtk_ui_manager_get_widget (merge, "/FileMenu");
466       
467       if (GTK_IS_MENU (menu)) 
468         {
469           gtk_menu_popup (GTK_MENU (menu), NULL, NULL,
470                           NULL, drawing_area,
471                           3, event->time);
472           return TRUE;
473         }
474     }
475
476   return FALSE;
477   
478 }
479
480 static void
481 activate_path (GtkWidget      *button,
482                GtkUIManager   *merge)
483 {
484   GtkAction *action = gtk_ui_manager_get_action (merge, 
485                                                  "/menubar/HelpMenu/About");
486   if (action)
487     gtk_action_activate (action);
488   else 
489     g_message ("no action found");
490 }
491
492 typedef struct _ActionStatus ActionStatus;
493
494 struct _ActionStatus {
495   GtkAction *action;
496   GtkWidget *statusbar;
497 };
498
499 static void
500 action_status_destroy (gpointer data)
501 {
502   ActionStatus *action_status = data;
503
504   g_object_unref (action_status->action);
505   g_object_unref (action_status->statusbar);
506
507   g_free (action_status);
508 }
509
510 static void
511 set_tip (GtkWidget *widget)
512 {
513   ActionStatus *data;
514   gchar *tooltip;
515   
516   data = g_object_get_data (G_OBJECT (widget), "action-status");
517   
518   if (data) 
519     {
520       g_object_get (data->action, "tooltip", &tooltip, NULL);
521       
522       gtk_statusbar_push (GTK_STATUSBAR (data->statusbar), 0, 
523                           tooltip ? tooltip : "");
524       
525       g_free (tooltip);
526     }
527 }
528
529 static void
530 unset_tip (GtkWidget *widget)
531 {
532   ActionStatus *data;
533
534   data = g_object_get_data (G_OBJECT (widget), "action-status");
535
536   if (data)
537     gtk_statusbar_pop (GTK_STATUSBAR (data->statusbar), 0);
538 }
539                     
540 static void
541 connect_proxy (GtkUIManager *merge,
542                GtkAction    *action,
543                GtkWidget    *proxy,
544                GtkWidget    *statusbar)
545 {
546   if (GTK_IS_MENU_ITEM (proxy)) 
547     {
548       ActionStatus *data;
549
550       data = g_object_get_data (G_OBJECT (proxy), "action-status");
551       if (data)
552         {
553           g_object_unref (data->action);
554           g_object_unref (data->statusbar);
555
556           data->action = g_object_ref (action);
557           data->statusbar = g_object_ref (statusbar);
558         }
559       else
560         {
561           data = g_new0 (ActionStatus, 1);
562
563           data->action = g_object_ref (action);
564           data->statusbar = g_object_ref (statusbar);
565
566           g_object_set_data_full (G_OBJECT (proxy), "action-status", 
567                                   data, action_status_destroy);
568           
569           g_signal_connect (proxy, "select",  G_CALLBACK (set_tip), NULL);
570           g_signal_connect (proxy, "deselect", G_CALLBACK (unset_tip), NULL);
571         }
572     }
573 }
574
575 int
576 main (int argc, char **argv)
577 {
578   GtkActionGroup *action_group;
579   GtkAction *action;
580   GtkUIManager *merge;
581   GtkWidget *window, *grid, *frame, *menu_box, *vbox, *view;
582   GtkWidget *button, *area, *statusbar;
583   GtkWidget *box;
584   gint i;
585   
586   gtk_init (&argc, &argv);
587
588   action_group = gtk_action_group_new ("TestActions");
589   gtk_action_group_add_actions (action_group, 
590                                 entries, n_entries, 
591                                 NULL);
592   action = gtk_action_group_get_action (action_group, "EmptyMenu1Action");
593   g_object_set (action, "hide_if_empty", FALSE, NULL);
594   action = gtk_action_group_get_action (action_group, "EmptyMenu2Action");
595   g_object_set (action, "hide_if_empty", TRUE, NULL);
596   gtk_action_group_add_toggle_actions (action_group, 
597                                        toggle_entries, n_toggle_entries, 
598                                        NULL);
599   gtk_action_group_add_radio_actions (action_group, 
600                                       radio_entries, n_radio_entries, 
601                                       JUSTIFY_RIGHT,
602                                       G_CALLBACK (radio_action_changed), NULL);
603
604   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
605   gtk_window_set_default_size (GTK_WINDOW (window), -1, 400);
606   g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
607
608   grid = gtk_grid_new ();
609   gtk_grid_set_row_spacing (GTK_GRID (grid), 2);
610   gtk_grid_set_column_spacing (GTK_GRID (grid), 2);
611   gtk_container_set_border_width (GTK_CONTAINER (grid), 2);
612   gtk_container_add (GTK_CONTAINER (window), grid);
613
614   frame = gtk_frame_new ("Menus and Toolbars");
615   gtk_grid_attach (GTK_GRID (grid), frame, 0, 1, 2, 1);
616   
617   menu_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
618   gtk_container_set_border_width (GTK_CONTAINER (menu_box), 2);
619   gtk_container_add (GTK_CONTAINER (frame), menu_box);
620
621   statusbar = gtk_statusbar_new ();
622   gtk_box_pack_end (GTK_BOX (menu_box), statusbar, FALSE, FALSE, 0);
623     
624   area = gtk_drawing_area_new ();
625   gtk_widget_set_events (area, GDK_BUTTON_PRESS_MASK);
626   gtk_widget_set_size_request (area, -1, 40);
627   gtk_box_pack_end (GTK_BOX (menu_box), area, FALSE, FALSE, 0);
628   gtk_widget_show (area);
629
630   button = gtk_button_new ();
631   gtk_box_pack_end (GTK_BOX (menu_box), button, FALSE, FALSE, 0);
632   gtk_activatable_set_related_action (GTK_ACTIVATABLE (button),
633                             gtk_action_group_get_action (action_group, "AboutAction"));
634
635   gtk_widget_show (button);
636
637   button = gtk_check_button_new ();
638   gtk_box_pack_end (GTK_BOX (menu_box), button, FALSE, FALSE, 0);
639   gtk_activatable_set_related_action (GTK_ACTIVATABLE (button),
640                             gtk_action_group_get_action (action_group, "BoldAction"));
641   gtk_widget_show (button);
642
643   box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
644   gtk_box_pack_end (GTK_BOX (menu_box), box, FALSE, FALSE, 0);
645   gtk_container_add (GTK_CONTAINER (box), gtk_label_new ("Bold:"));
646   button = gtk_switch_new ();
647   gtk_container_add (GTK_CONTAINER (box), button);
648   gtk_activatable_set_related_action (GTK_ACTIVATABLE (button),
649                             gtk_action_group_get_action (action_group, "BoldAction"));
650   gtk_widget_show_all (box);
651
652   merge = gtk_ui_manager_new ();
653
654   g_signal_connect (merge, "connect-proxy", G_CALLBACK (connect_proxy), statusbar);
655   g_signal_connect (area, "button_press_event", G_CALLBACK (area_press), merge);
656
657   gtk_ui_manager_insert_action_group (merge, action_group, 0);
658   g_signal_connect (merge, "add_widget", G_CALLBACK (add_widget), menu_box);
659
660   gtk_window_add_accel_group (GTK_WINDOW (window), 
661                               gtk_ui_manager_get_accel_group (merge));
662   
663   frame = gtk_frame_new ("UI Files");
664   gtk_widget_set_vexpand (frame, TRUE);
665   gtk_grid_attach (GTK_GRID (grid), frame, 0, 0, 1, 1);
666
667   vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2);
668   gtk_container_set_border_width (GTK_CONTAINER (vbox), 2);
669   gtk_container_add (GTK_CONTAINER (frame), vbox);
670
671   for (i = 0; i < G_N_ELEMENTS (merge_ids); i++)
672     {
673       button = gtk_check_button_new_with_label (merge_ids[i].filename);
674       g_object_set_data (G_OBJECT (button), "mergenum", GINT_TO_POINTER (i));
675       g_signal_connect (button, "toggled", G_CALLBACK (toggle_merge), merge);
676       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
677       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
678     }
679
680   button = gtk_check_button_new_with_label ("Tearoffs");
681   g_signal_connect (button, "clicked", G_CALLBACK (toggle_tearoffs), merge);
682   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
683
684   button = gtk_check_button_new_with_label ("Dynamic");
685   g_signal_connect (button, "clicked", G_CALLBACK (toggle_dynamic), merge);
686   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
687
688   button = gtk_button_new_with_label ("Activate path");
689   g_signal_connect (button, "clicked", G_CALLBACK (activate_path), merge);
690   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
691
692   button = gtk_button_new_with_label ("Dump Tree");
693   g_signal_connect (button, "clicked", G_CALLBACK (dump_tree), merge);
694   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
695
696   button = gtk_button_new_with_label ("Dump Toplevels");
697   g_signal_connect (button, "clicked", G_CALLBACK (dump_toplevels), merge);
698   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
699
700   button = gtk_button_new_with_label ("Dump Accels");
701   g_signal_connect (button, "clicked", G_CALLBACK (dump_accels), NULL);
702   gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
703
704   view = create_tree_view (merge);
705   gtk_widget_set_hexpand (view, TRUE);
706   gtk_widget_set_vexpand (view, TRUE);
707   gtk_grid_attach (GTK_GRID (grid), view, 1, 0, 1, 1);
708
709   gtk_widget_show_all (window);
710   gtk_main ();
711
712 #ifdef DEBUG_UI_MANAGER
713   {
714     GList *action;
715     
716     g_print ("\n> before unreffing the ui manager <\n");
717     for (action = gtk_action_group_list_actions (action_group);
718          action; 
719          action = action->next)
720       {
721         GtkAction *a = action->data;
722         g_print ("  action %s ref count %d\n", 
723                  gtk_action_get_name (a), G_OBJECT (a)->ref_count);
724       }
725   }
726 #endif
727
728   g_object_unref (merge);
729
730 #ifdef DEBUG_UI_MANAGER
731   {
732     GList *action;
733
734     g_print ("\n> after unreffing the ui manager <\n");
735     for (action = gtk_action_group_list_actions (action_group);
736          action; 
737          action = action->next)
738       {
739         GtkAction *a = action->data;
740         g_print ("  action %s ref count %d\n", 
741                  gtk_action_get_name (a), G_OBJECT (a)->ref_count);
742       }
743   }
744 #endif
745
746   g_object_unref (action_group);
747
748   return 0;
749 }