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.
This commit is contained in:
parent
5cafcbe920
commit
955aecab92
6 changed files with 166 additions and 119 deletions
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 *
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in a new issue