Update of /cvsroot/mahogany/M/src/gui
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv15288/src/gui

Modified Files:
        wxFolderTree.cpp 
Log Message:
implemented folder reordering in the tree by dragging them

Index: wxFolderTree.cpp
===================================================================
RCS file: /cvsroot/mahogany/M/src/gui/wxFolderTree.cpp,v
retrieving revision 1.227
retrieving revision 1.228
diff -b -u -2 -r1.227 -r1.228
--- wxFolderTree.cpp    12 Jan 2004 15:20:38 -0000      1.227
+++ wxFolderTree.cpp    13 Mar 2004 18:58:39 -0000      1.228
@@ -339,5 +339,7 @@
    void UpdateColours();
 
-   // callbacks
+   // tree event handlers
+   // -------------------
+
    void OnKeyDown(wxTreeEvent& event);
    void OnChar(wxKeyEvent& event);
@@ -357,4 +359,7 @@
    void OnEndLabelEdit(wxTreeEvent&);
 
+   void OnTreeBeginDrag(wxTreeEvent& event);
+   void OnTreeEndDrag(wxTreeEvent& event);
+
    void OnIdle(wxIdleEvent& event);
 
@@ -384,4 +389,16 @@
    }
 
+   // (safely) get the folder from item id
+   MFolder *GetFolderFromTreeItem(const wxTreeItemId& item) const
+   {
+      wxFolderTreeNode *node = GetFolderTreeNode(item);
+      CHECK( node, NULL, _T("tree item without associated data?") );
+
+      MFolder *folder = node->GetFolder();
+      ASSERT_MSG( folder, _T("tree node without associated folder?") );
+
+      return folder;
+   }
+
 protected:
    // return true if the current folder may be opened
@@ -432,5 +449,5 @@
    bool IsEditingInPlace() const;
 
-   // reexpand branch - called when something in the tree changes
+   // reexpand branch -- called when something in the tree changes
    void ReopenBranch(wxTreeItemId parent);
 
@@ -453,4 +470,16 @@
    wxTreeItemId GetNextItem(wxTreeItemId id, bool next = true) const;
 
+   // reposition the src folder between its two siblings, the caller must call
+   // ReopenBranch() to refresh the tree if wanted
+   //
+   // idBefore may be invalid, the other 2 are always valid
+   void MoveFolderBetween(wxTreeItemId id,
+                          wxTreeItemId idBefore,
+                          wxTreeItemId idAfter) const;
+
+   // MoveFolderBetween() helpers, see comments in them
+   int SetIndicesBefore(wxTreeItemId id) const;
+   int OffsetIndicesAfter(wxTreeItemId id) const;
+
 private:
    class FolderMenu : public wxMenu
@@ -580,4 +609,8 @@
    wxString m_suffix;
 
+
+   // the item currently being dragged or invalid item
+   wxTreeItemId m_idDragged;
+
 #ifdef USE_TREE_ACTIVATE_BUGFIX
    bool MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result);
@@ -712,4 +745,7 @@
    EVT_TREE_END_LABEL_EDIT(-1,   wxFolderTreeImpl::OnEndLabelEdit)
 
+   EVT_TREE_BEGIN_DRAG(-1, wxFolderTreeImpl::OnTreeBeginDrag)
+   EVT_TREE_END_DRAG(-1, wxFolderTreeImpl::OnTreeEndDrag)
+
    EVT_RIGHT_DOWN(wxFolderTreeImpl::OnRightDown)
 #ifdef USE_MIDDLE_CLICK_HACK
@@ -2446,4 +2482,255 @@
 
 // ----------------------------------------------------------------------------
