[glom] Update EggSpreadTable



commit d1950805a3eba5d9d54c4750fdcbac09b4ed5e02
Author: Murray Cumming <murrayc murrayc com>
Date:   Thu Oct 6 09:45:27 2011 +0200

    Update EggSpreadTable
    
    * glom/utility_widgets/eggspreadtable/: Update from libegg with Tristan's
    changes.
    * glom/utility_widgets/eggspreadtablemm/: Adapt.

 ChangeLog                                          |    8 +
 .../utility_widgets/eggspreadtable/eggmarshalers.c |   40 ++--
 .../utility_widgets/eggspreadtable/eggmarshalers.h |   14 +-
 .../eggspreadtable/eggspreadtablednd.c             |  302 +++++++++++++++-----
 .../eggspreadtable/eggspreadtablednd.h             |   45 +++-
 .../eggspreadtablemm/eggspreadtabledndmm.cc        |   50 +++-
 .../eggspreadtablemm/eggspreadtabledndmm.h         |   11 +-
 .../private/eggspreadtabledndmm_p.h                |    2 +-
 8 files changed, 341 insertions(+), 131 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 7493013..e9eaf77 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2011-10-06  Murray Cumming  <murrayc murrayc com>
+
+	Update EggSpreadTable
+
+	* glom/utility_widgets/eggspreadtable/: Update from libegg with Tristan's 
+	changes.
+	* glom/utility_widgets/eggspreadtablemm/: Adapt.
+
 2011-10-04  Murray Cumming  <murrayc murrayc com>
 
 	Move do_print_layout() to PrintLayoutUtils.
diff --git a/glom/utility_widgets/eggspreadtable/eggmarshalers.c b/glom/utility_widgets/eggspreadtable/eggmarshalers.c
index 80af893..f17eb06 100644
--- a/glom/utility_widgets/eggspreadtable/eggmarshalers.c
+++ b/glom/utility_widgets/eggspreadtable/eggmarshalers.c
@@ -53,31 +53,32 @@ G_BEGIN_DECLS
 #endif /* !G_ENABLE_DEBUG */
 
 
-/* BOOLEAN:OBJECT (./eggmarshalers.list:1) */
-extern void _egg_marshal_BOOLEAN__OBJECT (GClosure     *closure,
-                                          GValue       *return_value,
-                                          guint         n_param_values,
-                                          const GValue *param_values,
-                                          gpointer      invocation_hint,
-                                          gpointer      marshal_data);
+/* BOOLEAN:OBJECT,POINTER (./eggmarshalers.list:1) */
+extern void _egg_marshal_BOOLEAN__OBJECT_POINTER (GClosure     *closure,
+                                                  GValue       *return_value,
+                                                  guint         n_param_values,
+                                                  const GValue *param_values,
+                                                  gpointer      invocation_hint,
+                                                  gpointer      marshal_data);
 void
