2817 lines
86 KiB
C
2817 lines
86 KiB
C
/* PIKA - Photo and Image Kooker Application
|
|
* a rebranding of The GNU Image Manipulation Program (created with heckimp)
|
|
* A derived work which may be trivial. However, any changes may be (C)2023 by Aldercone Studio
|
|
*
|
|
* Original copyright, applying to most contents (license remains unchanged):
|
|
* Copyright (C) 1995-1997 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 <https://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <gegl.h>
|
|
#include <gtk/gtk.h>
|
|
#include <math.h>
|
|
|
|
#include "libpikacolor/pikacolor.h"
|
|
#include "libpikawidgets/pikawidgets.h"
|
|
|
|
#include "widgets-types.h"
|
|
|
|
#include "config/pikacoreconfig.h"
|
|
|
|
#include "core/pika.h"
|
|
#include "core/pikabrush.h"
|
|
#include "core/pikabuffer.h"
|
|
#include "core/pikachannel.h"
|
|
#include "core/pikacontainer.h"
|
|
#include "core/pikadatafactory.h"
|
|
#include "core/pikadrawable.h"
|
|
#include "core/pikagradient.h"
|
|
#include "core/pikaimage.h"
|
|
#include "core/pikaimagefile.h"
|
|
#include "core/pikalayer.h"
|
|
#include "core/pikalayermask.h"
|
|
#include "core/pikapalette.h"
|
|
#include "core/pikapattern.h"
|
|
#include "core/pikatemplate.h"
|
|
#include "core/pikatoolitem.h"
|
|
|
|
#include "text/pikafont.h"
|
|
|
|
#include "vectors/pikavectors.h"
|
|
|
|
#include "pikadnd.h"
|
|
#include "pikadnd-xds.h"
|
|
#include "pikapixbuf.h"
|
|
#include "pikaselectiondata.h"
|
|
#include "pikaview.h"
|
|
#include "pikaviewrendererimage.h"
|
|
|
|
#include "pika-log.h"
|
|
#include "pika-intl.h"
|
|
|
|
|
|
#define DRAG_PREVIEW_SIZE PIKA_VIEW_SIZE_LARGE
|
|
#define DRAG_ICON_OFFSET -8
|
|
|
|
|
|
typedef GtkWidget * (* PikaDndGetIconFunc) (GtkWidget *widget,
|
|
GdkDragContext *context,
|
|
GCallback get_data_func,
|
|
gpointer get_data_data);
|
|
typedef void (* PikaDndDragDataFunc) (GtkWidget *widget,
|
|
GdkDragContext *context,
|
|
GCallback get_data_func,
|
|
gpointer get_data_data,
|
|
GtkSelectionData *selection);
|
|
typedef gboolean (* PikaDndDropDataFunc) (GtkWidget *widget,
|
|
gint x,
|
|
gint y,
|
|
GCallback set_data_func,
|
|
gpointer set_data_data,
|
|
GtkSelectionData *selection);
|
|
|
|
|
|
typedef struct _PikaDndDataDef PikaDndDataDef;
|
|
|
|
struct _PikaDndDataDef
|
|
{
|
|
GtkTargetEntry target_entry;
|
|
|
|
const gchar *get_data_func_name;
|
|
const gchar *get_data_data_name;
|
|
|
|
const gchar *set_data_func_name;
|
|
const gchar *set_data_data_name;
|
|
|
|
PikaDndGetIconFunc get_icon_func;
|
|
PikaDndDragDataFunc get_data_func;
|
|
PikaDndDropDataFunc set_data_func;
|
|
};
|
|
|
|
|
|
static GtkWidget * pika_dnd_get_viewable_list_icon (GtkWidget *widget,
|
|
GdkDragContext *context,
|
|
GCallback get_viewable_list_func,
|
|
gpointer get_viewable_list_data);
|
|
static GtkWidget * pika_dnd_get_viewable_icon (GtkWidget *widget,
|
|
GdkDragContext *context,
|
|
GCallback get_viewable_func,
|
|
gpointer get_viewable_data);
|
|
static GtkWidget * pika_dnd_get_component_icon (GtkWidget *widget,
|
|
GdkDragContext *context,
|
|
GCallback get_comp_func,
|
|
gpointer get_comp_data);
|
|
static GtkWidget * pika_dnd_get_color_icon (GtkWidget *widget,
|
|
GdkDragContext *context,
|
|
GCallback get_color_func,
|
|
gpointer get_color_data);
|
|
|
|
static void pika_dnd_get_uri_list_data (GtkWidget *widget,
|
|
GdkDragContext *context,
|
|
GCallback get_uri_list_func,
|
|
gpointer get_uri_list_data,
|
|
GtkSelectionData *selection);
|
|
static gboolean pika_dnd_set_uri_list_data (GtkWidget *widget,
|
|
gint x,
|
|
gint y,
|
|
GCallback set_uri_list_func,
|
|
gpointer set_uri_list_data,
|
|
GtkSelectionData *selection);
|
|
|
|
static void pika_dnd_get_xds_data (GtkWidget *widget,
|
|
GdkDragContext *context,
|
|
GCallback get_image_func,
|
|
gpointer get_image_data,
|
|
GtkSelectionData *selection);
|
|
|
|
static void pika_dnd_get_color_data (GtkWidget *widget,
|
|
GdkDragContext *context,
|
|
GCallback get_color_func,
|
|
gpointer get_color_data,
|
|
GtkSelectionData *selection);
|
|
static gboolean pika_dnd_set_color_data (GtkWidget *widget,
|
|
gint x,
|
|
gint y,
|
|
GCallback set_color_func,
|
|
gpointer set_color_data,
|
|
GtkSelectionData *selection);
|
|
|
|
static void pika_dnd_get_stream_data (GtkWidget *widget,
|
|
GdkDragContext *context,
|
|
GCallback get_stream_func,
|
|
gpointer get_stream_data,
|
|
GtkSelectionData *selection);
|
|
static gboolean pika_dnd_set_stream_data (GtkWidget *widget,
|
|
gint x,
|
|
gint y,
|
|
GCallback set_stream_func,
|
|
gpointer set_stream_data,
|
|
GtkSelectionData *selection);
|
|
|
|
static void pika_dnd_get_pixbuf_data (GtkWidget *widget,
|
|
GdkDragContext *context,
|
|
GCallback get_pixbuf_func,
|
|
gpointer get_pixbuf_data,
|
|
GtkSelectionData *selection);
|
|
static gboolean pika_dnd_set_pixbuf_data (GtkWidget *widget,
|
|
gint x,
|
|
gint y,
|
|
GCallback set_pixbuf_func,
|
|
gpointer set_pixbuf_data,
|
|
GtkSelectionData *selection);
|
|
static void pika_dnd_get_component_data (GtkWidget *widget,
|
|
GdkDragContext *context,
|
|
GCallback get_comp_func,
|
|
gpointer get_comp_data,
|
|
GtkSelectionData *selection);
|
|
static gboolean pika_dnd_set_component_data (GtkWidget *widget,
|
|
gint x,
|
|
gint y,
|
|
GCallback set_comp_func,
|
|
gpointer set_comp_data,
|
|
GtkSelectionData *selection);
|
|
|
|
static void pika_dnd_get_image_data (GtkWidget *widget,
|
|
GdkDragContext *context,
|
|
GCallback get_image_func,
|
|
gpointer get_image_data,
|
|
GtkSelectionData *selection);
|
|
static gboolean pika_dnd_set_image_data (GtkWidget *widget,
|
|
gint x,
|
|
gint y,
|
|
GCallback set_image_func,
|
|
gpointer set_image_data,
|
|
GtkSelectionData *selection);
|
|
|
|
static void pika_dnd_get_item_data (GtkWidget *widget,
|
|
GdkDragContext *context,
|
|
GCallback get_item_func,
|
|
gpointer get_item_data,
|
|
GtkSelectionData *selection);
|
|
static gboolean pika_dnd_set_item_data (GtkWidget *widget,
|
|
gint x,
|
|
gint y,
|
|
GCallback set_item_func,
|
|
gpointer set_item_data,
|
|
GtkSelectionData *selection);
|
|
|
|
static void pika_dnd_get_item_list_data (GtkWidget *widget,
|
|
GdkDragContext *context,
|
|
GCallback get_item_func,
|
|
gpointer get_item_data,
|
|
GtkSelectionData *selection);
|
|
static gboolean pika_dnd_set_item_list_data (GtkWidget *widget,
|
|
gint x,
|
|
gint y,
|
|
GCallback set_item_func,
|
|
gpointer set_item_data,
|
|
GtkSelectionData *selection);
|
|
|
|
static void pika_dnd_get_object_data (GtkWidget *widget,
|
|
GdkDragContext *context,
|
|
GCallback get_object_func,
|
|
gpointer get_object_data,
|
|
GtkSelectionData *selection);
|
|
|
|
static gboolean pika_dnd_set_brush_data (GtkWidget *widget,
|
|
gint x,
|
|
gint y,
|
|
GCallback set_brush_func,
|
|
gpointer set_brush_data,
|
|
GtkSelectionData *selection);
|
|
static gboolean pika_dnd_set_pattern_data (GtkWidget *widget,
|
|
gint x,
|
|
gint y,
|
|
GCallback set_pattern_func,
|
|
gpointer set_pattern_data,
|
|
GtkSelectionData *selection);
|
|
static gboolean pika_dnd_set_gradient_data (GtkWidget *widget,
|
|
gint x,
|
|
gint y,
|
|
GCallback set_gradient_func,
|
|
gpointer set_gradient_data,
|
|
GtkSelectionData *selection);
|
|
static gboolean pika_dnd_set_palette_data (GtkWidget *widget,
|
|
gint x,
|
|
gint y,
|
|
GCallback set_palette_func,
|
|
gpointer set_palette_data,
|
|
GtkSelectionData *selection);
|
|
static gboolean pika_dnd_set_font_data (GtkWidget *widget,
|
|
gint x,
|
|
gint y,
|
|
GCallback set_font_func,
|
|
gpointer set_font_data,
|
|
GtkSelectionData *selection);
|
|
static gboolean pika_dnd_set_buffer_data (GtkWidget *widget,
|
|
gint x,
|
|
gint y,
|
|
GCallback set_buffer_func,
|
|
gpointer set_buffer_data,
|
|
GtkSelectionData *selection);
|
|
static gboolean pika_dnd_set_imagefile_data (GtkWidget *widget,
|
|
gint x,
|
|
gint y,
|
|
GCallback set_imagefile_func,
|
|
gpointer set_imagefile_data,
|
|
GtkSelectionData *selection);
|
|
static gboolean pika_dnd_set_template_data (GtkWidget *widget,
|
|
gint x,
|
|
gint y,
|
|
GCallback set_template_func,
|
|
gpointer set_template_data,
|
|
GtkSelectionData *selection);
|
|
static gboolean pika_dnd_set_tool_item_data (GtkWidget *widget,
|
|
gint x,
|
|
gint y,
|
|
GCallback set_tool_item_func,
|
|
gpointer set_tool_item_data,
|
|
GtkSelectionData *selection);
|
|
|
|
|
|
|
|
static const PikaDndDataDef dnd_data_defs[] =
|
|
{
|
|
{
|
|
{ NULL, 0, -1 },
|
|
|
|
NULL,
|
|
NULL,
|
|
|
|
NULL,
|
|
NULL,
|
|
NULL
|
|
},
|
|
|
|
{
|
|
PIKA_TARGET_URI_LIST,
|
|
|
|
"pika-dnd-get-uri-list-func",
|
|
"pika-dnd-get-uri-list-data",
|
|
|
|
"pika-dnd-set-uri-list-func",
|
|
"pika-dnd-set-uri-list-data",
|
|
|
|
NULL,
|
|
pika_dnd_get_uri_list_data,
|
|
pika_dnd_set_uri_list_data
|
|
},
|
|
|
|
{
|
|
PIKA_TARGET_TEXT_PLAIN,
|
|
|
|
NULL,
|
|
NULL,
|
|
|
|
"pika-dnd-set-uri-list-func",
|
|
"pika-dnd-set-uri-list-data",
|
|
|
|
NULL,
|
|
NULL,
|
|
pika_dnd_set_uri_list_data
|
|
},
|
|
|
|
{
|
|
PIKA_TARGET_NETSCAPE_URL,
|
|
|
|
NULL,
|
|
NULL,
|
|
|
|
"pika-dnd-set-uri-list-func",
|
|
"pika-dnd-set-uri-list-data",
|
|
|
|
NULL,
|
|
NULL,
|
|
pika_dnd_set_uri_list_data
|
|
},
|
|
|
|
{
|
|
PIKA_TARGET_XDS,
|
|
|
|
"pika-dnd-get-xds-func",
|
|
"pika-dnd-get-xds-data",
|
|
|
|
NULL,
|
|
NULL,
|
|
|
|
pika_dnd_get_viewable_icon,
|
|
pika_dnd_get_xds_data,
|
|
NULL
|
|
},
|
|
|
|
{
|
|
PIKA_TARGET_COLOR,
|
|
|
|
"pika-dnd-get-color-func",
|
|
"pika-dnd-get-color-data",
|
|
|
|
"pika-dnd-set-color-func",
|
|
"pika-dnd-set-color-data",
|
|
|
|
pika_dnd_get_color_icon,
|
|
pika_dnd_get_color_data,
|
|
pika_dnd_set_color_data
|
|
},
|
|
|
|
{
|
|
PIKA_TARGET_SVG,
|
|
|
|
"pika-dnd-get-svg-func",
|
|
"pika-dnd-get-svg-data",
|
|
|
|
"pika-dnd-set-svg-func",
|
|
"pika-dnd-set-svg-data",
|
|
|
|
pika_dnd_get_viewable_icon,
|
|
pika_dnd_get_stream_data,
|
|
pika_dnd_set_stream_data
|
|
},
|
|
|
|
{
|
|
PIKA_TARGET_SVG_XML,
|
|
|
|
"pika-dnd-get-svg-xml-func",
|
|
"pika-dnd-get-svg-xml-data",
|
|
|
|
"pika-dnd-set-svg-xml-func",
|
|
"pika-dnd-set-svg-xml-data",
|
|
|
|
pika_dnd_get_viewable_icon,
|
|
pika_dnd_get_stream_data,
|
|
pika_dnd_set_stream_data
|
|
},
|
|
|
|
{
|
|
PIKA_TARGET_PIXBUF,
|
|
|
|
"pika-dnd-get-pixbuf-func",
|
|
"pika-dnd-get-pixbuf-data",
|
|
|
|
"pika-dnd-set-pixbuf-func",
|
|
"pika-dnd-set-pixbuf-data",
|
|
|
|
pika_dnd_get_viewable_icon,
|
|
pika_dnd_get_pixbuf_data,
|
|
pika_dnd_set_pixbuf_data
|
|
},
|
|
|
|
{
|
|
PIKA_TARGET_IMAGE,
|
|
|
|
"pika-dnd-get-image-func",
|
|
"pika-dnd-get-image-data",
|
|
|
|
"pika-dnd-set-image-func",
|
|
"pika-dnd-set-image-data",
|
|
|
|
pika_dnd_get_viewable_icon,
|
|
pika_dnd_get_image_data,
|
|
pika_dnd_set_image_data,
|
|
},
|
|
|
|
{
|
|
PIKA_TARGET_COMPONENT,
|
|
|
|
"pika-dnd-get-component-func",
|
|
"pika-dnd-get-component-data",
|
|
|
|
"pika-dnd-set-component-func",
|
|
"pika-dnd-set-component-data",
|
|
|
|
pika_dnd_get_component_icon,
|
|
pika_dnd_get_component_data,
|
|
pika_dnd_set_component_data,
|
|
},
|
|
|
|
{
|
|
PIKA_TARGET_LAYER,
|
|
|
|
"pika-dnd-get-layer-func",
|
|
"pika-dnd-get-layer-data",
|
|
|
|
"pika-dnd-set-layer-func",
|
|
"pika-dnd-set-layer-data",
|
|
|
|
pika_dnd_get_viewable_icon,
|
|
pika_dnd_get_item_data,
|
|
pika_dnd_set_item_data,
|
|
},
|
|
|
|
{
|
|
PIKA_TARGET_CHANNEL,
|
|
|
|
"pika-dnd-get-channel-func",
|
|
"pika-dnd-get-channel-data",
|
|
|
|
"pika-dnd-set-channel-func",
|
|
"pika-dnd-set-channel-data",
|
|
|
|
pika_dnd_get_viewable_icon,
|
|
pika_dnd_get_item_data,
|
|
pika_dnd_set_item_data,
|
|
},
|
|
|
|
{
|
|
PIKA_TARGET_LAYER_MASK,
|
|
|
|
"pika-dnd-get-layer-mask-func",
|
|
"pika-dnd-get-layer-mask-data",
|
|
|
|
"pika-dnd-set-layer-mask-func",
|
|
"pika-dnd-set-layer-mask-data",
|
|
|
|
pika_dnd_get_viewable_icon,
|
|
pika_dnd_get_item_data,
|
|
pika_dnd_set_item_data,
|
|
},
|
|
|
|
{
|
|
PIKA_TARGET_VECTORS,
|
|
|
|
"pika-dnd-get-vectors-func",
|
|
"pika-dnd-get-vectors-data",
|
|
|
|
"pika-dnd-set-vectors-func",
|
|
"pika-dnd-set-vectors-data",
|
|
|
|
pika_dnd_get_viewable_icon,
|
|
pika_dnd_get_item_data,
|
|
pika_dnd_set_item_data,
|
|
},
|
|
|
|
{
|
|
PIKA_TARGET_BRUSH,
|
|
|
|
"pika-dnd-get-brush-func",
|
|
"pika-dnd-get-brush-data",
|
|
|
|
"pika-dnd-set-brush-func",
|
|
"pika-dnd-set-brush-data",
|
|
|
|
pika_dnd_get_viewable_icon,
|
|
pika_dnd_get_object_data,
|
|
pika_dnd_set_brush_data
|
|
},
|
|
|
|
{
|
|
PIKA_TARGET_PATTERN,
|
|
|
|
"pika-dnd-get-pattern-func",
|
|
"pika-dnd-get-pattern-data",
|
|
|
|
"pika-dnd-set-pattern-func",
|
|
"pika-dnd-set-pattern-data",
|
|
|
|
pika_dnd_get_viewable_icon,
|
|
pika_dnd_get_object_data,
|
|
pika_dnd_set_pattern_data
|
|
},
|
|
|
|
{
|
|
PIKA_TARGET_GRADIENT,
|
|
|
|
"pika-dnd-get-gradient-func",
|
|
"pika-dnd-get-gradient-data",
|
|
|
|
"pika-dnd-set-gradient-func",
|
|
"pika-dnd-set-gradient-data",
|
|
|
|
pika_dnd_get_viewable_icon,
|
|
pika_dnd_get_object_data,
|
|
pika_dnd_set_gradient_data
|
|
},
|
|
|
|
{
|
|
PIKA_TARGET_PALETTE,
|
|
|
|
"pika-dnd-get-palette-func",
|
|
"pika-dnd-get-palette-data",
|
|
|
|
"pika-dnd-set-palette-func",
|
|
"pika-dnd-set-palette-data",
|
|
|
|
pika_dnd_get_viewable_icon,
|
|
pika_dnd_get_object_data,
|
|
pika_dnd_set_palette_data
|
|
},
|
|
|
|
{
|
|
PIKA_TARGET_FONT,
|
|
|
|
"pika-dnd-get-font-func",
|
|
"pika-dnd-get-font-data",
|
|
|
|
"pika-dnd-set-font-func",
|
|
"pika-dnd-set-font-data",
|
|
|
|
pika_dnd_get_viewable_icon,
|
|
pika_dnd_get_object_data,
|
|
pika_dnd_set_font_data
|
|
},
|
|
|
|
{
|
|
PIKA_TARGET_BUFFER,
|
|
|
|
"pika-dnd-get-buffer-func",
|
|
"pika-dnd-get-buffer-data",
|
|
|
|
"pika-dnd-set-buffer-func",
|
|
"pika-dnd-set-buffer-data",
|
|
|
|
pika_dnd_get_viewable_icon,
|
|
pika_dnd_get_object_data,
|
|
pika_dnd_set_buffer_data
|
|
},
|
|
|
|
{
|
|
PIKA_TARGET_IMAGEFILE,
|
|
|
|
"pika-dnd-get-imagefile-func",
|
|
"pika-dnd-get-imagefile-data",
|
|
|
|
"pika-dnd-set-imagefile-func",
|
|
"pika-dnd-set-imagefile-data",
|
|
|
|
pika_dnd_get_viewable_icon,
|
|
pika_dnd_get_object_data,
|
|
pika_dnd_set_imagefile_data
|
|
},
|
|
|
|
{
|
|
PIKA_TARGET_TEMPLATE,
|
|
|
|
"pika-dnd-get-template-func",
|
|
"pika-dnd-get-template-data",
|
|
|
|
"pika-dnd-set-template-func",
|
|
"pika-dnd-set-template-data",
|
|
|
|
pika_dnd_get_viewable_icon,
|
|
pika_dnd_get_object_data,
|
|
pika_dnd_set_template_data
|
|
},
|
|
|
|
{
|
|
PIKA_TARGET_TOOL_ITEM,
|
|
|
|
"pika-dnd-get-tool-item-func",
|
|
"pika-dnd-get-tool-item-data",
|
|
|
|
"pika-dnd-set-tool-item-func",
|
|
"pika-dnd-set-tool-item-data",
|
|
|
|
pika_dnd_get_viewable_icon,
|
|
pika_dnd_get_object_data,
|
|
pika_dnd_set_tool_item_data
|
|
},
|
|
|
|
{
|
|
PIKA_TARGET_NOTEBOOK_TAB,
|
|
|
|
NULL,
|
|
NULL,
|
|
|
|
NULL,
|
|
NULL,
|
|
|
|
NULL,
|
|
NULL,
|
|
NULL
|
|
},
|
|
|
|
{
|
|
PIKA_TARGET_LAYER_LIST,
|
|
|
|
"pika-dnd-get-layer-list-func",
|
|
"pika-dnd-get-layer-list-data",
|
|
|
|
"pika-dnd-set-layer-list-func",
|
|
"pika-dnd-set-layer-list-data",
|
|
|
|
pika_dnd_get_viewable_list_icon,
|
|
pika_dnd_get_item_list_data,
|
|
pika_dnd_set_item_list_data,
|
|
},
|
|
|
|
{
|
|
PIKA_TARGET_CHANNEL_LIST,
|
|
|
|
"pika-dnd-get-channel-list-func",
|
|
"pika-dnd-get-channel-list-data",
|
|
|
|
"pika-dnd-set-channel-list-func",
|
|
"pika-dnd-set-channel-list-data",
|
|
|
|
pika_dnd_get_viewable_list_icon,
|
|
pika_dnd_get_item_list_data,
|
|
pika_dnd_set_item_list_data,
|
|
},
|
|
|
|
{
|
|
PIKA_TARGET_VECTORS_LIST,
|
|
|
|
"pika-dnd-get-vectors-list-func",
|
|
"pika-dnd-get-vectors-list-data",
|
|
|
|
"pika-dnd-set-vectors-list-func",
|
|
"pika-dnd-set-vectors-list-data",
|
|
|
|
pika_dnd_get_viewable_list_icon,
|
|
pika_dnd_get_item_list_data,
|
|
pika_dnd_set_item_list_data,
|
|
},
|
|
|
|
};
|
|
|
|
|
|
static Pika *the_dnd_pika = NULL;
|
|
|
|
|
|
void
|
|
pika_dnd_init (Pika *pika)
|
|
{
|
|
g_return_if_fail (PIKA_IS_PIKA (pika));
|
|
g_return_if_fail (the_dnd_pika == NULL);
|
|
|
|
the_dnd_pika = pika;
|
|
}
|
|
|
|
|
|
/**********************/
|
|
/* helper functions */
|
|
/**********************/
|
|
|
|
static void
|
|
pika_dnd_target_list_add (GtkTargetList *list,
|
|
const GtkTargetEntry *entry)
|
|
{
|
|
GdkAtom atom = gdk_atom_intern (entry->target, FALSE);
|
|
guint info;
|
|
|
|
if (! gtk_target_list_find (list, atom, &info) || info != entry->info)
|
|
{
|
|
gtk_target_list_add (list, atom, entry->flags, entry->info);
|
|
}
|
|
}
|
|
|
|
|
|
/********************************/
|
|
/* general data dnd functions */
|
|
/********************************/
|
|
|
|
static void
|
|
pika_dnd_data_drag_begin (GtkWidget *widget,
|
|
GdkDragContext *context,
|
|
gpointer data)
|
|
{
|
|
const PikaDndDataDef *dnd_data;
|
|
PikaDndType data_type;
|
|
GCallback get_data_func = NULL;
|
|
gpointer get_data_data = NULL;
|
|
GtkWidget *icon_widget;
|
|
|
|
data_type = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget),
|
|
"pika-dnd-get-data-type"));
|
|
|
|
PIKA_LOG (DND, "data type %d", data_type);
|
|
|
|
if (! data_type)
|
|
return;
|
|
|
|
dnd_data = dnd_data_defs + data_type;
|
|
|
|
if (dnd_data->get_data_func_name)
|
|
get_data_func = g_object_get_data (G_OBJECT (widget),
|
|
dnd_data->get_data_func_name);
|
|
|
|
if (dnd_data->get_data_data_name)
|
|
get_data_data = g_object_get_data (G_OBJECT (widget),
|
|
dnd_data->get_data_data_name);
|
|
|
|
if (! get_data_func)
|
|
return;
|
|
|
|
icon_widget = dnd_data->get_icon_func (widget,
|
|
context,
|
|
get_data_func,
|
|
get_data_data);
|
|
|
|
if (icon_widget)
|
|
{
|
|
GtkWidget *frame;
|
|
GtkWidget *window;
|
|
|
|
window = gtk_window_new (GTK_WINDOW_POPUP);
|
|
gtk_window_set_type_hint (GTK_WINDOW (window), GDK_WINDOW_TYPE_HINT_DND);
|
|
gtk_window_set_screen (GTK_WINDOW (window),
|
|
gtk_widget_get_screen (widget));
|
|
|
|
gtk_widget_realize (window);
|
|
|
|
frame = gtk_frame_new (NULL);
|
|
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT);
|
|
gtk_container_add (GTK_CONTAINER (window), frame);
|
|
gtk_widget_show (frame);
|
|
|
|
gtk_container_add (GTK_CONTAINER (frame), icon_widget);
|
|
gtk_widget_show (icon_widget);
|
|
|
|
g_object_set_data_full (G_OBJECT (widget), "pika-dnd-data-widget",
|
|
window, (GDestroyNotify) gtk_widget_destroy);
|
|
|
|
gtk_drag_set_icon_widget (context, window,
|
|
DRAG_ICON_OFFSET, DRAG_ICON_OFFSET);
|
|
|
|
/* remember for which drag context the widget was made */
|
|
g_object_set_data (G_OBJECT (window), "pika-gdk-drag-context", context);
|
|
}
|
|
}
|
|
|
|
static void
|
|
pika_dnd_data_drag_end (GtkWidget *widget,
|
|
GdkDragContext *context)
|
|
{
|
|
PikaDndType data_type;
|
|
GtkWidget *icon_widget;
|
|
|
|
data_type = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget),
|
|
"pika-dnd-get-data-type"));
|
|
|
|
PIKA_LOG (DND, "data type %d", data_type);
|
|
|
|
icon_widget = g_object_get_data (G_OBJECT (widget), "pika-dnd-data-widget");
|
|
|
|
if (icon_widget)
|
|
{
|
|
/* destroy the icon_widget only if it was made for this drag
|
|
* context. See bug #139337.
|
|
*/
|
|
if (g_object_get_data (G_OBJECT (icon_widget),
|
|
"pika-gdk-drag-context") ==
|
|
(gpointer) context)
|
|
{
|
|
g_object_set_data (G_OBJECT (widget), "pika-dnd-data-widget", NULL);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
pika_dnd_data_drag_handle (GtkWidget *widget,
|
|
GdkDragContext *context,
|
|
GtkSelectionData *selection_data,
|
|
guint info,
|
|
guint time,
|
|
gpointer data)
|
|
{
|
|
GCallback get_data_func = NULL;
|
|
gpointer get_data_data = NULL;
|
|
PikaDndType data_type;
|
|
|
|
PIKA_LOG (DND, "data type %d", info);
|
|
|
|
for (data_type = PIKA_DND_TYPE_NONE + 1;
|
|
data_type <= PIKA_DND_TYPE_LAST;
|
|
data_type++)
|
|
{
|
|
const PikaDndDataDef *dnd_data = dnd_data_defs + data_type;
|
|
|
|
if (dnd_data->target_entry.info == info)
|
|
{
|
|
PIKA_LOG (DND, "target %s", dnd_data->target_entry.target);
|
|
|
|
if (dnd_data->get_data_func_name)
|
|
get_data_func = g_object_get_data (G_OBJECT (widget),
|
|
dnd_data->get_data_func_name);
|
|
|
|
if (dnd_data->get_data_data_name)
|
|
get_data_data = g_object_get_data (G_OBJECT (widget),
|
|
dnd_data->get_data_data_name);
|
|
|
|
if (! get_data_func)
|
|
return;
|
|
|
|
dnd_data->get_data_func (widget,
|
|
context,
|
|
get_data_func,
|
|
get_data_data,
|
|
selection_data);
|
|
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
pika_dnd_data_drop_handle (GtkWidget *widget,
|
|
GdkDragContext *context,
|
|
gint x,
|
|
gint y,
|
|
GtkSelectionData *selection_data,
|
|
guint info,
|
|
guint time,
|
|
gpointer data)
|
|
{
|
|
PikaDndType data_type;
|
|
|
|
PIKA_LOG (DND, "data type %d", info);
|
|
|
|
if (gtk_selection_data_get_length (selection_data) <= 0)
|
|
{
|
|
gtk_drag_finish (context, FALSE, FALSE, time);
|
|
return;
|
|
}
|
|
|
|
for (data_type = PIKA_DND_TYPE_NONE + 1;
|
|
data_type <= PIKA_DND_TYPE_LAST;
|
|
data_type++)
|
|
{
|
|
const PikaDndDataDef *dnd_data = dnd_data_defs + data_type;
|
|
|
|
if (dnd_data->target_entry.info == info)
|
|
{
|
|
GCallback set_data_func = NULL;
|
|
gpointer set_data_data = NULL;
|
|
|
|
PIKA_LOG (DND, "target %s", dnd_data->target_entry.target);
|
|
|
|
if (dnd_data->set_data_func_name)
|
|
set_data_func = g_object_get_data (G_OBJECT (widget),
|
|
dnd_data->set_data_func_name);
|
|
|
|
if (dnd_data->set_data_data_name)
|
|
set_data_data = g_object_get_data (G_OBJECT (widget),
|
|
dnd_data->set_data_data_name);
|
|
|
|
if (set_data_func &&
|
|
dnd_data->set_data_func (widget, x, y,
|
|
set_data_func,
|
|
set_data_data,
|
|
selection_data))
|
|
{
|
|
gtk_drag_finish (context, TRUE, FALSE, time);
|
|
return;
|
|
}
|
|
|
|
gtk_drag_finish (context, FALSE, FALSE, time);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
pika_dnd_data_source_add (PikaDndType data_type,
|
|
GtkWidget *widget,
|
|
GCallback get_data_func,
|
|
gpointer get_data_data)
|
|
{
|
|
const PikaDndDataDef *dnd_data;
|
|
gboolean drag_connected;
|
|
|
|
dnd_data = dnd_data_defs + data_type;
|
|
|
|
/* set a default drag source if not already done */
|
|
if (! g_object_get_data (G_OBJECT (widget), "gtk-site-data"))
|
|
gtk_drag_source_set (widget, GDK_BUTTON1_MASK | GDK_BUTTON2_MASK,
|
|
NULL, 0,
|
|
GDK_ACTION_COPY | GDK_ACTION_MOVE);
|
|
|
|
drag_connected =
|
|
GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget),
|
|
"pika-dnd-drag-connected"));
|
|
|
|
if (! drag_connected)
|
|
{
|
|
g_signal_connect (widget, "drag-begin",
|
|
G_CALLBACK (pika_dnd_data_drag_begin),
|
|
NULL);
|
|
g_signal_connect (widget, "drag-end",
|
|
G_CALLBACK (pika_dnd_data_drag_end),
|
|
NULL);
|
|
g_signal_connect (widget, "drag-data-get",
|
|
G_CALLBACK (pika_dnd_data_drag_handle),
|
|
NULL);
|
|
|
|
g_object_set_data (G_OBJECT (widget), "pika-dnd-drag-connected",
|
|
GINT_TO_POINTER (TRUE));
|
|
}
|
|
|
|
g_object_set_data (G_OBJECT (widget), dnd_data->get_data_func_name,
|
|
get_data_func);
|
|
g_object_set_data (G_OBJECT (widget), dnd_data->get_data_data_name,
|
|
get_data_data);
|
|
|
|
/* remember the first set source type for drag view creation */
|
|
if (! g_object_get_data (G_OBJECT (widget), "pika-dnd-get-data-type"))
|
|
g_object_set_data (G_OBJECT (widget), "pika-dnd-get-data-type",
|
|
GINT_TO_POINTER (data_type));
|
|
|
|
if (dnd_data->target_entry.target)
|
|
{
|
|
GtkTargetList *target_list;
|
|
|
|
target_list = gtk_drag_source_get_target_list (widget);
|
|
|
|
if (target_list)
|
|
{
|
|
pika_dnd_target_list_add (target_list, &dnd_data->target_entry);
|
|
}
|
|
else
|
|
{
|
|
target_list = gtk_target_list_new (&dnd_data->target_entry, 1);
|
|
|
|
gtk_drag_source_set_target_list (widget, target_list);
|
|
gtk_target_list_unref (target_list);
|
|
}
|
|
}
|
|
}
|
|
|
|
static gboolean
|
|
pika_dnd_data_source_remove (PikaDndType data_type,
|
|
GtkWidget *widget)
|
|
{
|
|
const PikaDndDataDef *dnd_data;
|
|
gboolean drag_connected;
|
|
gboolean list_changed = FALSE;
|
|
|
|
drag_connected =
|
|
GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget),
|
|
"pika-dnd-drag-connected"));
|
|
|
|
if (! drag_connected)
|
|
return FALSE;
|
|
|
|
dnd_data = dnd_data_defs + data_type;
|
|
|
|
g_object_set_data (G_OBJECT (widget), dnd_data->get_data_func_name, NULL);
|
|
g_object_set_data (G_OBJECT (widget), dnd_data->get_data_data_name, NULL);
|
|
|
|
/* remove the dnd type remembered for the dnd icon */
|
|
if (data_type ==
|
|
GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget),
|
|
"pika-dnd-get-data-type")))
|
|
g_object_set_data (G_OBJECT (widget), "pika-dnd-get-data-type", NULL);
|
|
|
|
if (dnd_data->target_entry.target)
|
|
{
|
|
/* Don't just remove the target from the existing list, create a
|
|
* new list without the target and replace the old list. The
|
|
* source's target list is part of a drag operation's state, but
|
|
* only by reference, it's not copied. So when we change the
|
|
* list, we would change the state of that ongoing drag, making
|
|
* it impossible to drop anything. See bug #676522.
|
|
*/
|
|
GtkTargetList *target_list = gtk_drag_source_get_target_list (widget);
|
|
|
|
if (target_list)
|
|
{
|
|
GtkTargetList *new_list;
|
|
GtkTargetEntry *targets;
|
|
gint n_targets_old;
|
|
gint n_targets_new;
|
|
gint i;
|
|
|
|
targets = gtk_target_table_new_from_list (target_list, &n_targets_old);
|
|
|
|
new_list = gtk_target_list_new (NULL, 0);
|
|
|
|
for (i = 0; i < n_targets_old; i++)
|
|
{
|
|
if (targets[i].info != data_type)
|
|
{
|
|
gtk_target_list_add (new_list,
|
|
gdk_atom_intern (targets[i].target, FALSE),
|
|
targets[i].flags,
|
|
targets[i].info);
|
|
}
|
|
}
|
|
|
|
gtk_target_table_free (targets, n_targets_old);
|
|
|
|
targets = gtk_target_table_new_from_list (new_list, &n_targets_new);
|
|
gtk_target_table_free (targets, n_targets_new);
|
|
|
|
if (n_targets_old != n_targets_new)
|
|
{
|
|
list_changed = TRUE;
|
|
|
|
if (n_targets_new > 0)
|
|
gtk_drag_source_set_target_list (widget, new_list);
|
|
else
|
|
gtk_drag_source_set_target_list (widget, NULL);
|
|
}
|
|
|
|
gtk_target_list_unref (new_list);
|
|
}
|
|
}
|
|
|
|
return list_changed;
|
|
}
|
|
|
|
static void
|
|
pika_dnd_data_dest_add (PikaDndType data_type,
|
|
GtkWidget *widget,
|
|
gpointer set_data_func,
|
|
gpointer set_data_data)
|
|
{
|
|
const PikaDndDataDef *dnd_data;
|
|
gboolean drop_connected;
|
|
|
|
/* set a default drag dest if not already done */
|
|
if (! g_object_get_data (G_OBJECT (widget), "gtk-drag-dest"))
|
|
gtk_drag_dest_set (widget, GTK_DEST_DEFAULT_ALL, NULL, 0, GDK_ACTION_COPY);
|
|
|
|
drop_connected =
|
|
GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget),
|
|
"pika-dnd-drop-connected"));
|
|
|
|
if (set_data_func && ! drop_connected)
|
|
{
|
|
g_signal_connect (widget, "drag-data-received",
|
|
G_CALLBACK (pika_dnd_data_drop_handle),
|
|
NULL);
|
|
|
|
g_object_set_data (G_OBJECT (widget), "pika-dnd-drop-connected",
|
|
GINT_TO_POINTER (TRUE));
|
|
}
|
|
|
|
dnd_data = dnd_data_defs + data_type;
|
|
|
|
if (set_data_func)
|
|
{
|
|
g_object_set_data (G_OBJECT (widget), dnd_data->set_data_func_name,
|
|
set_data_func);
|
|
g_object_set_data (G_OBJECT (widget), dnd_data->set_data_data_name,
|
|
set_data_data);
|
|
}
|
|
|
|
if (dnd_data->target_entry.target)
|
|
{
|
|
GtkTargetList *target_list;
|
|
|
|
target_list = gtk_drag_dest_get_target_list (widget);
|
|
|
|
if (target_list)
|
|
{
|
|
pika_dnd_target_list_add (target_list, &dnd_data->target_entry);
|
|
}
|
|
else
|
|
{
|
|
target_list = gtk_target_list_new (&dnd_data->target_entry, 1);
|
|
|
|
gtk_drag_dest_set_target_list (widget, target_list);
|
|
gtk_target_list_unref (target_list);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
pika_dnd_data_dest_remove (PikaDndType data_type,
|
|
GtkWidget *widget)
|
|
{
|
|
const PikaDndDataDef *dnd_data;
|
|
|
|
dnd_data = dnd_data_defs + data_type;
|
|
|
|
g_object_set_data (G_OBJECT (widget), dnd_data->set_data_func_name, NULL);
|
|
g_object_set_data (G_OBJECT (widget), dnd_data->set_data_data_name, NULL);
|
|
|
|
if (dnd_data->target_entry.target)
|
|
{
|
|
GtkTargetList *target_list;
|
|
|
|
target_list = gtk_drag_dest_get_target_list (widget);
|
|
|
|
if (target_list)
|
|
{
|
|
GdkAtom atom = gdk_atom_intern (dnd_data->target_entry.target, TRUE);
|
|
|
|
if (atom != GDK_NONE)
|
|
gtk_target_list_remove (target_list, atom);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/****************************/
|
|
/* uri list dnd functions */
|
|
/****************************/
|
|
|
|
static void
|
|
pika_dnd_get_uri_list_data (GtkWidget *widget,
|
|
GdkDragContext *context,
|
|
GCallback get_uri_list_func,
|
|
gpointer get_uri_list_data,
|
|
GtkSelectionData *selection)
|
|
{
|
|
GList *uri_list;
|
|
|
|
uri_list = (* (PikaDndDragUriListFunc) get_uri_list_func) (widget,
|
|
get_uri_list_data);
|
|
|
|
PIKA_LOG (DND, "uri_list %p", uri_list);
|
|
|
|
if (uri_list)
|
|
{
|
|
pika_selection_data_set_uri_list (selection, uri_list);
|
|
|
|
g_list_free_full (uri_list, (GDestroyNotify) g_free);
|
|
}
|
|
}
|
|
|
|
static gboolean
|
|
pika_dnd_set_uri_list_data (GtkWidget *widget,
|
|
gint x,
|
|
gint y,
|
|
GCallback set_uri_list_func,
|
|
gpointer set_uri_list_data,
|
|
GtkSelectionData *selection)
|
|
{
|
|
GList *uri_list = pika_selection_data_get_uri_list (selection);
|
|
|
|
PIKA_LOG (DND, "uri_list %p", uri_list);
|
|
|
|
if (! uri_list)
|
|
return FALSE;
|
|
|
|
(* (PikaDndDropUriListFunc) set_uri_list_func) (widget, x, y, uri_list,
|
|
set_uri_list_data);
|
|
|
|
g_list_free_full (uri_list, (GDestroyNotify) g_free);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void
|
|
pika_dnd_uri_list_source_add (GtkWidget *widget,
|
|
PikaDndDragUriListFunc get_uri_list_func,
|
|
gpointer data)
|
|
{
|
|
g_return_if_fail (GTK_IS_WIDGET (widget));
|
|
|
|
pika_dnd_data_source_add (PIKA_DND_TYPE_URI_LIST, widget,
|
|
G_CALLBACK (get_uri_list_func),
|
|
data);
|
|
}
|
|
|
|
void
|
|
pika_dnd_uri_list_source_remove (GtkWidget *widget)
|
|
{
|
|
g_return_if_fail (GTK_IS_WIDGET (widget));
|
|
|
|
pika_dnd_data_source_remove (PIKA_DND_TYPE_URI_LIST, widget);
|
|
}
|
|
|
|
void
|
|
pika_dnd_uri_list_dest_add (GtkWidget *widget,
|
|
PikaDndDropUriListFunc set_uri_list_func,
|
|
gpointer data)
|
|
{
|
|
g_return_if_fail (GTK_IS_WIDGET (widget));
|
|
|
|
/* Set a default drag dest if not already done. Explicitly set
|
|
* COPY and MOVE for file drag destinations. Some file managers
|
|
* such as Konqueror only offer MOVE by default.
|
|
*/
|
|
if (! g_object_get_data (G_OBJECT (widget), "gtk-drag-dest"))
|
|
gtk_drag_dest_set (widget,
|
|
GTK_DEST_DEFAULT_ALL, NULL, 0,
|
|
GDK_ACTION_COPY | GDK_ACTION_MOVE);
|
|
|
|
pika_dnd_data_dest_add (PIKA_DND_TYPE_URI_LIST, widget,
|
|
G_CALLBACK (set_uri_list_func),
|
|
data);
|
|
pika_dnd_data_dest_add (PIKA_DND_TYPE_TEXT_PLAIN, widget,
|
|
G_CALLBACK (set_uri_list_func),
|
|
data);
|
|
pika_dnd_data_dest_add (PIKA_DND_TYPE_NETSCAPE_URL, widget,
|
|
G_CALLBACK (set_uri_list_func),
|
|
data);
|
|
}
|
|
|
|
void
|
|
pika_dnd_uri_list_dest_remove (GtkWidget *widget)
|
|
{
|
|
g_return_if_fail (GTK_IS_WIDGET (widget));
|
|
|
|
pika_dnd_data_dest_remove (PIKA_DND_TYPE_URI_LIST, widget);
|
|
pika_dnd_data_dest_remove (PIKA_DND_TYPE_TEXT_PLAIN, widget);
|
|
pika_dnd_data_dest_remove (PIKA_DND_TYPE_NETSCAPE_URL, widget);
|
|
}
|
|
|
|
|
|
/******************************/
|
|
/* Direct Save Protocol (XDS) */
|
|
/******************************/
|
|
|
|
static void
|
|
pika_dnd_get_xds_data (GtkWidget *widget,
|
|
GdkDragContext *context,
|
|
GCallback get_image_func,
|
|
gpointer get_image_data,
|
|
GtkSelectionData *selection)
|
|
{
|
|
PikaImage *image;
|
|
PikaContext *pika_context;
|
|
|
|
image = g_object_get_data (G_OBJECT (context), "pika-dnd-viewable");
|
|
|
|
if (! image)
|
|
image = (PikaImage *)
|
|
(* (PikaDndDragViewableFunc) get_image_func) (widget, &pika_context,
|
|
get_image_data);
|
|
|
|
PIKA_LOG (DND, "image %p", image);
|
|
|
|
if (image)
|
|
pika_dnd_xds_save_image (context, image, selection);
|
|
}
|
|
|
|
static void
|
|
pika_dnd_xds_drag_begin (GtkWidget *widget,
|
|
GdkDragContext *context)
|
|
{
|
|
const PikaDndDataDef *dnd_data = dnd_data_defs + PIKA_DND_TYPE_XDS;
|
|
GCallback get_data_func;
|
|
gpointer get_data_data;
|
|
|
|
get_data_func = g_object_get_data (G_OBJECT (widget),
|
|
dnd_data->get_data_func_name);
|
|
get_data_data = g_object_get_data (G_OBJECT (widget),
|
|
dnd_data->get_data_data_name);
|
|
|
|
if (get_data_func)
|
|
{
|
|
PikaImage *image;
|
|
PikaContext *pika_context;
|
|
|
|
image = (PikaImage *)
|
|
(* (PikaDndDragViewableFunc) get_data_func) (widget, &pika_context,
|
|
get_data_data);
|
|
|
|
PIKA_LOG (DND, "image %p", image);
|
|
|
|
pika_dnd_xds_source_set (context, image);
|
|
}
|
|
}
|
|
|
|
static void
|
|
pika_dnd_xds_drag_end (GtkWidget *widget,
|
|
GdkDragContext *context)
|
|
{
|
|
pika_dnd_xds_source_set (context, NULL);
|
|
}
|
|
|
|
void
|
|
pika_dnd_xds_source_add (GtkWidget *widget,
|
|
PikaDndDragViewableFunc get_image_func,
|
|
gpointer data)
|
|
{
|
|
gulong handler;
|
|
|
|
g_return_if_fail (GTK_IS_WIDGET (widget));
|
|
|
|
pika_dnd_data_source_add (PIKA_DND_TYPE_XDS, widget,
|
|
G_CALLBACK (get_image_func),
|
|
data);
|
|
|
|
handler = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (widget),
|
|
"pika-dnd-xds-drag-begin"));
|
|
|
|
if (! handler)
|
|
{
|
|
handler = g_signal_connect (widget, "drag-begin",
|
|
G_CALLBACK (pika_dnd_xds_drag_begin),
|
|
NULL);
|
|
g_object_set_data (G_OBJECT (widget), "pika-dnd-xds-drag-begin",
|
|
GUINT_TO_POINTER (handler));
|
|
}
|
|
|
|
handler = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (widget),
|
|
"pika-dnd-xds-drag-end"));
|
|
|
|
if (! handler)
|
|
{
|
|
handler = g_signal_connect (widget, "drag-end",
|
|
G_CALLBACK (pika_dnd_xds_drag_end),
|
|
NULL);
|
|
g_object_set_data (G_OBJECT (widget), "pika-dnd-xds-drag-end",
|
|
GUINT_TO_POINTER (handler));
|
|
}
|
|
}
|
|
|
|
void
|
|
pika_dnd_xds_source_remove (GtkWidget *widget)
|
|
{
|
|
gulong handler;
|
|
|
|
g_return_if_fail (GTK_IS_WIDGET (widget));
|
|
|
|
handler = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (widget),
|
|
"pika-dnd-xds-drag-begin"));
|
|
if (handler)
|
|
{
|
|
g_signal_handler_disconnect (widget, handler);
|
|
g_object_set_data (G_OBJECT (widget), "pika-dnd-xds-drag-begin", NULL);
|
|
}
|
|
|
|
handler = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (widget),
|
|
"pika-dnd-xds-drag-end"));
|
|
if (handler)
|
|
{
|
|
g_signal_handler_disconnect (widget, handler);
|
|
g_object_set_data (G_OBJECT (widget), "pika-dnd-xds-drag-end", NULL);
|
|
}
|
|
|
|
pika_dnd_data_source_remove (PIKA_DND_TYPE_XDS, widget);
|
|
}
|
|
|
|
|
|
/*************************/
|
|
/* color dnd functions */
|
|
/*************************/
|
|
|
|
static GtkWidget *
|
|
pika_dnd_get_color_icon (GtkWidget *widget,
|
|
GdkDragContext *context,
|
|
GCallback get_color_func,
|
|
gpointer get_color_data)
|
|
{
|
|
GtkWidget *color_area;
|
|
PikaRGB color;
|
|
|
|
(* (PikaDndDragColorFunc) get_color_func) (widget, &color, get_color_data);
|
|
|
|
PIKA_LOG (DND, "called");
|
|
|
|
g_object_set_data_full (G_OBJECT (context),
|
|
"pika-dnd-color", g_memdup2 (&color, sizeof (PikaRGB)),
|
|
(GDestroyNotify) g_free);
|
|
|
|
color_area = pika_color_area_new (&color, PIKA_COLOR_AREA_SMALL_CHECKS, 0);
|
|
pika_color_area_set_color_config (PIKA_COLOR_AREA (color_area),
|
|
the_dnd_pika->config->color_management);
|
|
gtk_widget_set_size_request (color_area,
|
|
DRAG_PREVIEW_SIZE, DRAG_PREVIEW_SIZE);
|
|
|
|
return color_area;
|
|
}
|
|
|
|
static void
|
|
pika_dnd_get_color_data (GtkWidget *widget,
|
|
GdkDragContext *context,
|
|
GCallback get_color_func,
|
|
gpointer get_color_data,
|
|
GtkSelectionData *selection)
|
|
{
|
|
PikaRGB *c;
|
|
PikaRGB color;
|
|
|
|
c = g_object_get_data (G_OBJECT (context), "pika-dnd-color");
|
|
|
|
if (c)
|
|
color = *c;
|
|
else
|
|
(* (PikaDndDragColorFunc) get_color_func) (widget, &color, get_color_data);
|
|
|
|
PIKA_LOG (DND, "called");
|
|
|
|
pika_selection_data_set_color (selection, &color);
|
|
}
|
|
|
|
static gboolean
|
|
pika_dnd_set_color_data (GtkWidget *widget,
|
|
gint x,
|
|
gint y,
|
|
GCallback set_color_func,
|
|
gpointer set_color_data,
|
|
GtkSelectionData *selection)
|
|
{
|
|
PikaRGB color;
|
|
|
|
PIKA_LOG (DND, "called");
|
|
|
|
if (! pika_selection_data_get_color (selection, &color))
|
|
return FALSE;
|
|
|
|
(* (PikaDndDropColorFunc) set_color_func) (widget, x, y, &color,
|
|
set_color_data);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void
|
|
pika_dnd_color_source_add (GtkWidget *widget,
|
|
PikaDndDragColorFunc get_color_func,
|
|
gpointer data)
|
|
{
|
|
g_return_if_fail (GTK_IS_WIDGET (widget));
|
|
|
|
pika_dnd_data_source_add (PIKA_DND_TYPE_COLOR, widget,
|
|
G_CALLBACK (get_color_func),
|
|
data);
|
|
}
|
|
|
|
void
|
|
pika_dnd_color_source_remove (GtkWidget *widget)
|
|
{
|
|
g_return_if_fail (GTK_IS_WIDGET (widget));
|
|
|
|
pika_dnd_data_source_remove (PIKA_DND_TYPE_COLOR, widget);
|
|
}
|
|
|
|
void
|
|
pika_dnd_color_dest_add (GtkWidget *widget,
|
|
PikaDndDropColorFunc set_color_func,
|
|
gpointer data)
|
|
{
|
|
g_return_if_fail (GTK_IS_WIDGET (widget));
|
|
|
|
pika_dnd_data_dest_add (PIKA_DND_TYPE_COLOR, widget,
|
|
G_CALLBACK (set_color_func),
|
|
data);
|
|
}
|
|
|
|
void
|
|
pika_dnd_color_dest_remove (GtkWidget *widget)
|
|
{
|
|
g_return_if_fail (GTK_IS_WIDGET (widget));
|
|
|
|
pika_dnd_data_dest_remove (PIKA_DND_TYPE_COLOR, widget);
|
|
}
|
|
|
|
|
|
/**************************/
|
|
/* stream dnd functions */
|
|
/**************************/
|
|
|
|
static void
|
|
pika_dnd_get_stream_data (GtkWidget *widget,
|
|
GdkDragContext *context,
|
|
GCallback get_stream_func,
|
|
gpointer get_stream_data,
|
|
GtkSelectionData *selection)
|
|
{
|
|
guchar *stream;
|
|
gsize stream_length;
|
|
|
|
stream = (* (PikaDndDragStreamFunc) get_stream_func) (widget, &stream_length,
|
|
get_stream_data);
|
|
|
|
PIKA_LOG (DND, "stream %p, length %" G_GSIZE_FORMAT, stream, stream_length);
|
|
|
|
if (stream)
|
|
{
|
|
pika_selection_data_set_stream (selection, stream, stream_length);
|
|
g_free (stream);
|
|
}
|
|
}
|
|
|
|
static gboolean
|
|
pika_dnd_set_stream_data (GtkWidget *widget,
|
|
gint x,
|
|
gint y,
|
|
GCallback set_stream_func,
|
|
gpointer set_stream_data,
|
|
GtkSelectionData *selection)
|
|
{
|
|
const guchar *stream;
|
|
gsize stream_length;
|
|
|
|
stream = pika_selection_data_get_stream (selection, &stream_length);
|
|
|
|
PIKA_LOG (DND, "stream %p, length %" G_GSIZE_FORMAT, stream, stream_length);
|
|
|
|
if (! stream)
|
|
return FALSE;
|
|
|
|
(* (PikaDndDropStreamFunc) set_stream_func) (widget, x, y,
|
|
stream, stream_length,
|
|
set_stream_data);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void
|
|
pika_dnd_svg_source_add (GtkWidget *widget,
|
|
PikaDndDragStreamFunc get_svg_func,
|
|
gpointer data)
|
|
{
|
|
g_return_if_fail (GTK_IS_WIDGET (widget));
|
|
|
|
pika_dnd_data_source_add (PIKA_DND_TYPE_SVG, widget,
|
|
G_CALLBACK (get_svg_func),
|
|
data);
|
|
pika_dnd_data_source_add (PIKA_DND_TYPE_SVG_XML, widget,
|
|
G_CALLBACK (get_svg_func),
|
|
data);
|
|
}
|
|
|
|
void
|
|
pika_dnd_svg_source_remove (GtkWidget *widget)
|
|
{
|
|
g_return_if_fail (GTK_IS_WIDGET (widget));
|
|
|
|
pika_dnd_data_source_remove (PIKA_DND_TYPE_SVG, widget);
|
|
pika_dnd_data_source_remove (PIKA_DND_TYPE_SVG_XML, widget);
|
|
}
|
|
|
|
void
|
|
pika_dnd_svg_dest_add (GtkWidget *widget,
|
|
PikaDndDropStreamFunc set_svg_func,
|
|
gpointer data)
|
|
{
|
|
g_return_if_fail (GTK_IS_WIDGET (widget));
|
|
|
|
pika_dnd_data_dest_add (PIKA_DND_TYPE_SVG, widget,
|
|
G_CALLBACK (set_svg_func),
|
|
data);
|
|
pika_dnd_data_dest_add (PIKA_DND_TYPE_SVG_XML, widget,
|
|
G_CALLBACK (set_svg_func),
|
|
data);
|
|
}
|
|
|
|
void
|
|
pika_dnd_svg_dest_remove (GtkWidget *widget)
|
|
{
|
|
g_return_if_fail (GTK_IS_WIDGET (widget));
|
|
|
|
pika_dnd_data_dest_remove (PIKA_DND_TYPE_SVG, widget);
|
|
pika_dnd_data_dest_remove (PIKA_DND_TYPE_SVG_XML, widget);
|
|
}
|
|
|
|
|
|
/**************************/
|
|
/* pixbuf dnd functions */
|
|
/**************************/
|
|
|
|
static void
|
|
pika_dnd_get_pixbuf_data (GtkWidget *widget,
|
|
GdkDragContext *context,
|
|
GCallback get_pixbuf_func,
|
|
gpointer get_pixbuf_data,
|
|
GtkSelectionData *selection)
|
|
{
|
|
GdkPixbuf *pixbuf;
|
|
|
|
pixbuf = (* (PikaDndDragPixbufFunc) get_pixbuf_func) (widget,
|
|
get_pixbuf_data);
|
|
|
|
PIKA_LOG (DND, "pixbuf %p", pixbuf);
|
|
|
|
if (pixbuf)
|
|
{
|
|
pika_set_busy (the_dnd_pika);
|
|
|
|
gtk_selection_data_set_pixbuf (selection, pixbuf);
|
|
g_object_unref (pixbuf);
|
|
|
|
pika_unset_busy (the_dnd_pika);
|
|
}
|
|
}
|
|
|
|
static gboolean
|
|
pika_dnd_set_pixbuf_data (GtkWidget *widget,
|
|
gint x,
|
|
gint y,
|
|
GCallback set_pixbuf_func,
|
|
gpointer set_pixbuf_data,
|
|
GtkSelectionData *selection)
|
|
{
|
|
GdkPixbuf *pixbuf;
|
|
|
|
pika_set_busy (the_dnd_pika);
|
|
|
|
pixbuf = gtk_selection_data_get_pixbuf (selection);
|
|
|
|
pika_unset_busy (the_dnd_pika);
|
|
|
|
PIKA_LOG (DND, "pixbuf %p", pixbuf);
|
|
|
|
if (! pixbuf)
|
|
return FALSE;
|
|
|
|
(* (PikaDndDropPixbufFunc) set_pixbuf_func) (widget, x, y,
|
|
pixbuf,
|
|
set_pixbuf_data);
|
|
|
|
g_object_unref (pixbuf);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void
|
|
pika_dnd_pixbuf_source_add (GtkWidget *widget,
|
|
PikaDndDragPixbufFunc get_pixbuf_func,
|
|
gpointer data)
|
|
{
|
|
GtkTargetList *target_list;
|
|
|
|
g_return_if_fail (GTK_IS_WIDGET (widget));
|
|
|
|
pika_dnd_data_source_add (PIKA_DND_TYPE_PIXBUF, widget,
|
|
G_CALLBACK (get_pixbuf_func),
|
|
data);
|
|
|
|
target_list = gtk_drag_source_get_target_list (widget);
|
|
|
|
if (target_list)
|
|
gtk_target_list_ref (target_list);
|
|
else
|
|
target_list = gtk_target_list_new (NULL, 0);
|
|
|
|
pika_pixbuf_targets_add (target_list, PIKA_DND_TYPE_PIXBUF, TRUE);
|
|
|
|
gtk_drag_source_set_target_list (widget, target_list);
|
|
gtk_target_list_unref (target_list);
|
|
}
|
|
|
|
void
|
|
pika_dnd_pixbuf_source_remove (GtkWidget *widget)
|
|
{
|
|
GtkTargetList *target_list;
|
|
|
|
g_return_if_fail (GTK_IS_WIDGET (widget));
|
|
|
|
pika_dnd_data_source_remove (PIKA_DND_TYPE_PIXBUF, widget);
|
|
|
|
target_list = gtk_drag_source_get_target_list (widget);
|
|
|
|
if (target_list)
|
|
pika_pixbuf_targets_remove (target_list);
|
|
}
|
|
|
|
void
|
|
pika_dnd_pixbuf_dest_add (GtkWidget *widget,
|
|
PikaDndDropPixbufFunc set_pixbuf_func,
|
|
gpointer data)
|
|
{
|
|
GtkTargetList *target_list;
|
|
|
|
g_return_if_fail (GTK_IS_WIDGET (widget));
|
|
|
|
pika_dnd_data_dest_add (PIKA_DND_TYPE_PIXBUF, widget,
|
|
G_CALLBACK (set_pixbuf_func),
|
|
data);
|
|
|
|
target_list = gtk_drag_dest_get_target_list (widget);
|
|
|
|
if (target_list)
|
|
gtk_target_list_ref (target_list);
|
|
else
|
|
target_list = gtk_target_list_new (NULL, 0);
|
|
|
|
pika_pixbuf_targets_add (target_list, PIKA_DND_TYPE_PIXBUF, FALSE);
|
|
|
|
gtk_drag_dest_set_target_list (widget, target_list);
|
|
gtk_target_list_unref (target_list);
|
|
}
|
|
|
|
void
|
|
pika_dnd_pixbuf_dest_remove (GtkWidget *widget)
|
|
{
|
|
GtkTargetList *target_list;
|
|
|
|
g_return_if_fail (GTK_IS_WIDGET (widget));
|
|
|
|
pika_dnd_data_dest_remove (PIKA_DND_TYPE_PIXBUF, widget);
|
|
|
|
target_list = gtk_drag_dest_get_target_list (widget);
|
|
|
|
if (target_list)
|
|
pika_pixbuf_targets_remove (target_list);
|
|
}
|
|
|
|
|
|
/*****************************/
|
|
/* component dnd functions */
|
|
/*****************************/
|
|
|
|
static GtkWidget *
|
|
pika_dnd_get_component_icon (GtkWidget *widget,
|
|
GdkDragContext *context,
|
|
GCallback get_comp_func,
|
|
gpointer get_comp_data)
|
|
{
|
|
GtkWidget *view;
|
|
PikaImage *image;
|
|
PikaContext *pika_context;
|
|
PikaChannelType channel;
|
|
|
|
image = (* (PikaDndDragComponentFunc) get_comp_func) (widget, &pika_context,
|
|
&channel,
|
|
get_comp_data);
|
|
|
|
PIKA_LOG (DND, "image %p, component %d", image, channel);
|
|
|
|
if (! image)
|
|
return NULL;
|
|
|
|
g_object_set_data_full (G_OBJECT (context),
|
|
"pika-dnd-viewable", g_object_ref (image),
|
|
(GDestroyNotify) g_object_unref);
|
|
g_object_set_data (G_OBJECT (context),
|
|
"pika-dnd-component", GINT_TO_POINTER (channel));
|
|
|
|
view = pika_view_new (pika_context, PIKA_VIEWABLE (image),
|
|
DRAG_PREVIEW_SIZE, 0, TRUE);
|
|
|
|
PIKA_VIEW_RENDERER_IMAGE (PIKA_VIEW (view)->renderer)->channel = channel;
|
|
|
|
return view;
|
|
}
|
|
|
|
static void
|
|
pika_dnd_get_component_data (GtkWidget *widget,
|
|
GdkDragContext *context,
|
|
GCallback get_comp_func,
|
|
gpointer get_comp_data,
|
|
GtkSelectionData *selection)
|
|
{
|
|
PikaImage *image;
|
|
PikaContext *pika_context;
|
|
PikaChannelType channel = 0;
|
|
|
|
image = g_object_get_data (G_OBJECT (context), "pika-dnd-viewable");
|
|
channel = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (context),
|
|
"pika-dnd-component"));
|
|
|
|
if (! image)
|
|
image = (* (PikaDndDragComponentFunc) get_comp_func) (widget, &pika_context,
|
|
&channel,
|
|
get_comp_data);
|
|
|
|
PIKA_LOG (DND, "image %p, component %d", image, channel);
|
|
|
|
if (image)
|
|
pika_selection_data_set_component (selection, image, channel);
|
|
}
|
|
|
|
static gboolean
|
|
pika_dnd_set_component_data (GtkWidget *widget,
|
|
gint x,
|
|
gint y,
|
|
GCallback set_comp_func,
|
|
gpointer set_comp_data,
|
|
GtkSelectionData *selection)
|
|
{
|
|
PikaImage *image;
|
|
PikaChannelType channel = 0;
|
|
|
|
image = pika_selection_data_get_component (selection, the_dnd_pika,
|
|
&channel);
|
|
|
|
PIKA_LOG (DND, "image %p, component %d", image, channel);
|
|
|
|
if (! image)
|
|
return FALSE;
|
|
|
|
(* (PikaDndDropComponentFunc) set_comp_func) (widget, x, y,
|
|
image, channel,
|
|
set_comp_data);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void
|
|
pika_dnd_component_source_add (GtkWidget *widget,
|
|
PikaDndDragComponentFunc get_comp_func,
|
|
gpointer data)
|
|
{
|
|
g_return_if_fail (GTK_IS_WIDGET (widget));
|
|
|
|
pika_dnd_data_source_add (PIKA_DND_TYPE_COMPONENT, widget,
|
|
G_CALLBACK (get_comp_func),
|
|
data);
|
|
}
|
|
|
|
void
|
|
pika_dnd_component_source_remove (GtkWidget *widget)
|
|
{
|
|
g_return_if_fail (GTK_IS_WIDGET (widget));
|
|
|
|
pika_dnd_data_source_remove (PIKA_DND_TYPE_COMPONENT, widget);
|
|
}
|
|
|
|
void
|
|
pika_dnd_component_dest_add (GtkWidget *widget,
|
|
PikaDndDropComponentFunc set_comp_func,
|
|
gpointer data)
|
|
{
|
|
g_return_if_fail (GTK_IS_WIDGET (widget));
|
|
|
|
pika_dnd_data_dest_add (PIKA_DND_TYPE_COMPONENT, widget,
|
|
G_CALLBACK (set_comp_func),
|
|
data);
|
|
}
|
|
|
|
void
|
|
pika_dnd_component_dest_remove (GtkWidget *widget)
|
|
{
|
|
g_return_if_fail (GTK_IS_WIDGET (widget));
|
|
|
|
pika_dnd_data_dest_remove (PIKA_DND_TYPE_COMPONENT, widget);
|
|
}
|
|
|
|
|
|
/*******************************************/
|
|
/* PikaViewable (by GType) dnd functions */
|
|
/*******************************************/
|
|
|
|
static GtkWidget *
|
|
pika_dnd_get_viewable_icon (GtkWidget *widget,
|
|
GdkDragContext *context,
|
|
GCallback get_viewable_func,
|
|
gpointer get_viewable_data)
|
|
{
|
|
PikaViewable *viewable;
|
|
PikaContext *pika_context;
|
|
GtkWidget *view;
|
|
gchar *desc;
|
|
|
|
viewable = (* (PikaDndDragViewableFunc) get_viewable_func) (widget,
|
|
&pika_context,
|
|
get_viewable_data);
|
|
|
|
PIKA_LOG (DND, "viewable %p", viewable);
|
|
|
|
if (! viewable)
|
|
return NULL;
|
|
|
|
g_object_set_data_full (G_OBJECT (context),
|
|
"pika-dnd-viewable", g_object_ref (viewable),
|
|
(GDestroyNotify) g_object_unref);
|
|
|
|
view = pika_view_new (pika_context, viewable,
|
|
DRAG_PREVIEW_SIZE, 0, TRUE);
|
|
|
|
desc = pika_viewable_get_description (viewable, NULL);
|
|
|
|
if (desc)
|
|
{
|
|
GtkWidget *hbox;
|
|
GtkWidget *label;
|
|
|
|
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 3);
|
|
gtk_container_set_border_width (GTK_CONTAINER (hbox), 3);
|
|
gtk_box_pack_start (GTK_BOX (hbox), view, FALSE, FALSE, 0);
|
|
gtk_widget_show (view);
|
|
|
|
label = g_object_new (GTK_TYPE_LABEL,
|
|
"label", desc,
|
|
"xalign", 0.0,
|
|
"yalign", 0.5,
|
|
"max-width-chars", 30,
|
|
"width-chars", MIN (strlen (desc), 10),
|
|
"ellipsize", PANGO_ELLIPSIZE_END,
|
|
NULL);
|
|
|
|
g_free (desc);
|
|
|
|
gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 0);
|
|
gtk_widget_show (label);
|
|
|
|
return hbox;
|
|
}
|
|
|
|
return view;
|
|
}
|
|
|
|
static PikaDndType
|
|
pika_dnd_data_type_get_by_g_type (GType type,
|
|
gboolean list)
|
|
{
|
|
PikaDndType dnd_type = PIKA_DND_TYPE_NONE;
|
|
|
|
if (g_type_is_a (type, PIKA_TYPE_IMAGE) && ! list)
|
|
{
|
|
dnd_type = PIKA_DND_TYPE_IMAGE;
|
|
}
|
|
else if (g_type_is_a (type, PIKA_TYPE_LAYER))
|
|
{
|
|
dnd_type = list ? PIKA_DND_TYPE_LAYER_LIST : PIKA_DND_TYPE_LAYER;
|
|
}
|
|
else if (g_type_is_a (type, PIKA_TYPE_LAYER_MASK) && ! list)
|
|
{
|
|
dnd_type = PIKA_DND_TYPE_LAYER_MASK;
|
|
}
|
|
else if (g_type_is_a (type, PIKA_TYPE_CHANNEL))
|
|
{
|
|
dnd_type = list ? PIKA_DND_TYPE_CHANNEL_LIST : PIKA_DND_TYPE_CHANNEL;
|
|
}
|
|
else if (g_type_is_a (type, PIKA_TYPE_VECTORS))
|
|
{
|
|
dnd_type = list ? PIKA_DND_TYPE_VECTORS_LIST : PIKA_DND_TYPE_VECTORS;
|
|
}
|
|
else if (g_type_is_a (type, PIKA_TYPE_BRUSH) && ! list)
|
|
{
|
|
dnd_type = PIKA_DND_TYPE_BRUSH;
|
|
}
|
|
else if (g_type_is_a (type, PIKA_TYPE_PATTERN) && ! list)
|
|
{
|
|
dnd_type = PIKA_DND_TYPE_PATTERN;
|
|
}
|
|
else if (g_type_is_a (type, PIKA_TYPE_GRADIENT) && ! list)
|
|
{
|
|
dnd_type = PIKA_DND_TYPE_GRADIENT;
|
|
}
|
|
else if (g_type_is_a (type, PIKA_TYPE_PALETTE) && ! list)
|
|
{
|
|
dnd_type = PIKA_DND_TYPE_PALETTE;
|
|
}
|
|
else if (g_type_is_a (type, PIKA_TYPE_FONT) && ! list)
|
|
{
|
|
dnd_type = PIKA_DND_TYPE_FONT;
|
|
}
|
|
else if (g_type_is_a (type, PIKA_TYPE_BUFFER) && ! list)
|
|
{
|
|
dnd_type = PIKA_DND_TYPE_BUFFER;
|
|
}
|
|
else if (g_type_is_a (type, PIKA_TYPE_IMAGEFILE) && ! list)
|
|
{
|
|
dnd_type = PIKA_DND_TYPE_IMAGEFILE;
|
|
}
|
|
else if (g_type_is_a (type, PIKA_TYPE_TEMPLATE) && ! list)
|
|
{
|
|
dnd_type = PIKA_DND_TYPE_TEMPLATE;
|
|
}
|
|
else if (g_type_is_a (type, PIKA_TYPE_TOOL_ITEM) && ! list)
|
|
{
|
|
dnd_type = PIKA_DND_TYPE_TOOL_ITEM;
|
|
}
|
|
|
|
return dnd_type;
|
|
}
|
|
|
|
gboolean
|
|
pika_dnd_drag_source_set_by_type (GtkWidget *widget,
|
|
GdkModifierType start_button_mask,
|
|
GType type,
|
|
GdkDragAction actions)
|
|
{
|
|
PikaDndType dnd_type;
|
|
|
|
g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
|
|
|
|
dnd_type = pika_dnd_data_type_get_by_g_type (type, FALSE);
|
|
|
|
if (dnd_type == PIKA_DND_TYPE_NONE)
|
|
return FALSE;
|
|
|
|
gtk_drag_source_set (widget, start_button_mask,
|
|
&dnd_data_defs[dnd_type].target_entry, 1,
|
|
actions);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
gboolean
|
|
pika_dnd_drag_dest_set_by_type (GtkWidget *widget,
|
|
GtkDestDefaults flags,
|
|
GType type,
|
|
gboolean list_accepted,
|
|
GdkDragAction actions)
|
|
{
|
|
GtkTargetEntry target_entries[2];
|
|
PikaDndType dnd_type;
|
|
gint target_entries_n = 0;
|
|
|
|
g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
|
|
|
|
if (list_accepted)
|
|
{
|
|
dnd_type = pika_dnd_data_type_get_by_g_type (type, TRUE);
|
|
|
|
if (dnd_type != PIKA_DND_TYPE_NONE)
|
|
{
|
|
target_entries[target_entries_n] = dnd_data_defs[dnd_type].target_entry;
|
|
target_entries_n++;
|
|
}
|
|
}
|
|
|
|
dnd_type = pika_dnd_data_type_get_by_g_type (type, FALSE);
|
|
if (dnd_type != PIKA_DND_TYPE_NONE)
|
|
{
|
|
target_entries[target_entries_n] = dnd_data_defs[dnd_type].target_entry;
|
|
target_entries_n++;
|
|
}
|
|
|
|
if (target_entries_n == 0)
|
|
return FALSE;
|
|
|
|
gtk_drag_dest_set (widget, flags,
|
|
(const GtkTargetEntry *) &target_entries,
|
|
target_entries_n,
|
|
actions);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
* pika_dnd_viewable_source_add:
|
|
* @widget:
|
|
* @type:
|
|
* @get_viewable_func:
|
|
* @data:
|
|
*
|
|
* Sets up @widget as a drag source for a #PikaViewable object, as
|
|
* returned by @get_viewable_func on @widget and @data.
|
|
*
|
|
* @type must be a list type for drag operations.
|
|
*/
|
|
gboolean
|
|
pika_dnd_viewable_source_add (GtkWidget *widget,
|
|
GType type,
|
|
PikaDndDragViewableFunc get_viewable_func,
|
|
gpointer data)
|
|
{
|
|
PikaDndType dnd_type;
|
|
|
|
g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
|
|
g_return_val_if_fail (get_viewable_func != NULL, FALSE);
|
|
|
|
dnd_type = pika_dnd_data_type_get_by_g_type (type, FALSE);
|
|
|
|
if (dnd_type == PIKA_DND_TYPE_NONE)
|
|
return FALSE;
|
|
|
|
pika_dnd_data_source_add (dnd_type, widget,
|
|
G_CALLBACK (get_viewable_func),
|
|
data);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
gboolean
|
|
pika_dnd_viewable_source_remove (GtkWidget *widget,
|
|
GType type)
|
|
{
|
|
PikaDndType dnd_type;
|
|
|
|
g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
|
|
|
|
dnd_type = pika_dnd_data_type_get_by_g_type (type, FALSE);
|
|
|
|
if (dnd_type == PIKA_DND_TYPE_NONE)
|
|
return FALSE;
|
|
|
|
return pika_dnd_data_source_remove (dnd_type, widget);
|
|
}
|
|
|
|
gboolean
|
|
pika_dnd_viewable_dest_add (GtkWidget *widget,
|
|
GType type,
|
|
PikaDndDropViewableFunc set_viewable_func,
|
|
gpointer data)
|
|
{
|
|
PikaDndType dnd_type;
|
|
|
|
g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
|
|
|
|
dnd_type = pika_dnd_data_type_get_by_g_type (type, FALSE);
|
|
|
|
if (dnd_type == PIKA_DND_TYPE_NONE)
|
|
return FALSE;
|
|
|
|
pika_dnd_data_dest_add (dnd_type, widget,
|
|
G_CALLBACK (set_viewable_func),
|
|
data);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
gboolean
|
|
pika_dnd_viewable_dest_remove (GtkWidget *widget,
|
|
GType type)
|
|
{
|
|
PikaDndType dnd_type;
|
|
|
|
g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
|
|
|
|
dnd_type = pika_dnd_data_type_get_by_g_type (type, FALSE);
|
|
|
|
if (dnd_type == PIKA_DND_TYPE_NONE)
|
|
return FALSE;
|
|
|
|
pika_dnd_data_dest_remove (dnd_type, widget);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
PikaViewable *
|
|
pika_dnd_get_drag_viewable (GtkWidget *widget)
|
|
{
|
|
const PikaDndDataDef *dnd_data;
|
|
PikaDndType data_type;
|
|
PikaDndDragViewableFunc get_data_func = NULL;
|
|
gpointer get_data_data = NULL;
|
|
PikaContext *context;
|
|
|
|
g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
|
|
|
|
data_type = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget),
|
|
"pika-dnd-get-data-type"));
|
|
|
|
if (! data_type)
|
|
return NULL;
|
|
|
|
dnd_data = dnd_data_defs + data_type;
|
|
|
|
if (dnd_data->get_data_func_name)
|
|
get_data_func = g_object_get_data (G_OBJECT (widget),
|
|
dnd_data->get_data_func_name);
|
|
|
|
if (dnd_data->get_data_data_name)
|
|
get_data_data = g_object_get_data (G_OBJECT (widget),
|
|
dnd_data->get_data_data_name);
|
|
|
|
if (! get_data_func)
|
|
return NULL;
|
|
|
|
return (PikaViewable *) (* get_data_func) (widget, &context, get_data_data);
|
|
}
|
|
|
|
|
|
/*************************************************/
|
|
/* PikaViewable (by GType) GList dnd functions */
|
|
/*************************************************/
|
|
|
|
static GtkWidget *
|
|
pika_dnd_get_viewable_list_icon (GtkWidget *widget,
|
|
GdkDragContext *context,
|
|
GCallback get_list_func,
|
|
gpointer get_list_data)
|
|
{
|
|
GList *viewables;
|
|
PikaViewable *viewable;
|
|
PikaContext *pika_context;
|
|
GtkWidget *view;
|
|
gchar *desc;
|
|
gboolean desc_use_markup = FALSE;
|
|
gfloat desc_yalign = 0.5f;
|
|
gint desc_width_chars;
|
|
|
|
viewables = (* (PikaDndDragViewableListFunc) get_list_func) (widget,
|
|
&pika_context,
|
|
get_list_data);
|
|
|
|
if (! viewables)
|
|
return NULL;
|
|
|
|
viewable = viewables->data;
|
|
|
|
PIKA_LOG (DND, "viewable %p", viewable);
|
|
|
|
g_object_set_data_full (G_OBJECT (context),
|
|
"pika-dnd-viewable", g_object_ref (viewable),
|
|
(GDestroyNotify) g_object_unref);
|
|
|
|
view = pika_view_new (pika_context, viewable,
|
|
DRAG_PREVIEW_SIZE, 0, TRUE);
|
|
|
|
if (g_list_length (viewables) > 1)
|
|
{
|
|
/* When dragging multiple viewable, just show the first of them in the
|
|
* icon box, and the number of viewables being dragged in the
|
|
* description label (instead of the viewable name).
|
|
*/
|
|
desc = g_strdup_printf ("<sup><i>(%d)</i></sup>", g_list_length (viewables));
|
|
desc_use_markup = TRUE;
|
|
desc_yalign = 0.0f;
|
|
desc_width_chars = (gint) log10 (g_list_length (viewables)) + 3;
|
|
}
|
|
else
|
|
{
|
|
desc = pika_viewable_get_description (viewable, NULL);
|
|
desc_width_chars = MIN (strlen (desc), 10);
|
|
}
|
|
g_list_free (viewables);
|
|
|
|
if (desc)
|
|
{
|
|
GtkWidget *hbox;
|
|
GtkWidget *label;
|
|
|
|
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 3);
|
|
gtk_container_set_border_width (GTK_CONTAINER (hbox), 3);
|
|
gtk_box_pack_start (GTK_BOX (hbox), view, FALSE, FALSE, 0);
|
|
gtk_widget_show (view);
|
|
|
|
label = g_object_new (GTK_TYPE_LABEL,
|
|
"label", desc,
|
|
"use-markup", desc_use_markup,
|
|
"xalign", 0.0,
|
|
"yalign", desc_yalign,
|
|
"max-width-chars", 30,
|
|
"width-chars", desc_width_chars,
|
|
"ellipsize", PANGO_ELLIPSIZE_END,
|
|
NULL);
|
|
|
|
g_free (desc);
|
|
|
|
gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 0);
|
|
gtk_widget_show (label);
|
|
|
|
return hbox;
|
|
}
|
|
|
|
return view;
|
|
}
|
|
|
|
/**
|
|
* pika_dnd_viewable_list_source_add:
|
|
* @widget:
|
|
* @type:
|
|
* @get_viewable_func:
|
|
* @data:
|
|
*
|
|
* Sets up @widget as a drag source for a #GList of #PikaViewable
|
|
* object, as returned by @get_viewable_func on @widget and @data.
|
|
*
|
|
* @type must be a list type for drag operations (only PikaLayer so
|
|
* far).
|
|
*/
|
|
gboolean
|
|
pika_dnd_viewable_list_source_add (GtkWidget *widget,
|
|
GType type,
|
|
PikaDndDragViewableListFunc get_viewable_list_func,
|
|
gpointer data)
|
|
{
|
|
PikaDndType dnd_type;
|
|
|
|
g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
|
|
g_return_val_if_fail (get_viewable_list_func != NULL, FALSE);
|
|
|
|
dnd_type = pika_dnd_data_type_get_by_g_type (type, TRUE);
|
|
|
|
if (dnd_type == PIKA_DND_TYPE_NONE)
|
|
return FALSE;
|
|
|
|
pika_dnd_data_source_add (dnd_type, widget,
|
|
G_CALLBACK (get_viewable_list_func),
|
|
data);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
gboolean
|
|
pika_dnd_viewable_list_source_remove (GtkWidget *widget,
|
|
GType type)
|
|
{
|
|
PikaDndType dnd_type;
|
|
|
|
g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
|
|
|
|
dnd_type = pika_dnd_data_type_get_by_g_type (type, TRUE);
|
|
|
|
if (dnd_type == PIKA_DND_TYPE_NONE)
|
|
return FALSE;
|
|
|
|
return pika_dnd_data_source_remove (dnd_type, widget);
|
|
}
|
|
|
|
gboolean
|
|
pika_dnd_viewable_list_dest_add (GtkWidget *widget,
|
|
GType type,
|
|
PikaDndDropViewableListFunc set_viewable_func,
|
|
gpointer data)
|
|
{
|
|
PikaDndType dnd_type;
|
|
|
|
g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
|
|
|
|
dnd_type = pika_dnd_data_type_get_by_g_type (type, TRUE);
|
|
|
|
if (dnd_type == PIKA_DND_TYPE_NONE)
|
|
return FALSE;
|
|
|
|
pika_dnd_data_dest_add (dnd_type, widget,
|
|
G_CALLBACK (set_viewable_func),
|
|
data);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
gboolean
|
|
pika_dnd_viewable_list_dest_remove (GtkWidget *widget,
|
|
GType type)
|
|
{
|
|
PikaDndType dnd_type;
|
|
|
|
g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
|
|
|
|
dnd_type = pika_dnd_data_type_get_by_g_type (type, TRUE);
|
|
|
|
if (dnd_type == PIKA_DND_TYPE_NONE)
|
|
return FALSE;
|
|
|
|
pika_dnd_data_dest_remove (dnd_type, widget);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
GList *
|
|
pika_dnd_get_drag_list (GtkWidget *widget)
|
|
{
|
|
const PikaDndDataDef *dnd_data;
|
|
PikaDndType data_type;
|
|
PikaDndDragViewableListFunc get_data_func = NULL;
|
|
gpointer get_data_data = NULL;
|
|
PikaContext *context;
|
|
|
|
g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
|
|
|
|
data_type = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget),
|
|
"pika-dnd-get-data-type"));
|
|
|
|
if (! data_type)
|
|
return NULL;
|
|
|
|
dnd_data = dnd_data_defs + data_type;
|
|
|
|
if (dnd_data->get_data_func_name)
|
|
get_data_func = g_object_get_data (G_OBJECT (widget),
|
|
dnd_data->get_data_func_name);
|
|
|
|
if (dnd_data->get_data_data_name)
|
|
get_data_data = g_object_get_data (G_OBJECT (widget),
|
|
dnd_data->get_data_data_name);
|
|
|
|
if (! get_data_func)
|
|
return NULL;
|
|
|
|
return (GList *) (* get_data_func) (widget, &context, get_data_data);
|
|
}
|
|
|
|
|
|
/*****************************/
|
|
/* PikaImage dnd functions */
|
|
/*****************************/
|
|
|
|
static void
|
|
pika_dnd_get_image_data (GtkWidget *widget,
|
|
GdkDragContext *context,
|
|
GCallback get_image_func,
|
|
gpointer get_image_data,
|
|
GtkSelectionData *selection)
|
|
{
|
|
PikaImage *image;
|
|
PikaContext *pika_context;
|
|
|
|
image = g_object_get_data (G_OBJECT (context), "pika-dnd-viewable");
|
|
|
|
if (! image)
|
|
image = (PikaImage *)
|
|
(* (PikaDndDragViewableFunc) get_image_func) (widget, &pika_context,
|
|
get_image_data);
|
|
|
|
PIKA_LOG (DND, "image %p", image);
|
|
|
|
if (image)
|
|
pika_selection_data_set_image (selection, image);
|
|
}
|
|
|
|
static gboolean
|
|
pika_dnd_set_image_data (GtkWidget *widget,
|
|
gint x,
|
|
gint y,
|
|
GCallback set_image_func,
|
|
gpointer set_image_data,
|
|
GtkSelectionData *selection)
|
|
{
|
|
PikaImage *image = pika_selection_data_get_image (selection, the_dnd_pika);
|
|
|
|
PIKA_LOG (DND, "image %p", image);
|
|
|
|
if (! image)
|
|
return FALSE;
|
|
|
|
(* (PikaDndDropViewableFunc) set_image_func) (widget, x, y,
|
|
PIKA_VIEWABLE (image),
|
|
set_image_data);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/****************************/
|
|
/* PikaItem dnd functions */
|
|
/****************************/
|
|
|
|
static void
|
|
pika_dnd_get_item_data (GtkWidget *widget,
|
|
GdkDragContext *context,
|
|
GCallback get_item_func,
|
|
gpointer get_item_data,
|
|
GtkSelectionData *selection)
|
|
{
|
|
PikaItem *item;
|
|
PikaContext *pika_context;
|
|
|
|
item = g_object_get_data (G_OBJECT (context), "pika-dnd-viewable");
|
|
|
|
if (! item)
|
|
item = (PikaItem *)
|
|
(* (PikaDndDragViewableFunc) get_item_func) (widget, &pika_context,
|
|
get_item_data);
|
|
|
|
PIKA_LOG (DND, "item %p", item);
|
|
|
|
if (item)
|
|
pika_selection_data_set_item (selection, item);
|
|
}
|
|
|
|
static gboolean
|
|
pika_dnd_set_item_data (GtkWidget *widget,
|
|
gint x,
|
|
gint y,
|
|
GCallback set_item_func,
|
|
gpointer set_item_data,
|
|
GtkSelectionData *selection)
|
|
{
|
|
PikaItem *item = pika_selection_data_get_item (selection, the_dnd_pika);
|
|
|
|
PIKA_LOG (DND, "item %p", item);
|
|
|
|
if (! item)
|
|
return FALSE;
|
|
|
|
(* (PikaDndDropViewableFunc) set_item_func) (widget, x, y,
|
|
PIKA_VIEWABLE (item),
|
|
set_item_data);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/**********************************/
|
|
/* PikaItem GList dnd functions */
|
|
/**********************************/
|
|
|
|
static void
|
|
pika_dnd_get_item_list_data (GtkWidget *widget,
|
|
GdkDragContext *context,
|
|
GCallback get_item_func,
|
|
gpointer get_item_data,
|
|
GtkSelectionData *selection)
|
|
{
|
|
GList *items;
|
|
PikaContext *pika_context;
|
|
|
|
items = (* (PikaDndDragViewableListFunc) get_item_func) (widget, &pika_context,
|
|
get_item_data);
|
|
|
|
if (items)
|
|
pika_selection_data_set_item_list (selection, items);
|
|
g_list_free (items);
|
|
}
|
|
|
|
static gboolean
|
|
pika_dnd_set_item_list_data (GtkWidget *widget,
|
|
gint x,
|
|
gint y,
|
|
GCallback set_item_func,
|
|
gpointer set_item_data,
|
|
GtkSelectionData *selection)
|
|
{
|
|
GList *items = pika_selection_data_get_item_list (selection, the_dnd_pika);
|
|
|
|
if (! items)
|
|
return FALSE;
|
|
|
|
(* (PikaDndDropViewableListFunc) set_item_func) (widget, x, y, items,
|
|
set_item_data);
|
|
g_list_free (items);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/******************************/
|
|
/* PikaObject dnd functions */
|
|
/******************************/
|
|
|
|
static void
|
|
pika_dnd_get_object_data (GtkWidget *widget,
|
|
GdkDragContext *context,
|
|
GCallback get_object_func,
|
|
gpointer get_object_data,
|
|
GtkSelectionData *selection)
|
|
{
|
|
PikaObject *object;
|
|
PikaContext *pika_context;
|
|
|
|
object = g_object_get_data (G_OBJECT (context), "pika-dnd-viewable");
|
|
|
|
if (! object)
|
|
object = (PikaObject *)
|
|
(* (PikaDndDragViewableFunc) get_object_func) (widget, &pika_context,
|
|
get_object_data);
|
|
|
|
PIKA_LOG (DND, "object %p", object);
|
|
|
|
if (PIKA_IS_OBJECT (object))
|
|
pika_selection_data_set_object (selection, object);
|
|
}
|
|
|
|
|
|
/*****************************/
|
|
/* PikaBrush dnd functions */
|
|
/*****************************/
|
|
|
|
static gboolean
|
|
pika_dnd_set_brush_data (GtkWidget *widget,
|
|
gint x,
|
|
gint y,
|
|
GCallback set_brush_func,
|
|
gpointer set_brush_data,
|
|
GtkSelectionData *selection)
|
|
{
|
|
PikaBrush *brush = pika_selection_data_get_brush (selection, the_dnd_pika);
|
|
|
|
PIKA_LOG (DND, "brush %p", brush);
|
|
|
|
if (! brush)
|
|
return FALSE;
|
|
|
|
(* (PikaDndDropViewableFunc) set_brush_func) (widget, x, y,
|
|
PIKA_VIEWABLE (brush),
|
|
set_brush_data);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/*******************************/
|
|
/* PikaPattern dnd functions */
|
|
/*******************************/
|
|
|
|
static gboolean
|
|
pika_dnd_set_pattern_data (GtkWidget *widget,
|
|
gint x,
|
|
gint y,
|
|
GCallback set_pattern_func,
|
|
gpointer set_pattern_data,
|
|
GtkSelectionData *selection)
|
|
{
|
|
PikaPattern *pattern = pika_selection_data_get_pattern (selection,
|
|
the_dnd_pika);
|
|
|
|
PIKA_LOG (DND, "pattern %p", pattern);
|
|
|
|
if (! pattern)
|
|
return FALSE;
|
|
|
|
(* (PikaDndDropViewableFunc) set_pattern_func) (widget, x, y,
|
|
PIKA_VIEWABLE (pattern),
|
|
set_pattern_data);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/********************************/
|
|
/* PikaGradient dnd functions */
|
|
/********************************/
|
|
|
|
static gboolean
|
|
pika_dnd_set_gradient_data (GtkWidget *widget,
|
|
gint x,
|
|
gint y,
|
|
GCallback set_gradient_func,
|
|
gpointer set_gradient_data,
|
|
GtkSelectionData *selection)
|
|
{
|
|
PikaGradient *gradient = pika_selection_data_get_gradient (selection,
|
|
the_dnd_pika);
|
|
|
|
PIKA_LOG (DND, "gradient %p", gradient);
|
|
|
|
if (! gradient)
|
|
return FALSE;
|
|
|
|
(* (PikaDndDropViewableFunc) set_gradient_func) (widget, x, y,
|
|
PIKA_VIEWABLE (gradient),
|
|
set_gradient_data);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/*******************************/
|
|
/* PikaPalette dnd functions */
|
|
/*******************************/
|
|
|
|
static gboolean
|
|
pika_dnd_set_palette_data (GtkWidget *widget,
|
|
gint x,
|
|
gint y,
|
|
GCallback set_palette_func,
|
|
gpointer set_palette_data,
|
|
GtkSelectionData *selection)
|
|
{
|
|
PikaPalette *palette = pika_selection_data_get_palette (selection,
|
|
the_dnd_pika);
|
|
|
|
PIKA_LOG (DND, "palette %p", palette);
|
|
|
|
if (! palette)
|
|
return FALSE;
|
|
|
|
(* (PikaDndDropViewableFunc) set_palette_func) (widget, x, y,
|
|
PIKA_VIEWABLE (palette),
|
|
set_palette_data);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/****************************/
|
|
/* PikaFont dnd functions */
|
|
/****************************/
|
|
|
|
static gboolean
|
|
pika_dnd_set_font_data (GtkWidget *widget,
|
|
gint x,
|
|
gint y,
|
|
GCallback set_font_func,
|
|
gpointer set_font_data,
|
|
GtkSelectionData *selection)
|
|
{
|
|
PikaFont *font = pika_selection_data_get_font (selection, the_dnd_pika);
|
|
|
|
PIKA_LOG (DND, "font %p", font);
|
|
|
|
if (! font)
|
|
return FALSE;
|
|
|
|
(* (PikaDndDropViewableFunc) set_font_func) (widget, x, y,
|
|
PIKA_VIEWABLE (font),
|
|
set_font_data);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/******************************/
|
|
/* PikaBuffer dnd functions */
|
|
/******************************/
|
|
|
|
static gboolean
|
|
pika_dnd_set_buffer_data (GtkWidget *widget,
|
|
gint x,
|
|
gint y,
|
|
GCallback set_buffer_func,
|
|
gpointer set_buffer_data,
|
|
GtkSelectionData *selection)
|
|
{
|
|
PikaBuffer *buffer = pika_selection_data_get_buffer (selection, the_dnd_pika);
|
|
|
|
PIKA_LOG (DND, "buffer %p", buffer);
|
|
|
|
if (! buffer)
|
|
return FALSE;
|
|
|
|
(* (PikaDndDropViewableFunc) set_buffer_func) (widget, x, y,
|
|
PIKA_VIEWABLE (buffer),
|
|
set_buffer_data);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/*********************************/
|
|
/* PikaImagefile dnd functions */
|
|
/*********************************/
|
|
|
|
static gboolean
|
|
pika_dnd_set_imagefile_data (GtkWidget *widget,
|
|
gint x,
|
|
gint y,
|
|
GCallback set_imagefile_func,
|
|
gpointer set_imagefile_data,
|
|
GtkSelectionData *selection)
|
|
{
|
|
PikaImagefile *imagefile = pika_selection_data_get_imagefile (selection,
|
|
the_dnd_pika);
|
|
|
|
PIKA_LOG (DND, "imagefile %p", imagefile);
|
|
|
|
if (! imagefile)
|
|
return FALSE;
|
|
|
|
(* (PikaDndDropViewableFunc) set_imagefile_func) (widget, x, y,
|
|
PIKA_VIEWABLE (imagefile),
|
|
set_imagefile_data);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/********************************/
|
|
/* PikaTemplate dnd functions */
|
|
/********************************/
|
|
|
|
static gboolean
|
|
pika_dnd_set_template_data (GtkWidget *widget,
|
|
gint x,
|
|
gint y,
|
|
GCallback set_template_func,
|
|
gpointer set_template_data,
|
|
GtkSelectionData *selection)
|
|
{
|
|
PikaTemplate *template = pika_selection_data_get_template (selection,
|
|
the_dnd_pika);
|
|
|
|
PIKA_LOG (DND, "template %p", template);
|
|
|
|
if (! template)
|
|
return FALSE;
|
|
|
|
(* (PikaDndDropViewableFunc) set_template_func) (widget, x, y,
|
|
PIKA_VIEWABLE (template),
|
|
set_template_data);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/*********************************/
|
|
/* PikaToolEntry dnd functions */
|
|
/*********************************/
|
|
|
|
static gboolean
|
|
pika_dnd_set_tool_item_data (GtkWidget *widget,
|
|
gint x,
|
|
gint y,
|
|
GCallback set_tool_item_func,
|
|
gpointer set_tool_item_data,
|
|
GtkSelectionData *selection)
|
|
{
|
|
PikaToolItem *tool_item = pika_selection_data_get_tool_item (selection,
|
|
the_dnd_pika);
|
|
|
|
PIKA_LOG (DND, "tool_item %p", tool_item);
|
|
|
|
if (! tool_item)
|
|
return FALSE;
|
|
|
|
(* (PikaDndDropViewableFunc) set_tool_item_func) (widget, x, y,
|
|
PIKA_VIEWABLE (tool_item),
|
|
set_tool_item_data);
|
|
|
|
return TRUE;
|
|
}
|