diff --git a/app/actions/layers-actions.c b/app/actions/layers-actions.c index 0b67608292..57f3bbbfa5 100644 --- a/app/actions/layers-actions.c +++ b/app/actions/layers-actions.c @@ -1040,7 +1040,7 @@ layers_actions_update (GimpActionGroup *group, SET_SENSITIVE ("layers-merge-down-button", layer && !fs && !ac); SET_VISIBLE ("layers-merge-group", children); SET_SENSITIVE ("layers-merge-group", layer && !fs && !ac && children); - SET_SENSITIVE ("layers-merge-layers", layer && !fs && !ac); + SET_SENSITIVE ("layers-merge-layers", n_layers > 0 && !fs && !ac); SET_SENSITIVE ("layers-flatten-image", layer && !fs && !ac); SET_VISIBLE ("layers-text-discard", text_layer && !ac); diff --git a/app/config/gimpdialogconfig.c b/app/config/gimpdialogconfig.c index f81d778d86..ca13737784 100644 --- a/app/config/gimpdialogconfig.c +++ b/app/config/gimpdialogconfig.c @@ -388,7 +388,7 @@ gimp_dialog_config_class_init (GimpDialogConfigClass *klass) GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_LAYER_MERGE_ACTIVE_GROUP_ONLY, "layer-merge-active-group-only", - "Default layer merge active group only", + "Default layer merge active groups only", LAYER_MERGE_ACTIVE_GROUP_ONLY_BLURB, TRUE, GIMP_PARAM_STATIC_STRINGS); diff --git a/app/core/gimpimage-merge.c b/app/core/gimpimage-merge.c index b8dc8cc11b..a39e0c1421 100644 --- a/app/core/gimpimage-merge.c +++ b/app/core/gimpimage-merge.c @@ -66,7 +66,7 @@ static GimpLayer * gimp_image_merge_layers (GimpImage *image, /* public functions */ -GimpLayer * +GList * gimp_image_merge_visible_layers (GimpImage *image, GimpContext *context, GimpMergeType merge_type, @@ -74,10 +74,11 @@ gimp_image_merge_visible_layers (GimpImage *image, gboolean discard_invisible, GimpProgress *progress) { - GimpContainer *container; - GList *list; - GSList *merge_list = NULL; - GSList *invisible_list = NULL; + const gchar *undo_desc = C_("undo-type", "Merge Visible Layers"); + GList *containers = NULL; + GList *new_layers = NULL; + GList *iter; + GList *iter2; g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL); g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL); @@ -85,89 +86,119 @@ gimp_image_merge_visible_layers (GimpImage *image, if (merge_active_group) { - GimpLayer *active_layer = gimp_image_get_active_layer (image); + GList *selected_layers = gimp_image_get_selected_layers (image); /* if the active layer is the floating selection, get the * underlying drawable, but only if it is a layer */ - if (active_layer && gimp_layer_is_floating_sel (active_layer)) + if (g_list_length (selected_layers) == 1 && gimp_layer_is_floating_sel (selected_layers->data)) { GimpDrawable *fs_drawable; - fs_drawable = gimp_layer_get_floating_sel_drawable (active_layer); + fs_drawable = gimp_layer_get_floating_sel_drawable (selected_layers->data); if (GIMP_IS_LAYER (fs_drawable)) - active_layer = GIMP_LAYER (fs_drawable); + containers = g_list_prepend (containers, + gimp_item_get_container (GIMP_ITEM (fs_drawable))); } - - if (active_layer) - container = gimp_item_get_container (GIMP_ITEM (active_layer)); else - container = gimp_image_get_layers (image); - } - else - { - container = gimp_image_get_layers (image); - } - - for (list = gimp_item_stack_get_item_iter (GIMP_ITEM_STACK (container)); - list; - list = g_list_next (list)) - { - GimpLayer *layer = list->data; - - if (gimp_layer_is_floating_sel (layer)) - continue; - - if (gimp_item_get_visible (GIMP_ITEM (layer))) { - merge_list = g_slist_append (merge_list, layer); + for (iter = selected_layers; iter; iter = iter->next) + if (! gimp_item_get_parent (iter->data)) + break; + + /* No need to list selected groups if any selected layer is + * to-level. + */ + if (iter == NULL) + { + for (iter = selected_layers; iter; iter = iter->next) + { + for (iter2 = selected_layers; iter2; iter2 = iter2->next) + { + /* Only retain a selected layer's container if no + * other selected layers are its parents. + */ + if (iter->data != iter2->data && + gimp_item_is_ancestor (iter->data, iter2->data)) + break; + } + if (iter2 == NULL && + ! g_list_find (containers, gimp_item_get_container (GIMP_ITEM (iter->data)))) + containers = g_list_prepend (containers, + gimp_item_get_container (GIMP_ITEM (iter->data))); + } + } } - else if (discard_invisible) + } + if (! containers) + containers = g_list_prepend (NULL, gimp_image_get_layers (image)); + + gimp_set_busy (image->gimp); + gimp_image_undo_group_start (image, + GIMP_UNDO_GROUP_IMAGE_LAYERS_MERGE, + undo_desc); + + for (iter = containers; iter; iter = iter->next) + { + GimpContainer *container = iter->data; + GSList *merge_list = NULL; + GSList *invisible_list = NULL; + + for (iter2 = gimp_item_stack_get_item_iter (GIMP_ITEM_STACK (container)); + iter2; + iter2 = g_list_next (iter2)) { - invisible_list = g_slist_append (invisible_list, layer); + GimpLayer *layer = iter2->data; + + if (gimp_layer_is_floating_sel (layer)) + continue; + + if (gimp_item_get_visible (GIMP_ITEM (layer))) + { + merge_list = g_slist_append (merge_list, layer); + } + else if (discard_invisible) + { + invisible_list = g_slist_append (invisible_list, layer); + } + } + + if (merge_list) + { + GimpLayer *layer; + /* if there's a floating selection, anchor it */ + if (gimp_image_get_floating_selection (image)) + floating_sel_anchor (gimp_image_get_floating_selection (image)); + + layer = gimp_image_merge_layers (image, + container, + merge_list, context, merge_type, + undo_desc, progress); + g_slist_free (merge_list); + + if (invisible_list) + { + GSList *list; + + for (list = invisible_list; list; list = g_slist_next (list)) + gimp_image_remove_layer (image, list->data, TRUE, NULL); + + g_slist_free (invisible_list); + } + + new_layers = g_list_prepend (new_layers, layer); } } - if (merge_list) - { - GimpLayer *layer; - const gchar *undo_desc = C_("undo-type", "Merge Visible Layers"); + gimp_image_set_selected_layers (image, new_layers); + gimp_image_undo_group_end (image); + gimp_unset_busy (image->gimp); - gimp_set_busy (image->gimp); + g_list_free (new_layers); + g_list_free (containers); - gimp_image_undo_group_start (image, - GIMP_UNDO_GROUP_IMAGE_LAYERS_MERGE, - undo_desc); - - /* if there's a floating selection, anchor it */ - if (gimp_image_get_floating_selection (image)) - floating_sel_anchor (gimp_image_get_floating_selection (image)); - - layer = gimp_image_merge_layers (image, - container, - merge_list, context, merge_type, - undo_desc, progress); - g_slist_free (merge_list); - - if (invisible_list) - { - GSList *list; - - for (list = invisible_list; list; list = g_slist_next (list)) - gimp_image_remove_layer (image, list->data, TRUE, NULL); - - g_slist_free (invisible_list); - } - - gimp_image_undo_group_end (image); - - gimp_unset_busy (image->gimp); - - return layer; - } - - return gimp_image_get_active_layer (image); + return gimp_image_get_selected_layers (image); } GimpLayer * diff --git a/app/core/gimpimage-merge.h b/app/core/gimpimage-merge.h index 93aab4e53a..de8e9297b6 100644 --- a/app/core/gimpimage-merge.h +++ b/app/core/gimpimage-merge.h @@ -19,7 +19,7 @@ #define __GIMP_IMAGE_MERGE_H__ -GimpLayer * gimp_image_merge_visible_layers (GimpImage *image, +GList * gimp_image_merge_visible_layers (GimpImage *image, GimpContext *context, GimpMergeType merge_type, gboolean merge_active_group, diff --git a/app/dialogs/image-merge-layers-dialog.c b/app/dialogs/image-merge-layers-dialog.c index 6ac115a44b..6426a9eee2 100644 --- a/app/dialogs/image-merge-layers-dialog.c +++ b/app/dialogs/image-merge-layers-dialog.c @@ -135,7 +135,7 @@ image_merge_layers_dialog_new (GimpImage *image, gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0); gtk_widget_show (frame); - button = gtk_check_button_new_with_mnemonic (_("Merge within active _group only")); + button = gtk_check_button_new_with_mnemonic (_("Merge within active _groups only")); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), private->merge_active_group); gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0); diff --git a/app/dialogs/preferences-dialog.c b/app/dialogs/preferences-dialog.c index 01d5305136..0fce63adc2 100644 --- a/app/dialogs/preferences-dialog.c +++ b/app/dialogs/preferences-dialog.c @@ -2353,7 +2353,7 @@ prefs_dialog_new (Gimp *gimp, GTK_GRID (grid), 0, size_group); prefs_check_button_add (object, "layer-merge-active-group-only", - _("Merge within active group only"), + _("Merge within active groups only"), GTK_BOX (vbox2)); prefs_check_button_add (object, "layer-merge-discard-invisible", _("Discard invisible layers"), diff --git a/app/file/file-open.c b/app/file/file-open.c index 86811673b0..5c3ba2b9a7 100644 --- a/app/file/file-open.c +++ b/app/file/file-open.c @@ -618,16 +618,13 @@ file_open_layers (Gimp *gimp, if (merge_visible && n_visible > 1) { - GimpLayer *layer; - g_list_free (layers); - layer = gimp_image_merge_visible_layers (new_image, context, - GIMP_CLIP_TO_IMAGE, - FALSE, FALSE, - NULL); - - layers = g_list_prepend (NULL, layer); + layers = gimp_image_merge_visible_layers (new_image, context, + GIMP_CLIP_TO_IMAGE, + FALSE, FALSE, + NULL); + layers = g_list_copy (layers); } if (layers) diff --git a/app/pdb/image-cmds.c b/app/pdb/image-cmds.c index aa4609af79..f64377aadc 100644 --- a/app/pdb/image-cmds.c +++ b/app/pdb/image-cmds.c @@ -1393,9 +1393,16 @@ image_merge_visible_layers_invoker (GimpProcedure *procedure, if (success) { - layer = gimp_image_merge_visible_layers (image, context, merge_type, - FALSE, FALSE, - progress); + GList *layers; + + layers = gimp_image_merge_visible_layers (image, context, merge_type, + FALSE, FALSE, progress); + + if (layers) + /* With merge_selected_groups set to FALSE, we always get only a + * single selected layer. + */ + layer = layers->data; if (! layer) success = FALSE; diff --git a/pdb/groups/image.pdb b/pdb/groups/image.pdb index 0d92af4ded..fa0064250e 100644 --- a/pdb/groups/image.pdb +++ b/pdb/groups/image.pdb @@ -737,9 +737,16 @@ HELP headers => [ qw("core/gimpimage-merge.h") ], code => <<'CODE' { - layer = gimp_image_merge_visible_layers (image, context, merge_type, - FALSE, FALSE, - progress); + GList *layers; + + layers = gimp_image_merge_visible_layers (image, context, merge_type, + FALSE, FALSE, progress); + + if (layers) + /* With merge_selected_groups set to FALSE, we always get only a + * single selected layer. + */ + layer = layers->data; if (! layer) success = FALSE;