mirror of https://github.com/GNOME/gimp.git
app: quick on-canvas copy-paste multi-layer aware.
This commit is contained in:
parent
bb7f94ce3b
commit
a7c59277fb
|
@ -35,6 +35,7 @@
|
||||||
#include "gimpdrawable-private.h"
|
#include "gimpdrawable-private.h"
|
||||||
#include "gimperror.h"
|
#include "gimperror.h"
|
||||||
#include "gimpimage.h"
|
#include "gimpimage.h"
|
||||||
|
#include "gimpimage-new.h"
|
||||||
#include "gimpimage-undo.h"
|
#include "gimpimage-undo.h"
|
||||||
#include "gimpimage-undo-push.h"
|
#include "gimpimage-undo-push.h"
|
||||||
#include "gimplayer.h"
|
#include "gimplayer.h"
|
||||||
|
@ -808,7 +809,7 @@ gimp_selection_extract (GimpSelection *selection,
|
||||||
|
|
||||||
GimpLayer *
|
GimpLayer *
|
||||||
gimp_selection_float (GimpSelection *selection,
|
gimp_selection_float (GimpSelection *selection,
|
||||||
GimpDrawable *drawable,
|
GList *drawables,
|
||||||
GimpContext *context,
|
GimpContext *context,
|
||||||
gboolean cut_image,
|
gboolean cut_image,
|
||||||
gint off_x,
|
gint off_x,
|
||||||
|
@ -817,22 +818,41 @@ gimp_selection_float (GimpSelection *selection,
|
||||||
{
|
{
|
||||||
GimpImage *image;
|
GimpImage *image;
|
||||||
GimpLayer *layer;
|
GimpLayer *layer;
|
||||||
|
GimpPickable *pickable;
|
||||||
GeglBuffer *buffer;
|
GeglBuffer *buffer;
|
||||||
GimpColorProfile *profile;
|
GimpColorProfile *profile;
|
||||||
|
GimpImage *temp_image = NULL;
|
||||||
|
const Babl *format = NULL;
|
||||||
|
GList *iter;
|
||||||
gint x1, y1;
|
gint x1, y1;
|
||||||
gint x2, y2;
|
gint x2, y2;
|
||||||
|
|
||||||
g_return_val_if_fail (GIMP_IS_SELECTION (selection), NULL);
|
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 (GIMP_IS_CONTEXT (context), NULL);
|
||||||
g_return_val_if_fail (error == NULL || *error == NULL, 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));
|
image = gimp_item_get_image (GIMP_ITEM (selection));
|
||||||
|
|
||||||
/* Make sure there is a region to float... */
|
/* Make sure there is a region to float... */
|
||||||
if (! gimp_item_mask_bounds (GIMP_ITEM (drawable), &x1, &y1, &x2, &y2) ||
|
for (iter = drawables; iter; iter = iter->next)
|
||||||
(x1 == x2 || y1 == y2))
|
{
|
||||||
|
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,
|
g_set_error_literal (error, GIMP_ERROR, GIMP_FAILED,
|
||||||
_("Cannot float selection because the selected "
|
_("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,
|
gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_FS_FLOAT,
|
||||||
C_("undo-type", "Float Selection"));
|
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 */
|
/* 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,
|
cut_image, FALSE, TRUE,
|
||||||
&x1, &y1, NULL);
|
&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 */
|
/* Clear the selection */
|
||||||
gimp_channel_clear (GIMP_CHANNEL (selection), NULL, TRUE);
|
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
|
* because it may be different from the image's type if we cut from
|
||||||
* a channel or layer mask
|
* a channel or layer mask
|
||||||
*/
|
*/
|
||||||
layer = gimp_layer_new_from_gegl_buffer (buffer, image,
|
layer = gimp_layer_new_from_gegl_buffer (buffer, image, format,
|
||||||
gimp_drawable_get_format_with_alpha (drawable),
|
|
||||||
_("Floated Layer"),
|
_("Floated Layer"),
|
||||||
GIMP_OPACITY_OPAQUE,
|
GIMP_OPACITY_OPAQUE,
|
||||||
gimp_image_get_default_new_layer_mode (image),
|
gimp_image_get_default_new_layer_mode (image),
|
||||||
|
@ -872,7 +901,7 @@ gimp_selection_float (GimpSelection *selection,
|
||||||
g_object_unref (buffer);
|
g_object_unref (buffer);
|
||||||
|
|
||||||
/* Add the floating layer to the image */
|
/* Add the floating layer to the image */
|
||||||
floating_sel_attach (layer, drawable);
|
floating_sel_attach (layer, drawables->data);
|
||||||
|
|
||||||
/* End an undo group */
|
/* End an undo group */
|
||||||
gimp_image_undo_group_end (image);
|
gimp_image_undo_group_end (image);
|
||||||
|
@ -880,5 +909,8 @@ gimp_selection_float (GimpSelection *selection,
|
||||||
/* invalidate the image's boundary variables */
|
/* invalidate the image's boundary variables */
|
||||||
GIMP_CHANNEL (selection)->boundary_known = FALSE;
|
GIMP_CHANNEL (selection)->boundary_known = FALSE;
|
||||||
|
|
||||||
|
if (temp_image)
|
||||||
|
g_object_unref (temp_image);
|
||||||
|
|
||||||
return layer;
|
return layer;
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,7 +65,7 @@ GeglBuffer * gimp_selection_extract (GimpSelection *selection,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
|
||||||
GimpLayer * gimp_selection_float (GimpSelection *selection,
|
GimpLayer * gimp_selection_float (GimpSelection *selection,
|
||||||
GimpDrawable *drawable,
|
GList *drawables,
|
||||||
GimpContext *context,
|
GimpContext *context,
|
||||||
gboolean cut_image,
|
gboolean cut_image,
|
||||||
gint off_x,
|
gint off_x,
|
||||||
|
|
|
@ -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_TO_LAYER:
|
||||||
case GIMP_TRANSLATE_MODE_MASK_COPY_TO_LAYER:
|
case GIMP_TRANSLATE_MODE_MASK_COPY_TO_LAYER:
|
||||||
if (! gimp_selection_float (GIMP_SELECTION (gimp_image_get_mask (image)),
|
if (! gimp_selection_float (GIMP_SELECTION (gimp_image_get_mask (image)),
|
||||||
GIMP_DRAWABLE (selected_items->data),
|
selected_items,
|
||||||
gimp_get_user_context (display->gimp),
|
gimp_get_user_context (display->gimp),
|
||||||
edit_select->edit_mode ==
|
edit_select->edit_mode ==
|
||||||
GIMP_TRANSLATE_MODE_MASK_TO_LAYER,
|
GIMP_TRANSLATE_MODE_MASK_TO_LAYER,
|
||||||
|
|
|
@ -225,7 +225,7 @@ gimp_selection_tool_oper_update (GimpTool *tool,
|
||||||
GimpSelectionTool *selection_tool = GIMP_SELECTION_TOOL (tool);
|
GimpSelectionTool *selection_tool = GIMP_SELECTION_TOOL (tool);
|
||||||
GimpSelectionOptions *options = GIMP_SELECTION_TOOL_GET_OPTIONS (tool);
|
GimpSelectionOptions *options = GIMP_SELECTION_TOOL_GET_OPTIONS (tool);
|
||||||
GimpImage *image;
|
GimpImage *image;
|
||||||
GimpDrawable *drawable;
|
GList *drawables;
|
||||||
GimpLayer *layer;
|
GimpLayer *layer;
|
||||||
GimpLayer *floating_sel;
|
GimpLayer *floating_sel;
|
||||||
GdkModifierType extend_mask;
|
GdkModifierType extend_mask;
|
||||||
|
@ -235,7 +235,7 @@ gimp_selection_tool_oper_update (GimpTool *tool,
|
||||||
gboolean move_floating_sel = FALSE;
|
gboolean move_floating_sel = FALSE;
|
||||||
|
|
||||||
image = gimp_display_get_image (display);
|
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);
|
layer = gimp_image_pick_layer (image, coords->x, coords->y, NULL);
|
||||||
floating_sel = gimp_image_get_floating_selection (image);
|
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);
|
have_selection = gimp_selection_tool_have_selection (selection_tool, display);
|
||||||
|
|
||||||
if (drawable)
|
if (drawables)
|
||||||
{
|
{
|
||||||
if (floating_sel)
|
if (floating_sel)
|
||||||
{
|
{
|
||||||
if (layer == floating_sel)
|
if (layer == floating_sel)
|
||||||
move_floating_sel = TRUE;
|
move_floating_sel = TRUE;
|
||||||
}
|
}
|
||||||
else if (have_selection &&
|
else if (have_selection)
|
||||||
gimp_item_mask_intersect (GIMP_ITEM (drawable),
|
|
||||||
NULL, NULL, NULL, NULL))
|
|
||||||
{
|
{
|
||||||
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;
|
selection_tool->function = SELECTION_SELECT;
|
||||||
|
@ -509,9 +519,8 @@ gimp_selection_tool_check (GimpSelectionTool *sel_tool,
|
||||||
GimpDisplay *display,
|
GimpDisplay *display,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
GimpSelectionOptions *options = GIMP_SELECTION_TOOL_GET_OPTIONS (sel_tool);
|
GimpSelectionOptions *options = GIMP_SELECTION_TOOL_GET_OPTIONS (sel_tool);
|
||||||
GimpImage *image = gimp_display_get_image (display);
|
GimpImage *image = gimp_display_get_image (display);
|
||||||
GimpDrawable *drawable = gimp_image_get_active_drawable (image);
|
|
||||||
|
|
||||||
switch (sel_tool->function)
|
switch (sel_tool->function)
|
||||||
{
|
{
|
||||||
|
@ -548,22 +557,34 @@ gimp_selection_tool_check (GimpSelectionTool *sel_tool,
|
||||||
|
|
||||||
case SELECTION_MOVE:
|
case SELECTION_MOVE:
|
||||||
case SELECTION_MOVE_COPY:
|
case SELECTION_MOVE_COPY:
|
||||||
if (gimp_viewable_get_children (GIMP_VIEWABLE (drawable)))
|
|
||||||
{
|
{
|
||||||
g_set_error (error, GIMP_ERROR, GIMP_FAILED,
|
GList *drawables = gimp_image_get_selected_drawables (image);
|
||||||
_("Cannot modify the pixels of layer groups."));
|
GList *iter;
|
||||||
|
|
||||||
return FALSE;
|
for (iter = drawables; iter; iter = iter->next)
|
||||||
}
|
{
|
||||||
else if (gimp_item_is_content_locked (GIMP_ITEM (drawable)))
|
if (gimp_viewable_get_children (iter->data))
|
||||||
{
|
{
|
||||||
g_set_error (error, GIMP_ERROR, GIMP_FAILED,
|
g_set_error (error, GIMP_ERROR, GIMP_FAILED,
|
||||||
_("The active layer's pixels are locked."));
|
_("Cannot modify the pixels of layer groups."));
|
||||||
|
|
||||||
if (error)
|
g_list_free (drawables);
|
||||||
gimp_tools_blink_lock_box (display->gimp, GIMP_ITEM (drawable));
|
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;
|
break;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue