[gimp] app, pdb: layers-merge-down action now multi-layer aware.
- From: Jehan <jehanp src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] app, pdb: layers-merge-down action now multi-layer aware.
- Date: Tue, 30 Jun 2020 21:30:37 +0000 (UTC)
commit 955aecab922b8ca96010d92723f0e40f76033fed
Author: Jehan <jehan girinstud io>
Date: Tue Jun 30 23:29:05 2020 +0200
app, pdb: layers-merge-down action now multi-layer aware.
When several layers are selected, each layer will merge down with the
layer below it. This is similar to running Merge Down several times, one
for each selected layer.
app/actions/layers-actions.c | 83 +++++++++++++-------------
app/actions/layers-commands.c | 24 ++++++--
app/core/gimpimage-merge.c | 132 ++++++++++++++++++++++++------------------
app/core/gimpimage-merge.h | 4 +-
app/pdb/image-cmds.c | 14 ++++-
pdb/groups/image.pdb | 14 ++++-
6 files changed, 159 insertions(+), 112 deletions(-)
---
diff --git a/app/actions/layers-actions.c b/app/actions/layers-actions.c
index d655f80d77..f44463f7d7 100644
--- a/app/actions/layers-actions.c
+++ b/app/actions/layers-actions.c
@@ -173,7 +173,7 @@ static const GimpActionEntry layers_actions[] =
{ "layers-merge-down", GIMP_ICON_LAYER_MERGE_DOWN,
NC_("layers-action", "Merge Do_wn"), NULL,
- NC_("layers-action", "Merge this layer with the first visible layer below it"),
+ NC_("layers-action", "Merge these layers with the first visible layer below each"),
layers_merge_down_cmd_callback,
GIMP_HELP_LAYER_MERGE_DOWN },
@@ -182,7 +182,7 @@ static const GimpActionEntry layers_actions[] =
*/
{ "layers-merge-down-button", GIMP_ICON_LAYER_MERGE_DOWN,
NC_("layers-action", "Merge Do_wn"), NULL,
- NC_("layers-action", "Merge this layer with the first visible layer below it"),
+ NC_("layers-action", "Merge these layers with the first visible layer below each"),
layers_merge_down_cmd_callback,
GIMP_HELP_LAYER_MERGE_DOWN },
@@ -774,14 +774,12 @@ layers_actions_update (GimpActionGroup *group,
gboolean lock_alpha = TRUE;
gboolean can_lock_alpha = FALSE;
gboolean text_layer = FALSE;
- gboolean visible = FALSE;
gboolean writable = FALSE;
gboolean movable = FALSE;
gboolean children = FALSE;
gboolean bs_mutable = FALSE; /* At least 1 selected layers' blend space is mutable. */
gboolean cs_mutable = FALSE; /* At least 1 selected layers' composite space is mutable. */
gboolean cm_mutable = FALSE; /* At least 1 selected layers' composite mode is mutable. */
- GList *next_visible = NULL;
gboolean next_mode = TRUE;
gboolean prev_mode = TRUE;
gboolean last_mode = FALSE;
@@ -795,6 +793,8 @@ layers_actions_update (GimpActionGroup *group,
gboolean have_prev = FALSE; /* At least 1 selected layer has a previous sibling. */
gboolean have_next = FALSE; /* At least 1 selected layer has a next sibling. */
+ gboolean all_visible = TRUE;
+ gboolean all_next_visible = TRUE;
gboolean all_masks_shown = TRUE;
gboolean all_masks_disabled = TRUE;
@@ -872,11 +872,33 @@ layers_actions_update (GimpActionGroup *group,
if (iter2)
{
+ GList *next_visible;
+
if (g_list_previous (iter2))
have_prev = TRUE;
if (g_list_next (iter2))
have_next = TRUE;
+
+ for (next_visible = g_list_next (iter2);
+ next_visible;
+ next_visible = g_list_next (next_visible))
+ {
+ if (gimp_item_get_visible (next_visible->data))
+ {
+ /* "next_visible" is actually "next_visible" and
+ * "writable" and "not group"
+ */
+ if (gimp_item_is_content_locked (next_visible->data) ||
+ gimp_viewable_get_children (next_visible->data))
+ next_visible = NULL;
+
+ break;
+ }
+ }
+
+ if (! next_visible)
+ all_next_visible = FALSE;
}
if (gimp_layer_mode_is_blend_space_mutable (mode))
@@ -886,23 +908,25 @@ layers_actions_update (GimpActionGroup *group,
if (gimp_layer_mode_is_composite_mode_mutable (mode))
cm_mutable = TRUE;
- if (have_masks && have_no_masks &&
- have_groups && have_no_groups &&
- have_writable && ! all_masks_shown &&
- ! all_masks_disabled &&
- ! lock_alpha && can_lock_alpha &&
- ! prev_mode && ! next_mode &&
- have_prev && have_next &&
- bs_mutable && cs_mutable && cm_mutable)
+ if (! gimp_item_get_visible (iter->data))
+ all_visible = FALSE;
+
+ if (have_masks && have_no_masks &&
+ have_groups && have_no_groups &&
+ have_writable && ! all_masks_shown &&
+ ! all_masks_disabled &&
+ ! lock_alpha && can_lock_alpha &&
+ ! prev_mode && ! next_mode &&
+ have_prev && have_next &&
+ bs_mutable && cs_mutable && cm_mutable &&
+ ! all_visible && ! all_next_visible)
break;
}
if (n_layers == 1)
{
/* Special unique layer case. */
- const gchar *action = NULL;
- GList *layer_list;
- GList *list;
+ const gchar *action = NULL;
layer = layers->data;
switch (gimp_layer_get_blend_space (layer))
@@ -953,37 +977,12 @@ layers_actions_update (GimpActionGroup *group,
mask = gimp_layer_get_mask (layer);
alpha = gimp_drawable_has_alpha (GIMP_DRAWABLE (layer));
- visible = gimp_item_get_visible (GIMP_ITEM (layer));
writable = ! gimp_item_is_content_locked (GIMP_ITEM (layer));
movable = ! gimp_item_is_position_locked (GIMP_ITEM (layer));
if (gimp_viewable_get_children (GIMP_VIEWABLE (layer)))
children = TRUE;
- layer_list = gimp_item_get_container_iter (GIMP_ITEM (layer));
-
- list = g_list_find (layer_list, layer);
-
- if (list)
- {
- for (next_visible = g_list_next (list);
- next_visible;
- next_visible = g_list_next (next_visible))
- {
- if (gimp_item_get_visible (next_visible->data))
- {
- /* "next_visible" is actually "next_visible" and
- * "writable" and "not group"
- */
- if (gimp_item_is_content_locked (next_visible->data) ||
- gimp_viewable_get_children (next_visible->data))
- next_visible = NULL;
-
- break;
- }
- }
- }
-
text_layer = gimp_item_is_text_layer (GIMP_ITEM (layer));
}
}
@@ -1037,9 +1036,9 @@ layers_actions_update (GimpActionGroup *group,
SET_VISIBLE ("layers-anchor", fs && !ac);
SET_VISIBLE ("layers-merge-down", !fs);
- SET_SENSITIVE ("layers-merge-down", layer && !fs && !ac && visible && next_visible);
+ SET_SENSITIVE ("layers-merge-down", n_layers > 0 && !fs && !ac && all_visible && all_next_visible);
SET_VISIBLE ("layers-merge-down-button", !fs);
- SET_SENSITIVE ("layers-merge-down-button", layer && !fs && !ac);
+ SET_SENSITIVE ("layers-merge-down-button", n_layers > 0 && !fs && !ac);
SET_VISIBLE ("layers-merge-group", have_groups);
SET_SENSITIVE ("layers-merge-group", n_layers && !fs && !ac && have_groups);
SET_SENSITIVE ("layers-merge-layers", n_layers > 0 && !fs && !ac);
diff --git a/app/actions/layers-commands.c b/app/actions/layers-commands.c
index d6a107b3ff..0df6cec1e9 100644
--- a/app/actions/layers-commands.c
+++ b/app/actions/layers-commands.c
@@ -822,14 +822,28 @@ layers_merge_down_cmd_callback (GimpAction *action,
gpointer data)
{
GimpImage *image;
- GimpLayer *layer;
+ GList *layers;
GimpDisplay *display;
- return_if_no_layer (image, layer, data);
+ GError *error = NULL;
+
+ return_if_no_layers (image, layers, data);
return_if_no_display (display, data);
- gimp_image_merge_down (image, layer, action_data_get_context (data),
- GIMP_EXPAND_AS_NECESSARY,
- GIMP_PROGRESS (display), NULL);
+ layers = gimp_image_merge_down (image, layers, action_data_get_context (data),
+ GIMP_EXPAND_AS_NECESSARY,
+ GIMP_PROGRESS (display), &error);
+
+ if (error)
+ {
+ gimp_message_literal (image->gimp,
+ G_OBJECT (display), GIMP_MESSAGE_WARNING,
+ error->message);
+ g_clear_error (&error);
+ return;
+ }
+ gimp_image_set_selected_layers (image, layers);
+ g_list_free (layers);
+
gimp_image_flush (image);
}
diff --git a/app/core/gimpimage-merge.c b/app/core/gimpimage-merge.c
index a39e0c1421..75fa60b158 100644
--- a/app/core/gimpimage-merge.c
+++ b/app/core/gimpimage-merge.c
@@ -264,86 +264,98 @@ gimp_image_flatten (GimpImage *image,
return NULL;
}
-GimpLayer *
+GList *
gimp_image_merge_down (GimpImage *image,
- GimpLayer *current_layer,
+ GList *layers,
GimpContext *context,
GimpMergeType merge_type,
GimpProgress *progress,
GError **error)
{
GimpLayer *layer;
+ GList *merged_layers = NULL;
GList *list;
- GList *layer_list = NULL;
- GSList *merge_list = NULL;
+ GList *merge_lists = NULL;
+ GSList *merge_list;
const gchar *undo_desc;
g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL);
- g_return_val_if_fail (GIMP_IS_LAYER (current_layer), NULL);
- g_return_val_if_fail (gimp_item_is_attached (GIMP_ITEM (current_layer)), NULL);
g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
g_return_val_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress), NULL);
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
- if (gimp_layer_is_floating_sel (current_layer))
+ for (list = layers; list; list = list->next)
{
- g_set_error_literal (error, GIMP_ERROR, GIMP_FAILED,
- _("Cannot merge down a floating selection."));
- return NULL;
- }
+ GList *list2;
+ GList *layer_list = NULL;
- if (! gimp_item_get_visible (GIMP_ITEM (current_layer)))
- {
- g_set_error_literal (error, GIMP_ERROR, GIMP_FAILED,
- _("Cannot merge down an invisible layer."));
- return NULL;
- }
+ g_return_val_if_fail (GIMP_IS_LAYER (list->data), NULL);
+ g_return_val_if_fail (gimp_item_is_attached (GIMP_ITEM (list->data)), NULL);
- for (list = gimp_item_get_container_iter (GIMP_ITEM (current_layer));
- list;
- list = g_list_next (list))
- {
- layer = list->data;
+ if (gimp_layer_is_floating_sel (list->data))
+ {
+ g_set_error_literal (error, GIMP_ERROR, GIMP_FAILED,
+ _("Cannot merge down a floating selection."));
+ return NULL;
+ }
- if (layer == current_layer)
- break;
- }
+ if (! gimp_item_get_visible (GIMP_ITEM (list->data)))
+ {
+ g_set_error_literal (error, GIMP_ERROR, GIMP_FAILED,
+ _("Cannot merge down an invisible layer."));
+ return NULL;
+ }
- for (layer_list = g_list_next (list);
- layer_list;
- layer_list = g_list_next (layer_list))
- {
- layer = layer_list->data;
+ for (list2 = gimp_item_get_container_iter (GIMP_ITEM (list->data));
+ list2;
+ list2 = g_list_next (list2))
+ {
+ layer = list2->data;
- if (gimp_item_get_visible (GIMP_ITEM (layer)))
+ if (layer == list->data)
+ break;
+ }
+
+ merge_list = NULL;
+
+ for (layer_list = g_list_next (list2);
+ layer_list;
+ layer_list = g_list_next (layer_list))
{
- if (gimp_viewable_get_children (GIMP_VIEWABLE (layer)))
- {
- g_set_error_literal (error, GIMP_ERROR, GIMP_FAILED,
- _("Cannot merge down to a layer group."));
- return NULL;
- }
+ layer = layer_list->data;
- if (gimp_item_is_content_locked (GIMP_ITEM (layer)))
+ if (gimp_item_get_visible (GIMP_ITEM (layer)))
{
- g_set_error_literal (error, GIMP_ERROR, GIMP_FAILED,
- _("The layer to merge down to is locked."));
- return NULL;
+ if (gimp_viewable_get_children (GIMP_VIEWABLE (layer)))
+ {
+ g_set_error_literal (error, GIMP_ERROR, GIMP_FAILED,
+ _("Cannot merge down to a layer group."));
+ return NULL;
+ }
+
+ if (gimp_item_is_content_locked (GIMP_ITEM (layer)))
+ {
+ g_set_error_literal (error, GIMP_ERROR, GIMP_FAILED,
+ _("The layer to merge down to is locked."));
+ return NULL;
+ }
+
+ merge_list = g_slist_append (NULL, layer);
+ break;
}
+ }
- merge_list = g_slist_append (NULL, layer);
- break;
+ if (! merge_list)
+ {
+ g_set_error_literal (error, GIMP_ERROR, GIMP_FAILED,
+ _("There is no visible layer to merge down to."));
+ return NULL;
}
- }
- if (! merge_list)
- {
- g_set_error_literal (error, GIMP_ERROR, GIMP_FAILED,
- _("There is no visible layer to merge down to."));
- return NULL;
- }
+ merge_list = g_slist_prepend (merge_list, list->data);
- merge_list = g_slist_prepend (merge_list, current_layer);
+ merge_lists = g_list_prepend (merge_lists, merge_list);
+ }
undo_desc = C_("undo-type", "Merge Down");
@@ -353,17 +365,23 @@ gimp_image_merge_down (GimpImage *image,
GIMP_UNDO_GROUP_IMAGE_LAYERS_MERGE,
undo_desc);
- layer = gimp_image_merge_layers (image,
- gimp_item_get_container (GIMP_ITEM (current_layer)),
- merge_list, context, merge_type,
- undo_desc, progress);
- g_slist_free (merge_list);
+ for (list = merge_lists; list; list = list->next)
+ {
+ merge_list = list->data;
+ layer = gimp_image_merge_layers (image,
+ gimp_item_get_container (merge_list->data),
+ merge_list, context, merge_type,
+ undo_desc, progress);
+ merged_layers = g_list_prepend (merged_layers, layer);
+ }
+
+ g_list_free_full (merge_lists, (GDestroyNotify) g_slist_free);
gimp_image_undo_group_end (image);
gimp_unset_busy (image->gimp);
- return layer;
+ return merged_layers;
}
GimpLayer *
diff --git a/app/core/gimpimage-merge.h b/app/core/gimpimage-merge.h
index de8e9297b6..f298ad54eb 100644
--- a/app/core/gimpimage-merge.h
+++ b/app/core/gimpimage-merge.h
@@ -25,8 +25,8 @@ GList * gimp_image_merge_visible_layers (GimpImage *image,
gboolean merge_active_group,
gboolean discard_invisible,
GimpProgress *progress);
-GimpLayer * gimp_image_merge_down (GimpImage *image,
- GimpLayer *current_layer,
+GList * gimp_image_merge_down (GimpImage *image,
+ GList *layers,
GimpContext *context,
GimpMergeType merge_type,
GimpProgress *progress,
diff --git a/app/pdb/image-cmds.c b/app/pdb/image-cmds.c
index 37b3fba3bc..44fcf02093 100644
--- a/app/pdb/image-cmds.c
+++ b/app/pdb/image-cmds.c
@@ -1468,11 +1468,19 @@ image_merge_down_invoker (GimpProcedure *procedure,
{
if (gimp_pdb_item_is_attached (GIMP_ITEM (merge_layer), image, 0, error))
{
- layer = gimp_image_merge_down (image, merge_layer, context, merge_type,
- progress, error);
+ GList *merge_layers = g_list_prepend (NULL, merge_layer);
+ GList *layers;
- if (! layer)
+ layers = gimp_image_merge_down (image, merge_layers, context,
+ merge_type, progress, error);
+ g_list_free (merge_layers);
+
+ if (! layers)
success = FALSE;
+ else
+ layer = layers->data;
+
+ g_list_free (layers);
}
else
success = FALSE;
diff --git a/pdb/groups/image.pdb b/pdb/groups/image.pdb
index 64d269ee25..59d90b84ae 100644
--- a/pdb/groups/image.pdb
+++ b/pdb/groups/image.pdb
@@ -826,11 +826,19 @@ HELP
{
if (gimp_pdb_item_is_attached (GIMP_ITEM (merge_layer), image, 0, error))
{
- layer = gimp_image_merge_down (image, merge_layer, context, merge_type,
- progress, error);
+ GList *merge_layers = g_list_prepend (NULL, merge_layer);
+ GList *layers;
- if (! layer)
+ layers = gimp_image_merge_down (image, merge_layers, context,
+ merge_type, progress, error);
+ g_list_free (merge_layers);
+
+ if (! layers)
success = FALSE;
+ else
+ layer = layers->data;
+
+ g_list_free (layers);
}
else
success = FALSE;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]