glom r1598 - in trunk: . glom/mode_data glom/utility_widgets



Author: jhs
Date: Tue Apr 29 16:39:20 2008
New Revision: 1598
URL: http://svn.gnome.org/viewvc/glom?rev=1598&view=rev

Log:
2008-04-29  Johannes Schmid  <johannes schmid openismus com>

	* glom/mode_data/flowtablewithfields.cc:
	* glom/mode_data/flowtablewithfields.h
	(on_dnd_add_layout_item)
	Added new method to reparent items from other flowtables.
	
	* glom/utility_widgets/flowtable_dnd.cc (start_dnd), (on_drag_motion),
	  (on_drag_data_received), (dnd_item_at_position),
	  (dnd_datawidget_from_item), (find_current_dnd_item),
	  (on_child_drag_motion), (on_child_drag_data_get),
	  (on_child_drag_begin), (on_child_drag_end):	  
	* glom/utility_widgets/flowtable_dnd.h
	Implemented drag sources for LayoutWidgets and allow dragging in and between
	flowtables. Only works for labels as I didn\'t find out yet how to set other
	widgets as drag sources.
	
	* glom/utility_widgets/layoutwidgetbase.cc
	  (set_dnd_in_progress), (get_dnd_in_progress):
	* glom/utility_widgets/layoutwidgetbase.h:
	Added some need methods for drag and drop

Modified:
   trunk/ChangeLog
   trunk/glom/mode_data/flowtablewithfields.cc
   trunk/glom/mode_data/flowtablewithfields.h
   trunk/glom/utility_widgets/flowtable_dnd.cc
   trunk/glom/utility_widgets/flowtable_dnd.h
   trunk/glom/utility_widgets/layoutwidgetbase.cc
   trunk/glom/utility_widgets/layoutwidgetbase.h

Modified: trunk/glom/mode_data/flowtablewithfields.cc
==============================================================================
--- trunk/glom/mode_data/flowtablewithfields.cc	(original)
+++ trunk/glom/mode_data/flowtablewithfields.cc	Tue Apr 29 16:39:20 2008
@@ -1272,6 +1272,15 @@
   signal_layout_changed().emit();
 }
 
