]> Pileus Git - ~andy/gtk/blob - tests/testmerge.c
Rename GtkMenuMerge to GtkUIManager.
[~andy/gtk] / tests / testmerge.c
1 #include <stdio.h>
2 #include <string.h>
3 #include <gtk/gtk.h>
4
5 #ifndef _
6 #  define _(String) (String)
7 #  define N_(String) (String)
8 #endif
9
10 struct { const gchar *filename; guint merge_id; } merge_ids[] = {
11   { "merge-1.ui", 0 },
12   { "merge-2.ui", 0 },
13   { "merge-3.ui", 0 }
14 };
15
16 static void
17 dump_tree (GtkWidget    *button, 
18            GtkUIManager *merge)
19 {
20   gchar *dump;
21
22   dump = gtk_ui_manager_get_ui (merge);
23   g_message (dump);
24   g_free (dump);
25 }
26
27 static void
28 activate_action (GtkAction *action)
29 {
30   const gchar *name = gtk_action_get_name (action);
31   const gchar *typename = G_OBJECT_TYPE_NAME (action);
32
33   g_message ("Action %s (type=%s) activated", name, typename);
34 }
35
36 static void
37 toggle_action (GtkAction *action)
38 {
39   const gchar *name = gtk_action_get_name (action);
40   const gchar *typename = G_OBJECT_TYPE_NAME (action);
41
42   g_message ("Action %s (type=%s) activated (active=%d)", name, typename,
43              gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)));
44 }
45
46
47 static GtkActionGroupEntry entries[] = {
48   { "StockFileMenuAction", N_("_File"), NULL, NULL, NULL, NULL, NULL },
49   { "StockEditMenuAction", N_("_Edit"), NULL, NULL, NULL, NULL, NULL },
50   { "StockHelpMenuAction", N_("_Help"), NULL, NULL, NULL, NULL, NULL },
51   { "Test", N_("Test"), NULL, NULL, NULL, NULL, NULL },
52
53   { "NewAction", NULL, GTK_STOCK_NEW, "<control>n", NULL,
54     G_CALLBACK (activate_action), NULL },
55   { "New2Action", NULL, GTK_STOCK_NEW, "<control>m", NULL,
56     G_CALLBACK (activate_action), NULL },
57   { "OpenAction", NULL, GTK_STOCK_OPEN, "<control>o", NULL,
58     G_CALLBACK (activate_action), NULL },
59   { "QuitAction", NULL, GTK_STOCK_QUIT, "<control>q", NULL,
60     G_CALLBACK (gtk_main_quit), NULL },
61   { "CutAction", NULL, GTK_STOCK_CUT, "<control>x", NULL,
62     G_CALLBACK (activate_action), NULL },
63   { "CopyAction", NULL, GTK_STOCK_COPY, "<control>c", NULL,
64     G_CALLBACK (activate_action), NULL },
65   { "PasteAction", NULL, GTK_STOCK_PASTE, "<control>v", NULL,
66     G_CALLBACK (activate_action), NULL },
67   { "justify-left", NULL, GTK_STOCK_JUSTIFY_LEFT, "<control>L",
68     N_("Left justify the text"),
69     G_CALLBACK (toggle_action), NULL, GTK_ACTION_RADIO, NULL },
70   { "justify-center", NULL, GTK_STOCK_JUSTIFY_CENTER, "<control>E",
71     N_("Center justify the text"),
72     G_CALLBACK (toggle_action), NULL, GTK_ACTION_RADIO, "justify-left" },
73   { "justify-right", NULL, GTK_STOCK_JUSTIFY_RIGHT, "<control>R",
74     N_("Right justify the text"),
75     G_CALLBACK (toggle_action), NULL, GTK_ACTION_RADIO, "justify-left" },
76   { "justify-fill", NULL, GTK_STOCK_JUSTIFY_FILL, "<control>J",
77     N_("Fill justify the text"),
78     G_CALLBACK (toggle_action), NULL, GTK_ACTION_RADIO, "justify-left" },
79   { "AboutAction", N_("_About"), NULL, NULL, NULL,
80     G_CALLBACK (activate_action), NULL },
81 };
82 static guint n_entries = G_N_ELEMENTS (entries);
83
84 static void
85 add_widget (GtkUIManager *merge, 
86             GtkWidget    *widget, 
87             GtkBox       *box)
88 {
89   gtk_box_pack_start (box, widget, FALSE, FALSE, 0);
90   gtk_widget_show (widget);
91 }
92
93 static void
94 toggle_merge (GtkWidget    *button, 
95               GtkUIManager *merge)
96 {
97   gint mergenum;
98
99   mergenum = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (button), "mergenum"));
100
101   if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)))
102     {
103       GError *err = NULL;
104
105       g_message ("merging %s", merge_ids[mergenum].filename);
106       merge_ids[mergenum].merge_id =
107         gtk_ui_manager_add_ui_from_file (merge, merge_ids[mergenum].filename, &err);
108       if (err != NULL)
109         {
110           GtkWidget *dialog;
111
112           dialog = gtk_message_dialog_new (GTK_WINDOW (gtk_widget_get_toplevel (button)),
113                                            0, GTK_MESSAGE_WARNING, GTK_BUTTONS_OK,
114                                            "could not merge %s: %s", merge_ids[mergenum].filename,
115                                            err->message);
116
117           g_signal_connect (G_OBJECT (dialog), "response", G_CALLBACK (gtk_object_destroy), NULL);
118           gtk_widget_show (dialog);
119
120           g_clear_error (&err);
121         }
122     }
123   else
124     {
125       g_message ("unmerging %s (merge_id=%u)", merge_ids[mergenum].filename,
126                  merge_ids[mergenum].merge_id);
127       gtk_ui_manager_remove_ui (merge, merge_ids[mergenum].merge_id);
128     }
129 }
130
131 static void  
132 set_name_func (GtkTreeViewColumn *tree_column,
133                GtkCellRenderer   *cell,
134                GtkTreeModel      *tree_model,
135                GtkTreeIter       *iter,
136                gpointer           data)
137 {
138   GtkAction *action;
139   char *name;
140   
141   gtk_tree_model_get (tree_model, iter, 0, &action, -1);
142   g_object_get (G_OBJECT (action), "name", &name, NULL);
143   g_object_set (G_OBJECT (cell), "text", name, NULL);
144   g_free (name);
145   g_object_unref (action);
146 }
147
148 static void
149 set_sensitive_func (GtkTreeViewColumn *tree_column,
150                     GtkCellRenderer   *cell,
151                     GtkTreeModel      *tree_model,
152                     GtkTreeIter       *iter,
153                     gpointer           data)
154 {
155   GtkAction *action;
156   gboolean sensitive;
157   
158   gtk_tree_model_get (tree_model, iter, 0, &action, -1);
159   g_object_get (G_OBJECT (action), "sensitive", &sensitive, NULL);
160   g_object_set (G_OBJECT (cell), "active", sensitive, NULL);
161   g_object_unref (action);
162 }
163
164
165 static void
166 set_visible_func (GtkTreeViewColumn *tree_column,
167                   GtkCellRenderer   *cell,
168                   GtkTreeModel      *tree_model,
169                   GtkTreeIter       *iter,
170                   gpointer           data)
171 {
172   GtkAction *action;
173   gboolean visible;
174   
175   gtk_tree_model_get (tree_model, iter, 0, &action, -1);
176   g_object_get (G_OBJECT (action), "visible", &visible, NULL);
177   g_object_set (G_OBJECT (cell), "active", visible, NULL);
178   g_object_unref (action);
179 }
180
181 static void
182 sensitivity_toggled (GtkCellRendererToggle *cell, 
183                      const gchar           *path_str,
184                      GtkTreeModel          *model)
185 {
186   GtkTreePath *path;
187   GtkTreeIter iter;
188   GtkAction *action;
189   gboolean sensitive;
190
191   path = gtk_tree_path_new_from_string (path_str);
192   gtk_tree_model_get_iter (model, &iter, path);
193
194   gtk_tree_model_get (model, &iter, 0, &action, -1);
195   g_object_get (G_OBJECT (action), "sensitive", &sensitive, NULL);
196   g_object_set (G_OBJECT (action), "sensitive", !sensitive, NULL);
197   gtk_tree_model_row_changed (model, path, &iter);
198   gtk_tree_path_free (path);
199 }
200
201 static void
202 visibility_toggled (GtkCellRendererToggle *cell, 
203                     const gchar           *path_str, 
204                     GtkTreeModel          *model)
205 {
206   GtkTreePath *path;
207   GtkTreeIter iter;
208   GtkAction *action;
209   gboolean visible;
210
211   path = gtk_tree_path_new_from_string (path_str);
212   gtk_tree_model_get_iter (model, &iter, path);
213
214   gtk_tree_model_get (model, &iter, 0, &action, -1);
215   g_object_get (G_OBJECT (action), "visible", &visible, NULL);
216   g_object_set (G_OBJECT (action), "visible", !visible, NULL);
217   gtk_tree_model_row_changed (model, path, &iter);
218   gtk_tree_path_free (path);
219 }
220
221 static gint
222 iter_compare_func (GtkTreeModel *model, 
223                    GtkTreeIter  *a, 
224                    GtkTreeIter  *b,
225                    gpointer      user_data)
226 {
227   GValue a_value = { 0, }, b_value = { 0, };
228   GtkAction *a_action, *b_action;
229   const gchar *a_name, *b_name;
230   gint retval = 0;
231
232   gtk_tree_model_get_value (model, a, 0, &a_value);
233   gtk_tree_model_get_value (model, b, 0, &b_value);
234   a_action = GTK_ACTION (g_value_get_object (&a_value));
235   b_action = GTK_ACTION (g_value_get_object (&b_value));
236
237   a_name = gtk_action_get_name (a_action);
238   b_name = gtk_action_get_name (b_action);
239   if (a_name == NULL && b_name == NULL) 
240     retval = 0;
241   else if (a_name == NULL)
242     retval = -1;
243   else if (b_name == NULL) 
244     retval = 1;
245   else 
246     retval = strcmp (a_name, b_name);
247
248   g_value_unset (&b_value);
249   g_value_unset (&a_value);
250
251   return retval;
252 }
253
254 static GtkWidget *
255 create_tree_view (GtkUIManager *merge)
256 {
257   GtkWidget *tree_view, *sw;
258   GtkListStore *store;
259   GList *p;
260   GtkCellRenderer *cell;
261   
262   store = gtk_list_store_new (1, GTK_TYPE_ACTION);
263   gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (store), 0,
264                                    iter_compare_func, NULL, NULL);
265   gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store), 0,
266                                         GTK_SORT_ASCENDING);
267   
268   for (p = gtk_ui_manager_get_action_groups (merge); p; p = p->next)
269     {
270       GList *actions, *l;
271
272       actions = gtk_action_group_list_actions (p->data);
273
274       for (l = actions; l; l = l->next)
275         {
276           GtkTreeIter iter;
277
278           gtk_list_store_append (store, &iter);
279           gtk_list_store_set (store, &iter, 0, l->data, -1);
280         }
281     }
282   
283   tree_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store));
284   g_object_unref (store);
285
286   gtk_tree_view_insert_column_with_data_func (GTK_TREE_VIEW (tree_view),
287                                               -1, "Action",
288                                               gtk_cell_renderer_text_new (),
289                                               set_name_func, NULL, NULL);
290
291   gtk_tree_view_column_set_sort_column_id (gtk_tree_view_get_column (GTK_TREE_VIEW (tree_view), 0), 0);
292
293   cell = gtk_cell_renderer_toggle_new ();
294   g_signal_connect (cell, "toggled", G_CALLBACK (sensitivity_toggled), store);
295   gtk_tree_view_insert_column_with_data_func (GTK_TREE_VIEW (tree_view),
296                                               -1, "Sensitive",
297                                               cell,
298                                               set_sensitive_func, NULL, NULL);
299
300   cell = gtk_cell_renderer_toggle_new ();
301   g_signal_connect (cell, "toggled", G_CALLBACK (visibility_toggled), store);
302   gtk_tree_view_insert_column_with_data_func (GTK_TREE_VIEW (tree_view),
303                                               -1, "Visible",
304                                               cell,
305                                               set_visible_func, NULL, NULL);
306
307   sw = gtk_scrolled_window_new (NULL, NULL);
308   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
309                                   GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
310   gtk_container_add (GTK_CONTAINER (sw), tree_view);
311   
312   return sw;
313 }
314
315 static gboolean
316 area_press (GtkWidget      *drawing_area,
317             GdkEventButton *event,
318             GtkUIManager   *merge)
319 {
320   gtk_widget_grab_focus (drawing_area);
321
322   if (event->button == 3 &&
323       event->type == GDK_BUTTON_PRESS)
324     {
325       GtkWidget *menu = gtk_ui_manager_get_widget (merge, "/popups/FileMenu");
326       
327       if (GTK_IS_MENU (menu)) 
328         {
329           gtk_menu_popup (GTK_MENU (menu), NULL, NULL,
330                           NULL, drawing_area,
331                           3, event->time);
332           return TRUE;
333         }
334     }
335
336   return FALSE;
337   
338 }
339
340 int
341 main (int argc, char **argv)
342 {
343   GtkActionGroup *action_group;
344   GtkUIManager *merge;
345   GtkWidget *window, *table, *frame, *menu_box, *vbox, *view, *area;
346   GtkWidget *button;
347   gint i;
348   
349   gtk_init (&argc, &argv);
350
351   action_group = gtk_action_group_new ("TestActions");
352   gtk_action_group_add_actions (action_group, entries, n_entries);
353
354   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
355   gtk_window_set_default_size (GTK_WINDOW (window), -1, 400);
356   g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
357
358   table = gtk_table_new (2, 2, FALSE);
359   gtk_table_set_row_spacings (GTK_TABLE (table), 2);
360   gtk_table_set_col_spacings (GTK_TABLE (table), 2);
361   gtk_container_set_border_width (GTK_CONTAINER (table), 2);
362   gtk_container_add (GTK_CONTAINER (window), table);
363
364   frame = gtk_frame_new ("Menus and Toolbars");
365   gtk_table_attach (GTK_TABLE (table), frame, 0,2, 1,2,
366                     GTK_FILL|GTK_EXPAND, GTK_FILL, 0, 0);
367   
368   menu_box = gtk_vbox_new (FALSE, 0);
369   gtk_container_set_border_width (GTK_CONTAINER (menu_box), 2);
370   gtk_container_add (GTK_CONTAINER (frame), menu_box);
371   
372   area = gtk_drawing_area_new ();
373   gtk_widget_set_events (area, GDK_BUTTON_PRESS_MASK);
374   gtk_widget_set_size_request (area, -1, 40);
375   gtk_box_pack_end (GTK_BOX (menu_box), area, FALSE, FALSE, 0);
376   gtk_widget_show (area);
377
378   merge = gtk_ui_manager_new ();
379
380   g_signal_connect (area, "button_press_event",
381                     G_CALLBACK (area_press), merge);
382
383   gtk_ui_manager_insert_action_group (merge, action_group, 0);
384   g_signal_connect (merge, "add_widget", G_CALLBACK (add_widget), menu_box);
385
386   gtk_window_add_accel_group (GTK_WINDOW (window), 
387                               gtk_ui_manager_get_accel_group (merge));
388   
389   frame = gtk_frame_new ("UI Files");
390   gtk_table_attach (GTK_TABLE (table), frame, 0,1, 0,1,
391                     GTK_FILL, GTK_FILL|GTK_EXPAND, 0, 0);
392
393   vbox = gtk_vbox_new (FALSE, 2);
394   gtk_container_set_border_width (GTK_CONTAINER (vbox), 2);
395   gtk_container_add (GTK_CONTAINER (frame), vbox);
396
397   for (i = 0; i < G_N_ELEMENTS (merge_ids); i++)
398     {
399       button = gtk_check_button_new_with_label (merge_ids[i].filename);
400       g_object_set_data (G_OBJECT (button), "mergenum", GINT_TO_POINTER (i));
401       g_signal_connect (button, "toggled", G_CALLBACK (toggle_merge), merge);
402       gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
403       gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), TRUE);
404     }
405
406   button = gtk_button_new_with_mnemonic ("_Dump Tree");
407   g_signal_connect (button, "clicked", G_CALLBACK (dump_tree), merge);
408   gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
409
410   view = create_tree_view (merge);
411   gtk_table_attach (GTK_TABLE (table), view, 1,2, 0,1,
412                     GTK_FILL|GTK_EXPAND, GTK_FILL|GTK_EXPAND, 0, 0);
413
414   gtk_widget_show_all (window);
415   gtk_main ();
416
417
418   return 0;
419 }