diff --git a/app/actions/buffers-actions.c b/app/actions/buffers-actions.c index 1321d80506..18d1f5fe01 100644 --- a/app/actions/buffers-actions.c +++ b/app/actions/buffers-actions.c @@ -42,24 +42,6 @@ static const GimpActionEntry buffers_actions[] = NC_("buffers-action", "Buffers Menu"), NULL, NULL, NULL, GIMP_HELP_BUFFER_DIALOG }, - { "buffers-paste", GIMP_ICON_EDIT_PASTE, - NC_("buffers-action", "_Paste Buffer"), NULL, - NC_("buffers-action", "Paste the selected buffer"), - G_CALLBACK (buffers_paste_cmd_callback), - GIMP_HELP_BUFFER_PASTE }, - - { "buffers-paste-into", GIMP_ICON_EDIT_PASTE_INTO, - NC_("buffers-action", "Paste Buffer _Into"), NULL, - NC_("buffers-action", "Paste the selected buffer into the selection"), - G_CALLBACK (buffers_paste_into_cmd_callback), - GIMP_HELP_BUFFER_PASTE_INTO }, - - { "buffers-paste-as-new-layer", GIMP_ICON_EDIT_PASTE_AS_NEW, - NC_("buffers-action", "Paste Buffer as New _Layer"), NULL, - NC_("buffers-action", "Paste the selected buffer as a new layer"), - G_CALLBACK (buffers_paste_as_new_layer_cmd_callback), - GIMP_HELP_BUFFER_PASTE_AS_NEW_LAYER }, - { "buffers-paste-as-new-image", GIMP_ICON_EDIT_PASTE_AS_NEW, NC_("buffers-action", "Paste Buffer as _New Image"), NULL, NC_("buffers-action", "Paste the selected buffer as a new image"), @@ -73,6 +55,47 @@ static const GimpActionEntry buffers_actions[] = GIMP_HELP_BUFFER_DELETE } }; +static const GimpEnumActionEntry buffers_paste_actions[] = +{ + { "buffers-paste", GIMP_ICON_EDIT_PASTE, + NC_("buffers-action", "_Paste Buffer"), NULL, + NC_("buffers-action", "Paste the selected buffer"), + GIMP_PASTE_TYPE_FLOATING, FALSE, + GIMP_HELP_BUFFER_PASTE }, + + { "buffers-paste-in-place", GIMP_ICON_EDIT_PASTE, + NC_("buffers-action", "Paste Buffer In Pl_ace"), NULL, + NC_("buffers-action", "Paste the selected buffer at its original position"), + GIMP_PASTE_TYPE_FLOATING_IN_PLACE, FALSE, + GIMP_HELP_BUFFER_PASTE_IN_PLACE }, + + { "buffers-paste-into", GIMP_ICON_EDIT_PASTE_INTO, + NC_("buffers-action", "Paste Buffer _Into"), NULL, + NC_("buffers-action", "Paste the selected buffer into the selection"), + GIMP_PASTE_TYPE_FLOATING_INTO, FALSE, + GIMP_HELP_BUFFER_PASTE_INTO }, + + { "buffers-paste-into-in-place", GIMP_ICON_EDIT_PASTE_INTO, + NC_("buffers-action", "Paste Buffer Into In Place"), NULL, + NC_("buffers-action", + "Paste the selected buffer into the selection at its original position"), + GIMP_PASTE_TYPE_FLOATING_INTO_IN_PLACE, FALSE, + GIMP_HELP_BUFFER_PASTE_INTO_IN_PLACE }, + + { "buffers-paste-as-new-layer", GIMP_ICON_EDIT_PASTE_AS_NEW, + NC_("buffers-action", "Paste Buffer as New _Layer"), NULL, + NC_("buffers-action", "Paste the selected buffer as a new layer"), + GIMP_PASTE_TYPE_NEW_LAYER, FALSE, + GIMP_HELP_BUFFER_PASTE_AS_NEW_LAYER }, + + { "buffers-paste-as-new-layer-in-place", GIMP_ICON_EDIT_PASTE_AS_NEW, + NC_("buffers-action", "Paste Buffer as New Layer in Place"), NULL, + NC_("buffers-action", + "Paste the selected buffer as a new layer at its original position"), + GIMP_PASTE_TYPE_NEW_LAYER_IN_PLACE, FALSE, + GIMP_HELP_BUFFER_PASTE_AS_NEW_LAYER_IN_PLACE }, +}; + void buffers_actions_setup (GimpActionGroup *group) @@ -80,6 +103,11 @@ buffers_actions_setup (GimpActionGroup *group) gimp_action_group_add_actions (group, "buffers-action", buffers_actions, G_N_ELEMENTS (buffers_actions)); + + gimp_action_group_add_enum_actions (group, "buffers-action", + buffers_paste_actions, + G_N_ELEMENTS (buffers_paste_actions), + G_CALLBACK (buffers_paste_cmd_callback)); } void @@ -95,11 +123,14 @@ buffers_actions_update (GimpActionGroup *group, #define SET_SENSITIVE(action,condition) \ gimp_action_group_set_action_sensitive (group, action, (condition) != 0) - SET_SENSITIVE ("buffers-paste", buffer); - SET_SENSITIVE ("buffers-paste-into", buffer); - SET_SENSITIVE ("buffers-paste-as-new-layer", buffer); - SET_SENSITIVE ("buffers-paste-as-new-image", buffer); - SET_SENSITIVE ("buffers-delete", buffer); + SET_SENSITIVE ("buffers-paste", buffer); + SET_SENSITIVE ("buffers-paste-in-place", buffer); + SET_SENSITIVE ("buffers-paste-into", buffer); + SET_SENSITIVE ("buffers-paste-into-in-place", buffer); + SET_SENSITIVE ("buffers-paste-as-new-layer", buffer); + SET_SENSITIVE ("buffers-paste-as-new-layer-in-place", buffer); + SET_SENSITIVE ("buffers-paste-as-new-image", buffer); + SET_SENSITIVE ("buffers-delete", buffer); #undef SET_SENSITIVE } diff --git a/app/actions/buffers-commands.c b/app/actions/buffers-commands.c index a0fe7c8100..454429ec52 100644 --- a/app/actions/buffers-commands.c +++ b/app/actions/buffers-commands.c @@ -30,7 +30,7 @@ #include "core/gimpcontext.h" #include "core/gimpimage.h" -#include "widgets/gimpbufferview.h" +#include "widgets/gimpcontainereditor.h" #include "widgets/gimpcontainerview.h" #include "widgets/gimpcontainerview-utils.h" @@ -43,84 +43,18 @@ #include "gimp-intl.h" -/* local function prototypes */ - -static void buffers_paste (GimpBufferView *view, - GimpPasteType paste_type); - - /* public functionss */ void buffers_paste_cmd_callback (GtkAction *action, + gint value, gpointer data) -{ - 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), GIMP_PASTE_TYPE_FLOATING_INTO); -} - -void -buffers_paste_as_new_layer_cmd_callback (GtkAction *action, - gpointer data) -{ - buffers_paste (GIMP_BUFFER_VIEW (data), GIMP_PASTE_TYPE_NEW_LAYER); -} - -void -buffers_paste_as_new_image_cmd_callback (GtkAction *action, - gpointer data) { GimpContainerEditor *editor = GIMP_CONTAINER_EDITOR (data); GimpContainer *container; GimpContext *context; GimpBuffer *buffer; - - container = gimp_container_view_get_container (editor->view); - context = gimp_container_view_get_context (editor->view); - - buffer = gimp_context_get_buffer (context); - - if (buffer && gimp_container_have (container, GIMP_OBJECT (buffer))) - { - GtkWidget *widget = GTK_WIDGET (editor); - GimpImage *new_image; - - new_image = gimp_edit_paste_as_new_image (context->gimp, - GIMP_OBJECT (buffer)); - gimp_create_display (context->gimp, new_image, - GIMP_UNIT_PIXEL, 1.0, - G_OBJECT (gtk_widget_get_screen (widget)), - gimp_widget_get_monitor (widget)); - g_object_unref (new_image); - } -} - -void -buffers_delete_cmd_callback (GtkAction *action, - gpointer data) -{ - GimpContainerEditor *editor = GIMP_CONTAINER_EDITOR (data); - - gimp_container_view_remove_active (editor->view); -} - - -/* private functions */ - -static void -buffers_paste (GimpBufferView *view, - GimpPasteType paste_type) -{ - GimpContainerEditor *editor = GIMP_CONTAINER_EDITOR (view); - GimpContainer *container; - GimpContext *context; - GimpBuffer *buffer; + GimpPasteType paste_type = (GimpPasteType) value; container = gimp_container_view_get_container (editor->view); context = gimp_container_view_get_context (editor->view); @@ -160,3 +94,41 @@ buffers_paste (GimpBufferView *view, } } } + +void +buffers_paste_as_new_image_cmd_callback (GtkAction *action, + gpointer data) +{ + GimpContainerEditor *editor = GIMP_CONTAINER_EDITOR (data); + GimpContainer *container; + GimpContext *context; + GimpBuffer *buffer; + + container = gimp_container_view_get_container (editor->view); + context = gimp_container_view_get_context (editor->view); + + buffer = gimp_context_get_buffer (context); + + if (buffer && gimp_container_have (container, GIMP_OBJECT (buffer))) + { + GtkWidget *widget = GTK_WIDGET (editor); + GimpImage *new_image; + + new_image = gimp_edit_paste_as_new_image (context->gimp, + GIMP_OBJECT (buffer)); + gimp_create_display (context->gimp, new_image, + GIMP_UNIT_PIXEL, 1.0, + G_OBJECT (gtk_widget_get_screen (widget)), + gimp_widget_get_monitor (widget)); + g_object_unref (new_image); + } +} + +void +buffers_delete_cmd_callback (GtkAction *action, + gpointer data) +{ + GimpContainerEditor *editor = GIMP_CONTAINER_EDITOR (data); + + gimp_container_view_remove_active (editor->view); +} diff --git a/app/actions/buffers-commands.h b/app/actions/buffers-commands.h index 8c4dcf5258..3af74136c2 100644 --- a/app/actions/buffers-commands.h +++ b/app/actions/buffers-commands.h @@ -20,10 +20,7 @@ void buffers_paste_cmd_callback (GtkAction *action, - gpointer data); -void buffers_paste_into_cmd_callback (GtkAction *action, - gpointer data); -void buffers_paste_as_new_layer_cmd_callback (GtkAction *action, + gint value, gpointer data); void buffers_paste_as_new_image_cmd_callback (GtkAction *action, gpointer data); diff --git a/app/actions/edit-actions.c b/app/actions/edit-actions.c index fef69804e7..d2f6a46e66 100644 --- a/app/actions/edit-actions.c +++ b/app/actions/edit-actions.c @@ -126,25 +126,6 @@ static const GimpActionEntry edit_actions[] = G_CALLBACK (edit_copy_visible_cmd_callback), GIMP_HELP_EDIT_COPY_VISIBLE }, - { "edit-paste", GIMP_ICON_EDIT_PASTE, - NC_("edit-action", "_Paste"), "V", - NC_("edit-action", "Paste the content of the clipboard"), - G_CALLBACK (edit_paste_cmd_callback), - GIMP_HELP_EDIT_PASTE }, - - { "edit-paste-into", GIMP_ICON_EDIT_PASTE_INTO, - NC_("edit-action", "Paste _Into"), NULL, - NC_("edit-action", - "Paste the content of the clipboard into the current selection"), - G_CALLBACK (edit_paste_into_cmd_callback), - GIMP_HELP_EDIT_PASTE_INTO }, - - { "edit-paste-as-new-layer", NULL, - NC_("edit-action", "New _Layer"), NULL, - NC_("edit-action", "Create a new layer from the content of the clipboard"), - G_CALLBACK (edit_paste_as_new_layer_cmd_callback), - GIMP_HELP_EDIT_PASTE_AS_NEW_LAYER }, - { "edit-paste-as-new-image", GIMP_ICON_EDIT_PASTE_AS_NEW, NC_("edit-action", "From _Clipboard"), "V", NC_("edit-action", "Create a new image from the content of the clipboard"), @@ -189,6 +170,51 @@ static const GimpActionEntry edit_actions[] = GIMP_HELP_EDIT_CLEAR } }; +static const GimpEnumActionEntry edit_paste_actions[] = +{ + { "edit-paste", GIMP_ICON_EDIT_PASTE, + NC_("edit-action", "_Paste"), "V", + NC_("edit-action", "Paste the content of the clipboard"), + GIMP_PASTE_TYPE_FLOATING, FALSE, + GIMP_HELP_EDIT_PASTE }, + + { "edit-paste-in-place", GIMP_ICON_EDIT_PASTE, + NC_("edit-action", "Paste In Place"), NULL, + NC_("edit-action", + "Paste the content of the clipboard at its original position"), + GIMP_PASTE_TYPE_FLOATING_IN_PLACE, FALSE, + GIMP_HELP_EDIT_PASTE_IN_PLACE }, + + { "edit-paste-into", GIMP_ICON_EDIT_PASTE_INTO, + NC_("edit-action", "Paste _Into Selection"), NULL, + NC_("edit-action", + "Paste the content of the clipboard into the current selection"), + GIMP_PASTE_TYPE_FLOATING_INTO, FALSE, + GIMP_HELP_EDIT_PASTE_INTO }, + + { "edit-paste-into-in-place", GIMP_ICON_EDIT_PASTE_INTO, + NC_("edit-action", "Paste Into Selection In Place"), NULL, + NC_("edit-action", + "Paste the content of the clipboard into the current selection " + "at its original position"), + GIMP_PASTE_TYPE_FLOATING_INTO_IN_PLACE, FALSE, + GIMP_HELP_EDIT_PASTE_INTO_IN_PLACE }, + + { "edit-paste-as-new-layer", GIMP_ICON_EDIT_PASTE_AS_NEW, + NC_("edit-action", "New _Layer"), NULL, + NC_("edit-action", "Create a new layer from the content of the clipboard"), + GIMP_PASTE_TYPE_NEW_LAYER, FALSE, + GIMP_HELP_EDIT_PASTE_AS_NEW_LAYER }, + + { "edit-paste-as-new-layer-in-place", GIMP_ICON_EDIT_PASTE_AS_NEW, + NC_("edit-action", "New Layer In _Place"), NULL, + NC_("edit-action", + "Create a new layer from the content of the clipboard" + "and place it at its original position"), + GIMP_PASTE_TYPE_NEW_LAYER_IN_PLACE, FALSE, + GIMP_HELP_EDIT_PASTE_AS_NEW_LAYER_IN_PLACE } +}; + static const GimpEnumActionEntry edit_fill_actions[] = { { "edit-fill-fg", GIMP_ICON_TOOL_BUCKET_FILL, @@ -223,6 +249,11 @@ edit_actions_setup (GimpActionGroup *group) edit_actions, G_N_ELEMENTS (edit_actions)); + gimp_action_group_add_enum_actions (group, "edit-action", + edit_paste_actions, + G_N_ELEMENTS (edit_paste_actions), + G_CALLBACK (edit_paste_cmd_callback)); + gimp_action_group_add_enum_actions (group, "edit-action", edit_fill_actions, G_N_ELEMENTS (edit_fill_actions), @@ -359,12 +390,15 @@ edit_actions_update (GimpActionGroup *group, g_free (redo_name); g_free (fade_name); - SET_SENSITIVE ("edit-cut", writable && !children); - SET_SENSITIVE ("edit-copy", drawable); - SET_SENSITIVE ("edit-copy-visible", image); + SET_SENSITIVE ("edit-cut", writable && !children); + SET_SENSITIVE ("edit-copy", drawable); + SET_SENSITIVE ("edit-copy-visible", image); /* "edit-paste" is always active */ - SET_SENSITIVE ("edit-paste-into", image); - SET_SENSITIVE ("edit-paste-as-new-layer", image); + SET_SENSITIVE ("edit-paste-in-place", image); + SET_SENSITIVE ("edit-paste-into", image); + SET_SENSITIVE ("edit-paste-into-in-place", image); + SET_SENSITIVE ("edit-paste-as-new-layer", image); + SET_SENSITIVE ("edit-paste-as-new-layer-in-place", image); SET_SENSITIVE ("edit-named-cut", writable && !children); SET_SENSITIVE ("edit-named-copy", drawable); diff --git a/app/actions/edit-commands.c b/app/actions/edit-commands.c index ef2a9a044e..9959c635bc 100644 --- a/app/actions/edit-commands.c +++ b/app/actions/edit-commands.c @@ -65,7 +65,7 @@ /* local function prototypes */ static void edit_paste (GimpDisplay *display, - GimpPasteType paste_into, + GimpPasteType paste_type, gboolean try_svg); static void cut_named_buffer_callback (GtkWidget *widget, const gchar *name, @@ -327,40 +327,40 @@ edit_copy_visible_cmd_callback (GtkAction *action, void edit_paste_cmd_callback (GtkAction *action, + gint value, gpointer data) { - GimpDisplay *display = action_data_get_display (data); + GimpDisplay *display = action_data_get_display (data); + GimpPasteType paste_type = (GimpPasteType) value; - if (display && gimp_display_get_image (display)) + if (paste_type == GIMP_PASTE_TYPE_FLOATING) { - edit_paste (display, GIMP_PASTE_TYPE_FLOATING, TRUE); + if (! display || ! gimp_display_get_image (display)) + { + edit_paste_as_new_image_cmd_callback (action, data); + return; + } } - else + + if (! display) + return; + + switch (paste_type) { - edit_paste_as_new_image_cmd_callback (action, data); + case GIMP_PASTE_TYPE_FLOATING: + case GIMP_PASTE_TYPE_FLOATING_IN_PLACE: + case GIMP_PASTE_TYPE_FLOATING_INTO: + case GIMP_PASTE_TYPE_FLOATING_INTO_IN_PLACE: + edit_paste (display, paste_type, TRUE); + break; + + case GIMP_PASTE_TYPE_NEW_LAYER: + case GIMP_PASTE_TYPE_NEW_LAYER_IN_PLACE: + edit_paste (display, paste_type, FALSE); + break; } } -void -edit_paste_into_cmd_callback (GtkAction *action, - gpointer data) -{ - GimpDisplay *display; - return_if_no_display (display, data); - - edit_paste (display, GIMP_PASTE_TYPE_FLOATING_INTO, TRUE); -} - -void -edit_paste_as_new_layer_cmd_callback (GtkAction *action, - gpointer data) -{ - GimpDisplay *display; - return_if_no_display (display, data); - - edit_paste (display, GIMP_PASTE_TYPE_NEW_LAYER, FALSE); -} - void edit_paste_as_new_image_cmd_callback (GtkAction *action, gpointer data) diff --git a/app/actions/edit-commands.h b/app/actions/edit-commands.h index 940dcc7510..bb916750f7 100644 --- a/app/actions/edit-commands.h +++ b/app/actions/edit-commands.h @@ -41,10 +41,7 @@ void edit_copy_visible_cmd_callback (GtkAction *action, gpointer data); void edit_paste_cmd_callback (GtkAction *action, - gpointer data); -void edit_paste_into_cmd_callback (GtkAction *action, - gpointer data); -void edit_paste_as_new_layer_cmd_callback (GtkAction *action, + gint value, gpointer data); void edit_paste_as_new_image_cmd_callback (GtkAction *action, gpointer data); diff --git a/app/core/core-enums.c b/app/core/core-enums.c index 1e1570e900..645c02280b 100644 --- a/app/core/core-enums.c +++ b/app/core/core-enums.c @@ -319,16 +319,22 @@ gimp_paste_type_get_type (void) static const GEnumValue values[] = { { GIMP_PASTE_TYPE_FLOATING, "GIMP_PASTE_TYPE_FLOATING", "floating" }, + { GIMP_PASTE_TYPE_FLOATING_IN_PLACE, "GIMP_PASTE_TYPE_FLOATING_IN_PLACE", "floating-in-place" }, { GIMP_PASTE_TYPE_FLOATING_INTO, "GIMP_PASTE_TYPE_FLOATING_INTO", "floating-into" }, + { GIMP_PASTE_TYPE_FLOATING_INTO_IN_PLACE, "GIMP_PASTE_TYPE_FLOATING_INTO_IN_PLACE", "floating-into-in-place" }, { GIMP_PASTE_TYPE_NEW_LAYER, "GIMP_PASTE_TYPE_NEW_LAYER", "new-layer" }, + { GIMP_PASTE_TYPE_NEW_LAYER_IN_PLACE, "GIMP_PASTE_TYPE_NEW_LAYER_IN_PLACE", "new-layer-in-place" }, { 0, NULL, NULL } }; static const GimpEnumDesc descs[] = { { GIMP_PASTE_TYPE_FLOATING, "GIMP_PASTE_TYPE_FLOATING", NULL }, + { GIMP_PASTE_TYPE_FLOATING_IN_PLACE, "GIMP_PASTE_TYPE_FLOATING_IN_PLACE", NULL }, { GIMP_PASTE_TYPE_FLOATING_INTO, "GIMP_PASTE_TYPE_FLOATING_INTO", NULL }, + { GIMP_PASTE_TYPE_FLOATING_INTO_IN_PLACE, "GIMP_PASTE_TYPE_FLOATING_INTO_IN_PLACE", NULL }, { GIMP_PASTE_TYPE_NEW_LAYER, "GIMP_PASTE_TYPE_NEW_LAYER", NULL }, + { GIMP_PASTE_TYPE_NEW_LAYER_IN_PLACE, "GIMP_PASTE_TYPE_NEW_LAYER_IN_PLACE", NULL }, { 0, NULL, NULL } }; diff --git a/app/core/core-enums.h b/app/core/core-enums.h index 429de3a00f..eb7a2ad888 100644 --- a/app/core/core-enums.h +++ b/app/core/core-enums.h @@ -169,8 +169,11 @@ GType gimp_paste_type_get_type (void) G_GNUC_CONST; typedef enum /*< pdb-skip >*/ { GIMP_PASTE_TYPE_FLOATING, + GIMP_PASTE_TYPE_FLOATING_IN_PLACE, GIMP_PASTE_TYPE_FLOATING_INTO, - GIMP_PASTE_TYPE_NEW_LAYER + GIMP_PASTE_TYPE_FLOATING_INTO_IN_PLACE, + GIMP_PASTE_TYPE_NEW_LAYER, + GIMP_PASTE_TYPE_NEW_LAYER_IN_PLACE } GimpPasteType; diff --git a/app/core/gimp-edit.c b/app/core/gimp-edit.c index 4ecbe13a78..5d2fa96a62 100644 --- a/app/core/gimp-edit.c +++ b/app/core/gimp-edit.c @@ -80,8 +80,15 @@ gimp_edit_cut (GimpImage *image, gimp_channel_is_empty (gimp_image_get_mask (image))) { GimpImage *clip_image; + gint off_x, off_y; + + gimp_item_get_offset (GIMP_ITEM (drawable), &off_x, &off_y); clip_image = gimp_image_new_from_drawable (image->gimp, drawable); + g_object_set_data (G_OBJECT (clip_image), "offset-x", + GINT_TO_POINTER (off_x)); + g_object_set_data (G_OBJECT (clip_image), "offset-y", + GINT_TO_POINTER (off_y)); gimp_container_remove (image->gimp->images, GIMP_OBJECT (clip_image)); gimp_set_clipboard_image (image->gimp, clip_image); g_object_unref (clip_image); @@ -131,8 +138,15 @@ gimp_edit_copy (GimpImage *image, gimp_channel_is_empty (gimp_image_get_mask (image))) { GimpImage *clip_image; + gint off_x, off_y; + + gimp_item_get_offset (GIMP_ITEM (drawable), &off_x, &off_y); clip_image = gimp_image_new_from_drawable (image->gimp, drawable); + g_object_set_data (G_OBJECT (clip_image), "offset-x", + GINT_TO_POINTER (off_x)); + g_object_set_data (G_OBJECT (clip_image), "offset-y", + GINT_TO_POINTER (off_y)); gimp_container_remove (image->gimp->images, GIMP_OBJECT (clip_image)); gimp_set_clipboard_image (image->gimp, clip_image); g_object_unref (clip_image); @@ -183,16 +197,110 @@ gimp_edit_copy_visible (GimpImage *image, return NULL; } -void -gimp_edit_get_paste_offset (GimpImage *image, - GimpDrawable *drawable, - GimpObject *paste, - gint viewport_x, - gint viewport_y, - gint viewport_width, - gint viewport_height, - gint *offset_x, - gint *offset_y) +static GimpLayer * +gimp_edit_paste_get_layer (GimpImage *image, + GimpDrawable *drawable, + GimpObject *paste, + GimpPasteType *paste_type) +{ + GimpLayer *layer = NULL; + const Babl *floating_format; + + /* change paste type to NEW_LAYER for cases where we can't attach a + * floating selection + */ + if (! drawable || + gimp_viewable_get_children (GIMP_VIEWABLE (drawable)) || + gimp_item_is_content_locked (GIMP_ITEM (drawable))) + { + *paste_type = GIMP_PASTE_TYPE_NEW_LAYER; + } + + /* floating pastes always have the pasted-to drawable's format with + * alpha; if drawable == NULL, user is pasting into an empty image + */ + if (drawable) + floating_format = gimp_drawable_get_format_with_alpha (drawable); + else + floating_format = gimp_image_get_layer_format (image, TRUE); + + if (GIMP_IS_IMAGE (paste)) + { + GType layer_type; + + layer = gimp_image_get_layer_iter (GIMP_IMAGE (paste))->data; + + switch (*paste_type) + { + case GIMP_PASTE_TYPE_FLOATING: + case GIMP_PASTE_TYPE_FLOATING_INTO: + /* when pasting as floating selection, force creation of a + * plain layer, so gimp_item_convert() will collapse a + * group layer + */ + layer_type = GIMP_TYPE_LAYER; + break; + + case GIMP_PASTE_TYPE_NEW_LAYER: + layer_type = G_TYPE_FROM_INSTANCE (layer); + break; + + default: + g_return_val_if_reached (NULL); + } + + layer = GIMP_LAYER (gimp_item_convert (GIMP_ITEM (layer), + image, layer_type)); + + switch (*paste_type) + { + case GIMP_PASTE_TYPE_FLOATING: + case GIMP_PASTE_TYPE_FLOATING_INTO: + /* when pasting as floating selection, get rid of the layer mask, + * and make sure the layer has the right format + */ + if (gimp_layer_get_mask (layer)) + gimp_layer_apply_mask (layer, GIMP_MASK_DISCARD, FALSE); + + if (gimp_drawable_get_format (GIMP_DRAWABLE (layer)) != + floating_format) + { + gimp_drawable_convert_type (GIMP_DRAWABLE (layer), image, + gimp_drawable_get_base_type (drawable), + gimp_drawable_get_precision (drawable), + TRUE, + NULL, + GEGL_DITHER_NONE, GEGL_DITHER_NONE, + FALSE, NULL); + } + break; + + default: + break; + } + } + else if (GIMP_IS_BUFFER (paste)) + { + layer = gimp_layer_new_from_buffer (GIMP_BUFFER (paste), image, + floating_format, + _("Pasted Layer"), + GIMP_OPACITY_OPAQUE, + gimp_image_get_default_new_layer_mode (image)); + } + + return layer; +} + +static void +gimp_edit_paste_get_viewport_offset (GimpImage *image, + GimpDrawable *drawable, + GimpObject *paste, + gint viewport_x, + gint viewport_y, + gint viewport_width, + gint viewport_height, + gint *offset_x, + gint *offset_y) { gint image_width; gint image_height; @@ -321,119 +429,45 @@ gimp_edit_get_paste_offset (GimpImage *image, } } -GimpLayer * -gimp_edit_paste (GimpImage *image, - GimpDrawable *drawable, - GimpObject *paste, - GimpPasteType paste_type, - gint viewport_x, - gint viewport_y, - gint viewport_width, - gint viewport_height) +static void +gimp_edit_paste_get_paste_offset (GimpImage *image, + GimpDrawable *drawable, + GimpObject *paste, + gint *offset_x, + gint *offset_y) { - GimpLayer *layer = NULL; - const Babl *floating_format; - 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_IMAGE (paste) || GIMP_IS_BUFFER (paste), NULL); - - /* change paste type to NEW_LAYER for cases where we can't attach a - * floating selection - */ - if (! drawable || - gimp_viewable_get_children (GIMP_VIEWABLE (drawable)) || - gimp_item_is_content_locked (GIMP_ITEM (drawable))) - { - paste_type = GIMP_PASTE_TYPE_NEW_LAYER; - } - - /* floating pastes always have the pasted-to drawable's format with - * alpha; if drawable == NULL, user is pasting into an empty image - */ - if (drawable) - floating_format = gimp_drawable_get_format_with_alpha (drawable); - else - floating_format = gimp_image_get_layer_format (image, TRUE); + g_return_if_fail (GIMP_IS_IMAGE (image)); + g_return_if_fail (drawable == NULL || GIMP_IS_DRAWABLE (drawable)); + g_return_if_fail (drawable == NULL || + gimp_item_is_attached (GIMP_ITEM (drawable))); + g_return_if_fail (GIMP_IS_VIEWABLE (paste)); + g_return_if_fail (offset_x != NULL); + g_return_if_fail (offset_y != NULL); if (GIMP_IS_IMAGE (paste)) { - GType layer_type; - - layer = gimp_image_get_layer_iter (GIMP_IMAGE (paste))->data; - - switch (paste_type) - { - case GIMP_PASTE_TYPE_FLOATING: - case GIMP_PASTE_TYPE_FLOATING_INTO: - /* when pasting as floating selection, force creation of a - * plain layer, so gimp_item_convert() will collapse a - * group layer - */ - layer_type = GIMP_TYPE_LAYER; - break; - - case GIMP_PASTE_TYPE_NEW_LAYER: - layer_type = G_TYPE_FROM_INSTANCE (layer); - break; - - default: - g_return_val_if_reached (NULL); - } - - layer = GIMP_LAYER (gimp_item_convert (GIMP_ITEM (layer), - image, layer_type)); - - switch (paste_type) - { - case GIMP_PASTE_TYPE_FLOATING: - case GIMP_PASTE_TYPE_FLOATING_INTO: - /* when pasting as floating selection, get rid of the layer mask, - * and make sure the layer has the right format - */ - if (gimp_layer_get_mask (layer)) - gimp_layer_apply_mask (layer, GIMP_MASK_DISCARD, FALSE); - - if (gimp_drawable_get_format (GIMP_DRAWABLE (layer)) != - floating_format) - { - gimp_drawable_convert_type (GIMP_DRAWABLE (layer), image, - gimp_drawable_get_base_type (drawable), - gimp_drawable_get_precision (drawable), - TRUE, - NULL, - GEGL_DITHER_NONE, GEGL_DITHER_NONE, - FALSE, NULL); - } - break; - - default: - break; - } + *offset_x = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (paste), + "offset-x")); + *offset_y = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (paste), + "offset-y")); } else if (GIMP_IS_BUFFER (paste)) { - layer = gimp_layer_new_from_buffer (GIMP_BUFFER (paste), image, - floating_format, - _("Pasted Layer"), - GIMP_OPACITY_OPAQUE, - gimp_image_get_default_new_layer_mode (image)); + GimpBuffer *buffer = GIMP_BUFFER (paste); + + *offset_x = buffer->offset_x; + *offset_y = buffer->offset_y; } +} - if (! layer) - return NULL; - - gimp_edit_get_paste_offset (image, drawable, GIMP_OBJECT (layer), - viewport_x, - viewport_y, - viewport_width, - viewport_height, - &offset_x, - &offset_y); +static GimpLayer * +gimp_edit_paste_paste (GimpImage *image, + GimpDrawable *drawable, + GimpLayer *layer, + GimpPasteType paste_type, + gint offset_x, + gint offset_y) +{ gimp_item_translate (GIMP_ITEM (layer), offset_x, offset_y, FALSE); gimp_image_undo_group_start (image, GIMP_UNDO_GROUP_EDIT_PASTE, @@ -442,6 +476,7 @@ gimp_edit_paste (GimpImage *image, switch (paste_type) { case GIMP_PASTE_TYPE_FLOATING: + case GIMP_PASTE_TYPE_FLOATING_IN_PLACE: /* if there is a selection mask clear it - this might not * always be desired, but in general, it seems like the correct * behavior @@ -452,16 +487,18 @@ gimp_edit_paste (GimpImage *image, /* fall thru */ case GIMP_PASTE_TYPE_FLOATING_INTO: + case GIMP_PASTE_TYPE_FLOATING_INTO_IN_PLACE: floating_sel_attach (layer, drawable); break; case GIMP_PASTE_TYPE_NEW_LAYER: + case GIMP_PASTE_TYPE_NEW_LAYER_IN_PLACE: { GimpLayer *parent = NULL; gint position = 0; - /* always add on top of the passed layer, where we would - * attach a floating selection + /* always add on top of a passed layer, where we would attach + * a floating selection */ if (GIMP_IS_LAYER (drawable)) { @@ -479,6 +516,58 @@ gimp_edit_paste (GimpImage *image, return layer; } +GimpLayer * +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; + gint offset_x = 0; + gint offset_y = 0; + + 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_IMAGE (paste) || GIMP_IS_BUFFER (paste), NULL); + + layer = gimp_edit_paste_get_layer (image, drawable, paste, &paste_type); + + if (! layer) + return NULL; + + switch (paste_type) + { + case GIMP_PASTE_TYPE_FLOATING: + case GIMP_PASTE_TYPE_FLOATING_INTO: + case GIMP_PASTE_TYPE_NEW_LAYER: + gimp_edit_paste_get_viewport_offset (image, drawable, GIMP_OBJECT (layer), + viewport_x, + viewport_y, + viewport_width, + viewport_height, + &offset_x, + &offset_y); + break; + + case GIMP_PASTE_TYPE_FLOATING_IN_PLACE: + case GIMP_PASTE_TYPE_FLOATING_INTO_IN_PLACE: + case GIMP_PASTE_TYPE_NEW_LAYER_IN_PLACE: + gimp_edit_paste_get_paste_offset (image, drawable, paste, + &offset_x, + &offset_y); + break; + } + + return gimp_edit_paste_paste (image, drawable, layer, paste_type, + offset_x, offset_y); +} + GimpImage * gimp_edit_paste_as_new_image (Gimp *gimp, GimpObject *paste) diff --git a/app/core/gimp-edit.h b/app/core/gimp-edit.h index 110384176e..dc8b6ac404 100644 --- a/app/core/gimp-edit.h +++ b/app/core/gimp-edit.h @@ -31,16 +31,6 @@ GimpBuffer * gimp_edit_copy_visible (GimpImage *image, GimpContext *context, GError **error); -void gimp_edit_get_paste_offset (GimpImage *image, - GimpDrawable *drawable, - GimpObject *paste, - gint viewport_x, - gint viewport_y, - gint viewport_width, - gint viewport_height, - gint *offset_x, - gint *offset_y); - GimpLayer * gimp_edit_paste (GimpImage *image, GimpDrawable *drawable, GimpObject *paste, diff --git a/app/widgets/gimpbufferview.c b/app/widgets/gimpbufferview.c index 73bf32261f..3eefb7c125 100644 --- a/app/widgets/gimpbufferview.c +++ b/app/widgets/gimpbufferview.c @@ -42,6 +42,7 @@ #include "gimpview.h" #include "gimpviewrendererbuffer.h" #include "gimpuimanager.h" +#include "gimpwidgets-utils.h" #include "gimp-intl.h" @@ -186,15 +187,24 @@ gimp_buffer_view_new (GimpViewType view_type, buffer_view->paste_button = gimp_editor_add_action_button (GIMP_EDITOR (editor->view), "buffers", - "buffers-paste", NULL); + "buffers-paste", + "buffers-paste-in-place", + gimp_get_extend_selection_mask (), + NULL); buffer_view->paste_into_button = gimp_editor_add_action_button (GIMP_EDITOR (editor->view), "buffers", - "buffers-paste-into", NULL); + "buffers-paste-into", + "buffers-paste-into-in-place", + gimp_get_extend_selection_mask (), + NULL); buffer_view->paste_as_new_layer_button = gimp_editor_add_action_button (GIMP_EDITOR (editor->view), "buffers", - "buffers-paste-as-new-layer", NULL); + "buffers-paste-as-new-layer", + "buffers-paste-as-new-layer-in-place", + gimp_get_extend_selection_mask (), + NULL); buffer_view->paste_as_new_image_button = gimp_editor_add_action_button (GIMP_EDITOR (editor->view), "buffers", diff --git a/app/widgets/gimphelp-ids.h b/app/widgets/gimphelp-ids.h index b9d35a4310..174546be00 100644 --- a/app/widgets/gimphelp-ids.h +++ b/app/widgets/gimphelp-ids.h @@ -56,8 +56,11 @@ #define GIMP_HELP_EDIT_COPY "gimp-edit-copy" #define GIMP_HELP_EDIT_COPY_VISIBLE "gimp-edit-copy-visible" #define GIMP_HELP_EDIT_PASTE "gimp-edit-paste" +#define GIMP_HELP_EDIT_PASTE_IN_PLACE "gimp-edit-paste-in-place" #define GIMP_HELP_EDIT_PASTE_INTO "gimp-edit-paste-into" +#define GIMP_HELP_EDIT_PASTE_INTO_IN_PLACE "gimp-edit-paste-into-in-place" #define GIMP_HELP_EDIT_PASTE_AS_NEW_LAYER "gimp-edit-paste-as-new-layer" +#define GIMP_HELP_EDIT_PASTE_AS_NEW_LAYER_IN_PLACE "gimp-edit-paste-as-new-layer-in-place" #define GIMP_HELP_EDIT_PASTE_AS_NEW_IMAGE "gimp-edit-paste-as-new-image" #define GIMP_HELP_EDIT_CLEAR "gimp-edit-clear" #define GIMP_HELP_EDIT_FILL_FG "gimp-edit-fill-fg" @@ -552,8 +555,11 @@ #define GIMP_HELP_BUFFER_CUT "gimp-buffer-cut" #define GIMP_HELP_BUFFER_COPY "gimp-buffer-copy" #define GIMP_HELP_BUFFER_PASTE "gimp-buffer-paste" +#define GIMP_HELP_BUFFER_PASTE_IN_PLACE "gimp-buffer-paste-in-place" #define GIMP_HELP_BUFFER_PASTE_INTO "gimp-buffer-paste-into" +#define GIMP_HELP_BUFFER_PASTE_INTO_IN_PLACE "gimp-buffer-paste-into-in-place" #define GIMP_HELP_BUFFER_PASTE_AS_NEW_LAYER "gimp-buffer-paste-as-new-layer" +#define GIMP_HELP_BUFFER_PASTE_AS_NEW_LAYER_IN_PLACE "gimp-buffer-paste-as-new-layer-in-place" #define GIMP_HELP_BUFFER_PASTE_AS_NEW_IMAGE "gimp-buffer-paste-as-new-image" #define GIMP_HELP_BUFFER_DELETE "gimp-buffer-delete" diff --git a/menus/buffers-menu.xml b/menus/buffers-menu.xml index 840ef615d9..05b7745900 100644 --- a/menus/buffers-menu.xml +++ b/menus/buffers-menu.xml @@ -4,8 +4,11 @@ + + + diff --git a/menus/image-menu.xml.in b/menus/image-menu.xml.in index e44e073ea8..5a8e8561e3 100644 --- a/menus/image-menu.xml.in +++ b/menus/image-menu.xml.in @@ -193,10 +193,13 @@ + + +