Index: glom/utility_widgets/test_flowtable.cc
===================================================================
--- glom/utility_widgets/test_flowtable.cc	(Revision 1082)
+++ glom/utility_widgets/test_flowtable.cc	(Arbeitskopie)
@@ -22,6 +22,16 @@
 #include "flowtable.h"
 
 
+void on_drag_data_get_label(const Glib::RefPtr<Gdk::DragContext>&, Gtk::SelectionData& selection_data, guint, guint)
+{
+  selection_data.set(selection_data.get_target(), 8, (const guchar*)"label", 5);
+}
+
+void on_drag_data_get_entry(const Glib::RefPtr<Gdk::DragContext>&, Gtk::SelectionData& selection_data, guint, guint)
+{
+  selection_data.set(selection_data.get_target(), 8, (const guchar*)"entry", 5);
+}
+
 int
 main(int argc, char* argv[])
 {
@@ -87,6 +97,36 @@
 
   flowtable.set_padding(20);
 
+  Gtk::Window tool_window;
+  tool_window.set_type_hint(Gdk::WINDOW_TYPE_HINT_UTILITY);
+  Gtk::HBox tool_buttonbox;
+  
+  Gtk::Button label_tool_button("Label");
+  Gtk::Image label_tool_image("label.png");
+  label_tool_button.set_image(label_tool_image);
+  std::list<Gtk::TargetEntry> label_tool_targetentries;
+  label_tool_targetentries.push_back(Gtk::TargetEntry("flowtable"));
+  label_tool_button.drag_source_set(label_tool_targetentries);
+  label_tool_button.drag_source_set_icon(label_tool_image.get_pixbuf());
+  label_tool_button.signal_drag_data_get().connect(sigc::ptr_fun(&on_drag_data_get_label));
+  tool_buttonbox.pack_end(label_tool_button, Gtk::PACK_EXPAND_PADDING);
+  label_tool_button.show();
+
+  Gtk::Button entry_tool_button("Entry");
+  Gtk::Image entry_tool_image("entry.png");
+  entry_tool_button.set_image(entry_tool_image);
+  std::list<Gtk::TargetEntry> entry_tool_targetentries;
+  entry_tool_targetentries.push_back(Gtk::TargetEntry("flowtable"));
+  entry_tool_button.drag_source_set(entry_tool_targetentries);
+  entry_tool_button.drag_source_set_icon(entry_tool_image.get_pixbuf());
+  entry_tool_button.signal_drag_data_get().connect(sigc::ptr_fun(&on_drag_data_get_entry));
+  tool_buttonbox.pack_end(entry_tool_button, Gtk::PACK_EXPAND_PADDING);
+  entry_tool_button.show();
+  
+  tool_window.add(tool_buttonbox);
+  tool_buttonbox.show();
+  tool_window.show();
+
   Gtk::Main::run(window);
 
 
Index: glom/utility_widgets/flowtable.cc
===================================================================
--- glom/utility_widgets/flowtable.cc	(Revision 1082)
+++ glom/utility_widgets/flowtable.cc	(Arbeitskopie)
@@ -1,3 +1,4 @@
+#include <iostream>
 /* Glom
  *
  * Copyright (C) 2001-2004 Murray Cumming
@@ -26,18 +27,26 @@
 {
 
 FlowTable::FlowTableItem::FlowTableItem()
-: m_expand_first_full(false),
+: m_first(NULL),
+  m_second(NULL),
+  m_expand_first_full(false),
   m_expand_second(false)
 {
 }
 
 FlowTable::FlowTable()
-: m_columns_count(1),
+: m_dnd_in_progress(false),
+  m_columns_count(1),
   m_padding(0),
   m_design_mode(false)
 {
   set_flags(Gtk::NO_WINDOW);
   set_redraw_on_allocate(false);
+  std::list<Gtk::TargetEntry> drag_targets;
+  Gtk::TargetEntry drag_target("flowtable");
+  drag_targets.push_back(drag_target);
+  drag_dest_set(drag_targets);
+//  signal_drag_motion().connect(sigc::mem_fun(*this, &FlowTable::on_drag_motion));
 }
 
 FlowTable::~FlowTable()
@@ -51,6 +60,16 @@
   queue_draw(); //because this changes how the widget would be drawn.
 }
 
+void FlowTable::setup_drag_target(Gtk::Widget& widget)
+{
+  std::list<Gtk::TargetEntry> drag_targets;
+  Gtk::TargetEntry drag_target("flowtable");
+  drag_targets.push_back(drag_target);
+  widget.drag_dest_set(drag_targets);
+  widget.signal_drag_motion().connect_notify(sigc::mem_fun(*this, &FlowTable::on_child_drag_motion));
+  widget.signal_drag_data_received().connect(sigc::bind<Gtk::Widget*> (sigc::mem_fun(*this, &FlowTable::on_child_drag_data_received), &widget));
+}
+
 void FlowTable::add(Gtk::Widget& first, Gtk::Widget& second, bool expand_second)
 {
   FlowTableItem item;
@@ -58,9 +77,41 @@
   item.m_second = &second;
   item.m_expand_second = expand_second; //Expand to fill the width for all of the second item.
   m_children.push_back(item);
+  gtk_widget_set_parent(first.gobj(), GTK_WIDGET(gobj()));
+  gtk_widget_set_parent(second.gobj(), GTK_WIDGET(gobj()));
+  setup_drag_target(first);
+  setup_drag_target(second);
+}
 
+void FlowTable::insert(Gtk::Widget& first, Gtk::Widget& second, Gtk::Widget& after, bool expand_second)
+{
+  bool found = false;
+  std::vector<FlowTableItem>::iterator pos;
+  for (pos = m_children.begin(); pos != m_children.end(); pos++)
+  {
+      if (((*pos).m_first && (*pos).m_first->gobj() == after.gobj()) || ((*pos).m_second && (*pos).m_second->gobj() == after.gobj()))
+      {
+        std::cout << "found!" << std::endl;
+        found = true;
+	break;
+      }
+  }
+  if (!found)
+    return;
+  FlowTableItem item;
+  item.m_first = &first;
+  item.m_second = &second;
+  item.m_expand_second = expand_second;
   gtk_widget_set_parent(first.gobj(), GTK_WIDGET(gobj()));
   gtk_widget_set_parent(second.gobj(), GTK_WIDGET(gobj()));
+  setup_drag_target(first);
+  setup_drag_target(second);
+  if (pos == m_children.end())
+  {
+    m_children.push_back(item);
+  } else {
+    m_children.insert(++pos, item);
+  }
 }
 
 void FlowTable::add(Gtk::Widget& first, bool expand)
@@ -74,6 +125,10 @@
   gtk_widget_set_parent(first.gobj(), GTK_WIDGET(gobj()));
 }
 
+/*
+ * {{{ Unrelevant for DND
+ */
+
 void FlowTable::set_columns_count(guint value)
 {
   //Silently correct an invalid value:
@@ -739,6 +794,50 @@
   return Gtk::Container::on_expose_event(event);
 }
 
+/*
+ * }}}
+ */
+
+bool FlowTable::on_drag_motion(const Glib::RefPtr<Gdk::DragContext>& drag_context, int, int, guint time)
+{
+  m_dnd_in_progress = true;
+  return true;
+}
+
+void FlowTable::on_child_drag_motion(const Glib::RefPtr<Gdk::DragContext>& drag_context, int, int, guint time)
+{
+  m_dnd_in_progress = true;
+}
+
+void FlowTable::on_child_drag_data_received(const Glib::RefPtr<Gdk::DragContext>& drag_context, int, int, const Gtk::SelectionData& selection_data, guint, guint time, Gtk::Widget* a)
+{
+  if (m_dnd_in_progress)
+  {
+    Gtk::Widget* foo;
+    Gtk::Widget* bar;
+    if (selection_data.get_data_as_string() == "label")
+    {
+      foo = manage(new Gtk::Label("foo"));
+      bar = manage(new Gtk::Label("bar"));
+    }
+    else if (selection_data.get_data_as_string() == "entry")
+    {
+      foo = manage(new Gtk::Entry());
+      bar = manage(new Gtk::Entry());
+    }
+    else
+    {
+      std::cerr << "Unknown selection_data" << std::endl;
+      return;
+    }
+    foo->show();
+    bar->show();
+    insert(*foo, *bar, *a);
+    std::cout << "drag_data_received" << std::endl;
+    m_dnd_in_progress = false;
+  }
+}
+
 } //namespace Glom
 
 
