[libegg] Enhanced EggSpreadTableDnd api



commit a5e9d5de2d1fb96104bb13135cc415626036c9a1
Author: Tristan Van Berkom <tristan van berkom gmail com>
Date:   Mon Oct 3 15:38:25 2011 -0400

    Enhanced EggSpreadTableDnd api
    
      o Removed egg_spread_table_dnd_steal_events() api
      o Added apis:
         egg_spread_table_dnd_set/get_drag_enabled()
         egg_spread_table_dnd_set/get_drop_enabled()
        The set/get_drag_enabled() apis use an EggDragEnableMode enumeration
        to decide whether dragging:
          - Is completely OFF
          - Is enabled (dragging starts when and where children dont handle events)
          - Overrides events on top of child widgets
      o Changed signature of 'widget-drop-possible' signal for something more
        useful (added out 'drop_possible' parameter in addition to boolean
        handled return value).
      o Added documentation

 libegg/spreadtable/eggmarshalers.list   |    2 +-
 libegg/spreadtable/eggspreadtablednd.c  |  302 +++++++++++++++++++++++--------
 libegg/spreadtable/eggspreadtablednd.h  |   45 ++++-
 libegg/spreadtable/testspreadtable.c    |    8 +
 libegg/spreadtable/testspreadtablednd.c |   46 ++++-
 5 files changed, 307 insertions(+), 96 deletions(-)
---
diff --git a/libegg/spreadtable/eggmarshalers.list b/libegg/spreadtable/eggmarshalers.list
index 00015cf..8fd7b2f 100644
--- a/libegg/spreadtable/eggmarshalers.list
+++ b/libegg/spreadtable/eggmarshalers.list
@@ -1 +1 @@
-BOOLEAN:OBJECT
+BOOLEAN:OBJECT,POINTER
diff --git a/libegg/spreadtable/eggspreadtablednd.c b/libegg/spreadtable/eggspreadtablednd.c
index c7f7e38..b07715a 100644
--- a/libegg/spreadtable/eggspreadtablednd.c
+++ b/libegg/spreadtable/eggspreadtablednd.c
@@ -30,13 +30,6 @@
 #define DEFAULT_LINES 2
 #define P_(msgid) (msgid)
 
