From 789d82355cdcda8fe02fcd3ecc45d0577b304237 Mon Sep 17 00:00:00 2001 From: Jehan Date: Wed, 7 Feb 2024 17:13:16 +0100 Subject: [PATCH] app, pdb: "Add Layer Mask" dialog asks whether to edit mask immediately. While there are cases when you want to edit the mask straight away (this is often the case when starting with a white or black mask), in many other cases, the mask may be already as you want it per its initialization (e.g. when initializing with a channel, selection, the alpha channel, etc.). Until now, the Add Mask dialog was always switching to the "Edit Layer Mask" mode by default, which forced an additional unneeded click each time you created a mask (and were in a case where you initialize the mask as you want it directly). Now adding "Edit mask immediately" feature in the "Add Layer Mask dialog": * It's checked by default to keep historical behavior. * As most other dialogs, the last value is remembered, allowing people with repetitive workflow not to have to repeatedly set the settings each and every time. * This default is also visible and settable in Preferences > Interface > Dialog Defaults. --- app/actions/layers-commands.c | 14 ++++++++++---- app/config/gimpdialogconfig.c | 14 ++++++++++++++ app/config/gimpdialogconfig.h | 1 + app/config/gimprc-blurbs.h | 3 +++ app/core/gimpimage-undo-push.c | 2 ++ app/core/gimplayer.c | 7 ++++--- app/core/gimplayer.h | 1 + app/core/gimplayermaskundo.c | 18 ++++++++++++++++-- app/core/gimplayermaskundo.h | 1 + app/dialogs/layer-add-mask-dialog.c | 20 +++++++++++++++++++- app/dialogs/layer-add-mask-dialog.h | 2 ++ app/dialogs/preferences-dialog.c | 3 +++ app/pdb/layer-cmds.c | 2 +- app/tests/test-xcf.c | 5 +++-- app/xcf/xcf-load.c | 3 +-- pdb/groups/layer.pdb | 2 +- 16 files changed, 82 insertions(+), 16 deletions(-) diff --git a/app/actions/layers-commands.c b/app/actions/layers-commands.c index 390caa31a4..01c98ec26e 100644 --- a/app/actions/layers-commands.c +++ b/app/actions/layers-commands.c @@ -150,6 +150,7 @@ static void layers_add_mask_callback (GtkWidget *dialog, GimpAddMaskType add_mask_type, GimpChannel *channel, gboolean invert, + gboolean edit_mask, gpointer user_data); static void layers_scale_callback (GtkWidget *dialog, GimpViewable *viewable, @@ -1568,6 +1569,7 @@ layers_mask_add_cmd_callback (GimpAction *action, widget, config->layer_add_mask_type, config->layer_add_mask_invert, + config->layer_add_mask_edit_mask, layers_add_mask_callback, NULL); @@ -1643,7 +1645,9 @@ layers_mask_add_last_vals_cmd_callback (GimpAction *action, if (config->layer_add_mask_invert) gimp_channel_invert (GIMP_CHANNEL (mask), FALSE); - gimp_layer_add_mask (iter->data, mask, TRUE, NULL); + gimp_layer_add_mask (iter->data, mask, + config->layer_add_mask_edit_mask, + TRUE, NULL); } gimp_image_undo_group_end (image); @@ -2591,6 +2595,7 @@ layers_add_mask_callback (GtkWidget *dialog, GimpAddMaskType add_mask_type, GimpChannel *channel, gboolean invert, + gboolean edit_mask, gpointer user_data) { GimpImage *image = gimp_item_get_image (GIMP_ITEM (layers->data)); @@ -2600,8 +2605,9 @@ layers_add_mask_callback (GtkWidget *dialog, GError *error = NULL; g_object_set (config, - "layer-add-mask-type", add_mask_type, - "layer-add-mask-invert", invert, + "layer-add-mask-type", add_mask_type, + "layer-add-mask-invert", invert, + "layer-add-mask-edit-mask", edit_mask, NULL); gimp_image_undo_group_start (image, @@ -2617,7 +2623,7 @@ layers_add_mask_callback (GtkWidget *dialog, if (config->layer_add_mask_invert) gimp_channel_invert (GIMP_CHANNEL (mask), FALSE); - if (! gimp_layer_add_mask (iter->data, mask, TRUE, &error)) + if (! gimp_layer_add_mask (iter->data, mask, edit_mask, TRUE, &error)) { gimp_message_literal (image->gimp, G_OBJECT (dialog), GIMP_MESSAGE_WARNING, diff --git a/app/config/gimpdialogconfig.c b/app/config/gimpdialogconfig.c index aa29c744ef..ce0dad833f 100644 --- a/app/config/gimpdialogconfig.c +++ b/app/config/gimpdialogconfig.c @@ -81,6 +81,7 @@ enum PROP_LAYER_ADD_MASK_TYPE, PROP_LAYER_ADD_MASK_INVERT, + PROP_LAYER_ADD_MASK_EDIT_MASK, PROP_LAYER_MERGE_TYPE, PROP_LAYER_MERGE_ACTIVE_GROUP_ONLY, @@ -389,6 +390,13 @@ gimp_dialog_config_class_init (GimpDialogConfigClass *klass) FALSE, GIMP_PARAM_STATIC_STRINGS); + GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_LAYER_ADD_MASK_EDIT_MASK, + "layer-add-mask-edit-mask", + "Default layer mask: edit mask immediately", + LAYER_ADD_MASK_EDIT_MASK, + TRUE, + GIMP_PARAM_STATIC_STRINGS); + GIMP_CONFIG_PROP_ENUM (object_class, PROP_LAYER_MERGE_TYPE, "layer-merge-type", "Default layer merge type", @@ -716,6 +724,9 @@ gimp_dialog_config_set_property (GObject *object, case PROP_LAYER_ADD_MASK_INVERT: config->layer_add_mask_invert = g_value_get_boolean (value); break; + case PROP_LAYER_ADD_MASK_EDIT_MASK: + config->layer_add_mask_edit_mask = g_value_get_boolean (value); + break; case PROP_LAYER_MERGE_TYPE: config->layer_merge_type = g_value_get_enum (value); @@ -908,6 +919,9 @@ gimp_dialog_config_get_property (GObject *object, case PROP_LAYER_ADD_MASK_INVERT: g_value_set_boolean (value, config->layer_add_mask_invert); break; + case PROP_LAYER_ADD_MASK_EDIT_MASK: + g_value_set_boolean (value, config->layer_add_mask_edit_mask); + break; case PROP_LAYER_MERGE_TYPE: g_value_set_enum (value, config->layer_merge_type); diff --git a/app/config/gimpdialogconfig.h b/app/config/gimpdialogconfig.h index 3e20aa6e18..3c69832b94 100644 --- a/app/config/gimpdialogconfig.h +++ b/app/config/gimpdialogconfig.h @@ -78,6 +78,7 @@ struct _GimpDialogConfig GimpAddMaskType layer_add_mask_type; gboolean layer_add_mask_invert; + gboolean layer_add_mask_edit_mask; GimpMergeType layer_merge_type; gboolean layer_merge_active_group_only; diff --git a/app/config/gimprc-blurbs.h b/app/config/gimprc-blurbs.h index ca5fabe0f5..096c4cc679 100644 --- a/app/config/gimprc-blurbs.h +++ b/app/config/gimprc-blurbs.h @@ -659,6 +659,9 @@ _("Sets the default mask for the 'Add Layer Mask' dialog.") #define LAYER_ADD_MASK_INVERT_BLURB \ _("Sets the default 'invert mask' state for the 'Add Layer Mask' dialog.") +#define LAYER_ADD_MASK_EDIT_MASK \ +_("Sets the default 'edit mask' state for the 'Add Layer Mask' dialog.") + #define LAYER_MERGE_TYPE_BLURB \ _("Sets the default merge type for the 'Merge Visible Layers' dialog.") diff --git a/app/core/gimpimage-undo-push.c b/app/core/gimpimage-undo-push.c index 035485b82e..df0345a962 100644 --- a/app/core/gimpimage-undo-push.c +++ b/app/core/gimpimage-undo-push.c @@ -960,6 +960,7 @@ gimp_image_undo_push_layer_mask_add (GimpImage *image, GIMP_DIRTY_IMAGE_STRUCTURE, "item", layer, "layer-mask", mask, + "edit-mask", FALSE, NULL); } @@ -982,6 +983,7 @@ gimp_image_undo_push_layer_mask_remove (GimpImage *image, GIMP_DIRTY_IMAGE_STRUCTURE, "item", layer, "layer-mask", mask, + "edit-mask", gimp_layer_get_edit_mask (layer), NULL); } diff --git a/app/core/gimplayer.c b/app/core/gimplayer.c index 678c34aaf9..d59cfc416c 100644 --- a/app/core/gimplayer.c +++ b/app/core/gimplayer.c @@ -991,10 +991,10 @@ gimp_layer_duplicate (GimpItem *item, mask = gimp_item_duplicate (GIMP_ITEM (layer->mask), G_TYPE_FROM_INSTANCE (layer->mask)); - gimp_layer_add_mask (new_layer, GIMP_LAYER_MASK (mask), FALSE, NULL); + gimp_layer_add_mask (new_layer, GIMP_LAYER_MASK (mask), + layer->edit_mask, FALSE, NULL); new_layer->apply_mask = layer->apply_mask; - new_layer->edit_mask = layer->edit_mask; new_layer->show_mask = layer->show_mask; } } @@ -1917,6 +1917,7 @@ gimp_layer_get_mask (GimpLayer *layer) GimpLayerMask * gimp_layer_add_mask (GimpLayer *layer, GimpLayerMask *mask, + gboolean edit_mask, gboolean push_undo, GError **error) { @@ -1958,7 +1959,7 @@ gimp_layer_add_mask (GimpLayer *layer, layer->mask = g_object_ref_sink (mask); layer->apply_mask = TRUE; - layer->edit_mask = TRUE; + layer->edit_mask = edit_mask; layer->show_mask = FALSE; gimp_layer_mask_set_layer (mask, layer); diff --git a/app/core/gimplayer.h b/app/core/gimplayer.h index 790814e41a..dbe79aa9ce 100644 --- a/app/core/gimplayer.h +++ b/app/core/gimplayer.h @@ -159,6 +159,7 @@ GimpLayerMask * gimp_layer_create_mask (GimpLayer *layer, GimpChannel *channel); GimpLayerMask * gimp_layer_add_mask (GimpLayer *layer, GimpLayerMask *mask, + gboolean edit_mask, gboolean push_undo, GError **error); void gimp_layer_apply_mask (GimpLayer *layer, diff --git a/app/core/gimplayermaskundo.c b/app/core/gimplayermaskundo.c index 96527a12f5..b6aeb200a2 100644 --- a/app/core/gimplayermaskundo.c +++ b/app/core/gimplayermaskundo.c @@ -33,7 +33,8 @@ enum { PROP_0, - PROP_LAYER_MASK + PROP_LAYER_MASK, + PROP_EDIT_MASK }; @@ -83,6 +84,11 @@ gimp_layer_mask_undo_class_init (GimpLayerMaskUndoClass *klass) GIMP_TYPE_LAYER_MASK, GIMP_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + g_object_class_install_property (object_class, PROP_EDIT_MASK, + g_param_spec_boolean ("edit-mask", NULL, NULL, + FALSE, + GIMP_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY)); } static void @@ -114,6 +120,9 @@ gimp_layer_mask_undo_set_property (GObject *object, case PROP_LAYER_MASK: layer_mask_undo->layer_mask = g_value_dup_object (value); break; + case PROP_EDIT_MASK: + layer_mask_undo->edit_mask = g_value_get_boolean (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); @@ -134,6 +143,9 @@ gimp_layer_mask_undo_get_property (GObject *object, case PROP_LAYER_MASK: g_value_set_object (value, layer_mask_undo->layer_mask); break; + case PROP_EDIT_MASK: + g_value_set_boolean (value, layer_mask_undo->edit_mask); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); @@ -175,13 +187,15 @@ gimp_layer_mask_undo_pop (GimpUndo *undo, { /* remove layer mask */ + layer_mask_undo->edit_mask = gimp_layer_get_edit_mask (layer); gimp_layer_apply_mask (layer, GIMP_MASK_DISCARD, FALSE); } else { /* restore layer mask */ - gimp_layer_add_mask (layer, layer_mask_undo->layer_mask, FALSE, NULL); + gimp_layer_add_mask (layer, layer_mask_undo->layer_mask, + layer_mask_undo->edit_mask, FALSE, NULL); } } diff --git a/app/core/gimplayermaskundo.h b/app/core/gimplayermaskundo.h index cb9e838675..cd1edf08ad 100644 --- a/app/core/gimplayermaskundo.h +++ b/app/core/gimplayermaskundo.h @@ -36,6 +36,7 @@ struct _GimpLayerMaskUndo GimpItemUndo parent_instance; GimpLayerMask *layer_mask; + gboolean edit_mask; }; struct _GimpLayerMaskUndoClass diff --git a/app/dialogs/layer-add-mask-dialog.c b/app/dialogs/layer-add-mask-dialog.c index 6c02dcfea9..1556fc8d4d 100644 --- a/app/dialogs/layer-add-mask-dialog.c +++ b/app/dialogs/layer-add-mask-dialog.c @@ -50,6 +50,7 @@ struct _LayerAddMaskDialog GimpAddMaskType add_mask_type; GimpChannel *channel; gboolean invert; + gboolean edit_mask; GimpAddMaskCallback callback; gpointer user_data; }; @@ -73,12 +74,14 @@ layer_add_mask_dialog_new (GList *layers, GtkWidget *parent, GimpAddMaskType add_mask_type, gboolean invert, + gboolean edit_mask, GimpAddMaskCallback callback, gpointer user_data) { LayerAddMaskDialog *private; GtkWidget *dialog; GtkWidget *vbox; + GtkWidget *hbox; GtkWidget *frame; GtkWidget *combo; GtkWidget *button; @@ -98,6 +101,7 @@ layer_add_mask_dialog_new (GList *layers, private->layers = layers; private->add_mask_type = add_mask_type; private->invert = invert; + private->edit_mask = edit_mask; private->callback = callback; private->user_data = user_data; @@ -180,15 +184,28 @@ layer_add_mask_dialog_new (GList *layers, gimp_container_view_set_1_selected (GIMP_CONTAINER_VIEW (combo), GIMP_VIEWABLE (channel)); + hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 1); + gtk_box_pack_end (GTK_BOX (vbox), hbox, FALSE, FALSE, 0); + gtk_widget_show (hbox); + button = gtk_check_button_new_with_mnemonic (_("In_vert mask")); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), private->invert); - gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0); gtk_widget_show (button); g_signal_connect (button, "toggled", G_CALLBACK (gimp_toggle_button_update), &private->invert); + button = gtk_check_button_new_with_mnemonic (_("_Edit mask immediately")); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), private->edit_mask); + gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0); + gtk_widget_show (button); + + g_signal_connect (button, "toggled", + G_CALLBACK (gimp_toggle_button_update), + &private->edit_mask); + return dialog; } @@ -224,6 +241,7 @@ layer_add_mask_dialog_response (GtkWidget *dialog, private->add_mask_type, private->channel, private->invert, + private->edit_mask, private->user_data); } else diff --git a/app/dialogs/layer-add-mask-dialog.h b/app/dialogs/layer-add-mask-dialog.h index db8f0c2abe..a34be60f34 100644 --- a/app/dialogs/layer-add-mask-dialog.h +++ b/app/dialogs/layer-add-mask-dialog.h @@ -23,6 +23,7 @@ typedef void (* GimpAddMaskCallback) (GtkWidget *dialog, GimpAddMaskType add_mask_type, GimpChannel *channel, gboolean invert, + gboolean edit_mask, gpointer user_data); @@ -31,5 +32,6 @@ GtkWidget * layer_add_mask_dialog_new (GList *layers, GtkWidget *parent, GimpAddMaskType add_mask_type, gboolean invert, + gboolean edit_mask, GimpAddMaskCallback callback, gpointer user_data); diff --git a/app/dialogs/preferences-dialog.c b/app/dialogs/preferences-dialog.c index c46a03d090..854295209f 100644 --- a/app/dialogs/preferences-dialog.c +++ b/app/dialogs/preferences-dialog.c @@ -2476,6 +2476,9 @@ prefs_dialog_new (Gimp *gimp, prefs_check_button_add (object, "layer-add-mask-invert", _("Invert mask"), GTK_BOX (vbox2)); + prefs_check_button_add (object, "layer-add-mask-edit-mask", + _("Edit mask immediately"), + GTK_BOX (vbox2)); /* Merge Layers Dialog */ vbox2 = prefs_frame_new (_("Merge Layers Dialog"), diff --git a/app/pdb/layer-cmds.c b/app/pdb/layer-cmds.c index cd65434e27..9e6a2dde57 100644 --- a/app/pdb/layer-cmds.c +++ b/app/pdb/layer-cmds.c @@ -622,7 +622,7 @@ layer_add_mask_invoker (GimpProcedure *procedure, if (gimp_pdb_item_is_floating (GIMP_ITEM (mask), gimp_item_get_image (GIMP_ITEM (layer)), error)) - success = (gimp_layer_add_mask (layer, mask, TRUE, error) == mask); + success = (gimp_layer_add_mask (layer, mask, TRUE, TRUE, error) == mask); else success = FALSE; } diff --git a/app/tests/test-xcf.c b/app/tests/test-xcf.c index 936735b964..6ee8c1c466 100644 --- a/app/tests/test-xcf.c +++ b/app/tests/test-xcf.c @@ -430,8 +430,9 @@ gimp_create_mainimage (Gimp *gimp, NULL /*channel*/); gimp_layer_add_mask (layer, layer_mask, - FALSE /*push_undo*/, - NULL /*error*/); + TRUE /* edit_mask */, + FALSE /* push_undo */, + NULL /* error */); /* Image compression type * diff --git a/app/xcf/xcf-load.c b/app/xcf/xcf-load.c index d1f918a807..a86899d613 100644 --- a/app/xcf/xcf-load.c +++ b/app/xcf/xcf-load.c @@ -1234,10 +1234,9 @@ xcf_load_add_masks (GimpImage *image) show_mask = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (layer), "gimp-layer-mask-show")); - gimp_layer_add_mask (layer, mask, FALSE, NULL); + gimp_layer_add_mask (layer, mask, edit_mask, FALSE, NULL); gimp_layer_set_apply_mask (layer, apply_mask, FALSE); - gimp_layer_set_edit_mask (layer, edit_mask); gimp_layer_set_show_mask (layer, show_mask, FALSE); g_object_set_data (G_OBJECT (layer), "gimp-layer-mask", NULL); diff --git a/pdb/groups/layer.pdb b/pdb/groups/layer.pdb index c6b753ec50..da5093d1a9 100644 --- a/pdb/groups/layer.pdb +++ b/pdb/groups/layer.pdb @@ -364,7 +364,7 @@ HELP if (gimp_pdb_item_is_floating (GIMP_ITEM (mask), gimp_item_get_image (GIMP_ITEM (layer)), error)) - success = (gimp_layer_add_mask (layer, mask, TRUE, error) == mask); + success = (gimp_layer_add_mask (layer, mask, TRUE, TRUE, error) == mask); else success = FALSE; }