Implement dragging and dropping in any GdkPixbuf supported format. Fixes

2005-04-09  Michael Natterer  <mitch@gimp.org>

	Implement dragging and dropping in any GdkPixbuf supported
	format. Fixes bug #172794 and bug #172795.

	* app/core/gimplayer.[ch] (gimp_layer_new_from_region): new
	function which contains all stuff that was in
	gimp_layer_new_from_tiles().

	(gimp_layer_new_from_tiles): use above function.
	(gimp_layer_new_from_pixbuf): new function.

	* app/widgets/Makefile.am
	* app/widgets/gimppixbuf.[ch]: new files containing GdkPixbuf
	utility functions for clipboard and DnD.

	* app/widgets/gimpselectiondata.[ch]: removed
	gimp_selection_data_set,get_pixbuf(), GTK+ provides the same API.
	Also removed GdkAtom parameters all over the place because it's
	always the same as selection_data->target.

	* app/widgets/gimpclipboard.c: use the new pixbuf utility
	functions and gtk_selection_data_set,get_pixbuf().

	* app/widgets/widgets-enums.h
	* app/widgets/gimpdnd.[ch]: removed never-implemented
	GIMP_DND_TYPE_PNG and added a generic GIMP_DND_TYPE_PIXBUF
	instead. Added API to drag and drop GdkPixbufs which transparently
	converts from/to and GdkPixbuf-supported image format. Removed
	passing around of GdkAtoms, since they were always the same
	as selection_data->target.

	* app/widgets/gimpdnd-xds.[ch]: follow GdkAtom parameter removal.

	* app/widgets/gimpcontainertreeview.[ch]: added virtual function
	GimpContainerTreeView::drop_pixbuf().

	* app/widgets/gimpcontainertreeview-dnd.c: dispatch drop_pixbuf().

	* app/widgets/gimplayertreeview.c: implement drop_pixbuf().

	* app/widgets/gimpdrawabletreeview.c: allow to drag all drawables
	as pixbufs.

	* app/display/gimpdisplayshell-dnd.c: allow dropping of pixbufs.
This commit is contained in:
Michael Natterer 2005-04-09 17:56:04 +00:00 committed by Michael Natterer
parent 97992621e7
commit 7609645970
20 changed files with 811 additions and 303 deletions

View file

@ -1,3 +1,49 @@
2005-04-09 Michael Natterer <mitch@gimp.org>
Implement dragging and dropping in any GdkPixbuf supported
format. Fixes bug #172794 and bug #172795.
* app/core/gimplayer.[ch] (gimp_layer_new_from_region): new
function which contains all stuff that was in
gimp_layer_new_from_tiles().
(gimp_layer_new_from_tiles): use above function.
(gimp_layer_new_from_pixbuf): new function.
* app/widgets/Makefile.am
* app/widgets/gimppixbuf.[ch]: new files containing GdkPixbuf
utility functions for clipboard and DnD.
* app/widgets/gimpselectiondata.[ch]: removed
gimp_selection_data_set,get_pixbuf(), GTK+ provides the same API.
Also removed GdkAtom parameters all over the place because it's
always the same as selection_data->target.
* app/widgets/gimpclipboard.c: use the new pixbuf utility
functions and gtk_selection_data_set,get_pixbuf().
* app/widgets/widgets-enums.h
* app/widgets/gimpdnd.[ch]: removed never-implemented
GIMP_DND_TYPE_PNG and added a generic GIMP_DND_TYPE_PIXBUF
instead. Added API to drag and drop GdkPixbufs which transparently
converts from/to and GdkPixbuf-supported image format. Removed
passing around of GdkAtoms, since they were always the same
as selection_data->target.
* app/widgets/gimpdnd-xds.[ch]: follow GdkAtom parameter removal.
* app/widgets/gimpcontainertreeview.[ch]: added virtual function
GimpContainerTreeView::drop_pixbuf().
* app/widgets/gimpcontainertreeview-dnd.c: dispatch drop_pixbuf().
* app/widgets/gimplayertreeview.c: implement drop_pixbuf().
* app/widgets/gimpdrawabletreeview.c: allow to drag all drawables
as pixbufs.
* app/display/gimpdisplayshell-dnd.c: allow dropping of pixbufs.
2005-04-10 Bill Skaggs <weskaggs@primate.ucdavis.edu>
* plug-ins/common/screenshot.c: Change default back to Window

View file

