app: make drag'n drop multi-drawable selection aware.
This whole drag'n drop code is quite overwhelming, I'm pretty sure this commit introduced various bugs, and there are already several areas of improvements I noticed. But at some point, I need to split at a not-too broken code state or I'll just make things worse.
This commit is contained in:
parent
48410d9ea4
commit
83b3d9e52e
17 changed files with 1012 additions and 309 deletions
|
|
@ -245,7 +245,7 @@ quit_close_all_dialog_new (Gimp *gimp,
|
|||
|
||||
dnd_widget = gimp_container_view_get_dnd_widget (GIMP_CONTAINER_VIEW (view));
|
||||
gimp_dnd_xds_source_add (dnd_widget,
|
||||
(GimpDndDragViewableFunc) gimp_dnd_get_drag_data,
|
||||
(GimpDndDragViewableFunc) gimp_dnd_get_drag_viewable,
|
||||
NULL);
|
||||
|
||||
g_signal_connect (tree_view->view, "query-tooltip",
|
||||
|
|
|
|||
|
|
@ -61,8 +61,8 @@ static void gimp_channel_tree_view_view_iface_init (GimpContainerViewInterfac
|
|||
|
||||
static void gimp_channel_tree_view_constructed (GObject *object);
|
||||
|
||||
static void gimp_channel_tree_view_drop_viewable (GimpContainerTreeView *view,
|
||||
GimpViewable *src_viewable,
|
||||
static void gimp_channel_tree_view_drop_viewables (GimpContainerTreeView *view,
|
||||
GList *src_viewables,
|
||||
GimpViewable *dest_viewable,
|
||||
GtkTreeViewDropPosition drop_pos);
|
||||
static void gimp_channel_tree_view_drop_component (GimpContainerTreeView *tree_view,
|
||||
|
|
@ -99,7 +99,7 @@ gimp_channel_tree_view_class_init (GimpChannelTreeViewClass *klass)
|
|||
|
||||
object_class->constructed = gimp_channel_tree_view_constructed;
|
||||
|
||||
view_class->drop_viewable = gimp_channel_tree_view_drop_viewable;
|
||||
view_class->drop_viewables = gimp_channel_tree_view_drop_viewables;
|
||||
view_class->drop_component = gimp_channel_tree_view_drop_component;
|
||||
|
||||
iv_class->set_image = gimp_channel_tree_view_set_image;
|
||||
|
|
@ -189,46 +189,52 @@ gimp_channel_tree_view_constructed (GObject *object)
|
|||
/* GimpContainerTreeView methods */
|
||||
|
||||
static void
|
||||
gimp_channel_tree_view_drop_viewable (GimpContainerTreeView *tree_view,
|
||||
GimpViewable *src_viewable,
|
||||
GimpViewable *dest_viewable,
|
||||
GtkTreeViewDropPosition drop_pos)
|
||||
gimp_channel_tree_view_drop_viewables (GimpContainerTreeView *tree_view,
|
||||
GList *src_viewables,
|
||||
GimpViewable *dest_viewable,
|
||||
GtkTreeViewDropPosition drop_pos)
|
||||
{
|
||||
GimpItemTreeView *item_view = GIMP_ITEM_TREE_VIEW (tree_view);
|
||||
GimpImage *image = gimp_item_tree_view_get_image (item_view);
|
||||
GimpItemTreeViewClass *item_view_class;
|
||||
GList *iter;
|
||||
|
||||
item_view_class = GIMP_ITEM_TREE_VIEW_GET_CLASS (item_view);
|
||||
|
||||
if (GIMP_IS_DRAWABLE (src_viewable) &&
|
||||
(image != gimp_item_get_image (GIMP_ITEM (src_viewable)) ||
|
||||
G_TYPE_FROM_INSTANCE (src_viewable) != item_view_class->item_type))
|
||||
for (iter = src_viewables; iter; iter = iter->next)
|
||||
{
|
||||
GimpItem *new_item;
|
||||
GimpItem *parent;
|
||||
gint index;
|
||||
GimpViewable *src_viewable = iter->data;
|
||||
|
||||
index = gimp_item_tree_view_get_drop_index (item_view, dest_viewable,
|
||||
drop_pos,
|
||||
(GimpViewable **) &parent);
|
||||
if (GIMP_IS_DRAWABLE (src_viewable) &&
|
||||
(image != gimp_item_get_image (GIMP_ITEM (src_viewable)) ||
|
||||
G_TYPE_FROM_INSTANCE (src_viewable) != item_view_class->item_type))
|
||||
{
|
||||
GimpItem *new_item;
|
||||
GimpItem *parent;
|
||||
gint index;
|
||||
|
||||
new_item = gimp_item_convert (GIMP_ITEM (src_viewable),
|
||||
gimp_item_tree_view_get_image (item_view),
|
||||
item_view_class->item_type);
|
||||
index = gimp_item_tree_view_get_drop_index (item_view, dest_viewable,
|
||||
drop_pos,
|
||||
(GimpViewable **) &parent);
|
||||
|
||||
gimp_item_set_linked (new_item, FALSE, FALSE);
|
||||
new_item = gimp_item_convert (GIMP_ITEM (src_viewable),
|
||||
gimp_item_tree_view_get_image (item_view),
|
||||
item_view_class->item_type);
|
||||
|
||||
item_view_class->add_item (image, new_item, parent, index, TRUE);
|
||||
gimp_item_set_linked (new_item, FALSE, FALSE);
|
||||
|
||||
gimp_image_flush (image);
|
||||
item_view_class->add_item (image, new_item, parent, index, TRUE);
|
||||
|
||||
return;
|
||||
gimp_image_flush (image);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
GIMP_CONTAINER_TREE_VIEW_CLASS (parent_class)->drop_viewable (tree_view,
|
||||
src_viewable,
|
||||
dest_viewable,
|
||||
drop_pos);
|
||||
GIMP_CONTAINER_TREE_VIEW_CLASS (parent_class)->drop_viewables (tree_view,
|
||||
src_viewables,
|
||||
dest_viewable,
|
||||
drop_pos);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
|||
|
|
@ -38,6 +38,97 @@
|
|||
#include "gimpselectiondata.h"
|
||||
|
||||
|
||||
static gint
|
||||
gimp_container_tree_view_viewable_sort (GimpViewable *v1,
|
||||
GimpViewable *v2,
|
||||
GimpContainerTreeView *tree_view)
|
||||
{
|
||||
GimpContainerView *view = GIMP_CONTAINER_VIEW (tree_view);
|
||||
GimpViewable *parent1;
|
||||
GimpViewable *parent2;
|
||||
GimpContainer *container1 = NULL;
|
||||
GimpContainer *container2 = NULL;
|
||||
GimpContainer *container = gimp_container_view_get_container (view);
|
||||
gint index1 = -1;
|
||||
gint index2 = -1;
|
||||
gint depth1;
|
||||
gint depth2;
|
||||
|
||||
parent1 = gimp_viewable_get_parent (v1);
|
||||
parent2 = gimp_viewable_get_parent (v2);
|
||||
|
||||
if (parent1)
|
||||
container1 = gimp_viewable_get_children (parent1);
|
||||
else if (gimp_container_have (container, GIMP_OBJECT (v1)))
|
||||
container1 = container;
|
||||
|
||||
if (parent2)
|
||||
container2 = gimp_viewable_get_children (parent2);
|
||||
else if (gimp_container_have (container, GIMP_OBJECT (v2)))
|
||||
container2 = container;
|
||||
|
||||
g_return_val_if_fail (container1 && container2, 0);
|
||||
|
||||
if (container1 == container2)
|
||||
{
|
||||
index1 = gimp_container_get_child_index (container1, GIMP_OBJECT (v1));
|
||||
index2 = gimp_container_get_child_index (container2, GIMP_OBJECT (v2));
|
||||
|
||||
return index1 < index2 ? -1 : (index1 > index2 ? 1 : 0);
|
||||
}
|
||||
|
||||
depth1 = gimp_viewable_get_depth (v1);
|
||||
depth2 = gimp_viewable_get_depth (v2);
|
||||
|
||||
if (depth1 == depth2)
|
||||
{
|
||||
return gimp_container_tree_view_viewable_sort (parent1, parent2, tree_view);
|
||||
}
|
||||
else if (depth1 > depth2)
|
||||
{
|
||||
depth1 = gimp_viewable_get_depth (parent1);
|
||||
while (depth1 > depth2)
|
||||
{
|
||||
parent1 = gimp_viewable_get_parent (parent1);
|
||||
depth1 = gimp_viewable_get_depth (parent1);
|
||||
}
|
||||
return gimp_container_tree_view_viewable_sort (parent1, v2, tree_view);
|
||||
}
|
||||
else /* if (depth1 < depth2) */
|
||||
{
|
||||
depth2 = gimp_viewable_get_depth (parent2);
|
||||
while (depth1 < depth2)
|
||||
{
|
||||
parent2 = gimp_viewable_get_parent (parent2);
|
||||
depth2 = gimp_viewable_get_depth (parent2);
|
||||
}
|
||||
return gimp_container_tree_view_viewable_sort (v1, parent2, tree_view);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* gimp_container_tree_view_drop_status:
|
||||
* @tree_view:
|
||||
* @context:
|
||||
* @x:
|
||||
* @y:
|
||||
* @time:
|
||||
* @return_path: the #GtkTreePath of the drop position if the drop is
|
||||
* possible.
|
||||
* @return_atom:
|
||||
* @return_src_type: the type of drag'n drop.
|
||||
* @return_src: allocated #GList of #GimpViewable being dragged.
|
||||
* @return_dest: the #GimpViewable you are dropping on.
|
||||
* @return_pos: the drop position (before, after or into @return_dest).
|
||||
*
|
||||
* Check whether the current drag can be dropped into @tree_view at
|
||||
* position (@x, @y). If so, the various return value information will
|
||||
* be optionally filled.
|
||||
* Note: if @return_src is not %NULL, hence is filled, it must be freed
|
||||
* with g_list_free().
|
||||
*
|
||||
* Returns: %TRUE is the drop is possible, %FALSE otherwise.
|
||||
*/
|
||||
static gboolean
|
||||
gimp_container_tree_view_drop_status (GimpContainerTreeView *tree_view,
|
||||
GdkDragContext *context,
|
||||
|
|
@ -47,11 +138,11 @@ gimp_container_tree_view_drop_status (GimpContainerTreeView *tree_view,
|
|||
GtkTreePath **return_path,
|
||||
GdkAtom *return_atom,
|
||||
GimpDndType *return_src_type,
|
||||
GimpViewable **return_src,
|
||||
GList **return_src,
|
||||
GimpViewable **return_dest,
|
||||
GtkTreeViewDropPosition *return_pos)
|
||||
{
|
||||
GimpViewable *src_viewable = NULL;
|
||||
GList *src_viewables = NULL;
|
||||
GimpViewable *dest_viewable = NULL;
|
||||
GtkTreePath *drop_path = NULL;
|
||||
GtkTargetList *target_list;
|
||||
|
|
@ -82,19 +173,67 @@ gimp_container_tree_view_drop_status (GimpContainerTreeView *tree_view,
|
|||
case GIMP_DND_TYPE_PIXBUF:
|
||||
break;
|
||||
|
||||
default:
|
||||
case GIMP_DND_TYPE_XDS:
|
||||
case GIMP_DND_TYPE_IMAGE:
|
||||
case GIMP_DND_TYPE_LAYER:
|
||||
case GIMP_DND_TYPE_CHANNEL:
|
||||
case GIMP_DND_TYPE_LAYER_MASK:
|
||||
case GIMP_DND_TYPE_VECTORS:
|
||||
case GIMP_DND_TYPE_BRUSH:
|
||||
case GIMP_DND_TYPE_PATTERN:
|
||||
case GIMP_DND_TYPE_GRADIENT:
|
||||
case GIMP_DND_TYPE_PALETTE:
|
||||
case GIMP_DND_TYPE_FONT:
|
||||
case GIMP_DND_TYPE_BUFFER:
|
||||
case GIMP_DND_TYPE_IMAGEFILE:
|
||||
case GIMP_DND_TYPE_TEMPLATE:
|
||||
case GIMP_DND_TYPE_TOOL_ITEM:
|
||||
case GIMP_DND_TYPE_NOTEBOOK_TAB:
|
||||
/* Various GimpViewable drag data. */
|
||||
{
|
||||
GtkWidget *src_widget = gtk_drag_get_source_widget (context);
|
||||
GtkWidget *src_widget = gtk_drag_get_source_widget (context);
|
||||
GimpViewable *src_viewable = NULL;
|
||||
|
||||
if (! src_widget)
|
||||
goto drop_impossible;
|
||||
|
||||
src_viewable = gimp_dnd_get_drag_data (src_widget);
|
||||
src_viewable = gimp_dnd_get_drag_viewable (src_widget);
|
||||
|
||||
if (! GIMP_IS_VIEWABLE (src_viewable))
|
||||
goto drop_impossible;
|
||||
|
||||
src_viewables = g_list_prepend (src_viewables, src_viewable);
|
||||
}
|
||||
break;
|
||||
|
||||
case GIMP_DND_TYPE_LAYER_LIST:
|
||||
/* Various GimpViewable list (GList) drag data. */
|
||||
{
|
||||
GtkWidget *src_widget = gtk_drag_get_source_widget (context);
|
||||
GList *iter;
|
||||
|
||||
if (! src_widget)
|
||||
goto drop_impossible;
|
||||
|
||||
src_viewables = gimp_dnd_get_drag_list (src_widget);
|
||||
|
||||
if (! src_viewables)
|
||||
goto drop_impossible;
|
||||
|
||||
for (iter = src_viewables; iter; iter = iter->next)
|
||||
if (! GIMP_IS_VIEWABLE (iter->data))
|
||||
{
|
||||
g_warning ("%s: contents of the viewable list has the wrong type '%s'.",
|
||||
G_STRFUNC, G_OBJECT_TYPE_NAME (iter->data));
|
||||
g_list_free (src_viewables);
|
||||
goto drop_impossible;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
goto drop_impossible;
|
||||
break;
|
||||
}
|
||||
|
||||
if (gtk_tree_view_get_path_at_pos (tree_view->view, x, y,
|
||||
|
|
@ -173,7 +312,7 @@ gimp_container_tree_view_drop_status (GimpContainerTreeView *tree_view,
|
|||
{
|
||||
if (GIMP_CONTAINER_TREE_VIEW_GET_CLASS (tree_view)->drop_possible (tree_view,
|
||||
src_type,
|
||||
src_viewable,
|
||||
src_viewables,
|
||||
dest_viewable,
|
||||
drop_path,
|
||||
drop_pos,
|
||||
|
|
@ -191,7 +330,12 @@ gimp_container_tree_view_drop_status (GimpContainerTreeView *tree_view,
|
|||
*return_atom = target_atom;
|
||||
|
||||
if (return_src)
|
||||
*return_src = src_viewable;
|
||||
{
|
||||
src_viewables = g_list_sort_with_data (src_viewables,
|
||||
(GCompareDataFunc) gimp_container_tree_view_viewable_sort,
|
||||
tree_view);
|
||||
*return_src = src_viewables;
|
||||
}
|
||||
|
||||
if (return_dest)
|
||||
*return_dest = dest_viewable;
|
||||
|
|
@ -359,7 +503,7 @@ gimp_container_tree_view_drag_drop (GtkWidget *widget,
|
|||
GimpContainerTreeView *tree_view)
|
||||
{
|
||||
GimpDndType src_type;
|
||||
GimpViewable *src_viewable;
|
||||
GList *src_viewables;
|
||||
GimpViewable *dest_viewable;
|
||||
GdkAtom target;
|
||||
GtkTreeViewDropPosition drop_pos;
|
||||
|
|
@ -373,28 +517,25 @@ gimp_container_tree_view_drag_drop (GtkWidget *widget,
|
|||
if (gimp_container_tree_view_drop_status (tree_view,
|
||||
context, x, y, time,
|
||||
NULL, &target, &src_type,
|
||||
&src_viewable,
|
||||
&src_viewables,
|
||||
&dest_viewable, &drop_pos))
|
||||
{
|
||||
GimpContainerTreeViewClass *tree_view_class;
|
||||
|
||||
tree_view_class = GIMP_CONTAINER_TREE_VIEW_GET_CLASS (tree_view);
|
||||
|
||||
if (src_viewable)
|
||||
if (src_viewables)
|
||||
{
|
||||
gboolean success = TRUE;
|
||||
|
||||
/* XXX: Make GimpContainerTreeViewClass::drop_viewable()
|
||||
* return success?
|
||||
*/
|
||||
tree_view_class->drop_viewable (tree_view, src_viewable,
|
||||
dest_viewable, drop_pos);
|
||||
tree_view_class->drop_viewables (tree_view, src_viewables,
|
||||
dest_viewable, drop_pos);
|
||||
|
||||
gtk_drag_finish (context, success, FALSE, time);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_drag_get_data (widget, context, target, time);
|
||||
g_list_free (src_viewables);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
|
@ -538,7 +679,7 @@ gimp_container_tree_view_drag_data_received (GtkWidget *widget,
|
|||
gboolean
|
||||
gimp_container_tree_view_real_drop_possible (GimpContainerTreeView *tree_view,
|
||||
GimpDndType src_type,
|
||||
GimpViewable *src_viewable,
|
||||
GList *src_viewables,
|
||||
GimpViewable *dest_viewable,
|
||||
GtkTreePath *drop_path,
|
||||
GtkTreeViewDropPosition drop_pos,
|
||||
|
|
@ -549,23 +690,10 @@ gimp_container_tree_view_real_drop_possible (GimpContainerTreeView *tree_view,
|
|||
GimpContainer *container = gimp_container_view_get_container (view);
|
||||
GimpContainer *src_container = NULL;
|
||||
GimpContainer *dest_container = NULL;
|
||||
GList *iter;
|
||||
gint src_index = -1;
|
||||
gint dest_index = -1;
|
||||
|
||||
if (src_viewable)
|
||||
{
|
||||
GimpViewable *parent = gimp_viewable_get_parent (src_viewable);
|
||||
|
||||
if (parent)
|
||||
src_container = gimp_viewable_get_children (parent);
|
||||
else if (gimp_container_have (container, GIMP_OBJECT (src_viewable)))
|
||||
src_container = container;
|
||||
|
||||
if (src_container)
|
||||
src_index = gimp_container_get_child_index (src_container,
|
||||
GIMP_OBJECT (src_viewable));
|
||||
}
|
||||
|
||||
if (dest_viewable)
|
||||
{
|
||||
GimpViewable *parent;
|
||||
|
|
@ -593,140 +721,181 @@ gimp_container_tree_view_real_drop_possible (GimpContainerTreeView *tree_view,
|
|||
GIMP_OBJECT (dest_viewable));
|
||||
}
|
||||
|
||||
if (src_viewable && g_type_is_a (G_TYPE_FROM_INSTANCE (src_viewable),
|
||||
gimp_container_get_children_type (container)))
|
||||
if (return_drag_action)
|
||||
{
|
||||
if (src_viewable == dest_viewable)
|
||||
return FALSE;
|
||||
|
||||
if (src_index == -1 || dest_index == -1)
|
||||
return FALSE;
|
||||
|
||||
/* don't allow dropping a parent node onto one of its descendants
|
||||
*/
|
||||
if (gimp_viewable_is_ancestor (src_viewable, dest_viewable))
|
||||
return FALSE;
|
||||
if (! src_viewables)
|
||||
*return_drag_action = GDK_ACTION_COPY;
|
||||
else
|
||||
*return_drag_action = GDK_ACTION_MOVE;
|
||||
}
|
||||
|
||||
if (src_container == dest_container)
|
||||
for (iter = src_viewables; iter; iter = iter->next)
|
||||
{
|
||||
if (drop_pos == GTK_TREE_VIEW_DROP_BEFORE)
|
||||
GimpViewable *src_viewable = iter->data;
|
||||
GimpViewable *parent;
|
||||
|
||||
parent = gimp_viewable_get_parent (src_viewable);
|
||||
|
||||
if (parent)
|
||||
src_container = gimp_viewable_get_children (parent);
|
||||
else if (gimp_container_have (container, GIMP_OBJECT (src_viewable)))
|
||||
src_container = container;
|
||||
|
||||
if (src_container)
|
||||
src_index = gimp_container_get_child_index (src_container,
|
||||
GIMP_OBJECT (src_viewable));
|
||||
|
||||
|
||||
if (g_type_is_a (G_TYPE_FROM_INSTANCE (src_viewable),
|
||||
gimp_container_get_children_type (container)))
|
||||
{
|
||||
if (dest_index == (src_index + 1))
|
||||
/* The drop won't change a thing. This is not a fatal drop
|
||||
* failure, unless there is only one source viewable.
|
||||
* See also the XXX below.
|
||||
*/
|
||||
if (src_viewable == dest_viewable && g_list_length (src_viewables) == 1)
|
||||
return FALSE;
|
||||
|
||||
if (src_index == -1 || dest_index == -1)
|
||||
return FALSE;
|
||||
|
||||
/* don't allow dropping a parent node onto one of its descendants
|
||||
*/
|
||||
if (gimp_viewable_is_ancestor (src_viewable, dest_viewable))
|
||||
return FALSE;
|
||||
}
|
||||
else if (drop_pos == GTK_TREE_VIEW_DROP_AFTER)
|
||||
|
||||
/* XXX only check these for list of 1 viewable for now.
|
||||
* Actually this drop failure would also happen for more than 1
|
||||
* viewable if all the sources are from the same src_container
|
||||
* with successive indexes.
|
||||
*/
|
||||
if (src_container == dest_container && g_list_length (src_viewables) == 1)
|
||||
{
|
||||
if (dest_index == (src_index - 1))
|
||||
return FALSE;
|
||||
if (drop_pos == GTK_TREE_VIEW_DROP_BEFORE)
|
||||
{
|
||||
if (dest_index == (src_index + 1))
|
||||
return FALSE;
|
||||
}
|
||||
else if (drop_pos == GTK_TREE_VIEW_DROP_AFTER)
|
||||
{
|
||||
if (dest_index == (src_index - 1))
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (return_drag_action)
|
||||
{
|
||||
if (! g_type_is_a (G_TYPE_FROM_INSTANCE (src_viewable),
|
||||
gimp_container_get_children_type (container)))
|
||||
*return_drag_action = GDK_ACTION_COPY;
|
||||
}
|
||||
}
|
||||
|
||||
if (return_drop_pos)
|
||||
*return_drop_pos = drop_pos;
|
||||
|
||||
if (return_drag_action)
|
||||
{
|
||||
if (src_viewable && g_type_is_a (G_TYPE_FROM_INSTANCE (src_viewable),
|
||||
gimp_container_get_children_type (container)))
|
||||
*return_drag_action = GDK_ACTION_MOVE;
|
||||
else
|
||||
*return_drag_action = GDK_ACTION_COPY;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
gimp_container_tree_view_real_drop_viewable (GimpContainerTreeView *tree_view,
|
||||
GimpViewable *src_viewable,
|
||||
GimpViewable *dest_viewable,
|
||||
GtkTreeViewDropPosition drop_pos)
|
||||
gimp_container_tree_view_real_drop_viewables (GimpContainerTreeView *tree_view,
|
||||
GList *src_viewables,
|
||||
GimpViewable *dest_viewable,
|
||||
GtkTreeViewDropPosition drop_pos)
|
||||
{
|
||||
GimpContainerView *view = GIMP_CONTAINER_VIEW (tree_view);
|
||||
GimpContainer *src_container;
|
||||
GimpContainer *dest_container;
|
||||
GList *iter;
|
||||
gint dest_index = 0;
|
||||
|
||||
if (gimp_viewable_get_parent (src_viewable))
|
||||
{
|
||||
src_container = gimp_viewable_get_children (
|
||||
gimp_viewable_get_parent (src_viewable));
|
||||
}
|
||||
else
|
||||
{
|
||||
src_container = gimp_container_view_get_container (view);
|
||||
}
|
||||
g_return_if_fail (g_list_length (src_viewables) > 0);
|
||||
|
||||
if ((drop_pos == GTK_TREE_VIEW_DROP_INTO_OR_AFTER ||
|
||||
drop_pos == GTK_TREE_VIEW_DROP_INTO_OR_BEFORE) &&
|
||||
gimp_viewable_get_children (dest_viewable))
|
||||
src_viewables = g_list_reverse (src_viewables);
|
||||
for (iter = src_viewables; iter; iter = iter->next)
|
||||
{
|
||||
dest_container = gimp_viewable_get_children (dest_viewable);
|
||||
dest_viewable = NULL;
|
||||
drop_pos = GTK_TREE_VIEW_DROP_BEFORE;
|
||||
}
|
||||
else if (gimp_viewable_get_parent (dest_viewable))
|
||||
{
|
||||
dest_container = gimp_viewable_get_children (
|
||||
gimp_viewable_get_parent (dest_viewable));
|
||||
}
|
||||
else
|
||||
{
|
||||
dest_container = gimp_container_view_get_container (view);
|
||||
}
|
||||
GimpViewable *src_viewable = iter->data;
|
||||
|
||||
if (dest_viewable)
|
||||
{
|
||||
dest_index = gimp_container_get_child_index (dest_container,
|
||||
GIMP_OBJECT (dest_viewable));
|
||||
}
|
||||
|
||||
if (src_container == dest_container)
|
||||
{
|
||||
gint src_index;
|
||||
|
||||
src_index = gimp_container_get_child_index (src_container,
|
||||
GIMP_OBJECT (src_viewable));
|
||||
|
||||
switch (drop_pos)
|
||||
if ((drop_pos == GTK_TREE_VIEW_DROP_INTO_OR_AFTER ||
|
||||
drop_pos == GTK_TREE_VIEW_DROP_INTO_OR_BEFORE) &&
|
||||
gimp_viewable_get_children (dest_viewable))
|
||||
{
|
||||
case GTK_TREE_VIEW_DROP_AFTER:
|
||||
case GTK_TREE_VIEW_DROP_INTO_OR_AFTER:
|
||||
if (src_index > dest_index)
|
||||
dest_index++;
|
||||
break;
|
||||
|
||||
case GTK_TREE_VIEW_DROP_BEFORE:
|
||||
case GTK_TREE_VIEW_DROP_INTO_OR_BEFORE:
|
||||
if (src_index < dest_index)
|
||||
dest_index--;
|
||||
break;
|
||||
dest_container = gimp_viewable_get_children (dest_viewable);
|
||||
dest_viewable = NULL;
|
||||
drop_pos = GTK_TREE_VIEW_DROP_BEFORE;
|
||||
}
|
||||
else if (gimp_viewable_get_parent (dest_viewable))
|
||||
{
|
||||
dest_container = gimp_viewable_get_children (gimp_viewable_get_parent (dest_viewable));
|
||||
}
|
||||
else
|
||||
{
|
||||
dest_container = gimp_container_view_get_container (view);
|
||||
}
|
||||
|
||||
gimp_container_reorder (src_container,
|
||||
GIMP_OBJECT (src_viewable), dest_index);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (drop_pos)
|
||||
if (dest_viewable)
|
||||
{
|
||||
case GTK_TREE_VIEW_DROP_AFTER:
|
||||
case GTK_TREE_VIEW_DROP_INTO_OR_AFTER:
|
||||
dest_index++;
|
||||
break;
|
||||
|
||||
case GTK_TREE_VIEW_DROP_BEFORE:
|
||||
case GTK_TREE_VIEW_DROP_INTO_OR_BEFORE:
|
||||
break;
|
||||
dest_index = gimp_container_get_child_index (dest_container,
|
||||
GIMP_OBJECT (dest_viewable));
|
||||
}
|
||||
|
||||
g_object_ref (src_viewable);
|
||||
if (gimp_viewable_get_parent (src_viewable))
|
||||
{
|
||||
src_container = gimp_viewable_get_children (
|
||||
gimp_viewable_get_parent (src_viewable));
|
||||
}
|
||||
else
|
||||
{
|
||||
src_container = gimp_container_view_get_container (view);
|
||||
}
|
||||
|
||||
gimp_container_remove (src_container, GIMP_OBJECT (src_viewable));
|
||||
gimp_container_insert (dest_container, GIMP_OBJECT (src_viewable),
|
||||
dest_index);
|
||||
if (src_container == dest_container)
|
||||
{
|
||||
gint src_index;
|
||||
|
||||
g_object_unref (src_viewable);
|
||||
src_index = gimp_container_get_child_index (src_container,
|
||||
GIMP_OBJECT (src_viewable));
|
||||
|
||||
switch (drop_pos)
|
||||
{
|
||||
case GTK_TREE_VIEW_DROP_AFTER:
|
||||
case GTK_TREE_VIEW_DROP_INTO_OR_AFTER:
|
||||
if (src_index > dest_index)
|
||||
dest_index++;
|
||||
break;
|
||||
|
||||
case GTK_TREE_VIEW_DROP_BEFORE:
|
||||
case GTK_TREE_VIEW_DROP_INTO_OR_BEFORE:
|
||||
if (src_index < dest_index)
|
||||
dest_index--;
|
||||
break;
|
||||
}
|
||||
|
||||
gimp_container_reorder (src_container,
|
||||
GIMP_OBJECT (src_viewable), dest_index);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (drop_pos)
|
||||
{
|
||||
case GTK_TREE_VIEW_DROP_AFTER:
|
||||
case GTK_TREE_VIEW_DROP_INTO_OR_AFTER:
|
||||
dest_index++;
|
||||
break;
|
||||
|
||||
case GTK_TREE_VIEW_DROP_BEFORE:
|
||||
case GTK_TREE_VIEW_DROP_INTO_OR_BEFORE:
|
||||
break;
|
||||
}
|
||||
|
||||
g_object_ref (src_viewable);
|
||||
|
||||
gimp_container_remove (src_container, GIMP_OBJECT (src_viewable));
|
||||
gimp_container_insert (dest_container, GIMP_OBJECT (src_viewable),
|
||||
dest_index);
|
||||
|
||||
g_object_unref (src_viewable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,17 +55,17 @@ void gimp_container_tree_view_drag_data_received
|
|||
gboolean
|
||||
gimp_container_tree_view_real_drop_possible (GimpContainerTreeView *tree_view,
|
||||
GimpDndType src_type,
|
||||
GimpViewable *src_viewable,
|
||||
GList *src_viewables,
|
||||
GimpViewable *dest_viewable,
|
||||
GtkTreePath *drop_path,
|
||||
GtkTreeViewDropPosition drop_pos,
|
||||
GtkTreeViewDropPosition *return_drop_pos,
|
||||
GdkDragAction *return_drag_action);
|
||||
void
|
||||
gimp_container_tree_view_real_drop_viewable (GimpContainerTreeView *tree_view,
|
||||
GimpViewable *src_viewable,
|
||||
GimpViewable *dest_viewable,
|
||||
GtkTreeViewDropPosition drop_pos);
|
||||
gimp_container_tree_view_real_drop_viewables (GimpContainerTreeView *tree_view,
|
||||
GList *src_viewables,
|
||||
GimpViewable *dest_viewable,
|
||||
GtkTreeViewDropPosition drop_pos);
|
||||
|
||||
|
||||
#endif /* __GIMP_CONTAINER_TREE_VIEW_DND_H__ */
|
||||
|
|
|
|||
|
|
@ -123,6 +123,9 @@ static gboolean gimp_container_tree_view_tooltip (GtkWidget
|
|||
static GimpViewable *gimp_container_tree_view_drag_viewable (GtkWidget *widget,
|
||||
GimpContext **context,
|
||||
gpointer data);
|
||||
static GList * gimp_container_tree_view_drag_viewable_list (GtkWidget *widget,
|
||||
GimpContext **context,
|
||||
gpointer data);
|
||||
static GdkPixbuf *gimp_container_tree_view_drag_pixbuf (GtkWidget *widget,
|
||||
gpointer data);
|
||||
|
||||
|
|
@ -171,7 +174,7 @@ gimp_container_tree_view_class_init (GimpContainerTreeViewClass *klass)
|
|||
|
||||
klass->edit_name = gimp_container_tree_view_real_edit_name;
|
||||
klass->drop_possible = gimp_container_tree_view_real_drop_possible;
|
||||
klass->drop_viewable = gimp_container_tree_view_real_drop_viewable;
|
||||
klass->drop_viewables = gimp_container_tree_view_real_drop_viewables;
|
||||
klass->drop_color = NULL;
|
||||
klass->drop_uri_list = NULL;
|
||||
klass->drop_svg = NULL;
|
||||
|
|
@ -653,8 +656,8 @@ gimp_container_tree_view_set_container (GimpContainerView *view,
|
|||
tree_view);
|
||||
if (! container)
|
||||
{
|
||||
if (gimp_dnd_viewable_source_remove (GTK_WIDGET (tree_view->view),
|
||||
gimp_container_get_children_type (old_container)))
|
||||
if (gimp_dnd_viewable_list_source_remove (GTK_WIDGET (tree_view->view),
|
||||
gimp_container_get_children_type (old_container)))
|
||||
{
|
||||
if (GIMP_VIEWABLE_CLASS (g_type_class_peek (gimp_container_get_children_type (old_container)))->get_size)
|
||||
gimp_dnd_pixbuf_source_remove (GTK_WIDGET (tree_view->view));
|
||||
|
|
@ -674,6 +677,10 @@ gimp_container_tree_view_set_container (GimpContainerView *view,
|
|||
gimp_container_get_children_type (container),
|
||||
GDK_ACTION_COPY))
|
||||
{
|
||||
gimp_dnd_viewable_list_source_add (GTK_WIDGET (tree_view->view),
|
||||
gimp_container_get_children_type (container),
|
||||
gimp_container_tree_view_drag_viewable_list,
|
||||
tree_view);
|
||||
gimp_dnd_viewable_source_add (GTK_WIDGET (tree_view->view),
|
||||
gimp_container_get_children_type (container),
|
||||
gimp_container_tree_view_drag_viewable,
|
||||
|
|
@ -1544,6 +1551,21 @@ gimp_container_tree_view_drag_viewable (GtkWidget *widget,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static GList *
|
||||
gimp_container_tree_view_drag_viewable_list (GtkWidget *widget,
|
||||
GimpContext **context,
|
||||
gpointer data)
|
||||
{
|
||||
GList *items = NULL;
|
||||
|
||||
if (context)
|
||||
*context = gimp_container_view_get_context (GIMP_CONTAINER_VIEW (data));
|
||||
|
||||
gimp_container_tree_view_get_selected (GIMP_CONTAINER_VIEW (data), &items, NULL);
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
static GdkPixbuf *
|
||||
gimp_container_tree_view_drag_pixbuf (GtkWidget *widget,
|
||||
gpointer data)
|
||||
|
|
|
|||
|
|
@ -66,14 +66,14 @@ struct _GimpContainerTreeViewClass
|
|||
|
||||
gboolean (* drop_possible) (GimpContainerTreeView *tree_view,
|
||||
GimpDndType src_type,
|
||||
GimpViewable *src_viewable,
|
||||
GList *src_viewables,
|
||||
GimpViewable *dest_viewable,
|
||||
GtkTreePath *drop_path,
|
||||
GtkTreeViewDropPosition drop_pos,
|
||||
GtkTreeViewDropPosition *return_drop_pos,
|
||||
GdkDragAction *return_drag_action);
|
||||
void (* drop_viewable) (GimpContainerTreeView *tree_view,
|
||||
GimpViewable *src_viewable,
|
||||
void (* drop_viewables) (GimpContainerTreeView *tree_view,
|
||||
GList *src_viewables,
|
||||
GimpViewable *dest_viewable,
|
||||
GtkTreeViewDropPosition drop_pos);
|
||||
void (* drop_color) (GimpContainerTreeView *tree_view,
|
||||
|
|
|
|||
|
|
@ -98,6 +98,10 @@ struct _GimpDndDataDef
|
|||
};
|
||||
|
||||
|
||||
static GtkWidget * gimp_dnd_get_viewable_list_icon (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GCallback get_viewable_list_func,
|
||||
gpointer get_viewable_list_data);
|
||||
static GtkWidget * gimp_dnd_get_viewable_icon (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GCallback get_viewable_func,
|
||||
|
|
@ -200,6 +204,18 @@ static gboolean gimp_dnd_set_item_data (GtkWidget *widget,
|
|||
gpointer set_item_data,
|
||||
GtkSelectionData *selection);
|
||||
|
||||
static void gimp_dnd_get_item_list_data (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GCallback get_item_func,
|
||||
gpointer get_item_data,
|
||||
GtkSelectionData *selection);
|
||||
static gboolean gimp_dnd_set_item_list_data (GtkWidget *widget,
|
||||
gint x,
|
||||
gint y,
|
||||
GCallback set_item_func,
|
||||
gpointer set_item_data,
|
||||
GtkSelectionData *selection);
|
||||
|
||||
static void gimp_dnd_get_object_data (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GCallback get_object_func,
|
||||
|
|
@ -610,7 +626,22 @@ static const GimpDndDataDef dnd_data_defs[] =
|
|||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
GIMP_TARGET_LAYER_LIST,
|
||||
|
||||
"gimp-dnd-get-layer-list-func",
|
||||
"gimp-dnd-get-layer-list-data",
|
||||
|
||||
"gimp-dnd-set-layer-list-func",
|
||||
"gimp-dnd-set-layer-list-data",
|
||||
|
||||
gimp_dnd_get_viewable_list_icon,
|
||||
gimp_dnd_get_item_list_data,
|
||||
gimp_dnd_set_item_list_data,
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -1867,63 +1898,64 @@ gimp_dnd_get_viewable_icon (GtkWidget *widget,
|
|||
}
|
||||
|
||||
static GimpDndType
|
||||
gimp_dnd_data_type_get_by_g_type (GType type)
|
||||
gimp_dnd_data_type_get_by_g_type (GType type,
|
||||
gboolean list)
|
||||
{
|
||||
GimpDndType dnd_type = GIMP_DND_TYPE_NONE;
|
||||
|
||||
if (g_type_is_a (type, GIMP_TYPE_IMAGE))
|
||||
if (g_type_is_a (type, GIMP_TYPE_IMAGE) && ! list)
|
||||
{
|
||||
dnd_type = GIMP_DND_TYPE_IMAGE;
|
||||
}
|
||||
else if (g_type_is_a (type, GIMP_TYPE_LAYER))
|
||||
{
|
||||
dnd_type = GIMP_DND_TYPE_LAYER;
|
||||
dnd_type = list ? GIMP_DND_TYPE_LAYER_LIST : GIMP_DND_TYPE_LAYER;
|
||||
}
|
||||
else if (g_type_is_a (type, GIMP_TYPE_LAYER_MASK))
|
||||
else if (g_type_is_a (type, GIMP_TYPE_LAYER_MASK) && ! list)
|
||||
{
|
||||
dnd_type = GIMP_DND_TYPE_LAYER_MASK;
|
||||
}
|
||||
else if (g_type_is_a (type, GIMP_TYPE_CHANNEL))
|
||||
else if (g_type_is_a (type, GIMP_TYPE_CHANNEL) && ! list)
|
||||
{
|
||||
dnd_type = GIMP_DND_TYPE_CHANNEL;
|
||||
}
|
||||
else if (g_type_is_a (type, GIMP_TYPE_VECTORS))
|
||||
else if (g_type_is_a (type, GIMP_TYPE_VECTORS) && ! list)
|
||||
{
|
||||
dnd_type = GIMP_DND_TYPE_VECTORS;
|
||||
}
|
||||
else if (g_type_is_a (type, GIMP_TYPE_BRUSH))
|
||||
else if (g_type_is_a (type, GIMP_TYPE_BRUSH) && ! list)
|
||||
{
|
||||
dnd_type = GIMP_DND_TYPE_BRUSH;
|
||||
}
|
||||
else if (g_type_is_a (type, GIMP_TYPE_PATTERN))
|
||||
else if (g_type_is_a (type, GIMP_TYPE_PATTERN) && ! list)
|
||||
{
|
||||
dnd_type = GIMP_DND_TYPE_PATTERN;
|
||||
}
|
||||
else if (g_type_is_a (type, GIMP_TYPE_GRADIENT))
|
||||
else if (g_type_is_a (type, GIMP_TYPE_GRADIENT) && ! list)
|
||||
{
|
||||
dnd_type = GIMP_DND_TYPE_GRADIENT;
|
||||
}
|
||||
else if (g_type_is_a (type, GIMP_TYPE_PALETTE))
|
||||
else if (g_type_is_a (type, GIMP_TYPE_PALETTE) && ! list)
|
||||
{
|
||||
dnd_type = GIMP_DND_TYPE_PALETTE;
|
||||
}
|
||||
else if (g_type_is_a (type, GIMP_TYPE_FONT))
|
||||
else if (g_type_is_a (type, GIMP_TYPE_FONT) && ! list)
|
||||
{
|
||||
dnd_type = GIMP_DND_TYPE_FONT;
|
||||
}
|
||||
else if (g_type_is_a (type, GIMP_TYPE_BUFFER))
|
||||
else if (g_type_is_a (type, GIMP_TYPE_BUFFER) && ! list)
|
||||
{
|
||||
dnd_type = GIMP_DND_TYPE_BUFFER;
|
||||
}
|
||||
else if (g_type_is_a (type, GIMP_TYPE_IMAGEFILE))
|
||||
else if (g_type_is_a (type, GIMP_TYPE_IMAGEFILE) && ! list)
|
||||
{
|
||||
dnd_type = GIMP_DND_TYPE_IMAGEFILE;
|
||||
}
|
||||
else if (g_type_is_a (type, GIMP_TYPE_TEMPLATE))
|
||||
else if (g_type_is_a (type, GIMP_TYPE_TEMPLATE) && ! list)
|
||||
{
|
||||
dnd_type = GIMP_DND_TYPE_TEMPLATE;
|
||||
}
|
||||
else if (g_type_is_a (type, GIMP_TYPE_TOOL_ITEM))
|
||||
else if (g_type_is_a (type, GIMP_TYPE_TOOL_ITEM) && ! list)
|
||||
{
|
||||
dnd_type = GIMP_DND_TYPE_TOOL_ITEM;
|
||||
}
|
||||
|
|
@ -1941,7 +1973,7 @@ gimp_dnd_drag_source_set_by_type (GtkWidget *widget,
|
|||
|
||||
g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
|
||||
|
||||
dnd_type = gimp_dnd_data_type_get_by_g_type (type);
|
||||
dnd_type = gimp_dnd_data_type_get_by_g_type (type, FALSE);
|
||||
|
||||
if (dnd_type == GIMP_DND_TYPE_NONE)
|
||||
return FALSE;
|
||||
|
|
@ -1957,24 +1989,56 @@ gboolean
|
|||
gimp_dnd_drag_dest_set_by_type (GtkWidget *widget,
|
||||
GtkDestDefaults flags,
|
||||
GType type,
|
||||
gboolean list_accepted,
|
||||
GdkDragAction actions)
|
||||
{
|
||||
GimpDndType dnd_type;
|
||||
GtkTargetEntry target_entries[2];
|
||||
GimpDndType dnd_type;
|
||||
gint target_entries_n = 0;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
|
||||
|
||||
dnd_type = gimp_dnd_data_type_get_by_g_type (type);
|
||||
if (list_accepted)
|
||||
{
|
||||
dnd_type = gimp_dnd_data_type_get_by_g_type (type, TRUE);
|
||||
|
||||
if (dnd_type == GIMP_DND_TYPE_NONE)
|
||||
if (dnd_type != GIMP_DND_TYPE_NONE)
|
||||
{
|
||||
target_entries[target_entries_n] = dnd_data_defs[dnd_type].target_entry;
|
||||
target_entries_n++;
|
||||
}
|
||||
}
|
||||
|
||||
dnd_type = gimp_dnd_data_type_get_by_g_type (type, FALSE);
|
||||
if (dnd_type != GIMP_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,
|
||||
&dnd_data_defs[dnd_type].target_entry, 1,
|
||||
(const GtkTargetEntry *) &target_entries,
|
||||
target_entries_n,
|
||||
actions);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* gimp_dnd_viewable_source_add:
|
||||
* @widget:
|
||||
* @type:
|
||||
* @get_viewable_func:
|
||||
* @data:
|
||||
*
|
||||
* Sets up @widget as a drag source for a #GimpViewable object, as
|
||||
* returned by @get_viewable_func on @widget and @data.
|
||||
*
|
||||
* @type must be a list type for drag operations.
|
||||
*/
|
||||
gboolean
|
||||
gimp_dnd_viewable_source_add (GtkWidget *widget,
|
||||
GType type,
|
||||
|
|
@ -1986,7 +2050,7 @@ gimp_dnd_viewable_source_add (GtkWidget *widget,
|
|||
g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
|
||||
g_return_val_if_fail (get_viewable_func != NULL, FALSE);
|
||||
|
||||
dnd_type = gimp_dnd_data_type_get_by_g_type (type);
|
||||
dnd_type = gimp_dnd_data_type_get_by_g_type (type, FALSE);
|
||||
|
||||
if (dnd_type == GIMP_DND_TYPE_NONE)
|
||||
return FALSE;
|
||||
|
|
@ -2006,7 +2070,7 @@ gimp_dnd_viewable_source_remove (GtkWidget *widget,
|
|||
|
||||
g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
|
||||
|
||||
dnd_type = gimp_dnd_data_type_get_by_g_type (type);
|
||||
dnd_type = gimp_dnd_data_type_get_by_g_type (type, FALSE);
|
||||
|
||||
if (dnd_type == GIMP_DND_TYPE_NONE)
|
||||
return FALSE;
|
||||
|
|
@ -2024,7 +2088,7 @@ gimp_dnd_viewable_dest_add (GtkWidget *widget,
|
|||
|
||||
g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
|
||||
|
||||
dnd_type = gimp_dnd_data_type_get_by_g_type (type);
|
||||
dnd_type = gimp_dnd_data_type_get_by_g_type (type, FALSE);
|
||||
|
||||
if (dnd_type == GIMP_DND_TYPE_NONE)
|
||||
return FALSE;
|
||||
|
|
@ -2044,7 +2108,7 @@ gimp_dnd_viewable_dest_remove (GtkWidget *widget,
|
|||
|
||||
g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
|
||||
|
||||
dnd_type = gimp_dnd_data_type_get_by_g_type (type);
|
||||
dnd_type = gimp_dnd_data_type_get_by_g_type (type, FALSE);
|
||||
|
||||
if (dnd_type == GIMP_DND_TYPE_NONE)
|
||||
return FALSE;
|
||||
|
|
@ -2055,7 +2119,7 @@ gimp_dnd_viewable_dest_remove (GtkWidget *widget,
|
|||
}
|
||||
|
||||
GimpViewable *
|
||||
gimp_dnd_get_drag_data (GtkWidget *widget)
|
||||
gimp_dnd_get_drag_viewable (GtkWidget *widget)
|
||||
{
|
||||
const GimpDndDataDef *dnd_data;
|
||||
GimpDndType data_type;
|
||||
|
|
@ -2088,6 +2152,201 @@ gimp_dnd_get_drag_data (GtkWidget *widget)
|
|||
}
|
||||
|
||||
|
||||
/*************************************************/
|
||||
/* GimpViewable (by GType) GList dnd functions */
|
||||
/*************************************************/
|
||||
|
||||
static GtkWidget *
|
||||
gimp_dnd_get_viewable_list_icon (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GCallback get_list_func,
|
||||
gpointer get_list_data)
|
||||
{
|
||||
GList *viewables;
|
||||
GimpViewable *viewable;
|
||||
GimpContext *gimp_context;
|
||||
GtkWidget *view;
|
||||
gchar *desc;
|
||||
|
||||
viewables = (* (GimpDndDragViewableListFunc) get_list_func) (widget,
|
||||
&gimp_context,
|
||||
get_list_data);
|
||||
|
||||
if (! viewables)
|
||||
return NULL;
|
||||
|
||||
/* Should we just show one of the viewable? Add a number to show we
|
||||
* are dragging several viewables? Something else? XXX
|
||||
*/
|
||||
viewable = viewables->data;
|
||||
|
||||
GIMP_LOG (DND, "viewable %p", viewable);
|
||||
|
||||
g_object_set_data_full (G_OBJECT (context),
|
||||
"gimp-dnd-viewable", g_object_ref (viewable),
|
||||
(GDestroyNotify) g_object_unref);
|
||||
|
||||
view = gimp_view_new (gimp_context, viewable,
|
||||
DRAG_PREVIEW_SIZE, 0, TRUE);
|
||||
|
||||
desc = gimp_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;
|
||||
}
|
||||
|
||||
/**
|
||||
* gimp_dnd_viewable_list_source_add:
|
||||
* @widget:
|
||||
* @type:
|
||||
* @get_viewable_func:
|
||||
* @data:
|
||||
*
|
||||
* Sets up @widget as a drag source for a #GList of #GimpViewable
|
||||
* object, as returned by @get_viewable_func on @widget and @data.
|
||||
*
|
||||
* @type must be a list type for drag operations (only GimpLayer so
|
||||
* far).
|
||||
*/
|
||||
gboolean
|
||||
gimp_dnd_viewable_list_source_add (GtkWidget *widget,
|
||||
GType type,
|
||||
GimpDndDragViewableListFunc get_viewable_list_func,
|
||||
gpointer data)
|
||||
{
|
||||
GimpDndType 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 = gimp_dnd_data_type_get_by_g_type (type, TRUE);
|
||||
|
||||
if (dnd_type == GIMP_DND_TYPE_NONE)
|
||||
return FALSE;
|
||||
|
||||
gimp_dnd_data_source_add (dnd_type, widget,
|
||||
G_CALLBACK (get_viewable_list_func),
|
||||
data);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gimp_dnd_viewable_list_source_remove (GtkWidget *widget,
|
||||
GType type)
|
||||
{
|
||||
GimpDndType dnd_type;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
|
||||
|
||||
dnd_type = gimp_dnd_data_type_get_by_g_type (type, TRUE);
|
||||
|
||||
if (dnd_type == GIMP_DND_TYPE_NONE)
|
||||
return FALSE;
|
||||
|
||||
return gimp_dnd_data_source_remove (dnd_type, widget);
|
||||
}
|
||||
|
||||
gboolean
|
||||
gimp_dnd_viewable_list_dest_add (GtkWidget *widget,
|
||||
GType type,
|
||||
GimpDndDropViewableListFunc set_viewable_func,
|
||||
gpointer data)
|
||||
{
|
||||
GimpDndType dnd_type;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
|
||||
|
||||
dnd_type = gimp_dnd_data_type_get_by_g_type (type, TRUE);
|
||||
|
||||
if (dnd_type == GIMP_DND_TYPE_NONE)
|
||||
return FALSE;
|
||||
|
||||
gimp_dnd_data_dest_add (dnd_type, widget,
|
||||
G_CALLBACK (set_viewable_func),
|
||||
data);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gimp_dnd_viewable_list_dest_remove (GtkWidget *widget,
|
||||
GType type)
|
||||
{
|
||||
GimpDndType dnd_type;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
|
||||
|
||||
dnd_type = gimp_dnd_data_type_get_by_g_type (type, TRUE);
|
||||
|
||||
if (dnd_type == GIMP_DND_TYPE_NONE)
|
||||
return FALSE;
|
||||
|
||||
gimp_dnd_data_dest_remove (dnd_type, widget);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
GList *
|
||||
gimp_dnd_get_drag_list (GtkWidget *widget)
|
||||
{
|
||||
const GimpDndDataDef *dnd_data;
|
||||
GimpDndType data_type;
|
||||
GimpDndDragViewableListFunc get_data_func = NULL;
|
||||
gpointer get_data_data = NULL;
|
||||
GimpContext *context;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
|
||||
|
||||
data_type = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget),
|
||||
"gimp-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);
|
||||
}
|
||||
|
||||
|
||||
/*****************************/
|
||||
/* GimpImage dnd functions */
|
||||
/*****************************/
|
||||
|
|
@ -2188,6 +2447,48 @@ gimp_dnd_set_item_data (GtkWidget *widget,
|
|||
}
|
||||
|
||||
|
||||
/**********************************/
|
||||
/* GimpItem GList dnd functions */
|
||||
/**********************************/
|
||||
|
||||
static void
|
||||
gimp_dnd_get_item_list_data (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
GCallback get_item_func,
|
||||
gpointer get_item_data,
|
||||
GtkSelectionData *selection)
|
||||
{
|
||||
GList *items;
|
||||
GimpContext *gimp_context;
|
||||
|
||||
items = (* (GimpDndDragViewableListFunc) get_item_func) (widget, &gimp_context,
|
||||
get_item_data);
|
||||
|
||||
if (items)
|
||||
gimp_selection_data_set_item_list (selection, items);
|
||||
g_list_free (items);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gimp_dnd_set_item_list_data (GtkWidget *widget,
|
||||
gint x,
|
||||
gint y,
|
||||
GCallback set_item_func,
|
||||
gpointer set_item_data,
|
||||
GtkSelectionData *selection)
|
||||
{
|
||||
GList *items = gimp_selection_data_get_item_list (selection, the_dnd_gimp);
|
||||
|
||||
if (! items)
|
||||
return FALSE;
|
||||
|
||||
(* (GimpDndDropViewableListFunc) set_item_func) (widget, x, y, items,
|
||||
set_item_data);
|
||||
g_list_free (items);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/******************************/
|
||||
/* GimpObject dnd functions */
|
||||
/******************************/
|
||||
|
|
|
|||
|
|
@ -94,6 +94,9 @@
|
|||
#define GIMP_TARGET_NOTEBOOK_TAB \
|
||||
{ "GTK_NOTEBOOK_TAB", GTK_TARGET_SAME_APP, GIMP_DND_TYPE_NOTEBOOK_TAB }
|
||||
|
||||
#define GIMP_TARGET_LAYER_LIST \
|
||||
{ "application/x-gimp-layer-list", GTK_TARGET_SAME_APP, GIMP_DND_TYPE_LAYER_LIST }
|
||||
|
||||
|
||||
/* dnd initialization */
|
||||
|
||||
|
|
@ -237,6 +240,7 @@ gboolean gimp_dnd_viewable_source_remove (GtkWidget *widget,
|
|||
gboolean gimp_dnd_drag_dest_set_by_type (GtkWidget *widget,
|
||||
GtkDestDefaults flags,
|
||||
GType type,
|
||||
gboolean list_accepted,
|
||||
GdkDragAction actions);
|
||||
|
||||
gboolean gimp_dnd_viewable_dest_add (GtkWidget *widget,
|
||||
|
|
@ -246,8 +250,32 @@ gboolean gimp_dnd_viewable_dest_add (GtkWidget *widget,
|
|||
gboolean gimp_dnd_viewable_dest_remove (GtkWidget *widget,
|
||||
GType type);
|
||||
|
||||
GimpViewable * gimp_dnd_get_drag_data (GtkWidget *widget);
|
||||
GimpViewable * gimp_dnd_get_drag_viewable (GtkWidget *widget);
|
||||
|
||||
/* GimpViewable (by GType) GList dnd functions */
|
||||
|
||||
typedef GList * (* GimpDndDragViewableListFunc) (GtkWidget *widget,
|
||||
GimpContext **context,
|
||||
gpointer data);
|
||||
typedef void (* GimpDndDropViewableListFunc) (GtkWidget *widget,
|
||||
gint x,
|
||||
gint y,
|
||||
GList *viewables,
|
||||
gpointer data);
|
||||
|
||||
gboolean gimp_dnd_viewable_list_source_add (GtkWidget *widget,
|
||||
GType type,
|
||||
GimpDndDragViewableListFunc get_viewable_list_func,
|
||||
gpointer data);
|
||||
gboolean gimp_dnd_viewable_list_source_remove (GtkWidget *widget,
|
||||
GType type);
|
||||
gboolean gimp_dnd_viewable_list_dest_add (GtkWidget *widget,
|
||||
GType type,
|
||||
GimpDndDropViewableListFunc set_viewable_func,
|
||||
gpointer data);
|
||||
gboolean gimp_dnd_viewable_list_dest_remove (GtkWidget *widget,
|
||||
GType type);
|
||||
GList * gimp_dnd_get_drag_list (GtkWidget *widget);
|
||||
|
||||
/* Direct Save Protocol (XDS) */
|
||||
|
||||
|
|
|
|||
|
|
@ -176,7 +176,7 @@ static GList *
|
|||
gimp_document_view_drag_uri_list (GtkWidget *widget,
|
||||
gpointer data)
|
||||
{
|
||||
GimpViewable *viewable = gimp_dnd_get_drag_data (widget);
|
||||
GimpViewable *viewable = gimp_dnd_get_drag_viewable (widget);
|
||||
|
||||
if (viewable)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -53,16 +53,16 @@ static gboolean gimp_drawable_tree_view_select_item (GimpContainerView *view,
|
|||
|
||||
static gboolean gimp_drawable_tree_view_drop_possible(GimpContainerTreeView *view,
|
||||
GimpDndType src_type,
|
||||
GimpViewable *src_viewable,
|
||||
GList *src_viewables,
|
||||
GimpViewable *dest_viewable,
|
||||
GtkTreePath *drop_path,
|
||||
GtkTreeViewDropPosition drop_pos,
|
||||
GtkTreeViewDropPosition *return_drop_pos,
|
||||
GdkDragAction *return_drag_action);
|
||||
static void gimp_drawable_tree_view_drop_viewable (GimpContainerTreeView *view,
|
||||
GimpViewable *src_viewable,
|
||||
GimpViewable *dest_viewable,
|
||||
GtkTreeViewDropPosition drop_pos);
|
||||
static void gimp_drawable_tree_view_drop_viewables (GimpContainerTreeView *view,
|
||||
GList *src_viewables,
|
||||
GimpViewable *dest_viewable,
|
||||
GtkTreeViewDropPosition drop_pos);
|
||||
static void gimp_drawable_tree_view_drop_color (GimpContainerTreeView *view,
|
||||
const GimpRGB *color,
|
||||
GimpViewable *dest_viewable,
|
||||
|
|
@ -112,9 +112,9 @@ gimp_drawable_tree_view_class_init (GimpDrawableTreeViewClass *klass)
|
|||
|
||||
object_class->constructed = gimp_drawable_tree_view_constructed;
|
||||
|
||||
tree_view_class->drop_possible = gimp_drawable_tree_view_drop_possible;
|
||||
tree_view_class->drop_viewable = gimp_drawable_tree_view_drop_viewable;
|
||||
tree_view_class->drop_color = gimp_drawable_tree_view_drop_color;
|
||||
tree_view_class->drop_possible = gimp_drawable_tree_view_drop_possible;
|
||||
tree_view_class->drop_viewables = gimp_drawable_tree_view_drop_viewables;
|
||||
tree_view_class->drop_color = gimp_drawable_tree_view_drop_color;
|
||||
|
||||
item_view_class->set_image = gimp_drawable_tree_view_set_image;
|
||||
|
||||
|
|
@ -203,7 +203,7 @@ gimp_drawable_tree_view_select_item (GimpContainerView *view,
|
|||
static gboolean
|
||||
gimp_drawable_tree_view_drop_possible (GimpContainerTreeView *tree_view,
|
||||
GimpDndType src_type,
|
||||
GimpViewable *src_viewable,
|
||||
GList *src_viewables,
|
||||
GimpViewable *dest_viewable,
|
||||
GtkTreePath *drop_path,
|
||||
GtkTreeViewDropPosition drop_pos,
|
||||
|
|
@ -212,7 +212,7 @@ gimp_drawable_tree_view_drop_possible (GimpContainerTreeView *tree_view,
|
|||
{
|
||||
if (GIMP_CONTAINER_TREE_VIEW_CLASS (parent_class)->drop_possible (tree_view,
|
||||
src_type,
|
||||
src_viewable,
|
||||
src_viewables,
|
||||
dest_viewable,
|
||||
drop_path,
|
||||
drop_pos,
|
||||
|
|
@ -240,34 +240,41 @@ gimp_drawable_tree_view_drop_possible (GimpContainerTreeView *tree_view,
|
|||
}
|
||||
|
||||
static void
|
||||
gimp_drawable_tree_view_drop_viewable (GimpContainerTreeView *view,
|
||||
GimpViewable *src_viewable,
|
||||
GimpViewable *dest_viewable,
|
||||
GtkTreeViewDropPosition drop_pos)
|
||||
gimp_drawable_tree_view_drop_viewables (GimpContainerTreeView *view,
|
||||
GList *src_viewables,
|
||||
GimpViewable *dest_viewable,
|
||||
GtkTreeViewDropPosition drop_pos)
|
||||
{
|
||||
if (dest_viewable && GIMP_IS_PATTERN (src_viewable))
|
||||
GList *iter;
|
||||
|
||||
for (iter = src_viewables; iter; iter = iter->next)
|
||||
{
|
||||
GimpImage *image = gimp_item_get_image (GIMP_ITEM (dest_viewable));
|
||||
GimpFillOptions *options = gimp_fill_options_new (image->gimp, NULL, FALSE);
|
||||
GimpViewable *src_viewable = iter->data;
|
||||
|
||||
gimp_fill_options_set_style (options, GIMP_FILL_STYLE_PATTERN);
|
||||
gimp_context_set_pattern (GIMP_CONTEXT (options),
|
||||
GIMP_PATTERN (src_viewable));
|
||||
if (dest_viewable && GIMP_IS_PATTERN (src_viewable))
|
||||
{
|
||||
GimpImage *image = gimp_item_get_image (GIMP_ITEM (dest_viewable));
|
||||
GimpFillOptions *options = gimp_fill_options_new (image->gimp, NULL, FALSE);
|
||||
|
||||
gimp_drawable_edit_fill (GIMP_DRAWABLE (dest_viewable),
|
||||
options,
|
||||
C_("undo-type", "Drop pattern to layer"));
|
||||
gimp_fill_options_set_style (options, GIMP_FILL_STYLE_PATTERN);
|
||||
gimp_context_set_pattern (GIMP_CONTEXT (options),
|
||||
GIMP_PATTERN (src_viewable));
|
||||
|
||||
g_object_unref (options);
|
||||
gimp_drawable_edit_fill (GIMP_DRAWABLE (dest_viewable),
|
||||
options,
|
||||
C_("undo-type", "Drop pattern to layer"));
|
||||
|
||||
gimp_image_flush (image);
|
||||
return;
|
||||
g_object_unref (options);
|
||||
|
||||
gimp_image_flush (image);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
GIMP_CONTAINER_TREE_VIEW_CLASS (parent_class)->drop_viewable (view,
|
||||
src_viewable,
|
||||
dest_viewable,
|
||||
drop_pos);
|
||||
GIMP_CONTAINER_TREE_VIEW_CLASS (parent_class)->drop_viewables (view,
|
||||
src_viewables,
|
||||
dest_viewable,
|
||||
drop_pos);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
|||
|
|
@ -120,7 +120,7 @@ gimp_image_view_new (GimpViewType view_type,
|
|||
dnd_widget = gimp_container_view_get_dnd_widget (editor->view);
|
||||
|
||||
gimp_dnd_xds_source_add (dnd_widget,
|
||||
(GimpDndDragViewableFunc) gimp_dnd_get_drag_data,
|
||||
(GimpDndDragViewableFunc) gimp_dnd_get_drag_viewable,
|
||||
NULL);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -141,15 +141,15 @@ static void gimp_item_tree_view_context_item (GimpContainerView *view,
|
|||
|
||||
static gboolean gimp_item_tree_view_drop_possible (GimpContainerTreeView *view,
|
||||
GimpDndType src_type,
|
||||
GimpViewable *src_viewable,
|
||||
GList *src_viewables,
|
||||
GimpViewable *dest_viewable,
|
||||
GtkTreePath *drop_path,
|
||||
GtkTreeViewDropPosition drop_pos,
|
||||
GtkTreeViewDropPosition *return_drop_pos,
|
||||
GdkDragAction *return_drag_action);
|
||||
static void gimp_item_tree_view_drop_viewable (GimpContainerTreeView *view,
|
||||
GimpViewable *src_viewable,
|
||||
GimpViewable *dest_viewable,
|
||||
static void gimp_item_tree_view_drop_viewables (GimpContainerTreeView *view,
|
||||
GList *src_viewables,
|
||||
GimpViewable *dest_viewable,
|
||||
GtkTreeViewDropPosition drop_pos);
|
||||
|
||||
static void gimp_item_tree_view_new_dropped (GtkWidget *widget,
|
||||
|
|
@ -157,6 +157,11 @@ static void gimp_item_tree_view_new_dropped (GtkWidget *widget,
|
|||
gint y,
|
||||
GimpViewable *viewable,
|
||||
gpointer data);
|
||||
static void gimp_item_tree_view_new_list_dropped (GtkWidget *widget,
|
||||
gint x,
|
||||
gint y,
|
||||
GList *viewables,
|
||||
gpointer data);
|
||||
|
||||
static void gimp_item_tree_view_item_changed (GimpImage *image,
|
||||
GimpItemTreeView *view);
|
||||
|
|
@ -252,8 +257,8 @@ gimp_item_tree_view_class_init (GimpItemTreeViewClass *klass)
|
|||
|
||||
widget_class->style_updated = gimp_item_tree_view_style_updated;
|
||||
|
||||
tree_view_class->drop_possible = gimp_item_tree_view_drop_possible;
|
||||
tree_view_class->drop_viewable = gimp_item_tree_view_drop_viewable;
|
||||
tree_view_class->drop_possible = gimp_item_tree_view_drop_possible;
|
||||
tree_view_class->drop_viewables = gimp_item_tree_view_drop_viewables;
|
||||
|
||||
klass->set_image = gimp_item_tree_view_real_set_image;
|
||||
|
||||
|
|
@ -419,6 +424,7 @@ gimp_item_tree_view_constructed (GObject *object)
|
|||
gimp_dnd_drag_dest_set_by_type (GTK_WIDGET (tree_view->view),
|
||||
GTK_DEST_DEFAULT_HIGHLIGHT,
|
||||
item_view_class->item_type,
|
||||
TRUE,
|
||||
GDK_ACTION_MOVE | GDK_ACTION_COPY);
|
||||
|
||||
item_view->priv->new_button =
|
||||
|
|
@ -430,6 +436,10 @@ gimp_item_tree_view_constructed (GObject *object)
|
|||
/* connect "drop to new" manually as it makes a difference whether
|
||||
* it was clicked or dropped
|
||||
*/
|
||||
gimp_dnd_viewable_list_dest_add (item_view->priv->new_button,
|
||||
item_view_class->item_type,
|
||||
gimp_item_tree_view_new_list_dropped,
|
||||
item_view);
|
||||
gimp_dnd_viewable_dest_add (item_view->priv->new_button,
|
||||
item_view_class->item_type,
|
||||
gimp_item_tree_view_new_dropped,
|
||||
|
|
@ -1147,17 +1157,37 @@ gimp_item_tree_view_context_item (GimpContainerView *view,
|
|||
static gboolean
|
||||
gimp_item_tree_view_drop_possible (GimpContainerTreeView *tree_view,
|
||||
GimpDndType src_type,
|
||||
GimpViewable *src_viewable,
|
||||
GList *src_viewables,
|
||||
GimpViewable *dest_viewable,
|
||||
GtkTreePath *drop_path,
|
||||
GtkTreeViewDropPosition drop_pos,
|
||||
GtkTreeViewDropPosition *return_drop_pos,
|
||||
GdkDragAction *return_drag_action)
|
||||
{
|
||||
if (GIMP_IS_ITEM (src_viewable) &&
|
||||
(dest_viewable == NULL ||
|
||||
gimp_item_get_image (GIMP_ITEM (src_viewable)) !=
|
||||
gimp_item_get_image (GIMP_ITEM (dest_viewable))))
|
||||
GList *iter;
|
||||
gboolean other_image_items;
|
||||
|
||||
if (src_viewables)
|
||||
other_image_items = TRUE;
|
||||
else
|
||||
other_image_items = FALSE;
|
||||
|
||||
for (iter = src_viewables; iter; iter = iter->next)
|
||||
{
|
||||
GimpViewable *src_viewable = iter->data;
|
||||
|
||||
if (! GIMP_IS_ITEM (src_viewable) ||
|
||||
(dest_viewable != NULL &&
|
||||
gimp_item_get_image (GIMP_ITEM (src_viewable)) ==
|
||||
gimp_item_get_image (GIMP_ITEM (dest_viewable))))
|
||||
{
|
||||
/* Not an item or from the same image. */
|
||||
other_image_items = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (other_image_items)
|
||||
{
|
||||
if (return_drop_pos)
|
||||
*return_drop_pos = drop_pos;
|
||||
|
|
@ -1170,7 +1200,7 @@ gimp_item_tree_view_drop_possible (GimpContainerTreeView *tree_view,
|
|||
|
||||
return GIMP_CONTAINER_TREE_VIEW_CLASS (parent_class)->drop_possible (tree_view,
|
||||
src_type,
|
||||
src_viewable,
|
||||
src_viewables,
|
||||
dest_viewable,
|
||||
drop_path,
|
||||
drop_pos,
|
||||
|
|
@ -1179,65 +1209,88 @@ gimp_item_tree_view_drop_possible (GimpContainerTreeView *tree_view,
|
|||
}
|
||||
|
||||
static void
|
||||
gimp_item_tree_view_drop_viewable (GimpContainerTreeView *tree_view,
|
||||
GimpViewable *src_viewable,
|
||||
GimpViewable *dest_viewable,
|
||||
GtkTreeViewDropPosition drop_pos)
|
||||
gimp_item_tree_view_drop_viewables (GimpContainerTreeView *tree_view,
|
||||
GList *src_viewables,
|
||||
GimpViewable *dest_viewable,
|
||||
GtkTreeViewDropPosition drop_pos)
|
||||
{
|
||||
GimpItemTreeViewClass *item_view_class;
|
||||
GimpItemTreeView *item_view = GIMP_ITEM_TREE_VIEW (tree_view);
|
||||
GList *iter;
|
||||
GType src_viewable_type = G_TYPE_NONE;
|
||||
gint dest_index = -1;
|
||||
|
||||
item_view_class = GIMP_ITEM_TREE_VIEW_GET_CLASS (item_view);
|
||||
|
||||
if (item_view->priv->image != gimp_item_get_image (GIMP_ITEM (src_viewable)) ||
|
||||
! g_type_is_a (G_TYPE_FROM_INSTANCE (src_viewable),
|
||||
item_view_class->item_type))
|
||||
for (iter = src_viewables; iter; iter = iter->next)
|
||||
{
|
||||
GType item_type = item_view_class->item_type;
|
||||
GimpItem *new_item;
|
||||
GimpItem *parent;
|
||||
GimpViewable *src_viewable = iter->data;
|
||||
|
||||
if (g_type_is_a (G_TYPE_FROM_INSTANCE (src_viewable), item_type))
|
||||
item_type = G_TYPE_FROM_INSTANCE (src_viewable);
|
||||
|
||||
dest_index = gimp_item_tree_view_get_drop_index (item_view, dest_viewable,
|
||||
drop_pos,
|
||||
(GimpViewable **) &parent);
|
||||
|
||||
new_item = gimp_item_convert (GIMP_ITEM (src_viewable),
|
||||
item_view->priv->image, item_type);
|
||||
|
||||
gimp_item_set_linked (new_item, FALSE, FALSE);
|
||||
|
||||
item_view_class->add_item (item_view->priv->image, new_item,
|
||||
parent, dest_index, TRUE);
|
||||
/* All dropped viewables must be of the same finale type. */
|
||||
if (src_viewable_type == G_TYPE_NONE)
|
||||
src_viewable_type = G_TYPE_FROM_INSTANCE (src_viewable);
|
||||
else
|
||||
g_return_if_fail (src_viewable_type == G_TYPE_FROM_INSTANCE (src_viewable));
|
||||
}
|
||||
else if (dest_viewable)
|
||||
|
||||
if (drop_pos == GTK_TREE_VIEW_DROP_AFTER ||
|
||||
(drop_pos == GTK_TREE_VIEW_DROP_INTO_OR_AFTER &&
|
||||
dest_viewable &&
|
||||
gimp_viewable_get_children (dest_viewable)))
|
||||
src_viewables = g_list_reverse (src_viewables);
|
||||
|
||||
for (iter = src_viewables; iter; iter = iter->next)
|
||||
{
|
||||
GimpItem *src_parent;
|
||||
GimpItem *dest_parent;
|
||||
gint src_index;
|
||||
gint dest_index;
|
||||
GimpViewable *src_viewable = iter->data;
|
||||
|
||||
src_parent = GIMP_ITEM (gimp_viewable_get_parent (src_viewable));
|
||||
src_index = gimp_item_get_index (GIMP_ITEM (src_viewable));
|
||||
|
||||
dest_index = gimp_item_tree_view_get_drop_index (item_view, dest_viewable,
|
||||
drop_pos,
|
||||
(GimpViewable **) &dest_parent);
|
||||
|
||||
if (src_parent == dest_parent)
|
||||
if (item_view->priv->image != gimp_item_get_image (GIMP_ITEM (src_viewable)) ||
|
||||
! g_type_is_a (src_viewable_type, item_view_class->item_type))
|
||||
{
|
||||
if (src_index < dest_index)
|
||||
dest_index--;
|
||||
}
|
||||
GType item_type = item_view_class->item_type;
|
||||
GimpItem *new_item;
|
||||
GimpItem *parent;
|
||||
|
||||
gimp_image_reorder_item (item_view->priv->image,
|
||||
GIMP_ITEM (src_viewable),
|
||||
dest_parent,
|
||||
dest_index,
|
||||
TRUE, NULL);
|
||||
if (g_type_is_a (src_viewable_type, item_type))
|
||||
item_type = G_TYPE_FROM_INSTANCE (src_viewable);
|
||||
|
||||
dest_index = gimp_item_tree_view_get_drop_index (item_view, dest_viewable,
|
||||
drop_pos,
|
||||
(GimpViewable **) &parent);
|
||||
|
||||
new_item = gimp_item_convert (GIMP_ITEM (src_viewable),
|
||||
item_view->priv->image, item_type);
|
||||
|
||||
gimp_item_set_linked (new_item, FALSE, FALSE);
|
||||
|
||||
item_view_class->add_item (item_view->priv->image, new_item,
|
||||
parent, dest_index, TRUE);
|
||||
}
|
||||
else if (dest_viewable)
|
||||
{
|
||||
GimpItem *src_parent;
|
||||
GimpItem *dest_parent;
|
||||
gint src_index;
|
||||
gint dest_index;
|
||||
|
||||
src_parent = GIMP_ITEM (gimp_viewable_get_parent (src_viewable));
|
||||
src_index = gimp_item_get_index (GIMP_ITEM (src_viewable));
|
||||
|
||||
dest_index = gimp_item_tree_view_get_drop_index (item_view, dest_viewable,
|
||||
drop_pos,
|
||||
(GimpViewable **) &dest_parent);
|
||||
|
||||
if (src_parent == dest_parent)
|
||||
{
|
||||
if (src_index < dest_index)
|
||||
dest_index--;
|
||||
}
|
||||
|
||||
gimp_image_reorder_item (item_view->priv->image,
|
||||
GIMP_ITEM (src_viewable),
|
||||
dest_parent,
|
||||
dest_index,
|
||||
TRUE, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
gimp_image_flush (item_view->priv->image);
|
||||
|
|
@ -1274,6 +1327,38 @@ gimp_item_tree_view_new_dropped (GtkWidget *widget,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_item_tree_view_new_list_dropped (GtkWidget *widget,
|
||||
gint x,
|
||||
gint y,
|
||||
GList *viewables,
|
||||
gpointer data)
|
||||
{
|
||||
GimpItemTreeViewClass *item_view_class = GIMP_ITEM_TREE_VIEW_GET_CLASS (data);
|
||||
GimpContainerView *view = GIMP_CONTAINER_VIEW (data);
|
||||
GimpAction *action;
|
||||
|
||||
action = gimp_ui_manager_find_action (gimp_editor_get_ui_manager (GIMP_EDITOR (view)),
|
||||
item_view_class->action_group,
|
||||
item_view_class->new_default_action);
|
||||
|
||||
if (item_view_class->new_default_action && viewables && action)
|
||||
{
|
||||
GList *iter;
|
||||
|
||||
for (iter = viewables; iter; iter = iter->next)
|
||||
{
|
||||
GimpViewable *viewable = iter->data;
|
||||
|
||||
if (gimp_container_view_lookup (view, viewable))
|
||||
{
|
||||
g_object_set (action, "viewable", viewable, NULL);
|
||||
gimp_action_activate (action);
|
||||
g_object_set (action, "viewable", NULL, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* GimpImage callbacks */
|
||||
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@ static gboolean gimp_layer_tree_view_select_items (GimpContainer
|
|||
static void gimp_layer_tree_view_set_view_size (GimpContainerView *view);
|
||||
static gboolean gimp_layer_tree_view_drop_possible (GimpContainerTreeView *view,
|
||||
GimpDndType src_type,
|
||||
GimpViewable *src_viewable,
|
||||
GList *src_viewables,
|
||||
GimpViewable *dest_viewable,
|
||||
GtkTreePath *drop_path,
|
||||
GtkTreeViewDropPosition drop_pos,
|
||||
|
|
@ -716,7 +716,7 @@ gimp_layer_tree_view_set_view_size (GimpContainerView *view)
|
|||
static gboolean
|
||||
gimp_layer_tree_view_drop_possible (GimpContainerTreeView *tree_view,
|
||||
GimpDndType src_type,
|
||||
GimpViewable *src_viewable,
|
||||
GList *src_viewables,
|
||||
GimpViewable *dest_viewable,
|
||||
GtkTreePath *drop_path,
|
||||
GtkTreeViewDropPosition drop_pos,
|
||||
|
|
@ -731,7 +731,7 @@ gimp_layer_tree_view_drop_possible (GimpContainerTreeView *tree_view,
|
|||
src_type == GIMP_DND_TYPE_NETSCAPE_URL ||
|
||||
src_type == GIMP_DND_TYPE_COMPONENT ||
|
||||
src_type == GIMP_DND_TYPE_PIXBUF ||
|
||||
GIMP_IS_DRAWABLE (src_viewable))
|
||||
g_list_length (src_viewables) > 0)
|
||||
{
|
||||
GimpImage *dest_image = gimp_item_tree_view_get_image (GIMP_ITEM_TREE_VIEW (tree_view));
|
||||
|
||||
|
|
@ -741,7 +741,7 @@ gimp_layer_tree_view_drop_possible (GimpContainerTreeView *tree_view,
|
|||
|
||||
return GIMP_CONTAINER_TREE_VIEW_CLASS (parent_class)->drop_possible (tree_view,
|
||||
src_type,
|
||||
src_viewable,
|
||||
src_viewables,
|
||||
dest_viewable,
|
||||
drop_path,
|
||||
drop_pos,
|
||||
|
|
|
|||
|
|
@ -626,6 +626,72 @@ gimp_selection_data_get_item (GtkSelectionData *selection,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
gimp_selection_data_set_item_list (GtkSelectionData *selection,
|
||||
GList *items)
|
||||
{
|
||||
GString *str;
|
||||
GList *iter;
|
||||
|
||||
g_return_if_fail (selection != NULL);
|
||||
g_return_if_fail (items);
|
||||
|
||||
for (iter = items; iter; iter = iter->next)
|
||||
g_return_if_fail (GIMP_IS_ITEM (iter->data));
|
||||
|
||||
str = g_string_new (NULL);
|
||||
g_string_printf (str, "%d", gimp_get_pid ());
|
||||
for (iter = items; iter; iter = iter->next)
|
||||
g_string_append_printf (str, ":%d", gimp_item_get_id (iter->data));
|
||||
|
||||
gtk_selection_data_set (selection,
|
||||
gtk_selection_data_get_target (selection),
|
||||
8, (guchar *) str->str, str->len);
|
||||
|
||||
g_string_free (str, TRUE);
|
||||
}
|
||||
|
||||
GList *
|
||||
gimp_selection_data_get_item_list (GtkSelectionData *selection,
|
||||
Gimp *gimp)
|
||||
{
|
||||
const gchar *str;
|
||||
GList *items = NULL;
|
||||
|
||||
g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL);
|
||||
g_return_val_if_fail (selection != NULL, NULL);
|
||||
|
||||
str = gimp_selection_data_get_name (selection, G_STRFUNC);
|
||||
|
||||
if (str)
|
||||
{
|
||||
gchar **tokens;
|
||||
gint64 pid;
|
||||
|
||||
tokens = g_strsplit (str, ":", -1);
|
||||
g_return_val_if_fail (tokens[0] != NULL && tokens[1] != NULL, NULL);
|
||||
|
||||
pid = g_ascii_strtoll (tokens[0], NULL, 10);
|
||||
if (pid == gimp_get_pid ())
|
||||
{
|
||||
gint i = 1;
|
||||
|
||||
while (tokens[i])
|
||||
{
|
||||
gint64 id = g_ascii_strtoll (tokens[i], NULL, 10);
|
||||
|
||||
items = g_list_prepend (items, gimp_item_get_by_id (gimp, id));
|
||||
i++;
|
||||
}
|
||||
items = g_list_reverse (items);
|
||||
}
|
||||
|
||||
g_strfreev (tokens);
|
||||
}
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
void
|
||||
gimp_selection_data_set_object (GtkSelectionData *selection,
|
||||
GimpObject *object)
|
||||
|
|
|
|||
|
|
@ -84,6 +84,14 @@ GimpItem * gimp_selection_data_get_item (GtkSelectionData *selection,
|
|||
Gimp *gimp);
|
||||
|
||||
|
||||
/* item list */
|
||||
|
||||
void gimp_selection_data_set_item_list (GtkSelectionData *selection,
|
||||
GList *items);
|
||||
GList * gimp_selection_data_get_item_list (GtkSelectionData *selection,
|
||||
Gimp *gimp);
|
||||
|
||||
|
||||
/* various data */
|
||||
|
||||
void gimp_selection_data_set_object (GtkSelectionData *selection,
|
||||
|
|
|
|||
|
|
@ -86,14 +86,14 @@ static void gimp_tool_editor_set_context (GimpContainer
|
|||
|
||||
static gboolean gimp_tool_editor_drop_possible (GimpContainerTreeView *tree_view,
|
||||
GimpDndType src_type,
|
||||
GimpViewable *src_viewable,
|
||||
GList *src_viewables,
|
||||
GimpViewable *dest_viewable,
|
||||
GtkTreePath *drop_path,
|
||||
GtkTreeViewDropPosition drop_pos,
|
||||
GtkTreeViewDropPosition *return_drop_pos,
|
||||
GdkDragAction *return_drag_action);
|
||||
static void gimp_tool_editor_drop_viewable (GimpContainerTreeView *tree_view,
|
||||
GimpViewable *src_viewable,
|
||||
static void gimp_tool_editor_drop_viewables (GimpContainerTreeView *tree_view,
|
||||
GList *src_viewables,
|
||||
GimpViewable *dest_viewable,
|
||||
GtkTreeViewDropPosition drop_pos);
|
||||
|
||||
|
|
@ -155,10 +155,10 @@ gimp_tool_editor_class_init (GimpToolEditorClass *klass)
|
|||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GimpContainerTreeViewClass *tree_view_class = GIMP_CONTAINER_TREE_VIEW_CLASS (klass);
|
||||
|
||||
object_class->constructed = gimp_tool_editor_constructed;
|
||||
object_class->constructed = gimp_tool_editor_constructed;
|
||||
|
||||
tree_view_class->drop_possible = gimp_tool_editor_drop_possible;
|
||||
tree_view_class->drop_viewable = gimp_tool_editor_drop_viewable;
|
||||
tree_view_class->drop_possible = gimp_tool_editor_drop_possible;
|
||||
tree_view_class->drop_viewables = gimp_tool_editor_drop_viewables;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -319,7 +319,7 @@ gimp_tool_editor_set_context (GimpContainerView *container_view,
|
|||
static gboolean
|
||||
gimp_tool_editor_drop_possible (GimpContainerTreeView *tree_view,
|
||||
GimpDndType src_type,
|
||||
GimpViewable *src_viewable,
|
||||
GList *src_viewables,
|
||||
GimpViewable *dest_viewable,
|
||||
GtkTreePath *drop_path,
|
||||
GtkTreeViewDropPosition drop_pos,
|
||||
|
|
@ -328,7 +328,7 @@ gimp_tool_editor_drop_possible (GimpContainerTreeView *tree_view,
|
|||
{
|
||||
if (GIMP_CONTAINER_TREE_VIEW_CLASS (parent_class)->drop_possible (
|
||||
tree_view,
|
||||
src_type, src_viewable, dest_viewable, drop_path, drop_pos,
|
||||
src_type, src_viewables, dest_viewable, drop_path, drop_pos,
|
||||
return_drop_pos, return_drag_action))
|
||||
{
|
||||
if (gimp_viewable_get_parent (dest_viewable) ||
|
||||
|
|
@ -336,7 +336,15 @@ gimp_tool_editor_drop_possible (GimpContainerTreeView *tree_view,
|
|||
(drop_pos == GTK_TREE_VIEW_DROP_INTO_OR_AFTER ||
|
||||
drop_pos == GTK_TREE_VIEW_DROP_INTO_OR_BEFORE)))
|
||||
{
|
||||
return ! gimp_viewable_get_children (src_viewable);
|
||||
GList *iter;
|
||||
|
||||
for (iter = src_viewables; iter; iter = iter->next)
|
||||
{
|
||||
GimpViewable *src_viewable = iter->data;
|
||||
|
||||
if (gimp_viewable_get_children (src_viewable))
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
|
@ -346,19 +354,20 @@ gimp_tool_editor_drop_possible (GimpContainerTreeView *tree_view,
|
|||
}
|
||||
|
||||
static void
|
||||
gimp_tool_editor_drop_viewable (GimpContainerTreeView *tree_view,
|
||||
GimpViewable *src_viewable,
|
||||
GimpViewable *dest_viewable,
|
||||
GtkTreeViewDropPosition drop_pos)
|
||||
gimp_tool_editor_drop_viewables (GimpContainerTreeView *tree_view,
|
||||
GList *src_viewables,
|
||||
GimpViewable *dest_viewable,
|
||||
GtkTreeViewDropPosition drop_pos)
|
||||
{
|
||||
GimpContainerView *container_view = GIMP_CONTAINER_VIEW (tree_view);
|
||||
|
||||
GIMP_CONTAINER_TREE_VIEW_CLASS (parent_class)->drop_viewable (tree_view,
|
||||
src_viewable,
|
||||
dest_viewable,
|
||||
drop_pos);
|
||||
GIMP_CONTAINER_TREE_VIEW_CLASS (parent_class)->drop_viewables (tree_view,
|
||||
src_viewables,
|
||||
dest_viewable,
|
||||
drop_pos);
|
||||
|
||||
gimp_container_view_select_item (container_view, src_viewable);
|
||||
if (src_viewables)
|
||||
gimp_container_view_select_item (container_view, src_viewables->data);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
|||
|
|
@ -167,7 +167,9 @@ typedef enum /*< skip >*/
|
|||
GIMP_DND_TYPE_TOOL_ITEM = 23,
|
||||
GIMP_DND_TYPE_NOTEBOOK_TAB = 24,
|
||||
|
||||
GIMP_DND_TYPE_LAST = GIMP_DND_TYPE_NOTEBOOK_TAB
|
||||
GIMP_DND_TYPE_LAYER_LIST = 25,
|
||||
|
||||
GIMP_DND_TYPE_LAST = GIMP_DND_TYPE_LAYER_LIST
|
||||
} GimpDndType;
|
||||
|
||||
typedef enum /*< skip >*/
|
||||
|
|
|
|||
Loading…
Reference in a new issue