offset fixes, admit to textline, proper updating of height/font at attr set,
[dia.git] / app / menus.c
blobd3bf93175fb44688493d2f594b1204bd2b0f5807
1 /* Dia -- an diagram creation/manipulation program
2 * Copyright (C) 1998 Alexander Larsson
3 * Copyright (C) 2006 Robert Staudinger <robert.staudinger@gmail.com>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
24 #include <gtk/gtk.h>
25 #include <gdk/gdkkeysyms.h>
26 #include <string.h>
28 #include "intl.h"
29 #include "menus.h"
30 #include "tool.h"
31 #include "commands.h"
32 #include "message.h"
33 #include "interface.h"
34 #include "display.h"
35 #include "filedlg.h"
36 #include "plugin-manager.h"
37 #include "select.h"
38 #include "dia_dirs.h"
39 #include "diagram_tree_window.h"
40 #include "object_ops.h"
41 #include "sheets.h"
42 #include "dia-app-icons.h"
44 #define DIA_STOCK_GROUP "dia-stock-group"
45 #define DIA_STOCK_UNGROUP "dia-stock-ungroup"
47 #define DIA_SHOW_TEAROFFS TRUE
49 static void plugin_callback (GtkWidget *widget, gpointer data);
51 /* Actions common to toolbox and diagram window */
52 static const GtkActionEntry common_entries[] =
54 { "File", NULL, N_("_File"), NULL, NULL, NULL },
55 { "FileNew", GTK_STOCK_NEW, NULL, "<control>N", NULL, G_CALLBACK (file_new_callback) },
56 { "FileOpen", GTK_STOCK_OPEN, NULL,"<control>O", NULL, G_CALLBACK (file_open_callback) },
57 { "FileQuit", GTK_STOCK_QUIT, NULL, "<control>Q", NULL, G_CALLBACK (file_quit_callback) },
58 { "Help", NULL, N_("_Help"), NULL, NULL, NULL },
59 { "HelpContents", GTK_STOCK_HELP, NULL, NULL, NULL, G_CALLBACK (help_manual_callback) },
60 { "HelpAbout", GTK_STOCK_ABOUT, NULL, NULL, NULL, G_CALLBACK (help_about_callback) }
63 /* Actions for toolbox menu */
64 static const GtkActionEntry toolbox_entries[] =
66 { "FileSheets", NULL, N_("Sheets and Objects..."), "F9", NULL, G_CALLBACK (sheets_dialog_show_callback) },
67 { "FilePrefs", GTK_STOCK_PREFERENCES, NULL, NULL, NULL, G_CALLBACK (file_preferences_callback) },
68 { "FilePlugins", NULL, N_("Plugins..."), NULL, NULL, G_CALLBACK (file_plugins_callback) }
71 /* Toggle-Actions for toolbox menu */
72 static const GtkToggleActionEntry toolbox_toggle_entries[] =
74 { "FileTree", NULL, N_("_Diagram tree..."), "F8", NULL, G_CALLBACK (diagtree_show_callback) }
77 /* Actions for diagram window */
78 static const GtkActionEntry display_entries[] =
80 { "FileSave", GTK_STOCK_SAVE, NULL, "<control>S", NULL, G_CALLBACK (file_save_callback) },
81 { "FileSaveas", GTK_STOCK_SAVE_AS, NULL, "<control><shift>S", NULL, G_CALLBACK (file_save_as_callback) },
82 { "FileExport", GTK_STOCK_CONVERT, N_("_Export ..."), NULL, NULL, G_CALLBACK (file_export_callback) },
83 { "FilePagesetup", NULL, N_("Page Set_up..."), NULL, NULL, G_CALLBACK (file_pagesetup_callback) },
84 { "FilePrint", GTK_STOCK_PRINT, NULL, "<control>P", NULL, G_CALLBACK (file_print_callback) },
85 { "FileClose", GTK_STOCK_CLOSE, NULL, "<control>W", NULL, G_CALLBACK (file_close_callback) },
87 { "Edit", NULL, N_("_Edit"), NULL, NULL, NULL },
88 { "EditUndo", GTK_STOCK_UNDO, NULL, "<control>Z", NULL, G_CALLBACK (edit_undo_callback) },
89 { "EditRedo", GTK_STOCK_REDO, NULL, "<control><shift>Z", NULL, G_CALLBACK (edit_redo_callback) },
91 { "EditCopy", GTK_STOCK_COPY, NULL, "<control>C", NULL, G_CALLBACK (edit_copy_callback) },
92 { "EditCut", GTK_STOCK_CUT, NULL, "<control>X", NULL, G_CALLBACK (edit_cut_callback) },
93 { "EditPaste", GTK_STOCK_PASTE, NULL, "<control>V", NULL, G_CALLBACK (edit_paste_callback) },
94 { "EditDuplicate", NULL, N_("_Duplicate"), "<control>D", NULL, G_CALLBACK (edit_duplicate_callback) },
95 { "EditDelete", GTK_STOCK_DELETE, NULL, "Delete", NULL, G_CALLBACK (edit_delete_callback) },
97 /* the following used to bind to <control><shift>C which collides with Unicode input.
98 * <control>>alt> doesn't work either */
99 { "EditCopytext", NULL, N_("Copy Text"), NULL, NULL, G_CALLBACK (edit_copy_text_callback) },
100 { "EditCuttext", NULL, N_("Cut Text"), "<control><shift>X", NULL, G_CALLBACK (edit_cut_text_callback) },
101 { "EditPastetext", NULL, N_("Paste _Text"), "<control><shift>V", NULL, G_CALLBACK (edit_paste_text_callback) },
103 { "Diagram", NULL, N_("_Diagram"), NULL, NULL, NULL },
104 { "DiagramProperties", GTK_STOCK_PROPERTIES, NULL, NULL, NULL, G_CALLBACK (view_diagram_properties_callback) },
105 { "DiagramLayers", NULL, N_("_Layers..."), NULL, NULL, G_CALLBACK (dialogs_layers_callback) },
107 { "View", NULL, N_("_View"), NULL, NULL, NULL },
108 { "ViewZoomin", GTK_STOCK_ZOOM_IN, NULL, "<control>plus", NULL, G_CALLBACK (view_zoom_in_callback) },
109 { "ViewZoomout", GTK_STOCK_ZOOM_OUT, NULL, "<control>minus", NULL, G_CALLBACK (view_zoom_out_callback) },
110 { "ViewZoom", NULL, N_("_Zoom"), NULL, NULL, NULL },
111 { "ViewZoom16000", NULL, N_("1600%"), NULL, NULL, G_CALLBACK (view_zoom_set_callback) },
112 { "ViewZoom8000", NULL, N_("800%"), NULL, NULL, G_CALLBACK (view_zoom_set_callback) },
113 { "ViewZoom4000", NULL, N_("400%"), "<alt>4", NULL, G_CALLBACK (view_zoom_set_callback) },
114 { "ViewZoom2830", NULL, N_("283"), NULL, NULL, G_CALLBACK (view_zoom_set_callback) },
115 { "ViewZoom2000", NULL, N_("200"), "<alt>2", NULL, G_CALLBACK (view_zoom_set_callback) },
116 { "ViewZoom1410", NULL, N_("141"), NULL, NULL, G_CALLBACK (view_zoom_set_callback) },
117 { "ViewZoom1000", GTK_STOCK_ZOOM_100, NULL, "<alt>1", NULL, G_CALLBACK (view_zoom_set_callback) },
118 { "ViewZoom850", NULL, N_("85"), NULL, NULL, G_CALLBACK (view_zoom_set_callback) },
119 { "ViewZoom707", NULL, N_("70.7"), NULL, NULL, G_CALLBACK (view_zoom_set_callback) },
120 { "ViewZoom500", NULL, N_("50"), "<alt>5", NULL, G_CALLBACK (view_zoom_set_callback) },
121 { "ViewZoom354", NULL, N_("35.4"), NULL, NULL, G_CALLBACK (view_zoom_set_callback) },
122 { "ViewZoom250", NULL, N_("25"), NULL, NULL, G_CALLBACK (view_zoom_set_callback) },
124 /* "display_toggle_entries" items go here */
126 { "ViewNewview", NULL, N_("New _View"), NULL, NULL, G_CALLBACK (view_new_view_callback) },
127 { "ViewCloneview", NULL, N_("C_lone View"), NULL, NULL, G_CALLBACK (view_clone_view_callback) },
128 /* Show All, Best Fit. Same as the Gimp, Ctrl+E */
129 { "ViewShowall", GTK_STOCK_ZOOM_FIT, NULL, "<control>E", NULL, G_CALLBACK (view_show_all_callback) },
130 { "ViewRedraw", GTK_STOCK_REFRESH, NULL, NULL, NULL, G_CALLBACK (view_redraw_callback) },
132 { "Objects", NULL, N_("_Objects"), NULL, NULL },
133 { "ObjectsSendtoback", GTK_STOCK_GOTO_BOTTOM, N_("Send to _Back"), "<control>B", NULL, G_CALLBACK (objects_place_under_callback) },
134 { "ObjectsBringtofront", GTK_STOCK_GOTO_TOP, N_("Bring to _Front"), "<control>F", NULL, G_CALLBACK (objects_place_over_callback) },
135 { "ObjectsSendbackwards", GTK_STOCK_GO_DOWN, N_("Send Backwards"), NULL, NULL, G_CALLBACK (objects_place_down_callback) },
136 { "ObjectsBringforwards", GTK_STOCK_GO_UP, N_("Bring Forwards"), NULL, NULL, G_CALLBACK (objects_place_up_callback) },
138 { "ObjectsGroup", DIA_STOCK_GROUP, N_("_Group"), "<control>G", NULL, G_CALLBACK (objects_group_callback) },
139 /* deliberately not using Ctrl+U for Ungroup */
140 { "ObjectsUngroup", DIA_STOCK_UNGROUP, N_("_Ungroup"), "<control><shift>G", NULL, G_CALLBACK (objects_ungroup_callback) },
142 { "ObjectsParent", NULL, N_("_Parent"), "<control>L", NULL, G_CALLBACK (objects_parent_callback) },
143 { "ObjectsUnparent", NULL, N_("_Unparent"), "<control><shift>L", NULL, G_CALLBACK (objects_unparent_callback) },
144 { "ObjectsUnparentchildren", NULL, N_("_Unparent Children"), NULL, NULL, G_CALLBACK (objects_unparent_children_callback) },
146 { "ObjectsAlign", NULL, N_("Align"), NULL, NULL, NULL },
147 { "ObjectsAlignLeft", GTK_STOCK_JUSTIFY_LEFT, NULL, "<alt><shift>L", NULL, G_CALLBACK (objects_align_h_callback) },
148 { "ObjectsAlignCenter", GTK_STOCK_JUSTIFY_CENTER, NULL, "<alt><shift>C", NULL, G_CALLBACK (objects_align_h_callback) },
149 { "ObjectsAlignRight", GTK_STOCK_JUSTIFY_RIGHT, NULL, "<alt><shift>R", NULL, G_CALLBACK (objects_align_h_callback) },
151 { "ObjectsAlignTop", NULL, N_("Top"), "<alt><shift>T", NULL, G_CALLBACK (objects_align_v_callback) },
152 { "ObjectsAlignMiddle", NULL, N_("Middle"), "<alt><shift>M", NULL, G_CALLBACK (objects_align_v_callback) },
153 { "ObjectsAlignBottom", NULL, N_("Bottom"), "<alt><shift>B", NULL, G_CALLBACK (objects_align_v_callback) },
155 { "ObjectsAlignSpreadouthorizontally", NULL, N_("Spread Out Horizontally"), "<alt><shift>H", NULL, G_CALLBACK (objects_align_h_callback) },
156 { "ObjectsAlignSpreadoutvertically", NULL, N_("Spread Out Vertically"), "<alt><shift>V", NULL, G_CALLBACK (objects_align_v_callback) },
157 { "ObjectsAlignAdjacent", NULL, N_("Adjacent"), "<alt><shift>A", NULL, G_CALLBACK (objects_align_h_callback) },
158 { "ObjectsAlignStacked", NULL, N_("Stacked"), "<alt><shift>S", NULL, G_CALLBACK (objects_align_v_callback) },
160 { "ObjectsProperties", GTK_STOCK_PROPERTIES, NULL, NULL, NULL, G_CALLBACK (dialogs_properties_callback) },
162 { "Select", NULL, N_("_Select"), NULL, NULL, NULL },
163 { "SelectAll", NULL, N_("All"), "<control>A", NULL, G_CALLBACK (select_all_callback) },
164 { "SelectNone", NULL, N_("None"), NULL, NULL, G_CALLBACK (select_none_callback) },
165 { "SelectInvert", NULL, N_("Invert"), "<control>I", NULL, G_CALLBACK (select_invert_callback) },
167 { "SelectTransitive", NULL, N_("Transitive"), "<control>T", NULL, G_CALLBACK (select_transitive_callback) },
168 { "SelectConnected", NULL, N_("Connected"), "<control><shift>T", NULL, G_CALLBACK (select_connected_callback) },
169 { "SelectSametype", NULL, N_("Same Type"), NULL, NULL, G_CALLBACK (select_same_type_callback) },
171 /* display_select_radio_entries go here */
173 { "SelectBy", NULL, N_("Select By"), NULL, NULL, NULL },
175 { "InputMethods", NULL, N_("_Input Methods"), NULL, NULL, NULL },
177 { "Dialogs", NULL, N_("D_ialogs"), NULL, NULL, NULL },
179 { "Debug", NULL, N_("D_ebug"), NULL, NULL, NULL }
182 /* Standard-Tool entries */
183 static const GtkActionEntry tool_entries[] =
185 { "Tools", NULL, N_("_Tools"), NULL, NULL, NULL },
186 { "ToolsModify", NULL, N_("Modify"), "<alt>N", NULL, NULL },
187 { "ToolsMagnify", NULL, N_("Magnify"), "<alt>M", NULL, NULL },
188 { "ToolsScroll", NULL, N_("Scroll"), "<alt>S", NULL, NULL },
189 { "ToolsText", NULL, N_("Text"), "<alt>T", NULL, NULL },
190 { "ToolsBox", NULL, N_("Box"), "<alt>R", NULL, NULL },
191 { "ToolsEllipse", NULL, N_("Ellipse"), "<alt>E", NULL, NULL },
192 { "ToolsPolygon", NULL, N_("Polygon"), "<alt>P", NULL, NULL },
193 { "ToolsBeziergon", NULL, N_("Beziergon"), "<alt>B", NULL, NULL },
195 { "ToolsLine", NULL, N_("Line"), "<alt>L", NULL, NULL },
196 { "ToolsArc", NULL, N_("Arc"), "<alt>A", NULL, NULL },
197 { "ToolsZigzagline", NULL, N_("Zigzagline"), "<alt>Z", NULL, NULL },
198 { "ToolsPolyline", NULL, N_("Polyline"), NULL, NULL },
199 { "ToolsBezierline", NULL, N_("Bezierline"), "<alt>C", NULL, NULL },
201 { "ToolsImage", NULL, N_("Image"), "<alt>I", NULL, NULL },
204 /* Toggle-Actions for diagram window */
205 static const GtkToggleActionEntry display_toggle_entries[] =
207 #ifdef GTK_STOCK_FULLSCREEN /* added with gtk+-2.8, but no reason to depend on it */
208 { "ViewFullscreen", GTK_STOCK_FULLSCREEN, NULL, "F11", NULL, G_CALLBACK (view_fullscreen_callback) },
209 #else
210 { "ViewFullscreen", NULL, N_("Fullscr_een"), "F11", NULL, G_CALLBACK (view_fullscreen_callback) },
211 #endif
212 #ifdef HAVE_LIBART
213 { "ViewAntialiased", NULL, N_("_AntiAliased"), NULL, NULL, G_CALLBACK (view_aa_callback) },
214 #endif
215 { "ViewShowgrid", NULL, N_("Show _Grid"), NULL, NULL, G_CALLBACK (view_visible_grid_callback) },
216 { "ViewSnaptogrid", NULL, N_("_Snap To Grid"), NULL, NULL, G_CALLBACK (view_snap_to_grid_callback) },
217 { "ViewSnaptoobjects", NULL, N_("Snap To _Objects"), NULL, NULL, G_CALLBACK (view_snap_to_objects_callback) },
218 { "ViewShowrulers", NULL, N_("Show _Rulers"), NULL, NULL, G_CALLBACK (view_toggle_rulers_callback) },
219 { "ViewShowconnectionpoints", NULL, N_("Show _Connection Points"), NULL, NULL, G_CALLBACK (view_show_cx_pts_callback) }
222 /* Radio-Actions for the diagram window's "Select"-Menu */
223 static const GtkRadioActionEntry display_select_radio_entries[] =
225 { "SelectReplace", NULL, N_("Replace"), NULL, NULL, SELECT_REPLACE },
226 { "SelectUnion", NULL, N_("Union"), NULL, NULL, SELECT_UNION },
227 { "SelectIntersection", NULL, N_("Intersection"), NULL, NULL, SELECT_INTERSECTION },
228 { "SelectRemove", NULL, N_("Remove"), NULL, NULL, SELECT_REMOVE },
229 /* Cannot also be called Invert, duplicate names caused keybinding problems */
230 { "SelectInverse", NULL, N_("Inverse"), NULL, NULL, SELECT_INVERT }
233 /* need initialisation? */
234 static gboolean initialise = TRUE;
236 /* toolbox */
237 static GtkUIManager *toolbox_ui_manager = NULL;
238 static GtkActionGroup *toolbox_actions = NULL;
239 static GtkAccelGroup *toolbox_accels = NULL;
240 static GtkWidget *toolbox_menubar = NULL;
242 GtkActionGroup *recent_actions = NULL;
243 static GSList *recent_merge_ids = NULL;
245 /* diagram */
246 static GtkUIManager *display_ui_manager = NULL;
247 static GtkActionGroup *display_actions = NULL;
248 static GtkActionGroup *display_tool_actions = NULL;
249 static GtkAccelGroup *display_accels = NULL;
250 static GtkWidget *display_menubar = NULL;
252 static void
253 tool_menu_select(GtkWidget *w, gpointer data) {
254 ToolButtonData *tooldata = (ToolButtonData *) data;
256 if (tooldata == NULL) {
257 g_warning(_("NULL tooldata in tool_menu_select"));
258 return;
261 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(tooldata->widget),TRUE);
264 static gint
265 save_accels(gpointer data)
267 gchar *accelfilename;
269 accelfilename = dia_config_filename("menurc");
270 if (accelfilename) {
271 gtk_accel_map_save (accelfilename);
272 g_free (accelfilename);
274 return TRUE;
278 * Initialise tool actions.
279 * The caller owns the return value.
281 static GtkActionGroup *
282 create_tool_actions (void)
284 GtkActionGroup *actions;
285 GtkAction *action;
286 int i;
287 gchar *name;
288 static guint cnt = 0;
290 name = g_strdup_printf ("tool-actions-%d", cnt);
291 actions = gtk_action_group_new (name);
292 gtk_action_group_set_translation_domain (actions, NULL);
293 g_free (name);
294 name = NULL;
295 cnt++;
297 gtk_action_group_add_actions (actions, tool_entries,
298 G_N_ELEMENTS (tool_entries), NULL);
300 for (i = 0; i < num_tools; i++) {
301 action = gtk_action_group_get_action (actions, tool_data[i].action_name);
302 if (action != NULL) {
303 g_signal_connect (G_OBJECT (action), "activate",
304 G_CALLBACK (tool_menu_select),
305 &tool_data[i].callback_data);
307 else {
308 g_warning ("couldn't find tool menu item %s", tool_data[i].action_name);
311 return actions;
314 /* initialize callbacks from plug-ins */
315 static void
316 add_plugin_actions (GtkUIManager *ui_manager)
318 GtkActionGroup *actions;
319 GtkAction *action;
320 GList *cblist;
321 DiaCallbackFilter *cbf = NULL;
322 gchar *name;
323 guint id;
324 static guint cnt = 0;
326 name = g_strdup_printf ("plugin-actions-%d", cnt);
327 actions = gtk_action_group_new (name);
328 gtk_action_group_set_translation_domain (actions, NULL);
329 g_free (name);
330 name = NULL;
331 cnt++;
333 gtk_ui_manager_insert_action_group (ui_manager, actions, 5 /* "back" */);
334 g_object_unref (actions);
336 for (cblist = filter_get_callbacks(); cblist; cblist = cblist->next) {
338 cbf = cblist->data;
340 if (cbf == NULL) {
341 g_warning ("missing DiaCallbackFilter instance");
342 continue;
345 if (cbf->action == NULL) {
346 g_warning ("Plugin '%s': doesn't specify action. Loading failed.",
347 cbf->description);
348 continue;
351 if (0 == strncmp (cbf->menupath, TOOLBOX_MENU, strlen (TOOLBOX_MENU))) {
352 /* hook for toolbox, skip */
353 continue;
356 action = gtk_action_new (cbf->action, cbf->description, NULL, NULL);
357 g_signal_connect (G_OBJECT (action), "activate",
358 G_CALLBACK (plugin_callback), (gpointer) cbf);
360 gtk_action_group_add_action (actions, action);
361 g_object_unref (G_OBJECT (action));
363 id = gtk_ui_manager_new_merge_id (ui_manager);
364 gtk_ui_manager_add_ui (ui_manager, id,
365 cbf->menupath,
366 cbf->description,
367 cbf->action,
368 GTK_UI_MANAGER_AUTO,
369 FALSE);
373 static void
374 register_stock_icons (void)
376 GtkIconFactory *factory;
377 GtkIconSet *set;
378 GdkPixbuf *pixbuf;
379 GError *err = NULL;
381 factory = gtk_icon_factory_new ();
383 pixbuf = gdk_pixbuf_new_from_inline (sizeof (dia_group_icon), dia_group_icon, FALSE, &err);
384 if (err) {
385 g_warning (err->message);
386 g_error_free (err);
387 err = NULL;
389 set = gtk_icon_set_new_from_pixbuf (pixbuf);
390 gtk_icon_factory_add (factory, DIA_STOCK_GROUP, set);
391 g_object_unref (pixbuf);
392 pixbuf = NULL;
394 pixbuf = gdk_pixbuf_new_from_inline (sizeof (dia_ungroup_icon), dia_ungroup_icon, FALSE, &err);
395 if (err) {
396 g_warning (err->message);
397 g_error_free (err);
398 err = NULL;
400 set = gtk_icon_set_new_from_pixbuf (pixbuf);
401 gtk_icon_factory_add (factory, DIA_STOCK_UNGROUP, set);
402 g_object_unref (pixbuf);
403 pixbuf = NULL;
405 gtk_icon_factory_add_default (factory);
406 g_object_unref (factory);
407 factory = NULL;
410 static gchar*
411 build_ui_filename (const gchar* name)
413 gchar* uifile;
415 if (g_getenv ("DIA_BASE_PATH") != NULL) {
416 /* a small hack cause the final destination and the local path differ */
417 const gchar* p = strrchr (name, '/');
418 if (p != NULL)
419 name = p+1;
420 uifile = g_build_filename (g_getenv ("DIA_BASE_PATH"), "data", name, NULL);
421 } else
422 uifile = dia_get_data_directory (name);
424 return uifile;
427 static void
428 menus_init(void)
430 DiaCallbackFilter *cbf;
431 GtkActionGroup *plugin_actions;
432 GtkAction *action;
433 gchar *accelfilename;
434 GList *cblist;
435 guint id;
436 GError *error = NULL;
437 gchar *uifile;
439 if (!initialise)
440 return;
442 initialise = FALSE;
444 register_stock_icons ();
446 /* the toolbox menu */
447 toolbox_actions = gtk_action_group_new ("toolbox-actions");
448 gtk_action_group_set_translation_domain (toolbox_actions, NULL);
449 gtk_action_group_add_actions (toolbox_actions, common_entries,
450 G_N_ELEMENTS (common_entries), NULL);
451 gtk_action_group_add_actions (toolbox_actions, toolbox_entries,
452 G_N_ELEMENTS (toolbox_entries), NULL);
453 gtk_action_group_add_toggle_actions (toolbox_actions, toolbox_toggle_entries,
454 G_N_ELEMENTS (toolbox_toggle_entries),
455 NULL);
457 toolbox_ui_manager = gtk_ui_manager_new ();
458 gtk_ui_manager_set_add_tearoffs (toolbox_ui_manager, DIA_SHOW_TEAROFFS);
459 gtk_ui_manager_insert_action_group (toolbox_ui_manager, toolbox_actions, 0);
460 uifile = build_ui_filename ("ui/toolbox-ui.xml");
461 if (!gtk_ui_manager_add_ui_from_file (toolbox_ui_manager, uifile, &error)) {
462 g_warning ("building menus failed: %s", error->message);
463 g_error_free (error);
464 error = NULL;
466 g_free (uifile);
468 toolbox_accels = gtk_ui_manager_get_accel_group (toolbox_ui_manager);
469 toolbox_menubar = gtk_ui_manager_get_widget (toolbox_ui_manager, "/ToolboxMenu");
472 /* the display menu */
473 display_actions = gtk_action_group_new ("display-actions");
474 gtk_action_group_set_translation_domain (display_actions, NULL);
475 gtk_action_group_add_actions (display_actions, common_entries,
476 G_N_ELEMENTS (common_entries), NULL);
477 gtk_action_group_add_actions (display_actions, display_entries,
478 G_N_ELEMENTS (display_entries), NULL);
479 gtk_action_group_add_toggle_actions (display_actions, display_toggle_entries,
480 G_N_ELEMENTS (display_toggle_entries),
481 NULL);
482 gtk_action_group_add_radio_actions (display_actions,
483 display_select_radio_entries,
484 G_N_ELEMENTS (display_select_radio_entries),
486 G_CALLBACK (select_style_callback),
487 NULL);
489 display_tool_actions = create_tool_actions ();
491 display_ui_manager = gtk_ui_manager_new ();
492 gtk_ui_manager_set_add_tearoffs (display_ui_manager, DIA_SHOW_TEAROFFS);
493 gtk_ui_manager_insert_action_group (display_ui_manager, display_actions, 0);
494 gtk_ui_manager_insert_action_group (display_ui_manager, display_tool_actions, 0);
495 uifile = build_ui_filename ("ui/popup-ui.xml");
496 /* TODO it would be more elegant if we had only one definition of the
497 * menu hierarchy and merge it into a popup somehow. */
498 if (!gtk_ui_manager_add_ui_from_file (display_ui_manager, uifile, &error)) {
499 g_warning ("building menus failed: %s", error->message);
500 g_error_free (error);
501 error = NULL;
503 g_free (uifile);
505 display_accels = gtk_ui_manager_get_accel_group (display_ui_manager);
506 display_menubar = gtk_ui_manager_get_widget (display_ui_manager, "/DisplayMenu");
507 g_assert (display_menubar);
510 /* plugin menu hooks */
511 plugin_actions = gtk_action_group_new ("toolbox-plugin-actions");
512 gtk_action_group_set_translation_domain (plugin_actions, NULL);
513 gtk_ui_manager_insert_action_group (toolbox_ui_manager,
514 plugin_actions, 5 /* "back" */);
515 g_object_unref (plugin_actions);
517 for (cblist = filter_get_callbacks(); cblist; cblist = cblist->next) {
519 cbf = cblist->data;
521 if (cbf == NULL) {
522 g_warning ("missing DiaCallbackFilter instance");
523 continue;
526 if (cbf->action == NULL) {
527 g_warning ("Plugin '%s': doesn't specify action. Loading failed.",
528 cbf->description);
529 continue;
532 if (0 != strncmp (cbf->menupath, TOOLBOX_MENU, strlen (TOOLBOX_MENU))) {
533 /* hook for display, skip */
534 continue;
537 action = gtk_action_new (cbf->action, cbf->description,
538 NULL, NULL);
539 g_signal_connect (G_OBJECT (action), "activate",
540 G_CALLBACK (plugin_callback),
541 (gpointer) cbf);
543 gtk_action_group_add_action (plugin_actions, action);
544 g_object_unref (G_OBJECT (action));
546 id = gtk_ui_manager_new_merge_id (toolbox_ui_manager);
547 gtk_ui_manager_add_ui (toolbox_ui_manager, id,
548 cbf->menupath,
549 cbf->description,
550 cbf->action,
551 GTK_UI_MANAGER_AUTO,
552 FALSE);
555 add_plugin_actions (display_ui_manager);
557 /* load accelerators and prepare to later save them */
558 accelfilename = dia_config_filename("menurc");
560 if (accelfilename) {
561 gtk_accel_map_load(accelfilename);
562 g_free(accelfilename);
564 gtk_quit_add(1, save_accels, NULL);
567 void
568 menus_get_toolbox_menubar (GtkWidget **menubar,
569 GtkAccelGroup **accel_group)
571 if (initialise)
572 menus_init();
574 if (menubar)
575 *menubar = toolbox_menubar;
576 if (accel_group)
577 *accel_group = toolbox_accels;
580 GtkWidget *
581 menus_get_display_popup (void)
583 if (initialise)
584 menus_init();
586 return display_menubar;
589 GtkAccelGroup *
590 menus_get_display_accels (void)
592 if (initialise)
593 menus_init();
595 return display_accels;
598 GtkWidget *
599 menus_create_display_menubar (GtkUIManager **ui_manager,
600 GtkActionGroup **actions)
602 GtkActionGroup *tool_actions;
603 GtkWidget *menu_bar;
604 GError *error = NULL;
605 gchar *uifile;
607 *actions = gtk_action_group_new ("display-actions");
608 gtk_action_group_set_translation_domain (*actions, NULL);
610 gtk_action_group_add_actions (*actions, common_entries,
611 G_N_ELEMENTS (common_entries), NULL);
612 gtk_action_group_add_actions (*actions, display_entries,
613 G_N_ELEMENTS (display_entries), NULL);
614 gtk_action_group_add_toggle_actions (*actions, display_toggle_entries,
615 G_N_ELEMENTS (display_toggle_entries),
616 NULL);
617 gtk_action_group_add_radio_actions (*actions,
618 display_select_radio_entries,
619 G_N_ELEMENTS (display_select_radio_entries),
621 G_CALLBACK (select_style_callback),
622 NULL);
624 tool_actions = create_tool_actions ();
626 *ui_manager = gtk_ui_manager_new ();
627 gtk_ui_manager_set_add_tearoffs (*ui_manager, DIA_SHOW_TEAROFFS);
628 gtk_ui_manager_insert_action_group (*ui_manager, *actions, 0);
629 gtk_ui_manager_insert_action_group (*ui_manager, tool_actions, 0);
630 g_object_unref (G_OBJECT (tool_actions));
632 uifile = build_ui_filename ("ui/display-ui.xml");
633 if (!gtk_ui_manager_add_ui_from_file (*ui_manager, uifile, &error)) {
634 g_warning ("building menus failed: %s", error->message);
635 g_error_free (error);
636 g_free (uifile);
637 return NULL;
639 g_free (uifile);
641 add_plugin_actions (*ui_manager);
643 menu_bar = gtk_ui_manager_get_widget (*ui_manager, "/DisplayMenu");
644 return menu_bar;
647 GtkAccelGroup *
648 menus_get_accel_group ()
650 return toolbox_accels;
653 GtkActionGroup *
654 menus_get_action_group ()
656 return toolbox_actions;
659 GtkAction *
660 menus_get_action (const gchar *name)
662 GtkAction *action;
664 action = gtk_action_group_get_action (toolbox_actions, name);
665 if (action == NULL) {
666 action = gtk_action_group_get_action (display_actions, name);
669 return action;
672 void
673 menus_set_recent (GtkActionGroup *actions)
675 GList *list;
676 guint id;
678 if (recent_actions) {
679 menus_clear_recent ();
682 list = gtk_action_group_list_actions (actions);
683 g_return_if_fail (list);
685 recent_actions = actions;
686 g_object_ref (G_OBJECT (recent_actions));
687 gtk_ui_manager_insert_action_group (toolbox_ui_manager,
688 recent_actions,
689 10 /* insert at back */ );
691 do {
692 id = gtk_ui_manager_new_merge_id (toolbox_ui_manager);
693 recent_merge_ids = g_slist_prepend (recent_merge_ids, (gpointer) id);
695 gtk_ui_manager_add_ui (toolbox_ui_manager, id,
696 "/ToolboxMenu/File/FileRecentEnd",
697 gtk_action_get_name (GTK_ACTION (list->data)),
698 gtk_action_get_name (GTK_ACTION (list->data)),
699 GTK_UI_MANAGER_AUTO,
700 TRUE);
702 } while (NULL != (list = list->next));
705 void
706 menus_clear_recent (void)
708 GSList *id;
710 g_return_if_fail (recent_merge_ids);
712 id = recent_merge_ids;
713 do {
714 gtk_ui_manager_remove_ui (toolbox_ui_manager, (guint) id->data);
716 } while (NULL != (id = id->next));
718 g_slist_free (recent_merge_ids);
719 recent_merge_ids = NULL;
721 gtk_ui_manager_remove_action_group (toolbox_ui_manager, recent_actions);
722 g_object_unref (G_OBJECT (recent_actions));
723 recent_actions = NULL;
726 void
727 menus_initialize_updatable_items (UpdatableMenuItems *items, GtkActionGroup *actions)
729 if (actions == NULL) {
730 actions = display_actions;
733 items->copy = gtk_action_group_get_action (actions, "EditCopy");
734 items->cut = gtk_action_group_get_action (actions, "EditCut");
735 items->paste = gtk_action_group_get_action (actions, "EditPaste");
736 items->edit_delete = gtk_action_group_get_action (actions, "EditDelete");
737 items->edit_duplicate = gtk_action_group_get_action (actions, "EditDuplicate");
739 items->copy_text = gtk_action_group_get_action (actions, "EditCopytext");
740 items->cut_text = gtk_action_group_get_action (actions, "EditCuttext");
741 items->paste_text = gtk_action_group_get_action (actions, "EditPastetext");
743 items->send_to_back = gtk_action_group_get_action (actions, "ObjectsSendtoback");
744 items->bring_to_front = gtk_action_group_get_action (actions, "ObjectsBringtofront");
745 items->send_backwards = gtk_action_group_get_action (actions, "ObjectsSendbackwards");
746 items->bring_forwards = gtk_action_group_get_action (actions, "ObjectsBringforwards");
748 items->group = gtk_action_group_get_action (actions, "ObjectsGroup");
749 items->ungroup = gtk_action_group_get_action (actions, "ObjectsUngroup");
751 items->parent = gtk_action_group_get_action (actions, "ObjectsParent");
752 items->unparent = gtk_action_group_get_action (actions, "ObjectsUnparent");
753 items->unparent_children = gtk_action_group_get_action (actions, "ObjectsUnparentchildren");
755 items->align_h_l = gtk_action_group_get_action (actions, "ObjectsAlignLeft");
756 items->align_h_c = gtk_action_group_get_action (actions, "ObjectsAlignCenter");
757 items->align_h_r = gtk_action_group_get_action (actions, "ObjectsAlignRight");
758 items->align_h_e = gtk_action_group_get_action (actions, "ObjectsAlignSpreadouthorizontally");
759 items->align_h_a = gtk_action_group_get_action (actions, "ObjectsAlignAdjacent");
760 items->align_v_t = gtk_action_group_get_action (actions, "ObjectsAlignTop");
761 items->align_v_c = gtk_action_group_get_action (actions, "ObjectsAlignMiddle");
762 items->align_v_b = gtk_action_group_get_action (actions, "ObjectsAlignBottom");
763 items->align_v_e = gtk_action_group_get_action (actions, "ObjectsAlignSpreadoutvertically");
764 items->align_v_a = gtk_action_group_get_action (actions, "ObjectsAlignStacked");
766 items->properties = gtk_action_group_get_action (actions, "ObjectsProperties");
769 static void
770 plugin_callback (GtkWidget *widget, gpointer data)
772 DiaCallbackFilter *cbf = data;
774 /* and finally invoke it */
775 if (cbf->callback) {
776 DDisplay *ddisp = ddisplay_active();
777 DiagramData* diadata = ddisp ? ddisp->diagram->data : NULL;
778 cbf->callback (diadata, 0, cbf->user_data);