@ -883,21 +883,100 @@ gimp_layer_new_from_tiles (TileManager *tiles,
gdouble opacity,
GimpLayerModeEffects mode)
{
GimpLayer *new_layer;
PixelRegion layerPR;
PixelRegion bufPR;
GimpImageType src_type;
gint width;
gint height;
PixelRegion bufPR;
g_return_val_if_fail (tiles != NULL, NULL);
g_return_val_if_fail (GIMP_IS_IMAGE (dest_gimage), NULL);
g_return_val_if_fail (name != NULL, NULL);
width = tile_manager_width (tiles);
height = tile_manager_height (tiles);
pixel_region_init (&bufPR, tiles,
0, 0,
tile_manager_width (tiles),
tile_manager_height (tiles),
FALSE);
switch (tile_manager_bpp (tiles))
return gimp_layer_new_from_region (&bufPR, dest_gimage, type,
name, opacity, mode);
}
/**
* gimp_layer_new_from_pixbuf:
* @tiles: The pixbuf to make the new layer from.
* @dest_gimage: The image the new layer will be added to.
* @type: The #GimpImageType of the new layer.
* @name: The new layer's name.
* @opacity: The new layer's opacity.
* @mode: The new layer's mode.
*
* Copies %pixbuf to a layer taking into consideration the
* possibility of transforming the contents to meet the requirements
* of the target image type
*
* Return value: The new layer.
**/
GimpLayer *
gimp_layer_new_from_pixbuf (GdkPixbuf *pixbuf,
GimpImage *dest_gimage,
GimpImageType type,
const gchar *name,
gdouble opacity,
GimpLayerModeEffects mode)
{
PixelRegion bufPR = { 0, };
g_return_val_if_fail (GDK_IS_PIXBUF (pixbuf), NULL);
g_return_val_if_fail (GIMP_IS_IMAGE (dest_gimage), NULL);
g_return_val_if_fail (name != NULL, NULL);
bufPR.data = gdk_pixbuf_get_pixels (pixbuf);
bufPR.rowstride = gdk_pixbuf_get_rowstride (pixbuf);
bufPR.x = 0;
bufPR.y = 0;
bufPR.w = gdk_pixbuf_get_width (pixbuf);
bufPR.h = gdk_pixbuf_get_height (pixbuf);
bufPR.bytes = gdk_pixbuf_get_n_channels (pixbuf);
return gimp_layer_new_from_region (&bufPR, dest_gimage, type,
name, opacity, mode);
}
/**
* gimp_layer_new_from_region:
* @region: A readable pixel region.
* @dest_gimage: The image the new layer will be added to.
* @type: The #GimpImageType of the new layer.
* @name: The new layer's name.
* @opacity: The new layer's opacity.
* @mode: The new layer's mode.
*
* Copies %region to a layer taking into consideration the
* possibility of transforming the contents to meet the requirements
* of the target image type
*
* Return value: The new layer.
**/
GimpLayer *
gimp_layer_new_from_region (PixelRegion *region,
GimpImage *dest_gimage,
GimpImageType type,
const gchar *name,
gdouble opacity,
GimpLayerModeEffects mode)
{
GimpLayer *new_layer;
PixelRegion layerPR;
GimpImageType src_type;
gint width;
gint height;
g_return_val_if_fail (region != NULL, NULL);
g_return_val_if_fail (GIMP_IS_IMAGE (dest_gimage), NULL);
g_return_val_if_fail (name != NULL, NULL);
width = region->w;
height = region->h;
switch (region->bytes)
{
case 1: src_type = GIMP_GRAY_IMAGE; break;
case 2: src_type = GIMP_GRAYA_IMAGE; break;
@ -913,14 +992,10 @@ gimp_layer_new_from_tiles (TileManager *tiles,
if (! new_layer)
{
g_message ("gimp_layer_new_from_tiles: could not allocate new layer");
g_message ("gimp_layer_new_from_region: could not allocate new layer");
return NULL;
}
/* Configure the pixel regions */
pixel_region_init (&bufPR, tiles,
0, 0, width, height,
FALSE);
pixel_region_init (&layerPR, GIMP_DRAWABLE (new_layer)->tiles,
0, 0, width, height,
TRUE);
@ -931,7 +1006,7 @@ gimp_layer_new_from_tiles (TileManager *tiles,
switch (src_type)
{
case GIMP_RGB_IMAGE:
copy_region (&bufPR, &layerPR);
copy_region (region, &layerPR);
break;
default:
g_warning ("%s: unhandled type conversion", G_STRFUNC);
@ -943,13 +1018,13 @@ gimp_layer_new_from_tiles (TileManager *tiles,
switch (src_type)
{
case GIMP_RGBA_IMAGE:
copy_region (&bufPR, &layerPR);
copy_region (region, &layerPR);
break;
case GIMP_RGB_IMAGE:
add_alpha_region (&bufPR, &layerPR);
add_alpha_region (region, &layerPR);
break;
case GIMP_GRAYA_IMAGE:
gimp_layer_transform_color (dest_gimage, &layerPR, &bufPR,
gimp_layer_transform_color (dest_gimage, &layerPR, region,
GIMP_DRAWABLE (new_layer), GIMP_GRAY);
break;
default:
@ -962,7 +1037,7 @@ gimp_layer_new_from_tiles (TileManager *tiles,
switch (src_type)
{
case GIMP_GRAY_IMAGE:
copy_region (&bufPR, &layerPR);
copy_region (region, &layerPR);
break;
default:
g_warning ("%s: unhandled type conversion", G_STRFUNC);
@ -974,14 +1049,14 @@ gimp_layer_new_from_tiles (TileManager *tiles,
switch (src_type)
{
case GIMP_RGBA_IMAGE:
gimp_layer_transform_color (dest_gimage, &layerPR, &bufPR,
gimp_layer_transform_color (dest_gimage, &layerPR, region,
GIMP_DRAWABLE (new_layer), GIMP_RGB);
break;
case GIMP_GRAYA_IMAGE:
copy_region (&bufPR, &layerPR);
copy_region (region, &layerPR);
break;
case GIMP_GRAY_IMAGE:
add_alpha_region (&bufPR, &layerPR);
add_alpha_region (region, &layerPR);
break;
default:
g_warning ("%s: unhandled type conversion", G_STRFUNC);
@ -997,11 +1072,11 @@ gimp_layer_new_from_tiles (TileManager *tiles,
switch (src_type)
{
case GIMP_RGBA_IMAGE:
gimp_layer_transform_color (dest_gimage, &layerPR, &bufPR,
gimp_layer_transform_color (dest_gimage, &layerPR, region,
GIMP_DRAWABLE (new_layer), GIMP_RGB);
break;
case GIMP_GRAYA_IMAGE:
gimp_layer_transform_color (dest_gimage, &layerPR, &bufPR,
gimp_layer_transform_color (dest_gimage, &layerPR, region,
GIMP_DRAWABLE (new_layer), GIMP_GRAY);
break;
default:

View file

@ -85,6 +85,18 @@ GimpLayer * gimp_layer_new_from_tiles (TileManager *tiles,
const gchar *name,
gdouble opacity,
GimpLayerModeEffects mode);
GimpLayer * gimp_layer_new_from_pixbuf (GdkPixbuf *pixbuf,
GimpImage *dest_gimage,
GimpImageType type,
const gchar *name,
gdouble opacity,
GimpLayerModeEffects mode);
GimpLayer * gimp_layer_new_from_region (PixelRegion *region,
GimpImage *dest_gimage,
GimpImageType type,
const gchar *name,
gdouble opacity,
GimpLayerModeEffects mode);
GimpLayerMask * gimp_layer_create_mask (const GimpLayer *layer,
GimpAddMaskType mask_type);

View file

@ -112,6 +112,11 @@ static void gimp_display_shell_drop_component (GtkWidget *widget,
GimpImage *image,
GimpChannelType component,
gpointer data);
static void gimp_display_shell_drop_pixbuf (GtkWidget *widget,
gint x,
gint y,
GdkPixbuf *pixbuf,
gpointer data);
/* public functions */
@ -151,6 +156,9 @@ gimp_display_shell_dnd_init (GimpDisplayShell *shell)
gimp_dnd_component_dest_add (GTK_WIDGET (shell),
gimp_display_shell_drop_component,
shell);
gimp_dnd_pixbuf_dest_add (GTK_WIDGET (shell),
gimp_display_shell_drop_pixbuf,
shell);
}
@ -511,3 +519,56 @@ gimp_display_shell_drop_component (GtkWidget *widget,
shell->gdisp);
}
}
static void
gimp_display_shell_drop_pixbuf (GtkWidget *widget,
gint x,
gint y,
GdkPixbuf *pixbuf,
gpointer data)
{
GimpDisplayShell *shell = GIMP_DISPLAY_SHELL (data);
GimpImage *gimage = shell->gdisp->gimage;
GimpLayer *new_layer;
D (g_print ("drop pixbuf on canvas\n"));
if (gimage->gimp->busy)
return;
new_layer =
gimp_layer_new_from_pixbuf (pixbuf, gimage,
gimp_image_base_type_with_alpha (gimage),
_("Dropped Buffer"),
GIMP_OPACITY_OPAQUE, GIMP_NORMAL_MODE);
if (new_layer)
{
GimpItem *new_item;
gint x, y, width, height;
gint off_x, off_y;
new_item = GIMP_ITEM (new_layer);
gimp_image_undo_group_start (gimage, GIMP_UNDO_GROUP_EDIT_PASTE,
_("Drop New Layer"));
gimp_display_shell_untransform_viewport (shell, &x, &y, &width, &height);
gimp_item_offsets (new_item, &off_x, &off_y);
off_x = x + (width - gimp_item_width (new_item)) / 2 - off_x;
off_y = y + (height - gimp_item_height (new_item)) / 2 - off_y;
gimp_item_translate (new_item, off_x, off_y, FALSE);
gimp_image_add_layer (gimage, new_layer, -1);
gimp_image_undo_group_end (gimage);
gimp_image_flush (gimage);
gimp_context_set_display (gimp_get_user_context (gimage->gimp),
shell->gdisp);
}
}

View file

@ -189,6 +189,8 @@ libappwidgets_a_sources = \
gimppatternselect.h \
gimppdbdialog.c \
gimppdbdialog.h \
gimppixbuf.c \
gimppixbuf.h \
gimppluginaction.c \
gimppluginaction.h \
gimpprogressbox.c \

View file

@ -32,7 +32,7 @@
#include "core/gimpviewable.h"
#include "gimpclipboard.h"
#include "gimpdnd.h"
#include "gimppixbuf.h"
#include "gimpselectiondata.h"
#include "gimp-intl.h"
@ -49,7 +49,6 @@ struct _GimpClipboard
GtkTargetEntry *target_entries;
gint n_target_entries;
gchar **savers;
};
@ -68,9 +67,6 @@ static void gimp_clipboard_send_buffer (GtkClipboard *clipboard,
static GdkAtom * gimp_clipboard_wait_for_targets (gint *n_targets);
static GdkAtom gimp_clipboard_wait_for_buffer (Gimp *gimp);
static gint gimp_clipboard_format_compare (GdkPixbufFormat *a,
GdkPixbufFormat *b);
void
gimp_clipboard_init (Gimp *gimp)
@ -95,9 +91,7 @@ gimp_clipboard_init (Gimp *gimp)
G_CALLBACK (gimp_clipboard_buffer_changed),
NULL, 0);
gimp_clip->pixbuf_formats =
g_slist_sort (gdk_pixbuf_get_formats (),
(GCompareFunc) gimp_clipboard_format_compare);
gimp_clip->pixbuf_formats = gimp_pixbuf_get_formats ();
for (list = gimp_clip->pixbuf_formats; list; list = g_slist_next (list))
{
@ -123,8 +117,6 @@ gimp_clipboard_init (Gimp *gimp)
gimp_clip->target_entries = g_new0 (GtkTargetEntry,
gimp_clip->n_target_entries);
gimp_clip->savers = g_new0 (gchar *,
gimp_clip->n_target_entries + 1);
for (list = gimp_clip->pixbuf_formats; list; list = g_slist_next (list))
{
@ -151,8 +143,6 @@ gimp_clipboard_init (Gimp *gimp)
gimp_clip->target_entries[i].flags = 0;
gimp_clip->target_entries[i].info = i;
gimp_clip->savers[i] = g_strdup (format_name);
i++;
}
@ -278,7 +268,7 @@ gimp_clipboard_get_buffer (Gimp *gimp)
if (data)
{
GdkPixbuf *pixbuf = gimp_selection_data_get_pixbuf (data);
GdkPixbuf *pixbuf = gtk_selection_data_get_pixbuf (data);
gtk_selection_data_free (data);
@ -315,7 +305,6 @@ gimp_clipboard_free (GimpClipboard *gimp_clip)
{
g_slist_free (gimp_clip->pixbuf_formats);
g_free (gimp_clip->target_entries);
g_strfreev (gimp_clip->savers);
g_free (gimp_clip);
}
@ -472,15 +461,10 @@ gimp_clipboard_send_buffer (GtkClipboard *clipboard,
if (pixbuf)
{
GdkAtom atom = gdk_atom_intern (gimp_clip->target_entries[info].target,
FALSE);
g_printerr ("sending pixbuf data as '%s'\n",
gimp_clip->target_entries[info].target);
g_printerr ("sending pixbuf data as '%s' (%s)\n",
gimp_clip->target_entries[info].target,
gimp_clip->savers[info]);
gimp_selection_data_set_pixbuf (selection_data, atom, pixbuf,
gimp_clip->savers[info]);
gtk_selection_data_set_pixbuf (selection_data, pixbuf);
}
else
{
@ -489,44 +473,3 @@ gimp_clipboard_send_buffer (GtkClipboard *clipboard,
gimp_unset_busy (gimp);
}
static gint
gimp_clipboard_format_compare (GdkPixbufFormat *a,
GdkPixbufFormat *b)
{
gchar *a_name = gdk_pixbuf_format_get_name (a);
gchar *b_name = gdk_pixbuf_format_get_name (b);
gint retval = 0;
#ifdef GDK_WINDOWING_WIN32
/* move BMP to the front of the list */
if (strcmp (a_name, "bmp") == 0)
retval = -1;
else if (strcmp (b_name, "bmp") == 0)
retval = 1;
else
#endif
/* move PNG to the front of the list */
if (strcmp (a_name, "png") == 0)
retval = -1;
else if (strcmp (b_name, "png") == 0)
retval = 1;
/* move JPEG to the end of the list */
else if (strcmp (a_name, "jpeg") == 0)
retval = 1;
else if (strcmp (b_name, "jpeg") == 0)
retval = -1;
/* move GIF to the end of the list */
else if (strcmp (a_name, "gif") == 0)
retval = 1;
else if (strcmp (b_name, "gif") == 0)
retval = -1;
g_free (a_name);
g_free (b_name);
return retval;
}

View file

@ -76,6 +76,7 @@ gimp_container_tree_view_drop_status (GimpContainerTreeView *tree_view,
case GIMP_DND_TYPE_SVG:
case GIMP_DND_TYPE_SVG_XML:
case GIMP_DND_TYPE_COMPONENT:
case GIMP_DND_TYPE_PIXBUF:
break;
default:
@ -429,6 +430,25 @@ gimp_container_tree_view_drag_data_received (GtkWidget *widget,
}
break;
case GIMP_DND_TYPE_PIXBUF:
if (tree_view_class->drop_pixbuf)
{
GdkPixbuf *pixbuf;
pixbuf = gtk_selection_data_get_pixbuf (selection_data);
if (pixbuf)
{
tree_view_class->drop_pixbuf (tree_view,
pixbuf,
dest_viewable, drop_pos);
g_object_unref (pixbuf);
success = TRUE;
}
}
break;
default:
break;
}

View file

@ -164,6 +164,7 @@ gimp_container_tree_view_class_init (GimpContainerTreeViewClass *klass)
klass->drop_uri_list = NULL;
klass->drop_svg = NULL;
klass->drop_component = NULL;
klass->drop_pixbuf = NULL;
}
static void

View file

@ -103,6 +103,10 @@ struct _GimpContainerTreeViewClass
GimpChannelType component,
GimpViewable *dest_viewable,
GtkTreeViewDropPosition drop_pos);
void (* drop_pixbuf) (GimpContainerTreeView *tree_view,
GdkPixbuf *pixbuf,
GimpViewable *dest_viewable,
GtkTreeViewDropPosition drop_pos);
};

View file

@ -102,8 +102,7 @@ gimp_dnd_xds_source_set (GdkDragContext *context,
void
gimp_dnd_xds_save_image (GdkDragContext *context,
GimpImage *image,
GtkSelectionData *selection,
GdkAtom atom)
GtkSelectionData *selection)
{
PlugInProcDef *proc;
GdkAtom property = gdk_atom_intern ("XdndDirectSave0", FALSE);
@ -143,11 +142,11 @@ gimp_dnd_xds_save_image (GdkDragContext *context,
uri, proc, GIMP_RUN_INTERACTIVE, FALSE,
&error) == GIMP_PDB_SUCCESS)
{
gtk_selection_data_set (selection, atom, 8, "S", 1);
gtk_selection_data_set (selection, selection->target, 8, "S", 1);
}
else
{
gtk_selection_data_set (selection, atom, 8, "E", 1);
gtk_selection_data_set (selection, selection->target, 8, "E", 1);
if (error)
{
@ -166,7 +165,7 @@ gimp_dnd_xds_save_image (GdkDragContext *context,
}
else
{
gtk_selection_data_set (selection, atom, 8, "E", 1);
gtk_selection_data_set (selection, selection->target, 8, "E", 1);
g_message (_("The given filename does not have any known "
"file extension."));

View file

@ -30,8 +30,7 @@ void gimp_dnd_xds_source_set (GdkDragContext *context,
GimpImage *image);
void gimp_dnd_xds_save_image (GdkDragContext *context,
GimpImage *image,
GtkSelectionData *selection,
GdkAtom atom);
GtkSelectionData *selection);
#endif /* __GIMP_DND_XDS_H__ */

View file

@ -49,8 +49,9 @@
#include "gimpdnd.h"
#include "gimpdnd-xds.h"
#include "gimpview.h"
#include "gimppixbuf.h"
#include "gimpselectiondata.h"
#include "gimpview.h"
#include "gimpviewrendererimage.h"
#include "gimp-intl.h"
@ -74,8 +75,7 @@ typedef void (* GimpDndDragDataFunc) (GtkWidget *widget,
GdkDragContext *context,
GCallback get_data_func,
gpointer get_data_data,
GtkSelectionData *selection,
GdkAtom atom);
GtkSelectionData *selection);
typedef gboolean (* GimpDndDropDataFunc) (GtkWidget *widget,
gint x,
gint y,
@ -116,8 +116,7 @@ static void gimp_dnd_get_uri_list_data (GtkWidget *widget,
GdkDragContext *context,
GCallback get_uri_list_func,
gpointer get_uri_list_data,
GtkSelectionData *selection,
GdkAtom atom);
GtkSelectionData *selection);
static gboolean gimp_dnd_set_uri_list_data (GtkWidget *widget,
gint x,
gint y,
@ -129,15 +128,13 @@ static void gimp_dnd_get_xds_data (GtkWidget *widget,
GdkDragContext *context,
GCallback get_image_func,
gpointer get_image_data,
GtkSelectionData *selection,
GdkAtom atom);
GtkSelectionData *selection);
static void gimp_dnd_get_color_data (GtkWidget *widget,
GdkDragContext *context,
GCallback get_color_func,
gpointer get_color_data,
GtkSelectionData *selection,
GdkAtom atom);
GtkSelectionData *selection);
static gboolean gimp_dnd_set_color_data (GtkWidget *widget,
gint x,
gint y,
@ -149,8 +146,7 @@ static void gimp_dnd_get_stream_data (GtkWidget *widget,
GdkDragContext *context,
GCallback get_stream_func,
gpointer get_stream_data,
GtkSelectionData *selection,
GdkAtom atom);
GtkSelectionData *selection);
static gboolean gimp_dnd_set_stream_data (GtkWidget *widget,
gint x,
gint y,
@ -158,12 +154,22 @@ static gboolean gimp_dnd_set_stream_data (GtkWidget *widget,
gpointer set_stream_data,
GtkSelectionData *selection);
static void gimp_dnd_get_pixbuf_data (GtkWidget *widget,
GdkDragContext *context,
GCallback get_pixbuf_func,
gpointer get_pixbuf_data,
GtkSelectionData *selection);
static gboolean gimp_dnd_set_pixbuf_data (GtkWidget *widget,
gint x,
gint y,
GCallback set_pixbuf_func,
gpointer set_pixbuf_data,
GtkSelectionData *selection);
static void gimp_dnd_get_component_data (GtkWidget *widget,
GdkDragContext *context,
GCallback get_comp_func,
gpointer get_comp_data,
GtkSelectionData *selection,
GdkAtom atom);
GtkSelectionData *selection);
static gboolean gimp_dnd_set_component_data (GtkWidget *widget,
gint x,
gint y,
@ -175,8 +181,7 @@ static void gimp_dnd_get_image_data (GtkWidget *widget,
GdkDragContext *context,
GCallback get_image_func,
gpointer get_image_data,
GtkSelectionData *selection,
GdkAtom atom);
GtkSelectionData *selection);
static gboolean gimp_dnd_set_image_data (GtkWidget *widget,
gint x,
gint y,
@ -188,8 +193,7 @@ static void gimp_dnd_get_item_data (GtkWidget *widget,
GdkDragContext *context,
GCallback get_item_func,
gpointer get_item_data,
GtkSelectionData *selection,
GdkAtom atom);
GtkSelectionData *selection);
static gboolean gimp_dnd_set_item_data (GtkWidget *widget,
gint x,
gint y,
@ -201,8 +205,7 @@ static void gimp_dnd_get_data_data (GtkWidget *widget,
GdkDragContext *context,
GCallback get_data_func,
gpointer get_data_data,
GtkSelectionData *selection,
GdkAtom atom);
GtkSelectionData *selection);
static gboolean gimp_dnd_set_brush_data (GtkWidget *widget,
gint x,
@ -344,20 +347,6 @@ static const GimpDndDataDef dnd_data_defs[] =
gimp_dnd_set_color_data
},
{
GIMP_TARGET_PNG,
"gimp-dnd-get-png-func",
"gimp-dnd-get-png-data",
"gimp-dnd-set-png-func",
"gimp-dnd-set-png-data",
gimp_dnd_get_viewable_icon,
gimp_dnd_get_stream_data,
gimp_dnd_set_stream_data
},
{
GIMP_TARGET_SVG,
@ -386,6 +375,20 @@ static const GimpDndDataDef dnd_data_defs[] =
gimp_dnd_set_stream_data
},
{
GIMP_TARGET_PIXBUF,
"gimp-dnd-get-pixbuf-func",
"gimp-dnd-get-pixbuf-data",
"gimp-dnd-set-pixbuf-func",
"gimp-dnd-set-pixbuf-data",
gimp_dnd_get_viewable_icon,
gimp_dnd_get_pixbuf_data,
gimp_dnd_set_pixbuf_data
},
{
GIMP_TARGET_IMAGE,
@ -756,8 +759,6 @@ gimp_dnd_data_drag_handle (GtkWidget *widget,
if (dnd_data->target_entry.info == info)
{
GdkAtom atom;
D (g_printerr ("gimp_dnd_data_drag_handle(%s)\n",
dnd_data->target_entry.target));
@ -772,14 +773,11 @@ gimp_dnd_data_drag_handle (GtkWidget *widget,
if (! get_data_func)
return;
atom = gdk_atom_intern (dnd_data->target_entry.target, FALSE);
dnd_data->get_data_func (widget,
context,
get_data_func,
get_data_data,
selection_data,
atom);
selection_data);
return;
}
@ -851,7 +849,6 @@ gimp_dnd_data_source_add (GimpDndType data_type,
gpointer get_data_data)
{
const GimpDndDataDef *dnd_data;
GtkTargetList *target_list;
gboolean drag_connected;
dnd_data = dnd_data_defs + data_type;
@ -859,7 +856,7 @@ gimp_dnd_data_source_add (GimpDndType 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,
&dnd_data->target_entry, 1,
NULL, 0,
GDK_ACTION_COPY | GDK_ACTION_MOVE);
drag_connected =
@ -892,18 +889,23 @@ gimp_dnd_data_source_add (GimpDndType data_type,
g_object_set_data (G_OBJECT (widget), "gimp-dnd-get-data-type",
GINT_TO_POINTER (data_type));
target_list = gtk_drag_source_get_target_list (widget);
if (target_list)
if (dnd_data->target_entry.target)
{
gimp_dnd_target_list_add (target_list, &dnd_data->target_entry);
}
else
{
target_list = gtk_target_list_new (&dnd_data->target_entry, 1);
GtkTargetList *target_list;
gtk_drag_source_set_target_list (widget, target_list);
gtk_target_list_unref (target_list);
target_list = gtk_drag_source_get_target_list (widget);
if (target_list)
{
gimp_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);
}
}
}
@ -912,7 +914,6 @@ gimp_dnd_data_source_remove (GimpDndType data_type,
GtkWidget *widget)
{
const GimpDndDataDef *dnd_data;
GtkTargetList *target_list;
gboolean drag_connected;
drag_connected =
@ -933,14 +934,19 @@ gimp_dnd_data_source_remove (GimpDndType data_type,
"gimp-dnd-get-data-type")))
g_object_set_data (G_OBJECT (widget), "gimp-dnd-get-data-type", NULL);
target_list = gtk_drag_source_get_target_list (widget);
if (target_list)
if (dnd_data->target_entry.target)
{
GdkAtom atom = gdk_atom_intern (dnd_data->target_entry.target, TRUE);
GtkTargetList *target_list;
if (atom != GDK_NONE)
gtk_target_list_remove (target_list, atom);
target_list = gtk_drag_source_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);
}
}
}
@ -951,7 +957,6 @@ gimp_dnd_data_dest_add (GimpDndType data_type,
gpointer set_data_data)
{
const GimpDndDataDef *dnd_data;
GtkTargetList *target_list;
gboolean drop_connected;
/* set a default drag dest if not already done */
@ -982,18 +987,23 @@ gimp_dnd_data_dest_add (GimpDndType data_type,
set_data_data);
}
target_list = gtk_drag_dest_get_target_list (widget);
if (target_list)
if (dnd_data->target_entry.target)
{
gimp_dnd_target_list_add (target_list, &dnd_data->target_entry);
}
else
{
target_list = gtk_target_list_new (&dnd_data->target_entry, 1);
GtkTargetList *target_list;
gtk_drag_dest_set_target_list (widget, target_list);
gtk_target_list_unref (target_list);
target_list = gtk_drag_dest_get_target_list (widget);
if (target_list)
{
gimp_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);
}
}
}
@ -1002,21 +1012,25 @@ gimp_dnd_data_dest_remove (GimpDndType data_type,
GtkWidget *widget)
{
const GimpDndDataDef *dnd_data;
GtkTargetList *target_list;
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);
target_list = gtk_drag_dest_get_target_list (widget);
if (target_list)
if (dnd_data->target_entry.target)
{
GdkAtom atom = gdk_atom_intern (dnd_data->target_entry.target, TRUE);
GtkTargetList *target_list;
if (atom != GDK_NONE)
gtk_target_list_remove (target_list, atom);
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);
}
}
}
@ -1030,8 +1044,7 @@ gimp_dnd_get_uri_list_data (GtkWidget *widget,
GdkDragContext *context,
GCallback get_uri_list_func,
gpointer get_uri_list_data,
GtkSelectionData *selection,
GdkAtom atom)
GtkSelectionData *selection)
{
GList *uri_list;
@ -1040,7 +1053,7 @@ gimp_dnd_get_uri_list_data (GtkWidget *widget,
if (uri_list)
{
gimp_selection_data_set_uri_list (selection, atom, uri_list);
gimp_selection_data_set_uri_list (selection, uri_list);
g_list_foreach (uri_list, (GFunc) g_free, NULL);
g_list_free (uri_list);
@ -1136,8 +1149,7 @@ gimp_dnd_get_xds_data (GtkWidget *widget,
GdkDragContext *context,
GCallback get_image_func,
gpointer get_image_data,
GtkSelectionData *selection,
GdkAtom atom)
GtkSelectionData *selection)
{
GimpImage *image;
@ -1145,7 +1157,7 @@ gimp_dnd_get_xds_data (GtkWidget *widget,
(* (GimpDndDragViewableFunc) get_image_func) (widget, get_image_data);
if (image)
gimp_dnd_xds_save_image (context, image, selection, atom);
gimp_dnd_xds_save_image (context, image, selection);
}
static void
@ -1267,14 +1279,13 @@ gimp_dnd_get_color_data (GtkWidget *widget,
GdkDragContext *context,
GCallback get_color_func,
gpointer get_color_data,
GtkSelectionData *selection,
GdkAtom atom)
GtkSelectionData *selection)
{
GimpRGB color;
(* (GimpDndDragColorFunc) get_color_func) (widget, &color, get_color_data);
gimp_selection_data_set_color (selection, atom, &color);
gimp_selection_data_set_color (selection, &color);
}
static gboolean
@ -1346,8 +1357,7 @@ gimp_dnd_get_stream_data (GtkWidget *widget,
GdkDragContext *context,
GCallback get_stream_func,
gpointer get_stream_data,
GtkSelectionData *selection,
GdkAtom atom)
GtkSelectionData *selection)
{
guchar *stream;
gsize stream_length;
@ -1357,7 +1367,7 @@ gimp_dnd_get_stream_data (GtkWidget *widget,
if (stream)
{
gimp_selection_data_set_stream (selection, atom, stream, stream_length);
gimp_selection_data_set_stream (selection, stream, stream_length);
g_free (stream);
}
}
@ -1434,6 +1444,136 @@ gimp_dnd_svg_dest_remove (GtkWidget *widget)
}
/**************************/
/* pixbuf dnd functions */
/**************************/
static void
gimp_dnd_get_pixbuf_data (GtkWidget *widget,
GdkDragContext *context,
GCallback get_pixbuf_func,
gpointer get_pixbuf_data,
GtkSelectionData *selection)
{
GdkPixbuf *pixbuf;
pixbuf = (* (GimpDndDragPixbufFunc) get_pixbuf_func) (widget,
get_pixbuf_data);
if (pixbuf)
{
gtk_selection_data_set_pixbuf (selection, pixbuf);
g_object_unref (pixbuf);
}
}
static gboolean
gimp_dnd_set_pixbuf_data (GtkWidget *widget,
gint x,
gint y,
GCallback set_pixbuf_func,
gpointer set_pixbuf_data,
GtkSelectionData *selection)
{
GdkPixbuf *pixbuf;
pixbuf = gtk_selection_data_get_pixbuf (selection);
if (! pixbuf)
return FALSE;
(* (GimpDndDropPixbufFunc) set_pixbuf_func) (widget, x, y,
pixbuf,
set_pixbuf_data);
g_object_unref (pixbuf);
return TRUE;
}
void
gimp_dnd_pixbuf_source_add (GtkWidget *widget,
GimpDndDragPixbufFunc get_pixbuf_func,
gpointer data)
{
GtkTargetList *target_list;
g_return_if_fail (GTK_IS_WIDGET (widget));
gimp_dnd_data_source_add (GIMP_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);
gimp_pixbuf_targets_add (target_list, GIMP_DND_TYPE_PIXBUF, TRUE);
gtk_drag_source_set_target_list (widget, target_list);
gtk_target_list_unref (target_list);
}
void
gimp_dnd_pixbuf_source_remove (GtkWidget *widget)
{
GtkTargetList *target_list;
g_return_if_fail (GTK_IS_WIDGET (widget));
gimp_dnd_data_source_remove (GIMP_DND_TYPE_PIXBUF, widget);
target_list = gtk_drag_source_get_target_list (widget);
if (target_list)
gimp_pixbuf_targets_remove (target_list);
}
void
gimp_dnd_pixbuf_dest_add (GtkWidget *widget,
GimpDndDropPixbufFunc set_pixbuf_func,
gpointer data)
{
GtkTargetList *target_list;
g_return_if_fail (GTK_IS_WIDGET (widget));
gimp_dnd_data_dest_add (GIMP_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);
gimp_pixbuf_targets_add (target_list, GIMP_DND_TYPE_PIXBUF, FALSE);
gtk_drag_dest_set_target_list (widget, target_list);
gtk_target_list_unref (target_list);
}
void
gimp_dnd_pixbuf_dest_remove (GtkWidget *widget)
{
GtkTargetList *target_list;
g_return_if_fail (GTK_IS_WIDGET (widget));
gimp_dnd_data_dest_remove (GIMP_DND_TYPE_PIXBUF, widget);
target_list = gtk_drag_dest_get_target_list (widget);
if (target_list)
gimp_pixbuf_targets_remove (target_list);
}
/*****************************/
/* component dnd functions */
/*****************************/
@ -1465,8 +1605,7 @@ gimp_dnd_get_component_data (GtkWidget *widget,
GdkDragContext *context,
GCallback get_comp_func,
gpointer get_comp_data,
GtkSelectionData *selection,
GdkAtom atom)
GtkSelectionData *selection)
{
GimpImage *image;
GimpChannelType channel = 0;
@ -1475,7 +1614,7 @@ gimp_dnd_get_component_data (GtkWidget *widget,
get_comp_data);
if (image)
gimp_selection_data_set_component (selection, atom, image, channel);
gimp_selection_data_set_component (selection, image, channel);
}
static gboolean
@ -1799,8 +1938,7 @@ gimp_dnd_get_image_data (GtkWidget *widget,
GdkDragContext *context,
GCallback get_image_func,
gpointer get_image_data,
GtkSelectionData *selection,
GdkAtom atom)
GtkSelectionData *selection)
{
GimpImage *gimage;
@ -1808,7 +1946,7 @@ gimp_dnd_get_image_data (GtkWidget *widget,
(* (GimpDndDragViewableFunc) get_image_func) (widget, get_image_data);
if (gimage)
gimp_selection_data_set_image (selection, atom, gimage);
gimp_selection_data_set_image (selection, gimage);
}
static gboolean
@ -1841,8 +1979,7 @@ gimp_dnd_get_item_data (GtkWidget *widget,
GdkDragContext *context,
GCallback get_item_func,
gpointer get_item_data,
GtkSelectionData *selection,
GdkAtom atom)
GtkSelectionData *selection)
{
GimpItem *item;
@ -1850,7 +1987,7 @@ gimp_dnd_get_item_data (GtkWidget *widget,
(* (GimpDndDragViewableFunc) get_item_func) (widget, get_item_data);
if (item)
gimp_selection_data_set_item (selection, atom, item);
gimp_selection_data_set_item (selection, item);
}
static gboolean
@ -1883,8 +2020,7 @@ gimp_dnd_get_data_data (GtkWidget *widget,
GdkDragContext *context,
GCallback get_data_func,
gpointer get_data_data,
GtkSelectionData *selection,
GdkAtom atom)
GtkSelectionData *selection)
{
GimpData *data;
@ -1892,7 +2028,7 @@ gimp_dnd_get_data_data (GtkWidget *widget,
(* (GimpDndDragViewableFunc) get_data_func) (widget, get_data_data);
if (data)
gimp_selection_data_set_viewable (selection, atom, GIMP_VIEWABLE (data));
gimp_selection_data_set_viewable (selection, GIMP_VIEWABLE (data));
}

View file

@ -35,15 +35,18 @@
#define GIMP_TARGET_COLOR \
{ "application/x-color", 0, GIMP_DND_TYPE_COLOR }
#define GIMP_TARGET_PNG \
{ "image/png", 0, GIMP_DND_TYPE_PNG }
#define GIMP_TARGET_SVG \
{ "image/svg", 0, GIMP_DND_TYPE_SVG }
#define GIMP_TARGET_SVG_XML \
{ "image/svg+xml", 0, GIMP_DND_TYPE_SVG_XML }
/* just here for documentation purposes, the actual list of targets
* is created dynamically from available GdkPixbuf loaders
*/
#define GIMP_TARGET_PIXBUF \
{ NULL, 0, GIMP_DND_TYPE_PIXBUF }
#define GIMP_TARGET_IMAGE \
{ "application/x-gimp-image-id", GTK_TARGET_SAME_APP, GIMP_DND_TYPE_IMAGE }
@ -164,6 +167,27 @@ void gimp_dnd_svg_dest_add (GtkWidget *widget,
void gimp_dnd_svg_dest_remove (GtkWidget *widget);
/* pixbuf dnd functions */
typedef GdkPixbuf * (* GimpDndDragPixbufFunc) (GtkWidget *widget,
gpointer data);
typedef void (* GimpDndDropPixbufFunc) (GtkWidget *widget,
gint x,
gint y,
GdkPixbuf *pixbuf,
gpointer data);
void gimp_dnd_pixbuf_source_add (GtkWidget *widget,
GimpDndDragPixbufFunc get_pixbuf_func,
gpointer data);
void gimp_dnd_pixbuf_source_remove (GtkWidget *widget);
void gimp_dnd_pixbuf_dest_add (GtkWidget *widget,
GimpDndDropPixbufFunc set_pixbuf_func,
gpointer data);
void gimp_dnd_pixbuf_dest_remove (GtkWidget *widget);
/* component dnd functions */
typedef GimpImage * (* GimpDndDragComponentFunc) (GtkWidget *widget,

View file

@ -51,6 +51,8 @@ static GObject * gimp_drawable_tree_view_constructor (GType type,
guint n_params,
GObjectConstructParam *params);
static void gimp_drawable_tree_view_set_container (GimpContainerView *view,
GimpContainer *container);
static gboolean gimp_drawable_tree_view_select_item (GimpContainerView *view,
GimpViewable *item,
gpointer insert_data);
@ -78,6 +80,10 @@ static void gimp_drawable_tree_view_floating_selection_changed
(GimpImage *gimage,
GimpDrawableTreeView *view);
static GdkPixbuf * gimp_drawable_tree_view_drag_pixbuf
(GtkWidget *widget,
gpointer data);
static void gimp_drawable_tree_view_new_pattern_dropped
(GtkWidget *widget,
gint x,
@ -195,12 +201,37 @@ gimp_drawable_tree_view_view_iface_init (GimpContainerViewInterface *view_iface)
{
parent_view_iface = g_type_interface_peek_parent (view_iface);
view_iface->select_item = gimp_drawable_tree_view_select_item;
view_iface->set_container = gimp_drawable_tree_view_set_container;
view_iface->select_item = gimp_drawable_tree_view_select_item;
}
/* GimpContainerView methods */
static void
gimp_drawable_tree_view_set_container (GimpContainerView *view,
GimpContainer *container)
{
GimpContainerTreeView *tree_view = GIMP_CONTAINER_TREE_VIEW (view);
GimpContainer *old_container;
old_container = gimp_container_view_get_container (GIMP_CONTAINER_VIEW (view));
if (old_container && ! container)
{
gimp_dnd_pixbuf_source_remove (GTK_WIDGET (tree_view->view));
}
parent_view_iface->set_container (view, container);
if (! old_container && container)
{
gimp_dnd_pixbuf_source_add (GTK_WIDGET (tree_view->view),
gimp_drawable_tree_view_drag_pixbuf,
tree_view);
}
}
static gboolean
gimp_drawable_tree_view_select_item (GimpContainerView *view,
GimpViewable *item,
@ -347,6 +378,30 @@ gimp_drawable_tree_view_floating_selection_changed (GimpImage *gimage
(GimpViewable *) item);
}
static GdkPixbuf *
gimp_drawable_tree_view_drag_pixbuf (GtkWidget *widget,
gpointer data)
{
GimpItemTreeView *view = GIMP_ITEM_TREE_VIEW (data);
GimpImage *gimage = view->gimage;
GimpItem *item;
GdkPixbuf *pixbuf = NULL;
item = GIMP_ITEM_TREE_VIEW_GET_CLASS (view)->get_active_item (gimage);
if (item)
{
pixbuf = gimp_viewable_get_pixbuf (GIMP_VIEWABLE (item),
gimp_item_width (item),
gimp_item_height (item));
if (pixbuf)
g_object_ref (pixbuf);
}
return pixbuf;
}
static void
gimp_drawable_tree_view_new_dropped (GimpItemTreeView *view,
gint x,

View file

@ -102,6 +102,10 @@ static void gimp_layer_tree_view_drop_component (GimpContainerTreeView *tree_v
GimpChannelType component,
GimpViewable *dest_viewable,
GtkTreeViewDropPosition drop_pos);
static void gimp_layer_tree_view_drop_pixbuf (GimpContainerTreeView *tree_view,
GdkPixbuf *pixbuf,
GimpViewable *dest_viewable,
GtkTreeViewDropPosition drop_pos);
static void gimp_layer_tree_view_set_image (GimpItemTreeView *view,
GimpImage *gimage);
@ -224,6 +228,7 @@ gimp_layer_tree_view_class_init (GimpLayerTreeViewClass *klass)
tree_view_class->drop_color = gimp_layer_tree_view_drop_color;
tree_view_class->drop_uri_list = gimp_layer_tree_view_drop_uri_list;
tree_view_class->drop_component = gimp_layer_tree_view_drop_component;
tree_view_class->drop_pixbuf = gimp_layer_tree_view_drop_pixbuf;
item_view_class->item_type = GIMP_TYPE_LAYER;
item_view_class->signal_name = "active-layer-changed";
@ -414,6 +419,8 @@ gimp_layer_tree_view_constructor (GType type,
NULL, tree_view);
gimp_dnd_viewable_dest_add (GTK_WIDGET (tree_view->view), GIMP_TYPE_LAYER_MASK,
NULL, tree_view);
gimp_dnd_pixbuf_dest_add (GTK_WIDGET (tree_view->view),
NULL, tree_view);
/* hide basically useless edit button */
gtk_widget_hide (GIMP_ITEM_TREE_VIEW (layer_view)->edit_button);
@ -663,6 +670,7 @@ gimp_layer_tree_view_drop_possible (GimpContainerTreeView *tree_view,
src_type == GIMP_DND_TYPE_TEXT_PLAIN ||
src_type == GIMP_DND_TYPE_NETSCAPE_URL ||
src_type == GIMP_DND_TYPE_COMPONENT ||
src_type == GIMP_DND_TYPE_PIXBUF ||
GIMP_IS_DRAWABLE (src_viewable))
{
GimpLayer *dest_layer = GIMP_LAYER (dest_viewable);
@ -820,6 +828,35 @@ gimp_layer_tree_view_drop_component (GimpContainerTreeView *tree_view,
gimp_image_flush (item_view->gimage);
}
static void
gimp_layer_tree_view_drop_pixbuf (GimpContainerTreeView *tree_view,
GdkPixbuf *pixbuf,
GimpViewable *dest_viewable,
GtkTreeViewDropPosition drop_pos)
{
GimpItemTreeView *item_view = GIMP_ITEM_TREE_VIEW (tree_view);
GimpImage *image = item_view->gimage;
GimpLayer *new_layer;
gint index = -1;
if (dest_viewable)
{
index = gimp_image_get_layer_index (image, GIMP_LAYER (dest_viewable));
if (drop_pos == GTK_TREE_VIEW_DROP_AFTER)
index++;
}
new_layer =
gimp_layer_new_from_pixbuf (pixbuf, image,
gimp_image_base_type_with_alpha (image),
_("Dropped Buffer"),
GIMP_OPACITY_OPAQUE, GIMP_NORMAL_MODE);
gimp_image_add_layer (image, new_layer, index);
gimp_image_flush (image);
}
/* GimpItemTreeView methods */

155
app/widgets/gimppixbuf.c Normal file
View file

@ -0,0 +1,155 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* gimppixbuf.c
* Copyright (C) 2005 Michael Natterer <mitch@gimp.org>
*
* 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 2 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <gtk/gtk.h>
#include "widgets-types.h"
#include "gimppixbuf.h"
/* local function prototypes */
static gint gimp_pixbuf_format_compare (GdkPixbufFormat *a,
GdkPixbufFormat *b);
/* public functions */
GSList *
gimp_pixbuf_get_formats (void)
{
return g_slist_sort (gdk_pixbuf_get_formats (),
(GCompareFunc) gimp_pixbuf_format_compare);
}
void
gimp_pixbuf_targets_add (GtkTargetList *target_list,
guint info,
gboolean writable)
{
GSList *formats;
GSList *list;
g_return_if_fail (target_list != NULL);
formats = gimp_pixbuf_get_formats ();
for (list = formats; list; list = g_slist_next (list))
{
GdkPixbufFormat *format = list->data;
gchar **mime_types;
gchar **type;
if (writable && ! gdk_pixbuf_format_is_writable (format))
continue;
mime_types = gdk_pixbuf_format_get_mime_types (format);
for (type = mime_types; *type; type++)
{
GdkAtom *atom = gdk_atom_intern (*type, FALSE);
gtk_target_list_add (target_list, atom, 0, info);
}
g_strfreev (mime_types);
}
g_slist_free (formats);
}
void
gimp_pixbuf_targets_remove (GtkTargetList *target_list)
{
GSList *formats;
GSList *list;
g_return_if_fail (target_list != NULL);
formats = gimp_pixbuf_get_formats ();
for (list = formats; list; list = g_slist_next (list))
{
GdkPixbufFormat *format = list->data;
gchar **mime_types;
gchar **type;
mime_types = gdk_pixbuf_format_get_mime_types (format);
for (type = mime_types; *type; type++)
{
GdkAtom *atom = gdk_atom_intern (*type, FALSE);
gtk_target_list_remove (target_list, atom);
}
g_strfreev (mime_types);
}
g_slist_free (formats);
}
/* private functions */
static gint
gimp_pixbuf_format_compare (GdkPixbufFormat *a,
GdkPixbufFormat *b)
{
gchar *a_name = gdk_pixbuf_format_get_name (a);
gchar *b_name = gdk_pixbuf_format_get_name (b);
gint retval = 0;
#ifdef GDK_WINDOWING_WIN32
/* move BMP to the front of the list */
if (strcmp (a_name, "bmp") == 0)
retval = -1;
else if (strcmp (b_name, "bmp") == 0)
retval = 1;
else
#endif
/* move PNG to the front of the list */
if (strcmp (a_name, "png") == 0)
retval = -1;
else if (strcmp (b_name, "png") == 0)
retval = 1;
/* move JPEG to the end of the list */
else if (strcmp (a_name, "jpeg") == 0)
retval = 1;
else if (strcmp (b_name, "jpeg") == 0)
retval = -1;
/* move GIF to the end of the list */
else if (strcmp (a_name, "gif") == 0)
retval = 1;
else if (strcmp (b_name, "gif") == 0)
retval = -1;
g_free (a_name);
g_free (b_name);
return retval;
}

34
app/widgets/gimppixbuf.h Normal file
View file

@ -0,0 +1,34 @@
/* The GIMP -- an image manipulation program
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* gimppixbuf.h
* Copyright (C) 2005 Michael Natterer <mitch@gimp.org>
*
* 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 2 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __GIMP_PIXBUF_H__
#define __GIMP_PIXBUF_H__
GSList * gimp_pixbuf_get_formats (void);
void gimp_pixbuf_targets_add (GtkTargetList *target_list,
guint info,
gboolean writable);
void gimp_pixbuf_targets_remove (GtkTargetList *target_list);
#endif /* __GIMP_PIXBUF_H__ */

View file

@ -58,14 +58,12 @@
void
gimp_selection_data_set_uri_list (GtkSelectionData *selection,
GdkAtom atom,
GList *uri_list)
{
GList *list;
gchar *vals = NULL;
g_return_if_fail (selection != NULL);
g_return_if_fail (atom != GDK_NONE);
g_return_if_fail (uri_list != NULL);
for (list = uri_list; list; list = g_list_next (list))
@ -87,7 +85,7 @@ gimp_selection_data_set_uri_list (GtkSelectionData *selection,
}
}
gtk_selection_data_set (selection, atom,
gtk_selection_data_set (selection, selection->target,
8, (guchar *) vals, strlen (vals) + 1);
g_free (vals);
@ -351,14 +349,12 @@ gimp_selection_data_get_uri_list (GtkSelectionData *selection)
void
gimp_selection_data_set_color (GtkSelectionData *selection,
GdkAtom atom,
const GimpRGB *color)
{
guint16 *vals;
guchar r, g, b, a;
g_return_if_fail (selection != NULL);
g_return_if_fail (atom != GDK_NONE);
g_return_if_fail (color != NULL);
vals = g_new (guint16, 4);
@ -370,7 +366,7 @@ gimp_selection_data_set_color (GtkSelectionData *selection,
vals[2] = b + (b << 8);
vals[3] = a + (a << 8);
gtk_selection_data_set (selection, atom,
gtk_selection_data_set (selection, selection->target,
16, (guchar *) vals, 8);
g_free (vals);
@ -404,16 +400,14 @@ gimp_selection_data_get_color (GtkSelectionData *selection,
void
gimp_selection_data_set_stream (GtkSelectionData *selection,
GdkAtom atom,
const guchar *stream,
gsize stream_length)
{
g_return_if_fail (selection != NULL);
g_return_if_fail (atom != GDK_NONE);
g_return_if_fail (stream != NULL);
g_return_if_fail (stream_length > 0);
gtk_selection_data_set (selection, atom,
gtk_selection_data_set (selection, selection->target,
8, (guchar *) stream, stream_length);
}
@ -435,85 +429,18 @@ gimp_selection_data_get_stream (GtkSelectionData *selection,
return (const guchar *) selection->data;
}
void
gimp_selection_data_set_pixbuf (GtkSelectionData *selection,
GdkAtom atom,
GdkPixbuf *pixbuf,
const gchar *format)
{
gchar *buffer;
gsize buffer_size;
GError *error = NULL;
g_return_if_fail (selection != NULL);
g_return_if_fail (atom != GDK_NONE);
g_return_if_fail (GDK_IS_PIXBUF (pixbuf));
g_return_if_fail (format != NULL);
if (gdk_pixbuf_save_to_buffer (pixbuf,
&buffer, &buffer_size, format,
&error, NULL))
{
gtk_selection_data_set (selection, atom,
8, (guchar *) buffer, buffer_size);
g_free (buffer);
}
else
{
g_warning ("%s: %s", G_STRFUNC, error->message);
g_error_free (error);
}
}
GdkPixbuf *
gimp_selection_data_get_pixbuf (GtkSelectionData *selection)
{
GdkPixbufLoader *loader;
GdkPixbuf *pixbuf = NULL;
GError *error = NULL;
g_return_val_if_fail (selection != NULL, NULL);
if ((selection->format != 8) || (selection->length < 1))
{
g_warning ("Received invalid image data!");
return NULL;
}
loader = gdk_pixbuf_loader_new ();
if (gdk_pixbuf_loader_write (loader,
selection->data, selection->length, &error) &&
gdk_pixbuf_loader_close (loader, &error))
{
pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
g_object_ref (pixbuf);
}
else
{
g_warning ("%s: %s", G_STRFUNC, error->message);
g_error_free (error);
}
g_object_unref (loader);
return pixbuf;
}
void
gimp_selection_data_set_image (GtkSelectionData *selection,
GdkAtom atom,
GimpImage *gimage)
{
gchar *id;
g_return_if_fail (selection != NULL);
g_return_if_fail (atom != GDK_NONE);
g_return_if_fail (GIMP_IS_IMAGE (gimage));
id = g_strdup_printf ("%d", gimp_image_get_ID (gimage));
gtk_selection_data_set (selection, atom,
gtk_selection_data_set (selection, selection->target,
8, (guchar *) id, strlen (id) + 1);
g_free (id);
@ -547,19 +474,17 @@ gimp_selection_data_get_image (GtkSelectionData *selection,
void
gimp_selection_data_set_component (GtkSelectionData *selection,
GdkAtom atom,
GimpImage *gimage,
GimpChannelType channel)
{
gchar *id;
g_return_if_fail (selection != NULL);
g_return_if_fail (atom != GDK_NONE);
g_return_if_fail (GIMP_IS_IMAGE (gimage));
id = g_strdup_printf ("%d:%d", gimp_image_get_ID (gimage), (gint) channel);
gtk_selection_data_set (selection, atom,
gtk_selection_data_set (selection, selection->target,
8, (guchar *) id, strlen (id) + 1);
g_free (id);
@ -604,18 +529,16 @@ gimp_selection_data_get_component (GtkSelectionData *selection,
void
gimp_selection_data_set_item (GtkSelectionData *selection,
GdkAtom atom,
GimpItem *item)
{
gchar *id;
g_return_if_fail (selection != NULL);
g_return_if_fail (atom != GDK_NONE);
g_return_if_fail (GIMP_IS_ITEM (item));
id = g_strdup_printf ("%d", gimp_item_get_ID (item));
gtk_selection_data_set (selection, atom,
gtk_selection_data_set (selection, selection->target,
8, (guchar *) id, strlen (id) + 1);
g_free (id);
@ -649,19 +572,17 @@ gimp_selection_data_get_item (GtkSelectionData *selection,
void
gimp_selection_data_set_viewable (GtkSelectionData *selection,
GdkAtom atom,
GimpViewable *viewable)
{
const gchar *name;
g_return_if_fail (selection != NULL);
g_return_if_fail (atom != GDK_NONE);
g_return_if_fail (GIMP_IS_VIEWABLE (viewable));
name = gimp_object_get_name (GIMP_OBJECT (viewable));
if (name)
gtk_selection_data_set (selection, atom,
gtk_selection_data_set (selection, selection->target,
8, (const guchar *) name, strlen (name) + 1);
}

View file

@ -23,7 +23,6 @@
/* uri list */
void gimp_selection_data_set_uri_list (GtkSelectionData *selection,
GdkAtom atom,
GList *uris);
GList * gimp_selection_data_get_uri_list (GtkSelectionData *selection);
@ -31,7 +30,6 @@ GList * gimp_selection_data_get_uri_list (GtkSelectionData *selection);
/* color */
void gimp_selection_data_set_color (GtkSelectionData *selection,
GdkAtom atom,
const GimpRGB *color);
gboolean gimp_selection_data_get_color (GtkSelectionData *selection,
GimpRGB *color);
@ -40,26 +38,15 @@ gboolean gimp_selection_data_get_color (GtkSelectionData *selection,
/* stream (svg/png) */
void gimp_selection_data_set_stream (GtkSelectionData *selection,
GdkAtom atom,
const guchar *stream,
gsize stream_length);
const guchar * gimp_selection_data_get_stream (GtkSelectionData *selection,
gsize *stream_length);
/* pixbuf */
void gimp_selection_data_set_pixbuf (GtkSelectionData *selection,
GdkAtom atom,
GdkPixbuf *pixbuf,
const gchar *format);
GdkPixbuf * gimp_selection_data_get_pixbuf (GtkSelectionData *selection);
/* image */
void gimp_selection_data_set_image (GtkSelectionData *selection,
GdkAtom atom,
GimpImage *gimage);
GimpImage * gimp_selection_data_get_image (GtkSelectionData *selection,
Gimp *gimp);
@ -68,7 +55,6 @@ GimpImage * gimp_selection_data_get_image (GtkSelectionData *selection,
/* component */
void gimp_selection_data_set_component (GtkSelectionData *selection,
GdkAtom atom,
GimpImage *gimage,
GimpChannelType channel);
GimpImage * gimp_selection_data_get_component (GtkSelectionData *selection,
@ -79,7 +65,6 @@ GimpImage * gimp_selection_data_get_component (GtkSelectionData *selection,
/* item */
void gimp_selection_data_set_item (GtkSelectionData *selection,
GdkAtom atom,
GimpItem *item);
GimpItem * gimp_selection_data_get_item (GtkSelectionData *selection,
Gimp *gimp);
@ -88,7 +73,6 @@ GimpItem * gimp_selection_data_get_item (GtkSelectionData *selection,
/* various data */
void gimp_selection_data_set_viewable (GtkSelectionData *selection,
GdkAtom atom,
GimpViewable *viewable);
GimpBrush * gimp_selection_data_get_brush (GtkSelectionData *selection,

View file

@ -194,9 +194,9 @@ typedef enum /*< skip >*/
GIMP_DND_TYPE_NETSCAPE_URL = 3,
GIMP_DND_TYPE_XDS = 4,
GIMP_DND_TYPE_COLOR = 5,
GIMP_DND_TYPE_PNG = 6,
GIMP_DND_TYPE_SVG = 7,
GIMP_DND_TYPE_SVG_XML = 8,
GIMP_DND_TYPE_SVG = 6,
GIMP_DND_TYPE_SVG_XML = 7,
GIMP_DND_TYPE_PIXBUF = 8,
GIMP_DND_TYPE_IMAGE = 9,
GIMP_DND_TYPE_COMPONENT = 10,
GIMP_DND_TYPE_LAYER = 11,