[glom] Update EggSpreadTableDnd from libegg.



commit 4474bc6e0b1e1d64224b50a6fb4724e9b715db69
Author: Murray Cumming <murrayc murrayc com>
Date:   Thu Sep 1 12:06:56 2011 +0200

    Update EggSpreadTableDnd from libegg.
    
    * glom/utility_widgets/eggspreadtable/eggspreadtablednd.[h|c]:
    Updated from libegg.
    * glom/utility_widgets/eggspreadtablemm/eggspreadtabledndmm.[h|cc]:
    Wrap the new API to add and remove widgets. Note the extra reference() in
    remove_child(), like Gtk::Container::remove().
    * glom/utility_widgets/eggspreadtablemm/test_spreadtablednd.cc: Adapt.
    * glom/utility_widgets/flowtable.[h|cc]: Adapt and make several corrections,
    for instance to really find our intermediate hbox parents.
    However, there is still a warning (from our code) about trying to remove a
    hbox that has no parent.
    * glom/mode_data/flowtablewithfields.[h|cc]: Remove the add_before parameters,
    always adding at the end, because we do not need the ability to insert
      anywhere else, and doing so required examining the children, but
      EggSpreadTableDnd adds internal children that we don't want to care about.

 ChangeLog                                          |   19 +
 glom/mode_data/flowtablewithfields.cc              |  126 ++----
 glom/mode_data/flowtablewithfields.h               |   16 +-
 .../eggspreadtable/eggspreadtablednd.c             |  470 +++++++++++---------
 .../eggspreadtable/eggspreadtablednd.h             |   14 +-
 .../eggspreadtablemm/eggspreadtabledndmm.cc        |   30 ++
 .../eggspreadtablemm/eggspreadtabledndmm.h         |    5 +
 .../eggspreadtablemm/eggspreadtablemm.h            |    3 +-
 .../eggspreadtablemm/test_spreadtablednd.cc        |    4 +-
 glom/utility_widgets/flowtable.cc                  |  242 +++++------
 glom/utility_widgets/flowtable.h                   |   16 +-
 po/ChangeLog                                       |    6 +
 po/POTFILES.in                                     |    1 +
 13 files changed, 510 insertions(+), 442 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index c1f4845..974c593 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,22 @@
+2011-09-01  Murray Cumming  <murrayc murrayc com>
+
+	Update EggSpreadTableDnd from libegg. 
+
+	* glom/utility_widgets/eggspreadtable/eggspreadtablednd.[h|c]:
+	Updated from libegg.
+	* glom/utility_widgets/eggspreadtablemm/eggspreadtabledndmm.[h|cc]:
+	Wrap the new API to add and remove widgets. Note the extra reference() in 
+	remove_child(), like Gtk::Container::remove().
+	* glom/utility_widgets/eggspreadtablemm/test_spreadtablednd.cc: Adapt.
+	* glom/utility_widgets/flowtable.[h|cc]: Adapt and make several corrections, 
+	for instance to really find our intermediate hbox parents.
+	However, there is still a warning (from our code) about trying to remove a 
+	hbox that has no parent. 
+	* glom/mode_data/flowtablewithfields.[h|cc]: Remove the add_before parameters,
+	always adding at the end, because we do not need the ability to insert 
+  anywhere else, and doing so required examining the children, but 
+  EggSpreadTableDnd adds internal children that we don't want to care about.
+
 2011-08-31  Murray Cumming  <murrayc murrayc com>
 
 	Print Layout: Allow the user to choose row and column line widths and color.
diff --git a/glom/mode_data/flowtablewithfields.cc b/glom/mode_data/flowtablewithfields.cc
index 7c5f430..4fa95bb 100644
--- a/glom/mode_data/flowtablewithfields.cc
+++ b/glom/mode_data/flowtablewithfields.cc
@@ -65,11 +65,15 @@ FlowTableWithFields::~FlowTableWithFields()
   {
     View_Composite_Glom* pViewFirst = dynamic_cast<View_Composite_Glom*>(iter->m_first);
     if(pViewFirst)
+    {
       remove_view(pViewFirst);
+    }
 
-   View_Composite_Glom* pViewSecond = dynamic_cast<View_Composite_Glom*>(iter->m_second);
+    View_Composite_Glom* pViewSecond = dynamic_cast<View_Composite_Glom*>(iter->m_second);
     if(pViewSecond)
+    {
       remove_view(pViewSecond);
+    }
   }
 }
 
