[libegg/spread-table-dnd] Added "widget-drop-possible" signal to EggSpreadTableDnd



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]