app: quick on-canvas copy-paste multi-layer aware.

This commit is contained in:
Jehan 2020-05-17 23:00:07 +02:00
parent bb7f94ce3b
commit a7c59277fb
4 changed files with 88 additions and 35 deletions

View File

@ -35,6 +35,7 @@
#include "gimpdrawable-private.h"
#include "gimperror.h"
#include "gimpimage.h"
#include "gimpimage-new.h"
#include "gimpimage-undo.h"
#include "gimpimage-undo-push.h"
#include "gimplayer.h"
@ -808,7 +809,7 @@ gimp_selection_extract (GimpSelection *selection,
GimpLayer *
gimp_selection_float (GimpSelection *selection,
GimpDrawable *drawable,
GList *drawables,
GimpContext *context,
gboolean cut_image,
gint off_x,
@ -817,22 +818,41 @@ gimp_selection_float (GimpSelection *selection,
{
GimpImage *image;
GimpLayer *layer;
GimpPickable *pickable;
GeglBuffer *buffer;
GimpColorProfile *profile;
GimpImage *temp_image = NULL;
const Babl *format = NULL;
GList *iter;
gint x1, y1;
gint x2, y2;
g_return_val_if_fail (GIMP_IS_SELECTION (selection), NULL);
g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL);
g_return_val_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable)), NULL);
g_return_val_if_fail (GIMP_IS_CONTEXT (context), NULL);
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
for (iter = drawables; iter; iter = iter->next)
{
g_return_val_if_fail (GIMP_IS_DRAWABLE (iter->data), NULL);
g_return_val_if_fail (gimp_item_is_attached (iter->data), NULL);
if (! format)
format = gimp_drawable_get_format_with_alpha (iter->data);
else
g_return_val_if_fail (format == gimp_drawable_get_format_with_alpha (iter->data),
NULL);
}
image = gimp_item_get_image (GIMP_ITEM (selection));
/* Make sure there is a region to float... */
if (! gimp_item_mask_bounds (GIMP_ITEM (drawable), &x1, &y1, &x2, &y2) ||
(x1 == x2 || y1 == y2))
for (iter = drawables; iter; iter = iter->next)
{
if (gimp_item_mask_bounds (iter->data, &x1, &y1, &x2, &y2) &&
x1 != x2 && y1 != y2)
break;
}
if (iter == NULL)
{
g_set_error_literal (error, GIMP_ERROR, GIMP_FAILED,
_("Cannot float selection because the selected "
@ -844,22 +864,31 @@ gimp_selection_float (GimpSelection *selection,
gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_FS_FLOAT,
C_("undo-type", "Float Selection"));
if (g_list_length (drawables) > 1)
{
temp_image = gimp_image_new_from_drawables (image->gimp, drawables, TRUE);
pickable = GIMP_PICKABLE (temp_image);
}
else
{
pickable = GIMP_PICKABLE (drawables->data);
}
/* Cut or copy the selected region */
buffer = gimp_selection_extract (selection, GIMP_PICKABLE (drawable), context,
buffer = gimp_selection_extract (selection, pickable, context,
cut_image, FALSE, TRUE,
&x1, &y1, NULL);
profile = gimp_color_managed_get_color_profile (GIMP_COLOR_MANAGED (drawable));
profile = gimp_color_managed_get_color_profile (GIMP_COLOR_MANAGED (pickable));
/* Clear the selection */
gimp_channel_clear (GIMP_CHANNEL (selection), NULL, TRUE);
/* Create a new layer from the buffer, using the drawable's type
/* Create a new layer from the buffer, using the drawables' type
* because it may be different from the image's type if we cut from
* a channel or layer mask
*/
layer = gimp_layer_new_from_gegl_buffer (buffer, image,
gimp_drawable_get_format_with_alpha (drawable),
layer = gimp_layer_new_from_gegl_buffer (buffer, image, format,
_("Floated Layer"),
GIMP_OPACITY_OPAQUE,
gimp_image_get_default_new_layer_mode (image),
@ -872,7 +901,7 @@ gimp_selection_float (GimpSelection *selection,
g_object_unref (buffer);
/* Add the floating layer to the image */
floating_sel_attach (layer, drawable);
floating_sel_attach (layer, drawables->data);
/* End an undo group */
gimp_image_undo_group_end (image);
@ -880,5 +909,8 @@ gimp_selection_float (GimpSelection *selection,
/* invalidate the image's boundary variables */
GIMP_CHANNEL (selection)->boundary_known = FALSE;
if (temp_image)
g_object_unref (temp_image);
return layer;
}

View File

@ -65,7 +65,7 @@ GeglBuffer * gimp_selection_extract (GimpSelection *selection,
GError **error);
GimpLayer * gimp_selection_float (GimpSelection *selection,
GimpDrawable *drawable,
GList *drawables,
GimpContext *context,
gboolean cut_image,
gint off_x,

View File

@ -595,7 +595,7 @@ gimp_edit_selection_tool_update_motion (GimpEditSelectionTool *edit_select,
case GIMP_TRANSLATE_MODE_MASK_TO_LAYER:
case GIMP_TRANSLATE_MODE_MASK_COPY_TO_LAYER:
if (! gimp_selection_float (GIMP_SELECTION (gimp_image_get_mask (image)),
GIMP_DRAWABLE (selected_items->data),
selected_items,
gimp_get_user_context (display->gimp),
edit_select->edit_mode ==
GIMP_TRANSLATE_MODE_MASK_TO_LAYER,

View File

@ -225,7 +225,7 @@ gimp_selection_tool_oper_update (GimpTool *tool,
GimpSelectionTool *selection_tool = GIMP_SELECTION_TOOL (tool);
GimpSelectionOptions *options = GIMP_SELECTION_TOOL_GET_OPTIONS (tool);
GimpImage *image;
GimpDrawable *drawable;
GList *drawables;
GimpLayer *layer;
GimpLayer *floating_sel;
GdkModifierType extend_mask;
@ -235,7 +235,7 @@ gimp_selection_tool_oper_update (GimpTool *tool,
gboolean move_floating_sel = FALSE;
image = gimp_display_get_image (display);
drawable = gimp_image_get_active_drawable (image);
drawables = gimp_image_get_selected_drawables (image);
layer = gimp_image_pick_layer (image, coords->x, coords->y, NULL);
floating_sel = gimp_image_get_floating_selection (image);
@ -244,19 +244,29 @@ gimp_selection_tool_oper_update (GimpTool *tool,
have_selection = gimp_selection_tool_have_selection (selection_tool, display);
if (drawable)
if (drawables)
{
if (floating_sel)
{
if (layer == floating_sel)
move_floating_sel = TRUE;
}
else if (have_selection &&
gimp_item_mask_intersect (GIMP_ITEM (drawable),
NULL, NULL, NULL, NULL))
else if (have_selection)
{
move_layer = TRUE;
GList *iter;
for (iter = drawables; iter; iter = iter->next)
{
if (gimp_item_mask_intersect (GIMP_ITEM (iter->data),
NULL, NULL, NULL, NULL))
{
move_layer = TRUE;
break;
}
}
}
g_list_free (drawables);
}
selection_tool->function = SELECTION_SELECT;
@ -509,9 +519,8 @@ gimp_selection_tool_check (GimpSelectionTool *sel_tool,
GimpDisplay *display,
GError **error)
{
GimpSelectionOptions *options = GIMP_SELECTION_TOOL_GET_OPTIONS (sel_tool);
GimpImage *image = gimp_display_get_image (display);
GimpDrawable *drawable = gimp_image_get_active_drawable (image);
GimpSelectionOptions *options = GIMP_SELECTION_TOOL_GET_OPTIONS (sel_tool);
GimpImage *image = gimp_display_get_image (display);
switch (sel_tool->function)
{
@ -548,22 +557,34 @@ gimp_selection_tool_check (GimpSelectionTool *sel_tool,
case SELECTION_MOVE:
case SELECTION_MOVE_COPY:
if (gimp_viewable_get_children (GIMP_VIEWABLE (drawable)))
{
g_set_error (error, GIMP_ERROR, GIMP_FAILED,
_("Cannot modify the pixels of layer groups."));
GList *drawables = gimp_image_get_selected_drawables (image);
GList *iter;
return FALSE;
}
else if (gimp_item_is_content_locked (GIMP_ITEM (drawable)))
{
g_set_error (error, GIMP_ERROR, GIMP_FAILED,
_("The active layer's pixels are locked."));
for (iter = drawables; iter; iter = iter->next)
{
if (gimp_viewable_get_children (iter->data))
{
g_set_error (error, GIMP_ERROR, GIMP_FAILED,
_("Cannot modify the pixels of layer groups."));
if (error)
gimp_tools_blink_lock_box (display->gimp, GIMP_ITEM (drawable));
g_list_free (drawables);
return FALSE;
}
else if (gimp_item_is_content_locked (iter->data))
{
g_set_error (error, GIMP_ERROR, GIMP_FAILED,
_("The active layer's pixels are locked."));
return FALSE;
if (error)
gimp_tools_blink_lock_box (display->gimp, iter->data);
g_list_free (drawables);
return FALSE;
}
}
g_list_free (drawables);
}
break;