Files
gimp/app/widgets/gimptoolbox-dnd.c
Michael Natterer 536cc8531a app: keep the src image's resolution and unit in copied/cut GimpBuffers
and use them for the new image in "Paste as new image". We were using
the resolution and unit of the image the paste command was invoked
from, which is entirely random and useless.
2017-05-01 18:39:13 +02:00

278 lines
9.8 KiB
C

/* GIMP - The GNU Image Manipulation Program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <string.h>
#include <gegl.h>
#include <gtk/gtk.h>
#include "libgimpbase/gimpbase.h"
#include "libgimpwidgets/gimpwidgets.h"
#include "widgets-types.h"
#include "core/gimp.h"
#include "core/gimpbuffer.h"
#include "core/gimpcontext.h"
#include "core/gimpimage.h"
#include "core/gimpimage-new.h"
#include "core/gimpimage-undo.h"
#include "core/gimplayer.h"
#include "core/gimplayermask.h"
#include "core/gimptoolinfo.h"
#include "file/file-open.h"
#include "gimpdnd.h"
#include "gimptoolbox.h"
#include "gimptoolbox-dnd.h"
#include "gimpwidgets-utils.h"
#include "gimp-intl.h"
/* local function prototypes */
static void gimp_toolbox_drop_uri_list (GtkWidget *widget,
gint x,
gint y,
GList *uri_list,
gpointer data);
static void gimp_toolbox_drop_drawable (GtkWidget *widget,
gint x,
gint y,
GimpViewable *viewable,
gpointer data);
static void gimp_toolbox_drop_tool (GtkWidget *widget,
gint x,
gint y,
GimpViewable *viewable,
gpointer data);
static void gimp_toolbox_drop_buffer (GtkWidget *widget,
gint x,
gint y,
GimpViewable *viewable,
gpointer data);
static void gimp_toolbox_drop_component (GtkWidget *widget,
gint x,
gint y,
GimpImage *image,
GimpChannelType component,
gpointer data);
static void gimp_toolbox_drop_pixbuf (GtkWidget *widget,
gint x,
gint y,
GdkPixbuf *pixbuf,
gpointer data);
/* public functions */
void
gimp_toolbox_dnd_init (GimpToolbox *toolbox,
GtkWidget *vbox)
{
GimpContext *context = NULL;
g_return_if_fail (GIMP_IS_TOOLBOX (toolbox));
g_return_if_fail (GTK_IS_BOX (vbox));
context = gimp_toolbox_get_context (toolbox);
/* Before caling any dnd helper functions, setup the drag
* destination manually since we want to handle all drag events
* manually, otherwise we would not be able to give the drag handler
* a chance to handle drag events
*/
gtk_drag_dest_set (vbox,
0, NULL, 0,
GDK_ACTION_COPY | GDK_ACTION_MOVE);
gimp_dnd_viewable_dest_add (vbox,
GIMP_TYPE_LAYER,
gimp_toolbox_drop_drawable,
context);
gimp_dnd_viewable_dest_add (vbox,
GIMP_TYPE_LAYER_MASK,
gimp_toolbox_drop_drawable,
context);
gimp_dnd_viewable_dest_add (vbox,
GIMP_TYPE_CHANNEL,
gimp_toolbox_drop_drawable,
context);
gimp_dnd_viewable_dest_add (vbox,
GIMP_TYPE_TOOL_INFO,
gimp_toolbox_drop_tool,
context);
gimp_dnd_viewable_dest_add (vbox,
GIMP_TYPE_BUFFER,
gimp_toolbox_drop_buffer,
context);
gimp_dnd_component_dest_add (vbox,
gimp_toolbox_drop_component,
context);
gimp_dnd_uri_list_dest_add (vbox,
gimp_toolbox_drop_uri_list,
context);
gimp_dnd_pixbuf_dest_add (vbox,
gimp_toolbox_drop_pixbuf,
context);
}
/* private functions */
static void
gimp_toolbox_drop_uri_list (GtkWidget *widget,
gint x,
gint y,
GList *uri_list,
gpointer data)
{
GimpContext *context = GIMP_CONTEXT (data);
GList *list;
if (context->gimp->busy)
return;
for (list = uri_list; list; list = g_list_next (list))
{
GFile *file = g_file_new_for_uri (list->data);
GimpImage *image;
GimpPDBStatusType status;
GError *error = NULL;
image = file_open_with_display (context->gimp, context, NULL,
file, FALSE,
G_OBJECT (gtk_widget_get_screen (widget)),
gimp_widget_get_monitor (widget),
&status, &error);
if (! image && status != GIMP_PDB_CANCEL)
{
gimp_message (context->gimp, G_OBJECT (widget), GIMP_MESSAGE_ERROR,
_("Opening '%s' failed:\n\n%s"),
gimp_file_get_utf8_name (file), error->message);
g_clear_error (&error);
}
g_object_unref (file);
}
}
static void
gimp_toolbox_drop_drawable (GtkWidget *widget,
gint x,
gint y,
GimpViewable *viewable,
gpointer data)
{
GimpContext *context = GIMP_CONTEXT (data);
GimpImage *new_image;
if (context->gimp->busy)
return;
new_image = gimp_image_new_from_drawable (context->gimp,
GIMP_DRAWABLE (viewable));
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);
}
static void
gimp_toolbox_drop_tool (GtkWidget *widget,
gint x,
gint y,
GimpViewable *viewable,
gpointer data)
{
GimpContext *context = GIMP_CONTEXT (data);
if (context->gimp->busy)
return;
gimp_context_set_tool (context, GIMP_TOOL_INFO (viewable));
}
static void
gimp_toolbox_drop_buffer (GtkWidget *widget,
gint x,
gint y,
GimpViewable *viewable,
gpointer data)
{
GimpContext *context = GIMP_CONTEXT (data);
GimpImage *image;
if (context->gimp->busy)
return;
image = gimp_image_new_from_buffer (context->gimp,
GIMP_BUFFER (viewable));
gimp_create_display (image->gimp, image, GIMP_UNIT_PIXEL, 1.0,
G_OBJECT (gtk_widget_get_screen (widget)),
gimp_widget_get_monitor (widget));
g_object_unref (image);
}
static void
gimp_toolbox_drop_component (GtkWidget *widget,
gint x,
gint y,
GimpImage *image,
GimpChannelType component,
gpointer data)
{
GimpContext *context = GIMP_CONTEXT (data);
GimpImage *new_image;
if (context->gimp->busy)
return;
new_image = gimp_image_new_from_component (context->gimp,
image, component);
gimp_create_display (new_image->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);
}
static void
gimp_toolbox_drop_pixbuf (GtkWidget *widget,
gint x,
gint y,
GdkPixbuf *pixbuf,
gpointer data)
{
GimpContext *context = GIMP_CONTEXT (data);
GimpImage *new_image;
if (context->gimp->busy)
return;
new_image = gimp_image_new_from_pixbuf (context->gimp, pixbuf,
_("Dropped Buffer"));
gimp_create_display (new_image->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);
}