[glom] Use EggSpreadTableDnd.



commit 03e556e5605e23796e5d371c6d31a8c48bd03649
Author: Murray Cumming <murrayc murrayc com>
Date:   Mon Apr 18 11:15:07 2011 +0200

    Use EggSpreadTableDnd.
    
    * glom/utility_widgets/eggspreadtable/eggmarshalers.[h|c}
    * glom/utility_widgets/eggspreadtable/eggplaceholder.[h|c]
    * glom/utility_widgets/eggspreadtable/eggspreadtablednd.[h|c]:
      Added these files, copied from libegg.
    * glom/utility_widgets/eggspreadtablemm/eggspreadtabledndmm.[h|cc]:
    * glom/utility_widgets/eggspreadtablemm/private/eggspreadtabledndmm
    _p.h:
    Created a hand-written C++ wrapper for EggSpreadTableDnd.
    * glom/Makefile_glom.am: Mention the new files.
    * glom/utility_widgets/flowtable.h: Use SpreadTableDnd instead of
    SpreadTable, though we do not use the drag-and-drop functionality yet.

 ChangeLog                                          |   16 +
 Makefile_glom.am                                   |    9 +
 .../utility_widgets/eggspreadtable/eggmarshalers.c |  104 ++
 .../utility_widgets/eggspreadtable/eggmarshalers.h |   20 +
 .../eggspreadtable/eggplaceholder.c                |  211 ++++
 .../eggspreadtable/eggplaceholder.h                |   53 +
 .../eggspreadtable/eggspreadtablednd.c             | 1251 ++++++++++++++++++++
 .../eggspreadtable/eggspreadtablednd.h             |   67 ++
 .../eggspreadtable/testspreadtable.c               |  393 ------
 .../eggspreadtablemm/eggspreadtabledndmm.cc        |  134 +++
 .../eggspreadtablemm/eggspreadtabledndmm.h         |  113 ++
 .../private/eggspreadtabledndmm_p.h                |   45 +
 glom/utility_widgets/flowtable.h                   |    4 +-
 13 files changed, 2025 insertions(+), 395 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index eb3c136..7e136b9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+2011-04-18  Murray Cumming  <murrayc murrayc com>
+
+	Use EggSpreadTableDnd.
+
+	* glom/utility_widgets/eggspreadtable/eggmarshalers.[h|c}
+	* glom/utility_widgets/eggspreadtable/eggplaceholder.[h|c]
+	* glom/utility_widgets/eggspreadtable/eggspreadtablednd.[h|c]:
+  Added these files, copied from libegg.
+	* glom/utility_widgets/eggspreadtablemm/eggspreadtabledndmm.[h|cc]:
+	* glom/utility_widgets/eggspreadtablemm/private/eggspreadtabledndmm
+	_p.h:
+	Created a hand-written C++ wrapper for EggSpreadTableDnd.
+	* glom/Makefile_glom.am: Mention the new files.
+	* glom/utility_widgets/flowtable.h: Use SpreadTableDnd instead of
+	SpreadTable, though we do not use the drag-and-drop functionality yet.
+
 2011-04-12  Murray Cumming  <murrayc murrayc com>
 
 	Correct the sizing of the ... date button.
diff --git a/Makefile_glom.am b/Makefile_glom.am
index 9b3517f..47b23c0 100644
--- a/Makefile_glom.am
+++ b/Makefile_glom.am
@@ -178,11 +178,20 @@ glom_source_files = \
 	glom/utility_widgets/dialog_properties.h			\
 	glom/utility_widgets/flowtable.cc				\
 	glom/utility_widgets/flowtable.h				\
+	glom/utility_widgets/eggspreadtable/eggmarshalers.c \
+	glom/utility_widgets/eggspreadtable/eggmarshalers.h \
 	glom/utility_widgets/eggspreadtable/eggspreadtable.c \
 	glom/utility_widgets/eggspreadtable/eggspreadtable.h \
+	glom/utility_widgets/eggspreadtable/eggspreadtablednd.c \
+	glom/utility_widgets/eggspreadtable/eggspreadtablednd.h \
+	glom/utility_widgets/eggspreadtable/eggplaceholder.c \
+	glom/utility_widgets/eggspreadtable/eggplaceholder.h \
 	glom/utility_widgets/eggspreadtablemm/eggspreadtablemm.cc \
 	glom/utility_widgets/eggspreadtablemm/eggspreadtablemm.h \
+	glom/utility_widgets/eggspreadtablemm/eggspreadtabledndmm.cc \
+	glom/utility_widgets/eggspreadtablemm/eggspreadtabledndmm.h \
 	glom/utility_widgets/eggspreadtablemm/private/eggspreadtablemm_p.h \
+	glom/utility_widgets/eggspreadtablemm/private/eggspreadtabledndmm_p.h \
 	glom/utility_widgets/gimpruler/gimpruler.c \
 	glom/utility_widgets/gimpruler/gimpruler.h \
 	glom/utility_widgets/gimpruler/libgimpbase/gimpbase.h \
