1 /*
2 * This is a plug-in for GIMP.
3 *
4 * Generates clickable image maps.
5 *
6 * Copyright (C) 1998-2006 Maurits Rijk m.rijk@chello.nl
7 *
8 * This program is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>.
20 *
21 */
22
23 #include "config.h"
24
25 #include "libgimp/gimp.h"
26 #include "libgimp/gimpui.h"
27
28 #include "imap_about.h"
29 #include "imap_circle.h"
30 #include "imap_file.h"
31 #include "imap_grid.h"
32 #include "imap_main.h"
33 #include "imap_menu.h"
34 #include "imap_menu_funcs.h"
35 #include "imap_polygon.h"
36 #include "imap_preferences.h"
37 #include "imap_rectangle.h"
38 #include "imap_settings.h"
39 #include "imap_stock.h"
40 #include "imap_source.h"
41
42 #include "libgimp/stdplugins-intl.h"
43
44 static Menu_t _menu;
45 static GtkUIManager *ui_manager;
46
47 GtkWidget*
menu_get_widget(const gchar * path)48 menu_get_widget(const gchar *path)
49 {
50 return gtk_ui_manager_get_widget (ui_manager, path);
51 }
52
53 static void
set_sensitive(const gchar * path,gboolean sensitive)54 set_sensitive (const gchar *path, gboolean sensitive)
55 {
56 GtkAction *action = gtk_ui_manager_get_action (ui_manager, path);
57 g_object_set (action, "sensitive", sensitive, NULL);
58 }
59
60 static void
menu_mru(GtkWidget * widget,gpointer data)61 menu_mru(GtkWidget *widget, gpointer data)
62 {
63 MRU_t *mru = get_mru();
64 char *filename = (char*) data;
65
66 if (g_file_test(filename, G_FILE_TEST_IS_REGULAR)) {
67 load(filename);
68 } else {
69 do_file_error_dialog(_("Error opening file"), filename);
70 mru_remove(mru, filename);
71 menu_build_mru_items(mru);
72 }
73 }
74
75 void
menu_set_zoom_sensitivity(gint factor)76 menu_set_zoom_sensitivity(gint factor)
77 {
78 set_sensitive ("/MainMenu/ViewMenu/ZoomIn", factor < 8);
79 set_sensitive ("/MainMenu/ViewMenu/ZoomOut", factor > 1);
80 }
81
82 void
menu_set_zoom(gint factor)83 menu_set_zoom(gint factor)
84 {
85 menu_set_zoom_sensitivity (factor);
86 }
87
88 void
menu_shapes_selected(gint count)89 menu_shapes_selected(gint count)
90 {
91 gboolean sensitive = (count > 0);
92
93 set_sensitive ("/MainMenu/EditMenu/Cut", sensitive);
94 set_sensitive ("/MainMenu/EditMenu/Copy", sensitive);
95 set_sensitive ("/MainMenu/EditMenu/Clear", sensitive);
96 set_sensitive ("/MainMenu/EditMenu/EditAreaInfo", sensitive);
97 set_sensitive ("/MainMenu/EditMenu/DeselectAll", sensitive);
98 }
99
100 static void
command_list_changed(Command_t * command,gpointer data)101 command_list_changed(Command_t *command, gpointer data)
102 {
103 GtkAction *action;
104 gchar *label;
105
106 action = gtk_ui_manager_get_action (ui_manager, "/MainMenu/EditMenu/Undo");
107
108 label = g_strdup_printf (_("_Undo %s"),
109 command && command->name ? command->name : "");
110
111 g_object_set (action,
112 "label", label,
113 "sensitive", command != NULL,
114 NULL);
115 g_free (label);
116
117 command = command_list_get_redo_command();
118
119 action = gtk_ui_manager_get_action (ui_manager, "/MainMenu/EditMenu/Redo");
120
121 label = g_strdup_printf (_("_Redo %s"),
122 command && command->name ? command->name : "");
123 g_object_set (action,
124 "label", label,
125 "sensitive", command != NULL,
126 NULL);
127 g_free (label);
128 }
129
130 static void
paste_buffer_added(Object_t * obj,gpointer data)131 paste_buffer_added(Object_t *obj, gpointer data)
132 {
133 set_sensitive("/MainMenu/EditMenu/Paste", TRUE);
134 }
135
136 static void
paste_buffer_removed(Object_t * obj,gpointer data)137 paste_buffer_removed(Object_t *obj, gpointer data)
138 {
139 set_sensitive("/MainMenu/EditMenu/Paste", FALSE);
140 }
141
142 /* Normal items */
143 static const GtkActionEntry entries[] =
144 {
145 { "FileMenu", NULL,
146 N_("_File") },
147 { "Open", GIMP_ICON_DOCUMENT_OPEN,
148 N_("_Open..."), NULL, N_("Open"),
149 do_file_open_dialog},
150 { "Save", GIMP_ICON_DOCUMENT_SAVE,
151 N_("_Save..."), NULL, N_("Save"),
152 save},
153 { "SaveAs", GIMP_ICON_DOCUMENT_SAVE_AS,
154 N_("Save _As..."), "<shift><control>S", NULL,
155 do_file_save_as_dialog},
156 { "Close", GIMP_ICON_CLOSE, N_("_Close"), "<primary>w", NULL, do_close},
157 { "Quit", GIMP_ICON_APPLICATION_EXIT,
158 N_("_Quit"), "<primary>q", NULL, do_quit},
159
160 { "EditMenu", NULL, N_("_Edit") },
161 { "Undo", GIMP_ICON_EDIT_UNDO,
162 N_("_Undo"), NULL, N_("Undo"), do_undo},
163 { "Redo", GIMP_ICON_EDIT_REDO,
164 N_("_Redo"), NULL, N_("Redo"), do_redo},
165 { "Cut", GIMP_ICON_EDIT_CUT,
166 N_("Cu_t"), "<primary>x", N_("Cut"), do_cut},
167 { "Copy", GIMP_ICON_EDIT_COPY,
168 N_("_Copy"), "<primary>c", N_("Copy"), do_copy},
169 { "Paste", GIMP_ICON_EDIT_PASTE,
170 N_("_Paste"), "<primary>v", N_("Paste"), do_paste},
171 { "Clear", GIMP_ICON_EDIT_DELETE,
172 N_("_Delete"), NULL, N_("Delete"), do_clear},
173 { "SelectAll", NULL,
174 N_("Select _All"), "<primary>A", NULL, do_select_all},
175 { "DeselectAll", NULL,
176 N_("D_eselect All"), "<shift><primary>A", NULL,
177 do_deselect_all},
178 { "EditAreaInfo", GIMP_ICON_EDIT
179 , N_("Edit Area _Info..."), NULL,
180 N_("Edit selected area info"), do_edit_selected_shape},
181 { "Preferences", GIMP_ICON_PREFERENCES_SYSTEM,
182 N_("_Preferences"), NULL, N_("Preferences"),
183 do_preferences_dialog},
184 { "MoveToFront", IMAP_STOCK_TO_FRONT, "", NULL, N_("Move Area to Front"),
185 do_move_to_front},
186 { "SendToBack", IMAP_STOCK_TO_BACK, "", NULL, N_("Move Area to Bottom"),
187 do_send_to_back},
188 { "DeleteArea", NULL, N_("Delete Area"), NULL, NULL, NULL},
189 { "MoveUp", GIMP_ICON_GO_UP, N_("Move Up"), NULL, NULL, NULL},
190 { "MoveDown", GIMP_ICON_GO_DOWN, N_("Move Down"), NULL, NULL, NULL},
191
192 { "InsertPoint", NULL, N_("Insert Point"), NULL, NULL, polygon_insert_point},
193 { "DeletePoint", NULL, N_("Delete Point"), NULL, NULL, polygon_delete_point},
194
195 { "ViewMenu", NULL, N_("_View") },
196 { "Source", NULL, N_("Source..."), NULL, NULL, do_source_dialog},
197 { "ZoomIn", GIMP_ICON_ZOOM_IN, N_("Zoom _In"), "plus", N_("Zoom in"), do_zoom_in},
198 { "ZoomOut", GIMP_ICON_ZOOM_OUT, N_("Zoom _Out"), "minus", N_("Zoom out"), do_zoom_out},
199 { "ZoomToMenu", NULL, N_("_Zoom To") },
200
201 { "MappingMenu", NULL, N_("_Mapping") },
202 { "EditMapInfo", GIMP_ICON_DIALOG_INFORMATION, N_("Edit Map Info..."), NULL,
203 N_("Edit Map Info"), do_settings_dialog},
204
205 { "ToolsMenu", NULL, N_("_Tools") },
206 { "GridSettings", NULL, N_("Grid Settings..."), NULL, NULL,
207 do_grid_settings_dialog},
208 { "UseGimpGuides", NULL, N_("Use GIMP Guides..."), NULL, NULL,
209 do_use_gimp_guides_dialog},
210 { "CreateGuides", NULL, N_("Create Guides..."), NULL, NULL,
211 do_create_guides_dialog},
212
213 { "HelpMenu", NULL, N_("_Help") },
214 { "Contents", GIMP_ICON_HELP, N_("_Contents"), NULL, NULL, imap_help},
215 { "About", GIMP_ICON_HELP_ABOUT, N_("_About"), NULL, NULL, do_about_dialog},
216
217 { "ZoomMenu", NULL, N_("_Zoom") },
218 };
219
220 /* Toggle items */
221 static const GtkToggleActionEntry toggle_entries[] = {
222 { "AreaList", NULL, N_("Area List"), NULL, NULL, NULL, TRUE },
223 { "Grid", GIMP_ICON_GRID, N_("_Grid"), NULL, N_("Grid"), toggle_grid, FALSE }
224 };
225
226 static const GtkRadioActionEntry color_entries[] = {
227 { "Color", NULL, N_("Color"), NULL, NULL, 0},
228 { "Gray", NULL, N_("Gray"), NULL, NULL, 1},
229 };
230
231 static const GtkRadioActionEntry mapping_entries[] = {
232 { "Arrow", GIMP_ICON_CURSOR, N_("Arrow"), NULL,
233 N_("Select existing area"), 0},
234 { "Rectangle", IMAP_STOCK_RECTANGLE, N_("Rectangle"), NULL,
235 N_("Define Rectangle area"), 1},
236 { "Circle", IMAP_STOCK_CIRCLE, N_("Circle"), NULL,
237 N_("Define Circle/Oval area"), 2},
238 { "Polygon", IMAP_STOCK_POLYGON, N_("Polygon"), NULL,
239 N_("Define Polygon area"), 3},
240 };
241
242 static const GtkRadioActionEntry zoom_entries[] = {
243 { "Zoom1:1", NULL, "1:1", NULL, NULL, 0},
244 { "Zoom1:2", NULL, "1:2", NULL, NULL, 1},
245 { "Zoom1:3", NULL, "1:3", NULL, NULL, 2},
246 { "Zoom1:4", NULL, "1:4", NULL, NULL, 3},
247 { "Zoom1:5", NULL, "1:5", NULL, NULL, 4},
248 { "Zoom1:6", NULL, "1:6", NULL, NULL, 5},
249 { "Zoom1:7", NULL, "1:7", NULL, NULL, 6},
250 { "Zoom1:8", NULL, "1:8", NULL, NULL, 7},
251 };
252
253 static const gchar ui_description[] =
254 "<ui>"
255 " <menubar name='MainMenu'>"
256 " <menu action='FileMenu'>"
257 " <menuitem action='Open'/>"
258 " <menuitem action='Save'/>"
259 " <menuitem action='SaveAs'/>"
260 " <separator/>"
261 " <menuitem action='Close'/>"
262 " <menuitem action='Quit'/>"
263 " </menu>"
264 " <menu action='EditMenu'>"
265 " <menuitem action='Undo'/>"
266 " <menuitem action='Redo'/>"
267 " <menuitem action='Cut'/>"
268 " <menuitem action='Copy'/>"
269 " <menuitem action='Paste'/>"
270 " <menuitem action='Clear'/>"
271 " <separator/>"
272 " <menuitem action='SelectAll'/>"
273 " <menuitem action='DeselectAll'/>"
274 " <separator/>"
275 " <menuitem action='EditAreaInfo'/>"
276 " <separator/>"
277 " <menuitem action='Preferences'/>"
278 " </menu>"
279 " <menu action='ViewMenu'>"
280 " <menuitem action='AreaList'/>"
281 " <menuitem action='Source'/>"
282 " <separator/>"
283 " <menuitem action='Color'/>"
284 " <menuitem action='Gray'/>"
285 " <separator/>"
286 " <menuitem action='ZoomIn'/>"
287 " <menuitem action='ZoomOut'/>"
288 " <menu action='ZoomToMenu'>"
289 " <menuitem action='Zoom1:1'/>"
290 " <menuitem action='Zoom1:2'/>"
291 " <menuitem action='Zoom1:3'/>"
292 " <menuitem action='Zoom1:4'/>"
293 " <menuitem action='Zoom1:5'/>"
294 " <menuitem action='Zoom1:6'/>"
295 " <menuitem action='Zoom1:7'/>"
296 " <menuitem action='Zoom1:8'/>"
297 " </menu>"
298 " </menu>"
299 " <menu action='MappingMenu'>"
300 " <menuitem action='Arrow'/>"
301 " <menuitem action='Rectangle'/>"
302 " <menuitem action='Circle'/>"
303 " <menuitem action='Polygon'/>"
304 " <separator/>"
305 " <menuitem action='EditMapInfo'/>"
306 " </menu>"
307 " <menu action='ToolsMenu'>"
308 " <menuitem action='Grid'/>"
309 " <menuitem action='GridSettings'/>"
310 " <separator/>"
311 " <menuitem action='UseGimpGuides'/>"
312 " <menuitem action='CreateGuides'/>"
313 " </menu>"
314 " <menu action='HelpMenu'>"
315 " <menuitem action='Contents'/>"
316 " <menuitem action='About'/>"
317 " </menu>"
318 " </menubar>"
319 ""
320 " <popup name='PopupMenu'>"
321 " <menuitem action='EditMapInfo'/>"
322 " <menu action='ToolsMenu'>"
323 " <menuitem action='Arrow'/>"
324 " <menuitem action='Rectangle'/>"
325 " <menuitem action='Circle'/>"
326 " <menuitem action='Polygon'/>"
327 " </menu>"
328 " <menu action='ZoomMenu'>"
329 " <menuitem action='ZoomIn'/>"
330 " <menuitem action='ZoomOut'/>"
331 " </menu>"
332 " <menuitem action='Grid'/>"
333 " <menuitem action='GridSettings'/>"
334 " <menuitem action='CreateGuides'/>"
335 " <menuitem action='Paste'/>"
336 " </popup>"
337 ""
338 " <popup name='ObjectPopupMenu'>"
339 " <menuitem action='EditAreaInfo'/>"
340 " <menuitem action='DeleteArea'/>"
341 " <menuitem action='MoveUp'/>"
342 " <menuitem action='MoveDown'/>"
343 " <menuitem action='Cut'/>"
344 " <menuitem action='Copy'/>"
345 " </popup>"
346 ""
347 " <popup name='PolygonPopupMenu'>"
348 " <menuitem action='InsertPoint'/>"
349 " <menuitem action='DeletePoint'/>"
350 " <menuitem action='EditAreaInfo'/>"
351 " <menuitem action='DeleteArea'/>"
352 " <menuitem action='MoveUp'/>"
353 " <menuitem action='MoveDown'/>"
354 " <menuitem action='Cut'/>"
355 " <menuitem action='Copy'/>"
356 " </popup>"
357 ""
358 " <toolbar name='Toolbar'>"
359 " <toolitem action='Open'/>"
360 " <toolitem action='Save'/>"
361 " <separator/>"
362 " <toolitem action='Preferences'/>"
363 " <separator/>"
364 " <toolitem action='Undo'/>"
365 " <toolitem action='Redo'/>"
366 " <separator/>"
367 " <toolitem action='Cut'/>"
368 " <toolitem action='Copy'/>"
369 " <toolitem action='Paste'/>"
370 " <separator/>"
371 " <toolitem action='ZoomIn'/>"
372 " <toolitem action='ZoomOut'/>"
373 " <separator/>"
374 " <toolitem action='EditMapInfo'/>"
375 " <separator/>"
376 " <toolitem action='MoveToFront'/>"
377 " <toolitem action='SendToBack'/>"
378 " <separator/>"
379 " <toolitem action='Grid'/>"
380 " </toolbar>"
381 ""
382 " <toolbar name='Tools'>"
383 " <toolitem action='Arrow'/>"
384 " <toolitem action='Rectangle'/>"
385 " <toolitem action='Circle'/>"
386 " <toolitem action='Polygon'/>"
387 " <separator/>"
388 " <toolitem action='EditAreaInfo'/>"
389 " </toolbar>"
390 ""
391 " <toolbar name='Selection'>"
392 " <toolitem action='MoveUp'/>"
393 " <toolitem action='MoveDown'/>"
394 " <toolitem action='EditAreaInfo'/>"
395 " <toolitem action='Clear'/>"
396 " </toolbar>"
397 "</ui>";
398
399 Menu_t*
make_menu(GtkWidget * main_vbox,GtkWidget * window)400 make_menu(GtkWidget *main_vbox, GtkWidget *window)
401 {
402 GtkWidget *menubar;
403 GtkActionGroup *action_group;
404 GtkAccelGroup *accel_group;
405 GError *error;
406
407 action_group = gtk_action_group_new ("MenuActions");
408 gtk_action_group_set_translation_domain (action_group, NULL);
409
410 gtk_action_group_add_actions (action_group, entries, G_N_ELEMENTS (entries),
411 window);
412 gtk_action_group_add_toggle_actions (action_group, toggle_entries,
413 G_N_ELEMENTS (toggle_entries), window);
414
415 gtk_action_group_add_radio_actions (action_group, color_entries,
416 G_N_ELEMENTS (color_entries), 0,
417 G_CALLBACK (set_preview_color), NULL);
418 gtk_action_group_add_radio_actions (action_group, zoom_entries,
419 G_N_ELEMENTS (zoom_entries), 0,
420 G_CALLBACK (set_zoom_factor), NULL);
421 gtk_action_group_add_radio_actions (action_group, mapping_entries,
422 G_N_ELEMENTS (mapping_entries), 0,
423 G_CALLBACK (set_func), window);
424
425 ui_manager = gtk_ui_manager_new ();
426 gtk_ui_manager_insert_action_group (ui_manager, action_group, 0);
427
428 accel_group = gtk_ui_manager_get_accel_group (ui_manager);
429 gtk_window_add_accel_group (GTK_WINDOW (window), accel_group);
430
431 error = NULL;
432 if (!gtk_ui_manager_add_ui_from_string (ui_manager, ui_description, -1,
433 &error))
434 {
435 g_warning ("building menus failed: %s", error->message);
436 g_error_free (error);
437 /* exit (EXIT_FAILURE); */
438 }
439
440 menubar = gtk_ui_manager_get_widget (ui_manager, "/MainMenu");
441 gtk_widget_show (menubar);
442 gtk_box_pack_start (GTK_BOX (main_vbox), menubar, FALSE, FALSE, 0);
443
444 paste_buffer_add_add_cb(paste_buffer_added, NULL);
445 paste_buffer_add_remove_cb(paste_buffer_removed, NULL);
446
447 set_sensitive ("/MainMenu/EditMenu/Paste", FALSE);
448 menu_shapes_selected (0);
449
450 menu_set_zoom_sensitivity (1);
451
452 command_list_add_update_cb (command_list_changed, NULL);
453
454 command_list_changed (NULL, NULL);
455
456 return &_menu;
457 }
458
459 void
menu_build_mru_items(MRU_t * mru)460 menu_build_mru_items(MRU_t *mru)
461 {
462 GList *p;
463 gint position = 0;
464 int i;
465
466 return;
467
468 if (_menu.nr_off_mru_items) {
469 GList *children;
470
471 children = gtk_container_get_children(GTK_CONTAINER(_menu.open_recent));
472 p = g_list_nth(children, position);
473 for (i = 0; i < _menu.nr_off_mru_items; i++, p = p->next) {
474 gtk_widget_destroy((GtkWidget*) p->data);
475 }
476 g_list_free(children);
477 }
478
479 i = 0;
480 for (p = mru->list; p; p = p->next, i++) {
481 GtkWidget *item = insert_item_with_label(_menu.open_recent, position++,
482 (gchar*) p->data,
483 menu_mru, p->data);
484 if (i < 9) {
485 guchar accelerator_key = '1' + i;
486 add_accelerator(item, accelerator_key, GDK_CONTROL_MASK);
487 }
488 }
489 _menu.nr_off_mru_items = i;
490 }
491
492 void
do_main_popup_menu(GdkEventButton * event)493 do_main_popup_menu(GdkEventButton *event)
494 {
495 GtkWidget *popup = gtk_ui_manager_get_widget (ui_manager, "/PopupMenu");
496 gtk_menu_popup (GTK_MENU (popup), NULL, NULL, NULL, NULL,
497 event->button, event->time);
498 }
499
500 void
menu_check_grid(gboolean check)501 menu_check_grid(gboolean check)
502 {
503 GtkAction *action = gtk_ui_manager_get_action (ui_manager,
504 "/MainMenu/ToolsMenu/Grid");
505 gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), check);
506 }
507
508 GtkWidget*
make_toolbar(GtkWidget * main_vbox,GtkWidget * window)509 make_toolbar(GtkWidget *main_vbox, GtkWidget *window)
510 {
511 GtkWidget *toolbar;
512
513 toolbar = gtk_ui_manager_get_widget (ui_manager, "/Toolbar");
514 gtk_toolbar_set_style (GTK_TOOLBAR (toolbar), GTK_TOOLBAR_ICONS);
515 gtk_container_set_border_width (GTK_CONTAINER (toolbar), 0);
516 gtk_box_pack_start (GTK_BOX (main_vbox), toolbar, FALSE, FALSE, 0);
517 gtk_widget_show (toolbar);
518
519 return toolbar;
520 }
521
522 GtkWidget*
make_tools(GtkWidget * window)523 make_tools(GtkWidget *window)
524 {
525 GtkWidget *toolbar;
526
527 toolbar = gtk_ui_manager_get_widget (ui_manager, "/Tools");
528 gtk_orientable_set_orientation (GTK_ORIENTABLE (toolbar),
529 GTK_ORIENTATION_VERTICAL);
530 gtk_toolbar_set_style (GTK_TOOLBAR (toolbar), GTK_TOOLBAR_ICONS);
531 gtk_container_set_border_width (GTK_CONTAINER (toolbar), 0);
532 gtk_widget_show (toolbar);
533
534 return toolbar;
535 }
536
537 GtkWidget*
make_selection_toolbar(void)538 make_selection_toolbar(void)
539 {
540 GtkWidget *toolbar;
541
542 toolbar = gtk_ui_manager_get_widget (ui_manager, "/Selection");
543
544 gtk_toolbar_set_style (GTK_TOOLBAR (toolbar), GTK_TOOLBAR_ICONS);
545 gtk_orientable_set_orientation (GTK_ORIENTABLE (toolbar),
546 GTK_ORIENTATION_VERTICAL);
547 gtk_container_set_border_width (GTK_CONTAINER (toolbar), 0);
548
549 gtk_widget_show (toolbar);
550 return toolbar;
551 }
552