summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJuan Pablo Ugarte <juanpablougarte@gmail.com>2012-12-13 18:58:47 -0300
committerJuan Pablo Ugarte <juanpablougarte@gmail.com>2013-01-18 20:11:03 -0300
commit248964acf59f004e0a284760a24bde325528b4e0 (patch)
tree8b76f82948018d7d6f702385aeaa1d5af82995f0
parent7e0d65bdd6e294eb4247f2690bd4dc2283ad10b0 (diff)
downloadglade-248964acf59f004e0a284760a24bde325528b4e0.tar.gz
Added Drag&Drop support from the palette.
-rw-r--r--gladeui/glade-design-view.c196
-rw-r--r--gladeui/glade-design-view.h3
-rw-r--r--gladeui/glade-palette.c27
-rw-r--r--gladeui/glade-palette.h2
-rw-r--r--src/glade-window.c2
5 files changed, 224 insertions, 6 deletions
diff --git a/gladeui/glade-design-view.c b/gladeui/glade-design-view.c
index eef800d4..aae16ff4 100644
--- a/gladeui/glade-design-view.c
+++ b/gladeui/glade-design-view.c
@@ -52,6 +52,7 @@ enum
{
PROP_0,
PROP_PROJECT,
+ PROP_DRAG_SOURCE
};
struct _GladeDesignViewPrivate
@@ -59,6 +60,9 @@ struct _GladeDesignViewPrivate
GladeProject *project;
GtkWidget *scrolled_window; /* Main scrolled window */
GtkWidget *layout_box; /* Box to pack a GladeDesignLayout for each toplevel in project */
+
+ GtkToolPalette *palette;
+ GladeWidgetAdaptor *drag_adaptor;
};
static GtkVBoxClass *parent_class = NULL;
@@ -232,6 +236,10 @@ 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;
@@ -249,6 +257,9 @@ 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;
@@ -365,6 +376,13 @@ 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));
}
@@ -426,3 +444,181 @@ glade_design_view_get_from_project (GladeProject *project)
return (p != NULL) ? GLADE_DESIGN_VIEW (p) : NULL;
}
+
+static GtkWidget *
+widget_get_child_from_position (GtkWidget *toplevel, GtkWidget *widget, gint x, gint y)
+{
+ 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 gboolean
+widget_is_outside_glade_ancestor (GtkWidget *widget)
+{
+ while (widget)
+ {
+ if (glade_widget_get_from_gobject (widget))
+ return TRUE;
+
+ widget = gtk_widget_get_parent (widget);
+ }
+
+ return FALSE;
+}
+
+static gboolean
+on_drag_motion (GtkWidget *widget,
+ GdkDragContext *context,
+ gint x, gint y,
+ guint time)
+{
+ GladeDesignViewPrivate *priv = GLADE_DESIGN_VIEW (widget)->priv;
+ GtkWidget *child;
+
+ child = widget_get_child_from_position (widget, widget, x, y);
+
+ if (!priv->drag_adaptor)
+ {
+ GdkAtom target = gtk_drag_dest_find_target (widget, context, NULL);
+
+ if (!target)
+ return FALSE;
+
+ gtk_drag_get_data (widget, context, target, time);
+ }
+
+ if (child &&
+ ((priv->drag_adaptor && GLADE_IS_PLACEHOLDER (child) &&
+ GWA_IS_TOPLEVEL (priv->drag_adaptor)) ||
+ (!GLADE_IS_PLACEHOLDER (child) &&
+ widget_is_outside_glade_ancestor (child)) ))
+ {
+ gdk_drag_status (context, 0, time);
+ return FALSE;
+ }
+
+ gdk_drag_status (context, GDK_ACTION_COPY, time);
+ return TRUE;
+}
+
+static void
+on_drag_data_received (GtkWidget *widget,
+ GdkDragContext *context,
+ gint x,
+ gint y,
+ GtkSelectionData *selection,
+ guint info,
+ guint time)
+{
+ GladeDesignViewPrivate *priv = GLADE_DESIGN_VIEW (widget)->priv;
+ GtkWidget *item;
+
+ item = gtk_tool_palette_get_drag_item (priv->palette, selection);
+ g_return_if_fail (item);
+
+ priv->drag_adaptor = g_object_get_data (G_OBJECT (item), "glade-widget-adaptor");
+}
+
+static gboolean
+on_drag_drop (GtkWidget *widget,
+ GdkDragContext *context,
+ gint x,
+ gint y,
+ guint time)
+{
+ GladeDesignViewPrivate *priv = GLADE_DESIGN_VIEW (widget)->priv;
+ GtkWidget *child;
+
+ if (!priv->drag_adaptor)
+ return FALSE;
+
+ child = widget_get_child_from_position (widget, widget, x, y);
+
+ if (child && GLADE_IS_PLACEHOLDER (child))
+ {
+ GladePlaceholder *placeholder = GLADE_PLACEHOLDER (child);
+
+ glade_command_create (priv->drag_adaptor,
+ glade_placeholder_get_parent (placeholder),
+ placeholder,
+ priv->project);
+ }
+ else
+ {
+ glade_command_create (priv->drag_adaptor, NULL, NULL, priv->project);
+ }
+
+ gtk_drag_finish (context, TRUE, FALSE, time);
+ priv->drag_adaptor = NULL;
+ return TRUE;
+}
+
+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;
+
+ if (priv->palette)
+ {
+ g_signal_connect (target, "drag-motion", G_CALLBACK (on_drag_motion), NULL);
+ g_signal_connect (target, "drag-data-received", G_CALLBACK (on_drag_data_received), NULL);
+ g_signal_connect (target, "drag-drop", G_CALLBACK (on_drag_drop), NULL);
+
+ gtk_tool_palette_add_drag_dest (priv->palette, target, 0,
+ GTK_TOOL_PALETTE_DRAG_ITEMS,
+ GDK_ACTION_COPY);
+ }
+ else
+ {
+ g_signal_handlers_disconnect_by_func (target, on_drag_motion, NULL);
+ g_signal_handlers_disconnect_by_func (target, on_drag_data_received, NULL);
+ g_signal_handlers_disconnect_by_func (target, on_drag_drop, NULL);
+ }
+}
diff --git a/gladeui/glade-design-view.h b/gladeui/glade-design-view.h
index 452b5df3..0f6fe975 100644
--- a/gladeui/glade-design-view.h
+++ b/gladeui/glade-design-view.h
@@ -69,6 +69,9 @@ 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-palette.c b/gladeui/glade-palette.c
index ec08bbbd..0fe5f3ff 100644
--- a/gladeui/glade-palette.c
+++ b/gladeui/glade-palette.c
@@ -275,17 +275,18 @@ palette_item_button_press_cb (GtkWidget *button,
GdkEventButton *event,
GtkToolItem *item)
{
+ GladePalette *palette = g_object_get_data (G_OBJECT (item), "glade-palette");
+ GladeWidgetAdaptor *adaptor = g_object_get_data (G_OBJECT (item), "glade-widget-adaptor");
+
if (glade_popup_is_popup_event (event))
{
- GladeWidgetAdaptor *adaptor;
- GladePalette *palette;
-
- adaptor = g_object_get_data (G_OBJECT (item), "glade-widget-adaptor");
- palette = g_object_get_data (G_OBJECT (item), "glade-palette");
-
glade_popup_palette_pop (palette, adaptor, event);
return TRUE;
}
+ else
+ {
+ gtk_drag_source_set_icon_name (button, glade_widget_adaptor_get_icon_name (adaptor));
+ }
return FALSE;
}
@@ -925,3 +926,17 @@ glade_palette_get_show_selector_button (GladePalette * palette)
return gtk_widget_get_visible (palette->priv->selector_hbox);
}
+
+/**
+ * glade_palette_get_tool_palette:
+ * @palette: a #GladePalette
+ *
+ * Returns: the GtkToolPalette associated to this palette.
+ */
+GtkToolPalette *
+glade_palette_get_tool_palette (GladePalette *palette)
+{
+ g_return_val_if_fail (GLADE_IS_PALETTE (palette), FALSE);
+
+ return GTK_TOOL_PALETTE (palette->priv->toolpalette);
+}
diff --git a/gladeui/glade-palette.h b/gladeui/glade-palette.h
index 163d3717..0e4bfacf 100644
--- a/gladeui/glade-palette.h
+++ b/gladeui/glade-palette.h
@@ -95,6 +95,8 @@ void glade_palette_set_show_selector_button (GladePalette *palette,
gboolean glade_palette_get_show_selector_button (GladePalette *palette);
+GtkToolPalette *glade_palette_get_tool_palette (GladePalette *palette);
+
G_END_DECLS
#endif /* __GLADE_PALETTE_H__ */
diff --git a/src/glade-window.c b/src/glade-window.c
index de2648c2..8e1bccef 100644
--- a/src/glade-window.c
+++ b/src/glade-window.c
@@ -1703,6 +1703,8 @@ on_notebook_tab_added (GtkNotebook *notebook,
gtk_notebook_append_page (GTK_NOTEBOOK (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")))
{