@@ -90,16 +94,11 @@ void FlowTableWithFields::set_table(const Glib::ustring& table_name)
 
 void FlowTableWithFields::add_layout_item(const sharedptr<LayoutItem>& item)
 {
-  add_layout_item_at_position(item, m_list_layoutwidgets.end());
-}
-
-void FlowTableWithFields::add_layout_item_at_position(const sharedptr<LayoutItem>& item, const type_list_layoutwidgets::iterator& add_before)
-{
   //Get derived type and do the appropriate thing:
   sharedptr<LayoutItem_Field> field = sharedptr<LayoutItem_Field>::cast_dynamic(item);
   if(field)
   {
-    add_field_at_position(field, m_table_name, add_before);
+    add_field(field, m_table_name);
 
     //Do not allow editing of auto-increment fields:
     sharedptr<const Field> field_details = field->get_full_field_details();
@@ -116,41 +115,41 @@ void FlowTableWithFields::add_layout_item_at_position(const sharedptr<LayoutItem
     sharedptr<LayoutItem_Portal> portal = sharedptr<LayoutItem_Portal>::cast_dynamic(item);
     if(portal)
     {
-      add_layout_portal_at_position(portal, add_before);
+      add_layout_portal(portal);
     }
     else
     {
       sharedptr<LayoutItem_Notebook> notebook = sharedptr<LayoutItem_Notebook>::cast_dynamic(item);
       if(notebook)
       {
-        add_layout_notebook_at_position(notebook, add_before);
+        add_layout_notebook(notebook);
       }
       else
       {
         sharedptr<LayoutGroup> group = sharedptr<LayoutGroup>::cast_dynamic(item);
         if(group)
-          add_layout_group_at_position(group, add_before);
+          add_layout_group(group);
         else
         {
           sharedptr<LayoutItem_Button> layout_button = sharedptr<LayoutItem_Button>::cast_dynamic(item);
           if(layout_button)
-            add_button_at_position(layout_button, m_table_name, add_before);
+            add_button(layout_button, m_table_name);
           else
           {
             sharedptr<LayoutItem_Text> layout_textobject = sharedptr<LayoutItem_Text>::cast_dynamic(item);
             if(layout_textobject)
-              add_textobject_at_position(layout_textobject, m_table_name, add_before);
+              add_textobject(layout_textobject, m_table_name);
             else
             {
               sharedptr<LayoutItem_Image> layout_imageobject = sharedptr<LayoutItem_Image>::cast_dynamic(item);
               if(layout_imageobject)
-                add_imageobject_at_position(layout_imageobject, m_table_name, add_before);
+                add_imageobject(layout_imageobject, m_table_name);
               else
               {
                 sharedptr<LayoutItem_Placeholder> layout_placeholder =
                   sharedptr<LayoutItem_Placeholder>::cast_dynamic(item);
                 if(layout_placeholder)
-                  add_placeholder_at_position(layout_placeholder, m_table_name, add_before);
+                  add_placeholder(layout_placeholder, m_table_name);
               }
             }
           }
@@ -162,11 +161,6 @@ void FlowTableWithFields::add_layout_item_at_position(const sharedptr<LayoutItem
 
 void FlowTableWithFields::add_layout_group(const sharedptr<LayoutGroup>& group, bool with_indent)
 {
-  add_layout_group_at_position(group, m_list_layoutwidgets.end(), with_indent);
-}
-
-void FlowTableWithFields::add_layout_group_at_position(const sharedptr<LayoutGroup>& group, const type_list_layoutwidgets::iterator& add_before, bool with_indent)
-{
   if(!group)
     return;
 
@@ -234,7 +228,7 @@ void FlowTableWithFields::add_layout_group_at_position(const sharedptr<LayoutGro
 
     m_sub_flow_tables.push_back(flow_table);
     flow_table->set_layout_item(group, m_table_name);
-    add_layoutwidgetbase(flow_table, add_before);
+    add_layoutwidgetbase(flow_table);
 
     //Connect signal:
     flow_table->signal_field_edited().connect( sigc::mem_fun(*this, &FlowTableWithFields::on_flowtable_entry_edited) );
@@ -325,7 +319,7 @@ Box_Data_Calendar_Related* FlowTableWithFields::create_related_calendar(const sh
   return 0;
 }
 
-void FlowTableWithFields::add_layout_portal_at_position(const sharedptr<LayoutItem_Portal>& portal, const type_list_layoutwidgets::iterator& add_before)
+void FlowTableWithFields::add_layout_portal(const sharedptr<LayoutItem_Portal>& portal)
 {
   Box_Data_Portal* portal_box = 0;
   sharedptr<LayoutItem_CalendarPortal> calendar_portal = sharedptr<LayoutItem_CalendarPortal>::cast_dynamic(portal);
@@ -337,13 +331,13 @@ void FlowTableWithFields::add_layout_portal_at_position(const sharedptr<LayoutIt
   if(portal_box)
   {
     add(*portal_box, true /* expand */);
-    add_layoutwidgetbase(portal_box, add_before);
+    add_layoutwidgetbase(portal_box);
   }
   else
     std::cerr << G_STRFUNC << ": No portal was created." << std::endl;
 }
 
-void FlowTableWithFields::add_layout_notebook_at_position(const sharedptr<LayoutItem_Notebook>& notebook, const type_list_layoutwidgets::iterator& add_before)
+void FlowTableWithFields::add_layout_notebook(const sharedptr<LayoutItem_Notebook>& notebook)
 {
   if(!notebook)
     return;
@@ -379,7 +373,7 @@ void FlowTableWithFields::add_layout_notebook_at_position(const sharedptr<Layout
         portal_box->show();
         notebook_widget->append_page(*portal_box, *tab_label);
 
-        add_layoutwidgetbase(portal_box, add_before);
+        add_layoutwidgetbase(portal_box);
       }
       else
       {
@@ -429,7 +423,7 @@ void FlowTableWithFields::add_layout_notebook_at_position(const sharedptr<Layout
 
         m_sub_flow_tables.push_back(flow_table);
         flow_table->set_layout_item(group, m_table_name);
-        add_layoutwidgetbase(flow_table, add_before);
+        add_layoutwidgetbase(flow_table);
 
         //Connect signal:
         flow_table->signal_field_edited().connect( sigc::mem_fun(*this, &FlowTableWithFields::on_flowtable_entry_edited) );
@@ -443,13 +437,9 @@ void FlowTableWithFields::add_layout_notebook_at_position(const sharedptr<Layout
     }
   }
 
-  add_layoutwidgetbase(notebook_widget, add_before);
+  add_layoutwidgetbase(notebook_widget);
   //add_view(button); //So it can get the document.
-  Gtk::Widget* widget = dynamic_cast<Gtk::Widget*>(*add_before);
-  if(widget)
-    insert_before (*notebook_widget, *widget, true /* expand */);
-  else
-    add(*notebook_widget, true /* expand */);
+  add(*notebook_widget, true /* expand */);
 }
 
 /*
@@ -507,17 +497,12 @@ void FlowTableWithFields::add_group(const Glib::ustring& group_name, const Glib:
 
 void FlowTableWithFields::add_field(const sharedptr<LayoutItem_Field>& layoutitem_field, const Glib::ustring& table_name)
 {
-  add_field_at_position(layoutitem_field, table_name, m_list_layoutwidgets.end());
-}
-
-void FlowTableWithFields::add_field_at_position(const sharedptr<LayoutItem_Field>& layoutitem_field, const Glib::ustring& table_name, const type_list_layoutwidgets::iterator& add_before)
-{
   Info info;
   info.m_field = layoutitem_field;
 
   //Add the entry or checkbox (handled by the DataWidget)
   DataWidget* pDataWidget = Gtk::manage(new DataWidget(layoutitem_field, table_name, get_document()) ); //TODO_Leak: Possibly leaked, according to valgrind.
-  add_layoutwidgetbase(pDataWidget, add_before);
+  add_layoutwidgetbase(pDataWidget);
   add_view(pDataWidget); //So it can get the document.
 
   info.m_second = pDataWidget;
@@ -555,11 +540,7 @@ void FlowTableWithFields::add_field_at_position(const sharedptr<LayoutItem_Field
   eventbox->set_events(Gdk::ALL_EVENTS_MASK);
   eventbox->show_all();
 
-  Gtk::Widget* widget = dynamic_cast<Gtk::Widget*>(*add_before);
-  if(widget)
-    insert_before(*eventbox, *(info.m_second), *widget, true);
-  else
-    add(*eventbox, *(info.m_second), true);
+  add(*eventbox, *(info.m_second), true);
 
   info.m_second->signal_edited().connect( sigc::bind(sigc::mem_fun(*this, &FlowTableWithFields::on_entry_edited), layoutitem_field)  ); //TODO:  Is it a good idea to bind the LayoutItem? sigc::bind() probably stores a copy at this point.
 
@@ -574,7 +555,7 @@ void FlowTableWithFields::add_field_at_position(const sharedptr<LayoutItem_Field
 }
 
 
-void FlowTableWithFields::add_button_at_position(const sharedptr<LayoutItem_Button>& layoutitem_button, const Glib::ustring& table_name, const type_list_layoutwidgets::iterator& add_before)
+void FlowTableWithFields::add_button(const sharedptr<LayoutItem_Button>& layoutitem_button, const Glib::ustring& table_name)
 {
   //Add the widget
   ButtonGlom* button = Gtk::manage(new ButtonGlom());
@@ -587,7 +568,7 @@ void FlowTableWithFields::add_button_at_position(const sharedptr<LayoutItem_Butt
 
   button->show();
 
-  add_layoutwidgetbase(button, add_before);
+  add_layoutwidgetbase(button);
   //add_view(button); //So it can get the document.
 
   const FieldFormatting::HorizontalAlignment alignment =
@@ -610,16 +591,12 @@ void FlowTableWithFields::add_button_at_position(const sharedptr<LayoutItem_Butt
     expand = true;
   }
 
-  Gtk::Widget* widget = dynamic_cast<Gtk::Widget*>(*add_before);
-  if(widget)
-    insert_before(*widget_to_add, *widget, expand);
-  else
-    add(*widget_to_add, expand);
+  add(*widget_to_add, expand);
 
   apply_formatting(*button, layoutitem_button);
 }
 
-void FlowTableWithFields::add_textobject_at_position(const sharedptr<LayoutItem_Text>& layoutitem_text, const Glib::ustring& table_name , const type_list_layoutwidgets::iterator& add_before)
+void FlowTableWithFields::add_textobject(const sharedptr<LayoutItem_Text>& layoutitem_text, const Glib::ustring& table_name)
 {
   //Add the widget:
 
@@ -638,16 +615,12 @@ void FlowTableWithFields::add_textobject_at_position(const sharedptr<LayoutItem_
 
   apply_formatting(*label, layoutitem_text);
 
-  add_layoutwidgetbase(label, add_before);
+  add_layoutwidgetbase(label);
 
   const Glib::ustring title = layoutitem_text->get_title();
   if(title.empty())
   {
-    Gtk::Widget* widget = dynamic_cast<Gtk::Widget*>(*add_before);
-    if(widget)
-      insert_before(*alignment_label, *widget, true /* expand */);
-    else
-      add(*alignment_label, true /* expand */);
+    add(*alignment_label, true /* expand */);
   }
   else
   {
@@ -659,17 +632,13 @@ void FlowTableWithFields::add_textobject_at_position(const sharedptr<LayoutItem_
     title_label->set_layout_item(layoutitem_text, table_name);
     title_label->show();
     alignment_title->add(*title_label);
-    add_layoutwidgetbase(title_label, add_before);
+    add_layoutwidgetbase(title_label);
 
-    Gtk::Widget* widget = dynamic_cast<Gtk::Widget*>(*add_before);
-    if(widget)
-      insert_before (*alignment_title, *alignment_label, *widget, true /* expand */);
-    else
-      add(*alignment_title, *alignment_label, true /* expand */);
+    add(*alignment_title, *alignment_label, true /* expand */);
   }
 }
 
-void FlowTableWithFields::add_placeholder_at_position(const sharedptr<LayoutItem_Placeholder>& /* layoutitem_placeholder */, const Glib::ustring& /* table_name */, const type_list_layoutwidgets::iterator& add_before)
+void FlowTableWithFields::add_placeholder(const sharedptr<LayoutItem_Placeholder>& /* layoutitem_placeholder */, const Glib::ustring& /* table_name */)
 {
   //Delete any existing placeholder (there can be only one):
   delete m_placeholder;
@@ -685,15 +654,11 @@ void FlowTableWithFields::add_placeholder_at_position(const sharedptr<LayoutItem
 
   m_placeholder->add(*preview);
 
-  m_list_layoutwidgets.insert(add_before, preview);
-  Gtk::Widget* widget = dynamic_cast<Gtk::Widget*>(*add_before);
-  if(widget)
-    insert_before(*m_placeholder, *widget, false /* expand */);
-  else
-    add(*m_placeholder, false);
+  m_list_layoutwidgets.push_back(preview);
+  add(*m_placeholder, false);
 }
 
-void FlowTableWithFields::add_imageobject_at_position(const sharedptr<LayoutItem_Image>& layoutitem_image, const Glib::ustring& table_name , const type_list_layoutwidgets::iterator& add_before)
+void FlowTableWithFields::add_imageobject(const sharedptr<LayoutItem_Image>& layoutitem_image, const Glib::ustring& table_name)
 {
   //Add the widget:
   ImageGlom* image = Gtk::manage(new ImageGlom());
@@ -703,17 +668,13 @@ void FlowTableWithFields::add_imageobject_at_position(const sharedptr<LayoutItem
   image->set_layout_item(layoutitem_image, table_name);
   image->show();
 
-  add_layoutwidgetbase(image, add_before);
+  add_layoutwidgetbase(image);
   //add_view(button); //So it can get the document.
 
   const Glib::ustring title = layoutitem_image->get_title();
   if(title.empty())
   {
-    Gtk::Widget* widget = dynamic_cast<Gtk::Widget*>(*add_before);
-    if(widget)
-      insert_before(*image, *widget, true /* expand */);
-    else
-      add(*image, true /* expand */);
+    add(*image, true /* expand */);
   }
   else
   {
@@ -724,11 +685,7 @@ void FlowTableWithFields::add_imageobject_at_position(const sharedptr<LayoutItem
     Gtk::Label* title_label = Gtk::manage(new Gtk::Label(title));
     title_label->show();
     alignment_title->add(*title_label);
-    Gtk::Widget* widget = dynamic_cast<Gtk::Widget*>(*add_before);
-    if(widget)
-      insert_before(*alignment_title, *image, *widget, true /* expand */);
-    else
-      add(*alignment_title, *image, true /* expand */);
+    add(*alignment_title, *image, true /* expand */);
   }
 }
 
@@ -1141,12 +1098,7 @@ void FlowTableWithFields::set_design_mode(bool value)
 
 void FlowTableWithFields::add_layoutwidgetbase(LayoutWidgetBase* layout_widget)
 {
-  add_layoutwidgetbase(layout_widget, m_list_layoutwidgets.end());
-}
-
-void FlowTableWithFields::add_layoutwidgetbase(LayoutWidgetBase* layout_widget, const type_list_layoutwidgets::iterator& add_before)
-{
-  m_list_layoutwidgets.insert(add_before, layout_widget);
+  m_list_layoutwidgets.push_back(layout_widget);
 
   //Handle layout_changed signal:
 #ifndef GLOM_ENABLE_CLIENT_ONLY
diff --git a/glom/mode_data/flowtablewithfields.h b/glom/mode_data/flowtablewithfields.h
index 463be08..3ad7bde 100644
--- a/glom/mode_data/flowtablewithfields.h
+++ b/glom/mode_data/flowtablewithfields.h
@@ -228,18 +228,14 @@ private:
   typedef std::list< LayoutWidgetBase* > type_list_layoutwidgets;
   type_list_layoutwidgets m_list_layoutwidgets;
 
-  void add_field_at_position(const sharedptr<LayoutItem_Field>& layoutitem_field, const Glib::ustring& table_name, const type_list_layoutwidgets::iterator& add_before);
-  void add_button_at_position(const sharedptr<LayoutItem_Button>& layoutitem_button, const Glib::ustring& table_name, const type_list_layoutwidgets::iterator& add_before);
-  void add_textobject_at_position(const sharedptr<LayoutItem_Text>& layoutitem_text, const Glib::ustring& table_name, const type_list_layoutwidgets::iterator& add_before);
-  void add_imageobject_at_position(const sharedptr<LayoutItem_Image>& layoutitem_image, const Glib::ustring& table_name, const type_list_layoutwidgets::iterator& add_before);
-  void add_placeholder_at_position(const sharedptr<LayoutItem_Placeholder>& layoutitem_image, const Glib::ustring& table_name, const type_list_layoutwidgets::iterator& add_before);
+  void add_button(const sharedptr<LayoutItem_Button>& layoutitem_button, const Glib::ustring& table_name);
+  void add_textobject(const sharedptr<LayoutItem_Text>& layoutitem_text, const Glib::ustring& table_name);
+  void add_imageobject(const sharedptr<LayoutItem_Image>& layoutitem_image, const Glib::ustring& table_name);
+  void add_placeholder(const sharedptr<LayoutItem_Placeholder>& layoutitem_image, const Glib::ustring& table_name);
 
   void add_layoutwidgetbase(LayoutWidgetBase* layout_widget);
-  void add_layoutwidgetbase(LayoutWidgetBase* layout_widget, const type_list_layoutwidgets::iterator& add_before);
-  void add_layout_item_at_position(const sharedptr<LayoutItem>& item, const type_list_layoutwidgets::iterator& add_before);
-  void add_layout_group_at_position(const sharedptr<LayoutGroup>& group, const type_list_layoutwidgets::iterator& add_before, bool with_indent = true);
-  void add_layout_notebook_at_position(const sharedptr<LayoutItem_Notebook>& notebook, const type_list_layoutwidgets::iterator& add_before);
-  void add_layout_portal_at_position(const sharedptr<LayoutItem_Portal>& portal, const type_list_layoutwidgets::iterator& add_before);
+  void add_layout_notebook(const sharedptr<LayoutItem_Notebook>& notebook);
+  void add_layout_portal(const sharedptr<LayoutItem_Portal>& portal);
 
 #ifndef GLOM_ENABLE_CLIENT_ONLY
 
diff --git a/glom/utility_widgets/eggspreadtable/eggspreadtablednd.c b/glom/utility_widgets/eggspreadtable/eggspreadtablednd.c
index db70787..c7f7e38 100644
--- a/glom/utility_widgets/eggspreadtable/eggspreadtablednd.c
+++ b/glom/utility_widgets/eggspreadtable/eggspreadtablednd.c
@@ -30,26 +30,28 @@
 #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,
+							     GValue             *value,
+							     GParamSpec         *pspec);
+static void          egg_spread_table_dnd_set_property      (GObject            *object,
+							     guint               prop_id,
+							     const GValue       *value,
+							     GParamSpec         *pspec);
+
 /* 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,
@@ -77,7 +79,7 @@ static void          egg_spread_table_dnd_remove             (GtkContainer
 							      GtkWidget         *child);
 
 /* EggSpreadTableClass */
-static void          egg_spread_table_dnd_insert_child       (EggSpreadTable    *spread_table,
+static void          egg_spread_table_dnd_insert_child_impl  (EggSpreadTable    *spread_table,
 							      GtkWidget         *child,
 							      gint               index);
 static gint          egg_spread_table_dnd_build_segments     (EggSpreadTable    *table,
@@ -106,9 +108,6 @@ static gboolean      drag_failed                       (GtkWidget         *widge
 							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,
@@ -141,21 +140,15 @@ struct _EggSpreadTableDndPrivate {
   /* 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 */
+  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 */
 
-  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;
+  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) */
 
+  gint       disappearing;     /* Count of placeholders that are currently disappearing */
+  gint      *locked_config;    /* Caching and locking the child configuration */
 };
 
 
@@ -164,6 +157,7 @@ enum {
   LAST_SIGNAL
 };
 
+static GQuark		    dnd_table_child_quark = 0;
 static guint                dnd_table_signals [LAST_SIGNAL] = { 0 };
 static GdkAtom              dnd_target_atom_child = GDK_NONE;
 static const GtkTargetEntry dnd_targets[] = {
@@ -177,33 +171,44 @@ G_DEFINE_TYPE (EggSpreadTableDnd, egg_spread_table_dnd, EGG_TYPE_SPREAD_TABLE)
 static void
 egg_spread_table_dnd_class_init (EggSpreadTableDndClass *class)
 {
+  GObjectClass        *gobject_class   = G_OBJECT_CLASS (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;
+  gobject_class->get_property           = egg_spread_table_dnd_get_property;
+  gobject_class->set_property           = egg_spread_table_dnd_set_property;
 
-  widget_class->size_allocate        = egg_spread_table_dnd_size_allocate;
+  widget_class->realize                 = egg_spread_table_dnd_realize;
+  widget_class->size_allocate           = egg_spread_table_dnd_size_allocate;
+  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;
 
-  /* Drag source */
-  widget_class->drag_data_get      = egg_spread_table_dnd_drag_data_get;
+  container_class->remove               = egg_spread_table_dnd_remove;
 
-  /* 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;
+  spread_class->insert_child            = egg_spread_table_dnd_insert_child_impl;
+  spread_class->build_segments_for_size = egg_spread_table_dnd_build_segments;
 
-  container_class->remove    = egg_spread_table_dnd_remove;
+  class->widget_drop_possible           = egg_spread_table_dnd_drop_possible;
 
-  spread_class->insert_child            = egg_spread_table_dnd_insert_child;
-  spread_class->build_segments_for_size = egg_spread_table_dnd_build_segments;
+  /**
+   * EggSpreadTableDnd:steal-events:
+   *
+   * Whether the table should steal all pointer events from added children
+   * for the purpose of Drag'n'Drop.
+   *
+   */
+  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,
+							 G_PARAM_READABLE | G_PARAM_WRITABLE));
 
-  class->widget_drop_possible = egg_spread_table_dnd_drop_possible;
 
   /**
    * EggSpreadTableDnd::widget-drop-possible
@@ -229,6 +234,7 @@ egg_spread_table_dnd_class_init (EggSpreadTableDndClass *class)
 
 
   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");
 
   g_type_class_add_private (class, sizeof (EggSpreadTableDndPrivate));
 }
@@ -241,8 +247,6 @@ egg_spread_table_dnd_init (EggSpreadTableDnd *spread_table)
   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,
@@ -259,6 +263,47 @@ egg_spread_table_dnd_init (EggSpreadTableDnd *spread_table)
 }
 
 /*****************************************************
+ *                  GObectClass                      *
+ *****************************************************/
+static void
+egg_spread_table_dnd_get_property (GObject      *object,
+				   guint         prop_id,
+				   GValue       *value,
+				   GParamSpec   *pspec)
+{
+  EggSpreadTableDnd *table = EGG_SPREAD_TABLE_DND (object);
+
+  switch (prop_id)
+    {
+    case PROP_STEAL_EVENTS:
+      g_value_set_boolean (value, table->priv->steal_events);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+egg_spread_table_dnd_set_property (GObject      *object,
+				   guint         prop_id,
+				   const GValue *value,
+				   GParamSpec   *pspec)
+{
+  EggSpreadTableDnd *table = EGG_SPREAD_TABLE_DND (object);
+
+  switch (prop_id)
+    {
+    case PROP_STEAL_EVENTS:
+      egg_spread_table_dnd_set_steal_events (table, g_value_get_boolean (value));
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+/*****************************************************
  *                 GtkWidgetClass                    *
  *****************************************************/
 static void
@@ -294,83 +339,6 @@ egg_spread_table_dnd_realize (GtkWidget *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,
@@ -434,7 +402,7 @@ allocate_child (EggSpreadTableDnd *table,
 }
 
 static void
-get_spread_table_dimentions (EggSpreadTableDnd *spread_table,
+get_spread_table_dimensions (EggSpreadTableDnd *spread_table,
 			     gint               for_size,
 			     gint              *line_spacing,
 			     gint              *item_spacing,
@@ -495,7 +463,7 @@ egg_spread_table_dnd_size_allocate (GtkWidget         *widget,
   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);
+  get_spread_table_dimensions (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));
 
@@ -537,34 +505,6 @@ egg_spread_table_dnd_size_allocate (GtkWidget         *widget,
   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               *
  *****************************************************/
@@ -638,8 +578,8 @@ get_placeholder_size (EggSpreadTableDnd *spread_table,
   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);
+  /* Calculate the size of the required placeholder based on the dimensions of the drag widget */
+  get_spread_table_dimensions (spread_table, -1, NULL, NULL, NULL, &line_width);
 
   if (orientation == GTK_ORIENTATION_VERTICAL)
     {
@@ -716,6 +656,9 @@ egg_spread_table_dnd_drag_motion (GtkWidget         *widget,
 	  get_placeholder_size (spread_table, &width, &height);
 
 	  spread_table->priv->drop_target = egg_placeholder_new (width, height);
+	  g_object_set_qdata (G_OBJECT (spread_table->priv->drop_target),
+			      dnd_table_child_quark, GINT_TO_POINTER (TRUE));
+
 	  egg_spread_table_insert_child (EGG_SPREAD_TABLE (spread_table),
 					 spread_table->priv->drop_target, index);
 	  adjust_line_segment (spread_table, line, 1);
@@ -813,6 +756,14 @@ static void
 egg_spread_table_dnd_remove (GtkContainer *container,
 			     GtkWidget    *child)
 {
+  if (GPOINTER_TO_INT (g_object_get_qdata (G_OBJECT (child), dnd_table_child_quark)) == FALSE)
+    {
+      g_message ("Refusing to remove child widget from EggSpreadTableDnd directly, "
+		 "use egg_spread_table_dnd_remove_child() instead.");
+      return;
+    }
+
+
   /* Disconnect dnd */
   if (!EGG_IS_PLACEHOLDER (child))
     {
@@ -831,10 +782,17 @@ egg_spread_table_dnd_remove (GtkContainer *container,
  *               EggSpreadTableClass                 *
  *****************************************************/
 static void
-egg_spread_table_dnd_insert_child (EggSpreadTable *spread_table,
-				   GtkWidget      *child,
-				   gint            index)
+egg_spread_table_dnd_insert_child_impl (EggSpreadTable *spread_table,
+					GtkWidget      *child,
+					gint            index)
 {
+  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, "
+		 "use egg_spread_table_dnd_insert_child() instead.");
+      return;
+    }
+
   EGG_SPREAD_TABLE_CLASS (egg_spread_table_dnd_parent_class)->insert_child (spread_table, child, index);
 
   /* Connect dnd */
@@ -874,7 +832,7 @@ egg_spread_table_dnd_build_segments (EggSpreadTable *table,
     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);
+  get_spread_table_dimensions (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));
@@ -926,15 +884,56 @@ egg_spread_table_dnd_drop_possible (EggSpreadTableDnd *table,
 /*****************************************************
  *       Drag'n'Drop signals & other functions       *
  *****************************************************/
+static void
+set_drag_icon (GtkWidget      *widget,
+	       GdkDragContext *context)
+{
+  GtkAllocation    allocation;
+  cairo_surface_t *surface;
+  cairo_t         *cr;
+  GtkStyleContext *style;
+  GdkPixbuf       *pixbuf;
+  gint             hot_x, hot_y;
+
+  /* XXX Force allocate here ? need to absolutely have an allocated widget
+   * for this to work (gtk_widget_draw() needs that). */
+
+  gtk_widget_get_allocation (widget, &allocation);
+  gtk_widget_get_pointer (widget, &hot_x, &hot_y);
+
+  surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, allocation.width, allocation.height);
+  cr      = cairo_create (surface);
+
+  /* Synthetically render a background */
+  style = gtk_widget_get_style_context (widget);
+  gtk_style_context_save (style);
+  gtk_style_context_add_class (style, GTK_STYLE_CLASS_BACKGROUND);
+  gtk_render_background (style, cr, 0, 0, allocation.width, allocation.height);
+  gtk_style_context_restore (style);
+
+  /* Draw the actual widget, this might or might not draw the background */
+  gtk_widget_draw (widget, cr);
+
+  /* Make a pixbuf and use that (just to take advantage of the 'hot_x'/'hot_y' parameters) */
+  pixbuf = gdk_pixbuf_get_from_surface (surface, 0, 0, allocation.width, allocation.height);
+  gtk_drag_set_icon_pixbuf (context, pixbuf, hot_x, hot_y);
+
+  g_object_unref (pixbuf);
+  cairo_destroy (cr);
+  cairo_surface_destroy (surface);
+}
 
 static void
 drag_begin (GtkWidget         *widget,
-	    G_GNUC_UNUSED GdkDragContext    *context,
+	    GdkDragContext    *context,
 	    EggSpreadTableDnd *spread_table)
 {
   GtkAllocation   allocation;
   gint            drop_index;
 
+  /* Set the icon for the drag */
+  set_drag_icon (widget, context);
+
   /* Mark the spread table for an active drag */
   lock_table (spread_table);
   spread_table->priv->dragging = TRUE;
@@ -950,9 +949,12 @@ drag_begin (GtkWidget         *widget,
 			   "position", &drop_index,
 			   NULL);
 
-  /* Create a placeholder of the correct dimentions and insert it at the drag origin */
+  /* Create a placeholder of the correct dimensions 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);
+  g_object_set_qdata (G_OBJECT (spread_table->priv->drop_target),
+		      dnd_table_child_quark, GINT_TO_POINTER (TRUE));
+
 
   egg_spread_table_insert_child (EGG_SPREAD_TABLE (spread_table),
 				 spread_table->priv->drop_target,
@@ -1031,7 +1033,7 @@ get_index_at_position (EggSpreadTableDnd *spread_table,
   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);
+  get_spread_table_dimensions (spread_table, -1, &spacing, NULL, &full_size, &line_width);
 
   if (orientation == GTK_ORIENTATION_VERTICAL)
     position = x;
@@ -1118,38 +1120,6 @@ get_index_at_position (EggSpreadTableDnd *spread_table,
   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)
@@ -1248,3 +1218,105 @@ egg_spread_table_dnd_new (GtkOrientation orientation,
 				    "lines", lines,
 				    NULL);
 }
+
+/**
+ * egg_spread_table_dnd_insert_child:
+ * @table: An #EggSpreadTableDnd
+ * @child: The child widget to insert.
+ *
+ * Adds a child widget to an #EggSpreadTableDnd.
+ *
+ * <note><para>Regular #GtkContainer apis and #EggSpreadTable
+ * apis are inappropriate for adding children as those
+ * are reserved for internal use by the #EggSpreadTableDnd.</para></note>
+ */
+void
+egg_spread_table_dnd_insert_child (EggSpreadTableDnd *table,
+				   GtkWidget         *child,
+				   gint               index)
+{
+  GtkWidget *event_box;
+
+  g_return_if_fail (EGG_IS_SPREAD_TABLE_DND (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);
+  g_object_set_qdata (G_OBJECT (event_box), dnd_table_child_quark, GINT_TO_POINTER (TRUE));
+  gtk_widget_show (event_box);
+
+  gtk_container_add (GTK_CONTAINER (event_box), child);
+  egg_spread_table_insert_child (EGG_SPREAD_TABLE (table), event_box, index);
+}
+
+/**
+ * egg_spread_table_dnd_remove_child:
+ * @table: An #EggSpreadTableDnd
+ * @child: The child widget to insert.
+ *
+ * Adds a child widget to an #EggSpreadTableDnd.
+ *
+ * <note><para>Regular #GtkContainer apis and #EggSpreadTable
+ * apis are inappropriate for removing children as those
+ * are reserved for internal use by the #EggSpreadTableDnd.</para></note>
+ */
+void
+egg_spread_table_dnd_remove_child (EggSpreadTableDnd *table,
+				   GtkWidget         *child)
+{
+  GtkWidget *event_box;
+
+  g_return_if_fail (EGG_IS_SPREAD_TABLE_DND (table));
+  g_return_if_fail (GTK_IS_WIDGET (child));
+
+  event_box = gtk_widget_get_parent (child);
+  if (!event_box)
+    {
+      g_message ("Bad hierarchy encountered in %s. The child had no parent.", G_STRFUNC);
+      return;
+    }
+
+  if (GPOINTER_TO_INT (g_object_get_qdata (G_OBJECT (event_box), dnd_table_child_quark)) == FALSE)
+    {
+      g_message ("Bad hierarchy encountered in %s.", G_STRFUNC);
+      return;
+    }
+
+  /* unparent the user's child and remove the intermediate spread-table owned event-box. */
+  gtk_container_remove (GTK_CONTAINER (event_box), child);
+  gtk_container_remove (GTK_CONTAINER (table), event_box);
+}
+
+static void
+flip_event_windows (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);
+}
+
+void
+egg_spread_table_dnd_set_steal_events (EggSpreadTableDnd *table,
+				       gboolean           steal_events)
+{
+  g_return_if_fail (EGG_IS_SPREAD_TABLE_DND (table));
+
+  if (table->priv->steal_events != steal_events)
+    {
+      table->priv->steal_events = steal_events;
+
+      gtk_container_forall (GTK_CONTAINER (table), (GtkCallback)flip_event_windows, table);
+
+      g_object_notify (G_OBJECT (table), "steal-events");
+    }
+}
+
+gboolean
+egg_spread_table_dnd_get_steal_events (EggSpreadTableDnd *table)
+{
+  g_return_val_if_fail (EGG_IS_SPREAD_TABLE_DND (table), FALSE);
+
+  return table->priv->steal_events;
+}
diff --git a/glom/utility_widgets/eggspreadtable/eggspreadtablednd.h b/glom/utility_widgets/eggspreadtable/eggspreadtablednd.h
index 36c323b..dba5dc7 100644
--- a/glom/utility_widgets/eggspreadtable/eggspreadtablednd.h
+++ b/glom/utility_widgets/eggspreadtable/eggspreadtablednd.h
@@ -57,9 +57,17 @@ struct _EggSpreadTableDndClass
 };
 
 GType                 egg_spread_table_dnd_get_type              (void) G_GNUC_CONST;
-GtkWidget            *egg_spread_table_dnd_new                   (GtkOrientation  orientation,
-								  guint           lines);
-
+GtkWidget            *egg_spread_table_dnd_new                   (GtkOrientation     orientation,
+								  guint              lines);
+
+void                  egg_spread_table_dnd_insert_child          (EggSpreadTableDnd *table,
+								  GtkWidget         *child,
+								  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);
 
 G_END_DECLS
 
diff --git a/glom/utility_widgets/eggspreadtablemm/eggspreadtabledndmm.cc b/glom/utility_widgets/eggspreadtablemm/eggspreadtabledndmm.cc
index 9e418fe..12c3437 100644
--- a/glom/utility_widgets/eggspreadtablemm/eggspreadtabledndmm.cc
+++ b/glom/utility_widgets/eggspreadtablemm/eggspreadtabledndmm.cc
@@ -238,6 +238,36 @@ SpreadTableDnd::SpreadTableDnd(Gtk::Orientation orientation, guint lines)
 {
 }
 
+void SpreadTableDnd::insert_child(Gtk::Widget& child, int index)
+{
+  egg_spread_table_dnd_insert_child(gobj(), child.gobj(), index);
+}
+
+void SpreadTableDnd::remove_child(Gtk::Widget& child)
+{
+  //This is based on Gtk::Container::remove()
+  //We don't need to do this often, because specialized remove() functions are unusual:
+  //
+  //If this is a managed widget,
+  //then do an extra ref so that it will
+  //not be destroyed when adding to another container
+  //This should leave it in much the same state as when it was instantiated,
+  //before being added to the first container.
+  if(child.is_managed_())
+    child.reference();
+    
+  egg_spread_table_dnd_remove_child(gobj(), child.gobj());
+}
+
+void SpreadTableDnd::set_steal_events(bool steal_events)
+{
+  egg_spread_table_dnd_set_steal_events(gobj(), steal_events);
+}
+
+bool SpreadTableDnd::get_steal_events() const
+{
+  return egg_spread_table_dnd_get_steal_events(const_cast<EggSpreadTableDnd*>(gobj()));
+} 
 
 bool SpreadTableDnd::on_widget_drop_possible(Gtk::Widget* widget)
 {
diff --git a/glom/utility_widgets/eggspreadtablemm/eggspreadtabledndmm.h b/glom/utility_widgets/eggspreadtablemm/eggspreadtabledndmm.h
index 7d185d3..91c7f03 100644
--- a/glom/utility_widgets/eggspreadtablemm/eggspreadtabledndmm.h
+++ b/glom/utility_widgets/eggspreadtablemm/eggspreadtabledndmm.h
@@ -93,6 +93,11 @@ public:
   SpreadTableDnd();
   explicit SpreadTableDnd(Gtk::Orientation orientation, guint lines);
 
+  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;
+
 
   /**
    * @par Prototype:
diff --git a/glom/utility_widgets/eggspreadtablemm/eggspreadtablemm.h b/glom/utility_widgets/eggspreadtablemm/eggspreadtablemm.h
index 734b18d..c1b5805 100644
--- a/glom/utility_widgets/eggspreadtablemm/eggspreadtablemm.h
+++ b/glom/utility_widgets/eggspreadtablemm/eggspreadtablemm.h
@@ -97,7 +97,8 @@ public:
 
   //TODO: Is the default packing appropriate (and like the default for a Box::pack_start())?
 
-  void insert_child(Gtk::Widget& widget, int index);
+  //This is virtual to avoid us needing to override append_child() too in EggSpreadTableDnd
+  virtual void insert_child(Gtk::Widget& widget, int index);
 
 
   guint get_child_line(const Gtk::Widget& child, int size) const;
diff --git a/glom/utility_widgets/eggspreadtablemm/test_spreadtablednd.cc b/glom/utility_widgets/eggspreadtablemm/test_spreadtablednd.cc
index 5368663..f045f4e 100644
--- a/glom/utility_widgets/eggspreadtablemm/test_spreadtablednd.cc
+++ b/glom/utility_widgets/eggspreadtablemm/test_spreadtablednd.cc
@@ -37,7 +37,7 @@ static bool parent_accepts_drops = true;
 
 
 static void
-populate_spread_table_wrappy(Egg::SpreadTable* spread_table)
+populate_spread_table_wrappy(Egg::SpreadTableDnd* spread_table)
 {
   const gchar *strings[] = {
     "These are", "some wrappy label", "texts", "of various", "lengths.",
@@ -55,7 +55,7 @@ populate_spread_table_wrappy(Egg::SpreadTable* spread_table)
     iter != children.end(); ++iter)
   {
     Gtk::Widget *child = *iter;
-    paper->remove(*child);
+    paper->remove_child(*child);
     delete child;
   }
 
diff --git a/glom/utility_widgets/flowtable.cc b/glom/utility_widgets/flowtable.cc
index 6696cd7..6ea612f 100644
--- a/glom/utility_widgets/flowtable.cc
+++ b/glom/utility_widgets/flowtable.cc
@@ -43,41 +43,33 @@ FlowTable::~FlowTable()
   }
 }
 
-Gtk::HBox* FlowTable::get_parent_hbox(Gtk::Widget* first)
+const Gtk::HBox* FlowTable::get_parent_hbox(const Gtk::Widget* first) const
 {
-  typedef std::vector<Widget*> type_children;
-  type_children children = get_children();
-  for(type_children::iterator iter = children.begin(); iter != children.end(); ++iter)
+  const type_const_list_widgets::const_iterator iter_find = 
+    std::find(m_list_first_widgets.begin(), m_list_first_widgets.end(), first);
+  if(iter_find == m_list_first_widgets.end())
   {
-    Gtk::Widget* widget = *iter;
-    if(!widget)
+    std::cerr << G_STRFUNC << ": first was not a first widget. first=" << first << std::endl;
+    return 0; //It has no HBox parent because it is not even a first widget.
+  }
+  
+  for(type_list_hboxes::const_iterator iter = m_list_hboxes.begin(); iter != m_list_hboxes.end(); ++iter)
+  {
+    const Gtk::HBox* hbox = *iter;
+    if(!hbox)
       continue;
 
-    if(widget == first) //It must be a single item.
-      return 0; //It has no HBox parent.
-    else
-    {
-      Gtk::HBox* hbox = dynamic_cast<Gtk::HBox*>(widget);
-      if(hbox) //The first and second widgets are inside an HBox
-      {
-        //Check that it is one of our special HBoxes,
-        //though this check should not be neccesary:
-        const type_list_hboxes::const_iterator iter_boxes =
-          std::find(m_list_hboxes.begin(), m_list_hboxes.end(), hbox);
-        if(iter_boxes != m_list_hboxes.end())
-        {
-          const type_children box_children = hbox->get_children();
-          if(!box_children.empty())
-          {
-            const Gtk::Widget* child_widget = box_children[0]; //TODO: Is this definitely the left-most one?
-            if(child_widget == first)
-              return hbox;
-          }
-        }
-      }
-    }
-  }
+    //Check if it has the widget as one of its children:
+    typedef std::vector<const Gtk::Widget*> type_children;
+    const type_children box_children = hbox->get_children();
+    if(box_children.empty())
+      continue;
 
+    const type_children::const_iterator iter_find = 
+      std::find(box_children.begin(), box_children.end(), first);
+    if(iter_find != box_children.end())
+      return hbox;
+  }
   return 0;
 }
 
@@ -94,26 +86,33 @@ void FlowTable::delete_and_forget_hbox(Gtk::HBox* hbox)
     children = hbox->get_children();
   }
 
-  if(hbox->get_parent() == this)
+  //This check does not work because EggSpreadTableDnD adds an intermediate GtkEventBox:
+  //if(hbox->get_parent() == this)
+  
+  //Check that it is in our list of hboxes:
+  const type_list_hboxes::iterator iter = std::find(
+    m_list_hboxes.begin(), m_list_hboxes.end(), hbox);
+  if(iter == m_list_hboxes.end())
+  {
+    std::cerr << G_STRFUNC << ": hbox=" << hbox << " is not in our list of hboxes." << std::endl;
+    return;
+  }
+  
+  //Check that it has a parent,
+  //as a sanity check:
+  Gtk::Widget* parent= hbox->get_parent();
+  if(parent)
   {
-    Egg::SpreadTable::remove(*hbox);
+    Egg::SpreadTableDnd::remove_child(*hbox);
   }
   else
   {
-    std::cerr << G_STRFUNC << ": hbox is not a direct child." << std::endl;
+    std::cerr << G_STRFUNC << ": hbox=" << hbox << " has no parent. Not removing from SpreadTableDnd" << std::endl;
   }
 
   //Delete and forget it:
-  for(type_list_hboxes::iterator iter = m_list_hboxes.begin(); iter != m_list_hboxes.end(); ++iter)
-  {
-    Gtk::HBox* this_hbox = *iter;
-    if(hbox == this_hbox)
-    {
-      delete hbox; //TODO: This causes a warning during gtk_container_remove(), though we have already removed it: sys:1: Warning: g_object_ref: assertion `object->ref_count > 0' failed
-      m_list_hboxes.erase(iter);
-      return;
-    }
-  }
+  delete hbox; //TODO: This causes a warning during gtk_container_remove(), though we have already removed it: sys:1: Warning: g_object_ref: assertion `object->ref_count > 0' failed
+  m_list_hboxes.erase(iter);
 }
 
 void FlowTable::set_design_mode(bool value)
@@ -145,12 +144,17 @@ void FlowTable::insert(Gtk::Widget* first, Gtk::Widget* second, int index, bool
     hbox->show();
 
     hbox->set_halign(Gtk::ALIGN_FILL);
-    insert_child(*hbox, index);
+    Egg::SpreadTableDnd::insert_child(*hbox, index);
+    //std::cout << "DEBUG: inserted hbox=" << hbox << " for first=" << first << std::endl;
+
+    m_list_first_widgets.push_back(first);
   }
   else if(first)
   {
     first->set_halign(expand ? Gtk::ALIGN_FILL : Gtk::ALIGN_START);
-    append_child(*first);
+    Egg::SpreadTableDnd::append_child(*first);
+    //std::cout << "DEBUG: inserted first=" << first << std::endl;
+    m_list_first_widgets.push_back(first);
   }
   else
   {
@@ -158,78 +162,52 @@ void FlowTable::insert(Gtk::Widget* first, Gtk::Widget* second, int index, bool
   }
 }
 
-int FlowTable::get_child_index(const Gtk::Widget& first) const
+void FlowTable::remove_all()
 {
-  int index = 0;
-
-  typedef std::vector<const Widget*> type_children;
-  const type_children children = get_children();
-  for(type_children::const_iterator iter = children.begin(); iter != children.end(); ++iter)
+  for(type_const_list_widgets::const_iterator iter = m_list_first_widgets.begin(); iter != m_list_first_widgets.end(); ++iter)
   {
-    const Gtk::Widget* widget = *iter;
-    if(!widget)
-      continue;
-
-    if(widget == &first) //It must be a single item.
-      break;
-    else
-    {
-      const Gtk::HBox* hbox = dynamic_cast<const Gtk::HBox*>(widget);
-      if(hbox) //The first and second widgets are inside an HBox
-      {
-        const type_children box_children = hbox->get_children();
-        if(!box_children.empty())
-        {
-          const Gtk::Widget* child_widget = box_children[0]; //TODO: Is this definitely the left-most one?
-          if(child_widget == &first)
-            break;
-        }
-      }
-    }
-
-    ++index;
+    Gtk::Widget* first_widget = const_cast<Gtk::Widget*>(*iter);
+    
+    if(first_widget)
+      remove(*first_widget);
   }
+  m_list_first_widgets.clear();
 
-  return index;
-}
-
-void FlowTable::insert_before(Gtk::Widget& first, Gtk::Widget& before, bool expand)
-{
-  const int index = get_child_index(before);
-  insert(&first, 0 /* second */, index - 1, expand);
-}
-
-void FlowTable::insert_before(Gtk::Widget& first, Gtk::Widget& second, Gtk::Widget& before, bool expand_second)
-{
-  const int index = get_child_index(before);
-  insert(&first, &second, index - 1, expand_second);
-}
-
-void FlowTable::remove_all()
-{
+  //We can't use get_children() because EggSpreadTableDnd does not allow that,
+  //because it handles children differently via its specific API.
+  /*
   typedef std::vector<Widget*> type_children;
-  type_children children = get_children();
-  while(!children.empty())
+  const type_children children = get_children();
+  for(type_children::iterator iter = children.begin(); iter != children.end(); ++iter)
   {
-    Gtk::Widget* widget = children[0];
+    Gtk::Widget* widget = *iter;
     remove(*widget);
-    children = get_children();
   }
+  */
 }
 
 void FlowTable::remove(Gtk::Widget& first)
 {
+  //std::cout << G_STRFUNC << ": debug: remove() first=" << &first << std::endl;
+  
   //Handle widgets that were added to an HBox:
-  Gtk::HBox* parent = get_parent_hbox(&first);
+  Gtk::HBox* parent = const_cast<Gtk::HBox*>(get_parent_hbox(&first));
   if(parent)
   {
+    //std::cout << "  debug: hbox=" << parent << std::endl;
+ 
     delete_and_forget_hbox(parent);
     return;
   }
 
-  Egg::SpreadTable::remove(first);
+  Egg::SpreadTableDnd::remove_child(first);
 }
 
+FlowTable::type_const_list_widgets FlowTable::get_first_child_widgets() const
+{
+  return m_list_first_widgets;
+}
+  
 bool FlowTable::get_column_for_first_widget(const Gtk::Widget& first, guint& column) const
 {
   //Initialize output parameter:
@@ -238,46 +216,40 @@ bool FlowTable::get_column_for_first_widget(const Gtk::Widget& first, guint& col
   if(get_lines() == 0)
     return false;
 
-  typedef std::vector<const Widget*> type_children;
-  const type_children children = get_children();
-  for(type_children::const_iterator iter = children.begin(); iter != children.end(); ++iter)
-  {
-    const Gtk::Widget* widget = *iter;
-    if(!widget)
-      continue;
-
-    //Get the widget that EggSpreadTable thinks of as the child:
-    const Gtk::Widget* child = 0;
-
-    if(widget == &first) //It must be a single item.
-      child = widget;
-    else
-    {
-      const Gtk::HBox* hbox = dynamic_cast<const Gtk::HBox*>(widget);
-      if(hbox) //The first and second widgets are inside an HBox
-      {
-        const type_children box_children = hbox->get_children();
-        if(!box_children.empty())
-        {
-          const Gtk::Widget* child_widget = box_children[0]; //TODO: Is this definitely the left-most one?
-          if(child_widget == &first)
-            child = hbox;
-        }
-      }
-
-      if(child)
-      {
-        int width_min = 0;
-        int width_natural = 0;
-        child->get_preferred_width(width_min, width_natural);
-        column = get_child_line(*child, width_natural);
-
-        return true;
-      }
-    }
-  }
+  //Discover actual child widget that was added to the EggSpreadTable,
+  //so we can use it again to call EggSpreadTable::get_child_line():
+  const Gtk::Widget* child = 0;
+      
+  //Check that it is really a child widget:
+  const type_const_list_widgets::const_iterator iter_find = 
+    std::find(m_list_first_widgets.begin(), m_list_first_widgets.end(), &first);
+  if(iter_find == m_list_first_widgets.end())
+    return false; //It is not a first widget.
+    
+  child = &first;
+  
+  //Check if it was added to an HBox:
+  const Gtk::HBox* hbox = get_parent_hbox(child);
+  if(hbox)
+    child = hbox;
+    
+  if(!child)
+    return false;
 
-  return false;
+  int width_min = 0;
+  int width_natural = 0;
+  child->get_preferred_width(width_min, width_natural);
+  //std::cout << G_STRFUNC << ": Calling get_child_line() with child=" << child << ", for first=" << &first << std::endl;
+  
+  //Get the internal parent GtkEventBox, if any,
+  //though we need a derived get_child_line() to do this automatically:
+  const Gtk::Widget* parent = child->get_parent();
+  if(dynamic_cast<const Gtk::EventBox*>(parent))
+     child = parent;
+     
+  column = get_child_line(*child, width_natural);
+
+  return true;
 }
 
 } //namespace Glom
diff --git a/glom/utility_widgets/flowtable.h b/glom/utility_widgets/flowtable.h
index df1c95c..b2b290f 100644
--- a/glom/utility_widgets/flowtable.h
+++ b/glom/utility_widgets/flowtable.h
@@ -38,9 +38,7 @@ public:
 
   virtual void add(Gtk::Widget& first, Gtk::Widget& second, bool expand_second = false);
   virtual void add(Gtk::Widget& first, bool expand = false); //override
-  void insert_before(Gtk::Widget& first, Gtk::Widget& second, Gtk::Widget& before, bool expand_second);
-  void insert_before(Gtk::Widget& first, Gtk::Widget& before, bool expand);
-
+ 
   /** Show extra UI that is useful in RAD tools:
    */
   virtual void set_design_mode(bool value = true);
@@ -58,10 +56,16 @@ protected:
 
   void insert(Gtk::Widget* first, Gtk::Widget* second, int index, bool expand);
 
+  typedef std::list<const Gtk::Widget*> type_const_list_widgets;
+
+  /** This returns all first widgets added with FlowTable::add().
+   * Gtk::Container::get_children() instead returns internal widgets.
+   */
+  type_const_list_widgets get_first_child_widgets() const;
+
 private:
-  int get_child_index(const Gtk::Widget& first) const;
 
-  Gtk::HBox* get_parent_hbox(Gtk::Widget* first);
+  const Gtk::HBox* get_parent_hbox(const Gtk::Widget* first) const;
   void delete_and_forget_hbox(Gtk::HBox* hbox);
 
   bool m_design_mode;
@@ -72,6 +76,8 @@ private:
   //We remember the HBoxes so we can delete them when the are no longer used.
   typedef std::list<Gtk::HBox*> type_list_hboxes;
   type_list_hboxes m_list_hboxes;
+
+  type_const_list_widgets m_list_first_widgets;
 };
 
 } //namespace Glom
diff --git a/po/ChangeLog b/po/ChangeLog
index 423fcd0..24a1510 100644
--- a/po/ChangeLog
+++ b/po/ChangeLog
@@ -1,3 +1,9 @@
+2011-09-01  Murray Cumming  <murrayc murrayc-desktop>
+
+	reviewed by: <delete if not using a buddy>
+
+	* POTFILES.in:
+
 2011-08-29  Murray Cumming  <murrayc murrayc-desktop>
 
 	reviewed by: <delete if not using a buddy>
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 553e4b6..3d3fcb4 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -125,6 +125,7 @@ glom/utility_widgets/dialog_image_load_progress.cc
 glom/utility_widgets/dialog_image_save_progress.cc
 glom/mode_data/datawidget/entry.cc
 glom/utility_widgets/eggspreadtable/eggspreadtable.c
+glom/utility_widgets/eggspreadtable/eggspreadtablednd.c
 glom/utility_widgets/filechooserdialog_saveextras.cc
 glom/utility_widgets/imageglom.cc
 glom/utility_widgets/layouttoolbar.cc



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