Index: glom/utility_widgets/test_flowtable.cc
===================================================================
--- glom/utility_widgets/test_flowtable.cc	(Revision 1099)
+++ 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[])
 {
@@ -30,39 +40,9 @@
   Gtk::Window window;
   //Gtk::VBox flowtable;
   Glom::FlowTable flowtable;
-  flowtable.set_columns_count(2);
+  flowtable.set_columns_count(1);
+  flowtable.set_padding(5);
 
-  Gtk::Entry button1; //"one");
-  button1.show();
-  button1.set_text("debug");
-
-  Glom::FlowTable inner_table;
-  inner_table.set_padding(20);
-  inner_table.set_design_mode();
-  inner_table.set_columns_count(1);
-  inner_table.show();
-  flowtable.add(inner_table);
-
-  Gtk::Entry button2; button2.set_text("two");
-  inner_table.add(button1, button2);
-  button2.show();
-  button2.set_size_request(40, 40);
-
-  Gtk::Entry button3; button3.set_text("three");
-  button3.show();
-
-  Gtk::Entry button4; button4.set_text("four");
-  inner_table.add(button3, button4);
-  button4.show();
-  button4.set_size_request(20, 30);
-
-  Gtk::Entry button5; button5.set_text("five");
-  button5.show();
-
-  Gtk::Entry button6; button6.set_text("six");
-  inner_table.add(button5, button6);
-  button6.show();
-
   Gtk::Entry button7; button7.set_text("seven");;
   button7.show();
   //button7.set_size_request(100, 100);
@@ -70,7 +50,7 @@
   Gtk::Entry button8; button8.set_text("eight");
   flowtable.add(button7, button8);
   button8.show();
-  button8.set_size_request(100, 300);
+  //button8.set_size_request(100, 100);
 
   Gtk::Entry button9; button9.set_text("nine");;
   button9.show();
@@ -80,6 +60,11 @@
   flowtable.add(button9, button10);
   button10.show();
 
+  Gtk::Entry button11; button11.set_text("eleven");
+  Gtk::Entry button12; button11.set_text("eleven");
+  flowtable.add(button11, button12);
+  button11.show(); button12.show();
+  
   window.add(flowtable);
   flowtable.set_design_mode();
   flowtable.show();
@@ -87,6 +72,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 1099)
+++ glom/utility_widgets/flowtable.cc	(Arbeitskopie)
@@ -21,23 +21,32 @@
 #include "flowtable.h"
 #include "gtk/gtkwidget.h"
 #include "gdk/gdktypes.h"
+#include <iostream>
+#include <gdkmm/window.h>
 
 namespace Glom
 {
 
 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);
 }
 
 FlowTable::~FlowTable()
@@ -58,9 +67,98 @@
   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_before(Gtk::Widget& widget, Gtk::Widget& before, 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() == before.gobj()) || ((*pos).m_second && (*pos).m_second->gobj() == before.gobj()))
+      {
+        std::cout << "found!" << std::endl;
+        found = true;
+	break;
+      }
+  }
+  if (!found)
+    return;
+  FlowTableItem item;
+  item.m_first = &widget;
+  item.m_second = 0;
+  item.m_expand_second = expand_second;
+  gtk_widget_set_parent(widget.gobj(), GTK_WIDGET(gobj()));
+  if (pos == m_children.end())
+  {
+    m_children.push_back(item);
+  } else {
+    m_children.insert(pos, item);
+  }
+}
+
+
+
+void FlowTable::insert_after(Gtk::Widget& widget, 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 = &widget;
+  item.m_second = 0;
+  item.m_expand_second = expand_second;
+  gtk_widget_set_parent(widget.gobj(), GTK_WIDGET(gobj()));
+  if (pos == m_children.end())
+  {
+    m_children.push_back(item);
+  } else {
+    m_children.insert(++pos, item);
+  }
+}
+
+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()));
+  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 +172,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:
@@ -711,7 +813,7 @@
     if(m_refGdkWindow)
     {
       m_refGC = Gdk::GC::create(m_refGdkWindow);
-      m_refGC->set_line_attributes(1 /* width */, Gdk::LINE_ON_OFF_DASH, Gdk::CAP_NOT_LAST, Gdk::JOIN_MITER);
+      m_refGC->set_line_attributes(2 /* width */, Gdk::LINE_ON_OFF_DASH, Gdk::CAP_NOT_LAST, Gdk::JOIN_MITER);
 
       //Glib::RefPtr<Gdk::Colormap> colormap = get_default_colormap();
       //Gdk::Color color_blue("blue");
@@ -733,12 +835,121 @@
       {
         m_refGdkWindow->draw_line(m_refGC, iter->first.get_x(), iter->first.get_y(), iter->second.get_x(), iter->second.get_y());
       }
+      if (m_dnd_in_progress)
+      {
+        /*std::cout << "Draw rect:" << m_preview_rect.get_x() <<
+         " " << m_preview_rect.get_y() << 
+         " " << m_preview_rect.get_width() << 
+         " " << m_preview_rect.get_height() << std::endl;*/
+        m_refGdkWindow->draw_rectangle(m_refGC, false, 
+                                   m_preview_rect.get_x(),
+                                   m_preview_rect.get_y(),
+                                   m_preview_rect.get_width(),
+                                   m_preview_rect.get_height());
+      }
     }
   }
 
   return Gtk::Container::on_expose_event(event);
 }
 