Index: glom/utility_widgets/flowtable.h
===================================================================
--- glom/utility_widgets/flowtable.h	(Revision 1082)
+++ glom/utility_widgets/flowtable.h	(Arbeitskopie)
@@ -36,6 +36,7 @@
 
   virtual void add(Gtk::Widget& first, Gtk::Widget& second, bool expand_second = false);
   virtual void add(Gtk::Widget& first, bool expand = false); //override
+  virtual void insert(Gtk::Widget& first, Gtk::Widget& second, Gtk::Widget& after, bool expand_second = false);
 
   virtual void remove(Gtk::Widget& first); //override
 
@@ -69,6 +70,14 @@
   virtual void on_unrealize();
   virtual bool on_expose_event(GdkEventExpose* event);
 
+  //DND stuff:
+  virtual void setup_drag_target(Gtk::Widget& widget);
+  virtual bool on_drag_motion(const Glib::RefPtr<Gdk::DragContext>& drag_context, int x, int y, guint time);
+  virtual void on_child_drag_motion(const Glib::RefPtr<Gdk::DragContext>& drag_context, int x, int y, guint time);
+  virtual void on_child_drag_data_received(const Glib::RefPtr<Gdk::DragContext>& drag_context, int, int, const Gtk::SelectionData& selection_data, guint, guint time, Gtk::Widget*);
+  
+  bool m_dnd_in_progress;
+
   int get_column_height(guint start_widget, guint widget_count, int& total_width) const;
 
   /** 
