diff options
author | sky@google.com <sky@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-02-26 17:51:54 +0000 |
---|---|---|
committer | sky@google.com <sky@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-02-26 17:51:54 +0000 |
commit | 56c66f21ef57db319f453499d3bf1442e5a0455c (patch) | |
tree | a401e0c1e636b3796089081086cbb954e60ca59e | |
parent | dddb3f5497326cb18f519bbbc4b79a8a5cbc53c9 (diff) | |
download | chromium_src-56c66f21ef57db319f453499d3bf1442e5a0455c.zip chromium_src-56c66f21ef57db319f453499d3bf1442e5a0455c.tar.gz chromium_src-56c66f21ef57db319f453499d3bf1442e5a0455c.tar.bz2 |
Adds ability for tree model to reorder its children. I'm going to use
this when sorting the contents of a bookmark folder.
BUG=1750
TEST=none
Review URL: http://codereview.chromium.org/28175
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@10477 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/views/tree_model.h | 6 | ||||
-rw-r--r-- | chrome/views/tree_view.cc | 70 | ||||
-rw-r--r-- | chrome/views/tree_view.h | 7 |
3 files changed, 68 insertions, 15 deletions
diff --git a/chrome/views/tree_model.h b/chrome/views/tree_model.h index 68a3ff7..3608fbc 100644 --- a/chrome/views/tree_model.h +++ b/chrome/views/tree_model.h @@ -39,6 +39,12 @@ class TreeModelObserver { int start, int count) = 0; + // Notification the children of |parent| have been reordered. Note, only + // the direct children of |parent| have been reordered, not descendants. + // TODO(sky): make this pure virtual after all sites have been updated. + virtual void TreeNodeChildrenReordered(TreeModel* model, + TreeModelNode* parent) {} + // Notification that the contents of a node has changed. virtual void TreeNodeChanged(TreeModel* model, TreeModelNode* node) = 0; }; diff --git a/chrome/views/tree_view.cc b/chrome/views/tree_view.cc index a9229c8..5f04ac4 100644 --- a/chrome/views/tree_view.cc +++ b/chrome/views/tree_view.cc @@ -239,22 +239,10 @@ void TreeView::TreeNodesRemoved(TreeModel* model, int start, int count) { DCHECK(parent && start >= 0 && count > 0); - if (node_to_details_map_.find(parent) == node_to_details_map_.end()) { - // User hasn't navigated to this entry yet. Ignore the change. + HTREEITEM parent_tree_item = GetTreeItemForNodeDuringMutation(parent); + if (!parent_tree_item) return; - } - HTREEITEM parent_tree_item = NULL; - if (!root_shown_ || parent != model_->GetRoot()) { - const NodeDetails* details = GetNodeDetails(parent); - if (!details->loaded_children) { - // Ignore the change, we haven't actually created entries in the tree - // for the children. - return; - } - parent_tree_item = details->tree_item; - } else { - parent_tree_item = TreeView_GetRoot(tree_view_); - } + // Find the last item. Windows doesn't offer a convenient way to get the // TREEITEM at a particular index, so we iterate. HTREEITEM tree_item = TreeView_GetChild(tree_view_, parent_tree_item); @@ -271,6 +259,44 @@ void TreeView::TreeNodesRemoved(TreeModel* model, } } +namespace { + +// Callback function used to compare two items. The first two args are the +// LPARAMs of the HTREEITEMs being compared. The last arg maps from LPARAM +// to order. This is invoked from TreeNodeChildrenReordered. +int CALLBACK CompareTreeItems(LPARAM item1_lparam, + LPARAM item2_lparam, + LPARAM map_as_lparam) { + std::map<int, int>& mapping = + *reinterpret_cast<std::map<int, int>*>(map_as_lparam); + return mapping[static_cast<int>(item1_lparam)] - + mapping[static_cast<int>(item2_lparam)]; +} + +} // namespace + +void TreeView::TreeNodeChildrenReordered(TreeModel* model, + TreeModelNode* parent) { + DCHECK(parent); + if (model_->GetChildCount(parent) <= 1) + return; + + TVSORTCB sort_details; + sort_details.hParent = GetTreeItemForNodeDuringMutation(parent); + if (!sort_details.hParent) + return; + + std::map<int, int> lparam_to_order_map; + for (int i = 0; i < model_->GetChildCount(parent); ++i) { + TreeModelNode* node = model_->GetChild(parent, i); + lparam_to_order_map[GetNodeDetails(node)->id] = i; + } + + sort_details.lpfnCompare = &CompareTreeItems; + sort_details.lParam = reinterpret_cast<LPARAM>(&lparam_to_order_map); + TreeView_SortChildrenCB(tree_view_, &sort_details, 0); +} + void TreeView::TreeNodeChanged(TreeModel* model, TreeModelNode* node) { if (node_to_details_map_.find(node) == node_to_details_map_.end()) { // User hasn't navigated to this entry yet. Ignore the change. @@ -622,6 +648,20 @@ HIMAGELIST TreeView::CreateImageList() { return image_list; } +HTREEITEM TreeView::GetTreeItemForNodeDuringMutation(TreeModelNode* node) { + if (node_to_details_map_.find(node) == node_to_details_map_.end()) { + // User hasn't navigated to this entry yet. Ignore the change. + return NULL; + } + if (!root_shown_ || node != model_->GetRoot()) { + const NodeDetails* details = GetNodeDetails(node); + if (!details->loaded_children) + return NULL; + return details->tree_item; + } + return TreeView_GetRoot(tree_view_); +} + LRESULT CALLBACK TreeView::TreeWndProc(HWND window, UINT message, WPARAM w_param, diff --git a/chrome/views/tree_view.h b/chrome/views/tree_view.h index 582de9f..5b86981 100644 --- a/chrome/views/tree_view.h +++ b/chrome/views/tree_view.h @@ -105,6 +105,8 @@ class TreeView : public NativeControl, TreeModelObserver { TreeModelNode* parent, int start, int count); + virtual void TreeNodeChildrenReordered(TreeModel* model, + TreeModelNode* parent); virtual void TreeNodeChanged(TreeModel* model, TreeModelNode* node); // Sets the controller, which may be null. TreeView does not take ownership @@ -234,6 +236,11 @@ class TreeView : public NativeControl, TreeModelObserver { // Creates the image list to use for the tree. HIMAGELIST CreateImageList(); + // Returns the HTREEITEM for |node|. This is intended to be called when a + // model mutation event occur with |node| as the parent. This returns null + // if the user has never expanded |node| or all of its parents. + HTREEITEM GetTreeItemForNodeDuringMutation(TreeModelNode* node); + // The window function installed on the treeview. static LRESULT CALLBACK TreeWndProc(HWND window, UINT message, |