+/*
+ * }}}
+ */
+
+bool FlowTable::on_drag_motion(const Glib::RefPtr<Gdk::DragContext>& drag_context, int x, int y, guint time)
+{
+  m_dnd_in_progress = true;
+  std::cout << "Drag motion" << std::endl;
+  bool before;
+  get_item(x, y, before);
+  return true;
+}
+
+void FlowTable::on_drag_data_received(const Glib::RefPtr<Gdk::DragContext>& drag_context, int drag_x, int drag_y, const Gtk::SelectionData& selection_data, guint, guint time)
+{
+  if (m_dnd_in_progress)
+  {
+    Gtk::Widget* widget;
+    if (selection_data.get_data_as_string() == "label")
+    {
+      widget = manage(new Gtk::Label("foo"));
+    }
+    else if (selection_data.get_data_as_string() == "entry")
+    {
+      widget = manage(new Gtk::Entry());
+    }
+    else
+    {
+      std::cerr << "Unknown selection_data" << std::endl;
+      return;
+    }
+    widget->show();
+    bool before;
+    FlowTableItem* item = get_item(drag_x, drag_y, before);
+    if (!item)
+    {
+      add(*widget, false);
+    }
+    else if (before)
+    {
+      insert_before(*widget, *item->m_first, false);
+    }
+    else
+    {
+      insert_after(*widget, *item->m_first, false);
+    }
+    m_dnd_in_progress = false;
+  }
+}
+
+void FlowTable::on_drag_leave(const Glib::RefPtr<Gdk::DragContext>& drag_context, guint time)
+{
+  if (m_dnd_in_progress)
+  {
+    std::cout << "Drag leave" << std::endl;
+  }
+}
+
+FlowTable::FlowTableItem*
+FlowTable::get_item(int drag_x, int drag_y, bool& before)
+{
+  std::vector<FlowTableItem>::iterator pos;
+  int min = -1;
+  before = false;
+  FlowTableItem* item = 0;
+  for (pos = m_children.begin(); pos != m_children.end(); pos++)
+  {
+    int x;
+    int y;
+    pos->m_first->get_window()->get_position(x, y);
+    std::cout << "drag_x: " << drag_x << std::endl;
+    std::cout << "drag_y: " << drag_y << std::endl;
+    std::cout << "x: " << x << std::endl;
+    std::cout << "y: " << y << std::endl;
+    
+    int diff_x = abs(x - drag_x);
+    int diff_y =  abs(y - drag_y);
+        
+    if (min == -1 || min > (diff_x + diff_y))
+    {
+      min = abs(diff_x) + abs(diff_y);
+      before = ((y - drag_y) > 0);
+      item = &(*pos);
+      int preview_width = 0, preview_height = 0;
+      item->m_first->get_window()->get_size(preview_width, preview_height);
+      m_preview_rect.set_width(preview_width);
+      m_preview_rect.set_height(preview_height);
+      m_preview_rect.set_x(x);
+      if (before)
+        m_preview_rect.set_y(y - preview_height);
+      else
+        m_preview_rect.set_y(y + preview_height);
+    }
+  }  
+  return item;
+}
+
 } //namespace Glom
 
 
Index: glom/utility_widgets/flowtable.h
===================================================================
--- glom/utility_widgets/flowtable.h	(Revision 1099)
+++ glom/utility_widgets/flowtable.h	(Arbeitskopie)
@@ -36,7 +36,11 @@
 
   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 insert_before(Gtk::Widget& widget, Gtk::Widget& before, bool expand_second = false);
+  virtual void insert_after(Gtk::Widget& widget, Gtk::Widget& after, bool expand_second = false);
 
+  
   virtual void remove(Gtk::Widget& first); //override
 
   void set_columns_count(guint value);
@@ -69,6 +73,13 @@
   virtual void on_unrealize();
   virtual bool on_expose_event(GdkEventExpose* event);
 
+  //DND stuff:
+  virtual bool on_drag_motion(const Glib::RefPtr<Gdk::DragContext>& drag_context, int x, int y, guint time);
+  virtual void on_drag_leave(const Glib::RefPtr<Gdk::DragContext>& drag_context, guint time);
+  virtual void on_drag_data_received(const Glib::RefPtr<Gdk::DragContext>& drag_context, int, int, const Gtk::SelectionData& selection_data, guint, guint time);
+  
+  bool m_dnd_in_progress;
+
   int get_column_height(guint start_widget, guint widget_count, int& total_width) const;
 
   /** 
@@ -97,6 +108,8 @@
   void get_item_requested_width(const FlowTableItem& item, int& first, int& second) const;
   void get_item_max_width_requested(guint start, guint height, guint& first_max_width, guint& second_max_width, guint& singles_max_width, bool& is_last_column) const; //TODO: maybe combine this with code in get_minimum_column_height().
 
+  FlowTableItem* get_item(int x, int y, bool& before);
+  
   bool child_is_visible(const Gtk::Widget* widget) const;
 
   Gtk::Allocation assign_child(Gtk::Widget* widget, int x, int y);
@@ -116,6 +129,9 @@
   //For drawing:
   Glib::RefPtr<Gdk::Window> m_refGdkWindow;
   Glib::RefPtr<Gdk::GC> m_refGC;
+  
+  // For preview rectacle
+  Gdk::Rectangle m_preview_rect;
 };
 
 } //namespace Glom
