[libegg/spread-table-dnd] Added "widget-drop-possible" signal to EggSpreadTableDnd
- From: Tristan Van Berkom <tvb src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libegg/spread-table-dnd] Added "widget-drop-possible" signal to EggSpreadTableDnd
- Date: Sun, 10 Apr 2011 21:38:15 +0000 (UTC)
commit b94b932d3d03cd963fbca85e106d0ccd8062a538
Author: Tristan Van Berkom <tristan van berkom gmail com>
Date: Sun Apr 10 18:36:51 2011 +0900
Added "widget-drop-possible" signal to EggSpreadTableDnd
This signal is like the GtkTreeDragDest.row_drop_possible virtual
method and is used to decide whether a widget can be dropped into
a said target spread table.
libegg/spreadtable/Makefile.am | 20 ++++++-
libegg/spreadtable/eggmarshalers.list | 1 +
libegg/spreadtable/eggspreadtablednd.c | 101 ++++++++++++++++++++++++++++++--
libegg/spreadtable/eggspreadtablednd.h | 2 +
4 files changed, 116 insertions(+), 8 deletions(-)
---
diff --git a/libegg/spreadtable/Makefile.am b/libegg/spreadtable/Makefile.am
index 02fd8f4..06d6c8e 100644
--- a/libegg/spreadtable/Makefile.am
+++ b/libegg/spreadtable/Makefile.am
@@ -7,15 +7,20 @@ noinst_LTLIBRARIES = libegg-spreadtable.la
libegg_spreadtable_la_LIBADD = $(EGG_30_LIBS)
+BUILT_SOURCES = eggmarshalers.c eggmarshalers.h
+
EGGSOURCES = \
eggspreadtable.c \
eggspreadtablednd.c \
- eggplaceholder.c
+ eggplaceholder.c \
+ eggmarshalers.c
+
EGGHEADERS = \
eggspreadtable.h \
eggspreadtablednd.h \
- eggplaceholder.h
+ eggplaceholder.h \
+ eggmarshalers.h
libegg_spreadtable_la_SOURCES = $(EGGSOURCES)
@@ -29,3 +34,14 @@ testspreadtable_SOURCES = testspreadtable.c
testspreadtable_LDADD = $(EGG_30_LIBS) \
$(top_builddir)/libegg/spreadtable/libegg-spreadtable.la
+
+
+#Marshallers rules
+eggmarshalers.h: eggmarshalers.list
+ $(GLIB_GENMARSHAL) --prefix=_egg_marshal $(srcdir)/eggmarshalers.list --header > eggmarshalers-h.tmp \
+ && mv eggmarshalers-h.tmp eggmarshalers.h \
+ || ( rm -f eggmarshalers-h.tmp && exit 1)
+eggmarshalers.c: eggmarshalers.list
+ $(GLIB_GENMARSHAL) --prefix=_egg_marshal $(srcdir)/eggmarshalers.list --body --header > eggmarshalers-c.tmp \
+ && mv eggmarshalers-c.tmp eggmarshalers.c \
+ || ( rm -f eggmarshalers-c.tmp && exit 1 )
diff --git a/libegg/spreadtable/eggmarshalers.list b/libegg/spreadtable/eggmarshalers.list
new file mode 100644
index 0000000..00015cf
--- /dev/null
+++ b/libegg/spreadtable/eggmarshalers.list
@@ -0,0 +1 @@
+BOOLEAN:OBJECT
diff --git a/libegg/spreadtable/eggspreadtablednd.c b/libegg/spreadtable/eggspreadtablednd.c
index e829d1d..88e949e 100644
--- a/libegg/spreadtable/eggspreadtablednd.c
+++ b/libegg/spreadtable/eggspreadtablednd.c
@@ -25,6 +25,7 @@
#include <string.h>
#include "eggspreadtablednd.h"
#include "eggplaceholder.h"
+#include "eggmarshalers.h"
#define DEFAULT_LINES 2
#define P_(msgid) (msgid)
@@ -76,6 +77,10 @@ static void egg_spread_table_dnd_insert_child (EggSpreadTable *sprea
GtkWidget *child,
gint index);
+/* EggSpreadTableDndClass */
+static gboolean egg_spread_table_dnd_drop_possible(EggSpreadTableDnd *table,
+ GtkWidget *widget);
+
/* Drag and Drop callbacks & other utilities */
static void drag_begin (GtkWidget *widget,
GdkDragContext *context,
@@ -98,7 +103,13 @@ static gint get_index_at_position (EggSpreadTableDnd *sprea
gint x,
gint y,
gint *line_ret);
+static gboolean boolean_handled_accumulator (GSignalInvocationHint *ihint,
+ GValue *return_accu,
+ const GValue *handler_return,
+ gpointer dummy);
+static gboolean drop_possible (EggSpreadTableDnd *spread_table,
+ GtkWidget *widget);
typedef struct {
EggSpreadTableDnd *table;
@@ -126,11 +137,20 @@ struct _EggSpreadTableDndPrivate {
gint press_start_y;
};
+
+enum {
+ SIGNAL_DROP_POSSIBLE,
+ LAST_SIGNAL
+};
+
+static guint dnd_table_signals [LAST_SIGNAL] = { 0 };
static GdkAtom dnd_target_atom_child = GDK_NONE;
static const GtkTargetEntry dnd_targets[] = {
{ "application/x-egg-spread-table-dnd-child", GTK_TARGET_SAME_APP, 0 }
};
+
+
G_DEFINE_TYPE (EggSpreadTableDnd, egg_spread_table_dnd, EGG_TYPE_SPREAD_TABLE)
static void
@@ -154,9 +174,35 @@ egg_spread_table_dnd_class_init (EggSpreadTableDndClass *class)
widget_class->drag_drop = egg_spread_table_dnd_drag_drop;
widget_class->drag_data_received = egg_spread_table_dnd_drag_data_received;
- container_class->remove = egg_spread_table_dnd_remove;
+ container_class->remove = egg_spread_table_dnd_remove;
+
spread_class->insert_child = egg_spread_table_dnd_insert_child;
+ class->widget_drop_possible = egg_spread_table_dnd_drop_possible;
+
+ /**
+ * EggSpreadTableDnd::widget-drop-possible
+ *
+ * Emitted to check if a widget can be dropped into this spread table.
+ *
+ * The first connected signal to return TRUE decides that the widget
+ * can be dropped.
+ *
+ * By default EggSpreadTableDnd accepts drops from the same table
+ * (the only way to dissallow drops from the same spread table is
+ * to implement a subclass which overrides the
+ * EggSpreadTableDndClass.widget_drop_possible() virtual method).
+ */
+ dnd_table_signals[SIGNAL_DROP_POSSIBLE] =
+ g_signal_new ("widget-drop-possible",
+ G_TYPE_FROM_CLASS (class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (EggSpreadTableDndClass, widget_drop_possible),
+ boolean_handled_accumulator, NULL,
+ _egg_marshal_BOOLEAN__OBJECT,
+ G_TYPE_BOOLEAN, 1, GTK_TYPE_WIDGET);
+
+
dnd_target_atom_child = gdk_atom_intern_static_string (dnd_targets[0].target);
g_type_class_add_private (class, sizeof (EggSpreadTableDndPrivate));
@@ -476,11 +522,15 @@ egg_spread_table_dnd_drag_motion (GtkWidget *widget,
/* Could be comming from another spread table, lock it now incase
* its not already locked. */
- egg_spread_table_lock (EGG_SPREAD_TABLE (spread_table));
- spread_table->priv->dragging = TRUE;
gtk_drag_get_data (widget, context, dnd_target_atom_child, time_);
+ if (!drop_possible (spread_table, spread_table->priv->drag_data.child))
+ return FALSE;
+
+ egg_spread_table_lock (EGG_SPREAD_TABLE (spread_table));
+ spread_table->priv->dragging = TRUE;
+
/* Dont do anything until the currently drop target placeholder finishes animating in */
if ((spread_table->priv->drop_target &&
egg_placeholder_get_animating
@@ -573,14 +623,14 @@ egg_spread_table_dnd_drag_drop (GtkWidget *widget,
egg_spread_table_unlock (EGG_SPREAD_TABLE (spread_table));
gtk_drag_finish (context, TRUE, TRUE, time_);
+ return TRUE;
}
else
{
- g_warning ("drag-drop signal received with no active drop target\n");
gtk_drag_finish (context, FALSE, TRUE, time_);
+ return FALSE;
}
- return TRUE;
}
static void
@@ -654,6 +704,16 @@ egg_spread_table_dnd_insert_child (EggSpreadTable *spread_table,
}
/*****************************************************
+ * EggSpreadTableDndClass *
+ *****************************************************/
+static gboolean
+egg_spread_table_dnd_drop_possible (EggSpreadTableDnd *table,
+ GtkWidget *widget)
+{
+ return (GTK_WIDGET (table) == gtk_widget_get_parent (widget));
+}
+
+/*****************************************************
* Drag'n'Drop signals & other functions *
*****************************************************/
@@ -669,7 +729,8 @@ drag_begin (GtkWidget *widget,
egg_spread_table_lock (EGG_SPREAD_TABLE (spread_table));
spread_table->priv->dragging = TRUE;
- /* Hold on to the drag child incase the drag fails */
+ /* Just assign a drag child, this is only important for
+ * child widgets that dont have a GdkWindow though really */
spread_table->priv->drag_child = widget;
/* Save the drag origin in case of failed drags and insert a placeholder as the first
@@ -869,6 +930,34 @@ get_child_at_position (EggSpreadTableDnd *spread_table,
return ret_child;
}
+static gboolean
+drop_possible (EggSpreadTableDnd *spread_table,
+ GtkWidget *widget)
+{
+ gboolean possible = FALSE;
+
+ g_signal_emit (spread_table, dnd_table_signals[SIGNAL_DROP_POSSIBLE], 0, widget, &possible);
+
+ return possible;
+}
+
+/* Copy of _gtk_boolean_handled_accumulator */
+static gboolean
+boolean_handled_accumulator (GSignalInvocationHint *ihint,
+ GValue *return_accu,
+ const GValue *handler_return,
+ gpointer dummy)
+{
+ gboolean continue_emission;
+ gboolean signal_handled;
+
+ signal_handled = g_value_get_boolean (handler_return);
+ g_value_set_boolean (return_accu, signal_handled);
+ continue_emission = !signal_handled;
+
+ return continue_emission;
+}
+
/*****************************************************
* API *
*****************************************************/
diff --git a/libegg/spreadtable/eggspreadtablednd.h b/libegg/spreadtable/eggspreadtablednd.h
index 885e1d6..36c323b 100644
--- a/libegg/spreadtable/eggspreadtablednd.h
+++ b/libegg/spreadtable/eggspreadtablednd.h
@@ -52,6 +52,8 @@ struct _EggSpreadTableDnd
struct _EggSpreadTableDndClass
{
EggSpreadTableClass parent_class;
+
+ gboolean (* widget_drop_possible) (EggSpreadTableDnd *table, GtkWidget *widget);
};
GType egg_spread_table_dnd_get_type (void) G_GNUC_CONST;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]