[gimp] Bug 637313 - Should be possible to copy/paste whole layers in a single step
- From: Michael Natterer <mitch src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] Bug 637313 - Should be possible to copy/paste whole layers in a single step
- Date: Mon, 19 Sep 2016 22:34:50 +0000 (UTC)
commit 67863dabf92e45ac5bda18c814e893f55d62cc9a
Author: Michael Natterer <mitch gimp org>
Date: Mon Sep 19 23:53:40 2016 +0200
Bug 637313 - Should be possible to copy/paste whole layers in a single step
Use the newly added clipboard for entire images to copy/paste layers
(we only create single-layer clipboard images, and use only the first
layer of any recieved image, the layers can be arbitrarily complex
though):
- change gimp_edit_copy,cut,paste() to return/take a GimpObject
that can be a GimpImage or GimpBuffer
- cut/copy the whole layer if there is no selection
- always paste layers as new layers, not floating selections
- always paste news layers on top of the active layer, where
we would attach a floating selection
- add enum GimpPasteType { FLOATING, FLOATING_INTO, NEW_LAYER }
- add GimpPasteType parameter to gimp_edit_paste() and handle all
three cases there because there is now a lot of common code
involved
- change all callers accordingly, use only legacy buffer pasting
from the PDB for now
app/actions/buffers-commands.c | 11 +-
app/actions/edit-commands.c | 291 +++++++++++++++++-------------------
app/core/core-enums.c | 31 ++++
app/core/core-enums.h | 12 ++
app/core/gimp-edit.c | 180 ++++++++++++++++-------
app/core/gimp-edit.h | 8 +-
app/display/gimpdisplayshell-dnd.c | 24 ++-
app/pdb/edit-cmds.c | 14 ++-
tools/pdbgen/pdb/edit.pdb | 14 ++-
9 files changed, 348 insertions(+), 237 deletions(-)
---
diff --git a/app/actions/buffers-commands.c b/app/actions/buffers-commands.c
index d21c5cb..813e1c1 100644
--- a/app/actions/buffers-commands.c
+++ b/app/actions/buffers-commands.c
@@ -47,7 +47,7 @@
/* local function prototypes */
static void buffers_paste (GimpBufferView *view,
- gboolean paste_into);
+ GimpPasteType paste_type);
/* public functionss */
@@ -56,14 +56,14 @@ void
buffers_paste_cmd_callback (GtkAction *action,
gpointer data)
{
- buffers_paste (GIMP_BUFFER_VIEW (data), FALSE);
+ buffers_paste (GIMP_BUFFER_VIEW (data), GIMP_PASTE_TYPE_FLOATING);
}
void
buffers_paste_into_cmd_callback (GtkAction *action,
gpointer data)
{
- buffers_paste (GIMP_BUFFER_VIEW (data), TRUE);
+ buffers_paste (GIMP_BUFFER_VIEW (data), GIMP_PASTE_TYPE_FLOATING_INTO);
}
void
@@ -108,7 +108,7 @@ buffers_delete_cmd_callback (GtkAction *action,
static void
buffers_paste (GimpBufferView *view,
- gboolean paste_into)
+ GimpPasteType paste_type)
{
GimpContainerEditor *editor = GIMP_CONTAINER_EDITOR (view);
GimpContainer *container;
@@ -146,7 +146,8 @@ buffers_paste (GimpBufferView *view,
if (image)
{
gimp_edit_paste (image, gimp_image_get_active_drawable (image),
- buffer, paste_into, x, y, width, height);
+ GIMP_OBJECT (buffer), paste_type,
+ x, y, width, height);
gimp_image_flush (image);
}
diff --git a/app/actions/edit-commands.c b/app/actions/edit-commands.c
index 6372022..f571775 100644
--- a/app/actions/edit-commands.c
+++ b/app/actions/edit-commands.c
@@ -36,6 +36,7 @@
#include "core/gimplayer.h"
#include "core/gimplayer-new.h"
#include "core/gimpimage.h"
+#include "core/gimpimage-duplicate.h"
#include "core/gimpimage-new.h"
#include "core/gimpimage-undo.h"
@@ -65,17 +66,18 @@
/* local function prototypes */
-static void edit_paste (GimpDisplay *display,
- gboolean paste_into);
-static void cut_named_buffer_callback (GtkWidget *widget,
- const gchar *name,
- gpointer data);
-static void copy_named_buffer_callback (GtkWidget *widget,
- const gchar *name,
- gpointer data);
-static void copy_named_visible_buffer_callback (GtkWidget *widget,
- const gchar *name,
- gpointer data);
+static void edit_paste (GimpDisplay *display,
+ GimpPasteType paste_into,
+ gboolean try_svg);
+static void cut_named_buffer_callback (GtkWidget *widget,
+ const gchar *name,
+ gpointer data);
+static void copy_named_buffer_callback (GtkWidget *widget,
+ const gchar *name,
+ gpointer data);
+static void copy_named_visible_buffer_callback (GtkWidget *widget,
+ const gchar *name,
+ gpointer data);
/* public functions */
@@ -229,17 +231,23 @@ edit_cut_cmd_callback (GtkAction *action,
{
GimpImage *image;
GimpDrawable *drawable;
+ GimpObject *cut;
GError *error = NULL;
return_if_no_drawable (image, drawable, data);
- if (gimp_edit_cut (image, drawable, action_data_get_context (data), &error))
+ cut = gimp_edit_cut (image, drawable, action_data_get_context (data),
+ &error);
+
+ if (cut)
{
GimpDisplay *display = action_data_get_display (data);
if (display)
gimp_message_literal (image->gimp,
G_OBJECT (display), GIMP_MESSAGE_INFO,
- _("Cut pixels to the clipboard"));
+ GIMP_IS_IMAGE (cut) ?
+ _("Cut layer to the clipboard.") :
+ _("Cut pixels to the clipboard."));
gimp_image_flush (image);
}
@@ -259,17 +267,23 @@ edit_copy_cmd_callback (GtkAction *action,
{
GimpImage *image;
GimpDrawable *drawable;
+ GimpObject *copy;
GError *error = NULL;
return_if_no_drawable (image, drawable, data);
- if (gimp_edit_copy (image, drawable, action_data_get_context (data), &error))
+ copy = gimp_edit_copy (image, drawable, action_data_get_context (data),
+ &error);
+
+ if (copy)
{
GimpDisplay *display = action_data_get_display (data);
if (display)
gimp_message_literal (image->gimp,
G_OBJECT (display), GIMP_MESSAGE_INFO,
- _("Copied pixels to the clipboard"));
+ GIMP_IS_IMAGE (copy) ?
+ _("Copied layer to the clipboard.") :
+ _("Copied pixels to the clipboard."));
gimp_image_flush (image);
}
@@ -298,7 +312,7 @@ edit_copy_visible_cmd_callback (GtkAction *action,
if (display)
gimp_message_literal (image->gimp,
G_OBJECT (display), GIMP_MESSAGE_INFO,
- _("Copied pixels to the clipboard"));
+ _("Copied pixels to the clipboard."));
gimp_image_flush (image);
}
@@ -320,31 +334,7 @@ edit_paste_cmd_callback (GtkAction *action,
if (display && gimp_display_get_image (display))
{
- GimpImage *image = gimp_display_get_image (display);
- GimpDrawable *drawable = gimp_image_get_active_drawable (image);;
-
- if (drawable && gimp_viewable_get_children (GIMP_VIEWABLE (drawable)))
- {
- gimp_message_literal (display->gimp, G_OBJECT (display),
- GIMP_MESSAGE_INFO,
- _("Pasting as new layer because the "
- "target is a group layer."));
-
- edit_paste_as_new_layer_cmd_callback (action, data);
- }
- else if (drawable && gimp_item_is_content_locked (GIMP_ITEM (drawable)))
- {
- gimp_message_literal (display->gimp, G_OBJECT (display),
- GIMP_MESSAGE_INFO,
- _("Pasting as new layer because the "
- "target's pixels are locked."));
-
- edit_paste_as_new_layer_cmd_callback (action, data);
- }
- else
- {
- edit_paste (display, FALSE);
- }
+ edit_paste (display, GIMP_PASTE_TYPE_FLOATING, TRUE);
}
else
{
@@ -356,36 +346,10 @@ void
edit_paste_into_cmd_callback (GtkAction *action,
gpointer data)
{
- GimpImage *image;
- GimpDisplay *display;
- GimpDrawable *drawable;
- return_if_no_image (image, data);
+ GimpDisplay *display;
return_if_no_display (display, data);
- drawable = gimp_image_get_active_drawable (image);;
-
- if (drawable && gimp_viewable_get_children (GIMP_VIEWABLE (drawable)))
- {
- gimp_message_literal (display->gimp, G_OBJECT (display),
- GIMP_MESSAGE_INFO,
- _("Pasting as new layer because the "
- "target is a group layer."));
-
- edit_paste_as_new_layer_cmd_callback (action, data);
- }
- else if (drawable && gimp_item_is_content_locked (GIMP_ITEM (drawable)))
- {
- gimp_message_literal (display->gimp, G_OBJECT (display),
- GIMP_MESSAGE_INFO,
- _("Pasting as new layer because the "
- "target's pixels are locked."));
-
- edit_paste_as_new_layer_cmd_callback (action, data);
- }
- else
- {
- edit_paste (display, TRUE);
- }
+ edit_paste (display, GIMP_PASTE_TYPE_FLOATING_INTO, TRUE);
}
void
@@ -393,30 +357,44 @@ edit_paste_as_new_image_cmd_callback (GtkAction *action,
gpointer data)
{
Gimp *gimp;
- GimpBuffer *buffer;
+ GimpImage *image;
+ GimpImage *new_image = NULL;
GtkWidget *widget;
return_if_no_gimp (gimp, data);
return_if_no_widget (widget, data);
- buffer = gimp_clipboard_get_buffer (gimp);
+ image = gimp_clipboard_get_image (gimp);
- if (buffer)
+ if (image)
+ {
+ new_image = gimp_image_duplicate (image);
+ g_object_unref (image);
+ }
+ else
{
- GimpImage *image;
+ GimpBuffer *buffer = gimp_clipboard_get_buffer (gimp);
- image = gimp_image_new_from_buffer (gimp, action_data_get_image (data),
- buffer);
- g_object_unref (buffer);
+ if (buffer)
+ {
+ new_image = gimp_image_new_from_buffer (gimp,
+ action_data_get_image (data),
+ buffer);
+ g_object_unref (buffer);
+ }
+ }
- gimp_create_display (image->gimp, image, GIMP_UNIT_PIXEL, 1.0,
+ if (new_image)
+ {
+ gimp_create_display (gimp, new_image, GIMP_UNIT_PIXEL, 1.0,
G_OBJECT (gtk_widget_get_screen (widget)),
gimp_widget_get_monitor (widget));
- g_object_unref (image);
+ g_object_unref (new_image);
}
else
{
gimp_message_literal (gimp, NULL, GIMP_MESSAGE_WARNING,
- _("There is no image data in the clipboard to paste."));
+ _("There is no image data in the clipboard "
+ "to paste."));
}
}
@@ -424,54 +402,10 @@ void
edit_paste_as_new_layer_cmd_callback (GtkAction *action,
gpointer data)
{
- Gimp *gimp;
- GimpImage *image;
GimpDisplay *display;
- GimpBuffer *buffer;
- return_if_no_gimp (gimp, data);
- return_if_no_image (image, data);
return_if_no_display (display, data);
- buffer = gimp_clipboard_get_buffer (gimp);
-
- if (buffer)
- {
- GimpLayer *layer;
- gint x, y;
- gint width, height;
- gint offset_x;
- gint offset_y;
-
- layer = gimp_layer_new_from_buffer (buffer, image,
- gimp_image_get_layer_format (image,
- TRUE),
- _("Clipboard"),
- GIMP_OPACITY_OPAQUE,
- GIMP_NORMAL_MODE);
- g_object_unref (buffer);
-
- gimp_display_shell_untransform_viewport (gimp_display_get_shell (display),
- &x, &y, &width, &height);
-
- gimp_edit_get_paste_offset (image,
- gimp_image_get_active_drawable (image),
- GIMP_OBJECT (buffer),
- x, y, width, height,
- &offset_x,
- &offset_y);
-
- gimp_item_set_offset (GIMP_ITEM (layer), offset_x, offset_y);
-
- gimp_image_add_layer (image, layer,
- GIMP_IMAGE_ACTIVE_PARENT, -1, TRUE);
-
- gimp_image_flush (image);
- }
- else
- {
- gimp_message_literal (gimp, NULL, GIMP_MESSAGE_WARNING,
- _("There is no image data in the clipboard to paste."));
- }
+ edit_paste (display, GIMP_PASTE_TYPE_NEW_LAYER, FALSE);
}
void
@@ -600,57 +534,100 @@ edit_fill_cmd_callback (GtkAction *action,
/* private functions */
static void
-edit_paste (GimpDisplay *display,
- gboolean paste_into)
+edit_paste (GimpDisplay *display,
+ GimpPasteType paste_type,
+ gboolean try_svg)
{
- GimpImage *image = gimp_display_get_image (display);
- gchar *svg;
- gsize svg_size;
-
- svg = gimp_clipboard_get_svg (display->gimp, &svg_size);
+ GimpImage *image = gimp_display_get_image (display);
+ GimpObject *paste;
- if (svg)
+ if (try_svg)
{
- if (gimp_vectors_import_buffer (image, svg, svg_size,
- TRUE, FALSE,
- GIMP_IMAGE_ACTIVE_PARENT, -1,
- NULL, NULL))
+ gchar *svg;
+ gsize svg_size;
+
+ svg = gimp_clipboard_get_svg (display->gimp, &svg_size);
+
+ if (svg)
{
- gimp_image_flush (image);
+ if (gimp_vectors_import_buffer (image, svg, svg_size,
+ TRUE, FALSE,
+ GIMP_IMAGE_ACTIVE_PARENT, -1,
+ NULL, NULL))
+ {
+ gimp_image_flush (image);
+ }
+
+ g_free (svg);
+
+ return;
}
+ }
- g_free (svg);
+ paste = GIMP_OBJECT (gimp_clipboard_get_image (display->gimp));
+
+ if (paste)
+ {
+ if (paste_type != GIMP_PASTE_TYPE_NEW_LAYER)
+ {
+ gimp_message_literal (display->gimp, G_OBJECT (display),
+ GIMP_MESSAGE_INFO,
+ _("Pasted as new layer because "
+ "there was a layer the clipboard."));
+
+ paste_type = GIMP_PASTE_TYPE_NEW_LAYER;
+ }
}
else
{
- GimpBuffer *buffer;
+ paste = GIMP_OBJECT (gimp_clipboard_get_buffer (display->gimp));
+ }
- buffer = gimp_clipboard_get_buffer (display->gimp);
+ if (paste)
+ {
+ GimpDisplayShell *shell = gimp_display_get_shell (display);
+ GimpDrawable *drawable = gimp_image_get_active_drawable (image);
+ gint x, y;
+ gint width, height;
- if (buffer)
+ if (drawable)
{
- GimpDisplayShell *shell = gimp_display_get_shell (display);
- gint x, y;
- gint width, height;
-
- gimp_display_shell_untransform_viewport (shell,
- &x, &y, &width, &height);
-
- if (gimp_edit_paste (image,
- gimp_image_get_active_drawable (image),
- buffer, paste_into, x, y, width, height))
+ if (gimp_viewable_get_children (GIMP_VIEWABLE (drawable)))
{
- gimp_image_flush (image);
+ gimp_message_literal (display->gimp, G_OBJECT (display),
+ GIMP_MESSAGE_INFO,
+ _("Pasted as new layer because the "
+ "target is a layer group."));
+
+ paste_type = GIMP_PASTE_TYPE_NEW_LAYER;
}
+ else if (gimp_item_is_content_locked (GIMP_ITEM (drawable)))
+ {
+ gimp_message_literal (display->gimp, G_OBJECT (display),
+ GIMP_MESSAGE_INFO,
+ _("Pasted as new layer because the "
+ "target's pixels are locked."));
- g_object_unref (buffer);
+ paste_type = GIMP_PASTE_TYPE_NEW_LAYER;
+ }
}
- else
+
+ gimp_display_shell_untransform_viewport (shell, &x, &y, &width, &height);
+
+ if (gimp_edit_paste (image, drawable, paste,
+ paste_type, x, y, width, height))
{
- gimp_message_literal (display->gimp, G_OBJECT (display),
- GIMP_MESSAGE_WARNING,
- _("There is no image data in the clipboard to paste."));
+ gimp_image_flush (image);
}
+
+ g_object_unref (paste);
+ }
+ else
+ {
+ gimp_message_literal (display->gimp, G_OBJECT (display),
+ GIMP_MESSAGE_WARNING,
+ _("There is no image data in the clipboard "
+ "to paste."));
}
}
diff --git a/app/core/core-enums.c b/app/core/core-enums.c
index 157a93b..4725723 100644
--- a/app/core/core-enums.c
+++ b/app/core/core-enums.c
@@ -401,6 +401,37 @@ gimp_matting_engine_get_type (void)
}
GType
+gimp_paste_type_get_type (void)
+{
+ static const GEnumValue values[] =
+ {
+ { GIMP_PASTE_TYPE_FLOATING, "GIMP_PASTE_TYPE_FLOATING", "floating" },
+ { GIMP_PASTE_TYPE_FLOATING_INTO, "GIMP_PASTE_TYPE_FLOATING_INTO", "floating-into" },
+ { GIMP_PASTE_TYPE_NEW_LAYER, "GIMP_PASTE_TYPE_NEW_LAYER", "new-layer" },
+ { 0, NULL, NULL }
+ };
+
+ static const GimpEnumDesc descs[] =
+ {
+ { GIMP_PASTE_TYPE_FLOATING, "GIMP_PASTE_TYPE_FLOATING", NULL },
+ { GIMP_PASTE_TYPE_FLOATING_INTO, "GIMP_PASTE_TYPE_FLOATING_INTO", NULL },
+ { GIMP_PASTE_TYPE_NEW_LAYER, "GIMP_PASTE_TYPE_NEW_LAYER", NULL },
+ { 0, NULL, NULL }
+ };
+
+ static GType type = 0;
+
+ if (G_UNLIKELY (! type))
+ {
+ type = g_enum_register_static ("GimpPasteType", values);
+ gimp_type_set_translation_context (type, "paste-type");
+ gimp_enum_set_value_descriptions (type, descs);
+ }
+
+ return type;
+}
+
+GType
gimp_alignment_type_get_type (void)
{
static const GEnumValue values[] =
diff --git a/app/core/core-enums.h b/app/core/core-enums.h
index 49ce8d1..96c837f 100644
--- a/app/core/core-enums.h
+++ b/app/core/core-enums.h
@@ -201,6 +201,18 @@ typedef enum /*< pdb-skip >*/
} GimpMattingEngine;
+#define GIMP_TYPE_PASTE_TYPE (gimp_paste_type_get_type ())
+
+GType gimp_paste_type_get_type (void) G_GNUC_CONST;
+
+typedef enum /*< pdb-skip >*/
+{
+ GIMP_PASTE_TYPE_FLOATING,
+ GIMP_PASTE_TYPE_FLOATING_INTO,
+ GIMP_PASTE_TYPE_NEW_LAYER
+} GimpPasteType;
+
+
#define GIMP_TYPE_ALIGNMENT_TYPE (gimp_alignment_type_get_type ())
GType gimp_alignment_type_get_type (void) G_GNUC_CONST;
diff --git a/app/core/gimp-edit.c b/app/core/gimp-edit.c
index 034b291..4430772 100644
--- a/app/core/gimp-edit.c
+++ b/app/core/gimp-edit.c
@@ -39,6 +39,7 @@
#include "gimpfilloptions.h"
#include "gimpdrawableundo.h"
#include "gimpimage.h"
+#include "gimpimage-new.h"
#include "gimpimage-undo.h"
#include "gimplayer.h"
#include "gimplayer-floating-selection.h"
@@ -62,57 +63,95 @@ static GimpBuffer * gimp_edit_extract (GimpImage *image,
/* public functions */
-GimpBuffer *
+GimpObject *
gimp_edit_cut (GimpImage *image,
GimpDrawable *drawable,
GimpContext *context,
GError **error)
{
- GimpBuffer *buffer;
-
g_return_val_if_fail (GIMP_IS_IMAGE (image), 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);
- buffer = gimp_edit_extract (image, GIMP_PICKABLE (drawable),
- context, TRUE, error);
+ if (GIMP_IS_LAYER (drawable) &&
+ gimp_channel_is_empty (gimp_image_get_mask (image)))
+ {
+ GimpImage *clip_image;
- if (buffer)
+ clip_image = gimp_image_new_from_drawable (image->gimp, drawable);
+ gimp_container_remove (image->gimp->images, GIMP_OBJECT (clip_image));
+ gimp_set_clipboard_image (image->gimp, clip_image);
+ g_object_unref (clip_image);
+
+ gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_EDIT_CUT,
+ C_("undo-type", "Cut Layer"));
+
+ gimp_image_remove_layer (image, GIMP_LAYER (drawable),
+ TRUE, NULL);
+
+ gimp_image_undo_group_end (image);
+
+ return GIMP_OBJECT (gimp_get_clipboard_image (image->gimp));
+ }
+ else
{
- gimp_set_clipboard_buffer (image->gimp, buffer);
- g_object_unref (buffer);
+ GimpBuffer *buffer;
- return gimp_get_clipboard_buffer (image->gimp);
+ buffer = gimp_edit_extract (image, GIMP_PICKABLE (drawable),
+ context, TRUE, error);
+
+ if (buffer)
+ {
+ gimp_set_clipboard_buffer (image->gimp, buffer);
+ g_object_unref (buffer);
+
+ return GIMP_OBJECT (gimp_get_clipboard_buffer (image->gimp));
+ }
}
return NULL;
}
-GimpBuffer *
+GimpObject *
gimp_edit_copy (GimpImage *image,
GimpDrawable *drawable,
GimpContext *context,
GError **error)
{
- GimpBuffer *buffer;
-
g_return_val_if_fail (GIMP_IS_IMAGE (image), 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);
- buffer = gimp_edit_extract (image, GIMP_PICKABLE (drawable),
- context, FALSE, error);
+ if (GIMP_IS_LAYER (drawable) &&
+ gimp_channel_is_empty (gimp_image_get_mask (image)))
+ {
+ GimpImage *clip_image;
- if (buffer)
+ clip_image = gimp_image_new_from_drawable (image->gimp, drawable);
+ gimp_container_remove (image->gimp->images, GIMP_OBJECT (clip_image));
+ gimp_set_clipboard_image (image->gimp, clip_image);
+ g_object_unref (clip_image);
+
+ return GIMP_OBJECT (gimp_get_clipboard_image (image->gimp));
+ }
+ else
{
- gimp_set_clipboard_buffer (image->gimp, buffer);
- g_object_unref (buffer);
+ GimpBuffer *buffer;
- return gimp_get_clipboard_buffer (image->gimp);
+ buffer = gimp_edit_extract (image, GIMP_PICKABLE (drawable),
+ context, FALSE, error);
+
+ if (buffer)
+ {
+ gimp_set_clipboard_buffer (image->gimp, buffer);
+ g_object_unref (buffer);
+
+ return GIMP_OBJECT (gimp_get_clipboard_buffer (image->gimp));
+ }
}
return NULL;
@@ -262,39 +301,48 @@ gimp_edit_get_paste_offset (GimpImage *image,
}
GimpLayer *
-gimp_edit_paste (GimpImage *image,
- GimpDrawable *drawable,
- GimpBuffer *paste,
- gboolean paste_into,
- gint viewport_x,
- gint viewport_y,
- gint viewport_width,
- gint viewport_height)
+gimp_edit_paste (GimpImage *image,
+ GimpDrawable *drawable,
+ GimpObject *paste,
+ GimpPasteType paste_type,
+ gint viewport_x,
+ gint viewport_y,
+ gint viewport_width,
+ gint viewport_height)
{
- GimpLayer *layer;
- const Babl *format;
- gint offset_x;
- gint offset_y;
+ GimpLayer *layer;
+ gint offset_x;
+ gint offset_y;
g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL);
g_return_val_if_fail (drawable == NULL || GIMP_IS_DRAWABLE (drawable), NULL);
g_return_val_if_fail (drawable == NULL ||
gimp_item_is_attached (GIMP_ITEM (drawable)), NULL);
- g_return_val_if_fail (GIMP_IS_BUFFER (paste), NULL);
+ g_return_val_if_fail (GIMP_IS_IMAGE (paste) || GIMP_IS_BUFFER (paste), NULL);
- /* Make a new layer: if drawable == NULL,
- * user is pasting into an empty image.
- */
+ if (GIMP_IS_IMAGE (paste))
+ {
+ layer = gimp_image_get_layer_iter (GIMP_IMAGE (paste))->data;
- if (drawable)
- format = gimp_drawable_get_format_with_alpha (drawable);
+ layer = GIMP_LAYER (gimp_item_convert (GIMP_ITEM (layer),
+ image,
+ G_TYPE_FROM_INSTANCE (layer)));
+ }
else
- format = gimp_image_get_layer_format (image, TRUE);
+ {
+ const Babl *format;
+
+ /* If drawable == NULL, user is pasting into an empty image */
+ if (drawable)
+ format = gimp_drawable_get_format_with_alpha (drawable);
+ else
+ format = gimp_image_get_layer_format (image, TRUE);
- layer = gimp_layer_new_from_buffer (paste, image,
- format,
- _("Pasted Layer"),
- GIMP_OPACITY_OPAQUE, GIMP_NORMAL_MODE);
+ layer = gimp_layer_new_from_buffer (GIMP_BUFFER (paste), image,
+ format,
+ _("Pasted Layer"),
+ GIMP_OPACITY_OPAQUE, GIMP_NORMAL_MODE);
+ }
if (! layer)
return NULL;
@@ -309,24 +357,48 @@ gimp_edit_paste (GimpImage *image,
gimp_item_set_offset (GIMP_ITEM (layer), offset_x, offset_y);
- /* Start a group undo */
+ /* change paste type to NEW_LAYER for cases where we can't attach
+ * a floating selection
+ */
+ if (GIMP_IS_IMAGE (paste) ||
+ ! drawable ||
+ gimp_viewable_get_children (GIMP_VIEWABLE (drawable)) ||
+ gimp_item_is_content_locked (GIMP_ITEM (drawable)))
+ {
+ paste_type = GIMP_PASTE_TYPE_NEW_LAYER;
+ }
+
gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_EDIT_PASTE,
C_("undo-type", "Paste"));
- /* If there is a selection mask clear it--
- * this might not always be desired, but in general,
- * it seems like the correct behavior.
- */
- if (! gimp_channel_is_empty (gimp_image_get_mask (image)) && ! paste_into)
- gimp_channel_clear (gimp_image_get_mask (image), NULL, TRUE);
+ switch (paste_type)
+ {
+ case GIMP_PASTE_TYPE_FLOATING:
+ /* If there is a selection mask clear it--
+ * this might not always be desired, but in general,
+ * it seems like the correct behavior.
+ */
+ if (! gimp_channel_is_empty (gimp_image_get_mask (image)))
+ gimp_channel_clear (gimp_image_get_mask (image), NULL, TRUE);
- /* if there's a drawable, add a new floating selection */
- if (drawable)
- floating_sel_attach (layer, drawable);
- else
- gimp_image_add_layer (image, layer, NULL, 0, TRUE);
+ /* fall thru */
+
+ case GIMP_PASTE_TYPE_FLOATING_INTO:
+ floating_sel_attach (layer, drawable);
+ break;
+
+ case GIMP_PASTE_TYPE_NEW_LAYER:
+ /* always add on top of the drawable or the active layer, where
+ * we would attach a floating selection
+ */
+ gimp_image_add_layer (image, layer,
+ GIMP_IS_LAYER (drawable) ?
+ gimp_item_get_parent (GIMP_ITEM (drawable)) :
+ NULL,
+ -1, TRUE);
+ break;
+ }
- /* end the group undo */
gimp_image_undo_group_end (image);
return layer;
diff --git a/app/core/gimp-edit.h b/app/core/gimp-edit.h
index 6829d52..8d38f78 100644
--- a/app/core/gimp-edit.h
+++ b/app/core/gimp-edit.h
@@ -19,11 +19,11 @@
#define __GIMP_EDIT_H__
-GimpBuffer * gimp_edit_cut (GimpImage *image,
+GimpObject * gimp_edit_cut (GimpImage *image,
GimpDrawable *drawable,
GimpContext *context,
GError **error);
-GimpBuffer * gimp_edit_copy (GimpImage *image,
+GimpObject * gimp_edit_copy (GimpImage *image,
GimpDrawable *drawable,
GimpContext *context,
GError **error);
@@ -43,8 +43,8 @@ void gimp_edit_get_paste_offset (GimpImage *image,
GimpLayer * gimp_edit_paste (GimpImage *image,
GimpDrawable *drawable,
- GimpBuffer *paste,
- gboolean paste_into,
+ GimpObject *paste,
+ GimpPasteType paste_type,
gint viewport_x,
gint viewport_y,
gint viewport_width,
diff --git a/app/display/gimpdisplayshell-dnd.c b/app/display/gimpdisplayshell-dnd.c
index 6a368f0..68f4511 100644
--- a/app/display/gimpdisplayshell-dnd.c
+++ b/app/display/gimpdisplayshell-dnd.c
@@ -448,6 +448,7 @@ gimp_display_shell_drop_buffer (GtkWidget *widget,
GimpImage *image = gimp_display_get_image (shell->display);
GimpDrawable *drawable;
GimpBuffer *buffer;
+ GimpPasteType paste_type;
gint x, y, width, height;
GIMP_LOG (DND, NULL);
@@ -467,6 +468,8 @@ gimp_display_shell_drop_buffer (GtkWidget *widget,
return;
}
+ paste_type = GIMP_PASTE_TYPE_FLOATING;
+
drawable = gimp_image_get_active_drawable (image);
if (drawable)
@@ -474,17 +477,20 @@ gimp_display_shell_drop_buffer (GtkWidget *widget,
if (gimp_viewable_get_children (GIMP_VIEWABLE (drawable)))
{
gimp_message_literal (shell->display->gimp, G_OBJECT (shell->display),
- GIMP_MESSAGE_ERROR,
- _("Cannot modify the pixels of layer groups."));
- return;
- }
+ GIMP_MESSAGE_INFO,
+ _("Pasted as new layer because the "
+ "target is a layer group."));
- if (gimp_item_is_content_locked (GIMP_ITEM (drawable)))
+ paste_type = GIMP_PASTE_TYPE_NEW_LAYER;
+ }
+ else if (gimp_item_is_content_locked (GIMP_ITEM (drawable)))
{
gimp_message_literal (shell->display->gimp, G_OBJECT (shell->display),
GIMP_MESSAGE_ERROR,
- _("The active layer's pixels are locked."));
- return;
+ _("Pasted as new layer because the "
+ "target's pixels are locked."));
+
+ paste_type = GIMP_PASTE_TYPE_NEW_LAYER;
}
}
@@ -494,8 +500,8 @@ gimp_display_shell_drop_buffer (GtkWidget *widget,
/* FIXME: popup a menu for selecting "Paste Into" */
- gimp_edit_paste (image, drawable, buffer, FALSE,
- x, y, width, height);
+ gimp_edit_paste (image, drawable, GIMP_OBJECT (buffer),
+ paste_type, x, y, width, height);
gimp_display_shell_dnd_flush (shell, image);
}
diff --git a/app/pdb/edit-cmds.c b/app/pdb/edit-cmds.c
index fde1fe4..982add6 100644
--- a/app/pdb/edit-cmds.c
+++ b/app/pdb/edit-cmds.c
@@ -211,8 +211,11 @@ edit_paste_invoker (GimpProcedure *procedure,
gimp_pdb_item_is_not_group (GIMP_ITEM (drawable), error))
{
floating_sel = gimp_edit_paste (gimp_item_get_image (GIMP_ITEM (drawable)),
- drawable, buffer,
- paste_into, -1, -1, -1, -1);
+ drawable, GIMP_OBJECT (buffer),
+ paste_into ?
+ GIMP_PASTE_TYPE_FLOATING_INTO :
+ GIMP_PASTE_TYPE_FLOATING,
+ -1, -1, -1, -1);
if (! floating_sel)
success = FALSE;
@@ -446,8 +449,11 @@ edit_named_paste_invoker (GimpProcedure *procedure,
gimp_pdb_item_is_not_group (GIMP_ITEM (drawable), error))
{
floating_sel = gimp_edit_paste (gimp_item_get_image (GIMP_ITEM (drawable)),
- drawable, buffer,
- paste_into, -1, -1, -1, -1);
+ drawable, GIMP_OBJECT (buffer),
+ paste_into ?
+ GIMP_PASTE_TYPE_FLOATING_INTO :
+ GIMP_PASTE_TYPE_FLOATING,
+ -1, -1, -1, -1);
if (! floating_sel)
success = FALSE;
}
diff --git a/tools/pdbgen/pdb/edit.pdb b/tools/pdbgen/pdb/edit.pdb
index 04af99a..605d0b3 100644
--- a/tools/pdbgen/pdb/edit.pdb
+++ b/tools/pdbgen/pdb/edit.pdb
@@ -209,8 +209,11 @@ HELP
gimp_pdb_item_is_not_group (GIMP_ITEM (drawable), error))
{
floating_sel = gimp_edit_paste (gimp_item_get_image (GIMP_ITEM (drawable)),
- drawable, buffer,
- paste_into, -1, -1, -1, -1);
+ drawable, GIMP_OBJECT (buffer),
+ paste_into ?
+ GIMP_PASTE_TYPE_FLOATING_INTO :
+ GIMP_PASTE_TYPE_FLOATING,
+ -1, -1, -1, -1);
if (! floating_sel)
success = FALSE;
@@ -451,8 +454,11 @@ HELP
gimp_pdb_item_is_not_group (GIMP_ITEM (drawable), error))
{
floating_sel = gimp_edit_paste (gimp_item_get_image (GIMP_ITEM (drawable)),
- drawable, buffer,
- paste_into, -1, -1, -1, -1);
+ drawable, GIMP_OBJECT (buffer),
+ paste_into ?
+ GIMP_PASTE_TYPE_FLOATING_INTO :
+ GIMP_PASTE_TYPE_FLOATING,
+ -1, -1, -1, -1);
if (! floating_sel)
success = FALSE;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]