+void FlowTableWithFields::on_dnd_add_layout_item (LayoutWidgetBase* above,
+                                                  sharedptr<LayoutItem>& item)
+{
+  dnd_add_to_layout_group (item, above);
+  
+  // Don't do this here - it's done in the drag_end handler
+  // signal_layout_changed().emit();
+}
+
 void FlowTableWithFields::on_dnd_add_placeholder(LayoutWidgetBase* above)
 {
   if(m_placeholder)

Modified: trunk/glom/mode_data/flowtablewithfields.h
==============================================================================
--- trunk/glom/mode_data/flowtablewithfields.h	(original)
+++ trunk/glom/mode_data/flowtablewithfields.h	Tue Apr 29 16:39:20 2008
@@ -55,11 +55,11 @@
   : 
 #ifdef GLOM_ENABLE_CLIENT_ONLY
     public FlowTable,
+    public LayoutWidgetUtils,
 #else
     public FlowTableDnd,
 #endif
-    public View_Composite_Glom,
-    public LayoutWidgetUtils
+    public View_Composite_Glom
 {
 public: 
   FlowTableWithFields(const Glib::ustring& table_name = Glib::ustring());
@@ -216,6 +216,8 @@
   virtual void on_dnd_add_layout_item_button (LayoutWidgetBase* above);
   virtual void on_dnd_add_layout_item_text (LayoutWidgetBase* above);
   virtual void on_dnd_add_layout_notebook (LayoutWidgetBase* above);
+  virtual void on_dnd_add_layout_item (LayoutWidgetBase* above,
+                                       sharedptr<LayoutItem>& item);
   
   bool get_field_information (sharedptr<LayoutItem>& item);
   void dnd_notify_failed_drop();

Modified: trunk/glom/utility_widgets/flowtable_dnd.cc
==============================================================================
--- trunk/glom/utility_widgets/flowtable_dnd.cc	(original)
+++ trunk/glom/utility_widgets/flowtable_dnd.cc	Tue Apr 29 16:39:20 2008
@@ -19,6 +19,7 @@
  */
 
 #include "flowtable_dnd.h"
+#include "../mode_data/flowtablewithfields.h"
 #include "eggtoolpalette/eggtoolpalette.h"
 #include "placeholder-glom.h"
 #include "dragbutton.h"
@@ -29,13 +30,18 @@
 
 namespace Glom
 {
+
+const std::string MOVE_TARGET = "FlowTableMoveTarget";
   
 FlowTableDnd::FlowTableDnd() :
-  m_current_dnd_item(0)
+  m_current_dnd_item(0),
+  m_internal_drag (false)
 {
   std::list<Gtk::TargetEntry> drag_targets;
-  Gtk::TargetEntry drag_target(egg_tool_palette_get_drag_target_item());
-  drag_targets.push_back(drag_target);
+  Gtk::TargetEntry toolbar_target (egg_tool_palette_get_drag_target_item());
+  Gtk::TargetEntry move_target(MOVE_TARGET);
+  drag_targets.push_back(toolbar_target);
+  drag_targets.push_back(move_target);
   drag_dest_set(drag_targets);
 }
 
@@ -64,31 +70,39 @@
   }
   if (!(child.get_flags() & Gtk::NO_WINDOW))
   {
-    std::list<Gtk::TargetEntry> new_targets;
-    Gtk::TargetEntry target(egg_tool_palette_get_drag_target_item());
-    new_targets.push_back(target);
+    // Needed to move items around
+    std::list<Gtk::TargetEntry> source_targets;
+    source_targets.push_back (Gtk::TargetEntry (MOVE_TARGET));
+    child.drag_source_set (source_targets, Gdk::BUTTON1_MASK|Gdk::BUTTON3_MASK, 
+                           Gdk::ACTION_MOVE | Gdk::ACTION_COPY);
+    
+    std::list<Gtk::TargetEntry> drag_targets;
+    Gtk::TargetEntry toolbar_target (egg_tool_palette_get_drag_target_item());
+    Gtk::TargetEntry move_target(MOVE_TARGET);
+    drag_targets.push_back(toolbar_target);
+    drag_targets.push_back(move_target);
+    
     Glib::RefPtr<Gtk::TargetList> targets =
 			child.drag_dest_get_target_list ();
     // The widget has already a default drag destination - add more targets
     if (targets)
     {
-      targets->add (new_targets);
+      targets->add (drag_targets);
       child.drag_dest_set_target_list (targets);
     }
     else
-      child.drag_dest_set(new_targets, Gtk::DEST_DEFAULT_ALL,
+      child.drag_dest_set(drag_targets, Gtk::DEST_DEFAULT_ALL,
                           Gdk::ACTION_COPY | Gdk::ACTION_MOVE);
-		
-    // Needed to move items around
-    //child.drag_source_set (new_targets, Gdk::BUTTON1_MASK|Gdk::BUTTON3_MASK, 
-    //                       Gdk::ACTION_COPY | Gdk::ACTION_MOVE);
-    
+		    
     // It's important to connect this one BEFORE
     child.signal_drag_motion().connect (sigc::bind<Gtk::Widget*>(sigc::mem_fun (*this, &FlowTableDnd::on_child_drag_motion), &child),
                                         false);
     child.signal_drag_data_received().connect (sigc::bind<Gtk::Widget*>(sigc::mem_fun (*this, &FlowTableDnd::on_child_drag_data_received), &child));
     child.signal_drag_leave().connect (sigc::mem_fun (*this, &FlowTableDnd::on_child_drag_leave));
-    child.signal_drag_data_get().connect (sigc::bind<Gtk::Widget*>(sigc::mem_fun (*this, &FlowTableDnd::on_child_drag_data_get), &child));
+
+    child.signal_drag_begin().connect (sigc::bind<Gtk::Widget*>(sigc::mem_fun (*this, &FlowTableDnd::on_child_drag_begin), &child), false);
+    child.signal_drag_end().connect (sigc::bind<Gtk::Widget*>(sigc::mem_fun (*this, &FlowTableDnd::on_child_drag_end), &child), false);
+    child.signal_drag_data_get().connect (sigc::bind<Gtk::Widget*>(sigc::mem_fun (*this, &FlowTableDnd::on_child_drag_data_get), &child), false);
   }
 }
 
@@ -124,7 +138,7 @@
   y += get_allocation().get_y();
   
   m_current_dnd_item = dnd_item_at_position(x, y);  
-  LayoutWidgetBase* above = dnd_datawidget_from_item();
+  LayoutWidgetBase* above = dnd_datawidget_from_item(0);
 	
   // above might be 0 here...
   on_dnd_add_placeholder(above);
@@ -136,13 +150,14 @@
   Gtk::Widget* palette = drag_get_source_widget (drag_context);
   while (palette && !EGG_IS_TOOL_PALETTE (palette->gobj()))
     palette = palette->get_parent();
+  
+  on_dnd_remove_placeholder();
+  LayoutWidgetBase* above = dnd_datawidget_from_item(0);
   if (palette)
   {
     GtkWidget* tool_item = egg_tool_palette_get_drag_item (EGG_TOOL_PALETTE (palette->gobj()), selection_data.gobj());
     LayoutWidgetBase::enumType type = 
       static_cast<LayoutWidgetBase::enumType>(GPOINTER_TO_INT(g_object_get_data(G_OBJECT(tool_item), "glom-type")));
-    on_dnd_remove_placeholder();
-    LayoutWidgetBase* above = dnd_datawidget_from_item();
     switch (type)
     {
       case LayoutWidgetBase::TYPE_FIELD:
@@ -164,6 +179,29 @@
         std::cerr << "Unknown drop type: " << type << std::endl;
     }
   }
+  else
+  {
+    gpointer* data = (gpointer*)selection_data.get_data();
+    LayoutWidgetBase* base = (LayoutWidgetBase*)*data;
+    if (base)
+    {
+      sharedptr<LayoutItem> item = base->get_layout_item();
+      if (item)
+      {
+        sharedptr<LayoutGroup> group = sharedptr<LayoutGroup>::cast_dynamic(get_layout_item());
+        LayoutGroup::type_list_items items = group->m_list_items;
+        if (std::find (items.begin(), items.end(), item) != items.end())
+        {
+          m_internal_drag = true;
+          group->remove_item(item);
+        }
+        else
+          m_internal_drag = false;
+        on_dnd_add_layout_item (above, item);
+        base->set_dnd_in_progress(false);
+      }
+    }
+  }
 }
 
 void FlowTableDnd::on_drag_leave(const Glib::RefPtr<Gdk::DragContext>& drag_context, guint time)
@@ -193,7 +231,9 @@
       rect.set_width (rect.get_width() + m_padding + second_rect.get_width());
     }
     
