[gimp] Bug 759601 - Add/Remove layer masks by clicking the layer preview
- From: Michael Natterer <mitch src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] Bug 759601 - Add/Remove layer masks by clicking the layer preview
- Date: Tue, 23 Aug 2016 17:26:30 +0000 (UTC)
commit 0b7381a8223f1a02e1c1c0b9e7609544d82e8fce
Author: Benoit Touchette <draekko software+gimp gmail com>
Date: Tue Aug 23 19:18:20 2016 +0200
Bug 759601 - Add/Remove layer masks by clicking the layer preview
Quite heavily modified by Mitch to address the more general issues
mentioned in comment 35 of the bug:
- Remember the added mask's type and the invert boolean in
GimpDialogConfig
- Add new prefs page "Dialog Defaults" which will contain
only stuff from GimpDialogConfig and can be reset separately
- Remove static mask variables from layers-commands.c and
use the new config values for both interactive mask adding
with the dialog, and for the shortcut based method
- Add a button to the layers dialog which supports add, add
with last values, delete, apply
- Add modifier-click shortcuts on the layer preview with the
same modifiers as on the button
app/actions/layers-actions.c | 22 ++++++-
app/actions/layers-commands.c | 134 ++++++++++++++++++++++++++-----------
app/actions/layers-commands.h | 2 +
app/config/gimpdialogconfig.c | 41 ++++++++++--
app/config/gimpdialogconfig.h | 2 +
app/config/gimprc-blurbs.h | 6 ++
app/dialogs/preferences-dialog.c | 45 ++++++++++++-
app/widgets/gimphelp-ids.h | 1 +
app/widgets/gimplayertreeview.c | 68 ++++++++++++++++---
9 files changed, 260 insertions(+), 61 deletions(-)
---
diff --git a/app/actions/layers-actions.c b/app/actions/layers-actions.c
index 11f3f84..e3f495f 100644
--- a/app/actions/layers-actions.c
+++ b/app/actions/layers-actions.c
@@ -225,6 +225,23 @@ static const GimpActionEntry layers_actions[] =
G_CALLBACK (layers_mask_add_cmd_callback),
GIMP_HELP_LAYER_MASK_ADD },
+ /* this is the same as layers-mask-add, except it's sensitive even if
+ * there is a mask on the layer
+ */
+ { "layers-mask-add-button", GIMP_STOCK_LAYER_MASK,
+ NC_("layers-action", "Add La_yer Mask..."), NULL,
+ NC_("layers-action",
+ "Add a mask that allows non-destructive editing of transparency"),
+ G_CALLBACK (layers_mask_add_cmd_callback),
+ GIMP_HELP_LAYER_MASK_ADD },
+
+ { "layers-mask-add-last-values", GIMP_STOCK_LAYER_MASK,
+ NC_("layers-action", "Add La_yer Mask"), NULL,
+ NC_("layers-action",
+ "Add a mask with last used values"),
+ G_CALLBACK (layers_mask_add_last_vals_cmd_callback),
+ GIMP_HELP_LAYER_MASK_ADD },
+
{ "layers-alpha-add", GIMP_STOCK_TRANSPARENCY,
NC_("layers-action", "Add Alpha C_hannel"), NULL,
NC_("layers-action", "Add transparency information to the layer"),
@@ -660,7 +677,10 @@ layers_actions_update (GimpActionGroup *group,
SET_SENSITIVE ("layers-lock-alpha", can_lock_alpha);
SET_ACTIVE ("layers-lock-alpha", lock_alpha);
- SET_SENSITIVE ("layers-mask-add", layer && !fs && !ac && !mask && !children);
+ SET_SENSITIVE ("layers-mask-add", layer && !fs && !ac && !mask && !children);
+ SET_SENSITIVE ("layers-mask-add-button", layer && !fs && !ac && !children);
+ SET_SENSITIVE ("layers-mask-add-last-values", layer && !fs && !ac && !mask && !children);
+
SET_SENSITIVE ("layers-mask-apply", writable && !fs && !ac && mask && !children);
SET_SENSITIVE ("layers-mask-delete", layer && !fs && !ac && mask);
diff --git a/app/actions/layers-commands.c b/app/actions/layers-commands.c
index e90723a..10be12f 100644
--- a/app/actions/layers-commands.c
+++ b/app/actions/layers-commands.c
@@ -29,10 +29,11 @@
#include "actions-types.h"
-#include "config/gimpcoreconfig.h"
+#include "config/gimpdialogconfig.h"
#include "core/gimp.h"
#include "core/gimpchannel.h"
+#include "core/gimpcontainer.h"
#include "core/gimpcontext.h"
#include "core/gimpdrawable-fill.h"
#include "core/gimpgrouplayer.h"
@@ -151,8 +152,6 @@ static gchar *layer_name = NULL;
static GimpUnit layer_resize_unit = GIMP_UNIT_PIXEL;
static GimpUnit layer_scale_unit = GIMP_UNIT_PIXEL;
static GimpInterpolationType layer_scale_interp = -1;
-static GimpAddMaskType layer_add_mask_type = GIMP_ADD_MASK_WHITE;
-static gboolean layer_mask_invert = FALSE;
/* public functions */
@@ -773,12 +772,19 @@ layers_mask_add_cmd_callback (GtkAction *action,
GimpImage *image;
GimpLayer *layer;
GtkWidget *widget;
+ GimpDialogConfig *config;
return_if_no_layer (image, layer, data);
return_if_no_widget (widget, data);
+ if (gimp_layer_get_mask (layer))
+ return;
+
+ config = GIMP_DIALOG_CONFIG (image->gimp->config);
+
dialog = layer_add_mask_dialog_new (layer, action_data_get_context (data),
widget,
- layer_add_mask_type, layer_mask_invert);
+ config->layer_add_mask_type,
+ config->layer_add_mask_invert);
g_signal_connect (dialog->dialog, "response",
G_CALLBACK (layers_add_mask_response),
@@ -788,19 +794,66 @@ layers_mask_add_cmd_callback (GtkAction *action,
}
void
+layers_mask_add_last_vals_cmd_callback (GtkAction *action,
+ gpointer data)
+{
+ GimpImage *image;
+ GimpLayer *layer;
+ GtkWidget *widget;
+ GimpDialogConfig *config;
+ GimpChannel *channel = NULL;
+ GimpLayerMask *mask;
+ return_if_no_layer (image, layer, data);
+ return_if_no_widget (widget, data);
+
+ if (gimp_layer_get_mask (layer))
+ return;
+
+ config = GIMP_DIALOG_CONFIG (image->gimp->config);
+
+ if (config->layer_add_mask_type == GIMP_ADD_MASK_CHANNEL)
+ {
+ channel = gimp_image_get_active_channel (image);
+
+ if (! channel)
+ {
+ GimpContainer *channels = gimp_image_get_channels (image);
+
+ channel = GIMP_CHANNEL (gimp_container_get_first_child (channels));
+ }
+
+ if (! channel)
+ {
+ layers_mask_add_cmd_callback (action, data);
+ return;
+ }
+ }
+
+ mask = gimp_layer_create_mask (layer,
+ config->layer_add_mask_type,
+ channel);
+
+ if (config->layer_add_mask_invert)
+ gimp_channel_invert (GIMP_CHANNEL (mask), FALSE);
+
+ gimp_layer_add_mask (layer, mask, TRUE, NULL);
+
+ gimp_image_flush (image);
+}
+
+void
layers_mask_apply_cmd_callback (GtkAction *action,
gint value,
gpointer data)
{
- GimpImage *image;
- GimpLayer *layer;
- GimpMaskApplyMode mode;
+ GimpImage *image;
+ GimpLayer *layer;
return_if_no_layer (image, layer, data);
- mode = (GimpMaskApplyMode) value;
-
if (gimp_layer_get_mask (layer))
{
+ GimpMaskApplyMode mode = (GimpMaskApplyMode) value;
+
gimp_layer_apply_mask (layer, mode, TRUE);
gimp_image_flush (image);
}
@@ -810,14 +863,11 @@ void
layers_mask_edit_cmd_callback (GtkAction *action,
gpointer data)
{
- GimpImage *image;
- GimpLayer *layer;
- GimpLayerMask *mask;
+ GimpImage *image;
+ GimpLayer *layer;
return_if_no_layer (image, layer, data);
- mask = gimp_layer_get_mask (layer);
-
- if (mask)
+ if (gimp_layer_get_mask (layer))
{
gboolean active;
@@ -832,14 +882,11 @@ void
layers_mask_show_cmd_callback (GtkAction *action,
gpointer data)
{
- GimpImage *image;
- GimpLayer *layer;
- GimpLayerMask *mask;
+ GimpImage *image;
+ GimpLayer *layer;
return_if_no_layer (image, layer, data);
- mask = gimp_layer_get_mask (layer);
-
- if (mask)
+ if (gimp_layer_get_mask (layer))
{
gboolean active;
@@ -854,14 +901,11 @@ void
layers_mask_disable_cmd_callback (GtkAction *action,
gpointer data)
{
- GimpImage *image;
- GimpLayer *layer;
- GimpLayerMask *mask;
+ GimpImage *image;
+ GimpLayer *layer;
return_if_no_layer (image, layer, data);
- mask = gimp_layer_get_mask (layer);
-
- if (mask)
+ if (gimp_layer_get_mask (layer))
{
gboolean active;
@@ -1125,9 +1169,13 @@ layers_add_mask_response (GtkWidget *widget,
{
if (response_id == GTK_RESPONSE_OK)
{
- GimpLayer *layer = dialog->layer;
- GimpImage *image = gimp_item_get_image (GIMP_ITEM (layer));
- GimpLayerMask *mask;
+ GimpLayer *layer = dialog->layer;
+ GimpImage *image = gimp_item_get_image (GIMP_ITEM (layer));
+ GimpLayerMask *mask;
+ GimpDialogConfig *config;
+ GError *error = NULL;
+
+ config = GIMP_DIALOG_CONFIG (image->gimp->config);
if (dialog->add_mask_type == GIMP_ADD_MASK_CHANNEL &&
! dialog->channel)
@@ -1138,21 +1186,27 @@ layers_add_mask_response (GtkWidget *widget,
return;
}
- layer_add_mask_type = dialog->add_mask_type;
- layer_mask_invert = dialog->invert;
-
- gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_LAYER_ADD_MASK,
- _("Add Layer Mask"));
+ g_object_set (config,
+ "layer-add-mask-type", dialog->add_mask_type,
+ "layer-add-mask-invert", dialog->invert,
+ NULL);
- mask = gimp_layer_create_mask (layer, layer_add_mask_type,
+ mask = gimp_layer_create_mask (layer,
+ config->layer_add_mask_type,
dialog->channel);
- if (layer_mask_invert)
+ if (config->layer_add_mask_invert)
gimp_channel_invert (GIMP_CHANNEL (mask), FALSE);
- gimp_layer_add_mask (layer, mask, TRUE, NULL);
-
- gimp_image_undo_group_end (image);
+ if (! gimp_layer_add_mask (layer, mask, TRUE, &error))
+ {
+ gimp_message_literal (image->gimp,
+ G_OBJECT (widget), GIMP_MESSAGE_WARNING,
+ error->message);
+ g_object_unref (mask);
+ g_clear_error (&error);
+ return;
+ }
gimp_image_flush (image);
}
diff --git a/app/actions/layers-commands.h b/app/actions/layers-commands.h
index 3a016e6..76e94cc 100644
--- a/app/actions/layers-commands.h
+++ b/app/actions/layers-commands.h
@@ -77,6 +77,8 @@ void layers_crop_to_content_cmd_callback (GtkAction *action,
void layers_mask_add_cmd_callback (GtkAction *action,
gpointer data);
+void layers_mask_add_last_vals_cmd_callback (GtkAction *action,
+ gpointer data);
void layers_mask_apply_cmd_callback (GtkAction *action,
gint value,
gpointer data);
diff --git a/app/config/gimpdialogconfig.c b/app/config/gimpdialogconfig.c
index 7c6f93f..c6ffd59 100644
--- a/app/config/gimpdialogconfig.c
+++ b/app/config/gimpdialogconfig.c
@@ -36,7 +36,9 @@
enum
{
PROP_0,
- PROP_COLOR_PROFILE_POLICY
+ PROP_COLOR_PROFILE_POLICY,
+ PROP_LAYER_ADD_MASK_TYPE,
+ PROP_LAYER_ADD_MASK_INVERT
};
@@ -70,6 +72,21 @@ gimp_dialog_config_class_init (GimpDialogConfigClass *klass)
GIMP_TYPE_COLOR_PROFILE_POLICY,
GIMP_COLOR_PROFILE_POLICY_ASK,
GIMP_PARAM_STATIC_STRINGS);
+
+ GIMP_CONFIG_PROP_ENUM (object_class, PROP_LAYER_ADD_MASK_TYPE,
+ "layer-add-mask-type",
+ "Default layer mask type",
+ LAYER_ADD_MASK_TYPE_BLURB,
+ GIMP_TYPE_ADD_MASK_TYPE,
+ GIMP_ADD_MASK_WHITE,
+ GIMP_PARAM_STATIC_STRINGS);
+
+ GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_LAYER_ADD_MASK_INVERT,
+ "layer-add-mask-invert",
+ "Default layer mask invert",
+ LAYER_ADD_MASK_INVERT_BLURB,
+ FALSE,
+ GIMP_PARAM_STATIC_STRINGS);
}
static void
@@ -83,12 +100,19 @@ gimp_dialog_config_set_property (GObject *object,
const GValue *value,
GParamSpec *pspec)
{
- GimpDialogConfig *dialog_config = GIMP_DIALOG_CONFIG (object);
+ GimpDialogConfig *config = GIMP_DIALOG_CONFIG (object);
switch (property_id)
{
case PROP_COLOR_PROFILE_POLICY:
- dialog_config->color_profile_policy = g_value_get_enum (value);
+ config->color_profile_policy = g_value_get_enum (value);
+ break;
+
+ case PROP_LAYER_ADD_MASK_TYPE:
+ config->layer_add_mask_type = g_value_get_enum (value);
+ break;
+ case PROP_LAYER_ADD_MASK_INVERT:
+ config->layer_add_mask_invert = g_value_get_boolean (value);
break;
default:
@@ -103,12 +127,19 @@ gimp_dialog_config_get_property (GObject *object,
GValue *value,
GParamSpec *pspec)
{
- GimpDialogConfig *dialog_config = GIMP_DIALOG_CONFIG (object);
+ GimpDialogConfig *config = GIMP_DIALOG_CONFIG (object);
switch (property_id)
{
case PROP_COLOR_PROFILE_POLICY:
- g_value_set_enum (value, dialog_config->color_profile_policy);
+ g_value_set_enum (value, config->color_profile_policy);
+ break;
+
+ case PROP_LAYER_ADD_MASK_TYPE:
+ g_value_set_enum (value, config->layer_add_mask_type);
+ break;
+ case PROP_LAYER_ADD_MASK_INVERT:
+ g_value_set_boolean (value, config->layer_add_mask_invert);
break;
default:
diff --git a/app/config/gimpdialogconfig.h b/app/config/gimpdialogconfig.h
index 6fa9305..14559aa 100644
--- a/app/config/gimpdialogconfig.h
+++ b/app/config/gimpdialogconfig.h
@@ -38,6 +38,8 @@ struct _GimpDialogConfig
GimpGuiConfig parent_instance;
GimpColorProfilePolicy color_profile_policy;
+ GimpAddMaskType layer_add_mask_type;
+ gboolean layer_add_mask_invert;
};
struct _GimpDialogConfigClass
diff --git a/app/config/gimprc-blurbs.h b/app/config/gimprc-blurbs.h
index 2b60216..e68f477 100644
--- a/app/config/gimprc-blurbs.h
+++ b/app/config/gimprc-blurbs.h
@@ -420,6 +420,12 @@ _("Sets the folder for temporary storage. Files will appear here " \
#define ICON_THEME_PATH_BLURB \
"Sets the icon theme search path."
+#define LAYER_ADD_MASK_TYPE_BLURB \
+_("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 THUMBNAIL_SIZE_BLURB \
_("Sets the size of the thumbnail shown in the Open dialog.")
diff --git a/app/dialogs/preferences-dialog.c b/app/dialogs/preferences-dialog.c
index aab9b7f..8b87cd7 100644
--- a/app/dialogs/preferences-dialog.c
+++ b/app/dialogs/preferences-dialog.c
@@ -1479,13 +1479,11 @@ prefs_dialog_new (Gimp *gimp,
/* Policies */
vbox2 = prefs_frame_new (_("Policies"), GTK_CONTAINER (vbox),
FALSE);
-
- table = prefs_table_new (3, GTK_CONTAINER (vbox2));
- row = 0;
+ table = prefs_table_new (1, GTK_CONTAINER (vbox2));
button = prefs_enum_combo_box_add (object, "color-profile-policy", 0, 0,
_("File Open behaviour:"),
- GTK_TABLE (table), row++, size_group);
+ GTK_TABLE (table), 0, size_group);
g_object_unref (size_group);
@@ -2008,6 +2006,45 @@ prefs_dialog_new (Gimp *gimp,
gtk_widget_show (tool_editor);
+ /*********************************/
+ /* Interface / Dialog Defaults */
+ /*********************************/
+ vbox = gimp_prefs_box_add_page (GIMP_PREFS_BOX (prefs_box),
+ /* FIXME need an icon */
+ "gimp-prefs-controllers",
+ _("Dialog Defaults"),
+ _("Dialog Defaults"),
+ GIMP_HELP_PREFS_DIALOG_DEFAULTS,
+ &top_iter,
+ &child_iter);
+
+ size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
+
+ /* Color profile import dialog */
+ vbox2 = prefs_frame_new (_("Color Profile Import dialog"), GTK_CONTAINER (vbox),
+ FALSE);
+ table = prefs_table_new (1, GTK_CONTAINER (vbox2));
+
+ button = prefs_enum_combo_box_add (object, "color-profile-policy", 0, 0,
+ _("Color profile policy:"),
+ GTK_TABLE (table), 0, size_group);
+
+ /* Add Layer Mask Dialog */
+ vbox2 = prefs_frame_new (_("Add Layer Mask Dialog"),
+ GTK_CONTAINER (vbox), FALSE);
+ table = prefs_table_new (1, GTK_CONTAINER (vbox2));
+
+ prefs_enum_combo_box_add (object, "layer-add-mask-type", 0, 0,
+ _("Layer mask type:"),
+ GTK_TABLE (table), 0, size_group);
+
+ prefs_check_button_add (object, "layer-add-mask-invert",
+ _("Invert mask"),
+ GTK_BOX (vbox2));
+
+ g_object_unref (size_group);
+
+
/*****************************/
/* Interface / Help System */
/*****************************/
diff --git a/app/widgets/gimphelp-ids.h b/app/widgets/gimphelp-ids.h
index ebcc1a1..f0bcde5 100644
--- a/app/widgets/gimphelp-ids.h
+++ b/app/widgets/gimphelp-ids.h
@@ -491,6 +491,7 @@
#define GIMP_HELP_PREFS_ICON_THEME "gimp-prefs-icon-theme"
#define GIMP_HELP_PREFS_TOOL_OPTIONS "gimp-prefs-tool-options"
#define GIMP_HELP_PREFS_TOOLBOX "gimp-prefs-toolbox"
+#define GIMP_HELP_PREFS_DIALOG_DEFAULTS "gimp-prefs-dialog-defaults"
#define GIMP_HELP_PREFS_INPUT_DEVICES "gimp-prefs-input-devices"
#define GIMP_HELP_PREFS_INPUT_CONTROLLERS "gimp-prefs-input-controllers"
#define GIMP_HELP_PREFS_IMAGE_WINDOW "gimp-prefs-image-window"
diff --git a/app/widgets/gimplayertreeview.c b/app/widgets/gimplayertreeview.c
index 9c0647c..0470f05 100644
--- a/app/widgets/gimplayertreeview.c
+++ b/app/widgets/gimplayertreeview.c
@@ -389,6 +389,22 @@ gimp_layer_tree_view_constructed (GObject *object)
GIMP_TYPE_LAYER);
gtk_box_reorder_child (gimp_editor_get_button_box (GIMP_EDITOR (layer_view)),
button, 6);
+
+ button = gimp_editor_add_action_button (GIMP_EDITOR (layer_view), "layers",
+ "layers-mask-add-button",
+ "layers-mask-add-last-values",
+ gimp_get_extend_selection_mask (),
+ "layers-mask-delete",
+ gimp_get_modify_selection_mask (),
+ "layers-mask-apply",
+ gimp_get_extend_selection_mask () |
+ gimp_get_modify_selection_mask (),
+ NULL);
+ gimp_container_view_enable_dnd (GIMP_CONTAINER_VIEW (layer_view),
+ GTK_BUTTON (button),
+ GIMP_TYPE_LAYER);
+ gtk_box_reorder_child (gimp_editor_get_button_box (GIMP_EDITOR (layer_view)),
+ button, 7);
}
static void
@@ -1299,18 +1315,18 @@ gimp_layer_tree_view_layer_clicked (GimpCellRendererViewable *cell,
GimpLayerTreeView *layer_view)
{
GimpContainerTreeView *tree_view = GIMP_CONTAINER_TREE_VIEW (layer_view);
- GtkTreePath *path;
+ GtkTreePath *path = gtk_tree_path_new_from_string (path_str);
GtkTreeIter iter;
- path = gtk_tree_path_new_from_string (path_str);
-
- if (gtk_tree_model_get_iter (tree_view->model, &iter, path))
+ if (gtk_tree_model_get_iter (tree_view->model, &iter, path) &&
+ ! (state & GDK_MOD1_MASK))
{
- GimpUIManager *ui_manager = gimp_editor_get_ui_manager (GIMP_EDITOR (tree_view));
+ GimpUIManager *ui_manager;
GimpActionGroup *group;
GimpViewRenderer *renderer;
- group = gimp_ui_manager_get_action_group (ui_manager, "layers");
+ ui_manager = gimp_editor_get_ui_manager (GIMP_EDITOR (tree_view));
+ group = gimp_ui_manager_get_action_group (ui_manager, "layers");
gtk_tree_model_get (tree_view->model, &iter,
GIMP_CONTAINER_TREE_STORE_COLUMN_RENDERER, &renderer,
@@ -1318,13 +1334,43 @@ gimp_layer_tree_view_layer_clicked (GimpCellRendererViewable *cell,
if (renderer)
{
- GimpLayer *layer = GIMP_LAYER (renderer->viewable);
+ GimpLayer *layer = GIMP_LAYER (renderer->viewable);
+ GimpLayerMask *mask = gimp_layer_get_mask (layer);
+
+ if (state & gimp_get_extend_selection_mask ())
+ {
+ if (state & gimp_get_modify_selection_mask ())
+ {
+ /* Shift-Control-click apply a layer mask */
+
+ if (mask)
+ gimp_ui_manager_activate_action (ui_manager, "layers",
+ "layers-mask-apply");
+ }
+ else
+ {
+ /* Shift-click add a layer mask with last values */
+
+ if (! mask)
+ gimp_ui_manager_activate_action (ui_manager, "layers",
+ "layers-mask-add-last-values");
+ }
+ }
+ else if (state & gimp_get_modify_selection_mask ())
+ {
+ /* Control-click remove a layer mask */
- if (gimp_layer_get_mask (layer) &&
- gimp_layer_get_edit_mask (layer))
+ if (mask)
+ gimp_ui_manager_activate_action (ui_manager, "layers",
+ "layers-mask-delete");
+ }
+ else if (mask && gimp_layer_get_edit_mask (layer))
{
- gimp_action_group_set_action_active (group,
- "layers-mask-edit", FALSE);
+ /* other clicks activate the layer */
+
+ if (mask)
+ gimp_action_group_set_action_active (group,
+ "layers-mask-edit", FALSE);
}
g_object_unref (renderer);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]