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