-    int cur_column = rect.get_x() / column_width;
+    int cur_column = 0;
+    if (column_width != 0)
+      cur_column = rect.get_x() / column_width;
     
     if (cur_column != column)
     {
@@ -219,29 +259,35 @@
   return 0;
 }
 
-LayoutWidgetBase* FlowTableDnd::dnd_datawidget_from_item()
+LayoutWidgetBase* FlowTableDnd::dnd_datawidget_from_item(FlowTable::FlowTableItem* item)
 {
   // Test if we have a datawidget below which we want to add
   LayoutWidgetBase* above = 0;
-  if(m_current_dnd_item)
+  FlowTableItem* used_item;
+  if (item)
+    used_item = item;
+  else
+    used_item = m_current_dnd_item;
+  
+  if(used_item)
   {
-		if(m_current_dnd_item->m_first)
+		if(used_item->m_first)
     {
-      Gtk::Alignment* alignment = dynamic_cast <Gtk::Alignment*>(m_current_dnd_item->m_first);
+      Gtk::Alignment* alignment = dynamic_cast <Gtk::Alignment*>(used_item->m_first);
       if (alignment)
       {
         above = dynamic_cast<LayoutWidgetBase*>(alignment->get_child());
       }
     }
-    if(!above && m_current_dnd_item->m_first)
-      above = dynamic_cast<LayoutWidgetBase*>(m_current_dnd_item->m_first);
-    if(!above && m_current_dnd_item->m_second)
+    if(!above && used_item->m_first)
+      above = dynamic_cast<LayoutWidgetBase*>(used_item->m_first);
+    if(!above && used_item->m_second)
     {
-      above = dynamic_cast<LayoutWidgetBase*>(m_current_dnd_item->m_second);
+      above = dynamic_cast<LayoutWidgetBase*>(used_item->m_second);
       // Special case for labels
       if (!above)
       {       
-        Gtk::Alignment* alignment = dynamic_cast <Gtk::Alignment*>(m_current_dnd_item->m_second);
+        Gtk::Alignment* alignment = dynamic_cast <Gtk::Alignment*>(used_item->m_second);
         if (alignment)
         {
           above = dynamic_cast<LayoutWidgetBase*>(alignment->get_child());
@@ -252,9 +298,9 @@
   return above;
 }
 
-bool FlowTableDnd::on_child_drag_motion(const Glib::RefPtr<Gdk::DragContext>& drag_context, int x, int y, guint time,
-                                        Gtk::Widget* child)
+FlowTable::FlowTableItem* FlowTableDnd::find_current_dnd_item (Gtk::Widget* child, int x, int y)
 {
+  FlowTableItem* item;
   type_vecChildren::iterator cur_child;
   for (cur_child = m_children.begin();
        cur_child != m_children.end(); cur_child++)
@@ -281,9 +327,9 @@
     }
   }
   if (cur_child != m_children.end())
-    m_current_dnd_item = &(*cur_child);
+    item = &(*cur_child);
   else
-    m_current_dnd_item = 0;
+    item = 0;
   
   // Allow dragging at-the-end
   if (cur_child == --m_children.end())
@@ -292,12 +338,20 @@
     if (y > (rect.get_y() + rect.get_height() / 2) &&
         y < (rect.get_y() + rect.get_height()))
     {
-      m_current_dnd_item = 0; // means end
+      item = 0; // means end
     }
-  }
+  } 
+  return item;
+}
+
+bool FlowTableDnd::on_child_drag_motion(const Glib::RefPtr<Gdk::DragContext>& drag_context, int x, int y, guint time,
+                                        Gtk::Widget* child)
+{
+  find_current_dnd_item(child, x, y);
+  
   on_dnd_remove_placeholder ();
   
-  LayoutWidgetBase* above = dnd_datawidget_from_item();
+  LayoutWidgetBase* above = dnd_datawidget_from_item(0);
   
   // above might be 0 here...
   on_dnd_add_placeholder(above);
@@ -317,10 +371,54 @@
 }
 
 void FlowTableDnd::on_child_drag_data_get(const Glib::RefPtr<Gdk::DragContext>& drag_context, 
-                                          const Gtk::SelectionData& selection_data, guint, guint time, 
+                                          Gtk::SelectionData& selection_data, guint, guint time, 
                                           Gtk::Widget* child)
 {
-  std::cout << __FUNCTION__ << std::endl;
+  FlowTableItem* item = find_current_dnd_item (child);
+  LayoutWidgetBase* base = dnd_datawidget_from_item (item);
+  if (base)
+  {
+    gpointer data = base;
+    selection_data.set ("LayoutWidgetBase*", 8, (guint8*)&data, 
+                             sizeof(gpointer*));
+  }
+}
+
+void FlowTableDnd::on_child_drag_begin (const Glib::RefPtr<Gdk::DragContext>& drag_context,
+                          Gtk::Widget* child)
+{
+  FlowTableItem* item = find_current_dnd_item (child);
+  if (!item)
+    return;
+  if (item->m_first)
+    item->m_first->hide();
+  if (item->m_second)
+    item->m_second->hide();
+  LayoutWidgetBase* base = dnd_datawidget_from_item (item);
+  base->set_dnd_in_progress(); 
+}
+
+void FlowTableDnd::on_child_drag_end (const Glib::RefPtr<Gdk::DragContext>& drag_context,
+                        Gtk::Widget* child)
+{
+  FlowTableItem* item = find_current_dnd_item (child);
+  LayoutWidgetBase* base = dnd_datawidget_from_item (item);
+  if (base->get_dnd_in_progress())
+  {
+    if (!item)
+      return;
+    if (item->m_first)
+      item->m_first->show();
+    if (item->m_second)
+      item->m_second->show();  
+  }
+  else if (!m_internal_drag)
+  {
+    sharedptr<LayoutItem> item = base->get_layout_item();
+    sharedptr<LayoutGroup> group = sharedptr<LayoutGroup>::cast_dynamic(get_layout_item());
+    group->remove_item(item);
+  }  
+  signal_layout_changed().emit();
 }
 
 void FlowTableDnd::set_design_mode(bool value)

Modified: trunk/glom/utility_widgets/flowtable_dnd.h
==============================================================================
--- trunk/glom/utility_widgets/flowtable_dnd.h	(original)
+++ trunk/glom/utility_widgets/flowtable_dnd.h	Tue Apr 29 16:39:20 2008
@@ -23,6 +23,7 @@
 
 #include <gtkmm.h>
 #include "flowtable.h"
+#include "layoutwidgetutils.h"
 
 #ifdef GLOM_ENABLE_CLIENT_ONLY
 #error FlowTableDnd does not work in Client-only mode
@@ -31,7 +32,9 @@
 namespace Glom
 {
 
-class FlowTableDnd : public FlowTable
+class FlowTableDnd : 
+  public FlowTable,
+  public LayoutWidgetUtils
 {
 public:
   FlowTableDnd();
@@ -47,8 +50,10 @@
   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* child);  
   virtual void on_child_drag_data_get(const Glib::RefPtr<Gdk::DragContext>& drag_context, 
-                                           const Gtk::SelectionData& selection_data, guint, guint time, Gtk::Widget* child);  
-
+                                           Gtk::SelectionData& selection_data, guint, guint time, Gtk::Widget* child);  
+  virtual void on_child_drag_begin (const Glib::RefPtr<Gdk::DragContext>& drag_context, Gtk::Widget* child);
+  virtual void on_child_drag_end (const Glib::RefPtr<Gdk::DragContext>& drag_context, Gtk::Widget* child);    
+    
   virtual void start_dnd (Gtk::Widget& child);
   virtual void stop_dnd (Gtk::Widget& child);
 
@@ -60,6 +65,8 @@
   virtual void on_dnd_add_layout_item_button (LayoutWidgetBase* above) = 0;
   virtual void on_dnd_add_layout_item_text (LayoutWidgetBase* above) = 0;
   virtual void on_dnd_add_layout_notebook (LayoutWidgetBase* above) = 0;
+  virtual void on_dnd_add_layout_item (LayoutWidgetBase* above,
+                                       sharedptr<LayoutItem>& item) = 0;
   
   virtual void on_dnd_add_placeholder(LayoutWidgetBase* above) = 0;
   virtual void on_dnd_remove_placeholder() = 0;    
@@ -68,10 +75,13 @@
   bool dnd_remove_placeholder_real();
   
   FlowTableItem* dnd_item_at_position(int x, int y);
-  LayoutWidgetBase* dnd_datawidget_from_item();
+  LayoutWidgetBase* dnd_datawidget_from_item(FlowTableItem* item);
     
 private:
+  FlowTableItem* find_current_dnd_item (Gtk::Widget* child, int x = -1, int y = -1);
   FlowTableItem* m_current_dnd_item;
+    
+  bool m_internal_drag;
 };
 
 } // namespace Glom

Modified: trunk/glom/utility_widgets/layoutwidgetbase.cc
==============================================================================
--- trunk/glom/utility_widgets/layoutwidgetbase.cc	(original)
+++ trunk/glom/utility_widgets/layoutwidgetbase.cc	Tue Apr 29 16:39:20 2008
@@ -27,7 +27,8 @@
 
 LayoutWidgetBase::LayoutWidgetBase()
 #ifndef GLOM_ENABLE_CLIENT_ONLY
-: m_pLayoutItem(0)
+: m_pLayoutItem(0),
+  m_drag_in_progress(false)
 #endif // !GLOM_ENABLE_CLIENT_ONLY
 {
 
@@ -102,4 +103,15 @@
     widget.modify_base(Gtk::STATE_NORMAL, Gdk::Color(bg));
 }
 
+void LayoutWidgetBase::set_dnd_in_progress(bool drag)
+{
+  m_drag_in_progress = drag;
+}
+
+bool LayoutWidgetBase::get_dnd_in_progress()
+{
+  return m_drag_in_progress; 
+}
+
+
 } //namespace Glom

Modified: trunk/glom/utility_widgets/layoutwidgetbase.h
==============================================================================
--- trunk/glom/utility_widgets/layoutwidgetbase.h	(original)
+++ trunk/glom/utility_widgets/layoutwidgetbase.h	Tue Apr 29 16:39:20 2008
@@ -77,6 +77,11 @@
 
   virtual void set_read_only(bool read_only = true);
 
+#ifndef GLOM_ENABLE_CLIENT_ONLY
+  void set_dnd_in_progress(bool drag = true);
+  bool get_dnd_in_progress();
+#endif // !GLOM_ENABLE_CLIENT_ONLY
+    
 protected:
   virtual App_Glom* get_application() const; // = 0;
 
@@ -95,6 +100,7 @@
   type_signal_user_requested_layout m_signal_user_requested_layout;
   type_signal_user_requested_layout_properties m_signal_user_requested_layout_properties;
 
+  bool m_drag_in_progress;
 #endif // !GLOM_ENABLE_CLIENT_ONLY
 };
 



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