-_egg_marshal_BOOLEAN__OBJECT (GClosure     *closure,
-                              GValue       *return_value G_GNUC_UNUSED,
-                              guint         n_param_values,
-                              const GValue *param_values,
-                              gpointer      invocation_hint G_GNUC_UNUSED,
-                              gpointer      marshal_data)
+_egg_marshal_BOOLEAN__OBJECT_POINTER (GClosure     *closure,
+                                      GValue       *return_value G_GNUC_UNUSED,
+                                      guint         n_param_values,
+                                      const GValue *param_values,
+                                      gpointer      invocation_hint G_GNUC_UNUSED,
+                                      gpointer      marshal_data)
 {
-  typedef gboolean (*GMarshalFunc_BOOLEAN__OBJECT) (gpointer     data1,
-                                                    gpointer     arg_1,
-                                                    gpointer     data2);
-  register GMarshalFunc_BOOLEAN__OBJECT callback;
+  typedef gboolean (*GMarshalFunc_BOOLEAN__OBJECT_POINTER) (gpointer     data1,
+                                                            gpointer     arg_1,
+                                                            gpointer     arg_2,
+                                                            gpointer     data2);
+  register GMarshalFunc_BOOLEAN__OBJECT_POINTER callback;
   register GCClosure *cc = (GCClosure*) closure;
   register gpointer data1, data2;
   gboolean v_return;
 
   g_return_if_fail (return_value != NULL);
-  g_return_if_fail (n_param_values == 2);
+  g_return_if_fail (n_param_values == 3);
 
   if (G_CCLOSURE_SWAP_DATA (closure))
     {
@@ -89,10 +90,11 @@ _egg_marshal_BOOLEAN__OBJECT (GClosure     *closure,
       data1 = g_value_peek_pointer (param_values + 0);
       data2 = closure->data;
     }
-  callback = (GMarshalFunc_BOOLEAN__OBJECT) (marshal_data ? marshal_data : cc->callback);
+  callback = (GMarshalFunc_BOOLEAN__OBJECT_POINTER) (marshal_data ? marshal_data : cc->callback);
 
   v_return = callback (data1,
                        g_marshal_value_peek_object (param_values + 1),
+                       g_marshal_value_peek_pointer (param_values + 2),
                        data2);
 
   g_value_set_boolean (return_value, v_return);
diff --git a/glom/utility_widgets/eggspreadtable/eggmarshalers.h b/glom/utility_widgets/eggspreadtable/eggmarshalers.h
index 7307150..70dabfd 100644
--- a/glom/utility_widgets/eggspreadtable/eggmarshalers.h
+++ b/glom/utility_widgets/eggspreadtable/eggmarshalers.h
@@ -6,13 +6,13 @@
 
 G_BEGIN_DECLS
 
-/* BOOLEAN:OBJECT (./eggmarshalers.list:1) */
-extern void _egg_marshal_BOOLEAN__OBJECT (GClosure     *closure,
-                                          GValue       *return_value,
-                                          guint         n_param_values,
-                                          const GValue *param_values,
-                                          gpointer      invocation_hint,
-                                          gpointer      marshal_data);
+/* BOOLEAN:OBJECT,POINTER (./eggmarshalers.list:1) */
+extern void _egg_marshal_BOOLEAN__OBJECT_POINTER (GClosure     *closure,
+                                                  GValue       *return_value,
+                                                  guint         n_param_values,
+                                                  const GValue *param_values,
+                                                  gpointer      invocation_hint,
+                                                  gpointer      marshal_data);
 
 G_END_DECLS
 
diff --git a/glom/utility_widgets/eggspreadtable/eggspreadtablednd.c b/glom/utility_widgets/eggspreadtable/eggspreadtablednd.c
index c7f7e38..b07715a 100644
--- a/glom/utility_widgets/eggspreadtable/eggspreadtablednd.c
+++ b/glom/utility_widgets/eggspreadtable/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/glom/utility_widgets/eggspreadtable/eggspreadtablednd.h b/glom/utility_widgets/eggspreadtable/eggspreadtablednd.h
index dba5dc7..d6cdb1c 100644
--- a/glom/utility_widgets/eggspreadtable/eggspreadtablednd.h
+++ b/glom/utility_widgets/eggspreadtable/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/glom/utility_widgets/eggspreadtablemm/eggspreadtabledndmm.cc b/glom/utility_widgets/eggspreadtablemm/eggspreadtabledndmm.cc
index 12c3437..aa9c5e6 100644
--- a/glom/utility_widgets/eggspreadtablemm/eggspreadtabledndmm.cc
+++ b/glom/utility_widgets/eggspreadtablemm/eggspreadtabledndmm.cc
@@ -38,7 +38,7 @@ Egg::SpreadTableDnd* wrap(EggSpreadTableDnd* object, bool take_copy)
 namespace
 {
 
-static gboolean EggSpreadTableDnd_signal_widget_drop_possible_callback(EggSpreadTableDnd* self, GtkWidget* p0, void* data)
+static gboolean EggSpreadTableDnd_signal_widget_drop_possible_callback(EggSpreadTableDnd* self, GtkWidget* p0, gboolean* drop_possible, void* data)
 {
   using namespace Egg;
   typedef sigc::slot< bool, Gtk::Widget* > SlotType;
@@ -66,7 +66,7 @@ static gboolean EggSpreadTableDnd_signal_widget_drop_possible_callback(EggSpread
   return RType();
 }
 
-static gboolean EggSpreadTableDnd_signal_widget_drop_possible_notify_callback(EggSpreadTableDnd* self, GtkWidget* p0, void* data)
+static gboolean EggSpreadTableDnd_signal_widget_drop_possible_notify_callback(EggSpreadTableDnd* self, GtkWidget* p0, gboolean* drop_possible, void* data)
 {
   using namespace Egg;
   typedef sigc::slot< bool, Gtk::Widget* > SlotType;
@@ -137,7 +137,7 @@ void SpreadTableDnd_Class::class_init_function(void* g_class, void* class_data)
   klass->widget_drop_possible = &widget_drop_possible_callback;
 }
 
-gboolean SpreadTableDnd_Class::widget_drop_possible_callback(EggSpreadTableDnd* self, GtkWidget* p0)
+gboolean SpreadTableDnd_Class::widget_drop_possible_callback(EggSpreadTableDnd* self, GtkWidget* p0, gboolean* drop_possible)
 {
   Glib::ObjectBase *const obj_base = static_cast<Glib::ObjectBase*>(
       Glib::ObjectBase::_get_current_wrapper((GObject*)self));
@@ -157,8 +157,12 @@ gboolean SpreadTableDnd_Class::widget_drop_possible_callback(EggSpreadTableDnd*
       {
       #endif //GLIBMM_EXCEPTIONS_ENABLED
         // Call the virtual member method, which derived classes might override.
-        return static_cast<int>(obj->on_widget_drop_possible(Glib::wrap(p0)
-));
+        bool cpp_drop_possible = false;
+        const bool result = 
+          static_cast<int>(obj->on_widget_drop_possible(Glib::wrap(p0), 
+            cpp_drop_possible));
+        *drop_possible = cpp_drop_possible;
+        return result;
       #ifdef GLIBMM_EXCEPTIONS_ENABLED
       }
       catch(...)
@@ -175,7 +179,7 @@ gboolean SpreadTableDnd_Class::widget_drop_possible_callback(EggSpreadTableDnd*
 
   // Call the original underlying C function:
   if(base && base->widget_drop_possible)
-    return (*base->widget_drop_possible)(self, p0);
+    return (*base->widget_drop_possible)(self, p0, drop_possible);
 
   typedef gboolean RType;
   return RType();
@@ -259,31 +263,47 @@ void SpreadTableDnd::remove_child(Gtk::Widget& child)
   egg_spread_table_dnd_remove_child(gobj(), child.gobj());
 }
 
-void SpreadTableDnd::set_steal_events(bool steal_events)
+void SpreadTableDnd::set_drag_enabled(EggDragEnableMode drag_enabled)
+{
+  egg_spread_table_dnd_set_drag_enabled(gobj(), drag_enabled);
+}
+
+EggDragEnableMode SpreadTableDnd::get_drag_enabled() const
+{
+  return egg_spread_table_dnd_get_drag_enabled(const_cast<EggSpreadTableDnd*>(gobj()));
+}
+
+void SpreadTableDnd::set_drop_enabled(bool drop_enabled)
 {
-  egg_spread_table_dnd_set_steal_events(gobj(), steal_events);
+  egg_spread_table_dnd_set_drop_enabled(gobj(), drop_enabled);
 }
 
-bool SpreadTableDnd::get_steal_events() const
+bool SpreadTableDnd::get_drop_enabled() const
 {
-  return egg_spread_table_dnd_get_steal_events(const_cast<EggSpreadTableDnd*>(gobj()));
-} 
+  return egg_spread_table_dnd_get_drop_enabled(const_cast<EggSpreadTableDnd*>(gobj()));
+}
 
-bool SpreadTableDnd::on_widget_drop_possible(Gtk::Widget* widget)
+bool SpreadTableDnd::on_widget_drop_possible(Gtk::Widget* widget, bool& drop_possible)
 {
   BaseClassType *const base = static_cast<BaseClassType*>(
       g_type_class_peek_parent(G_OBJECT_GET_CLASS(gobject_)) // Get the parent class of the object class (The original underlying C class).
   );
 
   if(base && base->widget_drop_possible)
-    return (*base->widget_drop_possible)(gobj(), Glib::unwrap(widget));
+  {
+    gboolean c_drop_possible = FALSE;
+    const gboolean result =
+      (*base->widget_drop_possible)(gobj(), Glib::unwrap(widget), &c_drop_possible);
+    drop_possible = c_drop_possible;
+    return result;
+  }
   else
     return false;
 }
 
-Glib::SignalProxy1< bool, Gtk::Widget* > SpreadTableDnd::signal_widget_drop_possible()
+Glib::SignalProxy2< bool, Gtk::Widget*, bool& > SpreadTableDnd::signal_widget_drop_possible()
 {
-  return Glib::SignalProxy1< bool, Gtk::Widget* >(this, &SpreadTableDnd_signal_widget_drop_possible_info);
+  return Glib::SignalProxy2< bool, Gtk::Widget*, bool& >(this, &SpreadTableDnd_signal_widget_drop_possible_info);
 }
 
 } // namespace Egg
diff --git a/glom/utility_widgets/eggspreadtablemm/eggspreadtabledndmm.h b/glom/utility_widgets/eggspreadtablemm/eggspreadtabledndmm.h
index 91c7f03..8e5da33 100644
--- a/glom/utility_widgets/eggspreadtablemm/eggspreadtabledndmm.h
+++ b/glom/utility_widgets/eggspreadtablemm/eggspreadtabledndmm.h
@@ -19,6 +19,7 @@
 #define _EGG_SPREADTABLE_DND_H
 
 #include <glom/utility_widgets/eggspreadtablemm/eggspreadtablemm.h>
+#include <glom/utility_widgets/eggspreadtable/eggspreadtablednd.h> //For the enum, though we could wrap it instead.
 
 
 #ifndef DOXYGEN_SHOULD_SKIP_THIS
@@ -84,7 +85,7 @@ protected:
 
   //Default Signal Handlers::
 
-  bool on_widget_drop_possible(Gtk::Widget* widget);
+  bool on_widget_drop_possible(Gtk::Widget* widget, bool& drop_possible);
 
 private:
 
@@ -95,8 +96,10 @@ public:
 
   void insert_child(Gtk::Widget& child, int index);
   void remove_child(Gtk::Widget& child);
-  void set_steal_events(bool steal_events);
-  bool get_steal_events() const;
+  void set_drag_enabled(EggDragEnableMode drag_enabled);
+  EggDragEnableMode get_drag_enabled() const;
+  void set_drop_enabled(bool drop_enabled = true);
+  bool get_drop_enabled() const;
 
 
   /**
@@ -104,7 +107,7 @@ public:
    * <tt>void on_my_%widget_drop_possible()</tt>
    */
 
-  Glib::SignalProxy1< bool, Gtk::Widget* > signal_widget_drop_possible();
+  Glib::SignalProxy2< bool, Gtk::Widget*, bool& > signal_widget_drop_possible();
 };
 
 } // namespace Egg
diff --git a/glom/utility_widgets/eggspreadtablemm/private/eggspreadtabledndmm_p.h b/glom/utility_widgets/eggspreadtablemm/private/eggspreadtabledndmm_p.h
index af1f917..57ef6e4 100644
--- a/glom/utility_widgets/eggspreadtablemm/private/eggspreadtabledndmm_p.h
+++ b/glom/utility_widgets/eggspreadtablemm/private/eggspreadtabledndmm_p.h
@@ -35,7 +35,7 @@ protected:
   //These will call the *_impl member methods, which will then call the existing default signal callbacks, if any.
   //You could prevent the original default signal handlers being called by overriding the *_impl method.
 
-  static gboolean widget_drop_possible_callback(EggSpreadTableDnd* self, GtkWidget* p0);
+  static gboolean widget_drop_possible_callback(EggSpreadTableDnd* self, GtkWidget* p0, gboolean* drop_possible);
 
   //Callbacks (virtual functions):
 };



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