diff --git a/app/actions/drawable-actions.c b/app/actions/drawable-actions.c index 8a45a99219..5b6cbc737e 100644 --- a/app/actions/drawable-actions.c +++ b/app/actions/drawable-actions.c @@ -53,18 +53,6 @@ static const GimpActionEntry drawable_actions[] = G_CALLBACK (drawable_levels_stretch_cmd_callback), GIMP_HELP_LAYER_WHITE_BALANCE }, - { "drawable-dilate", GIMP_ICON_GEGL, - NC_("drawable-action", "_Dilate"), NULL, - NC_("drawable-action", "Grow lighter areas of the image"), - G_CALLBACK (drawable_dilate_cmd_callback), - GIMP_HELP_LAYER_DILATE }, - - { "drawable-erode", GIMP_ICON_GEGL, - NC_("drawable-action", "E_rode"), NULL, - NC_("drawable-action", "Grow darker areas of the image"), - G_CALLBACK (drawable_erode_cmd_callback), - GIMP_HELP_LAYER_ERODE }, - { "drawable-offset", NULL, NC_("drawable-action", "_Offset..."), "O", NC_("drawable-action", @@ -229,8 +217,6 @@ drawable_actions_update (GimpActionGroup *group, SET_SENSITIVE ("drawable-equalize", writable && !children); SET_SENSITIVE ("drawable-levels-stretch", writable && !children && is_rgb); - SET_SENSITIVE ("drawable-dilate", writable && !children); - SET_SENSITIVE ("drawable-erode", writable && !children); SET_SENSITIVE ("drawable-offset", writable && !children); SET_SENSITIVE ("drawable-visible", drawable); diff --git a/app/actions/drawable-commands.c b/app/actions/drawable-commands.c index 378be6c84e..7553f1cee8 100644 --- a/app/actions/drawable-commands.c +++ b/app/actions/drawable-commands.c @@ -95,70 +95,6 @@ drawable_levels_stretch_cmd_callback (GtkAction *action, gimp_image_flush (image); } -void -drawable_dilate_cmd_callback (GtkAction *action, - gpointer data) -{ - GimpImage *image; - GimpDrawable *drawable; - GimpDisplay *display; - GeglNode *node; - return_if_no_drawable (image, drawable, data); - return_if_no_display (display, data); - - node = gegl_node_new_child (NULL, - "operation", "gegl:value-propagate", - "mode", 0, /* GEGL_VALUE_PROPAGATE_MODE_WHITE */ - "lower-threshold", 0.0, - "upper-threshold", 1.0, - "rate", 1.0, - "top", TRUE, - "left", TRUE, - "right", TRUE, - "bottom", TRUE, - "value", TRUE, - "alpha", FALSE, - NULL); - - gimp_drawable_apply_operation (drawable, GIMP_PROGRESS (display), - _("Dilate"), node); - g_object_unref (node); - - gimp_image_flush (image); -} - -void -drawable_erode_cmd_callback (GtkAction *action, - gpointer data) -{ - GimpImage *image; - GimpDrawable *drawable; - GimpDisplay *display; - GeglNode *node; - return_if_no_drawable (image, drawable, data); - return_if_no_display (display, data); - - node = gegl_node_new_child (NULL, - "operation", "gegl:value-propagate", - "mode", 1, /* GEGL_VALUE_PROPAGATE_MODE_BLACK */ - "lower-threshold", 0.0, - "upper-threshold", 1.0, - "rate", 1.0, - "top", TRUE, - "left", TRUE, - "right", TRUE, - "bottom", TRUE, - "value", TRUE, - "alpha", FALSE, - NULL); - - gimp_drawable_apply_operation (drawable, GIMP_PROGRESS (display), - _("Erode"), node); - g_object_unref (node); - - gimp_image_flush (image); -} - void drawable_offset_cmd_callback (GtkAction *action, gpointer data) diff --git a/app/actions/drawable-commands.h b/app/actions/drawable-commands.h index ae437e1310..4a2ec5b808 100644 --- a/app/actions/drawable-commands.h +++ b/app/actions/drawable-commands.h @@ -23,10 +23,6 @@ void drawable_equalize_cmd_callback (GtkAction *action, gpointer data); void drawable_levels_stretch_cmd_callback (GtkAction *action, gpointer data); -void drawable_dilate_cmd_callback (GtkAction *action, - gpointer data); -void drawable_erode_cmd_callback (GtkAction *action, - gpointer data); void drawable_offset_cmd_callback (GtkAction *action, gpointer data); diff --git a/app/actions/filters-actions.c b/app/actions/filters-actions.c index f895e20843..cf2a893d67 100644 --- a/app/actions/filters-actions.c +++ b/app/actions/filters-actions.c @@ -43,8 +43,11 @@ /* local function prototypes */ -static void filters_actions_history_changed (Gimp *gimp, - GimpActionGroup *group); +static void filters_actions_set_tooltips (GimpActionGroup *group, + const GimpStringActionEntry *entries, + gint n_entries); +static void filters_actions_history_changed (Gimp *gimp, + GimpActionGroup *group); /* private variables */ @@ -128,6 +131,41 @@ static const GimpStringActionEntry filters_actions[] = GIMP_HELP_FILTER_STRETCH_CONTRAST_HSV } }; +static const GimpStringActionEntry filters_settings_actions[] = +{ + { "filters-dilate", GIMP_ICON_GEGL, + NC_("filters-action", "_Dilate"), NULL, + NC_("drawable-action", "Grow lighter areas of the image"), + "gegl:value-propagate\n" + "(mode white)" + "(lower-threshold 0.000000)" + "(upper-threshold 1.000000)" + "(rate 1.000000)" + "(top yes)" + "(left yes)" + "(right yes)" + "(bottom yes)" + "(value yes)" + "(alpha no)", + GIMP_HELP_FILTER_DILATE }, + + { "filters-erode", GIMP_ICON_GEGL, + NC_("filters-action", "_Erode"), NULL, + NC_("drawable-action", "Grow darker areas of the image"), + "gegl:value-propagate\n" + "(mode black)" + "(lower-threshold 0.000000)" + "(upper-threshold 1.000000)" + "(rate 1.000000)" + "(top yes)" + "(left yes)" + "(right yes)" + "(bottom yes)" + "(value yes)" + "(alpha no)", + GIMP_HELP_FILTER_ERODE } +}; + static const GimpStringActionEntry filters_interactive_actions[] = { { "filters-alien-map", GIMP_ICON_GEGL, @@ -643,41 +681,28 @@ filters_actions_setup (GimpActionGroup *group) filters_actions, G_N_ELEMENTS (filters_actions), G_CALLBACK (filters_apply_cmd_callback)); + filters_actions_set_tooltips (group, filters_actions, + G_N_ELEMENTS (filters_actions)); + + gimp_action_group_add_string_actions (group, "filters-action", + filters_settings_actions, + G_N_ELEMENTS (filters_settings_actions), + G_CALLBACK (filters_apply_cmd_callback)); + filters_actions_set_tooltips (group, filters_settings_actions, + G_N_ELEMENTS (filters_settings_actions)); gimp_action_group_add_string_actions (group, "filters-action", filters_interactive_actions, G_N_ELEMENTS (filters_interactive_actions), G_CALLBACK (filters_apply_interactive_cmd_callback)); + filters_actions_set_tooltips (group, filters_interactive_actions, + G_N_ELEMENTS (filters_interactive_actions)); gimp_action_group_add_enum_actions (group, "filters-action", filters_repeat_actions, G_N_ELEMENTS (filters_repeat_actions), G_CALLBACK (filters_repeat_cmd_callback)); - for (i = 0; i < G_N_ELEMENTS (filters_actions); i++) - { - const GimpStringActionEntry *entry = &filters_actions[i]; - const gchar *description; - - description = gegl_operation_get_key (entry->value, "description"); - - if (description) - gimp_action_group_set_action_tooltip (group, entry->name, - description); - } - - for (i = 0; i < G_N_ELEMENTS (filters_interactive_actions); i++) - { - const GimpStringActionEntry *entry = &filters_interactive_actions[i]; - const gchar *description; - - description = gegl_operation_get_key (entry->value, "description"); - - if (description) - gimp_action_group_set_action_tooltip (group, entry->name, - description); - } - n_entries = gimp_filter_history_size (group->gimp); entries = g_new0 (GimpProcedureActionEntry, n_entries); @@ -771,6 +796,7 @@ filters_actions_update (GimpActionGroup *group, SET_SENSITIVE ("filters-desaturate", writable && !gray); SET_SENSITIVE ("filters-difference-of-gaussians", writable); SET_SENSITIVE ("filters-diffraction-patterns", writable); + SET_SENSITIVE ("filters-dilate", writable); SET_SENSITIVE ("filters-displace", writable); SET_SENSITIVE ("filters-distance-map", writable); SET_SENSITIVE ("filters-dropshadow", writable && alpha); @@ -780,6 +806,7 @@ filters_actions_update (GimpActionGroup *group, SET_SENSITIVE ("filters-edge-sobel", writable); SET_SENSITIVE ("filters-emboss", writable); SET_SENSITIVE ("filters-engrave", writable); + SET_SENSITIVE ("filters-erode", writable); SET_SENSITIVE ("filters-exposure", writable); SET_SENSITIVE ("filters-fattal-2002", writable); SET_SENSITIVE ("filters-fractal-trace", writable); @@ -882,7 +909,27 @@ filters_actions_update (GimpActionGroup *group, g_free (name); } - } + } +} + +static void +filters_actions_set_tooltips (GimpActionGroup *group, + const GimpStringActionEntry *entries, + gint n_entries) +{ + gint i; + + for (i = 0; i < n_entries; i++) + { + const GimpStringActionEntry *entry = entries + i; + const gchar *description; + + description = gegl_operation_get_key (entry->value, "description"); + + if (description) + gimp_action_group_set_action_tooltip (group, entry->name, + description); + } } static GimpActionGroup * diff --git a/app/actions/filters-commands.c b/app/actions/filters-commands.c index 4d1de8773b..9f3296b01d 100644 --- a/app/actions/filters-commands.c +++ b/app/actions/filters-commands.c @@ -17,17 +17,23 @@ #include "config.h" +#include + #include #include #include "libgimpbase/gimpbase.h" +#include "libgimpconfig/gimpconfig.h" #include "libgimpwidgets/gimpwidgets.h" #include "actions-types.h" +#include "operations/gimp-operation-config.h" + #include "core/gimp.h" #include "core/gimp-filter-history.h" #include "core/gimpprogress.h" +#include "core/gimpsettings.h" #include "actions.h" #include "filters-commands.h" @@ -35,19 +41,39 @@ #include "procedure-commands.h" +/* local function prototypes */ + +static gchar * filters_parse_operation (Gimp *gimp, + const gchar *operation_str, + const gchar *icon_name, + GimpObject **settings); + +static void filters_run_procedure (Gimp *gimp, + GimpDisplay *display, + GimpProcedure *procedure, + GimpRunMode run_mode); + + /* public functions */ void filters_apply_cmd_callback (GtkAction *action, - const gchar *operation, + const gchar *operation_str, gpointer data) { GimpDisplay *display; + gchar *operation; + GimpObject *settings; GimpProcedure *procedure; return_if_no_display (display, data); + operation = filters_parse_operation (action_data_get_gimp (data), + operation_str, + gtk_action_get_icon_name (action), + &settings); + procedure = gimp_gegl_procedure_new (action_data_get_gimp (data), - GIMP_RUN_NONINTERACTIVE, + GIMP_RUN_NONINTERACTIVE, settings, operation, gtk_action_get_name (action), gtk_action_get_label (action), @@ -56,6 +82,11 @@ filters_apply_cmd_callback (GtkAction *action, g_object_get_qdata (G_OBJECT (action), GIMP_HELP_ID)); + g_free (operation); + + if (settings) + g_object_unref (settings); + gimp_filter_history_add (action_data_get_gimp (data), procedure); filters_history_cmd_callback (NULL, procedure, data); @@ -72,7 +103,7 @@ filters_apply_interactive_cmd_callback (GtkAction *action, return_if_no_display (display, data); procedure = gimp_gegl_procedure_new (action_data_get_gimp (data), - GIMP_RUN_INTERACTIVE, + GIMP_RUN_INTERACTIVE, NULL, operation, gtk_action_get_name (action), gtk_action_get_label (action), @@ -94,48 +125,14 @@ filters_repeat_cmd_callback (GtkAction *action, { Gimp *gimp; GimpDisplay *display; - GimpRunMode run_mode; GimpProcedure *procedure; return_if_no_gimp (gimp, data); return_if_no_display (display, data); - run_mode = (GimpRunMode) value; - procedure = gimp_filter_history_nth (gimp, 0); if (procedure) - { - GimpValueArray *args; - gboolean success = FALSE; - - args = procedure_commands_get_display_args (procedure, display, NULL); - - if (args) - { - if (GIMP_IS_GEGL_PROCEDURE (procedure) && - GIMP_GEGL_PROCEDURE (procedure)->default_run_mode == - GIMP_RUN_NONINTERACTIVE) - { - success = - procedure_commands_run_procedure (procedure, gimp, - GIMP_PROGRESS (display), - args); - } - else - { - success = - procedure_commands_run_procedure_async (procedure, gimp, - GIMP_PROGRESS (display), - run_mode, args, - display); - } - - if (success) - gimp_filter_history_add (gimp, procedure); - - gimp_value_array_unref (args); - } - } + filters_run_procedure (gimp, display, procedure, (GimpRunMode) value); } void @@ -143,21 +140,91 @@ filters_history_cmd_callback (GtkAction *action, GimpProcedure *procedure, gpointer data) { - Gimp *gimp; - GimpDisplay *display; - GimpValueArray *args; + Gimp *gimp; + GimpDisplay *display; return_if_no_gimp (gimp, data); return_if_no_display (display, data); - args = procedure_commands_get_display_args (procedure, display, NULL); + filters_run_procedure (gimp, display, procedure, GIMP_RUN_INTERACTIVE); +} + + +/* private functions */ + +static gchar * +filters_parse_operation (Gimp *gimp, + const gchar *operation_str, + const gchar *icon_name, + GimpObject **settings) +{ + const gchar *newline = strchr (operation_str, '\n'); + + *settings = NULL; + + if (newline) + { + gchar *operation; + const gchar *serialized; + + operation = g_strndup (operation_str, newline - operation_str); + serialized = newline + 1; + + if (*serialized) + { + GError *error = NULL; + + *settings = + g_object_new (gimp_operation_config_get_type (gimp, operation, + icon_name, + GIMP_TYPE_SETTINGS), + NULL); + + if (! gimp_config_deserialize_string (GIMP_CONFIG (*settings), + serialized, -1, NULL, + &error)) + { + g_warning ("filters_parse_operation: deserializing hardcoded " + "operation settings failed: %s", + error->message); + g_clear_error (&error); + + g_object_unref (*settings); + *settings = NULL; + } + } + + return operation; + } + + return g_strdup (operation_str); +} + +static void +filters_run_procedure (Gimp *gimp, + GimpDisplay *display, + GimpProcedure *procedure, + GimpRunMode run_mode) +{ + GimpObject *settings = NULL; + GimpValueArray *args; + + if (GIMP_IS_GEGL_PROCEDURE (procedure)) + { + GimpGeglProcedure *gegl_procedure = GIMP_GEGL_PROCEDURE (procedure); + + if (gegl_procedure->default_run_mode == GIMP_RUN_NONINTERACTIVE) + run_mode = GIMP_RUN_NONINTERACTIVE; + + settings = gegl_procedure->default_settings; + } + + args = procedure_commands_get_display_args (procedure, display, settings); if (args) { gboolean success = FALSE; - if (GIMP_IS_GEGL_PROCEDURE (procedure) && - GIMP_GEGL_PROCEDURE (procedure)->default_run_mode == - GIMP_RUN_NONINTERACTIVE) + if (run_mode == GIMP_RUN_NONINTERACTIVE) { success = procedure_commands_run_procedure (procedure, gimp, @@ -169,7 +236,7 @@ filters_history_cmd_callback (GtkAction *action, success = procedure_commands_run_procedure_async (procedure, gimp, GIMP_PROGRESS (display), - GIMP_RUN_INTERACTIVE, args, + run_mode, args, display); } diff --git a/app/actions/gimpgeglprocedure.c b/app/actions/gimpgeglprocedure.c index 28d6e4eae8..6850f8ac00 100644 --- a/app/actions/gimpgeglprocedure.c +++ b/app/actions/gimpgeglprocedure.c @@ -119,6 +119,9 @@ gimp_gegl_procedure_finalize (GObject *object) { GimpGeglProcedure *proc = GIMP_GEGL_PROCEDURE (object); + if (proc->default_settings) + g_object_unref (proc->default_settings); + g_free (proc->menu_label); g_free (proc->label); g_free (proc->help_id); @@ -374,6 +377,7 @@ gimp_gegl_procedure_execute_async (GimpProcedure *procedure, GimpProcedure * gimp_gegl_procedure_new (Gimp *gimp, GimpRunMode default_run_mode, + GimpObject *default_settings, const gchar *operation, const gchar *name, const gchar *menu_label, @@ -381,8 +385,9 @@ gimp_gegl_procedure_new (Gimp *gimp, const gchar *icon_name, const gchar *help_id) { - GimpProcedure *procedure; - GType config_type; + GimpProcedure *procedure; + GimpGeglProcedure *gegl_procedure; + GType config_type; g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL); g_return_val_if_fail (operation != NULL, NULL); @@ -394,9 +399,14 @@ gimp_gegl_procedure_new (Gimp *gimp, procedure = g_object_new (GIMP_TYPE_GEGL_PROCEDURE, NULL); - GIMP_GEGL_PROCEDURE (procedure)->default_run_mode = default_run_mode; - GIMP_GEGL_PROCEDURE (procedure)->menu_label = g_strdup (menu_label); - GIMP_GEGL_PROCEDURE (procedure)->help_id = g_strdup (help_id); + gegl_procedure = GIMP_GEGL_PROCEDURE (procedure); + + gegl_procedure->default_run_mode = default_run_mode; + gegl_procedure->menu_label = g_strdup (menu_label); + gegl_procedure->help_id = g_strdup (help_id); + + if (default_settings) + gegl_procedure->default_settings = g_object_ref (default_settings); gimp_object_set_name (GIMP_OBJECT (procedure), name); gimp_viewable_set_icon_name (GIMP_VIEWABLE (procedure), icon_name); diff --git a/app/actions/gimpgeglprocedure.h b/app/actions/gimpgeglprocedure.h index 62371a7c1f..4f94a1e6c5 100644 --- a/app/actions/gimpgeglprocedure.h +++ b/app/actions/gimpgeglprocedure.h @@ -41,6 +41,7 @@ struct _GimpGeglProcedure GimpProcedure parent_instance; GimpRunMode default_run_mode; + GimpObject *default_settings; gchar *menu_label; gchar *label; @@ -57,6 +58,7 @@ GType gimp_gegl_procedure_get_type (void) G_GNUC_CONST; GimpProcedure * gimp_gegl_procedure_new (Gimp *gimp, GimpRunMode default_run_mode, + GimpObject *default_settings, const gchar *operation, const gchar *name, const gchar *menu_label, diff --git a/app/core/gimp-filter-history.c b/app/core/gimp-filter-history.c index 140b49d068..f5fe321bef 100644 --- a/app/core/gimp-filter-history.c +++ b/app/core/gimp-filter-history.c @@ -19,6 +19,8 @@ #include "config.h" +#include + #include #include @@ -34,6 +36,14 @@ #include "pdb/gimpprocedure.h" +/* local function prototypes */ + +static gint gimp_filter_history_compare (GimpProcedure *proc1, + GimpProcedure *proc2); + + +/* public functions */ + gint gimp_filter_history_size (Gimp *gimp) { @@ -70,14 +80,14 @@ gimp_filter_history_add (Gimp *gimp, /* return early if the procedure is already at the top */ if (gimp->filter_history && - gimp_procedure_name_compare (gimp->filter_history->data, procedure) == 0) + gimp_filter_history_compare (gimp->filter_history->data, procedure) == 0) return; /* ref new first then unref old, they might be the same */ g_object_ref (procedure); link = g_list_find_custom (gimp->filter_history, procedure, - (GCompareFunc) gimp_procedure_name_compare); + (GCompareFunc) gimp_filter_history_compare); if (link) { @@ -108,7 +118,7 @@ gimp_filter_history_remove (Gimp *gimp, g_return_if_fail (GIMP_IS_PROCEDURE (procedure)); link = g_list_find_custom (gimp->filter_history, procedure, - (GCompareFunc) gimp_procedure_name_compare); + (GCompareFunc) gimp_filter_history_compare); if (link) { @@ -132,3 +142,19 @@ gimp_filter_history_clear (Gimp *gimp) gimp_filter_history_changed (gimp); } } + + +/* private functions */ + +static gint +gimp_filter_history_compare (GimpProcedure *proc1, + GimpProcedure *proc2) +{ + /* the procedures can have the same name, but could still be two + * different filters using the same operation, so also compare + * their menu labels + */ + return (gimp_procedure_name_compare (proc1, proc2) || + strcmp (gimp_procedure_get_menu_label (proc1), + gimp_procedure_get_menu_label (proc2))); +} diff --git a/app/widgets/gimphelp-ids.h b/app/widgets/gimphelp-ids.h index c9d9a11ecc..c5a318f831 100644 --- a/app/widgets/gimphelp-ids.h +++ b/app/widgets/gimphelp-ids.h @@ -186,8 +186,6 @@ #define GIMP_HELP_LAYER_LOWER_TO_BOTTOM "gimp-layer-lower-to-bottom" #define GIMP_HELP_LAYER_WHITE_BALANCE "gimp-layer-white-balance" #define GIMP_HELP_LAYER_EQUALIZE "gimp-layer-equalize" -#define GIMP_HELP_LAYER_DILATE "gimp-layer-dilate" -#define GIMP_HELP_LAYER_ERODE "gimp-layer-erode" #define GIMP_HELP_LAYER_VISIBLE "gimp-layer-visible" #define GIMP_HELP_LAYER_LINKED "gimp-layer-linked" #define GIMP_HELP_LAYER_COLOR_TAG "gimp-layer-color-tag" @@ -352,6 +350,7 @@ #define GIMP_HELP_FILTER_DESATURATE "gimp-filter-desaturate" #define GIMP_HELP_FILTER_DIFFERENCE_OF_GAUSSIANS "gimp-filter-difference-of-gaussians" #define GIMP_HELP_FILTER_DIFFRACTION_PATTERNS "gimp-filter-diffraction-patterns" +#define GIMP_HELP_FILTER_DILATE "gimp-filter-dilate" #define GIMP_HELP_FILTER_DISPLACE "gimp-filter-displace" #define GIMP_HELP_FILTER_DISTANCE_MAP "gimp-filter-distance-map" #define GIMP_HELP_FILTER_DITHER "gimp-filter-dither" @@ -362,6 +361,7 @@ #define GIMP_HELP_FILTER_EDGE_SOBEL "gimp-filter-edge-sobel" #define GIMP_HELP_FILTER_EMBOSS "gimp-filter-emboss" #define GIMP_HELP_FILTER_ENGRAVE "gimp-filter-engrave" +#define GIMP_HELP_FILTER_ERODE "gimp-filter-erode" #define GIMP_HELP_FILTER_EXPOSURE "gimp-filter-exposure" #define GIMP_HELP_FILTER_FATTAL_2002 "gimp-filter-fattal-2002" #define GIMP_HELP_FILTER_FRACTAL_TRACE "gimp-filter-fractal-trace" diff --git a/menus/image-menu.xml.in b/menus/image-menu.xml.in index 160f7dd715..d921ff493d 100644 --- a/menus/image-menu.xml.in +++ b/menus/image-menu.xml.in @@ -761,8 +761,8 @@ - - + +