1 /* Dia -- an diagram creation/manipulation program
2 * Copyright (C) 1998 Alexander Larsson
3 * Copyright (C) 2006 Robert Staudinger <robert.staudinger@gmail.com>
4 *
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.
9 *
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.
14 *
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.
18 */
19
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23
24 #undef GTK_DISABLE_DEPRECATED /* GtkTooltips */
25 #include <gtk/gtk.h>
26 #include <gdk/gdkkeysyms.h>
27 #include <string.h>
28
29 #include "intl.h"
30 #include "menus.h"
31 #include "tool.h"
32 #include "commands.h"
33 #include "message.h"
34 #include "interface.h"
35 #include "display.h"
36 #include "filedlg.h"
37 #include "find-and-replace.h"
38 #include "plugin-manager.h"
39 #include "select.h"
40 #include "dia_dirs.h"
41 #include "diagram_tree_window.h"
42 #include "object_ops.h"
43 #include "sheets.h"
44 #include "dia-app-icons.h"
45 #include "widgets.h"
46 #include "preferences.h"
47
48 #define DIA_STOCK_GROUP "dia-stock-group"
49 #define DIA_STOCK_UNGROUP "dia-stock-ungroup"
50 #define DIA_STOCK_LAYER_ADD "dia-stock-layer-add"
51 #define DIA_STOCK_LAYER_RENAME "dia-stock-layer-rename"
52 #define DIA_STOCK_OBJECTS_LAYER_ABOVE "dia-stock-objects-layer-above"
53 #define DIA_STOCK_OBJECTS_LAYER_BELOW "dia-stock-objects-layer-below"
54 #define DIA_STOCK_LAYERS "dia-stock-layers"
55
56 #define DIA_SHOW_TEAROFFS TRUE
57
58 /* Integrated UI Toolbar Constants */
59 #define DIA_INTEGRATED_TOOLBAR_ZOOM_COMBO "dia-integrated-toolbar-zoom-combo_entry"
60 #define DIA_INTEGRATED_TOOLBAR_SNAP_GRID "dia-integrated-toolbar-snap-grid"
61 #define DIA_INTEGRATED_TOOLBAR_OBJECT_SNAP "dia-integrated-toolbar-object-snap"
62
63 #define ZOOM_FIT _("Fit")
64
65 static void plugin_callback (GtkWidget *widget, gpointer data);
66
67 static GtkWidget *
68 create_integrated_ui_toolbar (void);
69
70 static void add_plugin_actions (GtkUIManager *ui_manager, const char *base_path);
71
72 static gchar*
73 build_ui_filename (const gchar* name);
74
75 /* Active/inactive state is set in diagram_update_menu_sensitivity()
76 * in diagram.c */
77
78 /* Actions common to toolbox and diagram window */
79 static const GtkActionEntry common_entries[] =
80 {
81 { "File", NULL, N_("_File"), NULL, NULL, NULL },
82 { "FileNew", GTK_STOCK_NEW, NULL, "<control>N", NULL, G_CALLBACK (file_new_callback) },
83 { "FileOpen", GTK_STOCK_OPEN, NULL,"<control>O", NULL, G_CALLBACK (file_open_callback) },
84 { "FileQuit", GTK_STOCK_QUIT, NULL, "<control>Q", NULL, G_CALLBACK (file_quit_callback) },
85 { "Help", NULL, N_("_Help"), NULL, NULL, NULL },
86 { "HelpContents", GTK_STOCK_HELP, NULL, "F1", NULL, G_CALLBACK (help_manual_callback) },
87 { "HelpAbout", GTK_STOCK_ABOUT, NULL, NULL, NULL, G_CALLBACK (help_about_callback) }
88 };
89
90 /* Actions for toolbox menu */
91 static const GtkActionEntry toolbox_entries[] =
92 {
93 { "FileSheets", NULL, N_("Sheets and Objects..."), "F9", NULL, G_CALLBACK (sheets_dialog_show_callback) },
94 { "FilePrefs", GTK_STOCK_PREFERENCES, NULL, NULL, NULL, G_CALLBACK (file_preferences_callback) },
95 { "FilePlugins", NULL, N_("Plugins..."), NULL, NULL, G_CALLBACK (file_plugins_callback) }
96 };
97
98 /* Toggle-Actions for toolbox menu */
99 static const GtkToggleActionEntry toolbox_toggle_entries[] =
100 {
101 { "FileTree", NULL, N_("_Diagram tree..."), "F8", NULL, G_CALLBACK (diagtree_show_callback) }
102 };
103
104 /* Toggle-Actions for toolbox menu */
105 static const GtkToggleActionEntry integrated_ui_view_toggle_entries[] =
106 {
107 { VIEW_MAIN_TOOLBAR_ACTION, NULL, N_("Show Toolbar"), NULL, NULL, G_CALLBACK (view_main_toolbar_callback) },
108 { VIEW_MAIN_STATUSBAR_ACTION, NULL, N_("Show Statusbar"), NULL, NULL, G_CALLBACK (view_main_statusbar_callback) },
109 { VIEW_LAYERS_ACTION, NULL, N_("Show Layers"), "<control>L", NULL, G_CALLBACK (view_layers_callback) }
110 };
111
112 /* Actions for diagram window */
113 static const GtkActionEntry display_entries[] =
114 {
115 { "FileSave", GTK_STOCK_SAVE, NULL, "<control>S", NULL, G_CALLBACK (file_save_callback) },
116 { "FileSaveas", GTK_STOCK_SAVE_AS, NULL, "<control><shift>S", NULL, G_CALLBACK (file_save_as_callback) },
117 { "FileExport", GTK_STOCK_CONVERT, N_("_Export ..."), NULL, NULL, G_CALLBACK (file_export_callback) },
118 { "DiagramProperties", GTK_STOCK_PROPERTIES, N_("_Diagram Properties"), "<shift><alt>Return", NULL, G_CALLBACK (view_diagram_properties_callback) },
119 { "FilePagesetup", NULL, N_("Page Set_up..."), NULL, NULL, G_CALLBACK (file_pagesetup_callback) },
120 { "FilePrint", GTK_STOCK_PRINT, NULL, "<control>P", NULL, G_CALLBACK (file_print_callback) },
121 { "FileClose", GTK_STOCK_CLOSE, NULL, "<control>W", NULL, G_CALLBACK (file_close_callback) },
122
123 { "Edit", NULL, N_("_Edit"), NULL, NULL, NULL },
124 { "EditUndo", GTK_STOCK_UNDO, NULL, "<control>Z", NULL, G_CALLBACK (edit_undo_callback) },
125 { "EditRedo", GTK_STOCK_REDO, NULL, "<control><shift>Z", NULL, G_CALLBACK (edit_redo_callback) },
126
127 { "EditCopy", GTK_STOCK_COPY, NULL, "<control>C", NULL, G_CALLBACK (edit_copy_callback) },
128 { "EditCut", GTK_STOCK_CUT, NULL, "<control>X", NULL, G_CALLBACK (edit_cut_callback) },
129 { "EditPaste", GTK_STOCK_PASTE, NULL, "<control>V", NULL, G_CALLBACK (edit_paste_callback) },
130 { "EditDuplicate", NULL, N_("_Duplicate"), "<control>D", NULL, G_CALLBACK (edit_duplicate_callback) },
131 { "EditDelete", GTK_STOCK_DELETE, NULL, "Delete", NULL, G_CALLBACK (edit_delete_callback) },
132
133 { "EditFind", GTK_STOCK_FIND, NULL, "<control>F", NULL, G_CALLBACK (edit_find_callback) },
134 { "EditReplace", GTK_STOCK_FIND_AND_REPLACE, NULL, "<control>H", NULL, G_CALLBACK (edit_replace_callback) },
135
136 /* the following used to bind to <control><shift>C which collides with Unicode input.
137 * <control>>alt> doesn't work either */
138 { "EditCopytext", NULL, N_("Copy Text"), NULL, NULL, G_CALLBACK (edit_copy_text_callback) },
139 { "EditCuttext", NULL, N_("Cut Text"), "<control><shift>X", NULL, G_CALLBACK (edit_cut_text_callback) },
140 { "EditPastetext", NULL, N_("Paste _Text"), "<control><shift>V", NULL, G_CALLBACK (edit_paste_text_callback) },
141
142 { "Layers", NULL, N_("_Layers"), NULL, NULL, NULL },
143 { "LayerAdd", DIA_STOCK_LAYER_ADD, N_("Add Layer..."), NULL, NULL, G_CALLBACK (layers_add_layer_callback) },
144 { "LayerRename", DIA_STOCK_LAYER_RENAME, N_("Rename Layer..."), NULL, NULL, G_CALLBACK (layers_rename_layer_callback) },
145 { "ObjectsLayerAbove", DIA_STOCK_OBJECTS_LAYER_ABOVE, N_("Move selection to layer above"), NULL, NULL, G_CALLBACK (objects_move_up_layer) },
146 { "ObjectsLayerBelow", DIA_STOCK_OBJECTS_LAYER_BELOW, N_("Move selection to layer below"), NULL, NULL, G_CALLBACK (objects_move_down_layer) },
147 { "DiagramLayers", DIA_STOCK_LAYERS, N_("_Layers..."), "<control>L", NULL, G_CALLBACK (dialogs_layers_callback) },
148
149 { "View", NULL, N_("_View"), NULL, NULL, NULL },
150 { "ViewZoomin", GTK_STOCK_ZOOM_IN, NULL, "<control>plus", NULL, G_CALLBACK (view_zoom_in_callback) },
151 { "ViewZoomout", GTK_STOCK_ZOOM_OUT, NULL, "<control>minus", NULL, G_CALLBACK (view_zoom_out_callback) },
152 { "ViewZoom", NULL, N_("_Zoom"), NULL, NULL, NULL },
153 { "ViewZoom16000", NULL, N_("1600%"), NULL, NULL, G_CALLBACK (view_zoom_set_callback) },
154 { "ViewZoom8000", NULL, N_("800%"), NULL, NULL, G_CALLBACK (view_zoom_set_callback) },
155 { "ViewZoom4000", NULL, N_("400%"), "<alt>4", NULL, G_CALLBACK (view_zoom_set_callback) },
156 { "ViewZoom2830", NULL, N_("283"), NULL, NULL, G_CALLBACK (view_zoom_set_callback) },
157 { "ViewZoom2000", NULL, N_("200"), "<alt>2", NULL, G_CALLBACK (view_zoom_set_callback) },
158 { "ViewZoom1410", NULL, N_("141"), NULL, NULL, G_CALLBACK (view_zoom_set_callback) },
159 { "ViewZoom1000", GTK_STOCK_ZOOM_100, NULL, "<alt>1", NULL, G_CALLBACK (view_zoom_set_callback) },
160 { "ViewZoom850", NULL, N_("85"), NULL, NULL, G_CALLBACK (view_zoom_set_callback) },
161 { "ViewZoom707", NULL, N_("70.7"), NULL, NULL, G_CALLBACK (view_zoom_set_callback) },
162 { "ViewZoom500", NULL, N_("50"), "<alt>5", NULL, G_CALLBACK (view_zoom_set_callback) },
163 { "ViewZoom354", NULL, N_("35.4"), NULL, NULL, G_CALLBACK (view_zoom_set_callback) },
164 { "ViewZoom250", NULL, N_("25"), NULL, NULL, G_CALLBACK (view_zoom_set_callback) },
165 /* Show All, Best Fit. Same as the Gimp, Ctrl+E */
166 { "ViewShowall", GTK_STOCK_ZOOM_FIT, NULL, "<control>E", NULL, G_CALLBACK (view_show_all_callback) },
167
168 /* "display_toggle_entries" items go here */
169
170 { "ViewNewview", NULL, N_("New _View"), NULL, NULL, G_CALLBACK (view_new_view_callback) },
171 { "ViewCloneview", NULL, N_("C_lone View"), NULL, NULL, G_CALLBACK (view_clone_view_callback) },
172 { "ViewRedraw", GTK_STOCK_REFRESH, NULL, NULL, NULL, G_CALLBACK (view_redraw_callback) },
173
174 { "Objects", NULL, N_("_Objects"), NULL, NULL },
175 { "ObjectsSendtoback", GTK_STOCK_GOTO_BOTTOM, N_("Send to _Back"), "<control><shift>B", NULL, G_CALLBACK (objects_place_under_callback) },
176 { "ObjectsBringtofront", GTK_STOCK_GOTO_TOP, N_("Bring to _Front"), "<control><shift>F", NULL, G_CALLBACK (objects_place_over_callback) },
177 { "ObjectsSendbackwards", GTK_STOCK_GO_DOWN, N_("Send Backwards"), NULL, NULL, G_CALLBACK (objects_place_down_callback) },
178 { "ObjectsBringforwards", GTK_STOCK_GO_UP, N_("Bring Forwards"), NULL, NULL, G_CALLBACK (objects_place_up_callback) },
179
180 { "ObjectsGroup", DIA_STOCK_GROUP, N_("_Group"), "<control>G", NULL, G_CALLBACK (objects_group_callback) },
181 /* deliberately not using Ctrl+U for Ungroup */
182 { "ObjectsUngroup", DIA_STOCK_UNGROUP, N_("_Ungroup"), "<control><shift>G", NULL, G_CALLBACK (objects_ungroup_callback) },
183
184 { "ObjectsParent", NULL, N_("_Parent"), "<control>K", NULL, G_CALLBACK (objects_parent_callback) },
185 { "ObjectsUnparent", NULL, N_("_Unparent"), "<control><shift>K", NULL, G_CALLBACK (objects_unparent_callback) },
186 { "ObjectsUnparentchildren", NULL, N_("_Unparent Children"), NULL, NULL, G_CALLBACK (objects_unparent_children_callback) },
187
188 { "ObjectsAlign", NULL, N_("Align"), NULL, NULL, NULL },
189 { "ObjectsAlignLeft", GTK_STOCK_JUSTIFY_LEFT, NULL, "<alt><shift>L", NULL, G_CALLBACK (objects_align_h_callback) },
190 { "ObjectsAlignCenter", GTK_STOCK_JUSTIFY_CENTER, NULL, "<alt><shift>C", NULL, G_CALLBACK (objects_align_h_callback) },
191 { "ObjectsAlignRight", GTK_STOCK_JUSTIFY_RIGHT, NULL, "<alt><shift>R", NULL, G_CALLBACK (objects_align_h_callback) },
192
193 { "ObjectsAlignTop", NULL, N_("Top"), "<alt><shift>T", NULL, G_CALLBACK (objects_align_v_callback) },
194 { "ObjectsAlignMiddle", NULL, N_("Middle"), "<alt><shift>M", NULL, G_CALLBACK (objects_align_v_callback) },
195 { "ObjectsAlignBottom", NULL, N_("Bottom"), "<alt><shift>B", NULL, G_CALLBACK (objects_align_v_callback) },
196
197 { "ObjectsAlignSpreadouthorizontally", NULL, N_("Spread Out Horizontally"), "<alt><shift>H", NULL, G_CALLBACK (objects_align_h_callback) },
198 { "ObjectsAlignSpreadoutvertically", NULL, N_("Spread Out Vertically"), "<alt><shift>V", NULL, G_CALLBACK (objects_align_v_callback) },
199 { "ObjectsAlignAdjacent", NULL, N_("Adjacent"), "<alt><shift>A", NULL, G_CALLBACK (objects_align_h_callback) },
200 { "ObjectsAlignStacked", NULL, N_("Stacked"), "<alt><shift>S", NULL, G_CALLBACK (objects_align_v_callback) },
201
202 { "ObjectsProperties", GTK_STOCK_PROPERTIES, NULL, "<alt>Return", NULL, G_CALLBACK (dialogs_properties_callback) },
203
204 { "Select", NULL, N_("_Select"), NULL, NULL, NULL },
205 { "SelectAll", NULL, N_("All"), "<control>A", NULL, G_CALLBACK (select_all_callback) },
206 { "SelectNone", NULL, N_("None"), "<control><shift>A", NULL, G_CALLBACK (select_none_callback) },
207 { "SelectInvert", NULL, N_("Invert"), "<control>I", NULL, G_CALLBACK (select_invert_callback) },
208
209 { "SelectTransitive", NULL, N_("Transitive"), "<control>T", NULL, G_CALLBACK (select_transitive_callback) },
210 { "SelectConnected", NULL, N_("Connected"), "<control><shift>T", NULL, G_CALLBACK (select_connected_callback) },
211 { "SelectSametype", NULL, N_("Same Type"), NULL, NULL, G_CALLBACK (select_same_type_callback) },
212
213 /* display_select_radio_entries go here */
214
215 { "SelectBy", NULL, N_("Select By"), NULL, NULL, NULL },
216
217 { "InputMethods", NULL, N_("_Input Methods"), NULL, NULL, NULL },
218
219 { "Dialogs", NULL, N_("D_ialogs"), NULL, NULL, NULL },
220
221 { "Debug", NULL, N_("D_ebug"), NULL, NULL, NULL }
222 };
223
224 /* Standard-Tool entries */
225 static const GtkActionEntry tool_entries[] =
226 {
227 { "Tools", NULL, N_("_Tools"), NULL, NULL, NULL },
228 { "ToolsModify", NULL, N_("Modify"), "N", NULL, NULL },
229 { "ToolsMagnify", NULL, N_("Magnify"), "M", NULL, NULL },
230 { "ToolsTextedit", NULL, N_("Edit text"), "F2", NULL, NULL },
231 { "ToolsScroll", NULL, N_("Scroll"), "S", NULL, NULL },
232 { "ToolsText", NULL, N_("Text"), "T", NULL, NULL },
233 { "ToolsBox", NULL, N_("Box"), "R", NULL, NULL },
234 { "ToolsEllipse", NULL, N_("Ellipse"), "E", NULL, NULL },
235 { "ToolsPolygon", NULL, N_("Polygon"), "P", NULL, NULL },
236 { "ToolsBeziergon", NULL, N_("Beziergon"), "B", NULL, NULL },
237
238 { "ToolsLine", NULL, N_("Line"), "L", NULL, NULL },
239 { "ToolsArc", NULL, N_("Arc"), "A", NULL, NULL },
240 { "ToolsZigzagline", NULL, N_("Zigzagline"), "Z", NULL, NULL },
241 { "ToolsPolyline", NULL, N_("Polyline"), "Y", NULL },
242 { "ToolsBezierline", NULL, N_("Bezierline"), "C", NULL, NULL },
243 { "ToolsOutline", NULL, N_("Outline"), "O", NULL, NULL },
244
245 { "ToolsImage", NULL, N_("Image"), "I", NULL, NULL },
246 };
247
248 /* Toggle-Actions for diagram window */
249 static const GtkToggleActionEntry display_toggle_entries[] =
250 {
251 #ifdef GTK_STOCK_FULLSCREEN /* added with gtk+-2.8, but no reason to depend on it */
252 { "ViewFullscreen", GTK_STOCK_FULLSCREEN, NULL, "F11", NULL, G_CALLBACK (view_fullscreen_callback) },
253 #else
254 { "ViewFullscreen", NULL, N_("Fullscr_een"), "F11", NULL, G_CALLBACK (view_fullscreen_callback) },
255 #endif
256 { "ViewAntialiased", NULL, N_("_AntiAliased"), NULL, NULL, G_CALLBACK (view_aa_callback) },
257 { "ViewShowgrid", NULL, N_("Show _Grid"), NULL, NULL, G_CALLBACK (view_visible_grid_callback) },
258 { "ViewSnaptogrid", NULL, N_("_Snap To Grid"), NULL, NULL, G_CALLBACK (view_snap_to_grid_callback) },
259 { "ViewSnaptoobjects", NULL, N_("Snap To _Objects"), NULL, NULL, G_CALLBACK (view_snap_to_objects_callback) },
260 { "ViewShowrulers", NULL, N_("Show _Rulers"), NULL, NULL, G_CALLBACK (view_toggle_rulers_callback) },
261 { "ViewShowconnectionpoints", NULL, N_("Show _Connection Points"), NULL, NULL, G_CALLBACK (view_show_cx_pts_callback) }
262 };
263
264 /* Radio-Actions for the diagram window's "Select"-Menu */
265 static const GtkRadioActionEntry display_select_radio_entries[] =
266 {
267 { "SelectReplace", NULL, N_("Replace"), NULL, NULL, SELECT_REPLACE },
268 { "SelectUnion", NULL, N_("Union"), NULL, NULL, SELECT_UNION },
269 { "SelectIntersection", NULL, N_("Intersection"), NULL, NULL, SELECT_INTERSECTION },
270 { "SelectRemove", NULL, N_("Remove"), NULL, NULL, SELECT_REMOVE },
271 /* Cannot also be called Invert, duplicate names caused keybinding problems */
272 { "SelectInverse", NULL, N_("Inverse"), NULL, NULL, SELECT_INVERT }
273 };
274
275 /* need initialisation? */
276 static gboolean initialise = TRUE;
277
278 /* integrated ui */
279 static GtkUIManager *integrated_ui_manager = NULL;
280 static GtkActionGroup *integrated_ui_actions = NULL;
281 static GtkActionGroup *integrated_ui_tool_actions = NULL;
282 static GtkAccelGroup *integrated_ui_accels = NULL;
283 static GtkWidget *integrated_ui_menubar = NULL;
284 static GtkWidget *integrated_ui_toolbar = NULL;
285
286 /* toolbox */
287 static GtkUIManager *toolbox_ui_manager = NULL;
288 static GtkActionGroup *toolbox_actions = NULL;
289 static GtkAccelGroup *toolbox_accels = NULL;
290 static GtkWidget *toolbox_menubar = NULL;
291
292 GtkActionGroup *recent_actions = NULL;
293 static GSList *recent_merge_ids = NULL;
294
295 /* diagram */
296 static GtkUIManager *display_ui_manager = NULL;
297 static GtkActionGroup *display_actions = NULL;
298 static GtkActionGroup *display_tool_actions = NULL;
299 static GtkAccelGroup *display_accels = NULL;
300 static GtkWidget *display_menubar = NULL;
301
302 static gchar*
_dia_translate(const gchar * term,gpointer data)303 _dia_translate (const gchar* term, gpointer data)
304 {
305 gchar* trans = (gchar*) term;
306
307 if (term && *term) {
308 /* first try our own ... */
309 trans = dgettext (GETTEXT_PACKAGE, term);
310 /* ... than gtk */
311 if (term == trans)
312 trans = dgettext ("gtk20", term);
313 #if 0
314 /* FIXME: final fallback */
315 if (term == trans) { /* FIXME: translation to be updated */
316 gchar* kludge = g_strdup_printf ("/%s", term);
317 trans = dgettext (GETTEXT_PACKAGE, kludge);
318 if (kludge == trans)
319 trans = term;
320 else
321 ++trans;
322 g_free (kludge);
323 }
324 if (term == trans)
325 trans = g_strdup_printf ("XXX: %s", term);
326 #endif
327 }
328 return trans;
329 }
330
331 static void
tool_menu_select(GtkWidget * w,gpointer data)332 tool_menu_select(GtkWidget *w, gpointer data) {
333 ToolButtonData *tooldata = (ToolButtonData *) data;
334
335 if (tooldata == NULL) {
336 g_warning(_("NULL tooldata in tool_menu_select"));
337 return;
338 }
339
340 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(tooldata->widget),TRUE);
341 }
342
343 static gint
save_accels(gpointer data)344 save_accels(gpointer data)
345 {
346 gchar *accelfilename;
347
348 accelfilename = dia_config_filename("menurc");
349 if (accelfilename) {
350 gtk_accel_map_save (accelfilename);
351 g_free (accelfilename);
352 }
353 return TRUE;
354 }
355
356 /**
357 * Synchronized the Object snap property button with the display.
358 * @param param Display to synchronize to.
359 */
360 void
integrated_ui_toolbar_object_snap_synchronize_to_display(gpointer param)361 integrated_ui_toolbar_object_snap_synchronize_to_display(gpointer param)
362 {
363 DDisplay *ddisp = param;
364 if (ddisp && ddisp->common_toolbar)
365 {
366 GtkToggleButton *b = g_object_get_data (G_OBJECT (ddisp->common_toolbar),
367 DIA_INTEGRATED_TOOLBAR_OBJECT_SNAP);
368 gboolean active = ddisp->mainpoint_magnetism? TRUE : FALSE;
369 gtk_toggle_button_set_active (b, active);
370 }
371 }
372
373 /**
374 * Sets the Object-snap property for the active display.
375 * @param b Object snap toggle button.
376 * @param not_used
377 */
378 static void
integrated_ui_toolbar_object_snap_toggle(GtkToggleButton * b,gpointer * not_used)379 integrated_ui_toolbar_object_snap_toggle(GtkToggleButton *b, gpointer *not_used)
380 {
381 DDisplay *ddisp = ddisplay_active ();
382 if (ddisp)
383 {
384 ddisplay_set_snap_to_objects (ddisp, gtk_toggle_button_get_active (b));
385 }
386 }
387
388 /**
389 * Synchronizes the Snap-to-grid property button with the display.
390 * @param param Display to synchronize to.
391 */
392 void
integrated_ui_toolbar_grid_snap_synchronize_to_display(gpointer param)393 integrated_ui_toolbar_grid_snap_synchronize_to_display(gpointer param)
394 {
395 DDisplay *ddisp = param;
396 if (ddisp && ddisp->common_toolbar)
397 {
398 GtkToggleButton *b = g_object_get_data (G_OBJECT (ddisp->common_toolbar),
399 DIA_INTEGRATED_TOOLBAR_SNAP_GRID);
400 gboolean active = ddisp->grid.snap? TRUE : FALSE;
401 gtk_toggle_button_set_active (b, active);
402 }
403 }
404
405 /**
406 * Sets the Snap-to-grid property for the active display.
407 * @param b Snap to grid toggle button.
408 * @param not_used
409 */
410 static void
integrated_ui_toolbar_grid_snap_toggle(GtkToggleButton * b,gpointer * not_used)411 integrated_ui_toolbar_grid_snap_toggle(GtkToggleButton *b, gpointer *not_used)
412 {
413 DDisplay *ddisp = ddisplay_active ();
414 if (ddisp)
415 {
416 ddisplay_set_snap_to_grid (ddisp, gtk_toggle_button_get_active (b));
417 }
418 }
419
420 /**
421 * Sets the zoom text for the toolbar
422 * @param toolbar Integrated UI toolbar.
423 * @param text Current zoom percentage for the active window
424 */
integrated_ui_toolbar_set_zoom_text(GtkToolbar * toolbar,const gchar * text)425 void integrated_ui_toolbar_set_zoom_text (GtkToolbar *toolbar, const gchar * text)
426 {
427 if (toolbar)
428 {
429 GtkComboBoxEntry *combo_entry = g_object_get_data (G_OBJECT (toolbar),
430 DIA_INTEGRATED_TOOLBAR_ZOOM_COMBO);
431
432 if (combo_entry)
433 {
434 GtkWidget * entry = gtk_bin_get_child (GTK_BIN (combo_entry));
435
436 gtk_entry_set_text (GTK_ENTRY (entry), text);
437 }
438 }
439 }
440
441 /**
442 * Adds a widget to the toolbar making sure that it doesn't take any excess space, and
443 * vertically centers it.
444 * @param toolbar The toolbar to add the widget to.
445 * @param w The widget to add to the toolbar.
446 */
integrated_ui_toolbar_add_custom_item(GtkToolbar * toolbar,GtkWidget * w)447 static void integrated_ui_toolbar_add_custom_item (GtkToolbar *toolbar, GtkWidget *w)
448 {
449 GtkToolItem *tool_item;
450 GtkWidget *c; /* container */
451
452 tool_item = gtk_tool_item_new ();
453 c = gtk_vbox_new (FALSE, 0);
454 gtk_container_add (GTK_CONTAINER (tool_item), c);
455 gtk_box_set_homogeneous (GTK_BOX (c), TRUE); /* Centers the button */
456 gtk_box_pack_start (GTK_BOX (c), w, FALSE, FALSE, 0);
457 gtk_toolbar_insert (toolbar, tool_item, -1);
458 gtk_widget_show (GTK_WIDGET (tool_item));
459 gtk_widget_show (c);
460 gtk_widget_show (w);
461 }
462
463 static void
integrated_ui_toolbar_zoom_activate(GtkWidget * item,gpointer user_data)464 integrated_ui_toolbar_zoom_activate (GtkWidget *item,
465 gpointer user_data)
466 {
467 const gchar *text = gtk_entry_get_text (GTK_ENTRY (item));
468 float zoom_percent;
469
470 if (sscanf (text, "%f", &zoom_percent) == 1)
471 {
472 view_zoom_set (10.0 * zoom_percent);
473 }
474 }
475
476 static void
integrated_ui_toolbar_zoom_combo_selection_changed(GtkComboBox * combo,gpointer user_data)477 integrated_ui_toolbar_zoom_combo_selection_changed (GtkComboBox *combo,
478 gpointer user_data)
479 {
480 /*
481 * We call gtk_combo_get_get_active() so that typing in the combo entry
482 * doesn't get handled as a selection change
483 */
484 if (gtk_combo_box_get_active (combo) != -1)
485 {
486 float zoom_percent;
487 gchar * text = gtk_combo_box_get_active_text (combo);
488
489 if (sscanf (text, "%f", &zoom_percent) == 1)
490 {
491 view_zoom_set (zoom_percent * 10.0);
492 }
493 else if (g_strcasecmp (text, ZOOM_FIT) == 0)
494 {
495 view_show_all_callback (NULL);
496 }
497
498 g_free (text);
499 }
500 }
501
502 static guint
ensure_menu_path(GtkUIManager * ui_manager,GtkActionGroup * actions,const gchar * path,gboolean end)503 ensure_menu_path (GtkUIManager *ui_manager, GtkActionGroup *actions, const gchar *path, gboolean end)
504 {
505 guint id = gtk_ui_manager_new_merge_id (ui_manager);
506
507 if (!gtk_ui_manager_get_widget (ui_manager, path)) {
508 gchar *subpath = g_strdup (path);
509
510 if (strrchr (subpath, '/')) {
511 const gchar *action_name;
512 gchar *sep;
513
514 GtkAction *action;
515
516 sep = strrchr (subpath, '/');
517 *sep = '\0'; /* cut subpath */
518 action_name = sep + 1;
519
520 ensure_menu_path (ui_manager, actions, subpath, FALSE);
521
522 action = gtk_action_new (action_name, sep + 1, NULL, NULL);
523 if (!gtk_action_group_get_action (actions, action_name))
524 gtk_action_group_add_action (actions, action);
525 g_object_unref (G_OBJECT (action));
526
527 gtk_ui_manager_add_ui (ui_manager, id, subpath,
528 action_name, action_name,
529 end ? GTK_UI_MANAGER_SEPARATOR : GTK_UI_MANAGER_MENU,
530 FALSE); /* FALSE=add-to-end */
531 } else {
532 g_warning ("ensure_menu_path() invalid menu path: %s.", subpath ? subpath : "NULL");
533 }
534 g_free (subpath);
535 }
536 return id;
537 }
538
539 /**
540 * Create the toolbar for the integrated UI
541 * @return Main toolbar (GtkToolbar*) for the integrated UI main window
542 */
543 static GtkWidget *
create_integrated_ui_toolbar(void)544 create_integrated_ui_toolbar (void)
545 {
546 GtkToolbar *toolbar;
547 GtkToolItem *sep;
548 GtkWidget *w;
549 GError *error = NULL;
550 gchar *uifile;
551
552 uifile = build_ui_filename ("ui/toolbar-ui.xml");
553 if (!gtk_ui_manager_add_ui_from_file (integrated_ui_manager, uifile, &error)) {
554 g_warning ("building menus failed: %s", error->message);
555 g_error_free (error);
556 error = NULL;
557 toolbar = GTK_TOOLBAR (gtk_toolbar_new ());
558 }
559 else {
560 toolbar = GTK_TOOLBAR(gtk_ui_manager_get_widget (integrated_ui_manager, "/Toolbar"));
561 }
562 g_free (uifile);
563
564 /* Zoom Combo Box Entry */
565 w = gtk_combo_box_entry_new_text ();
566
567 g_object_set_data (G_OBJECT (toolbar),
568 DIA_INTEGRATED_TOOLBAR_ZOOM_COMBO,
569 w);
570 integrated_ui_toolbar_add_custom_item (toolbar, w);
571
572 gtk_combo_box_append_text (GTK_COMBO_BOX (w), ZOOM_FIT);
573 gtk_combo_box_append_text (GTK_COMBO_BOX (w), _("800%"));
574 gtk_combo_box_append_text (GTK_COMBO_BOX (w), _("400%"));
575 gtk_combo_box_append_text (GTK_COMBO_BOX (w), _("300%"));
576 gtk_combo_box_append_text (GTK_COMBO_BOX (w), _("200%"));
577 gtk_combo_box_append_text (GTK_COMBO_BOX (w), _("150%"));
578 gtk_combo_box_append_text (GTK_COMBO_BOX (w), _("100%"));
579 gtk_combo_box_append_text (GTK_COMBO_BOX (w), _("75%"));
580 gtk_combo_box_append_text (GTK_COMBO_BOX (w), _("50%"));
581 gtk_combo_box_append_text (GTK_COMBO_BOX (w), _("25%"));
582 gtk_combo_box_append_text (GTK_COMBO_BOX (w), _("10%"));
583
584 g_signal_connect (G_OBJECT (w),
585 "changed",
586 G_CALLBACK (integrated_ui_toolbar_zoom_combo_selection_changed),
587 NULL);
588
589 /* Get the combo's GtkEntry child to set the width for the widget */
590 w = gtk_bin_get_child (GTK_BIN (w));
591 gtk_entry_set_width_chars (GTK_ENTRY (w), 6);
592
593 g_signal_connect (GTK_OBJECT (w), "activate",
594 G_CALLBACK(integrated_ui_toolbar_zoom_activate),
595 NULL);
596
597 /* Seperator */
598 sep = gtk_separator_tool_item_new ();
599 gtk_toolbar_insert (toolbar, sep, -1);
600 gtk_widget_show (GTK_WIDGET (sep));
601
602 /* Snap to grid */
603 w = dia_toggle_button_new_with_icons (dia_on_grid_icon,
604 dia_off_grid_icon);
605 g_signal_connect (G_OBJECT (w), "toggled",
606 G_CALLBACK (integrated_ui_toolbar_grid_snap_toggle), toolbar);
607 gtk_tooltips_set_tip (tool_tips, w,
608 _("Toggles snap-to-grid."), NULL);
609 g_object_set_data (G_OBJECT (toolbar),
610 DIA_INTEGRATED_TOOLBAR_SNAP_GRID,
611 w);
612 integrated_ui_toolbar_add_custom_item (toolbar, w);
613
614 /* Object Snapping */
615 w = dia_toggle_button_new_with_icons (dia_mainpoints_on_icon,
616 dia_mainpoints_off_icon);
617 g_signal_connect (G_OBJECT (w), "toggled",
618 G_CALLBACK (integrated_ui_toolbar_object_snap_toggle), toolbar);
619 gtk_tooltips_set_tip (tool_tips, w,
620 _("Toggles object snapping."), NULL);
621 g_object_set_data (G_OBJECT (toolbar),
622 DIA_INTEGRATED_TOOLBAR_OBJECT_SNAP,
623 w);
624 integrated_ui_toolbar_add_custom_item (toolbar, w);
625
626 sep = gtk_separator_tool_item_new ();
627 gtk_toolbar_insert (toolbar, sep, -1);
628 gtk_widget_show (GTK_WIDGET (sep));
629
630 return GTK_WIDGET (toolbar);
631 }
632
633 /*
634 * Initialise tool actions.
635 * The caller owns the return value.
636 */
637 static GtkActionGroup *
create_tool_actions(void)638 create_tool_actions (void)
639 {
640 GtkActionGroup *actions;
641 GtkAction *action;
642 int i;
643 gchar *name;
644 static guint cnt = 0;
645
646 name = g_strdup_printf ("tool-actions-%d", cnt);
647 actions = gtk_action_group_new (name);
648 gtk_action_group_set_translation_domain (actions, NULL);
649 gtk_action_group_set_translate_func (actions, _dia_translate, NULL, NULL);
650 g_free (name);
651 name = NULL;
652 cnt++;
653
654 gtk_action_group_add_actions (actions, tool_entries,
655 G_N_ELEMENTS (tool_entries), NULL);
656
657 for (i = 0; i < num_tools; i++) {
658 action = gtk_action_group_get_action (actions, tool_data[i].action_name);
659 if (action != NULL) {
660 g_signal_connect (G_OBJECT (action), "activate",
661 G_CALLBACK (tool_menu_select),
662 &tool_data[i].callback_data);
663 }
664 else {
665 g_warning ("couldn't find tool menu item %s", tool_data[i].action_name);
666 }
667 }
668 return actions;
669 }
670
671 /* initialize callbacks from plug-ins */
672 static void
add_plugin_actions(GtkUIManager * ui_manager,const gchar * base_path)673 add_plugin_actions (GtkUIManager *ui_manager, const gchar *base_path)
674 {
675 GtkActionGroup *actions;
676 GtkAction *action;
677 GList *cblist;
678 DiaCallbackFilter *cbf = NULL;
679 gchar *name;
680 guint id;
681 static guint cnt = 0;
682
683 name = g_strdup_printf ("plugin-actions-%d", cnt);
684 actions = gtk_action_group_new (name);
685 gtk_action_group_set_translation_domain (actions, NULL);
686 gtk_action_group_set_translate_func (actions, _dia_translate, NULL, NULL);
687 g_free (name);
688 name = NULL;
689 cnt++;
690
691 gtk_ui_manager_insert_action_group (ui_manager, actions, 5 /* "back" */);
692 g_object_unref (actions);
693
694 for (cblist = filter_get_callbacks(); cblist; cblist = cblist->next) {
695 gchar *menu_path = NULL;
696
697 cbf = cblist->data;
698
699 if (cbf == NULL) {
700 g_warning ("missing DiaCallbackFilter instance");
701 continue;
702 }
703
704 if (cbf->action == NULL) {
705 g_warning ("Plugin '%s': doesn't specify action. Loading failed.",
706 cbf->description);
707 continue;
708 }
709
710 if ( base_path != NULL
711 && strncmp (cbf->menupath, base_path, strlen (base_path)) != 0) {
712 /* hook for wrong base path, skip */
713 continue;
714 } else if (!base_path) {
715 /* only replace what we know */
716 if (strncmp (cbf->menupath, DISPLAY_MENU, strlen (DISPLAY_MENU)) == 0)
717 menu_path = g_strdup_printf ("%s%s", INTEGRATED_MENU, cbf->menupath + strlen (DISPLAY_MENU));
718 else if (strncmp (cbf->menupath, TOOLBOX_MENU, strlen (TOOLBOX_MENU)) == 0)
719 menu_path = g_strdup_printf ("%s%s", INTEGRATED_MENU, cbf->menupath + strlen (TOOLBOX_MENU));
720 }
721
722 action = gtk_action_new (cbf->action, cbf->description, NULL, NULL);
723 g_signal_connect (G_OBJECT (action), "activate",
724 G_CALLBACK (plugin_callback), (gpointer) cbf);
725
726 gtk_action_group_add_action (actions, action);
727 g_object_unref (G_OBJECT (action));
728
729 id = ensure_menu_path (ui_manager, actions, menu_path ? menu_path : cbf->menupath, TRUE);
730 gtk_ui_manager_add_ui (ui_manager, id,
731 menu_path ? menu_path : cbf->menupath,
732 cbf->description,
733 cbf->action,
734 GTK_UI_MANAGER_AUTO,
735 FALSE);
736 g_free (menu_path);
737 }
738 }
739
740 static void
_add_stock_icon(GtkIconFactory * factory,const char * name,const guint8 * data,const size_t size)741 _add_stock_icon (GtkIconFactory *factory, const char *name, const guint8 *data, const size_t size)
742 {
743 GdkPixbuf *pixbuf;
744 GtkIconSet *set;
745 GError *err = NULL;
746
747 pixbuf = gdk_pixbuf_new_from_inline (size, data, FALSE, &err);
748 if (err) {
749 g_warning ("%s", err->message);
750 g_error_free (err);
751 err = NULL;
752 }
753 set = gtk_icon_set_new_from_pixbuf (pixbuf);
754 gtk_icon_factory_add (factory, name, set);
755 g_object_unref (pixbuf);
756 pixbuf = NULL;
757 }
758
759 static void
register_stock_icons(void)760 register_stock_icons (void)
761 {
762 GtkIconFactory *factory;
763
764 factory = gtk_icon_factory_new ();
765
766 _add_stock_icon (factory, DIA_STOCK_GROUP, dia_group_icon, sizeof(dia_group_icon));
767 _add_stock_icon (factory, DIA_STOCK_UNGROUP, dia_ungroup_icon, sizeof(dia_ungroup_icon));
768
769 _add_stock_icon (factory, DIA_STOCK_LAYER_ADD, dia_layer_add, sizeof(dia_layer_add));
770 _add_stock_icon (factory, DIA_STOCK_LAYER_RENAME, dia_layer_rename, sizeof(dia_layer_rename));
771 _add_stock_icon (factory, DIA_STOCK_OBJECTS_LAYER_ABOVE, dia_objects_layer_above, sizeof(dia_objects_layer_above));
772 _add_stock_icon (factory, DIA_STOCK_OBJECTS_LAYER_BELOW, dia_objects_layer_below, sizeof(dia_objects_layer_below));
773 _add_stock_icon (factory, DIA_STOCK_LAYERS, dia_layers, sizeof(dia_layers));
774
775 gtk_icon_factory_add_default (factory);
776 g_object_unref (factory);
777 factory = NULL;
778 }
779
780 static gchar*
build_ui_filename(const gchar * name)781 build_ui_filename (const gchar* name)
782 {
783 gchar* uifile;
784
785 if (g_getenv ("DIA_BASE_PATH") != NULL) {
786 /* a small hack cause the final destination and the local path differ */
787 const gchar* p = strrchr (name, '/');
788 if (p != NULL)
789 name = p+1;
790 uifile = g_build_filename (g_getenv ("DIA_BASE_PATH"), "data", name, NULL);
791 } else
792 uifile = dia_get_data_directory (name);
793
794 return uifile;
795 }
796
797 /*!
798 * Not sure why this service is not provided by GTK+.
799 * We are passing tooltips into the actions (especially recent file menu).
800 * But they were not shown without explicit setting on connect.
801 */
802 static void
_ui_manager_connect_proxy(GtkUIManager * manager,GtkAction * action,GtkWidget * proxy)803 _ui_manager_connect_proxy (GtkUIManager *manager,
804 GtkAction *action,
805 GtkWidget *proxy)
806 {
807 if (GTK_IS_MENU_ITEM (proxy))
808 {
809 gchar *tooltip;
810
811 g_object_get (action, "tooltip", &tooltip, NULL);
812
813 if (tooltip)
814 {
815 gtk_tooltips_set_tip (tool_tips, proxy, tooltip, NULL);
816 g_free (tooltip);
817 }
818 }
819 }
820
821 GtkActionGroup *
create_or_ref_display_actions(void)822 create_or_ref_display_actions (void)
823 {
824 if (display_actions)
825 return g_object_ref (display_actions);
826 display_actions = gtk_action_group_new ("display-actions");
827 gtk_action_group_set_translation_domain (display_actions, NULL);
828 gtk_action_group_set_translate_func (display_actions, _dia_translate, NULL, NULL);
829 gtk_action_group_add_actions (display_actions, common_entries,
830 G_N_ELEMENTS (common_entries), NULL);
831 gtk_action_group_add_actions (display_actions, display_entries,
832 G_N_ELEMENTS (display_entries), NULL);
833 gtk_action_group_add_toggle_actions (display_actions, display_toggle_entries,
834 G_N_ELEMENTS (display_toggle_entries),
835 NULL);
836 gtk_action_group_add_radio_actions (display_actions,
837 display_select_radio_entries,
838 G_N_ELEMENTS (display_select_radio_entries),
839 0, /* SELECT_REPLACE - first radio entry */
840 G_CALLBACK (select_style_callback),
841 NULL);
842 /* the initial reference */
843 return display_actions;
844 }
845
846 /* Very minimal fallback menu info for ui-files missing
847 * as well as to register the InvisibleMenu */
848 static const gchar *ui_info =
849 "<ui>\n"
850 " <popup name=\"InvisibleMenu\">\n"
851 " <menu name=\"File\" action=\"File\">\n"
852 " <menuitem name=\"FilePrint\" action=\"FilePrint\" />\n"
853 " <menuitem name=\"FileQuit\" action=\"FileQuit\" />\n"
854 " </menu>\n"
855 " </popup>\n"
856 "</ui>";
857
858 static void
menus_init(void)859 menus_init(void)
860 {
861 gchar *accelfilename;
862 GError *error = NULL;
863 gchar *uifile;
864
865 if (!initialise)
866 return;
867
868 initialise = FALSE;
869
870 register_stock_icons ();
871
872 /* the toolbox menu */
873 toolbox_actions = gtk_action_group_new ("toolbox-actions");
874 gtk_action_group_set_translation_domain (toolbox_actions, NULL);
875 gtk_action_group_set_translate_func (toolbox_actions, _dia_translate, NULL, NULL);
876 gtk_action_group_add_actions (toolbox_actions, common_entries,
877 G_N_ELEMENTS (common_entries), NULL);
878 gtk_action_group_add_actions (toolbox_actions, toolbox_entries,
879 G_N_ELEMENTS (toolbox_entries), NULL);
880 gtk_action_group_add_toggle_actions (toolbox_actions, toolbox_toggle_entries,
881 G_N_ELEMENTS (toolbox_toggle_entries),
882 NULL);
883
884 toolbox_ui_manager = gtk_ui_manager_new ();
885 g_signal_connect (G_OBJECT (toolbox_ui_manager),
886 "connect_proxy",
887 G_CALLBACK (_ui_manager_connect_proxy),
888 NULL);
889 gtk_ui_manager_set_add_tearoffs (toolbox_ui_manager, DIA_SHOW_TEAROFFS);
890 gtk_ui_manager_insert_action_group (toolbox_ui_manager, toolbox_actions, 0);
891 uifile = build_ui_filename ("ui/toolbox-ui.xml");
892 if (!gtk_ui_manager_add_ui_from_file (toolbox_ui_manager, uifile, &error)) {
893 g_warning ("building menus failed: %s", error->message);
894 g_error_free (error);
895 error = NULL;
896 }
897 g_free (uifile);
898
899 toolbox_accels = gtk_ui_manager_get_accel_group (toolbox_ui_manager);
900 toolbox_menubar = gtk_ui_manager_get_widget (toolbox_ui_manager, TOOLBOX_MENU);
901
902 /* the display menu */
903 display_actions = create_or_ref_display_actions ();
904 display_tool_actions = create_tool_actions ();
905
906 display_ui_manager = gtk_ui_manager_new ();
907 g_signal_connect (G_OBJECT (display_ui_manager),
908 "connect_proxy",
909 G_CALLBACK (_ui_manager_connect_proxy),
910 NULL);
911 gtk_ui_manager_set_add_tearoffs (display_ui_manager, DIA_SHOW_TEAROFFS);
912 gtk_ui_manager_insert_action_group (display_ui_manager, display_actions, 0);
913 gtk_ui_manager_insert_action_group (display_ui_manager, display_tool_actions, 0);
914 if (!gtk_ui_manager_add_ui_from_string (display_ui_manager, ui_info, -1, &error)) {
915 g_warning ("built-in menus failed: %s", error->message);
916 g_error_free (error);
917 error = NULL;
918 }
919
920 uifile = build_ui_filename ("ui/popup-ui.xml");
921 /* TODO it would be more elegant if we had only one definition of the
922 * menu hierarchy and merge it into a popup somehow. */
923 if (!gtk_ui_manager_add_ui_from_file (display_ui_manager, uifile, &error)) {
924 g_warning ("building menus failed: %s", error->message);
925 g_error_free (error);
926 error = NULL;
927 }
928 g_free (uifile);
929
930 display_accels = gtk_ui_manager_get_accel_group (display_ui_manager);
931 display_menubar = gtk_ui_manager_get_widget (display_ui_manager, DISPLAY_MENU);
932 g_assert (display_menubar);
933
934 add_plugin_actions (toolbox_ui_manager, TOOLBOX_MENU);
935 add_plugin_actions (display_ui_manager, DISPLAY_MENU);
936 add_plugin_actions (display_ui_manager, INVISIBLE_MENU);
937
938 /* load accelerators and prepare to later save them */
939 accelfilename = dia_config_filename("menurc");
940
941 if (accelfilename) {
942 gtk_accel_map_load(accelfilename);
943 g_free(accelfilename);
944 }
945 gtk_quit_add(1, save_accels, NULL);
946 }
947
948 void
menus_get_integrated_ui_menubar(GtkWidget ** menubar,GtkWidget ** toolbar,GtkAccelGroup ** accel_group)949 menus_get_integrated_ui_menubar (GtkWidget **menubar,
950 GtkWidget **toolbar,
951 GtkAccelGroup **accel_group)
952 {
953 GError *error = NULL;
954 gchar *uifile;
955
956 if (initialise)
957 menus_init();
958
959 /* the integrated ui menu */
960 integrated_ui_actions = gtk_action_group_new ("integrated-ui-actions");
961 gtk_action_group_set_translation_domain (integrated_ui_actions, NULL);
962 gtk_action_group_set_translate_func (integrated_ui_actions, _dia_translate, NULL, NULL);
963 gtk_action_group_add_actions (integrated_ui_actions, common_entries,
964 G_N_ELEMENTS (common_entries), NULL);
965 gtk_action_group_add_actions (integrated_ui_actions, toolbox_entries,
966 G_N_ELEMENTS (toolbox_entries), NULL);
967 gtk_action_group_add_actions (integrated_ui_actions, display_entries,
968 G_N_ELEMENTS (display_entries), NULL);
969 gtk_action_group_add_toggle_actions (integrated_ui_actions, integrated_ui_view_toggle_entries,
970 G_N_ELEMENTS (integrated_ui_view_toggle_entries), NULL);
971 gtk_action_group_add_toggle_actions (integrated_ui_actions, toolbox_toggle_entries,
972 G_N_ELEMENTS (toolbox_toggle_entries),
973 NULL);
974 gtk_action_group_add_toggle_actions (integrated_ui_actions, display_toggle_entries,
975 G_N_ELEMENTS (display_toggle_entries),
976 NULL);
977 gtk_action_group_add_radio_actions (integrated_ui_actions,
978 display_select_radio_entries,
979 G_N_ELEMENTS (display_select_radio_entries),
980 1,
981 G_CALLBACK (select_style_callback),
982 NULL);
983
984 integrated_ui_tool_actions = create_tool_actions ();
985
986 integrated_ui_manager = gtk_ui_manager_new ();
987 gtk_ui_manager_set_add_tearoffs (integrated_ui_manager, DIA_SHOW_TEAROFFS);
988 gtk_ui_manager_insert_action_group (integrated_ui_manager, integrated_ui_actions, 0);
989 gtk_ui_manager_insert_action_group (integrated_ui_manager, integrated_ui_tool_actions, 0);
990
991 uifile = build_ui_filename ("ui/integrated-ui.xml");
992 if (!gtk_ui_manager_add_ui_from_file (integrated_ui_manager, uifile, &error)) {
993 g_warning ("building integrated ui menus failed: %s", error->message);
994 g_error_free (error);
995 error = NULL;
996 }
997 g_free (uifile);
998 if (!gtk_ui_manager_add_ui_from_string (integrated_ui_manager, ui_info, -1, &error)) {
999 g_warning ("built-in menus failed: %s", error->message);
1000 g_error_free (error);
1001 error = NULL;
1002 }
1003
1004 add_plugin_actions (integrated_ui_manager, NULL);
1005
1006 integrated_ui_accels = gtk_ui_manager_get_accel_group (integrated_ui_manager);
1007 integrated_ui_menubar = gtk_ui_manager_get_widget (integrated_ui_manager, INTEGRATED_MENU);
1008 integrated_ui_toolbar = create_integrated_ui_toolbar ();
1009
1010 if (menubar)
1011 *menubar = integrated_ui_menubar;
1012 if (toolbar)
1013 *toolbar = integrated_ui_toolbar;
1014 if (accel_group)
1015 *accel_group = integrated_ui_accels;
1016 }
1017
1018 void
menus_get_toolbox_menubar(GtkWidget ** menubar,GtkAccelGroup ** accel_group)1019 menus_get_toolbox_menubar (GtkWidget **menubar,
1020 GtkAccelGroup **accel_group)
1021 {
1022 if (initialise)
1023 menus_init();
1024
1025 if (menubar)
1026 *menubar = toolbox_menubar;
1027 if (accel_group)
1028 *accel_group = toolbox_accels;
1029 }
1030
1031 GtkWidget *
menus_get_display_popup(void)1032 menus_get_display_popup (void)
1033 {
1034 if (initialise)
1035 menus_init();
1036
1037 return display_menubar;
1038 }
1039
1040 GtkAccelGroup *
menus_get_display_accels(void)1041 menus_get_display_accels (void)
1042 {
1043 if (initialise)
1044 menus_init();
1045
1046 if (is_integrated_ui ())
1047 return integrated_ui_accels;
1048
1049 return display_accels;
1050 }
1051
1052 GtkWidget *
menus_create_display_menubar(GtkUIManager ** ui_manager,GtkActionGroup ** actions)1053 menus_create_display_menubar (GtkUIManager **ui_manager,
1054 GtkActionGroup **actions)
1055 {
1056 GtkActionGroup *tool_actions;
1057 GtkWidget *menu_bar;
1058 GError *error = NULL;
1059 gchar *uifile;
1060
1061
1062 *actions = create_or_ref_display_actions ();
1063 tool_actions = create_tool_actions ();
1064
1065 *ui_manager = gtk_ui_manager_new ();
1066 gtk_ui_manager_set_add_tearoffs (*ui_manager, DIA_SHOW_TEAROFFS);
1067 gtk_ui_manager_insert_action_group (*ui_manager, *actions, 0);
1068 gtk_ui_manager_insert_action_group (*ui_manager, tool_actions, 0);
1069 g_object_unref (G_OBJECT (tool_actions));
1070
1071 uifile = build_ui_filename ("ui/display-ui.xml");
1072 if (!gtk_ui_manager_add_ui_from_file (*ui_manager, uifile, &error)) {
1073 g_warning ("building menus failed: %s", error->message);
1074 g_error_free (error);
1075 g_free (uifile);
1076 return NULL;
1077 }
1078 g_free (uifile);
1079
1080 add_plugin_actions (*ui_manager, DISPLAY_MENU);
1081 menu_bar = gtk_ui_manager_get_widget (*ui_manager, DISPLAY_MENU);
1082 return menu_bar;
1083 }
1084
1085 GtkAccelGroup *
menus_get_accel_group()1086 menus_get_accel_group ()
1087 {
1088 return is_integrated_ui ()? integrated_ui_accels : toolbox_accels;
1089 }
1090
1091 GtkActionGroup *
menus_get_action_group()1092 menus_get_action_group ()
1093 {
1094 return is_integrated_ui ()? integrated_ui_actions : toolbox_actions;
1095 }
1096
1097 GtkAction *
menus_get_action(const gchar * name)1098 menus_get_action (const gchar *name)
1099 {
1100 GtkAction *action;
1101
1102 if (is_integrated_ui ())
1103 {
1104 action = gtk_action_group_get_action (integrated_ui_actions, name);
1105 if (action == NULL) {
1106 action = gtk_action_group_get_action (integrated_ui_tool_actions, name);
1107 }
1108 }
1109 else
1110 {
1111 action = gtk_action_group_get_action (toolbox_actions, name);
1112 if (action == NULL) {
1113 action = gtk_action_group_get_action (display_actions, name);
1114 }
1115 if (action == NULL) {
1116 action = gtk_action_group_get_action (display_tool_actions, name);
1117 }
1118 }
1119 if (!action) {
1120 GList *groups, *list;
1121
1122 /* search everthing there is, could probably replace the above */
1123 groups = gtk_ui_manager_get_action_groups (display_ui_manager);
1124 for (list = groups; list != NULL; list = list->next) {
1125 action = gtk_action_group_get_action (GTK_ACTION_GROUP (list->data), name);
1126 if (action)
1127 break;
1128 }
1129 }
1130
1131 return action;
1132 }
1133
1134 void
menus_set_recent(GtkActionGroup * actions)1135 menus_set_recent (GtkActionGroup *actions)
1136 {
1137 GList *list;
1138 guint id;
1139 GtkUIManager *ui_manager;
1140 const char *recent_path;
1141
1142 if (is_integrated_ui ())
1143 {
1144 ui_manager = integrated_ui_manager;
1145 recent_path = INTEGRATED_MENU "/File/FileRecentEnd";
1146 }
1147 else
1148 {
1149 ui_manager = toolbox_ui_manager;
1150 recent_path = TOOLBOX_MENU "/File/FileRecentEnd";
1151 }
1152
1153 if (recent_actions) {
1154 menus_clear_recent ();
1155 }
1156
1157 list = gtk_action_group_list_actions (actions);
1158 g_return_if_fail (list);
1159
1160 recent_actions = actions;
1161 g_object_ref (G_OBJECT (recent_actions));
1162 gtk_ui_manager_insert_action_group (ui_manager,
1163 recent_actions,
1164 10 /* insert at back */ );
1165
1166 do {
1167 id = gtk_ui_manager_new_merge_id (ui_manager);
1168 recent_merge_ids = g_slist_prepend (recent_merge_ids, (gpointer) id);
1169
1170 gtk_ui_manager_add_ui (ui_manager, id,
1171 recent_path,
1172 gtk_action_get_name (GTK_ACTION (list->data)),
1173 gtk_action_get_name (GTK_ACTION (list->data)),
1174 GTK_UI_MANAGER_AUTO,
1175 TRUE);
1176
1177 } while (NULL != (list = list->next));
1178 }
1179
1180 void
menus_clear_recent(void)1181 menus_clear_recent (void)
1182 {
1183 GSList *id;
1184 GtkUIManager *ui_manager;
1185
1186 if (is_integrated_ui ())
1187 ui_manager = integrated_ui_manager;
1188 else
1189 ui_manager = toolbox_ui_manager;
1190
1191 if (recent_merge_ids) {
1192 id = recent_merge_ids;
1193 do {
1194 gtk_ui_manager_remove_ui (ui_manager, (guint) id->data);
1195
1196 } while (NULL != (id = id->next));
1197
1198 g_slist_free (recent_merge_ids);
1199 recent_merge_ids = NULL;
1200 }
1201
1202 if (recent_actions) {
1203 gtk_ui_manager_remove_action_group (ui_manager, recent_actions);
1204 g_object_unref (G_OBJECT (recent_actions));
1205 recent_actions = NULL;
1206 }
1207 }
1208
1209 static void
plugin_callback(GtkWidget * widget,gpointer data)1210 plugin_callback (GtkWidget *widget, gpointer data)
1211 {
1212 DiaCallbackFilter *cbf = data;
1213
1214 /* and finally invoke it */
1215 if (cbf->callback) {
1216 DDisplay *ddisp = NULL;
1217 DiagramData* diadata = NULL;
1218 /* stuff from the toolbox menu should never get a diagram to modify */
1219 if (strncmp (cbf->menupath, TOOLBOX_MENU, strlen (TOOLBOX_MENU)) != 0) {
1220 ddisp = ddisplay_active();
1221 diadata = ddisp ? ddisp->diagram->data : NULL;
1222 }
1223 cbf->callback (diadata, ddisp ? ddisp->diagram->filename : NULL, 0, cbf->user_data);
1224 }
1225 }
1226