diff --git a/glom/utility_widgets/eggspreadtable/eggmarshalers.c b/glom/utility_widgets/eggspreadtable/eggmarshalers.c
new file mode 100644
index 0000000..80af893
--- /dev/null
+++ b/glom/utility_widgets/eggspreadtable/eggmarshalers.c
@@ -0,0 +1,104 @@
+
+#ifndef ___egg_marshal_MARSHAL_H__
+#define ___egg_marshal_MARSHAL_H__
+
+#include	<glib-object.h>
+
+G_BEGIN_DECLS
+
+#ifdef G_ENABLE_DEBUG
+#define g_marshal_value_peek_boolean(v)  g_value_get_boolean (v)
+#define g_marshal_value_peek_char(v)     g_value_get_char (v)
+#define g_marshal_value_peek_uchar(v)    g_value_get_uchar (v)
+#define g_marshal_value_peek_int(v)      g_value_get_int (v)
+#define g_marshal_value_peek_uint(v)     g_value_get_uint (v)
+#define g_marshal_value_peek_long(v)     g_value_get_long (v)
+#define g_marshal_value_peek_ulong(v)    g_value_get_ulong (v)
+#define g_marshal_value_peek_int64(v)    g_value_get_int64 (v)
+#define g_marshal_value_peek_uint64(v)   g_value_get_uint64 (v)
+#define g_marshal_value_peek_enum(v)     g_value_get_enum (v)
+#define g_marshal_value_peek_flags(v)    g_value_get_flags (v)
+#define g_marshal_value_peek_float(v)    g_value_get_float (v)
+#define g_marshal_value_peek_double(v)   g_value_get_double (v)
+#define g_marshal_value_peek_string(v)   (char*) g_value_get_string (v)
+#define g_marshal_value_peek_param(v)    g_value_get_param (v)
+#define g_marshal_value_peek_boxed(v)    g_value_get_boxed (v)
+#define g_marshal_value_peek_pointer(v)  g_value_get_pointer (v)
+#define g_marshal_value_peek_object(v)   g_value_get_object (v)
+#define g_marshal_value_peek_variant(v)  g_value_get_variant (v)
+#else /* !G_ENABLE_DEBUG */
+/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API.
+ *          Do not access GValues directly in your code. Instead, use the
+ *          g_value_get_*() functions
+ */
+#define g_marshal_value_peek_boolean(v)  (v)->data[0].v_int
+#define g_marshal_value_peek_char(v)     (v)->data[0].v_int
+#define g_marshal_value_peek_uchar(v)    (v)->data[0].v_uint
+#define g_marshal_value_peek_int(v)      (v)->data[0].v_int
+#define g_marshal_value_peek_uint(v)     (v)->data[0].v_uint
+#define g_marshal_value_peek_long(v)     (v)->data[0].v_long
+#define g_marshal_value_peek_ulong(v)    (v)->data[0].v_ulong
+#define g_marshal_value_peek_int64(v)    (v)->data[0].v_int64
+#define g_marshal_value_peek_uint64(v)   (v)->data[0].v_uint64
+#define g_marshal_value_peek_enum(v)     (v)->data[0].v_long
+#define g_marshal_value_peek_flags(v)    (v)->data[0].v_ulong
+#define g_marshal_value_peek_float(v)    (v)->data[0].v_float
+#define g_marshal_value_peek_double(v)   (v)->data[0].v_double
+#define g_marshal_value_peek_string(v)   (v)->data[0].v_pointer
+#define g_marshal_value_peek_param(v)    (v)->data[0].v_pointer
+#define g_marshal_value_peek_boxed(v)    (v)->data[0].v_pointer
+#define g_marshal_value_peek_pointer(v)  (v)->data[0].v_pointer
+#define g_marshal_value_peek_object(v)   (v)->data[0].v_pointer
+#define g_marshal_value_peek_variant(v)  (v)->data[0].v_pointer
+#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);
+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)
+{
+  typedef gboolean (*GMarshalFunc_BOOLEAN__OBJECT) (gpointer     data1,
+                                                    gpointer     arg_1,
+                                                    gpointer     data2);
+  register GMarshalFunc_BOOLEAN__OBJECT 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);
+
+  if (G_CCLOSURE_SWAP_DATA (closure))
+    {
+      data1 = closure->data;
+      data2 = g_value_peek_pointer (param_values + 0);
+    }
+  else
+    {
+      data1 = g_value_peek_pointer (param_values + 0);
+      data2 = closure->data;
+    }
+  callback = (GMarshalFunc_BOOLEAN__OBJECT) (marshal_data ? marshal_data : cc->callback);
+
+  v_return = callback (data1,
+                       g_marshal_value_peek_object (param_values + 1),
+                       data2);
+
+  g_value_set_boolean (return_value, v_return);
+}
+
+G_END_DECLS
+
+#endif /* ___egg_marshal_MARSHAL_H__ */
+
diff --git a/glom/utility_widgets/eggspreadtable/eggmarshalers.h b/glom/utility_widgets/eggspreadtable/eggmarshalers.h
new file mode 100644
index 0000000..7307150
--- /dev/null
+++ b/glom/utility_widgets/eggspreadtable/eggmarshalers.h
@@ -0,0 +1,20 @@
+
+#ifndef ___egg_marshal_MARSHAL_H__
+#define ___egg_marshal_MARSHAL_H__
+
+#include	<glib-object.h>
+
+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);
+
+G_END_DECLS
+
+#endif /* ___egg_marshal_MARSHAL_H__ */
+
diff --git a/glom/utility_widgets/eggspreadtable/eggplaceholder.c b/glom/utility_widgets/eggspreadtable/eggplaceholder.c
new file mode 100644
index 0000000..d0913e8
--- /dev/null
+++ b/glom/utility_widgets/eggspreadtable/eggplaceholder.c
@@ -0,0 +1,211 @@
+
+#include "eggplaceholder.h"
+
+/* GObjectClass */
+static void      egg_placeholder_finalize             (GObject    *object);
+
+/* GtkWidgetClass */
+static void      egg_placeholder_get_preferred_width  (GtkWidget  *widget,
+						       gint       *min_width,
+						       gint       *nat_width);
+static void      egg_placeholder_get_preferred_height (GtkWidget  *widget,
+						       gint       *min_height,
+						       gint       *nat_height);
+
+#define ANIMATION_STEP 0.12F  /* How much percentage of the size to animate per iteration */
+#define ANIMATION_FREQ 20    /* At what frequency in millisecs to animate */
+
+enum {
+  SIGNAL_ANIMATION_DONE,
+  NUM_SIGNALS
+};
+
+static guint placeholder_signals[NUM_SIGNALS] = { 0, };
+
+struct _EggPlaceholderPrivate
+{
+  gint           width;
+  gint           height;
+
+  GtkOrientation animation_orientation; /* Whether we are animating in/out horizontally or vertically */
+  gdouble        animation_percent;     /* A multiplier between 0 and 1 representing the current progress */
+  guint          animation_id;          /* The GSource id for the animation timeout */
+  EggPlaceholderAnimDirection animation_direction;  /* Whether the placeholder is animating in or out */
+};
+
+G_DEFINE_TYPE (EggPlaceholder, egg_placeholder, GTK_TYPE_DRAWING_AREA)
+
+static void egg_placeholder_class_init (EggPlaceholderClass * klass)
+{
+  GObjectClass   *object_class = G_OBJECT_CLASS (klass);
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+  object_class->finalize = egg_placeholder_finalize;
+
+  widget_class->get_preferred_width  = egg_placeholder_get_preferred_width;
+  widget_class->get_preferred_height = egg_placeholder_get_preferred_height;
+
+  placeholder_signals[SIGNAL_ANIMATION_DONE] = 
+    g_signal_new ("animation-done",
+		  G_OBJECT_CLASS_TYPE (klass),
+		  G_SIGNAL_RUN_FIRST,
+		  0, NULL, NULL,
+		  g_cclosure_marshal_VOID__VOID,
+		  G_TYPE_NONE, 0);
+
+  g_type_class_add_private (klass, sizeof (EggPlaceholderPrivate));
+}
+
+static void
+egg_placeholder_init (EggPlaceholder * placeholder)
+{
+  placeholder->priv = 
+    G_TYPE_INSTANCE_GET_PRIVATE (placeholder,
+				 EGG_TYPE_PLACEHOLDER,
+				 EggPlaceholderPrivate);
+
+  placeholder->priv->animation_percent = 1.0F;
+
+  /* Default visible, avoid cluttering code in eggspreadtablednd.c */
+  gtk_widget_show (GTK_WIDGET (placeholder));
+}
+
+static void
+egg_placeholder_finalize (GObject * object)
+{
+  EggPlaceholder *placeholder = EGG_PLACEHOLDER (object);
+
+  if (placeholder->priv->animation_id > 0)
+    {
+      g_source_remove (placeholder->priv->animation_id);
+      placeholder->priv->animation_id = 0;
+    }
+
+  G_OBJECT_CLASS (egg_placeholder_parent_class)->finalize (object);
+}
+
+static void
+egg_placeholder_get_preferred_width (GtkWidget  *widget,
+				     gint       *min_width,
+				     gint       *nat_width)
+{
+  EggPlaceholder *placeholder = EGG_PLACEHOLDER (widget);
+  gint            width;
+
+  if (placeholder->priv->animation_orientation == GTK_ORIENTATION_HORIZONTAL)
+    width = placeholder->priv->width * placeholder->priv->animation_percent;
+  else
+    width = placeholder->priv->width;
+
+  *min_width = *nat_width = width;
+}
+
+static void
+egg_placeholder_get_preferred_height (GtkWidget  *widget,
+				      gint       *min_height,
+				      gint       *nat_height)
+{
+  EggPlaceholder *placeholder = EGG_PLACEHOLDER (widget);
+  gint            height;
+
+  if (placeholder->priv->animation_orientation == GTK_ORIENTATION_VERTICAL)
+    height = placeholder->priv->height * placeholder->priv->animation_percent;
+  else
+    height = placeholder->priv->height;
+
+  *min_height = *nat_height = height;
+}
+
+static gboolean 
+placeholder_animate (EggPlaceholder *placeholder)
+{
+  if (placeholder->priv->animation_direction == EGG_PLACEHOLDER_ANIM_IN)
+    placeholder->priv->animation_percent += ANIMATION_STEP;
+  else if (placeholder->priv->animation_direction == EGG_PLACEHOLDER_ANIM_OUT)
+    placeholder->priv->animation_percent -= ANIMATION_STEP;
+  else
+    g_error ("Placeholder animation called while not animating");
+
+  placeholder->priv->animation_percent =
+    CLAMP (placeholder->priv->animation_percent, 0.0, 1.0);
+
+  gtk_widget_queue_resize (GTK_WIDGET (placeholder));
+
+  if (placeholder->priv->animation_percent >= 1.0 ||
+      placeholder->priv->animation_percent <= 0.0)
+    {
+      placeholder->priv->animation_id = 0;
+      placeholder->priv->animation_direction = EGG_PLACEHOLDER_ANIM_NONE;
+
+      g_signal_emit (placeholder, placeholder_signals[SIGNAL_ANIMATION_DONE], 0);
+
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
+void
+egg_placeholder_animate_in (EggPlaceholder *placeholder,
+			    GtkOrientation  orientation)
+{
+  g_return_if_fail (EGG_IS_PLACEHOLDER (placeholder));
+
+  placeholder->priv->animation_orientation = orientation;
+  placeholder->priv->animation_direction   = EGG_PLACEHOLDER_ANIM_IN;
+
+  if (placeholder->priv->animation_id == 0)
+    {
+      placeholder->priv->animation_percent = 0.0F;
+      placeholder->priv->animation_id = 
+	gdk_threads_add_timeout (ANIMATION_FREQ, 
+				 (GSourceFunc)placeholder_animate, 
+				 placeholder);
+    }
+
+  gtk_widget_queue_resize (GTK_WIDGET (placeholder));
+}
+
+void
+egg_placeholder_animate_out (EggPlaceholder *placeholder,
+			     GtkOrientation  orientation)
+{
+  g_return_if_fail (EGG_IS_PLACEHOLDER (placeholder));
+
+  placeholder->priv->animation_orientation = orientation;
+  placeholder->priv->animation_direction   = EGG_PLACEHOLDER_ANIM_OUT;
+
+  if (placeholder->priv->animation_id == 0)
+    {
+      placeholder->priv->animation_percent = 1.0F;
+      placeholder->priv->animation_id = 
+	gdk_threads_add_timeout (ANIMATION_FREQ, 
+				 (GSourceFunc)placeholder_animate, 
+				 placeholder);
+    }
+
+  gtk_widget_queue_resize (GTK_WIDGET (placeholder));
+}
+
+
+EggPlaceholderAnimDirection 
+egg_placeholder_get_animating (EggPlaceholder *placeholder)
+{
+  g_return_val_if_fail (EGG_IS_PLACEHOLDER (placeholder),
+			EGG_PLACEHOLDER_ANIM_NONE);
+
+  return placeholder->priv->animation_direction;
+}
+
+
+GtkWidget *
+egg_placeholder_new (gint width, 
+		     gint height)
+{
+  EggPlaceholder *placeholder = g_object_new (EGG_TYPE_PLACEHOLDER, NULL);
+
+  placeholder->priv->width  = width;
+  placeholder->priv->height = height;
+
+  return GTK_WIDGET (placeholder);
+}
diff --git a/glom/utility_widgets/eggspreadtable/eggplaceholder.h b/glom/utility_widgets/eggspreadtable/eggplaceholder.h
new file mode 100644
index 0000000..496cdff
--- /dev/null
+++ b/glom/utility_widgets/eggspreadtable/eggplaceholder.h
@@ -0,0 +1,53 @@
+ 
+#ifndef __EGG_PLACEHOLDER_H__
+#define __EGG_PLACEHOLDER_H__
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define EGG_TYPE_PLACEHOLDER            (egg_placeholder_get_type ())
+#define EGG_PLACEHOLDER(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), EGG_TYPE_PLACEHOLDER, EggPlaceholder))
+#define EGG_PLACEHOLDER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), EGG_TYPE_PLACEHOLDER, EggPlaceholderClass))
+#define EGG_IS_PLACEHOLDER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EGG_TYPE_PLACEHOLDER))
+#define EGG_IS_PLACEHOLDER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EGG_TYPE_PLACEHOLDER))
+#define EGG_PLACEHOLDER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), EGG_TYPE_PLACEHOLDER, EggPlaceholderClass))
+
+typedef struct _EggPlaceholder        EggPlaceholder;
+typedef struct _EggPlaceholderClass   EggPlaceholderClass;
+typedef struct _EggPlaceholderPrivate EggPlaceholderPrivate;
+
+
+typedef enum {
+  EGG_PLACEHOLDER_ANIM_NONE,
+  EGG_PLACEHOLDER_ANIM_IN,
+  EGG_PLACEHOLDER_ANIM_OUT
+} EggPlaceholderAnimDirection;
+
+
+struct _EggPlaceholder
+{
+  GtkDrawingArea drawing_area;
+	
+  EggPlaceholderPrivate *priv;
+};
+
+struct _EggPlaceholderClass
+{
+  GtkDrawingAreaClass parent_class;
+};
+
+GType         egg_placeholder_get_type        (void) G_GNUC_CONST;
+
+GtkWidget    *egg_placeholder_new             (gint            width,
+					       gint            height);
+void          egg_placeholder_animate_in      (EggPlaceholder *placeholder,
+					       GtkOrientation  orientation);
+void          egg_placeholder_animate_out     (EggPlaceholder *placeholder,
+					       GtkOrientation  orientation);
+
+EggPlaceholderAnimDirection egg_placeholder_get_animating (EggPlaceholder *placeholder);
+
+G_END_DECLS
+
+#endif /* __EGG_PLACEHOLDER_H__ */
diff --git a/glom/utility_widgets/eggspreadtable/eggspreadtablednd.c b/glom/utility_widgets/eggspreadtable/eggspreadtablednd.c
new file mode 100644
index 0000000..6fad48e
--- /dev/null
+++ b/glom/utility_widgets/eggspreadtable/eggspreadtablednd.c
@@ -0,0 +1,1251 @@
+/* gtkspreadtablednd.c
+ * Copyright (C) 2011 Openismus GmbH
+ *
+ * Authors:
+ *      Tristan Van Berkom <tristanvb openismus com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+#include <gtk/gtk.h>
+#include <string.h>
+#include "eggspreadtablednd.h"
+#include "eggplaceholder.h"
+#include "eggmarshalers.h"
+
+#define DEFAULT_LINES 2
+#define P_(msgid) (msgid)
+
+/* GtkWidgetClass */
+static void          egg_spread_table_dnd_realize            (GtkWidget         *widget);
+static gboolean      egg_spread_table_dnd_motion             (GtkWidget         *widget,
+							      GdkEventMotion    *event);
+static gboolean      egg_spread_table_dnd_leave              (GtkWidget         *widget,
+							      GdkEventCrossing  *event);
+static gboolean      egg_spread_table_dnd_button_press       (GtkWidget         *widget,
+							      GdkEventButton    *event);
+static gboolean      egg_spread_table_dnd_button_release     (GtkWidget         *widget,
+							      GdkEventButton    *event);
+static void          egg_spread_table_dnd_size_allocate      (GtkWidget         *widget,
+							      GtkAllocation     *allocation);
+
+/* GtkWidgetClass drag-source */
+static void          egg_spread_table_dnd_drag_data_get      (GtkWidget         *widget,
+							      GdkDragContext    *context,
+							      GtkSelectionData  *selection_data,
+							      guint              info,
+							      guint              time_);
+
+/* GtkWidgetClass drag-dest */
+static void          egg_spread_table_dnd_drag_leave         (GtkWidget         *widget,
+							      GdkDragContext    *context,
+							      guint              time_);
+static gboolean      egg_spread_table_dnd_drag_motion        (GtkWidget	        *widget,
+							      GdkDragContext    *context,
+							      gint               x,
+							      gint               y,
+							      guint              time_);
+static gboolean      egg_spread_table_dnd_drag_drop          (GtkWidget         *widget,
+							      GdkDragContext    *context,
+							      gint               x,
+							      gint               y,
+							      guint              time_);
+static void          egg_spread_table_dnd_drag_data_received (GtkWidget         *widget,
+							      GdkDragContext    *drag_context,
+							      gint               x,
+							      gint               y,
+							      GtkSelectionData  *data,
+							      guint              info,
+							      guint              time);
+
+/* GtkContainerClass */
+static void          egg_spread_table_dnd_remove             (GtkContainer      *container,
+							      GtkWidget         *child);
+
+/* EggSpreadTableClass */
+static void          egg_spread_table_dnd_insert_child       (EggSpreadTable    *spread_table,
+							      GtkWidget         *child,
+							      gint               index);
+static gint          egg_spread_table_dnd_build_segments     (EggSpreadTable    *table,
+							      gint               for_size,
+							      gint             **segments);
+
+/* 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,
+							EggSpreadTableDnd *spread_table);
+static void          drag_end                          (GtkWidget         *widget,
+							GdkDragContext    *context,
+							EggSpreadTableDnd *spread_table);
+static void          drag_data_get                     (GtkWidget         *widget,
+							GdkDragContext    *context,
+							GtkSelectionData  *selection,
+							guint              info,
+							guint              time,
+							EggSpreadTableDnd *spread_table);
+static gboolean      drag_failed                       (GtkWidget         *widget,
+							GdkDragContext    *drag_context,
+							GtkDragResult      result,
+							EggSpreadTableDnd *spread_table);
+
+static GtkWidget    *get_child_at_position             (EggSpreadTableDnd *spread_table,
+							gint               x,
+							gint               y);
+static gint          get_index_at_position             (EggSpreadTableDnd *spread_table,
+							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);
+static void          adjust_line_segment               (EggSpreadTableDnd *table,
+							gint               segment,
+							gint               offset);
+static void          lock_table                        (EggSpreadTableDnd *spread_table);
+static void          unlock_table                      (EggSpreadTableDnd *spread_table);
+static void          animate_out_drop_target           (EggSpreadTableDnd *table,
+							gboolean           end);
+
+typedef struct {
+  EggSpreadTableDnd *table;
+  GtkWidget         *child;
+} EggSpreadTableDndDragData;
+
+struct _EggSpreadTableDndPrivate {
+
+  /* State of drop target while drag-motion is happening over this spread table */
+  GtkWidget *drop_target;  /* Remember which child widget is the active placeholder */
+
+  /* After successfully calling gtk_drag_get_data(), the drag data ends up in this struct */
+  EggSpreadTableDndDragData drag_data;
+
+  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 */
+
+  gint       disappearing; /* Count of placeholders that are currently disappearing */
+
+  /* These states are used to trigger a drag operation on a child widget with no window */
+  gint       pressed_button;
+  gint       press_start_x;
+  gint       press_start_y;
+
+  /* Caching and locking the child configuration */
+  gint      *locked_config;
+
+};
+
+
+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
+egg_spread_table_dnd_class_init (EggSpreadTableDndClass *class)
+{
+  GtkWidgetClass      *widget_class    = GTK_WIDGET_CLASS (class);
+  GtkContainerClass   *container_class = GTK_CONTAINER_CLASS (class);
+  EggSpreadTableClass *spread_class    = EGG_SPREAD_TABLE_CLASS (class);
+
+  widget_class->realize              = egg_spread_table_dnd_realize;
+  widget_class->button_press_event   = egg_spread_table_dnd_button_press;
+  widget_class->button_release_event = egg_spread_table_dnd_button_release;
+  widget_class->motion_notify_event  = egg_spread_table_dnd_motion;
+  widget_class->leave_notify_event   = egg_spread_table_dnd_leave;
+
+  widget_class->size_allocate        = egg_spread_table_dnd_size_allocate;
+
+  /* Drag source */
+  widget_class->drag_data_get      = egg_spread_table_dnd_drag_data_get;
+
+  /* Drag dest */
+  widget_class->drag_leave         = egg_spread_table_dnd_drag_leave;
+  widget_class->drag_motion        = egg_spread_table_dnd_drag_motion;
+  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;
+
+  spread_class->insert_child            = egg_spread_table_dnd_insert_child;
+  spread_class->build_segments_for_size = egg_spread_table_dnd_build_segments;
+
+  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));
+}
+
+static void
+egg_spread_table_dnd_init (EggSpreadTableDnd *spread_table)
+{
+  EggSpreadTableDndPrivate *priv;
+
+  spread_table->priv = priv =
+    G_TYPE_INSTANCE_GET_PRIVATE (spread_table, EGG_TYPE_SPREAD_TABLE_DND, EggSpreadTableDndPrivate);
+
+  priv->pressed_button = -1;
+
+  /* Setup the spread table as a drag target for our target type */
+  gtk_drag_dest_set (GTK_WIDGET (spread_table),
+		     0,
+		     dnd_targets, G_N_ELEMENTS (dnd_targets),
+		     GDK_ACTION_MOVE);
+
+  /* Setup the spread table as a drag source for our target type also
+   * (to handle no-window widget children) */
+  gtk_drag_source_set (GTK_WIDGET (spread_table),
+		       0, dnd_targets, G_N_ELEMENTS (dnd_targets),
+		       GDK_ACTION_MOVE);
+
+  gtk_widget_set_has_window (GTK_WIDGET (spread_table), TRUE);
+}
+
+/*****************************************************
+ *                 GtkWidgetClass                    *
+ *****************************************************/
+static void
+egg_spread_table_dnd_realize (GtkWidget *widget)
+{
+  GtkAllocation allocation;
+  GdkWindow *window;
+  GdkWindowAttr attributes;
+  gint attributes_mask;
+
+  gtk_widget_set_realized (widget, TRUE);
+
+  gtk_widget_get_allocation (widget, &allocation);
+
+  attributes.window_type = GDK_WINDOW_CHILD;
+  attributes.x = allocation.x;
+  attributes.y = allocation.y;
+  attributes.width = allocation.width;
+  attributes.height = allocation.height;
+  attributes.wclass = GDK_INPUT_OUTPUT;
+  attributes.visual = gtk_widget_get_visual (widget);
+  attributes.event_mask = gtk_widget_get_events (widget)
+                         | GDK_VISIBILITY_NOTIFY_MASK | GDK_EXPOSURE_MASK
+                         | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK
+                         | GDK_POINTER_MOTION_MASK | GDK_LEAVE_NOTIFY_MASK;
+  attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
+
+  window = gdk_window_new (gtk_widget_get_parent_window (widget),
+                           &attributes, attributes_mask);
+  gtk_widget_set_window (widget, window);
+  gdk_window_set_user_data (window, widget);
+
+  gtk_style_context_set_background (gtk_widget_get_style_context (widget), window);
+}
+
+static gboolean
+egg_spread_table_dnd_motion (GtkWidget         *widget,
+			     GdkEventMotion    *event)
+{
+  EggSpreadTableDnd *spread_table = EGG_SPREAD_TABLE_DND (widget);
+
+  if (spread_table->priv->pressed_button >= 0 &&
+      gtk_drag_check_threshold (widget,
+				spread_table->priv->press_start_x,
+				spread_table->priv->press_start_y,
+				event->x, event->y))
+    {
+      spread_table->priv->drag_child =
+	get_child_at_position (spread_table,
+			       spread_table->priv->press_start_x,
+			       spread_table->priv->press_start_y);
+
+      if (spread_table->priv->drag_child)
+	{
+	  gtk_drag_begin (spread_table->priv->drag_child,
+			  gtk_drag_source_get_target_list (widget),
+			  GDK_ACTION_MOVE,
+			  spread_table->priv->pressed_button,
+			  (GdkEvent*)event);
+	  return TRUE;
+	}
+    }
+  return FALSE;
+}
+
+static gboolean
+egg_spread_table_dnd_leave (GtkWidget        *widget,
+			    G_GNUC_UNUSED GdkEventCrossing *event)
+{
+  EggSpreadTableDnd *spread_table = EGG_SPREAD_TABLE_DND (widget);
+
+  spread_table->priv->pressed_button = -1;
+
+  return TRUE;
+}
+
+static gboolean
+egg_spread_table_dnd_button_press (GtkWidget         *widget,
+				   GdkEventButton    *event)
+{
+  EggSpreadTableDnd *spread_table = EGG_SPREAD_TABLE_DND (widget);
+  gboolean           handled = FALSE;
+
+  if (event->button == 1 && event->type == GDK_BUTTON_PRESS)
+    {
+      /* Save press to possibly begin a drag */
+      if (get_child_at_position (spread_table, event->x, event->y) &&
+	  spread_table->priv->pressed_button < 0)
+	{
+	  spread_table->priv->pressed_button = event->button;
+	  spread_table->priv->press_start_x  = event->x;
+	  spread_table->priv->press_start_y  = event->y;
+
+	  handled = TRUE;
+	}
+    }
+
+  return handled;
+}
+
+static gboolean
+egg_spread_table_dnd_button_release (GtkWidget      *widget,
+				     GdkEventButton *event)
+{
+  EggSpreadTableDnd *spread_table = EGG_SPREAD_TABLE_DND (widget);
+
+  if (spread_table->priv->pressed_button == (gint)event->button)
+    spread_table->priv->pressed_button = -1;
+
+  return TRUE;
+}
+
+static void
+get_widget_size (GtkWidget      *widget,
+		 GtkOrientation  orientation,
+		 gint            for_size,
+		 gint           *min_size,
+		 gint           *nat_size)
+{
+  if (orientation == GTK_ORIENTATION_HORIZONTAL)
+    {
+      if (for_size < 0)
+	gtk_widget_get_preferred_width (widget, min_size, nat_size);
+      else
+	gtk_widget_get_preferred_width_for_height (widget, for_size, min_size, nat_size);
+    }
+  else
+    {
+      if (for_size < 0)
+	gtk_widget_get_preferred_height (widget, min_size, nat_size);
+      else
+	gtk_widget_get_preferred_height_for_width (widget, for_size, min_size, nat_size);
+    }
+}
+
+static void
+allocate_child (EggSpreadTableDnd *table,
+                GtkWidget         *child,
+                gint               item_offset,
+                gint               line_offset,
+                gint               item_size,
+                gint               line_size)
+{
+  GtkAllocation           widget_allocation;
+  GtkAllocation           child_allocation;
+  GtkOrientation          orientation;
+
+  gtk_widget_get_allocation (GTK_WIDGET (table), &widget_allocation);
+  orientation = gtk_orientable_get_orientation (GTK_ORIENTABLE (table));
+
+  if (gtk_widget_get_has_window (GTK_WIDGET (table)))
+    {
+      widget_allocation.x = 0;
+      widget_allocation.y = 0;
+    }
+
+  if (orientation == GTK_ORIENTATION_HORIZONTAL)
+    {
+      child_allocation.x      = widget_allocation.x + item_offset;
+      child_allocation.y      = widget_allocation.y + line_offset;
+      child_allocation.width  = item_size;
+      child_allocation.height = line_size;
+    }
+  else /* GTK_ORIENTATION_VERTICAL */
+    {
+      child_allocation.x      = widget_allocation.x + line_offset;
+      child_allocation.y      = widget_allocation.y + item_offset;
+      child_allocation.width  = line_size;
+      child_allocation.height = item_size;
+    }
+
+  gtk_widget_size_allocate (child, &child_allocation);
+}
+
+static void
+get_spread_table_dimentions (EggSpreadTableDnd *spread_table,
+			     gint               for_size,
+			     gint              *line_spacing,
+			     gint              *item_spacing,
+			     gint              *full_size,
+			     gint              *line_width)
+{
+  EggSpreadTable *table = EGG_SPREAD_TABLE (spread_table);
+  gint local_full_size, local_item_spacing, local_spacing;
+  gint lines = egg_spread_table_get_lines (table);
+  GtkAllocation allocation;
+
+  gtk_widget_get_allocation (GTK_WIDGET (table), &allocation);
+
+  if (gtk_orientable_get_orientation (GTK_ORIENTABLE (table)) == GTK_ORIENTATION_VERTICAL)
+    {
+      local_full_size    = for_size < 0 ? allocation.width : for_size;
+      local_spacing      = egg_spread_table_get_horizontal_spacing (table);
+      local_item_spacing = egg_spread_table_get_vertical_spacing (table);
+    }
+  else
+    {
+      local_full_size    = for_size < 0 ? allocation.height : for_size;
+      local_spacing      = egg_spread_table_get_vertical_spacing (table);
+      local_item_spacing = egg_spread_table_get_horizontal_spacing (table);
+    }
+
+  if (full_size)
+    *full_size = local_full_size;
+  if (line_spacing)
+    *line_spacing = local_spacing;
+  if (item_spacing)
+    *item_spacing = local_item_spacing;
+
+  if (line_width)
+    *line_width = (local_full_size - (local_spacing * (lines -1))) / lines;
+}
+
+static void
+egg_spread_table_dnd_size_allocate (GtkWidget         *widget,
+				    GtkAllocation     *allocation)
+{
+  EggSpreadTableDnd        *table = EGG_SPREAD_TABLE_DND (widget);
+  GList                    *list, *children;
+  gint                     *segments = NULL;
+  gint                      full_thickness;
+  gint                      i, j;
+  gint                      line_offset, item_offset;
+  gint                      line_thickness;
+  gint                      line_spacing;
+  gint                      item_spacing;
+  gint                      placeholder_cnt = 0;
+  gint                      lines;
+  GtkWidgetClass           *parent_parent_class;
+  GtkOrientation            orientation;
+
+  /* Skip the EggSpreadTableClass allocator, chain up to it's parent to resize
+   * the GdkWindow properly */
+  parent_parent_class = g_type_class_peek_parent (egg_spread_table_dnd_parent_class);
+  parent_parent_class->size_allocate (widget, allocation);
+
+  get_spread_table_dimentions (table, -1, &line_spacing, &item_spacing, &full_thickness, &line_thickness);
+  lines       = egg_spread_table_get_lines (EGG_SPREAD_TABLE (table));
+  orientation = gtk_orientable_get_orientation (GTK_ORIENTABLE (table));
+
+  egg_spread_table_build_segments_for_size (EGG_SPREAD_TABLE (table), full_thickness, &segments);
+
+  children = gtk_container_get_children (GTK_CONTAINER (table));
+
+  for (list = children, line_offset = 0, i = 0; i < lines;
+       line_offset += line_thickness + line_spacing, i++)
+    {
+      /* Count the placeholders on each line */
+      placeholder_cnt = 0;
+
+      for (j = 0, item_offset = 0; list && j < segments[i]; list = list->next, j++)
+	{
+	  GtkWidget *child = list->data;
+	  gint       child_size;
+
+	  if (!gtk_widget_get_visible (child))
+	    continue;
+
+	  get_widget_size (child, orientation, line_thickness, NULL, &child_size);
+
+	  /* Stop allocating children on this line after 2 placeholders
+	   * this avoids annoying flicker when moving a widget inside a single column */
+	  if (placeholder_cnt >= 2)
+	    continue;
+
+	  if (placeholder_cnt < 2 && EGG_IS_PLACEHOLDER (child))
+	      placeholder_cnt++;
+
+	  allocate_child (table, child, item_offset, line_offset, child_size, line_thickness);
+
+	  item_offset += child_size + item_spacing;
+	}
+    }
+
+  g_list_free (children);
+  g_free (segments);
+}
+
+
+/*****************************************************
+ *            GtkWidgetClass drag source             *
+ *****************************************************/
+
+static void
+egg_spread_table_dnd_drag_data_get (GtkWidget         *widget,
+				    G_GNUC_UNUSED GdkDragContext    *context,
+				    GtkSelectionData  *selection,
+				    G_GNUC_UNUSED guint              info,
+				    G_GNUC_UNUSED guint              time_)
+{
+  EggSpreadTableDnd        *spread_table = EGG_SPREAD_TABLE_DND (widget);
+  EggSpreadTableDndDragData drag_data    = { spread_table, NULL };
+  GdkAtom target;
+
+  target = gtk_selection_data_get_target (selection);
+
+  if (spread_table->priv->drag_child &&
+      target == dnd_target_atom_child)
+    {
+      drag_data.child = spread_table->priv->drag_child;
+
+      gtk_selection_data_set (selection, target, 8,
+			      (guchar*) &drag_data, sizeof (drag_data));
+    }
+}
+
+/*****************************************************
+ *            GtkWidgetClass drag dest               *
+ *****************************************************/
+static gint
+get_child_line (EggSpreadTableDnd *table,
+		GtkWidget         *child)
+{
+  gint size;
+
+  if (gtk_orientable_get_orientation (GTK_ORIENTABLE (table)) == GTK_ORIENTATION_VERTICAL)
+    size = gtk_widget_get_allocated_width (GTK_WIDGET (table));
+  else
+    size = gtk_widget_get_allocated_height (GTK_WIDGET (table));
+
+  return egg_spread_table_get_child_line (EGG_SPREAD_TABLE (table), child, size);
+}
+
+static void
+placeholder_animated_out (GtkWidget         *placeholder,
+			  EggSpreadTableDnd *spread_table)
+{
+  gint line = -1;
+  gboolean last_target = FALSE;
+
+  if (spread_table->priv->drop_target == placeholder)
+    {
+      spread_table->priv->drop_target = NULL;
+      last_target = TRUE;
+    }
+
+  if (spread_table->priv->dragging)
+    line = get_child_line (spread_table, placeholder);
+
+  gtk_container_remove (GTK_CONTAINER (spread_table), placeholder);
+
+  /* Adjust line segment here manually since table may be locked */
+  if (spread_table->priv->dragging)
+    adjust_line_segment (spread_table, line, -1);
+  else if (last_target)
+    /* Unlock the table after the drag is finished */
+    unlock_table (spread_table);
+
+  spread_table->priv->disappearing--;
+}
+
+static void
+egg_spread_table_dnd_drag_leave (GtkWidget         *widget,
+				 GdkDragContext    *context,
+				 guint              time_)
+{
+  EggSpreadTableDnd *spread_table = EGG_SPREAD_TABLE_DND (widget);
+
+  gtk_drag_get_data (widget, context, dnd_target_atom_child, time_);
+
+  /* Animate-out drop target for drop-zone spread table */
+  animate_out_drop_target (spread_table, TRUE);
+
+  /* Animate-out drop target for drag-source spread table
+   * (sometimes when drag'n'drop happens very fast no drag-leave gets
+   * emitted on the source spread table so we take care of it here)
+   */
+  if (spread_table->priv->drag_data.table != spread_table)
+    animate_out_drop_target (spread_table->priv->drag_data.table, TRUE);
+}
+
+static void
+get_placeholder_size (EggSpreadTableDnd *spread_table,
+		      gint              *width,
+		      gint              *height)
+{
+  GtkOrientation orientation = gtk_orientable_get_orientation (GTK_ORIENTABLE (spread_table));
+  gint           line_width;
+
+  /* Calculate the size of the required placeholder based on the dimentions of the drag widget */
+  get_spread_table_dimentions (spread_table, -1, NULL, NULL, NULL, &line_width);
+
+  if (orientation == GTK_ORIENTATION_VERTICAL)
+    {
+      gint min_width;
+
+      gtk_widget_get_preferred_width (spread_table->priv->drag_data.child, &min_width, NULL);
+
+      *width = MAX (line_width, min_width);
+
+      gtk_widget_get_preferred_height_for_width (spread_table->priv->drag_data.child,
+						 *width, height, NULL);
+    }
+  else
+    {
+      gint min_height;
+
+      gtk_widget_get_preferred_width (spread_table->priv->drag_data.child, &min_height, NULL);
+
+      *height = MAX (line_width, min_height);
+
+      gtk_widget_get_preferred_width_for_height (spread_table->priv->drag_data.child,
+						 *height, width, NULL);
+    }
+}
+
+static gboolean
+egg_spread_table_dnd_drag_motion (GtkWidget         *widget,
+				  GdkDragContext    *context,
+				  gint               x,
+				  gint               y,
+				  guint              time_)
+{
+  EggSpreadTableDnd *spread_table = EGG_SPREAD_TABLE_DND (widget);
+  gint               index, line, drop_index;
+
+  /* Could be comming from another spread table, lock it now incase
+   * its not already locked. */
+
+  gtk_drag_get_data (widget, context, dnd_target_atom_child, time_);
+
+  if (!drop_possible (spread_table, spread_table->priv->drag_data.child))
+    return FALSE;
+
+  lock_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
+       (EGG_PLACEHOLDER (spread_table->priv->drop_target)) != EGG_PLACEHOLDER_ANIM_NONE) ||
+      spread_table->priv->disappearing)
+    return TRUE;
+
+  if (spread_table->priv->drop_target)
+    gtk_container_child_get (GTK_CONTAINER (spread_table),
+			     spread_table->priv->drop_target,
+			     "position", &drop_index,
+			     NULL);
+  else
+    drop_index = -1;
+
+  index = get_index_at_position (spread_table, x, y, &line);
+
+  if (index != drop_index)
+    {
+
+      animate_out_drop_target (spread_table, FALSE);
+
+      if (index >= 0)
+	{
+	  gint width, height;
+
+	  /* Import the drag data, get the drag widget and query it's size for this spread table */
+	  get_placeholder_size (spread_table, &width, &height);
+
+	  spread_table->priv->drop_target = egg_placeholder_new (width, height);
+	  egg_spread_table_insert_child (EGG_SPREAD_TABLE (spread_table),
+					 spread_table->priv->drop_target, index);
+	  adjust_line_segment (spread_table, line, 1);
+
+	  egg_placeholder_animate_in (EGG_PLACEHOLDER (spread_table->priv->drop_target),
+				      gtk_orientable_get_orientation (GTK_ORIENTABLE (spread_table)));
+	}
+    }
+
+  return TRUE;
+}
+
+static gboolean
+egg_spread_table_dnd_drag_drop (GtkWidget         *widget,
+				GdkDragContext    *context,
+				G_GNUC_UNUSED gint               x,
+				G_GNUC_UNUSED gint               y,
+				guint              time_)
+{
+  EggSpreadTableDnd *spread_table = EGG_SPREAD_TABLE_DND (widget);
+
+  gtk_drag_get_data (widget, context, dnd_target_atom_child, time_);
+
+  if (spread_table->priv->drop_target &&
+      spread_table->priv->drag_data.child)
+    {
+      gint drop_index;
+
+      /* Carry the widget over */
+      g_object_ref (spread_table->priv->drag_data.child);
+
+      gtk_container_remove (GTK_CONTAINER (spread_table->priv->drag_data.table),
+			    spread_table->priv->drag_data.child);
+
+      /* Get the appropriate target index */
+      gtk_container_child_get (GTK_CONTAINER (spread_table),
+			       spread_table->priv->drop_target,
+			       "position", &drop_index,
+			       NULL);
+
+      /* Insert drag child at the index */
+      egg_spread_table_insert_child (EGG_SPREAD_TABLE (spread_table),
+				     spread_table->priv->drag_data.child,
+				     drop_index);
+      g_object_unref (spread_table->priv->drag_data.child);
+
+      /* Ensure visibility */
+      gtk_widget_show (spread_table->priv->drag_data.child);
+
+      /* Hide the drop target placeholder in the target spread table,
+       * it will be removed and the spread table unlocked after animating out
+       * (the placeholder started animating out at "drag-leave" time).
+       */
+      gtk_widget_hide (spread_table->priv->drop_target);
+
+      gtk_drag_finish (context, TRUE, TRUE, time_);
+      return TRUE;
+    }
+  else
+    {
+      gtk_drag_finish (context, FALSE, TRUE, time_);
+      return FALSE;
+    }
+
+}
+
+static void
+egg_spread_table_dnd_drag_data_received (GtkWidget        *widget,
+					 GdkDragContext   *context,
+					 G_GNUC_UNUSED gint              x,
+					 G_GNUC_UNUSED gint              y,
+					 GtkSelectionData *data,
+					 G_GNUC_UNUSED guint             info,
+					 guint             time_)
+{
+  EggSpreadTableDnd         *spread_table = EGG_SPREAD_TABLE_DND (widget);
+  EggSpreadTableDndDragData *drag_data;
+
+  memset (&spread_table->priv->drag_data, 0x0, sizeof (EggSpreadTableDndDragData));
+
+  g_return_if_fail (gtk_selection_data_get_format (data) == 8);
+  g_return_if_fail (gtk_selection_data_get_length (data) == sizeof (EggSpreadTableDndDragData));
+  g_return_if_fail (gtk_selection_data_get_target (data) == dnd_target_atom_child);
+
+  drag_data = (EggSpreadTableDndDragData*) gtk_selection_data_get_data (data);
+  memcpy (&spread_table->priv->drag_data, drag_data, sizeof (EggSpreadTableDndDragData));
+
+  gdk_drag_status (context, GDK_ACTION_MOVE, time_);
+}
+
+/*****************************************************
+ *                GtkContainerClass                  *
+ *****************************************************/
+static void
+egg_spread_table_dnd_remove (GtkContainer *container,
+			     GtkWidget    *child)
+{
+  /* 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);
+    }
+
+  GTK_CONTAINER_CLASS (egg_spread_table_dnd_parent_class)->remove (container, child);
+}
+
+
+/*****************************************************
+ *               EggSpreadTableClass                 *
+ *****************************************************/
+static void
+egg_spread_table_dnd_insert_child (EggSpreadTable *spread_table,
+				   GtkWidget      *child,
+				   gint            index)
+{
+  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);
+    }
+}
+
+static gint
+egg_spread_table_dnd_build_segments (EggSpreadTable *table,
+				     gint            for_size,
+				     gint          **segments)
+{
+  EggSpreadTableDnd        *dnd_table = EGG_SPREAD_TABLE_DND (table);
+  EggSpreadTableDndPrivate *priv = dnd_table->priv;
+  GList                    *list, *children;
+  gint                      i, j, lines;
+  gint                      largest_line = 0, line_size = 0;
+  gint                      line_thickness;
+  gint                      spacing;
+  GtkOrientation            orientation;
+  gboolean                  first_widget = TRUE;
+
+  if (!priv->locked_config)
+    return EGG_SPREAD_TABLE_CLASS
+      (egg_spread_table_dnd_parent_class)->build_segments_for_size (table, for_size, segments);
+
+  get_spread_table_dimentions (dnd_table, for_size, NULL, &spacing, NULL, &line_thickness);
+
+  children    = gtk_container_get_children (GTK_CONTAINER (table));
+  orientation = gtk_orientable_get_orientation (GTK_ORIENTABLE (table));
+  lines       = egg_spread_table_get_lines (table);
+
+  for (list = children, i = 0; i < lines; i++)
+    {
+      for (j = 0; list && j < priv->locked_config[i]; list = list->next, j++)
+	{
+	  GtkWidget *child = list->data;
+	  gint       child_size;
+
+	  if (!gtk_widget_get_visible (child))
+	    continue;
+
+	  get_widget_size (child, orientation, line_thickness, NULL, &child_size);
+
+	  line_size += child_size;
+	  if (!first_widget)
+	    line_size += spacing;
+	  else
+	    first_widget = FALSE;
+	}
+
+      largest_line = MAX (largest_line, line_size);
+      line_size = 0;
+      first_widget = TRUE;
+    }
+
+  if (segments)
+    *segments = g_memdup (priv->locked_config, lines * sizeof (gint));
+
+  g_list_free (children);
+
+  return largest_line;
+}
+
+
+/*****************************************************
+ *              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       *
+ *****************************************************/
+
+static void
+drag_begin (GtkWidget         *widget,
+	    G_GNUC_UNUSED GdkDragContext    *context,
+	    EggSpreadTableDnd *spread_table)
+{
+  GtkAllocation   allocation;
+  gint            drop_index;
+
+  /* Mark the spread table for an active drag */
+  lock_table (spread_table);
+  spread_table->priv->dragging = TRUE;
+
+  /* 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
+   * default drop target */
+  gtk_container_child_get (GTK_CONTAINER (spread_table),
+			   spread_table->priv->drag_child,
+			   "position", &drop_index,
+			   NULL);
+
+  /* Create a placeholder of the correct dimentions and insert it at the drag origin */
+  gtk_widget_get_allocation (widget, &allocation);
+  spread_table->priv->drop_target = egg_placeholder_new (allocation.width, allocation.height);
+
+  egg_spread_table_insert_child (EGG_SPREAD_TABLE (spread_table),
+				 spread_table->priv->drop_target,
+				 drop_index);
+
+  /* Add one index for the new placeholder */
+  adjust_line_segment (spread_table,
+		       get_child_line (spread_table, spread_table->priv->drop_target), 1);
+
+  /* Hide the drag child (we cant remove it because it needs a GdkWindow in the mean time) */
+  gtk_widget_hide (spread_table->priv->drag_child);
+}
+
+static void
+drag_end (G_GNUC_UNUSED GtkWidget         *widget,
+	  G_GNUC_UNUSED GdkDragContext    *context,
+	  EggSpreadTableDnd *spread_table)
+{
+  /* Sometimes when drag'n'drop happens very fast, drag-leave,
+   * drag-failed and drag-drop dont happen, so we cancel it out here
+   */
+  animate_out_drop_target (spread_table, TRUE);
+}
+
+static void
+drag_data_get (GtkWidget         *widget,
+	       G_GNUC_UNUSED GdkDragContext    *context,
+	       GtkSelectionData  *selection,
+	       G_GNUC_UNUSED guint              info,
+	       G_GNUC_UNUSED guint              time,
+	       EggSpreadTableDnd *spread_table)
+{
+  EggSpreadTableDndDragData drag_data = { spread_table, NULL };
+  GdkAtom target;
+
+  target = gtk_selection_data_get_target (selection);
+
+  if (target == dnd_target_atom_child)
+    {
+      drag_data.child = widget;
+
+      gtk_selection_data_set (selection, target, 8,
+			      (guchar*) &drag_data, sizeof (drag_data));
+    }
+}
+
+static gboolean
+drag_failed (GtkWidget         *widget,
+	     G_GNUC_UNUSED GdkDragContext    *drag_context,
+	     G_GNUC_UNUSED GtkDragResult      result,
+	     G_GNUC_UNUSED EggSpreadTableDnd *spread_table)
+{
+  gtk_widget_show (widget);
+
+  return FALSE;
+}
+
+static gint
+get_index_at_position (EggSpreadTableDnd *spread_table,
+		       gint               x,
+		       gint               y,
+		       gint              *line_ret)
+{
+  EggSpreadTable *table;
+  GtkWidget      *widget, *child;
+  GList          *children, *l;
+  GtkAllocation   allocation;
+  gint            placeholder_cnt = 0;
+  GtkOrientation  orientation = gtk_orientable_get_orientation (GTK_ORIENTABLE (spread_table));
+  gint           *segments, lines, line = -1, i, full_size, spacing, position, line_width, first_child;
+  gint            index = -1;
+
+  widget = GTK_WIDGET (spread_table);
+  table  = EGG_SPREAD_TABLE (spread_table);
+
+  /* First find the "line" in question */
+  lines    = egg_spread_table_get_lines (table);
+  segments = egg_spread_table_get_segments (table);
+
+  get_spread_table_dimentions (spread_table, -1, &spacing, NULL, &full_size, &line_width);
+
+  if (orientation == GTK_ORIENTATION_VERTICAL)
+    position = x;
+  else
+    position = y;
+
+  for (i = 0; i < lines; i++)
+    {
+      gint start, end;
+
+      start = line_width * i + (spacing / 2) * i;
+      end   = start + line_width + (spacing / 2) * i;
+
+      if (i == lines - 1)
+	end = full_size;
+
+      if (position >= start && position <= end)
+	{
+	  line = i;
+	  break;
+	}
+    }
+  g_assert (line >= 0);
+
+  /* Get the first child on this line */
+  for (i = 0, first_child = 0; i < line; i++)
+    first_child += segments[i];
+
+  children = gtk_container_get_children (GTK_CONTAINER (spread_table));
+
+  for (l = g_list_nth (children, first_child), i = 0;
+       l != NULL && index < 0 && i < segments[line];
+       l = l->next, i++)
+    {
+      child = l->data;
+
+      if (!gtk_widget_get_visible (child))
+	continue;
+
+      gtk_widget_get_allocation (child, &allocation);
+
+      if (child == spread_table->priv->drop_target)
+	{
+	  if (orientation == GTK_ORIENTATION_VERTICAL)
+	    {
+	      if (y < allocation.y + allocation.height)
+		index = first_child + i;
+	    }
+	  else
+	    {
+	      if (x < allocation.x + allocation.width)
+		index = first_child + i;
+	    }
+
+	  placeholder_cnt++;
+	}
+      else
+	{
+	  if (orientation == GTK_ORIENTATION_VERTICAL)
+	    {
+	      if (y < allocation.y + allocation.height / 2)
+		index = first_child + i + placeholder_cnt;
+	    }
+	  else
+	    {
+	      if (x < allocation.x + allocation.width / 2)
+		index = first_child + i + placeholder_cnt;
+	    }
+	}
+    }
+
+  if (index < 0)
+    index = first_child + segments[line];
+
+  g_list_free (children);
+
+  g_free (segments);
+
+  if (line_ret)
+    *line_ret = line;
+
+  g_assert (index >= 0);
+
+  return index;
+}
+
+static GtkWidget *
+get_child_at_position (EggSpreadTableDnd *spread_table,
+		       gint               x,
+		       gint               y)
+{
+  GtkWidget    *child, *ret_child = NULL;
+  GList        *children, *l;
+  GtkAllocation allocation;
+
+  children = gtk_container_get_children (GTK_CONTAINER (spread_table));
+
+  for (l = children; ret_child == NULL && l != NULL; l = l->next)
+    {
+      child = l->data;
+
+      if (!gtk_widget_get_visible (child))
+	continue;
+
+      gtk_widget_get_allocation (child, &allocation);
+
+      if (x >= allocation.x && x <= allocation.x + allocation.width &&
+	  y >= allocation.y && y <= allocation.y + allocation.height)
+	{
+	  ret_child = child;
+	}
+    }
+
+  g_list_free (children);
+
+  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 (G_GNUC_UNUSED GSignalInvocationHint *ihint,
+			     GValue                *return_accu,
+			     const GValue          *handler_return,
+			     G_GNUC_UNUSED 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;
+}
+
+static void
+adjust_line_segment (EggSpreadTableDnd *table,
+		     gint               segment,
+		     gint               offset)
+{
+  if (table->priv->locked_config)
+    table->priv->locked_config[segment] += offset;
+}
+
+static void
+animate_out_drop_target (EggSpreadTableDnd *table,
+			 gboolean           end)
+{
+  if (table->priv->drop_target &&
+      egg_placeholder_get_animating
+      (EGG_PLACEHOLDER (table->priv->drop_target)) != EGG_PLACEHOLDER_ANIM_OUT)
+    {
+      egg_placeholder_animate_out (EGG_PLACEHOLDER (table->priv->drop_target),
+				   gtk_orientable_get_orientation (GTK_ORIENTABLE (table)));
+
+      g_signal_connect (table->priv->drop_target, "animation-done",
+			G_CALLBACK (placeholder_animated_out), table);
+
+      table->priv->disappearing++;
+    }
+
+  if (end)
+    table->priv->dragging = FALSE;
+}
+
+static void
+lock_table (EggSpreadTableDnd *table)
+
+{
+  if (table->priv->locked_config == NULL)
+    table->priv->locked_config = egg_spread_table_get_segments (EGG_SPREAD_TABLE (table));
+}
+
+static void
+unlock_table (EggSpreadTableDnd *table)
+{
+
+  g_free (table->priv->locked_config);
+  table->priv->locked_config = NULL;
+
+  gtk_widget_queue_resize (GTK_WIDGET (table));
+}
+
+/*****************************************************
+ *                       API                         *
+ *****************************************************/
+
+/**
+ * egg_spread_table_dnd_new:
+ * @orientation: The #GtkOrientation for the #EggSpreadTableDnd
+ * @lines: The fixed amount of lines to distribute children to.
+ *
+ * Creates a #EggSpreadTableDnd.
+ *
+ * Returns: A new #EggSpreadTableDnd container
+ */
+GtkWidget *
+egg_spread_table_dnd_new (GtkOrientation orientation,
+			  guint          lines)
+{
+  return (GtkWidget *)g_object_new (EGG_TYPE_SPREAD_TABLE_DND,
+				    "orientation", orientation,
+				    "lines", lines,
+				    NULL);
+}
diff --git a/glom/utility_widgets/eggspreadtable/eggspreadtablednd.h b/glom/utility_widgets/eggspreadtable/eggspreadtablednd.h
new file mode 100644
index 0000000..36c323b
--- /dev/null
+++ b/glom/utility_widgets/eggspreadtable/eggspreadtablednd.h
@@ -0,0 +1,67 @@
+/* 
+ * Copyright (C) 2011 Openismus GmbH
+ *
+ * Authors:
+ *      Tristan Van Berkom <tristanvb openismus com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __EGG_SPREAD_TABLE_DND_H__
+#define __EGG_SPREAD_TABLE_DND_H__
+
+#include <gtk/gtk.h>
+#include "eggspreadtable.h"
+
+G_BEGIN_DECLS
+
+
+#define EGG_TYPE_SPREAD_TABLE_DND            (egg_spread_table_dnd_get_type ())
+#define EGG_SPREAD_TABLE_DND(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), EGG_TYPE_SPREAD_TABLE_DND, EggSpreadTableDnd))
+#define EGG_SPREAD_TABLE_DND_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), EGG_TYPE_SPREAD_TABLE_DND, EggSpreadTableDndClass))
+#define EGG_IS_SPREAD_TABLE_DND(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EGG_TYPE_SPREAD_TABLE_DND))
+#define EGG_IS_SPREAD_TABLE_DND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EGG_TYPE_SPREAD_TABLE_DND))
+#define EGG_SPREAD_TABLE_DND_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), EGG_TYPE_SPREAD_TABLE_DND, EggSpreadTableDndClass))
+
+typedef struct _EggSpreadTableDnd            EggSpreadTableDnd;
+typedef struct _EggSpreadTableDndPrivate     EggSpreadTableDndPrivate;
+typedef struct _EggSpreadTableDndClass       EggSpreadTableDndClass;
+
+
+struct _EggSpreadTableDnd
+{
+  EggSpreadTable parent_instance;
+
+  /*< private >*/
+  EggSpreadTableDndPrivate *priv;
+};
+
+struct _EggSpreadTableDndClass
+{
+  EggSpreadTableClass parent_class;
+
+  gboolean  (* widget_drop_possible) (EggSpreadTableDnd *table, GtkWidget *widget);
+};
+
+GType                 egg_spread_table_dnd_get_type              (void) G_GNUC_CONST;
+GtkWidget            *egg_spread_table_dnd_new                   (GtkOrientation  orientation,
+								  guint           lines);
+
+
+G_END_DECLS
+
+
+#endif /* __EGG_SPREAD_TABLE_H__ */
diff --git a/glom/utility_widgets/eggspreadtablemm/eggspreadtabledndmm.cc b/glom/utility_widgets/eggspreadtablemm/eggspreadtabledndmm.cc
new file mode 100644
index 0000000..873700b
--- /dev/null
+++ b/glom/utility_widgets/eggspreadtablemm/eggspreadtabledndmm.cc
@@ -0,0 +1,134 @@
+/*
+ *
+ * Copyright 2011 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glom/utility_widgets/eggspreadtablemm/eggspreadtabledndmm.h>
+#include <glom/utility_widgets/eggspreadtablemm/private/eggspreadtabledndmm_p.h>
+
+
+#include <glib.h>
+#include <gtk/gtk.h>
+#include <glom/utility_widgets/eggspreadtable/eggspreadtablednd.h>
+
+namespace Glib
+{
+
+Egg::SpreadTableDnd* wrap(EggSpreadTableDnd* object, bool take_copy)
+{
+  return dynamic_cast<Egg::SpreadTableDnd *> (Glib::wrap_auto ((GObject*)(object), take_copy));
+}
+
+} /* namespace Glib */
+
+namespace Egg
+{
+
+
+/* The *_Class implementation: */
+
+const Glib::Class& SpreadTableDnd_Class::init()
+{
+  if(!gtype_) // create the GType if necessary
+  {
+    // Glib::Class has to know the class init function to clone custom types.
+    class_init_func_ = &SpreadTableDnd_Class::class_init_function;
+
+    // This is actually just optimized away, apparently with no harm.
+    // Make sure that the parent type has been created.
+    //CppClassParent::CppObjectType::get_type();
+
+    // Create the wrapper type, with the same class/instance size as the base type.
+    register_derived_type(egg_spread_table_get_type());
+
+    // Add derived versions of interfaces, if the C type implements any interfaces:
+    Gtk::Orientable::add_interface(get_type());
+
+  }
+
+  return *this;
+}
+
+
+void SpreadTableDnd_Class::class_init_function(void* g_class, void* class_data)
+{
+  BaseClassType *const klass = static_cast<BaseClassType*>(g_class);
+  CppClassParent::class_init_function(klass, class_data);
+
+
+}
+
+
+Glib::ObjectBase* SpreadTableDnd_Class::wrap_new(GObject* o)
+{
+  return manage(new SpreadTableDnd((EggSpreadTableDnd*)(o)));
+
+}
+
+
+/* The implementation: */
+
+SpreadTableDnd::SpreadTableDnd(const Glib::ConstructParams& construct_params)
+:
+  SpreadTable(construct_params)
+{
+  }
+
+SpreadTableDnd::SpreadTableDnd(EggSpreadTableDnd* castitem)
+:
+  SpreadTable((EggSpreadTable*)(castitem))
+{
+  }
+
+SpreadTableDnd::~SpreadTableDnd()
+{
+  destroy_();
+}
+
+SpreadTableDnd::CppClassType SpreadTableDnd::spreadtable_class_; // initialize static member
+
+GType SpreadTableDnd::get_type()
+{
+  return spreadtable_class_.init().get_type();
+}
+
+
+GType SpreadTableDnd::get_base_type()
+{
+  return egg_spread_table_get_type();
+}
+
+
+SpreadTableDnd::SpreadTableDnd()
+:
+  // Mark this class as non-derived to allow C++ vfuncs to be skipped.
+  Glib::ObjectBase(0),
+  SpreadTable(Glib::ConstructParams(spreadtable_class_.init()))
+{
+
+
+}
+
+SpreadTableDnd::SpreadTableDnd(Gtk::Orientation orientation, guint lines)
+:
+  // Mark this class as non-derived to allow C++ vfuncs to be skipped.
+  Glib::ObjectBase(0),
+  SpreadTable(Glib::ConstructParams(spreadtable_class_.init(), "orientation", ((GtkOrientation)(orientation)), "lines", lines, static_cast<char*>(0)))
+{
+}
+
+} // namespace Egg
diff --git a/glom/utility_widgets/eggspreadtablemm/eggspreadtabledndmm.h b/glom/utility_widgets/eggspreadtablemm/eggspreadtabledndmm.h
new file mode 100644
index 0000000..069a65b
--- /dev/null
+++ b/glom/utility_widgets/eggspreadtablemm/eggspreadtabledndmm.h
@@ -0,0 +1,113 @@
+/* Copyright (C) 2011 The gtkmm Development Team
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _EGG_SPREADTABLE_DND_H
+#define _EGG_SPREADTABLE_DND_H
+
+#include <glom/utility_widgets/eggspreadtablemm/eggspreadtablemm.h>
+
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+typedef struct _EggSpreadTableDnd EggSpreadTableDnd;
+typedef struct _EggSpreadTableDndClass EggSpreadTableDndClass;
+#endif /* DOXYGEN_SHOULD_SKIP_THIS */
+
+
+namespace Egg
+{ class SpreadTableDnd_Class; } // namespace Egg
+namespace Egg
+{
+
+class SpreadTableDnd
+: public SpreadTable
+{
+  public:
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+  typedef SpreadTableDnd CppObjectType;
+  typedef SpreadTableDnd_Class CppClassType;
+  typedef EggSpreadTableDnd BaseObjectType;
+  typedef EggSpreadTableDndClass BaseClassType;
+#endif /* DOXYGEN_SHOULD_SKIP_THIS */
+
+  virtual ~SpreadTableDnd();
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+
+private:
+  friend class SpreadTableDnd_Class;
+  static CppClassType spreadtable_class_;
+
+  // noncopyable
+  SpreadTableDnd(const SpreadTableDnd&);
+  SpreadTableDnd& operator=(const SpreadTableDnd&);
+
+protected:
+  explicit SpreadTableDnd(const Glib::ConstructParams& construct_params);
+  explicit SpreadTableDnd(EggSpreadTableDnd* castitem);
+
+#endif /* DOXYGEN_SHOULD_SKIP_THIS */
+
+public:
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+  static GType get_type()      G_GNUC_CONST;
+
+
+  static GType get_base_type() G_GNUC_CONST;
+#endif
+
+  ///Provides access to the underlying C GtkObject.
+  EggSpreadTableDnd*       gobj()       { return reinterpret_cast<EggSpreadTableDnd*>(gobject_); }
+
+  ///Provides access to the underlying C GtkObject.
+  const EggSpreadTableDnd* gobj() const { return reinterpret_cast<EggSpreadTableDnd*>(gobject_); }
+
+
+public:
+  //C++ methods used to invoke GTK+ virtual functions:
+
+protected:
+  //GTK+ Virtual Functions (override these to change behaviour):
+
+  //Default Signal Handlers::
+
+
+private:
+
+
+public:
+  SpreadTableDnd();
+  explicit SpreadTableDnd(Gtk::Orientation orientation, guint lines);
+};
+
+} // namespace Egg
+
+
+namespace Glib
+{
+  /** A Glib::wrap() method for this object.
+   *
+   * @param object The C instance.
+   * @param take_copy False if the result should take ownership of the C instance. True if it should take a new copy or ref.
+   * @result A C++ instance that wraps this C instance.
+   *
+   * @relates Egg::SpreadTableDnd
+   */
+  Egg::SpreadTableDnd* wrap(EggSpreadTableDnd* object, bool take_copy = false);
+} //namespace Glib
+
+
+#endif /* _EGG_SPREADTABLE_H */
diff --git a/glom/utility_widgets/eggspreadtablemm/private/eggspreadtabledndmm_p.h b/glom/utility_widgets/eggspreadtablemm/private/eggspreadtabledndmm_p.h
new file mode 100644
index 0000000..7acf0f9
--- /dev/null
+++ b/glom/utility_widgets/eggspreadtablemm/private/eggspreadtabledndmm_p.h
@@ -0,0 +1,45 @@
+#ifndef _EGG_SPREADTABLE_DND_P_H
+#define _EGG_SPREADTABLE_DND_P_H
+
+
+#include <glom/utility_widgets/eggspreadtablemm/private/eggspreadtablemm_p.h>
+
+#include <glibmm/class.h>
+
+namespace Egg
+{
+
+class SpreadTableDnd_Class : public Glib::Class
+{
+public:
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+  typedef SpreadTableDnd CppObjectType;
+  typedef EggSpreadTableDnd BaseObjectType;
+  typedef EggSpreadTableDndClass BaseClassType;
+  typedef SpreadTable_Class CppClassParent;
+  typedef EggSpreadTableClass BaseClassParent;
+
+  friend class SpreadTableDnd;
+#endif /* DOXYGEN_SHOULD_SKIP_THIS */
+
+  const Glib::Class& init();
+
+
+  static void class_init_function(void* g_class, void* class_data);
+
+  static Glib::ObjectBase* wrap_new(GObject*);
+
+protected:
+
+  //Callbacks (default signal handlers):
+  //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.
+
+  //Callbacks (virtual functions):
+};
+
+
+} // namespace Egg
+
+
+#endif /* _EGG_SPREADTABLE_P_H */
diff --git a/glom/utility_widgets/flowtable.h b/glom/utility_widgets/flowtable.h
index 8a426e3..df1c95c 100644
--- a/glom/utility_widgets/flowtable.h
+++ b/glom/utility_widgets/flowtable.h
@@ -22,13 +22,13 @@
 #define GLOM_UTILITYWIDGETS_FLOWTABLE_H
 
 #include <gtkmm.h>
-#include <glom/utility_widgets/eggspreadtablemm/eggspreadtablemm.h>
+#include <glom/utility_widgets/eggspreadtablemm/eggspreadtabledndmm.h>
 #include "layoutwidgetbase.h"
 
 namespace Glom
 {
 
-class FlowTable : public Egg::SpreadTable
+class FlowTable : public Egg::SpreadTableDnd
 {
 public:
   FlowTable();



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