/* The GIMP -- an image manipulation program * Copyright (C) 1995 Spencer Kimball and Peter Mattis * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include "appenv.h" #include "colormaps.h" #include "commands.h" #include "fileops.h" #include "gimprc.h" #include "interface.h" #include "menus.h" #include "paint_funcs.h" #include "procedural_db.h" #include "scale.h" #include "tools.h" #include "gdisplay.h" static void menus_init (void); static void menus_foreach (gpointer key, gpointer value, gpointer user_data); static gint menus_install_accel (GtkWidget *widget, gchar *signal_name, gchar key, gchar modifiers, gchar *path); static void menus_remove_accel (GtkWidget *widget, gchar *signal_name, gchar *path); static void menus_activate_callback (GtkWidget *widget, GtkMenuEntry *entry); static GtkMenuEntry menu_items[] = { { "/File/New", "N", file_new_cmd_callback, NULL }, { "/File/Open", "O", file_open_cmd_callback, NULL }, { "/File/About...", NULL, about_dialog_cmd_callback, NULL }, { "/File/Preferences...", NULL, file_pref_cmd_callback, NULL }, { "/File/Tip of the day", NULL, tips_dialog_cmd_callback, NULL }, { "/File/", NULL, NULL, NULL }, { "/File/Dialogs/Brushes...", "B", dialogs_brushes_cmd_callback, NULL }, { "/File/Dialogs/Patterns...", "P", dialogs_patterns_cmd_callback, NULL }, { "/File/Dialogs/Palette...", "P", dialogs_palette_cmd_callback, NULL }, { "/File/Dialogs/Gradient Editor...", "G", dialogs_gradient_editor_cmd_callback, NULL }, { "/File/Dialogs/Tool Options...", "T", dialogs_tools_options_cmd_callback, NULL }, { "/File/",NULL,NULL,NULL}, { "/File/Quit", "Q", file_quit_cmd_callback, NULL }, { "/File/New", "N", file_new_cmd_callback, (gpointer) 1 }, { "/File/Open", "O", file_open_cmd_callback, NULL }, { "/File/Save", "S", file_save_cmd_callback, NULL }, { "/File/Save as", NULL, file_save_as_cmd_callback, NULL }, { "/File/Preferences...", NULL, file_pref_cmd_callback, NULL }, { "/File/", NULL, NULL, NULL }, { "/File/Close", "W", file_close_cmd_callback, NULL }, { "/File/Quit", "Q", file_quit_cmd_callback, NULL }, { "/File/", NULL, NULL, NULL }, { "/Edit/Cut", "X", edit_cut_cmd_callback, NULL }, { "/Edit/Copy", "C", edit_copy_cmd_callback, NULL }, { "/Edit/Paste", "V", edit_paste_cmd_callback, NULL }, { "/Edit/Paste Into", NULL, edit_paste_into_cmd_callback, NULL }, { "/Edit/Clear", "K", edit_clear_cmd_callback, NULL }, { "/Edit/Fill", ".", edit_fill_cmd_callback, NULL }, { "/Edit/Stroke", NULL, edit_stroke_cmd_callback, NULL }, { "/Edit/Undo", "Z", edit_undo_cmd_callback, NULL }, { "/Edit/Redo", "R", edit_redo_cmd_callback, NULL }, { "/Edit/", NULL, NULL, NULL }, { "/Edit/Cut Named", "X", edit_named_cut_cmd_callback, NULL }, { "/Edit/Copy Named", "C", edit_named_copy_cmd_callback, NULL }, { "/Edit/Paste Named", "V", edit_named_paste_cmd_callback, NULL }, { "/Edit/", NULL, NULL, NULL }, { "/Select/Toggle", "T", select_toggle_cmd_callback, NULL }, { "/Select/Invert", "I", select_invert_cmd_callback, NULL }, { "/Select/All", "A", select_all_cmd_callback, NULL }, { "/Select/None", "A", select_none_cmd_callback, NULL }, { "/Select/Float", "L", select_float_cmd_callback, NULL }, { "/Select/Sharpen", "H", select_sharpen_cmd_callback, NULL }, { "/Select/Border", "B", select_border_cmd_callback, NULL }, { "/Select/Feather", "F", select_feather_cmd_callback, NULL }, { "/Select/Grow", NULL, select_grow_cmd_callback, NULL }, { "/Select/Shrink", NULL, select_shrink_cmd_callback, NULL }, { "/Select/Save To Channel", NULL, select_save_cmd_callback, NULL }, { "/Select/By Color...", NULL, select_by_color_cmd_callback, NULL }, { "/View/Zoom In", "=", view_zoomin_cmd_callback, NULL }, { "/View/Zoom Out", "-", view_zoomout_cmd_callback, NULL }, { "/View/Zoom/16:1", NULL, view_zoom_16_1_callback, NULL }, { "/View/Zoom/8:1", NULL, view_zoom_8_1_callback, NULL }, { "/View/Zoom/4:1", NULL, view_zoom_4_1_callback, NULL }, { "/View/Zoom/2:1", NULL, view_zoom_2_1_callback, NULL }, { "/View/Zoom/1:1", "1", view_zoom_1_1_callback, NULL }, { "/View/Zoom/1:2", NULL, view_zoom_1_2_callback, NULL }, { "/View/Zoom/1:4", NULL, view_zoom_1_4_callback, NULL }, { "/View/Zoom/1:8", NULL, view_zoom_1_8_callback, NULL }, { "/View/Zoom/1:16", NULL, view_zoom_1_16_callback, NULL }, { "/View/Window Info...", "I", view_window_info_cmd_callback, NULL }, { "/View/Toggle Rulers", "R", view_toggle_rulers_cmd_callback, NULL }, { "/View/Toggle Guides", "T", view_toggle_guides_cmd_callback, NULL }, { "/View/Snap To Guides", NULL, view_snap_to_guides_cmd_callback, NULL }, { "/View/", NULL, NULL, NULL }, { "/View/New View", NULL, view_new_view_cmd_callback, NULL }, { "/View/Shrink Wrap", "E", view_shrink_wrap_cmd_callback, NULL }, { "/Image/Colors/Equalize", NULL, image_equalize_cmd_callback, NULL }, { "/Image/Colors/Invert", NULL, image_invert_cmd_callback, NULL }, { "/Image/Colors/Posterize", NULL, image_posterize_cmd_callback, NULL }, { "/Image/Colors/Threshold", NULL, image_threshold_cmd_callback, NULL }, { "/Image/Colors/", NULL, NULL, NULL }, { "/Image/Colors/Color Balance", NULL, image_color_balance_cmd_callback, NULL }, { "/Image/Colors/Brightness-Contrast", NULL, image_brightness_contrast_cmd_callback, NULL }, { "/Image/Colors/Hue-Saturation", NULL, image_hue_saturation_cmd_callback, NULL }, { "/Image/Colors/Curves", NULL, image_curves_cmd_callback, NULL }, { "/Image/Colors/Levels", NULL, image_levels_cmd_callback, NULL }, { "/Image/Colors/", NULL, NULL, NULL }, { "/Image/Colors/Desaturate", NULL, image_desaturate_cmd_callback, NULL }, { "/Image/Channel Ops/Duplicate", "D", channel_ops_duplicate_cmd_callback, NULL }, { "/Image/Channel Ops/Offset", "O", channel_ops_offset_cmd_callback, NULL }, { "/Image/", NULL, NULL, NULL }, { "/Image/RGB", NULL, image_convert_rgb_cmd_callback, NULL }, { "/Image/Grayscale", NULL, image_convert_grayscale_cmd_callback, NULL }, { "/Image/Indexed", NULL, image_convert_indexed_cmd_callback, NULL }, { "/Image/", NULL, NULL, NULL }, { "/Image/Resize", NULL, image_resize_cmd_callback, NULL }, { "/Image/Scale", NULL, image_scale_cmd_callback, NULL }, { "/Image/", NULL, NULL, NULL }, { "/Image/Histogram", NULL, image_histogram_cmd_callback, NULL }, { "/Image/", NULL, NULL, NULL }, { "/Layers/Layers & Channels...", "L", dialogs_lc_cmd_callback, NULL }, { "/Layers/Raise Layer", "F", layers_raise_cmd_callback, NULL }, { "/Layers/Lower Layer", "B", layers_lower_cmd_callback, NULL }, { "/Layers/Anchor Layer", "H", layers_anchor_cmd_callback, NULL }, { "/Layers/Merge Visible Layers", "M", layers_merge_cmd_callback, NULL }, { "/Layers/Flatten Image", NULL, layers_flatten_cmd_callback, NULL }, { "/Layers/Alpha To Selection", NULL, layers_alpha_select_cmd_callback, NULL }, { "/Layers/Mask To Selection", NULL, layers_mask_select_cmd_callback, NULL }, { "/Tools/Rect Select", "R", tools_select_cmd_callback, (gpointer) RECT_SELECT }, { "/Tools/Ellipse Select", "E", tools_select_cmd_callback, (gpointer) ELLIPSE_SELECT }, { "/Tools/Free Select", "F", tools_select_cmd_callback, (gpointer) FREE_SELECT }, { "/Tools/Fuzzy Select", "Z", tools_select_cmd_callback, (gpointer) FUZZY_SELECT }, { "/Tools/Bezier Select", "B", tools_select_cmd_callback, (gpointer) BEZIER_SELECT }, { "/Tools/Intelligent Scissors", "I", tools_select_cmd_callback, (gpointer) ISCISSORS }, { "/Tools/Move", "M", tools_select_cmd_callback, (gpointer) MOVE }, { "/Tools/Magnify", "M", tools_select_cmd_callback, (gpointer) MAGNIFY }, { "/Tools/Crop", "C", tools_select_cmd_callback, (gpointer) CROP }, { "/Tools/Transform", "T", tools_select_cmd_callback, (gpointer) ROTATE }, { "/Tools/Flip", "F", tools_select_cmd_callback, (gpointer) FLIP_HORZ }, { "/Tools/Text", "T", tools_select_cmd_callback, (gpointer) TEXT }, { "/Tools/Color Picker", "O", tools_select_cmd_callback, (gpointer) COLOR_PICKER }, { "/Tools/Bucket Fill", "B", tools_select_cmd_callback, (gpointer) BUCKET_FILL }, { "/Tools/Blend", "L", tools_select_cmd_callback, (gpointer) BLEND }, { "/Tools/Paintbrush", "P", tools_select_cmd_callback, (gpointer) PAINTBRUSH }, { "/Tools/Pencil", "P", tools_select_cmd_callback, (gpointer) PENCIL }, { "/Tools/Eraser", "E", tools_select_cmd_callback, (gpointer) ERASER }, { "/Tools/Airbrush", "A", tools_select_cmd_callback, (gpointer) AIRBRUSH }, { "/Tools/Clone", "C", tools_select_cmd_callback, (gpointer) CLONE }, { "/Tools/Convolve", "V", tools_select_cmd_callback, (gpointer) CONVOLVE }, { "/Tools/Default Colors", "D", tools_default_colors_cmd_callback, NULL}, { "/Tools/Swap Colors", "X", tools_swap_colors_cmd_callback, NULL}, { "/Tools/", NULL, NULL, NULL }, { "/Tools/Toolbox", NULL, toolbox_raise_callback, NULL }, { "/Filters/", NULL, NULL, NULL }, { "/Filters/Repeat last", "F", filters_repeat_cmd_callback, (gpointer) 0x0 }, { "/Filters/Re-show last", "F", filters_repeat_cmd_callback, (gpointer) 0x1 }, { "/Filters/", NULL, NULL, NULL }, { "/Script-Fu/", NULL, NULL, NULL }, { "/Dialogs/Brushes...", "B", dialogs_brushes_cmd_callback, NULL }, { "/Dialogs/Patterns...", "P", dialogs_patterns_cmd_callback, NULL }, { "/Dialogs/Palette...", "P", dialogs_palette_cmd_callback, NULL }, { "/Dialogs/Gradient Editor...", "G", dialogs_gradient_editor_cmd_callback, NULL }, { "/Dialogs/Layers & Channels...", "L", dialogs_lc_cmd_callback, NULL }, { "/Dialogs/Indexed Palette...", NULL, dialogs_indexed_palette_cmd_callback, NULL }, { "/Dialogs/Tool Options...", NULL, dialogs_tools_options_cmd_callback, NULL }, { "/Automatic", NULL, file_load_by_extension_callback, NULL }, { "/", NULL, NULL, NULL }, { "/By extension", NULL, file_save_by_extension_callback, NULL }, { "/", NULL, NULL, NULL }, }; static int nmenu_items = sizeof (menu_items) / sizeof (menu_items[0]); static int initialize = TRUE; static GtkMenuFactory *factory = NULL; static GtkMenuFactory *subfactories[4]; static GHashTable *entry_ht = NULL; void menus_get_toolbox_menubar (GtkWidget **menubar, GtkAcceleratorTable **table) { if (initialize) menus_init (); if (menubar) *menubar = subfactories[0]->widget; if (table) *table = subfactories[0]->table; } void menus_get_image_menu (GtkWidget **menu, GtkAcceleratorTable **table) { if (initialize) menus_init (); if (menu) *menu = subfactories[1]->widget; if (table) *table = subfactories[1]->table; } void menus_get_load_menu (GtkWidget **menu, GtkAcceleratorTable **table) { if (initialize) menus_init (); if (menu) *menu = subfactories[2]->widget; if (table) *table = subfactories[2]->table; } void menus_get_save_menu (GtkWidget **menu, GtkAcceleratorTable **table) { if (initialize) menus_init (); if (menu) *menu = subfactories[3]->widget; if (table) *table = subfactories[3]->table; } void menus_create (GtkMenuEntry *entries, int nmenu_entries) { char *accelerator; int i; if (initialize) menus_init (); if (entry_ht) for (i = 0; i < nmenu_entries; i++) { accelerator = g_hash_table_lookup (entry_ht, entries[i].path); if (accelerator) { if (accelerator[0] == '\0') entries[i].accelerator = NULL; else entries[i].accelerator = accelerator; } } gtk_menu_factory_add_entries (factory, entries, nmenu_entries); for (i = 0; i < nmenu_entries; i++) if (entries[i].widget && GTK_BIN (entries[i].widget)->child) { gtk_signal_connect (GTK_OBJECT (entries[i].widget), "install_accelerator", (GtkSignalFunc) menus_install_accel, entries[i].path); gtk_signal_connect (GTK_OBJECT (entries[i].widget), "remove_accelerator", (GtkSignalFunc) menus_remove_accel, entries[i].path); gtk_signal_connect (GTK_OBJECT (entries[i].widget), "activate", (GtkSignalFunc) menus_activate_callback, &entries[i]); } } void menus_set_sensitive (char *path, int sensitive) { GtkMenuPath *menu_path; if (initialize) menus_init (); menu_path = gtk_menu_factory_find (factory, path); if (menu_path) gtk_widget_set_sensitive (menu_path->widget, sensitive); else g_warning ("Unable to set sensitivity for menu which doesn't exist: %s", path); } void menus_set_state (char *path, int state) { GtkMenuPath *menu_path; if (initialize) menus_init (); menu_path = gtk_menu_factory_find (factory, path); if (menu_path) { if (GTK_IS_CHECK_MENU_ITEM (menu_path->widget)) gtk_check_menu_item_set_state (GTK_CHECK_MENU_ITEM (menu_path->widget), state); } else g_warning ("Unable to set state for menu which doesn't exist: %s", path); } void menus_add_path (char *path, char *accelerator) { if (!entry_ht) entry_ht = g_hash_table_new (g_str_hash, g_str_equal); g_hash_table_insert (entry_ht, path, accelerator); } void menus_destroy (char *path) { if (initialize) menus_init (); gtk_menu_factory_remove_paths (factory, &path, 1); } void menus_quit () { FILE *fp; char filename[512]; char *gimp_dir; if (entry_ht) { gimp_dir = gimp_directory (); if ('\000' != gimp_dir[0]) { sprintf (filename, "%s/menurc", gimp_dir); fp = fopen (filename, "w"); if (fp) { g_hash_table_foreach (entry_ht, menus_foreach, fp); fclose (fp); } } } if (!initialize) { gtk_menu_factory_destroy (factory); } } static void menus_init () { char filename[512]; if (initialize) { initialize = FALSE; factory = gtk_menu_factory_new (GTK_MENU_FACTORY_MENU_BAR); subfactories[0] = gtk_menu_factory_new (GTK_MENU_FACTORY_MENU_BAR); gtk_menu_factory_add_subfactory (factory, subfactories[0], ""); subfactories[1] = gtk_menu_factory_new (GTK_MENU_FACTORY_MENU); gtk_menu_factory_add_subfactory (factory, subfactories[1], ""); subfactories[2] = gtk_menu_factory_new (GTK_MENU_FACTORY_MENU); gtk_menu_factory_add_subfactory (factory, subfactories[2], ""); subfactories[3] = gtk_menu_factory_new (GTK_MENU_FACTORY_MENU); gtk_menu_factory_add_subfactory (factory, subfactories[3], ""); sprintf (filename, "%s/menurc", gimp_directory ()); parse_gimprc_file (filename); menus_create (menu_items, nmenu_items); } } static void menus_foreach (gpointer key, gpointer value, gpointer user_data) { char accel[64]; int i, j; for (i = j = 0; ((char*) value)[i] != '\0'; i++, j++) { if (((char *) value)[i] == '"' || ((char *) value)[i] == '\\') accel[j++] = '\\'; accel[j] = ((char *) value)[i]; } accel[j] = '\0'; fprintf ((FILE*) user_data, "(menu-path \"%s\" \"%s\")\n", (char*) key, accel); } static gint menus_install_accel (GtkWidget *widget, gchar *signal_name, gchar key, gchar modifiers, gchar *path) { char accel[64]; char *t1, t2[2]; accel[0] = '\0'; if (modifiers & GDK_CONTROL_MASK) strcat (accel, ""); if (modifiers & GDK_SHIFT_MASK) strcat (accel, ""); if (modifiers & GDK_MOD1_MASK) strcat (accel, ""); t2[0] = key; t2[1] = '\0'; strcat (accel, t2); if (entry_ht) { t1 = g_hash_table_lookup (entry_ht, path); g_free (t1); } else entry_ht = g_hash_table_new (g_str_hash, g_str_equal); g_hash_table_insert (entry_ht, path, g_strdup (accel)); return TRUE; } static void menus_remove_accel (GtkWidget *widget, gchar *signal_name, gchar *path) { char *t; if (entry_ht) { t = g_hash_table_lookup (entry_ht, path); g_free (t); g_hash_table_insert (entry_ht, path, g_strdup ("")); } } static void menus_activate_callback (GtkWidget *widget, GtkMenuEntry *entry) { /* These are the functions upon which we won't destroy the tool... "safe", so to say. All the others are expected to alter the image, so the tool must be destroyed */ const GtkMenuCallback ignore[]={ image_posterize_cmd_callback, image_threshold_cmd_callback, image_color_balance_cmd_callback, image_brightness_contrast_cmd_callback, image_hue_saturation_cmd_callback, image_curves_cmd_callback, image_levels_cmd_callback, image_histogram_cmd_callback, tools_select_cmd_callback, about_dialog_cmd_callback, tips_dialog_cmd_callback, file_new_cmd_callback, file_open_cmd_callback, file_save_cmd_callback, file_save_as_cmd_callback, file_pref_cmd_callback, file_close_cmd_callback, file_quit_cmd_callback, view_zoomin_cmd_callback, view_zoomout_cmd_callback, view_zoom_16_1_callback, view_zoom_8_1_callback, view_zoom_4_1_callback, view_zoom_2_1_callback, view_zoom_1_1_callback, view_zoom_1_2_callback, view_zoom_1_4_callback, view_zoom_1_8_callback, view_zoom_1_16_callback, view_window_info_cmd_callback, view_toggle_rulers_cmd_callback, view_toggle_guides_cmd_callback, view_snap_to_guides_cmd_callback, channel_ops_duplicate_cmd_callback, dialogs_lc_cmd_callback, dialogs_brushes_cmd_callback, dialogs_patterns_cmd_callback, dialogs_palette_cmd_callback, dialogs_gradient_editor_cmd_callback, dialogs_lc_cmd_callback, dialogs_indexed_palette_cmd_callback, dialogs_tools_options_cmd_callback, file_load_by_extension_callback, file_save_by_extension_callback }; int i; if (active_tool){ for (i=0; icallback == ignore[i]) return; if (active_tool->gdisp_ptr == NULL) active_tool_control (DESTROY, active_tool->gdisp_ptr); else { GDisplay *gdisp; gdisp = gdisplay_active (); if (gdisp == NULL || ((GDisplay*)active_tool->gdisp_ptr)->gimage == gdisp->gimage) active_tool_control (DESTROY, active_tool->gdisp_ptr); } } }