+// dragging items in the tree
+// ----------------------------------------------------------------------------
+
+// this function sets tree positions for all the siblings of the given folder
+// up to and including it and returns the new index of idThis
+int wxFolderTreeImpl::SetIndicesBefore(wxTreeItemId idThis) const
+{
+   static const int idxInvalid = GetNumericDefault(MP_FOLDER_TREEINDEX);
+
+   const wxTreeItemId idParent = GetItemParent(idThis);
+
+   int idxThis = 0;
+
+   wxTreeItemIdValue cookie;
+   wxTreeItemId id = GetFirstChild(idParent, cookie);
+   while ( id.IsOk() )
+   {
+      MFolder * const folder = GetFolderFromTreeItem(id);
+      if ( !folder )
+         return idxInvalid;
+
+      int idx = folder->GetTreeIndex();
+      if ( idx != idxInvalid )
+      {
+         // so far, so good: remember the highest previous index
+         ASSERT_MSG( idx >= idxThis, _T("inconsistent tree index values!") );
+
+         idxThis = idx;
+      }
+      else // item without defined position in the tree
+      {
+         // set it now
+         folder->SetTreeIndex(++idxThis);
+      }
+
+      if ( id == idThis )
+         break;
+
+      id = GetNextChild(idParent, cookie);
+   }
+
+   return idxThis;
+}
+
+// this functions moves up the tree positions of all the folders starting
+// (inclusively) from the given one and returns the new index of idThis
+int wxFolderTreeImpl::OffsetIndicesAfter(wxTreeItemId idThis) const
+{
+   static const int idxInvalid = GetNumericDefault(MP_FOLDER_TREEINDEX);
+
+   const wxTreeItemId idParent = GetItemParent(idThis);
+
+   wxTreeItemId id = GetLastChild(idParent);
+   while ( id.IsOk() )
+   {
+      MFolder * const folder = GetFolderFromTreeItem(id);
+      if ( !folder )
+         return idxInvalid;
+
+      int idx = folder->GetTreeIndex();
+      if ( idx != idxInvalid )
+      {
+         // bump the index up
+         folder->SetTreeIndex(idx + 1);
+      }
+      //else: nothing to do, leave it at the end of all the other items
+
+      if ( id == idThis )
+      {
+         // done, alll indices from this item up to the end are offset
+         ASSERT_MSG( idx != idxInvalid, _T("logic error") );
+
+         return idx + 1;
+      }
+
+      id = GetPrevSibling(id);
+   }
+
+   return idxInvalid;
+}
+
+void
+wxFolderTreeImpl::MoveFolderBetween(wxTreeItemId id,
+                                    wxTreeItemId idBefore,
+                                    wxTreeItemId idAfter) const
+{
+   static const int idxInvalid = GetNumericDefault(MP_FOLDER_TREEINDEX);
+
+   // the (new) index of the folder, must be in ]idxBefore, idxAfter[
+   int idx = idxInvalid;
+
+   const MFolder * const folderAfter = GetFolderFromTreeItem(idAfter);
+   if ( !folderAfter )
+      return;
+
+   int idxAfter = folderAfter->GetTreeIndex();
+   if ( idxAfter == idxInvalid )
+   {
+      if ( idBefore.IsOk() )
+      {
+         const MFolder * const folderBefore = GetFolderFromTreeItem(idBefore);
+         if ( !folderBefore )
+            return;
+
+         int idxBefore = folderBefore->GetTreeIndex();
+         if ( idxBefore == idxInvalid )
+         {
+            // we have to fix the indices of all the items before this one so
+            // make it position stick, otherwise it would bubble up to the top
+            idx = SetIndicesBefore(idBefore);
+            if ( idx == idxInvalid )
+               return;
+
+            idx++;
+         }
+         else // position just after idxBefore
+         {
+            idx = idxBefore + 1;
+         }
+      }
+      else // make folder the first child
+      {
+         idx = 0;
+      }
+   }
+   else // we must select an index less than idxAfter
+   {
+      if ( idBefore )
+      {
+         const MFolder * const folderBefore = GetFolderFromTreeItem(idBefore);
+         if ( !folderBefore )
+            return;
+
+         int idxBefore = folderBefore->GetTreeIndex();
+
+         // it can't possibly happen that an item without index is positioned
+         // before another item with index
+         ASSERT_MSG( idxBefore != idxInvalid, _T("confusion with tree indices!") );
+
+         // this might not be the final value, it will be tested below
+         idx = idxBefore + 1;
+      }
+      else // position just before idxAfter
+      {
+         // same as above: this value might be invalid
+         idx = idxAfter - 1;
+      }
+
+      // did we choose a valid value above?
+      if ( idx < 0 || idx >= idxAfter )
+      {
+         // we have to offset the indices of all subsequent items...
+         idx = OffsetIndicesAfter(idAfter);
+         if ( idx == idxInvalid )
+            return;
+
+         idx--;
+      }
+   }
+
+   // do change the folder position
+   ASSERT_MSG( idx != idxInvalid, _T("logic error in MoveFolderBetween()") );
+
+   MFolder * const folder = GetFolderFromTreeItem(id);
+   if ( !folder )
+      return;
+
+   folder->SetTreeIndex(idx);
+}
+
+void wxFolderTreeImpl::OnTreeBeginDrag(wxTreeEvent& event)
+{
+   // do we have something basically valid?
+   const wxTreeItemId idDragged = event.GetItem();
+   const MFolder * const folder = GetFolderFromTreeItem(idDragged);
+   if ( !folder )
+      return;
+
+   // determine if we can drag this item at all?
+   if ( folder->GetType() == MF_ROOT ||
+         (folder->GetFlags() & MF_FLAGS_DONTDELETE) )
+   {
+      wxLogStatus(GetFrame(this),
+                 _("The folder \"%s\" cannot be moved."),
+                 folder->GetFullName().c_str());
+      return;
+   }
+
+   // ok, allow the user to drag it
+   ASSERT_MSG( !m_idDragged.IsOk(), _T("didn't finish the previous drag?") );
+
+   m_idDragged = idDragged;
+   event.Allow();
+}
+
+void wxFolderTreeImpl::OnTreeEndDrag(wxTreeEvent& event)
+{
+   CHECK_RET( m_idDragged.IsOk(), _T("end drag without begin drag?") );
+
+   // get the source and destination folders
+   const wxTreeItemId idDst = event.GetItem();
+   const wxTreeItemId idSrc = m_idDragged;
+   m_idDragged.Unset();
+
+   if ( !idDst.IsOk() )
+   {
+      // happens if the user dragged the mouse completely outside the window,
+      // for example
+      return;
+   }
+
+   MFolder * const folderDst = GetFolderFromTreeItem(idDst);
+   MFolder * const folderSrc = GetFolderFromTreeItem(idSrc);
+
+   if ( !folderDst || !folderSrc )
+   {
+      // this is not supposed to happen (debug error message already given)
+      return;
+   }
+
+   // do we want to just change the item position among its siblings or move it?
+   if ( folderDst->GetParent() == folderSrc->GetParent() )
+   {
+      // just changing the order: put the src folder just before the dst one 
+      // (not just after: this would make it impossible to reposition a folder
+      // to be the first one among its siblings, as dropping it on the parent
+      // would move it one level up)
+      MoveFolderBetween(idSrc, GetPrevSibling(idDst), idDst);
+
+      // reflect the changes in the tree
+      ReopenBranch(GetItemParent(idDst));
+   }
+   else // really moving
+   {
+      if ( !folderSrc->Move(folderDst) )
+      {
+         wxLogError(_("Failed to move the folder \"%s\" to \"%s\"."),
+                    folderSrc->GetFullName().c_str(),
+                    folderDst->GetFullName().c_str());
+      }
+      else // moved ok
+      {
+         wxLogStatus(GetFrame(this),
+                     _("Successfully moved the folder \"%s\" to \"%s\"."),
+                     folderSrc->GetFullName().c_str(),
+                     folderDst->GetFullName().c_str());
+      }
+   }
+}
+
+// ----------------------------------------------------------------------------
 // tree notifications
 // ----------------------------------------------------------------------------



-------------------------------------------------------
This SF.Net email is sponsored by: IBM Linux Tutorials
Free Linux tutorial presented by Daniel Robbins, President and CEO of
GenToo technologies. Learn everything from fundamentals to system
administration.http://ads.osdn.com/?ad_id=1470&alloc_id=3638&op=click
_______________________________________________
Mahogany-cvsupdates mailing list
[EMAIL PROTECTED]
https://lists.sourceforge.net/lists/listinfo/mahogany-cvsupdates

Reply via email to