mirror of
https://gitlab.gnome.org/GNOME/gimp.git
synced 2025-07-03 17:33:25 +00:00
app, pdb: layers-merge-layers* and image-merge-layers multi-layer aware.
Multi selection actually only really matter when "Merge within active groups only" option is checked, in which case we are able to merge layers within several layer groups simultaneously, and end up with multi-selected merged layers. Also not sure why both layers-merge-layers and image-merge-layers exist, as they are exactly the same (exact same callback called when activated).
This commit is contained in:
parent
0ae4686172
commit
5964f72cea
9 changed files with 130 additions and 88 deletions
|
@ -1040,7 +1040,7 @@ layers_actions_update (GimpActionGroup *group,
|
||||||
SET_SENSITIVE ("layers-merge-down-button", layer && !fs && !ac);
|
SET_SENSITIVE ("layers-merge-down-button", layer && !fs && !ac);
|
||||||
SET_VISIBLE ("layers-merge-group", children);
|
SET_VISIBLE ("layers-merge-group", children);
|
||||||
SET_SENSITIVE ("layers-merge-group", layer && !fs && !ac && 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_SENSITIVE ("layers-flatten-image", layer && !fs && !ac);
|
||||||
|
|
||||||
SET_VISIBLE ("layers-text-discard", text_layer && !ac);
|
SET_VISIBLE ("layers-text-discard", text_layer && !ac);
|
||||||
|
|
|
@ -388,7 +388,7 @@ gimp_dialog_config_class_init (GimpDialogConfigClass *klass)
|
||||||
|
|
||||||
GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_LAYER_MERGE_ACTIVE_GROUP_ONLY,
|
GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_LAYER_MERGE_ACTIVE_GROUP_ONLY,
|
||||||
"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,
|
LAYER_MERGE_ACTIVE_GROUP_ONLY_BLURB,
|
||||||
TRUE,
|
TRUE,
|
||||||
GIMP_PARAM_STATIC_STRINGS);
|
GIMP_PARAM_STATIC_STRINGS);
|
||||||
|
|
|
@ -66,7 +66,7 @@ static GimpLayer * gimp_image_merge_layers (GimpImage *image,
|
||||||
|
|
||||||
/* public functions */
|
/* public functions */
|
||||||
|
|
||||||
GimpLayer *
|
GList *
|
||||||
gimp_image_merge_visible_layers (GimpImage *image,
|
gimp_image_merge_visible_layers (GimpImage *image,
|
||||||
GimpContext *context,
|
GimpContext *context,
|
||||||
GimpMergeType merge_type,
|
GimpMergeType merge_type,
|
||||||
|
@ -74,10 +74,11 @@ gimp_image_merge_visible_layers (GimpImage *image,
|
||||||
gboolean discard_invisible,
|
gboolean discard_invisible,
|
||||||
GimpProgress *progress)
|
GimpProgress *progress)
|
||||||
{
|
{
|
||||||
GimpContainer *container;
|
const gchar *undo_desc = C_("undo-type", "Merge Visible Layers");
|
||||||
GList *list;
|
GList *containers = NULL;
|
||||||
GSList *merge_list = NULL;
|
GList *new_layers = NULL;
|
||||||
GSList *invisible_list = NULL;
|
GList *iter;
|
||||||
|
GList *iter2;
|
||||||
|
|
||||||
g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL);
|
g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL);
|
||||||
g_return_val_if_fail (GIMP_IS_CONTEXT (context), 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)
|
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
|
/* if the active layer is the floating selection, get the
|
||||||
* underlying drawable, but only if it is a layer
|
* 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;
|
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))
|
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
|
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)
|
gimp_image_set_selected_layers (image, new_layers);
|
||||||
{
|
gimp_image_undo_group_end (image);
|
||||||
GimpLayer *layer;
|
gimp_unset_busy (image->gimp);
|
||||||
const gchar *undo_desc = C_("undo-type", "Merge Visible Layers");
|
|
||||||
|
|
||||||
gimp_set_busy (image->gimp);
|
g_list_free (new_layers);
|
||||||
|
g_list_free (containers);
|
||||||
|
|
||||||
gimp_image_undo_group_start (image,
|
return gimp_image_get_selected_layers (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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GimpLayer *
|
GimpLayer *
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
#define __GIMP_IMAGE_MERGE_H__
|
#define __GIMP_IMAGE_MERGE_H__
|
||||||
|
|
||||||
|
|
||||||
GimpLayer * gimp_image_merge_visible_layers (GimpImage *image,
|
GList * gimp_image_merge_visible_layers (GimpImage *image,
|
||||||
GimpContext *context,
|
GimpContext *context,
|
||||||
GimpMergeType merge_type,
|
GimpMergeType merge_type,
|
||||||
gboolean merge_active_group,
|
gboolean merge_active_group,
|
||||||
|
|
|
@ -135,7 +135,7 @@ image_merge_layers_dialog_new (GimpImage *image,
|
||||||
gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
|
gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
|
||||||
gtk_widget_show (frame);
|
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),
|
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
|
||||||
private->merge_active_group);
|
private->merge_active_group);
|
||||||
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
|
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
|
||||||
|
|
|
@ -2353,7 +2353,7 @@ prefs_dialog_new (Gimp *gimp,
|
||||||
GTK_GRID (grid), 0, size_group);
|
GTK_GRID (grid), 0, size_group);
|
||||||
|
|
||||||
prefs_check_button_add (object, "layer-merge-active-group-only",
|
prefs_check_button_add (object, "layer-merge-active-group-only",
|
||||||
_("Merge within active group only"),
|
_("Merge within active groups only"),
|
||||||
GTK_BOX (vbox2));
|
GTK_BOX (vbox2));
|
||||||
prefs_check_button_add (object, "layer-merge-discard-invisible",
|
prefs_check_button_add (object, "layer-merge-discard-invisible",
|
||||||
_("Discard invisible layers"),
|
_("Discard invisible layers"),
|
||||||
|
|
|
@ -618,16 +618,13 @@ file_open_layers (Gimp *gimp,
|
||||||
|
|
||||||
if (merge_visible && n_visible > 1)
|
if (merge_visible && n_visible > 1)
|
||||||
{
|
{
|
||||||
GimpLayer *layer;
|
|
||||||
|
|
||||||
g_list_free (layers);
|
g_list_free (layers);
|
||||||
|
|
||||||
layer = gimp_image_merge_visible_layers (new_image, context,
|
layers = gimp_image_merge_visible_layers (new_image, context,
|
||||||
GIMP_CLIP_TO_IMAGE,
|
GIMP_CLIP_TO_IMAGE,
|
||||||
FALSE, FALSE,
|
FALSE, FALSE,
|
||||||
NULL);
|
NULL);
|
||||||
|
layers = g_list_copy (layers);
|
||||||
layers = g_list_prepend (NULL, layer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (layers)
|
if (layers)
|
||||||
|
|
|
@ -1393,9 +1393,16 @@ image_merge_visible_layers_invoker (GimpProcedure *procedure,
|
||||||
|
|
||||||
if (success)
|
if (success)
|
||||||
{
|
{
|
||||||
layer = gimp_image_merge_visible_layers (image, context, merge_type,
|
GList *layers;
|
||||||
FALSE, FALSE,
|
|
||||||
progress);
|
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)
|
if (! layer)
|
||||||
success = FALSE;
|
success = FALSE;
|
||||||
|
|
|
@ -737,9 +737,16 @@ HELP
|
||||||
headers => [ qw("core/gimpimage-merge.h") ],
|
headers => [ qw("core/gimpimage-merge.h") ],
|
||||||
code => <<'CODE'
|
code => <<'CODE'
|
||||||
{
|
{
|
||||||
layer = gimp_image_merge_visible_layers (image, context, merge_type,
|
GList *layers;
|
||||||
FALSE, FALSE,
|
|
||||||
progress);
|
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)
|
if (! layer)
|
||||||
success = FALSE;
|
success = FALSE;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue