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 (layer == current_layer) - break; - } - - for (layer_list = g_list_next (list); - layer_list; - layer_list = g_list_next (layer_list)) - { - layer = layer_list->data; - - if (gimp_item_get_visible (GIMP_ITEM (layer))) + if (gimp_layer_is_floating_sel (list->data)) { - 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; + g_set_error_literal (error, GIMP_ERROR, GIMP_FAILED, + _("Cannot merge down a floating selection.")); + 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; - } + 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; + } - merge_list = g_slist_prepend (merge_list, current_layer); + for (list2 = gimp_item_get_container_iter (GIMP_ITEM (list->data)); + list2; + list2 = g_list_next (list2)) + { + layer = list2->data; + + if (layer == list->data) + break; + } + + merge_list = NULL; + + for (layer_list = g_list_next (list2); + layer_list; + layer_list = g_list_next (layer_list)) + { + layer = layer_list->data; + + if (gimp_item_get_visible (GIMP_ITEM (layer))) + { + 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; + } + } + + 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_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;