-
-enum {
-  PROP_0,
-  PROP_STEAL_EVENTS
-};
-
-
 /* GObjectClass */
 static void          egg_spread_table_dnd_get_property      (GObject            *object,
 							     guint               prop_id,
@@ -88,7 +81,8 @@ static gint          egg_spread_table_dnd_build_segments     (EggSpreadTable
 
 /* EggSpreadTableDndClass */
 static gboolean      egg_spread_table_dnd_drop_possible(EggSpreadTableDnd *table,
-							GtkWidget         *widget);
+							GtkWidget         *widget,
+							gboolean          *possible);
 
 /* Drag and Drop callbacks & other utilities */
 static void          drag_begin                        (GtkWidget         *widget,
@@ -143,9 +137,11 @@ struct _EggSpreadTableDndPrivate {
   GtkWidget *drag_child;       /* If the drag started on a widget with no window, then the spread table
 				* keeps a hold on which child is being dragged */
 
-  guint      dragging : 1;     /* Whether the drag'n'drop operation is currently active over this table */
-  guint      steal_events : 1; /* Whether to steal all child events (causes the event-boxes to
-				* place thier event window above all children) */
+  guint      dragging     : 1; /* Whether a drag'n'drop operation is currently active over this table */
+
+  guint      drop_enabled : 1; /* Whether dropping is allowed on this table */
+  guint      drag_enabled : 2; /* The EggDragEnableMode (can cause the event-boxes to
+				* place thier event window above of below all children) */
 
   gint       disappearing;     /* Count of placeholders that are currently disappearing */
   gint      *locked_config;    /* Caching and locking the child configuration */
@@ -153,19 +149,25 @@ struct _EggSpreadTableDndPrivate {
 
 
 enum {
+  PROP_0,
+  PROP_DRAG_ENABLED,
+  PROP_DROP_ENABLED
+};
+
+enum {
   SIGNAL_DROP_POSSIBLE,
   LAST_SIGNAL
 };
 
-static GQuark		    dnd_table_child_quark = 0;
 static guint                dnd_table_signals [LAST_SIGNAL] = { 0 };
+static GQuark		    dnd_table_child_quark     = 0;
+static GQuark		    dnd_table_connected_quark = 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
@@ -194,34 +196,75 @@ egg_spread_table_dnd_class_init (EggSpreadTableDndClass *class)
   class->widget_drop_possible           = egg_spread_table_dnd_drop_possible;
 
   /**
-   * EggSpreadTableDnd:steal-events:
+   * EggSpreadTableDnd:drag-enabled:
+   *
+   * Specifies the #EggDragEnableMode controlling whether child
+   * widgets can be dragged from this table.
+   *
+   * 
+   */
+  g_object_class_install_property (gobject_class,
+                                   PROP_DRAG_ENABLED,
+                                   g_param_spec_int ("drag-enabled",
+						     P_("Drag Enabled"),
+						     P_("The #EggDragEnableMode controlling whether "
+							"children can be dragged"),
+						     EGG_DRAG_DISABLED,
+						     EGG_DRAG_FULL,
+						     EGG_DRAG_ENABLED,
+						     G_PARAM_READABLE | G_PARAM_WRITABLE));
+
+  /**
+   * EggSpreadTableDnd:drop-enabled:
    *
-   * Whether the table should steal all pointer events from added children
-   * for the purpose of Drag'n'Drop.
+   * Whether this spread table accepts drops.
    *
+   * If this is set to %FALSE then the EggSpreadTableDnd::widget-drop-possible
+   * signal will never be emitted.
    */
   g_object_class_install_property (gobject_class,
-                                   PROP_STEAL_EVENTS,
-                                   g_param_spec_boolean ("steal-events",
-							 P_("Steal Events"),
-							 P_("Whether the table should steal all pointer "
-							    "events from children"),
-							 FALSE,
+                                   PROP_DROP_ENABLED,
+                                   g_param_spec_boolean ("drop-enabled",
+							 P_("Drop Enabled"),
+							 P_("Whether this spread table accepts drops"),
+							 TRUE,
 							 G_PARAM_READABLE | G_PARAM_WRITABLE));
 
 
   /**
-   * EggSpreadTableDnd::widget-drop-possible
+   * EggSpreadTableDnd::widget-drop-possible:
+   * @eggspreadtablednd: An #EggSpreadTableDnd
+   * @widget: The currently dragging widget to check
+   * @drop_possible: (out): Location to store whether the @eggspreadtablednd should accept @widget
+   *
+   * Emitted to check if @widget can be dropped into @eggspreadtablednd.
+   *
+   * The first connected signal to return TRUE decides whether @widget
+   * can be dropped into @eggspreadtablednd.
    *
-   * Emitted to check if a widget can be dropped into this spread table.
+   * When handling this signal and returning %TRUE, you must set the value of @drop_possible:
+   * <programlisting><![CDATA[
+   * static gboolean
+   * my_spread_table_accepts_your_widget_cb (EggSpreadTableDnd *table,
+   *                                         GtkWidget         *child,
+   *                                         gboolean          *drop_possible,
+   *                                         gpointer           user_data)
+   * {
+   *   if (i_would_rather_the_default_behaviour_for (child))
+   *     return FALSE;
    *
-   * The first connected signal to return TRUE decides that the widget
-   * can be dropped.
+   *   if (child_widget_asked_kindly (child))
+   *     *drop_possible = TRUE;
+   *   else
+   *     *drop_possible = FALSE;
    *
-   * 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).
+   *   return TRUE;
+   * }
+   * ]]></programlisting>
+   *
+   * By default EggSpreadTableDnd accepts drops from only the same table
+   *
+   * To disable dropping completely in a spread table, use egg_spread_table_set_drop_enabled().
    */
   dnd_table_signals[SIGNAL_DROP_POSSIBLE] =
         g_signal_new ("widget-drop-possible",
@@ -229,12 +272,13 @@ egg_spread_table_dnd_class_init (EggSpreadTableDndClass *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);
+		      _egg_marshal_BOOLEAN__OBJECT_POINTER,
+		      G_TYPE_BOOLEAN, 2, GTK_TYPE_WIDGET, G_TYPE_POINTER);
 
 
-  dnd_target_atom_child = gdk_atom_intern_static_string (dnd_targets[0].target);
-  dnd_table_child_quark = g_quark_from_static_string ("egg-spread-table-dnd-child");
+  dnd_target_atom_child     = gdk_atom_intern_static_string (dnd_targets[0].target);
+  dnd_table_child_quark     = g_quark_from_static_string ("egg-spread-table-dnd-child");
+  dnd_table_connected_quark = g_quark_from_static_string ("egg-spread-table-dnd-connected");
 
   g_type_class_add_private (class, sizeof (EggSpreadTableDndPrivate));
 }
@@ -259,6 +303,9 @@ egg_spread_table_dnd_init (EggSpreadTableDnd *spread_table)
 		       0, dnd_targets, G_N_ELEMENTS (dnd_targets),
 		       GDK_ACTION_MOVE);
 
+  priv->drag_enabled = EGG_DRAG_ENABLED;
+  priv->drop_enabled = TRUE;
+
   gtk_widget_set_has_window (GTK_WIDGET (spread_table), TRUE);
 }
 
@@ -275,8 +322,11 @@ egg_spread_table_dnd_get_property (GObject      *object,
 
   switch (prop_id)
     {
-    case PROP_STEAL_EVENTS:
-      g_value_set_boolean (value, table->priv->steal_events);
+    case PROP_DRAG_ENABLED:
+      g_value_set_int (value, table->priv->drag_enabled);
+      break;
+    case PROP_DROP_ENABLED:
+      g_value_set_boolean (value, table->priv->drop_enabled);
       break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -294,8 +344,11 @@ egg_spread_table_dnd_set_property (GObject      *object,
 
   switch (prop_id)
     {
-    case PROP_STEAL_EVENTS:
-      egg_spread_table_dnd_set_steal_events (table, g_value_get_boolean (value));
+    case PROP_DRAG_ENABLED:
+      egg_spread_table_dnd_set_drag_enabled (table, g_value_get_int (value));
+      break;
+    case PROP_DROP_ENABLED:
+      egg_spread_table_dnd_set_drop_enabled (table, g_value_get_int (value));
       break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -753,6 +806,50 @@ egg_spread_table_dnd_drag_data_received (GtkWidget        *widget,
  *                GtkContainerClass                  *
  *****************************************************/
 static void
+egg_spread_table_connect_child (gpointer spread_table,
+				gpointer child)
+{
+  if (!EGG_IS_PLACEHOLDER (child) &&
+      GPOINTER_TO_INT (g_object_get_qdata (G_OBJECT (child), dnd_table_connected_quark)) == FALSE)
+    {
+      gtk_drag_source_set (child, GDK_BUTTON1_MASK | GDK_BUTTON3_MASK,
+			   dnd_targets, G_N_ELEMENTS (dnd_targets),
+			   GDK_ACTION_MOVE);
+
+      g_signal_connect (child, "drag-data-get",
+			G_CALLBACK (drag_data_get), spread_table);
+      g_signal_connect (child, "drag-failed",
+			G_CALLBACK (drag_failed), spread_table);
+      g_signal_connect (child, "drag-begin",
+			G_CALLBACK (drag_begin), spread_table);
+      g_signal_connect (child, "drag-end",
+			G_CALLBACK (drag_end), spread_table);
+
+      g_object_set_qdata (G_OBJECT (child),
+			  dnd_table_connected_quark, GINT_TO_POINTER (TRUE));
+    }
+}
+
+static void
+egg_spread_table_disconnect_child (gpointer spread_table,
+				   gpointer child)
+{
+  /* Disconnect dnd */
+  if (!EGG_IS_PLACEHOLDER (child) &&
+      GPOINTER_TO_INT (g_object_get_qdata (G_OBJECT (child), dnd_table_connected_quark)))
+    {
+      g_signal_handlers_disconnect_by_func (child, G_CALLBACK (drag_data_get), spread_table);
+      g_signal_handlers_disconnect_by_func (child, G_CALLBACK (drag_failed), spread_table);
+      g_signal_handlers_disconnect_by_func (child, G_CALLBACK (drag_begin), spread_table);
+      g_signal_handlers_disconnect_by_func (child, G_CALLBACK (drag_end), spread_table);
+      gtk_drag_source_unset (child);
+
+      g_object_set_qdata (G_OBJECT (child),
+			  dnd_table_connected_quark, GINT_TO_POINTER (FALSE));
+    }
+}
+
+static void
 egg_spread_table_dnd_remove (GtkContainer *container,
 			     GtkWidget    *child)
 {
@@ -763,16 +860,8 @@ egg_spread_table_dnd_remove (GtkContainer *container,
       return;
     }
 
-
   /* Disconnect dnd */
-  if (!EGG_IS_PLACEHOLDER (child))
-    {
-      g_signal_handlers_disconnect_by_func (child, G_CALLBACK (drag_data_get), container);
-      g_signal_handlers_disconnect_by_func (child, G_CALLBACK (drag_failed), container);
-      g_signal_handlers_disconnect_by_func (child, G_CALLBACK (drag_begin), container);
-      g_signal_handlers_disconnect_by_func (child, G_CALLBACK (drag_end), container);
-      gtk_drag_source_unset (child);
-    }
+  egg_spread_table_disconnect_child (container, child);
 
   GTK_CONTAINER_CLASS (egg_spread_table_dnd_parent_class)->remove (container, child);
 }
@@ -786,6 +875,8 @@ egg_spread_table_dnd_insert_child_impl (EggSpreadTable *spread_table,
 					GtkWidget      *child,
 					gint            index)
 {
+  EggSpreadTableDnd *table = EGG_SPREAD_TABLE_DND (spread_table);
+
   if (GPOINTER_TO_INT (g_object_get_qdata (G_OBJECT (child), dnd_table_child_quark)) == FALSE)
     {
       g_message ("Refusing to add child widget to an EggSpreadTableDnd directly, "
@@ -795,22 +886,9 @@ egg_spread_table_dnd_insert_child_impl (EggSpreadTable *spread_table,
 
   EGG_SPREAD_TABLE_CLASS (egg_spread_table_dnd_parent_class)->insert_child (spread_table, child, index);
 
-  /* Connect dnd */
-  if (!EGG_IS_PLACEHOLDER (child))
-    {
-      gtk_drag_source_set (child, GDK_BUTTON1_MASK | GDK_BUTTON3_MASK,
-			   dnd_targets, G_N_ELEMENTS (dnd_targets),
-			   GDK_ACTION_MOVE);
-
-      g_signal_connect (child, "drag-data-get",
-			G_CALLBACK (drag_data_get), spread_table);
-      g_signal_connect (child, "drag-failed",
-			G_CALLBACK (drag_failed), spread_table);
-      g_signal_connect (child, "drag-begin",
-			G_CALLBACK (drag_begin), spread_table);
-      g_signal_connect (child, "drag-end",
-			G_CALLBACK (drag_end), spread_table);
-    }
+  /* Connect dnd after really parenting the child */
+  if (table->priv->drag_enabled != EGG_DRAG_DISABLED)
+    egg_spread_table_connect_child (spread_table, child);
 }
 
 static gint
@@ -876,9 +954,12 @@ egg_spread_table_dnd_build_segments (EggSpreadTable *table,
  *****************************************************/
 static gboolean
 egg_spread_table_dnd_drop_possible (EggSpreadTableDnd *table,
-				    GtkWidget         *widget)
+				    GtkWidget         *widget,
+				    gboolean          *possible)
 {
-  return (GTK_WIDGET (table) == gtk_widget_get_parent (widget));
+  *possible = (GTK_WIDGET (table) == gtk_widget_get_parent (widget));
+
+  return TRUE;
 }
 
 /*****************************************************
@@ -1125,8 +1206,10 @@ drop_possible (EggSpreadTableDnd *spread_table,
 	       GtkWidget         *widget)
 {
   gboolean possible = FALSE;
+  gboolean handled = FALSE;
 
-  g_signal_emit (spread_table, dnd_table_signals[SIGNAL_DROP_POSSIBLE], 0, widget, &possible);
+  if (spread_table->priv->drop_enabled)
+    g_signal_emit (spread_table, dnd_table_signals[SIGNAL_DROP_POSSIBLE], 0, widget, &possible, &handled);
 
   return possible;
 }
@@ -1241,7 +1324,7 @@ egg_spread_table_dnd_insert_child (EggSpreadTableDnd *table,
   g_return_if_fail (GTK_IS_WIDGET (child));
 
   event_box = gtk_event_box_new ();
-  gtk_event_box_set_above_child (GTK_EVENT_BOX (event_box), table->priv->steal_events);
+  gtk_event_box_set_above_child (GTK_EVENT_BOX (event_box), table->priv->drag_enabled == EGG_DRAG_FULL);
   g_object_set_qdata (G_OBJECT (event_box), dnd_table_child_quark, GINT_TO_POINTER (TRUE));
   gtk_widget_show (event_box);
 
@@ -1288,35 +1371,98 @@ egg_spread_table_dnd_remove_child (EggSpreadTableDnd *table,
 }
 
 static void
-flip_event_windows (GtkEventBox       *child,
-		    EggSpreadTableDnd *table)
+reconfigure_children (GtkEventBox       *child,
+		      EggSpreadTableDnd *table)
 {
   /* Besides the internally owned event boxes, only EggPlaceholders can exist 
    * as direct children of the EggSpreadTableDnd */
   if (GTK_IS_EVENT_BOX (child))
-    gtk_event_box_set_above_child (child, table->priv->steal_events);
+    {
+      gtk_event_box_set_above_child (child, table->priv->drag_enabled == EGG_DRAG_FULL);
+
+      if (table->priv->drag_enabled == EGG_DRAG_DISABLED)
+	egg_spread_table_disconnect_child (table, child);
+      else
+	egg_spread_table_connect_child (table, child);
+    }
 }
 
+/**
+ * egg_spread_table_dnd_set_drag_enabled:
+ * @table: An #EggSpreadTableDnd
+ * @drag_enabled: The #EggDragEnableMode to set
+ *
+ * Sets the #EggDragEnableMode determining whther
+ * dragging of children is enabled.
+ */
 void
-egg_spread_table_dnd_set_steal_events (EggSpreadTableDnd *table,
-				       gboolean           steal_events)
+egg_spread_table_dnd_set_drag_enabled (EggSpreadTableDnd *table,
+				       EggDragEnableMode  drag_enabled)
 {
   g_return_if_fail (EGG_IS_SPREAD_TABLE_DND (table));
 
-  if (table->priv->steal_events != steal_events)
+  if (table->priv->drag_enabled != drag_enabled)
     {
-      table->priv->steal_events = steal_events;
+      table->priv->drag_enabled = drag_enabled;
 
-      gtk_container_forall (GTK_CONTAINER (table), (GtkCallback)flip_event_windows, table);
+      gtk_container_foreach (GTK_CONTAINER (table),
+			     (GtkCallback)reconfigure_children, table);
 
-      g_object_notify (G_OBJECT (table), "steal-events");
+      g_object_notify (G_OBJECT (table), "drag-enabled");
     }
 }
 
+/**
+ * egg_spread_table_dnd_get_drag_enabled:
+ * @table: An #EggSpreadTableDnd
+ *
+ * Gets the #EggDragEnableMode determining whther
+ * dragging of children is enabled.
+ *
+ * Returns: The #EggDragEnableMode for @table
+ */
+EggDragEnableMode
+egg_spread_table_dnd_get_drag_enabled (EggSpreadTableDnd *table)
+{
+  g_return_val_if_fail (EGG_IS_SPREAD_TABLE_DND (table), 0);
+
+  return table->priv->drag_enabled;
+}
+
+/**
+ * egg_spread_table_dnd_set_drop_enabled:
+ * @table: An #EggSpreadTableDnd
+ * @drop_enabled: Whether to enable or disable dropping in @table
+ *
+ * Enables/disables dropping of children into @table.
+ */
+void
+egg_spread_table_dnd_set_drop_enabled (EggSpreadTableDnd *table,
+				       gboolean           drop_enabled)
+{
+  g_return_if_fail (EGG_IS_SPREAD_TABLE_DND (table));
+
+  if (table->priv->drop_enabled != drop_enabled)
+    {
+      table->priv->drop_enabled = drop_enabled;
+
+      g_object_notify (G_OBJECT (table), "drop-enabled");
+    }
+}
+
+/**
+ * egg_spread_table_dnd_get_drop_enabled:
+ * @table: An #EggSpreadTableDnd
+ *
+ * Gets whether dropping of children into @table is enabled.
+ *
+ * Returns: Whether dropping of children into @table is enabled.
+ */
 gboolean
-egg_spread_table_dnd_get_steal_events (EggSpreadTableDnd *table)
+egg_spread_table_dnd_get_drop_enabled (EggSpreadTableDnd *table)
 {
   g_return_val_if_fail (EGG_IS_SPREAD_TABLE_DND (table), FALSE);
 
-  return table->priv->steal_events;
+  return table->priv->drop_enabled;
 }
+
diff --git a/libegg/spreadtable/eggspreadtablednd.h b/libegg/spreadtable/eggspreadtablednd.h
index dba5dc7..d6cdb1c 100644
--- a/libegg/spreadtable/eggspreadtablednd.h
+++ b/libegg/spreadtable/eggspreadtablednd.h
@@ -40,20 +40,47 @@ typedef struct _EggSpreadTableDnd            EggSpreadTableDnd;
 typedef struct _EggSpreadTableDndPrivate     EggSpreadTableDndPrivate;
 typedef struct _EggSpreadTableDndClass       EggSpreadTableDndClass;
 
-
+/**
+ * EggDragEnableMode:
+ * @EGG_DRAG_DISABLED: Children cannot be dragged.
+ * @EGG_DRAG_ENABLED:  Children can be dragged if the needed mouse events 
+ *                     are not handled by those said children.
+ * @EGG_DRAG_FULL:     All mouse events on children are consumed for the
+ *                     purpose of starting drag and drop operations on children.
+ *
+ * Constants that control whether child widgets can be dragged from
+ * an #EggSpreadTableDnd.
+ *
+ */
+typedef enum {
+  EGG_DRAG_DISABLED = 0,
+  EGG_DRAG_ENABLED,
+  EGG_DRAG_FULL
+} EggDragEnableMode;
+
+/**
+ * EggSpreadTableDnd:
+ */
 struct _EggSpreadTableDnd
 {
-  EggSpreadTable parent_instance;
-
   /*< private >*/
+  EggSpreadTable parent_instance;
   EggSpreadTableDndPrivate *priv;
 };
 
+/**
+ * EggSpreadTableDndClass:
+ * @widget_drop_possible: A signal to determine whether @widget can be dropped into @table
+ */
 struct _EggSpreadTableDndClass
 {
+  /*< private >*/
   EggSpreadTableClass parent_class;
 
-  gboolean  (* widget_drop_possible) (EggSpreadTableDnd *table, GtkWidget *widget);
+  /*< public >*/
+  gboolean  (* widget_drop_possible) (EggSpreadTableDnd *table,
+				      GtkWidget         *widget,
+				      gboolean          *drop_possible);
 };
 
 GType                 egg_spread_table_dnd_get_type              (void) G_GNUC_CONST;
@@ -65,9 +92,13 @@ void                  egg_spread_table_dnd_insert_child          (EggSpreadTable
 								  gint               index);
 void                  egg_spread_table_dnd_remove_child          (EggSpreadTableDnd *table,
 								  GtkWidget         *child);
-void                  egg_spread_table_dnd_set_steal_events      (EggSpreadTableDnd *table,
-								  gboolean           steal_events);
-gboolean              egg_spread_table_dnd_get_steal_events      (EggSpreadTableDnd *table);
+
+void                  egg_spread_table_dnd_set_drag_enabled      (EggSpreadTableDnd *table,
+								  EggDragEnableMode  drag_enabled);
+EggDragEnableMode     egg_spread_table_dnd_get_drag_enabled      (EggSpreadTableDnd *table);
+void                  egg_spread_table_dnd_set_drop_enabled      (EggSpreadTableDnd *table,
+								  gboolean           drop_enabled);
+gboolean              egg_spread_table_dnd_get_drop_enabled      (EggSpreadTableDnd *table);
 
 G_END_DECLS
 
diff --git a/libegg/spreadtable/testspreadtable.c b/libegg/spreadtable/testspreadtable.c
index 2da5073..d9768ea 100644
--- a/libegg/spreadtable/testspreadtable.c
+++ b/libegg/spreadtable/testspreadtable.c
@@ -41,6 +41,14 @@ static GtkAlign   child_halign     = INITIAL_HALIGN;
 static int        test_image       = INITIAL_IMAGE;
 static int        test_image_index = INITIAL_IMAGE_INDEX;
 
+
+/* Lazy */
+#define gtk_hbox_new(homogeneous, spacing) \
+  gtk_box_new (GTK_ORIENTATION_HORIZONTAL, spacing)
+
+#define gtk_vbox_new(homogeneous, spacing) \
+  gtk_box_new (GTK_ORIENTATION_VERTICAL, spacing)
+
 static void
 populate_spread_table_wrappy (EggSpreadTable *spread_table)
 {
diff --git a/libegg/spreadtable/testspreadtablednd.c b/libegg/spreadtable/testspreadtablednd.c
index d8dd04f..a7f5924 100644
--- a/libegg/spreadtable/testspreadtablednd.c
+++ b/libegg/spreadtable/testspreadtablednd.c
@@ -160,30 +160,37 @@ halign_changed (GtkComboBox   *box,
 static gboolean
 parent_drop_possible (EggSpreadTableDnd *table,
 		      GtkWidget         *child,
+		      gboolean          *drop_possible,
 		      gpointer           unused)
 {
-  if (parent_accepts_drops)
-    return TRUE;
+  *drop_possible = parent_accepts_drops;
 
-  return FALSE;
+  return TRUE;
 }
 
 static gboolean
 child_drop_possible (EggSpreadTableDnd *table,
 		     GtkWidget         *child,
+		     gboolean          *drop_possible,
 		     gpointer           unused)
 {
-  if (child_accepts_drops)
-    return TRUE;
+  *drop_possible = child_accepts_drops;
 
-  return FALSE;
+  return TRUE;
 }
 
 static void
-steal_events_toggled (GtkToggleButton   *button,
+drag_enabled_changed (GtkComboBox       *box,
 		      EggSpreadTableDnd *table)
 {
-  egg_spread_table_dnd_set_steal_events (table, gtk_toggle_button_get_active (button));
+  egg_spread_table_dnd_set_drag_enabled (table, gtk_combo_box_get_active (box));
+}
+
+static void
+drop_disable_toggled (GtkToggleButton *button,
+		      EggSpreadTableDnd *table)
+{
+  egg_spread_table_dnd_set_drop_enabled (table, !gtk_toggle_button_get_active (button));
 }
 
 static void
@@ -298,11 +305,26 @@ create_window (void)
 
 
   /* Add widget-drop-possible controls */
-  widget = gtk_toggle_button_new_with_label ("Steal Events");
+  widget = gtk_combo_box_text_new ();
+  gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (widget), "Disable Drag");
+  gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (widget), "Enable Drag");
+  gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (widget), "Full Drag");
+  gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 1);
+  gtk_widget_show (widget);
+
+  gtk_widget_set_tooltip_text (widget, "Set whether you can drag widgets from the table");
+  gtk_box_pack_start (GTK_BOX (paper_cntl), widget, FALSE, FALSE, 0);
+
+  g_signal_connect (G_OBJECT (widget), "changed",
+                    G_CALLBACK (drag_enabled_changed), paper);
+
+  /* Add widget-drop-possible controls */
+  widget = gtk_toggle_button_new_with_label ("Disable Drop");
   gtk_widget_show (widget);
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), FALSE);
   gtk_box_pack_start (GTK_BOX (paper_cntl), widget, FALSE, FALSE, 0);
-  g_signal_connect (widget, "toggled", G_CALLBACK (steal_events_toggled), paper);
+  g_signal_connect (widget, "toggled", G_CALLBACK (drop_disable_toggled), paper);
+  gtk_widget_set_tooltip_text (widget, "Set whether you can drop widgets on the table");
 
   /* Add widget-drop-possible controls */
   widget = gtk_toggle_button_new_with_label ("parent accept drop");
@@ -310,12 +332,16 @@ create_window (void)
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), TRUE);
   gtk_box_pack_start (GTK_BOX (paper_cntl), widget, FALSE, FALSE, 0);
   g_signal_connect (widget, "toggled", G_CALLBACK (set_boolean), &parent_accepts_drops);
+  gtk_widget_set_tooltip_text (widget, "Set whether the parent will return TRUE from "
+			       "the \"widget-drop-possible\" signal");
 
   widget = gtk_toggle_button_new_with_label ("child accept drop");
   gtk_widget_show (widget);
   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), TRUE);
   gtk_box_pack_start (GTK_BOX (paper_cntl), widget, FALSE, FALSE, 0);
   g_signal_connect (widget, "toggled", G_CALLBACK (set_boolean), &child_accepts_drops);
+  gtk_widget_set_tooltip_text (widget, "Set whether the child will return TRUE from "
+			       "the \"widget-drop-possible\" signal");
 
   /* Add lines controls */
   hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]