[glade] Drag&Drop clean up.
- From: Juan Pablo Ugarte <jpu src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glade] Drag&Drop clean up.
- Date: Mon, 19 Aug 2013 18:54:51 +0000 (UTC)
commit 4fced46855d4f947a5dfc28ef238ee35bc02e360
Author: Juan Pablo Ugarte <juanpablougarte gmail com>
Date: Wed Jul 17 17:54:16 2013 -0300
Drag&Drop clean up.
Added private _GladeDrag interface. (only used internaly in gladeui)
Implemented _GladeDrag in GladePlaceholder GladeWidget GladeDesignView and GladeDesignLayout
Added drag-dest property to GladeWidget to enable/disable drag support
(used in GtkFixed GtkLayout and GtkOverlay containers)
Made GladeInspector a drag source by implementing GtkTreeDragSource interface in GladeProject
gladeui/Makefile.am | 8 +-
gladeui/glade-design-layout.c | 187 +++++---------
gladeui/glade-design-private.h | 19 +-
gladeui/glade-design-view.c | 522 ++++++++++++++++----------------------
gladeui/glade-design-view.h | 3 -
gladeui/glade-dnd.c | 174 +++++++++++++
gladeui/glade-dnd.h | 52 ++++
gladeui/glade-drag.c | 86 +++++++
gladeui/glade-drag.h | 81 ++++++
gladeui/glade-inspector.c | 6 +
gladeui/glade-palette.c | 36 ++--
gladeui/glade-placeholder.c | 255 +++++++++++++------
gladeui/glade-project.c | 48 ++++-
gladeui/glade-widget.c | 102 ++++++++-
plugins/gtk+/glade-gtk-overlay.c | 5 +-
src/glade-window.c | 2 -
16 files changed, 1045 insertions(+), 541 deletions(-)
---
diff --git a/gladeui/Makefile.am b/gladeui/Makefile.am
index 88b143b..230efda 100644
--- a/gladeui/Makefile.am
+++ b/gladeui/Makefile.am
@@ -121,7 +121,9 @@ libgladeui_2_la_SOURCES = \
glade-widget.c \
glade-widget-action.c \
glade-widget-adaptor.c \
- glade-xml-utils.c
+ glade-xml-utils.c \
+ glade-drag.c \
+ glade-dnd.c
libgladeui_2_la_CPPFLAGS = \
$(common_defines) \
@@ -189,7 +191,9 @@ noinst_HEADERS = \
glade-preview.h \
glade-preview-tokens.h \
glade-project-properties.h \
- gladeui-resources.h
+ gladeui-resources.h \
+ glade-drag.h \
+ glade-dnd.h
if PLATFORM_WIN32
libgladeui_2_la_LDFLAGS += -no-undefined
diff --git a/gladeui/glade-design-layout.c b/gladeui/glade-design-layout.c
index 8a48aed..ae9d7ca 100644
--- a/gladeui/glade-design-layout.c
+++ b/gladeui/glade-design-layout.c
@@ -2,7 +2,7 @@
* glade-design-layout.c
*
* Copyright (C) 2006-2007 Vincent Geddes
- * 2011 Juan Pablo Ugarte
+ * 2011-2013 Juan Pablo Ugarte
*
* Authors:
* Vincent Geddes <vgeddes gnome org>
@@ -110,8 +110,8 @@ struct _GladeDesignLayoutPrivate
/* Drag & Drop */
GtkWidget *drag_source;
- GtkWidget *drag_icon;
gint drag_x, drag_y;
+ GladeWidget *drag_dest;
/* Properties */
GladeDesignView *view;
@@ -382,9 +382,9 @@ glade_design_layout_motion_notify_event (GtkWidget *widget, GdkEventMotion *ev)
static GtkTargetList *target = NULL;
if (target == NULL)
- target = gtk_target_list_new (_glade_design_layout_get_dnd_target (), 1);
+ target = gtk_target_list_new (_glade_dnd_get_target (), 1);
- gtk_drag_begin (widget, target, GDK_ACTION_COPY, 1, (GdkEvent*)ev);
+ gtk_drag_begin_with_coordinates (widget, target, 0, 1, (GdkEvent*)ev, x, y);
return TRUE;
}
@@ -1472,6 +1472,30 @@ draw_selection_nodes (cairo_t *cr,
cairo_restore (cr);
}
+static inline void
+draw_drag_dest (GladeDesignLayout *layout, cairo_t *cr, GladeWidget *drag)
+{
+ GladeDesignLayoutPrivate *priv = layout->priv;
+ GObject *obj = glade_widget_get_object (drag);
+ const double dashes = 3;
+ GtkWidget *widget;
+ gint x, y;
+
+ if (!GTK_IS_WIDGET (obj))
+ return;
+
+ widget = GTK_WIDGET (obj);
+
+ gtk_widget_translate_coordinates (widget, GTK_WIDGET (layout), 0, 0, &x, &y);
+ cairo_set_line_width (cr, 2);
+ cairo_set_dash (cr, &dashes, 1, 0);
+ gdk_cairo_set_source_rgba (cr, &priv->frame_color_active[0]);
+ cairo_rectangle (cr, x+1, y+1,
+ gtk_widget_get_allocated_width (widget)-2,
+ gtk_widget_get_allocated_height(widget)-2);
+ cairo_stroke (cr);
+}
+
static gboolean
glade_design_layout_draw (GtkWidget *widget, cairo_t *cr)
{
@@ -1537,6 +1561,9 @@ glade_design_layout_draw (GtkWidget *widget, cairo_t *cr)
/* Draw selection nodes if we are in margins edit mode */
if (priv->selection && gtk_widget_is_ancestor (priv->selection, child))
draw_selection_nodes (cr, priv, widget);
+
+ if (priv->drag_dest)
+ draw_drag_dest (GLADE_DESIGN_LAYOUT (widget), cr, priv->drag_dest);
}
}
else if (gtk_cairo_should_draw_window (cr, priv->offscreen_window))
@@ -1934,7 +1961,8 @@ glade_design_layout_finalize (GObject *object)
GladeDesignLayoutPrivate *priv = layout->priv;
g_clear_object (&priv->default_context);
-
+ g_clear_object (&priv->drag_dest);
+
g_signal_handlers_disconnect_by_func (priv->project,
on_project_selection_changed,
layout);
@@ -1945,121 +1973,24 @@ glade_design_layout_finalize (GObject *object)
G_OBJECT_CLASS (glade_design_layout_parent_class)->finalize (object);
}
-static gboolean
-on_drag_icon_draw (GtkWidget *widget, cairo_t *cr)
-{
- GtkStyleContext *context = gtk_widget_get_style_context (widget);
- cairo_pattern_t *gradient;
- GtkAllocation alloc;
- gint x, y, w, h;
- gdouble h2;
- GdkRGBA bg;
-
- /* Not needed acording to GtkWidget:draw documentation
- * But seems like there is a bug when used as a drag_icon that makes the
- * cairo translation used here persist when drawind children.
- */
- cairo_save (cr);
-
- /* Clear BG */
- cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
- cairo_paint (cr);
- cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
-
- gtk_widget_get_allocation (widget, &alloc);
- x = alloc.x;
- y = alloc.y;
- w = alloc.width;
- h = alloc.height;
- h2 = h/2.0;
-
- gtk_style_context_get_background_color (context, GTK_STATE_NORMAL, &bg);
-
- gradient = cairo_pattern_create_linear (x, y, x, y+h);
- cairo_pattern_add_color_stop_rgba (gradient, 0, bg.red, bg.green, bg.blue, 0);
- cairo_pattern_add_color_stop_rgba (gradient, .5, bg.red, bg.green, bg.blue, .8);
- cairo_pattern_add_color_stop_rgba (gradient, 1, bg.red, bg.green, bg.blue, 0);
-
- cairo_set_source (cr, gradient);
- cairo_rectangle (cr, x+h2, y, w-h, h);
- cairo_fill (cr);
- cairo_pattern_destroy (gradient);
-
- gradient = cairo_pattern_create_radial (x+h2, y+h2, 0, x+h2, y+h2, h2);
- cairo_pattern_add_color_stop_rgba (gradient, 0, bg.red, bg.green, bg.blue, .8);
- cairo_pattern_add_color_stop_rgba (gradient, 1, bg.red, bg.green, bg.blue, 0);
-
- cairo_set_source (cr, gradient);
- cairo_rectangle (cr, x, y, h2, h);
- cairo_fill (cr);
-
- cairo_translate (cr, w-h, 0);
- cairo_set_source (cr, gradient);
- cairo_rectangle (cr, x+h2, y, h2, h);
- cairo_fill (cr);
-
- cairo_pattern_destroy (gradient);
- cairo_restore (cr);
-
- return FALSE;
-}
-
-GtkWidget *
-_glade_design_layout_dnd_icon_widget_new (GdkDragContext *context,
- const gchar *icon_name,
- const gchar *description)
-{
- GtkWidget *window, *box, *label, *icon;
- GdkScreen *screen;
- GdkVisual *visual;
-
- screen = gdk_window_get_screen (gdk_drag_context_get_source_window (context));
- visual = gdk_screen_get_rgba_visual (screen);
- window = gtk_window_new (GTK_WINDOW_POPUP);
-
- gtk_window_set_type_hint (GTK_WINDOW (window), GDK_WINDOW_TYPE_HINT_DND);
- gtk_window_set_screen (GTK_WINDOW (window), screen);
- gtk_widget_set_visual (window, visual);
-
- box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 4);
- gtk_container_set_border_width (GTK_CONTAINER (box), 12);
-
- icon = gtk_image_new_from_icon_name (icon_name, GTK_ICON_SIZE_BUTTON);
- gtk_widget_set_opacity (icon, .8);
-
- label = gtk_label_new (description);
-
- gtk_box_pack_start (GTK_BOX (box), icon, FALSE, TRUE, 0);
- gtk_box_pack_start (GTK_BOX (box), label, FALSE, TRUE, 0);
-
- gtk_widget_show_all (box);
- gtk_container_add (GTK_CONTAINER (window), box);
-
- gtk_widget_set_app_paintable (window, TRUE);
- g_signal_connect (window, "draw", G_CALLBACK (on_drag_icon_draw), NULL);
-
- return window;
-}
-
static void
glade_design_layout_drag_begin (GtkWidget *widget, GdkDragContext *context)
{
GladeDesignLayoutPrivate *priv = GLADE_DESIGN_LAYOUT_PRIVATE (widget);
GladeWidgetAdaptor *adaptor;
GladeWidget *gwidget;
- const gchar *icon_name;
gchar *description;
gwidget = glade_widget_get_from_gobject (priv->drag_source);
adaptor = glade_widget_get_adaptor (gwidget);
- icon_name = glade_widget_adaptor_get_icon_name (adaptor);
description = g_strdup_printf ("%s [%s]",
glade_widget_adaptor_get_name (adaptor),
glade_widget_get_name (gwidget));
- priv->drag_icon = _glade_design_layout_dnd_icon_widget_new (context, icon_name, description);
- g_object_ref_sink (priv->drag_icon);
- gtk_drag_set_icon_widget (context, priv->drag_icon, 0, 0);
+ _glade_dnd_set_icon_widget (context,
+ glade_widget_adaptor_get_icon_name (adaptor),
+ description);
+
g_free (description);
}
@@ -2071,25 +2002,13 @@ glade_design_layout_drag_data_get (GtkWidget *widget,
guint time)
{
GladeDesignLayoutPrivate *priv = GLADE_DESIGN_LAYOUT_PRIVATE (widget);
-
- if (priv->drag_source)
- {
- static GdkAtom type = 0;
-
- if (!type)
- type = gdk_atom_intern_static_string (GDL_DND_TARGET_WIDGET);
-
- gtk_selection_data_set (data, type, sizeof (gpointer),
- (const guchar *)&priv->drag_source, sizeof (gpointer));
- }
+ _glade_dnd_set_data (data, G_OBJECT (priv->drag_source));
}
static void
glade_design_layout_drag_end (GtkWidget *widget, GdkDragContext *context)
{
GladeDesignLayoutPrivate *priv = GLADE_DESIGN_LAYOUT_PRIVATE (widget);
-
- g_clear_object (&priv->drag_icon);
priv->drag_source = NULL;
}
@@ -2278,13 +2197,6 @@ _glade_design_layout_get_colors (GtkStyleContext *context,
c1->blue += off;
}
-GtkTargetEntry *
-_glade_design_layout_get_dnd_target (void)
-{
- static GtkTargetEntry target = {GDL_DND_TARGET_WIDGET, GTK_TARGET_SAME_APP, GDL_DND_INFO_WIDGET};
- return ⌖
-}
-
void
_glade_design_layout_get_hot_point (GladeDesignLayout *layout,
gint *x,
@@ -2299,6 +2211,20 @@ _glade_design_layout_get_hot_point (GladeDesignLayout *layout,
*y = priv->drag_y;
}
+void
+_glade_design_layout_set_highlight (GladeDesignLayout *layout,
+ GladeWidget *drag)
+{
+ GladeDesignLayoutPrivate *priv = layout->priv;
+
+ g_clear_object (&priv->drag_dest);
+
+ if (drag)
+ priv->drag_dest = g_object_ref (drag);
+
+ gtk_widget_queue_draw (GTK_WIDGET (layout));
+}
+
typedef struct
{
GtkWidget *toplevel;
@@ -2484,7 +2410,8 @@ gdl_drag_source_check (GladeDesignLayout *layout,
GObject *source;
if (gwidget && (source = glade_widget_get_object (gwidget)) &&
- !(event->button.state & GDK_SHIFT_MASK))
+ !(event->button.state & GDK_SHIFT_MASK) &&
+ _glade_drag_can_drag (GLADE_DRAG (gwidget)))
{
priv->drag_source = GTK_WIDGET (source);
@@ -2503,6 +2430,12 @@ gdl_drag_source_check (GladeDesignLayout *layout,
}
}
+GladeWidget *
+_glade_design_layout_get_child (GladeDesignLayout *layout)
+{
+ return layout->priv->gchild;
+}
+
/*
* _glade_design_layout_do_event:
* @layout: A #GladeDesignLayout
diff --git a/gladeui/glade-design-private.h b/gladeui/glade-design-private.h
index 82b202f..708869d 100644
--- a/gladeui/glade-design-private.h
+++ b/gladeui/glade-design-private.h
@@ -25,11 +25,9 @@
#ifndef __GLADE_DESIGN_PRIVATE_H__
#define __GLADE_DESIGN_PRIVATE_H__
-#define GDL_DND_INFO_WIDGET 15956
-#define GDL_DND_TARGET_WIDGET "glade/x-widget"
-
#include "glade-design-view.h"
#include "glade-design-layout.h"
+#include "glade-dnd.h"
G_BEGIN_DECLS
@@ -53,20 +51,19 @@ void _glade_design_layout_draw_pushpin (cairo_t *cr,
GdkRGBA *bg,
GdkRGBA *fg);
-void _glade_design_layout_get_hot_point (GladeDesignLayout *layout,
- gint *x,
- gint *y);
-
-GtkTargetEntry *_glade_design_layout_get_dnd_target (void);
+void _glade_design_layout_get_hot_point (GladeDesignLayout *layout,
+ gint *x,
+ gint *y);
-GtkWidget *_glade_design_layout_dnd_icon_widget_new (GdkDragContext *context,
- const gchar *icon_name,
- const gchar *description);
+GladeWidget * _glade_design_layout_get_child (GladeDesignLayout *layout);
GtkWidget *_glade_design_layout_get_child_at_position (GtkWidget *widget,
gint x,
gint y);
+void _glade_design_layout_set_highlight (GladeDesignLayout *layout,
+ GladeWidget *drag);
+
G_END_DECLS
#endif /* __GLADE_DESIGN_PRIVATE_H__ */
diff --git a/gladeui/glade-design-view.c b/gladeui/glade-design-view.c
index d696d31..7d45b37 100644
--- a/gladeui/glade-design-view.c
+++ b/gladeui/glade-design-view.c
@@ -1,8 +1,8 @@
/*
* glade-design-view.c
*
- * Copyright (C) 2006 Vincent Geddes
- * 2011 Juan Pablo Ugarte
+ * Copyright (C) 2006 Vincent Geddes
+ * 2011-2013 Juan Pablo Ugarte
*
* Authors:
* Vincent Geddes <vincent geddes gmail com>
@@ -35,6 +35,7 @@
#include "config.h"
#include "glade.h"
+#include "glade-dnd.h"
#include "glade-utils.h"
#include "glade-design-view.h"
#include "glade-design-layout.h"
@@ -51,8 +52,7 @@
enum
{
PROP_0,
- PROP_PROJECT,
- PROP_DRAG_SOURCE
+ PROP_PROJECT
};
struct _GladeDesignViewPrivate
@@ -61,15 +61,18 @@ struct _GladeDesignViewPrivate
GtkWidget *scrolled_window; /* Main scrolled window */
GtkWidget *layout_box; /* Box to pack a GladeDesignLayout for each toplevel in project */
- GtkToolPalette *palette;
- GladeWidgetAdaptor *drag_adaptor;
- GtkWidget *drag_source;
- GtkWidget *drag_target;
+ _GladeDrag *drag_target;
+ GObject *drag_data;
+ gboolean drag_highlight;
};
static GtkVBoxClass *parent_class = NULL;
-G_DEFINE_TYPE (GladeDesignView, glade_design_view, GTK_TYPE_BOX)
+static void glade_design_view_drag_init (_GladeDragInterface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (GladeDesignView, glade_design_view, GTK_TYPE_BOX,
+ G_IMPLEMENT_INTERFACE (GLADE_TYPE_DRAG,
+ glade_design_view_drag_init))
static void
glade_design_layout_scroll (GladeDesignView *view, gint x, gint y, gint w, gint h)
@@ -275,10 +278,6 @@ glade_design_view_set_property (GObject *object,
glade_design_view_set_project (GLADE_DESIGN_VIEW (object),
g_value_get_object (value));
break;
- case PROP_DRAG_SOURCE:
- glade_design_view_set_drag_source (GLADE_DESIGN_VIEW (object),
- GTK_TOOL_PALETTE (g_value_get_object (value)));
- break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -296,9 +295,6 @@ glade_design_view_get_property (GObject *object,
case PROP_PROJECT:
g_value_set_object (value, GLADE_DESIGN_VIEW (object)->priv->project);
break;
- case PROP_DRAG_SOURCE:
- g_value_set_object (value, GLADE_DESIGN_VIEW (object)->priv->palette);
- break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -334,20 +330,37 @@ glade_design_view_draw (GtkWidget *widget, cairo_t *cr)
{
GladeDesignViewPrivate *priv = GLADE_DESIGN_VIEW_GET_PRIVATE (widget);
GdkWindow *window = gtk_widget_get_window (widget);
+ gboolean should_draw = gtk_cairo_should_draw_window (cr, window);
+ gboolean sw_visible = gtk_widget_get_visible (priv->scrolled_window);
- if (gtk_cairo_should_draw_window (cr, window))
+ if (should_draw)
{
- if (gtk_widget_get_visible (priv->scrolled_window) == FALSE)
- logo_draw (widget, cr);
- else
+ if (sw_visible)
gtk_render_background (gtk_widget_get_style_context (widget),
- cr,
- 0, 0,
- gdk_window_get_width (window),
- gdk_window_get_height (window));
+ cr, 0, 0,
+ gtk_widget_get_allocated_width (widget),
+ gtk_widget_get_allocated_height (widget));
+ else
+ logo_draw (widget, cr);
}
GTK_WIDGET_CLASS (glade_design_view_parent_class)->draw (widget, cr);
+
+ if (should_draw && sw_visible && priv->drag_highlight)
+ {
+ GtkStyleContext *context = gtk_widget_get_style_context (widget);
+ GdkRGBA c;
+
+ gtk_style_context_get_background_color (context, GTK_STATE_FLAG_SELECTED |
+ GTK_STATE_FLAG_FOCUSED, &c);
+
+ cairo_set_line_width (cr, 2);
+ gdk_cairo_set_source_rgba (cr, &c);
+ cairo_rectangle (cr, 0, 0,
+ gtk_widget_get_allocated_width (widget),
+ gtk_widget_get_allocated_height (widget));
+ cairo_stroke (cr);
+ }
return FALSE;
}
@@ -388,6 +401,8 @@ glade_design_view_init (GladeDesignView *view)
gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET (view)),
GTK_STYLE_CLASS_VIEW);
+
+ _glade_dnd_dest_set (GTK_WIDGET (view));
}
static void
@@ -400,120 +415,52 @@ glade_design_view_finalize (GObject *object)
G_OBJECT_CLASS (parent_class)->finalize (object);
}
-static GtkWidget *
-widget_get_child_from_position (GtkWidget *toplevel, GtkWidget *widget, gint x, gint y)
+typedef struct
{
- GtkWidget *retval = NULL;
- GList *children, *l;
-
- if (!GTK_IS_CONTAINER (widget))
- return NULL;
-
- children = glade_util_container_get_all_children (GTK_CONTAINER (widget));
-
- for (l = children;l; l = g_list_next (l))
- {
- GtkWidget *child = l->data;
-
- if (gtk_widget_get_mapped (child))
- {
- GtkAllocation alloc;
- gint xx, yy;
-
- gtk_widget_translate_coordinates (toplevel, child, x, y, &xx, &yy);
- gtk_widget_get_allocation (child, &alloc);
-
- if (xx >= 0 && yy >= 0 && xx <= alloc.width && yy <= alloc.height)
- {
- if (GTK_IS_CONTAINER (child))
- retval = widget_get_child_from_position (toplevel, child, x, y);
-
- if (!retval)
- retval = child;
-
- break;
- }
- }
- }
-
- g_list_free (children);
-
- return retval;
-}
-
-static GtkWidget *
-widget_get_gchild_from_position (GtkWidget *toplevel, GtkWidget *widget, gint x, gint y)
-{
- GtkWidget *retval = widget_get_child_from_position (toplevel, widget, x, y);
-
- while (retval)
- {
- if (retval == toplevel || GLADE_IS_PLACEHOLDER (retval) ||
- glade_widget_get_from_gobject (retval))
- return retval;
-
- retval = gtk_widget_get_parent (retval);
- }
-
- return NULL;
-}
+ GtkWidget *child;
+ gint x, y;
+} FindInContainerData;
-static gboolean
-drag_highlight_draw (GtkWidget *widget, cairo_t *cr, GladeDesignView *view)
+static void
+find_inside_container (GtkWidget *widget, FindInContainerData *data)
{
- GtkStyleContext *context;
- gint width, height;
- GdkRGBA c;
-
- context = gtk_widget_get_style_context (GTK_WIDGET (view));
- width = gtk_widget_get_allocated_width (widget);
- height = gtk_widget_get_allocated_height (widget);
-
- gtk_style_context_get_background_color (context, GTK_STATE_FLAG_SELECTED |
- GTK_STATE_FLAG_FOCUSED, &c);
-
- if (GLADE_IS_PLACEHOLDER (widget))
- {
- cairo_pattern_t *gradient;
- gdouble w, h;
-
- w = gtk_widget_get_allocated_width (widget)/2.0;
- h = gtk_widget_get_allocated_height (widget)/2.0;
- gradient = cairo_pattern_create_radial (w, h, MIN (width, height)/6,
- w, h, MAX (w, h));
- cairo_pattern_add_color_stop_rgba (gradient, 0, c.red, c.green, c.blue, .08);
- cairo_pattern_add_color_stop_rgba (gradient, 1, c.red, c.green, c.blue, .28);
+ GtkAllocation alloc;
+ gint x, y;
- cairo_set_source (cr, gradient);
+ if (data->child || !gtk_widget_get_mapped (widget))
+ return;
- cairo_rectangle (cr, 0, 0, width, height);
- cairo_fill (cr);
+ x = data->x;
+ y = data->y;
+ gtk_widget_get_allocation (widget, &alloc);
- cairo_pattern_destroy (gradient);
- }
- else
+ if (x >= alloc.x && x <= (alloc.x + alloc.width) &&
+ y >= alloc.y && y <= (alloc.y + alloc.height))
{
- cairo_set_line_width (cr, 2);
- gdk_cairo_set_source_rgba (cr, &c);
- cairo_rectangle (cr, 1, 1, width-2, height-2);
- cairo_stroke (cr);
+ data->child = widget;
}
-
- return FALSE;
}
static void
-glade_design_view_drag_highlight (GladeDesignView *view, GtkWidget *widget)
+glade_design_view_drag_highlight (_GladeDrag *dest,
+ gint x,
+ gint y)
{
- g_signal_connect_after (widget, "draw", G_CALLBACK (drag_highlight_draw), view);
- gtk_widget_queue_draw (widget);
-}
+ if (GLADE_IS_WIDGET (dest))
+ {
+ GObject *obj = glade_widget_get_object (GLADE_WIDGET (dest));
+
+ if (GTK_IS_WIDGET (obj))
+ {
+ GtkWidget *layout = gtk_widget_get_ancestor (GTK_WIDGET (obj),
+ GLADE_TYPE_DESIGN_LAYOUT);
+ if (layout)
+ _glade_design_layout_set_highlight (GLADE_DESIGN_LAYOUT (layout),
+ (x<0 || y<0) ? NULL : GLADE_WIDGET (dest));
+ }
+ }
-static void
-glade_design_view_drag_unhighlight (GladeDesignView *view, GtkWidget *widget)
-{
- g_signal_handlers_disconnect_by_func (widget, drag_highlight_draw, view);
- gtk_widget_queue_draw (widget);
+ _glade_drag_highlight (dest, x, y);
}
static gboolean
@@ -522,13 +469,13 @@ glade_design_view_drag_motion (GtkWidget *widget,
gint x, gint y,
guint time)
{
- GladeDesignViewPrivate *priv = GLADE_DESIGN_VIEW (widget)->priv;
- GdkDragAction drag_action = GDK_ACTION_COPY;
- GtkWidget *child;
+ GladeDesignView *view = GLADE_DESIGN_VIEW (widget);
+ GladeDesignViewPrivate *priv = view->priv;
+ FindInContainerData data;
+ _GladeDrag *drag = NULL;
+ gint xx, yy;
- child = widget_get_gchild_from_position (widget, widget, x, y);
-
- if (!(priv->drag_adaptor || priv->drag_source))
+ if (!priv->drag_data)
{
GdkAtom target = gtk_drag_dest_find_target (widget, context, NULL);
@@ -536,78 +483,93 @@ glade_design_view_drag_motion (GtkWidget *widget,
gtk_drag_get_data (widget, context, target, time);
}
- if (child)
- {
- GladeWidget *gwidget;
-
- if (priv->drag_source &&
- (priv->drag_source == child || gtk_widget_is_ancestor (child, priv->drag_source) ||
- (!GLADE_IS_PLACEHOLDER (child) &&
- !GTK_IS_FIXED (child) && !GTK_IS_LAYOUT (child) &&
- (glade_widget_get_from_gobject (child) ||
- ((gwidget = glade_widget_get_from_gobject (priv->drag_source)) &&
- !glade_widget_get_parent (gwidget)
- ))
- )))
- drag_action = 0;
-
- if (priv->drag_adaptor &&
- ((GLADE_IS_PLACEHOLDER (child) && GWA_IS_TOPLEVEL (priv->drag_adaptor)) ||
- (!GLADE_IS_PLACEHOLDER (child) && !GTK_IS_FIXED (child) && !GTK_IS_LAYOUT (child) &&
- glade_widget_get_from_gobject (child))))
- drag_action = 0;
- }
- else
- drag_action = 0;
-
- gdk_drag_status (context, drag_action, time);
+ data.child = NULL;
+ gtk_widget_translate_coordinates (widget, GTK_WIDGET (priv->layout_box),
+ x, y, &data.x, &data.y);
+ gtk_container_forall (GTK_CONTAINER (priv->layout_box),
+ (GtkCallback) find_inside_container,
+ &data);
- if (priv->drag_target != child)
+ if (data.child)
{
- if (priv->drag_target)
- {
- glade_design_view_drag_unhighlight (GLADE_DESIGN_VIEW (widget),
- priv->drag_target);
- priv->drag_target = NULL;
- }
+ GladeDesignLayout *layout = GLADE_DESIGN_LAYOUT (data.child);
+ GladeWidget *gchild = _glade_design_layout_get_child (layout);
+ GtkWidget *child = GTK_WIDGET (glade_widget_get_object (gchild));
+ GtkWidget *drag_target;
+
+ gtk_widget_translate_coordinates (widget, child, x, y, &xx, &yy);
+
+ drag_target = _glade_design_layout_get_child_at_position (child, xx, yy);
- if (drag_action == GDK_ACTION_COPY)
+ if (drag_target)
{
- glade_design_view_drag_highlight (GLADE_DESIGN_VIEW (widget), child);
- priv->drag_target = child;
+ GladeWidget *gwidget;
+
+ if (GLADE_IS_PLACEHOLDER (drag_target))
+ drag = GLADE_DRAG (drag_target);
+ else if ((gwidget = glade_widget_get_from_gobject (drag_target)))
+ {
+ while (gwidget && !_glade_drag_can_drop (GLADE_DRAG (gwidget),
+ xx, yy, priv->drag_data))
+ gwidget = glade_widget_get_parent (gwidget);
+
+ if (gwidget)
+ drag = GLADE_DRAG (gwidget);
+ }
}
}
+ else if (_glade_drag_can_drop (GLADE_DRAG (widget), x, y, priv->drag_data))
+ {
+ drag = GLADE_DRAG (widget);
+ xx = x;
+ yy = y;
+ }
+
+ if (priv->drag_target && priv->drag_target != drag)
+ {
+ glade_design_view_drag_highlight (priv->drag_target, -1, -1);
+ g_clear_object (&priv->drag_target);
+ }
- return drag_action != 0;
+ if (drag)
+ {
+ priv->drag_target = g_object_ref (drag);
+
+ glade_design_view_drag_highlight (drag, xx, yy);
+
+ gdk_drag_status (context, GDK_ACTION_COPY, time);
+ return TRUE;
+ }
+
+ gdk_drag_status (context, 0, time);
+ return FALSE;
}
static void
glade_design_view_drag_leave (GtkWidget *widget,
- GdkDragContext *drag_context,
+ GdkDragContext *context,
guint time)
{
GladeDesignViewPrivate *priv = GLADE_DESIGN_VIEW (widget)->priv;
if (priv->drag_target)
- {
- glade_design_view_drag_unhighlight (GLADE_DESIGN_VIEW (widget),
- priv->drag_target);
- priv->drag_target = NULL;
- }
+ glade_design_view_drag_highlight (priv->drag_target, -1, -1);
}
static void
-on_drag_item_drag_end (GtkWidget *widget,
- GdkDragContext *context,
- GladeDesignView *view)
+on_source_drag_end (GtkWidget *widget,
+ GdkDragContext *context,
+ GladeDesignView *view)
{
GladeDesignViewPrivate *priv = view->priv;
-
- priv->drag_adaptor = NULL;
- priv->drag_source = NULL;
- priv->drag_target = NULL;
- g_signal_handlers_disconnect_by_func (widget, on_drag_item_drag_end, view);
+ if (priv->drag_target)
+ {
+ glade_design_view_drag_highlight (priv->drag_target, -1, -1);
+ g_clear_object (&priv->drag_target);
+ }
+
+ g_clear_object (&priv->drag_data);
}
static void
@@ -619,34 +581,19 @@ glade_design_view_drag_data_received (GtkWidget *widget,
guint info,
guint time)
{
- GladeDesignViewPrivate *priv = GLADE_DESIGN_VIEW (widget)->priv;
- GdkAtom target = gtk_selection_data_get_target (selection);
- const GtkTargetEntry *palette_target;
+ GtkWidget *source = gtk_drag_get_source_widget (context);
+ GladeDesignView *view = GLADE_DESIGN_VIEW (widget);
+ GladeDesignViewPrivate *priv = view->priv;
- if (info == GDL_DND_INFO_WIDGET &&
- g_strcmp0 (gdk_atom_name (target), GDL_DND_TARGET_WIDGET) == 0)
- {
- const guchar *data = gtk_selection_data_get_data (selection);
-
- if (data)
- priv->drag_source = *((GtkWidget **)data);
- }
- else if (priv->palette &&
- (palette_target = gtk_tool_palette_get_drag_target_item ()) &&
- palette_target->info == info &&
- g_strcmp0 (gdk_atom_name (target), palette_target->target) == 0)
- {
- GtkWidget *item = gtk_tool_palette_get_drag_item (priv->palette, selection);
+ g_signal_handlers_disconnect_by_func (source, on_source_drag_end, view);
- if (item)
- priv->drag_adaptor = g_object_get_data (G_OBJECT (item), "glade-widget-adaptor");
- }
- else
- return;
+ g_clear_object (&priv->drag_data);
+ priv->drag_data = _glade_dnd_get_data (context, selection, info);
- g_signal_connect (gtk_drag_get_source_widget (context), "drag-end",
- G_CALLBACK (on_drag_item_drag_end),
- GLADE_DESIGN_VIEW (widget));
+ if (priv->drag_data)
+ g_object_ref (priv->drag_data);
+
+ g_signal_connect_object (source, "drag-end", G_CALLBACK (on_source_drag_end), view, 0);
}
static gboolean
@@ -657,62 +604,87 @@ glade_design_view_drag_drop (GtkWidget *widget,
guint time)
{
GladeDesignViewPrivate *priv = GLADE_DESIGN_VIEW (widget)->priv;
- GtkWidget *child;
- child = widget_get_gchild_from_position (widget, widget, x, y);
-
- if (priv->drag_source)
+ if (priv->drag_data && priv->drag_target)
{
- GladeWidget *gsource = glade_widget_get_from_gobject (priv->drag_source);
- GList widgets = {gsource, NULL, NULL};
+ GtkWidget *target;
+ gint xx, yy;
- if (GLADE_IS_PLACEHOLDER (child))
- {
- GladePlaceholder *placeholder = GLADE_PLACEHOLDER (child);
- GladeWidget *parent = glade_placeholder_get_parent (placeholder);
+ if (GLADE_IS_WIDGET (priv->drag_target))
+ target = GTK_WIDGET (glade_widget_get_object (GLADE_WIDGET (priv->drag_target)));
+ else
+ target = GTK_WIDGET (priv->drag_target);
+
+ gtk_widget_translate_coordinates (widget, target, x, y, &xx, &yy);
+ _glade_drag_drop (GLADE_DRAG (priv->drag_target), xx, yy, priv->drag_data);
+ gtk_drag_finish (context, TRUE, FALSE, time);
+ }
+ else
+ gtk_drag_finish (context, FALSE, FALSE, time);
- /* Check for recursive paste */
- if (parent != gsource)
- glade_command_dnd (&widgets, parent, placeholder);
- }
- else if (GTK_IS_FIXED (child) || GTK_IS_LAYOUT (child))
- {
- GladeWidget *parent = glade_widget_get_from_gobject (child);
+ return TRUE;
+}
- glade_command_dnd (&widgets, parent, NULL);
- }
- else if (!glade_widget_get_from_gobject (child))
- glade_command_dnd (&widgets, NULL, NULL);
+static gboolean
+glade_design_view_drag_iface_can_drop (_GladeDrag *drag,
+ gint x, gint y,
+ GObject *data)
+{
+ GladeWidget *gwidget;
+
+ if (GLADE_IS_WIDGET_ADAPTOR (data) ||
+ ((gwidget = glade_widget_get_from_gobject (data)) &&
+ glade_widget_get_parent (gwidget)))
+ return TRUE;
+ else
+ return FALSE;
+}
+
+static gboolean
+glade_design_view_drag_iface_drop (_GladeDrag *drag,
+ gint x, gint y,
+ GObject *data)
+{
+ GladeDesignViewPrivate *priv = GLADE_DESIGN_VIEW (drag)->priv;
+ GladeWidget *gsource;
+
+ if (GLADE_IS_WIDGET_ADAPTOR (data))
+ {
+ glade_command_create (GLADE_WIDGET_ADAPTOR (data),
+ NULL, NULL, priv->project);
+ return TRUE;
}
- else if (child && priv->drag_adaptor)
+ else if ((gsource = glade_widget_get_from_gobject (data)))
{
- if (GLADE_IS_PLACEHOLDER (child))
- {
- GladePlaceholder *placeholder = GLADE_PLACEHOLDER (child);
+ GList widgets = {gsource, NULL, NULL};
+ glade_command_dnd (&widgets, NULL, NULL);
+ return TRUE;
+ }
- glade_command_create (priv->drag_adaptor,
- glade_placeholder_get_parent (placeholder),
- placeholder,
- priv->project);
- }
- else if (GTK_IS_FIXED (child) || GTK_IS_LAYOUT (child))
- {
- GladeWidget *parent = glade_widget_get_from_gobject (child);
+ return FALSE;
+}
- if (parent)
- glade_command_create (priv->drag_adaptor,
- parent, NULL,
- priv->project);
- }
- else
- {
- glade_command_create (priv->drag_adaptor, NULL, NULL, priv->project);
- }
- }
+static void
+glade_design_view_drag_iface_highlight (_GladeDrag *drag, gint x, gint y)
+{
+ GladeDesignViewPrivate *priv = GLADE_DESIGN_VIEW (drag)->priv;
+ gboolean highlight = !(x < 0 || y < y);
- gtk_drag_finish (context, TRUE, FALSE, time);
+ if (priv->drag_highlight == highlight)
+ return;
+
+ priv->drag_highlight = highlight;
- return TRUE;
+ gtk_widget_queue_draw (priv->scrolled_window);
+}
+
+static void
+glade_design_view_drag_init (_GladeDragInterface *iface)
+{
+ iface->can_drag = NULL;
+ iface->can_drop = glade_design_view_drag_iface_can_drop;
+ iface->drop = glade_design_view_drag_iface_drop;
+ iface->highlight = glade_design_view_drag_iface_highlight;
}
static void
@@ -743,19 +715,11 @@ glade_design_view_class_init (GladeDesignViewClass *klass)
GLADE_TYPE_PROJECT,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY));
- g_object_class_install_property (object_class,
- PROP_DRAG_SOURCE,
- g_param_spec_object ("drag-source",
- "Drag Source",
- "A palette to use as the source of drag events for
this view",
- GTK_TYPE_TOOL_PALETTE,
- G_PARAM_READWRITE));
g_type_class_add_private (object_class, sizeof (GladeDesignViewPrivate));
}
/* Private API */
-
void
_glade_design_view_freeze (GladeDesignView *view)
{
@@ -809,44 +773,4 @@ glade_design_view_get_from_project (GladeProject *project)
p = g_object_get_data (G_OBJECT (project), GLADE_DESIGN_VIEW_KEY);
return (p != NULL) ? GLADE_DESIGN_VIEW (p) : NULL;
-
-}
-
-void
-glade_design_view_set_drag_source (GladeDesignView *view, GtkToolPalette *source)
-{
- GladeDesignViewPrivate *priv;
- GtkWidget *target;
-
- g_return_if_fail (GLADE_IS_DESIGN_VIEW (view));
- priv = view->priv;
-
- if (priv->palette == source)
- return;
-
- if (priv->palette)
- gtk_drag_dest_unset (GTK_WIDGET (priv->palette));
-
- target = GTK_WIDGET (view);
- priv->palette = source;
-
- gtk_drag_dest_set (target, 0, NULL, 0, GDK_ACTION_COPY);
-
- if (priv->palette)
- {
- GtkTargetEntry targets[2];
- GtkTargetList *list;
-
- gtk_tool_palette_add_drag_dest (priv->palette, target, 0,
- GTK_TOOL_PALETTE_DRAG_ITEMS,
- GDK_ACTION_COPY);
-
- targets[0] = *gtk_tool_palette_get_drag_target_item ();
- targets[1] = *_glade_design_layout_get_dnd_target ();
-
- list = gtk_target_list_new (targets, 2);
- gtk_drag_dest_set_target_list (target, list);
-
- gtk_target_list_unref (list);
- }
}
diff --git a/gladeui/glade-design-view.h b/gladeui/glade-design-view.h
index 950ec45..733c748 100644
--- a/gladeui/glade-design-view.h
+++ b/gladeui/glade-design-view.h
@@ -69,9 +69,6 @@ GladeProject *glade_design_view_get_project (GladeDesignView *view);
GladeDesignView *glade_design_view_get_from_project (GladeProject *project);
-void glade_design_view_set_drag_source (GladeDesignView *view,
- GtkToolPalette *source);
-
G_END_DECLS
#endif /* __GLADE_DESIGN_VIEW_H__ */
diff --git a/gladeui/glade-dnd.c b/gladeui/glade-dnd.c
new file mode 100644
index 0000000..122d74d
--- /dev/null
+++ b/gladeui/glade-dnd.c
@@ -0,0 +1,174 @@
+/*
+ * glade-dnd.c
+ *
+ * Copyright (C) 2013 Juan Pablo Ugarte
+ *
+ * Authors:
+ * Juan Pablo Ugarte <juanpablougarte gmail com>
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "glade.h"
+#include "glade-dnd.h"
+
+GtkTargetEntry *
+_glade_dnd_get_target (void)
+{
+ static GtkTargetEntry target = {GLADE_DND_TARGET_DATA, GTK_TARGET_SAME_APP, GLADE_DND_INFO_DATA};
+ return ⌖
+}
+
+void
+_glade_dnd_dest_set (GtkWidget *target)
+{
+ GtkTargetEntry targets[1];
+
+ targets[0] = *_glade_dnd_get_target ();
+
+ gtk_drag_dest_set (target, 0, targets, 2, GDK_ACTION_COPY);
+}
+
+GObject *
+_glade_dnd_get_data (GdkDragContext *context,
+ GtkSelectionData *selection,
+ guint info)
+{
+ GdkAtom target = gtk_selection_data_get_target (selection);
+
+ if (info == GLADE_DND_INFO_DATA &&
+ g_strcmp0 (gdk_atom_name (target), GLADE_DND_TARGET_DATA) == 0)
+ {
+ const guchar *data = gtk_selection_data_get_data (selection);
+ if (data)
+ return *((GObject **)data);
+ }
+ return NULL;
+}
+
+
+void
+_glade_dnd_set_data (GtkSelectionData *selection, GObject *data)
+{
+ static GdkAtom type = 0;
+
+ if (!type)
+ type = gdk_atom_intern_static_string (GLADE_DND_TARGET_DATA);
+
+ gtk_selection_data_set (selection, type, sizeof (gpointer),
+ (const guchar *)&data,
+ sizeof (gpointer));
+}
+
+static gboolean
+on_drag_icon_draw (GtkWidget *widget, cairo_t *cr)
+{
+ GtkStyleContext *context = gtk_widget_get_style_context (widget);
+ cairo_pattern_t *gradient;
+ GtkAllocation alloc;
+ gint x, y, w, h;
+ gdouble h2;
+ GdkRGBA bg;
+
+ /* Not needed acording to GtkWidget:draw documentation
+ * But seems like there is a bug when used as a drag_icon that makes the
+ * cairo translation used here persist when drawing children.
+ */
+ cairo_save (cr);
+
+ /* Clear BG */
+ cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
+ cairo_paint (cr);
+ cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
+
+ gtk_widget_get_allocation (widget, &alloc);
+ x = alloc.x;
+ y = alloc.y;
+ w = alloc.width;
+ h = alloc.height;
+ h2 = h/2.0;
+
+ gtk_style_context_get_background_color (context, GTK_STATE_NORMAL, &bg);
+
+ gradient = cairo_pattern_create_linear (x, y, x, y+h);
+ cairo_pattern_add_color_stop_rgba (gradient, 0, bg.red, bg.green, bg.blue, 0);
+ cairo_pattern_add_color_stop_rgba (gradient, .5, bg.red, bg.green, bg.blue, .8);
+ cairo_pattern_add_color_stop_rgba (gradient, 1, bg.red, bg.green, bg.blue, 0);
+
+ cairo_set_source (cr, gradient);
+ cairo_rectangle (cr, x+h2, y, w-h, h);
+ cairo_fill (cr);
+ cairo_pattern_destroy (gradient);
+
+ gradient = cairo_pattern_create_radial (x+h2, y+h2, 0, x+h2, y+h2, h2);
+ cairo_pattern_add_color_stop_rgba (gradient, 0, bg.red, bg.green, bg.blue, .8);
+ cairo_pattern_add_color_stop_rgba (gradient, 1, bg.red, bg.green, bg.blue, 0);
+
+ cairo_set_source (cr, gradient);
+ cairo_rectangle (cr, x, y, h2, h);
+ cairo_fill (cr);
+
+ cairo_translate (cr, w-h, 0);
+ cairo_set_source (cr, gradient);
+ cairo_rectangle (cr, x+h2, y, h2, h);
+ cairo_fill (cr);
+
+ cairo_pattern_destroy (gradient);
+ cairo_restore (cr);
+
+ return FALSE;
+}
+
+void
+_glade_dnd_set_icon_widget (GdkDragContext *context,
+ const gchar *icon_name,
+ const gchar *description)
+{
+ GtkWidget *window, *box, *label, *icon;
+ GdkScreen *screen;
+ GdkVisual *visual;
+
+ screen = gdk_window_get_screen (gdk_drag_context_get_source_window (context));
+ window = gtk_window_new (GTK_WINDOW_POPUP);
+
+ gtk_window_set_type_hint (GTK_WINDOW (window), GDK_WINDOW_TYPE_HINT_DND);
+ gtk_window_set_screen (GTK_WINDOW (window), screen);
+
+ box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 4);
+ gtk_container_set_border_width (GTK_CONTAINER (box), 12);
+
+ icon = gtk_image_new_from_icon_name (icon_name, GTK_ICON_SIZE_BUTTON);
+ gtk_widget_set_opacity (icon, .8);
+
+ label = gtk_label_new (description);
+
+ gtk_box_pack_start (GTK_BOX (box), icon, FALSE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (box), label, FALSE, TRUE, 0);
+
+ gtk_widget_show_all (box);
+ gtk_container_add (GTK_CONTAINER (window), box);
+
+ if ((visual = gdk_screen_get_rgba_visual (screen)))
+ {
+ gtk_widget_set_visual (window, visual);
+ gtk_widget_set_app_paintable (window, TRUE);
+ g_signal_connect (window, "draw", G_CALLBACK (on_drag_icon_draw), NULL);
+ }
+
+ g_object_ref_sink (window);
+ gtk_drag_set_icon_widget (context, window, 0, 0);
+ g_object_unref (window);
+}
diff --git a/gladeui/glade-dnd.h b/gladeui/glade-dnd.h
new file mode 100644
index 0000000..2101618
--- /dev/null
+++ b/gladeui/glade-dnd.h
@@ -0,0 +1,52 @@
+/*
+ * glade-dnd.h
+ *
+ * Copyright (C) 2013 Juan Pablo Ugarte
+ *
+ * Authors:
+ * Juan Pablo Ugarte <juanpablougarte gmail com>
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef __GLADE_DND_H__
+#define __GLADE_DND_H__
+
+#define GLADE_DND_INFO_DATA 96323
+#define GLADE_DND_TARGET_DATA "glade/x-drag-data"
+
+#include "glade-drag.h"
+
+G_BEGIN_DECLS
+
+GtkTargetEntry *_glade_dnd_get_target (void);
+
+void _glade_dnd_dest_set (GtkWidget *target);
+
+void _glade_dnd_set_data (GtkSelectionData *selection,
+ GObject *data);
+
+GObject *_glade_dnd_get_data (GdkDragContext *context,
+ GtkSelectionData *selection,
+ guint info);
+
+void _glade_dnd_set_icon_widget (GdkDragContext *context,
+ const gchar *icon_name,
+ const gchar *description);
+
+G_END_DECLS
+
+#endif /* __GLADE_DND_H__ */
diff --git a/gladeui/glade-drag.c b/gladeui/glade-drag.c
new file mode 100644
index 0000000..248467c
--- /dev/null
+++ b/gladeui/glade-drag.c
@@ -0,0 +1,86 @@
+/*
+ * glade-drag.c
+ *
+ * Copyright (C) 2013 Juan Pablo Ugarte
+ *
+ * Authors:
+ * Juan Pablo Ugarte <juanpablougarte gmail com>
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "glade-drag.h"
+
+G_DEFINE_INTERFACE (_GladeDrag, _glade_drag, G_TYPE_OBJECT);
+
+static void
+_glade_drag_default_init (_GladeDragInterface *iface)
+{
+}
+
+gboolean
+_glade_drag_can_drag (_GladeDrag *source)
+{
+ _GladeDragInterface *iface;
+
+ g_return_val_if_fail (GLADE_IS_DRAG (source), FALSE);
+ iface = GLADE_DRAG_GET_INTERFACE (source);
+
+ if (iface->can_drag)
+ return iface->can_drag (source);
+ else
+ return FALSE;
+}
+
+gboolean
+_glade_drag_can_drop (_GladeDrag *dest, gint x, gint y, GObject *data)
+{
+ _GladeDragInterface *iface;
+
+ g_return_val_if_fail (GLADE_IS_DRAG (dest), FALSE);
+ iface = GLADE_DRAG_GET_INTERFACE (dest);
+
+ if (iface->can_drop)
+ return iface->can_drop (dest, x, y, data);
+ else
+ return FALSE;
+}
+
+gboolean
+_glade_drag_drop (_GladeDrag *dest, gint x, gint y, GObject *data)
+{
+ _GladeDragInterface *iface;
+
+ g_return_val_if_fail (GLADE_IS_DRAG (dest), FALSE);
+ iface = GLADE_DRAG_GET_INTERFACE (dest);
+
+ if (iface->drop)
+ return iface->drop (dest, x, y, data);
+ else
+ return FALSE;
+}
+
+void
+_glade_drag_highlight (_GladeDrag *dest, gint x, gint y)
+{
+ _GladeDragInterface *iface;
+
+ g_return_if_fail (GLADE_IS_DRAG (dest));
+ iface = GLADE_DRAG_GET_INTERFACE (dest);
+
+ if (iface->highlight)
+ iface->highlight (dest, x, y);
+}
diff --git a/gladeui/glade-drag.h b/gladeui/glade-drag.h
new file mode 100644
index 0000000..85903f7
--- /dev/null
+++ b/gladeui/glade-drag.h
@@ -0,0 +1,81 @@
+/*
+ * glade-drag.h
+ *
+ * Copyright (C) 2013 Juan Pablo Ugarte
+ *
+ * Authors:
+ * Juan Pablo Ugarte <juanpablougarte gmail com>
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef _GLADE_DRAG_H_
+#define _GLADE_DRAG_H_
+
+#include "glade-widget-adaptor.h"
+
+G_BEGIN_DECLS
+
+#define GLADE_TYPE_DRAG (_glade_drag_get_type ())
+#define GLADE_DRAG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GLADE_TYPE_DRAG, _GladeDrag))
+#define GLADE_IS_DRAG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GLADE_TYPE_DRAG))
+#define GLADE_DRAG_GET_INTERFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), GLADE_TYPE_DRAG,
_GladeDragInterface))
+
+typedef struct __GladeDrag _GladeDrag;
+typedef struct __GladeDragInterface _GladeDragInterface;
+
+struct __GladeDragInterface
+{
+ GTypeInterface parent_instance;
+
+ gboolean (*can_drag) (_GladeDrag *source);
+
+ gboolean (*can_drop) (_GladeDrag *dest,
+ gint x,
+ gint y,
+ GObject *data);
+
+ gboolean (*drop) (_GladeDrag *dest,
+ gint x,
+ gint y,
+ GObject *data);
+
+ void (*highlight) (_GladeDrag *dest,
+ gint x,
+ gint y);
+};
+
+GType _glade_drag_get_type (void) G_GNUC_CONST;
+
+gboolean _glade_drag_can_drag (_GladeDrag *source);
+
+gboolean _glade_drag_can_drop (_GladeDrag *dest,
+ gint x,
+ gint y,
+ GObject *data);
+
+gboolean _glade_drag_drop (_GladeDrag *dest,
+ gint x,
+ gint y,
+ GObject *data);
+
+void _glade_drag_highlight (_GladeDrag *dest,
+ gint x,
+ gint y);
+
+G_END_DECLS
+
+#endif /* _GLADE_DRAG_DEST_H_ */
diff --git a/gladeui/glade-inspector.c b/gladeui/glade-inspector.c
index 75274be..9475f7f 100644
--- a/gladeui/glade-inspector.c
+++ b/gladeui/glade-inspector.c
@@ -43,6 +43,7 @@
#include "glade-inspector.h"
#include "glade-popup.h"
#include "glade-app.h"
+#include "glade-dnd.h"
#include <string.h>
#include <glib/gi18n-lib.h>
@@ -604,6 +605,11 @@ glade_inspector_init (GladeInspector *inspector)
gtk_scrollable_set_hscroll_policy (GTK_SCROLLABLE (priv->view), GTK_SCROLL_MINIMUM);
add_columns (GTK_TREE_VIEW (priv->view));
+ /* Set it as a drag source */
+ gtk_tree_view_enable_model_drag_source (GTK_TREE_VIEW (priv->view),
+ GDK_BUTTON1_MASK,
+ _glade_dnd_get_target (), 1, 0);
+
g_signal_connect (G_OBJECT (priv->view), "row-activated",
G_CALLBACK (item_activated_cb), inspector);
diff --git a/gladeui/glade-palette.c b/gladeui/glade-palette.c
index 811f935..cb3263f 100644
--- a/gladeui/glade-palette.c
+++ b/gladeui/glade-palette.c
@@ -47,6 +47,7 @@
#include "glade-widget-adaptor.h"
#include "glade-popup.h"
#include "glade-design-private.h"
+#include "glade-dnd.h"
#include <glib/gi18n-lib.h>
#include <gdk/gdk.h>
@@ -271,28 +272,24 @@ palette_item_toggled_cb (GtkToggleToolButton *button, GladePalette *palette)
}
static void
-glade_palette_drag_end (GtkWidget *widget,
- GdkDragContext *context,
- GtkWidget *drag_icon)
-{
- g_object_unref (drag_icon);
- g_signal_handlers_disconnect_by_func (widget, glade_palette_drag_end, drag_icon);
-}
-
-static void
glade_palette_drag_begin (GtkWidget *widget,
GdkDragContext *context,
GladeWidgetAdaptor *adaptor)
{
- GtkWidget *drag_icon;
+ _glade_dnd_set_icon_widget (context,
+ glade_widget_adaptor_get_icon_name (adaptor),
+ glade_widget_adaptor_get_name (adaptor));
+}
- drag_icon = _glade_design_layout_dnd_icon_widget_new (context,
- glade_widget_adaptor_get_icon_name (adaptor),
- glade_widget_adaptor_get_name (adaptor));
- g_object_ref_sink (drag_icon);
- gtk_drag_set_icon_widget (context, drag_icon, 0, 0);
- g_signal_connect_object (widget, "drag-end",
- G_CALLBACK (glade_palette_drag_end), drag_icon, 0);
+static void
+glade_palette_drag_data_get (GtkWidget *widget,
+ GdkDragContext *context,
+ GtkSelectionData *data,
+ guint info,
+ guint time,
+ GladeWidgetAdaptor *adaptor)
+{
+ _glade_dnd_set_data (data, G_OBJECT (adaptor));
}
static gint
@@ -350,6 +347,11 @@ glade_palette_new_item (GladePalette * palette, GladeWidgetAdaptor * adaptor)
G_CALLBACK (palette_item_button_press_cb), item);
g_signal_connect_object (button, "drag-begin",
G_CALLBACK (glade_palette_drag_begin), adaptor, 0);
+ g_signal_connect_object (button, "drag-data-get",
+ G_CALLBACK (glade_palette_drag_data_get), adaptor, 0);
+
+ gtk_drag_source_set (button, GDK_BUTTON1_MASK, _glade_dnd_get_target (), 1, 0);
+
gtk_widget_show (item);
g_hash_table_insert (palette->priv->button_table,
diff --git a/gladeui/glade-placeholder.c b/gladeui/glade-placeholder.c
index 8eca99d..1b6dc82 100644
--- a/gladeui/glade-placeholder.c
+++ b/gladeui/glade-placeholder.c
@@ -47,37 +47,12 @@
#include "glade-app.h"
#include <math.h>
+#include "glade-dnd.h"
+#include "glade-drag.h"
+
#define WIDTH_REQUISITION 20
#define HEIGHT_REQUISITION 20
-static void glade_placeholder_finalize (GObject *object);
-static void glade_placeholder_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec);
-static void glade_placeholder_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec);
-static void glade_placeholder_realize (GtkWidget *widget);
-static void glade_placeholder_unrealize (GtkWidget *widget);
-static void glade_placeholder_map (GtkWidget *widget);
-static void glade_placeholder_unmap (GtkWidget *widget);
-
-static void glade_placeholder_size_allocate (GtkWidget *widget,
- GtkAllocation *allocation);
-
-static gboolean glade_placeholder_draw (GtkWidget *widget, cairo_t *cr);
-
-static gboolean glade_placeholder_motion_notify_event (GtkWidget *widget,
- GdkEventMotion *event);
-
-static gboolean glade_placeholder_button_press (GtkWidget *widget,
- GdkEventButton *event);
-
-static gboolean glade_placeholder_popup_menu (GtkWidget *widget);
-
-
static cairo_pattern_t *placeholder_pattern = NULL;
struct _GladePlaceholderPrivate
@@ -85,6 +60,8 @@ struct _GladePlaceholderPrivate
GList *packing_actions;
GdkWindow *event_window;
+
+ gboolean drag_highlight;
};
enum
@@ -99,56 +76,14 @@ enum
#define GLADE_PLACEHOLDER_GET_PRIVATE(object) (G_TYPE_INSTANCE_GET_PRIVATE ((object), \
GLADE_TYPE_PLACEHOLDER, \
GladePlaceholderPrivate))
+#define GLADE_PLACEHOLDER_PRIVATE(object) (((GladePlaceholder*)object)->priv)
-G_DEFINE_TYPE_WITH_CODE (GladePlaceholder, glade_placeholder, GTK_TYPE_WIDGET,
- G_IMPLEMENT_INTERFACE (GTK_TYPE_SCROLLABLE, NULL))
-
-static void glade_placeholder_class_init (GladePlaceholderClass *klass)
-{
- GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
- gchar *path;
- cairo_surface_t *surface;
-
- object_class->finalize = glade_placeholder_finalize;
- object_class->set_property = glade_placeholder_set_property;
- object_class->get_property = glade_placeholder_get_property;
-
- widget_class->realize = glade_placeholder_realize;
- widget_class->unrealize = glade_placeholder_unrealize;
- widget_class->map = glade_placeholder_map;
- widget_class->unmap = glade_placeholder_unmap;
- widget_class->size_allocate = glade_placeholder_size_allocate;
- widget_class->draw = glade_placeholder_draw;
- widget_class->motion_notify_event = glade_placeholder_motion_notify_event;
- widget_class->button_press_event = glade_placeholder_button_press;
- widget_class->popup_menu = glade_placeholder_popup_menu;
-
- /* GtkScrollable implementation */
- g_object_class_override_property (object_class, PROP_HADJUSTMENT,
- "hadjustment");
- g_object_class_override_property (object_class, PROP_VADJUSTMENT,
- "vadjustment");
- g_object_class_override_property (object_class, PROP_HSCROLL_POLICY,
- "hscroll-policy");
- g_object_class_override_property (object_class, PROP_VSCROLL_POLICY,
- "vscroll-policy");
-
- /* Create our tiled background pattern */
- path = g_build_filename (glade_app_get_pixmaps_dir (), "placeholder.png", NULL);
- surface = cairo_image_surface_create_from_png (path);
-
- if (!surface)
- g_warning ("Failed to create surface for %s\n", path);
- else
- {
- placeholder_pattern = cairo_pattern_create_for_surface (surface);
- cairo_pattern_set_extend (placeholder_pattern, CAIRO_EXTEND_REPEAT);
- }
- g_free (path);
+static void glade_placeholder_drag_init (_GladeDragInterface *iface);
- g_type_class_add_private (klass, sizeof (GladePlaceholderPrivate));
-}
+G_DEFINE_TYPE_WITH_CODE (GladePlaceholder, glade_placeholder, GTK_TYPE_WIDGET,
+ G_IMPLEMENT_INTERFACE (GTK_TYPE_SCROLLABLE, NULL)
+ G_IMPLEMENT_INTERFACE (GLADE_TYPE_DRAG,
+ glade_placeholder_drag_init))
static void
glade_placeholder_notify_parent (GObject *gobject,
@@ -188,6 +123,8 @@ glade_placeholder_init (GladePlaceholder *placeholder)
gtk_widget_set_size_request (GTK_WIDGET (placeholder),
WIDTH_REQUISITION, HEIGHT_REQUISITION);
+ _glade_dnd_dest_set (GTK_WIDGET (placeholder));
+
g_signal_connect (placeholder, "notify::parent",
G_CALLBACK (glade_placeholder_notify_parent), NULL);
@@ -360,6 +297,7 @@ glade_placeholder_size_allocate (GtkWidget *widget, GtkAllocation *allocation)
static gboolean
glade_placeholder_draw (GtkWidget *widget, cairo_t *cr)
{
+ GladePlaceholder *placeholder = GLADE_PLACEHOLDER (widget);
gint h = gtk_widget_get_allocated_height (widget) - 1;
gint w = gtk_widget_get_allocated_width (widget) - 1;
@@ -388,6 +326,32 @@ glade_placeholder_draw (GtkWidget *widget, cairo_t *cr)
cairo_line_to (cr, 0, h);
cairo_stroke (cr);
+ if (placeholder->priv->drag_highlight)
+ {
+ cairo_pattern_t *gradient;
+ GtkStyleContext *context;
+ gdouble ww, hh;
+ GdkRGBA c;
+
+ context = gtk_widget_get_style_context (widget);
+ gtk_style_context_get_background_color (context, GTK_STATE_FLAG_SELECTED |
+ GTK_STATE_FLAG_FOCUSED, &c);
+
+ ww = w/2.0;
+ hh = h/2.0;
+ gradient = cairo_pattern_create_radial (ww, hh, MIN (w, h)/6,
+ ww, hh, MAX (ww, hh));
+ cairo_pattern_add_color_stop_rgba (gradient, 0, c.red, c.green, c.blue, .08);
+ cairo_pattern_add_color_stop_rgba (gradient, 1, c.red, c.green, c.blue, .28);
+
+ cairo_set_source (cr, gradient);
+
+ cairo_rectangle (cr, 0, 0, w, h);
+ cairo_fill (cr);
+
+ cairo_pattern_destroy (gradient);
+ }
+
return FALSE;
}
@@ -465,6 +429,145 @@ glade_placeholder_popup_menu (GtkWidget *widget)
return TRUE;
}
+static gboolean
+glade_placeholder_drag_can_drag (_GladeDrag *source)
+{
+ GladeWidget *parent = glade_placeholder_get_parent (GLADE_PLACEHOLDER (source));
+ return (parent) ? _glade_drag_can_drag (GLADE_DRAG (parent)) : FALSE;
+}
+
+static gboolean
+glade_placeholder_drag_can_drop (_GladeDrag *dest, gint x, gint y, GObject *data)
+{
+ if (GLADE_IS_WIDGET_ADAPTOR (data))
+ {
+ GType otype = glade_widget_adaptor_get_object_type (GLADE_WIDGET_ADAPTOR (data));
+
+ if (g_type_is_a (otype, GTK_TYPE_WIDGET) && !GWA_IS_TOPLEVEL (data))
+ return TRUE;
+ }
+ else if (GTK_IS_WIDGET (data))
+ {
+ GladeWidget *parent, *new_child;
+
+ /* Avoid recursion */
+ if (gtk_widget_is_ancestor (GTK_WIDGET (dest), GTK_WIDGET (data)))
+ return FALSE;
+
+ parent = glade_placeholder_get_parent (GLADE_PLACEHOLDER (dest));
+
+ if ((new_child = glade_widget_get_from_gobject (data)) &&
+ !glade_widget_add_verify (parent, new_child, FALSE))
+ return FALSE;
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gboolean
+glade_placeholder_drag_drop (_GladeDrag *dest, gint x, gint y, GObject *data)
+{
+ GladePlaceholder *placeholder = GLADE_PLACEHOLDER (dest);
+ GladeWidget *gsource;
+
+ if (!data)
+ return FALSE;
+
+ if (GLADE_IS_WIDGET_ADAPTOR (data))
+ {
+ GladeWidget *parent = glade_placeholder_get_parent (placeholder);
+
+ glade_command_create (GLADE_WIDGET_ADAPTOR (data), parent, placeholder,
+ glade_widget_get_project (parent));
+ return TRUE;
+ }
+ else if ((gsource = glade_widget_get_from_gobject (data)))
+ {
+ GladeWidget *parent = glade_placeholder_get_parent (placeholder);
+ GList widgets = {gsource, NULL, NULL};
+
+ /* Check for recursive paste */
+ if (parent != gsource)
+ {
+ glade_command_dnd (&widgets, parent, placeholder);
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+static void
+glade_placeholder_drag_highlight (_GladeDrag *dest, gint x, gint y)
+{
+ GladePlaceholderPrivate *priv = GLADE_PLACEHOLDER (dest)->priv;
+ gboolean highlight = !(x < 0 || y < 0);
+
+ if (priv->drag_highlight == highlight)
+ return;
+
+ priv->drag_highlight = highlight;
+ gtk_widget_queue_draw (GTK_WIDGET (dest));
+}
+
+static void
+glade_placeholder_drag_init (_GladeDragInterface *iface)
+{
+ iface->can_drag = glade_placeholder_drag_can_drag;
+ iface->can_drop = glade_placeholder_drag_can_drop;
+ iface->drop = glade_placeholder_drag_drop;
+ iface->highlight = glade_placeholder_drag_highlight;
+}
+
+static void
+glade_placeholder_class_init (GladePlaceholderClass *klass)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ gchar *path;
+ cairo_surface_t *surface;
+
+ object_class->finalize = glade_placeholder_finalize;
+ object_class->set_property = glade_placeholder_set_property;
+ object_class->get_property = glade_placeholder_get_property;
+
+ widget_class->realize = glade_placeholder_realize;
+ widget_class->unrealize = glade_placeholder_unrealize;
+ widget_class->map = glade_placeholder_map;
+ widget_class->unmap = glade_placeholder_unmap;
+ widget_class->size_allocate = glade_placeholder_size_allocate;
+ widget_class->draw = glade_placeholder_draw;
+ widget_class->motion_notify_event = glade_placeholder_motion_notify_event;
+ widget_class->button_press_event = glade_placeholder_button_press;
+ widget_class->popup_menu = glade_placeholder_popup_menu;
+
+ /* GtkScrollable implementation */
+ g_object_class_override_property (object_class, PROP_HADJUSTMENT,
+ "hadjustment");
+ g_object_class_override_property (object_class, PROP_VADJUSTMENT,
+ "vadjustment");
+ g_object_class_override_property (object_class, PROP_HSCROLL_POLICY,
+ "hscroll-policy");
+ g_object_class_override_property (object_class, PROP_VSCROLL_POLICY,
+ "vscroll-policy");
+
+ /* Create our tiled background pattern */
+ path = g_build_filename (glade_app_get_pixmaps_dir (), "placeholder.png", NULL);
+ surface = cairo_image_surface_create_from_png (path);
+
+ if (!surface)
+ g_warning ("Failed to create surface for %s\n", path);
+ else
+ {
+ placeholder_pattern = cairo_pattern_create_for_surface (surface);
+ cairo_pattern_set_extend (placeholder_pattern, CAIRO_EXTEND_REPEAT);
+ }
+ g_free (path);
+
+ g_type_class_add_private (klass, sizeof (GladePlaceholderPrivate));
+}
/**
* glade_placeholder_new:
diff --git a/gladeui/glade-project.c b/gladeui/glade-project.c
index 31d8b72..5d8d9ef 100644
--- a/gladeui/glade-project.c
+++ b/gladeui/glade-project.c
@@ -53,6 +53,7 @@
#include "glade-name-context.h"
#include "glade-object-stub.h"
#include "glade-project-properties.h"
+#include "glade-dnd.h"
static void glade_project_target_version_for_adaptor
(GladeProject *project,
@@ -80,6 +81,7 @@ static void glade_project_model_get_iter_for_object
GtkTreeIter *iter);
static gint glade_project_count_children (GladeProject *project,
GladeWidget *parent);
+static void glade_project_drag_source_init (GtkTreeDragSourceIface *iface);
struct _GladeProjectPrivate
{
@@ -207,7 +209,9 @@ static GladeIDAllocator *unsaved_number_allocator = NULL;
G_DEFINE_TYPE_WITH_CODE (GladeProject, glade_project, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_MODEL,
- glade_project_model_iface_init))
+ glade_project_model_iface_init)
+ G_IMPLEMENT_INTERFACE (GTK_TYPE_TREE_DRAG_SOURCE,
+ glade_project_drag_source_init))
/*******************************************************************
@@ -1449,6 +1453,48 @@ glade_project_model_iface_init (GtkTreeModelIface *iface)
iface->iter_parent = glade_project_model_iter_parent;
}
+static gboolean
+glade_project_row_draggable (GtkTreeDragSource *drag_source, GtkTreePath *path)
+{
+ return TRUE;
+}
+
+static gboolean
+glade_project_drag_data_delete (GtkTreeDragSource *drag_source, GtkTreePath *path)
+{
+ return FALSE;
+}
+
+static gboolean
+glade_project_drag_data_get (GtkTreeDragSource *drag_source,
+ GtkTreePath *path,
+ GtkSelectionData *selection_data)
+{
+ GtkTreeIter iter;
+
+ if (gtk_tree_model_get_iter (GTK_TREE_MODEL (drag_source), &iter, path))
+ {
+ GObject *object;
+
+ gtk_tree_model_get (GTK_TREE_MODEL (drag_source), &iter,
+ GLADE_PROJECT_MODEL_COLUMN_OBJECT, &object,
+ -1);
+
+ _glade_dnd_set_data (selection_data, object);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void
+glade_project_drag_source_init (GtkTreeDragSourceIface *iface)
+{
+ iface->row_draggable = glade_project_row_draggable;
+ iface->drag_data_delete = glade_project_drag_data_delete;
+ iface->drag_data_get = glade_project_drag_data_get;
+}
+
/*******************************************************************
Loading project code here
*******************************************************************/
diff --git a/gladeui/glade-widget.c b/gladeui/glade-widget.c
index d585939..fe62fda 100644
--- a/gladeui/glade-widget.c
+++ b/gladeui/glade-widget.c
@@ -57,6 +57,7 @@
#include "glade-widget-action.h"
#include "glade-signal-model.h"
#include "glade-object-stub.h"
+#include "glade-dnd.h"
static void glade_widget_set_adaptor (GladeWidget * widget,
GladeWidgetAdaptor * adaptor);
@@ -203,7 +204,12 @@ static guint glade_widget_signals[LAST_SIGNAL] = { 0 };
static GQuark glade_widget_name_quark = 0;
-G_DEFINE_TYPE (GladeWidget, glade_widget, G_TYPE_INITIALLY_UNOWNED)
+static void glade_widget_drag_init (_GladeDragInterface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (GladeWidget, glade_widget, G_TYPE_INITIALLY_UNOWNED,
+ G_IMPLEMENT_INTERFACE (GLADE_TYPE_DRAG,
+ glade_widget_drag_init))
+
/*******************************************************************************
GladeWidget class methods
*******************************************************************************/
@@ -1215,6 +1221,100 @@ glade_widget_init (GladeWidget * widget)
widget->priv->height = -1;
}
+static gboolean
+glade_widget_drag_can_drag (_GladeDrag *source)
+{
+ g_return_val_if_fail (GLADE_IS_DRAG (source), FALSE);
+
+ return GLADE_WIDGET (source)->priv->internal == NULL;
+}
+
+static gboolean
+glade_widget_drag_can_drop (_GladeDrag *dest, gint x, gint y, GObject *data)
+{
+ GObject *object;
+
+ g_return_val_if_fail (GLADE_IS_DRAG (dest), FALSE);
+
+ object = GLADE_WIDGET (dest)->priv->object;
+
+ if (!(GTK_IS_FIXED (object) ||
+ GTK_IS_LAYOUT (object) ||
+ GTK_IS_OVERLAY (object)))
+ return FALSE;
+
+ if (GLADE_IS_WIDGET_ADAPTOR (data))
+ {
+ GType otype = glade_widget_adaptor_get_object_type (GLADE_WIDGET_ADAPTOR (data));
+
+ if (g_type_is_a (otype, GTK_TYPE_WIDGET) && !GWA_IS_TOPLEVEL (data))
+ return TRUE;
+ }
+ else
+ {
+ GladeWidget *new_child, *parent = GLADE_WIDGET (dest);
+ GObject *object = glade_widget_get_object (parent);
+
+ if (object == data)
+ return FALSE;
+
+ if (GTK_IS_WIDGET (data) && GTK_IS_WIDGET (object) &&
+ gtk_widget_is_ancestor (GTK_WIDGET (data), GTK_WIDGET (object)))
+ return FALSE;
+
+ if ((new_child = glade_widget_get_from_gobject (data)) &&
+ (!glade_widget_add_verify (parent, new_child, FALSE) ||
+ glade_widget_placeholder_relation (parent, new_child)))
+ return FALSE;
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gboolean
+glade_widget_drag_drop (_GladeDrag *dest, gint x, gint y, GObject *data)
+{
+ GladeWidget *gsource;
+
+ g_return_val_if_fail (GLADE_IS_DRAG (dest), FALSE);
+
+ if (!data)
+ return FALSE;
+
+ if (GLADE_IS_WIDGET_ADAPTOR (data))
+ {
+ GladeWidget *parent = GLADE_WIDGET (dest);
+
+ glade_command_create (GLADE_WIDGET_ADAPTOR (data), parent, NULL,
+ glade_widget_get_project (parent));
+ return TRUE;
+ }
+ else if ((gsource = glade_widget_get_from_gobject (data)))
+ {
+ GladeWidget *parent = GLADE_WIDGET (dest);
+ GList widgets = {gsource, NULL, NULL};
+
+ /* Check for recursive paste */
+ if (parent != gsource)
+ {
+ glade_command_dnd (&widgets, parent, NULL);
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+static void
+glade_widget_drag_init (_GladeDragInterface *iface)
+{
+ iface->can_drag = glade_widget_drag_can_drag;
+ iface->can_drop = glade_widget_drag_can_drop;
+ iface->drop = glade_widget_drag_drop;
+}
+
static void
glade_widget_class_init (GladeWidgetClass * klass)
{
diff --git a/plugins/gtk+/glade-gtk-overlay.c b/plugins/gtk+/glade-gtk-overlay.c
index c509135..8ccd3dc 100644
--- a/plugins/gtk+/glade-gtk-overlay.c
+++ b/plugins/gtk+/glade-gtk-overlay.c
@@ -119,11 +119,12 @@ glade_gtk_overlay_post_create (GladeWidgetAdaptor *adaptor,
GObject *object,
GladeCreateReason reason)
{
+ GladeWidget *widget = glade_widget_get_from_gobject (object);
+
if (reason == GLADE_CREATE_USER)
gtk_container_add (GTK_CONTAINER (object), glade_placeholder_new ());
- on_widget_project_notify (G_OBJECT (glade_widget_get_from_gobject (object)),
- NULL, NULL);
+ on_widget_project_notify (G_OBJECT (widget), NULL, NULL);
}
gboolean
diff --git a/src/glade-window.c b/src/glade-window.c
index 25f9e49..8fdf4fa 100644
--- a/src/glade-window.c
+++ b/src/glade-window.c
@@ -1813,8 +1813,6 @@ on_notebook_tab_added (GtkNotebook *notebook,
gtk_radio_action_get_current_value (GTK_RADIO_ACTION
(priv->icons_and_labels_radioaction)));
gtk_notebook_append_page (window->priv->palettes_notebook, palette, NULL);
-
- glade_design_view_set_drag_source (view, glade_palette_get_tool_palette (GLADE_PALETTE (palette)));
if (GPOINTER_TO_INT
(g_object_get_data (G_OBJECT (view), "view-added-while-loading")))
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]