diff options
Diffstat (limited to 'chrome/views/controls/tree')
-rw-r--r-- | chrome/views/controls/tree/tree_model.h | 91 | ||||
-rw-r--r-- | chrome/views/controls/tree/tree_node_iterator.h | 74 | ||||
-rw-r--r-- | chrome/views/controls/tree/tree_node_iterator_unittest.cc | 41 | ||||
-rw-r--r-- | chrome/views/controls/tree/tree_node_model.h | 283 | ||||
-rw-r--r-- | chrome/views/controls/tree/tree_view.cc | 745 | ||||
-rw-r--r-- | chrome/views/controls/tree/tree_view.h | 305 |
6 files changed, 0 insertions, 1539 deletions
diff --git a/chrome/views/controls/tree/tree_model.h b/chrome/views/controls/tree/tree_model.h deleted file mode 100644 index 8c54b75..0000000 --- a/chrome/views/controls/tree/tree_model.h +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright (c) 2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_VIEWS_CONTROLS_TREE_TREE_MODEL_H_ -#define CHROME_VIEWS_CONTROLS_TREE_TREE_MODEL_H_ - -#include <string> - -#include "base/logging.h" - -class SkBitmap; - -namespace views { - -class TreeModel; - -// TreeModelNode -------------------------------------------------------------- - -// Type of class returned from the model. -class TreeModelNode { - public: - // Returns the title for the node. - virtual std::wstring GetTitle() = 0; -}; - -// Observer for the TreeModel. Notified of significant events to the model. -class TreeModelObserver { - public: - // Notification that nodes were added to the specified parent. - virtual void TreeNodesAdded(TreeModel* model, - TreeModelNode* parent, - int start, - int count) = 0; - - // Notification that nodes were removed from the specified parent. - virtual void TreeNodesRemoved(TreeModel* model, - TreeModelNode* parent, - 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. - virtual void TreeNodeChildrenReordered(TreeModel* model, - TreeModelNode* parent) = 0; - - // Notification that the contents of a node has changed. - virtual void TreeNodeChanged(TreeModel* model, TreeModelNode* node) = 0; -}; - -// TreeModel ------------------------------------------------------------------ - -// The model for TreeView. -class TreeModel { - public: - // Returns the root of the tree. This may or may not be shown in the tree, - // see SetRootShown for details. - virtual TreeModelNode* GetRoot() = 0; - - // Returns the number of children in the specified node. - virtual int GetChildCount(TreeModelNode* parent) = 0; - - // Returns the child node at the specified index. - virtual TreeModelNode* GetChild(TreeModelNode* parent, int index) = 0; - - // Returns the parent of a node, or NULL if node is the root. - virtual TreeModelNode* GetParent(TreeModelNode* node) = 0; - - // Sets the observer of the model. - virtual void SetObserver(TreeModelObserver* observer) = 0; - - // Sets the title of the specified node. - // This is only invoked if the node is editable and the user edits a node. - virtual void SetTitle(TreeModelNode* node, - const std::wstring& title) { - NOTREACHED(); - } - - // Returns the set of icons for the nodes in the tree. You only need override - // this if you don't want to use the default folder icons. - virtual void GetIcons(std::vector<SkBitmap>* icons) {} - - // Returns the index of the icon to use for |node|. Return -1 to use the - // default icon. The index is relative to the list of icons returned from - // GetIcons. - virtual int GetIconIndex(TreeModelNode* node) { return -1; } -}; - -} // namespace views - -#endif // CHROME_VIEWS_CONTROLS_TREE_TREE_MODEL_H_ diff --git a/chrome/views/controls/tree/tree_node_iterator.h b/chrome/views/controls/tree/tree_node_iterator.h deleted file mode 100644 index fa28b3e..0000000 --- a/chrome/views/controls/tree/tree_node_iterator.h +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_VIEWS_CONTROLS_TREE_TREE_NODE_ITERATOR_H_ -#define CHROME_VIEWS_CONTROLS_TREE_TREE_NODE_ITERATOR_H_ - -#include <stack> - -#include "base/basictypes.h" -#include "base/logging.h" - -namespace views { - -// Iterator that iterates over the descendants of a node. The iteration does -// not include the node itself, only the descendants. The following illustrates -// typical usage: -// while (iterator.has_next()) { -// Node* node = iterator.Next(); -// // do something with node. -// } -template <class NodeType> -class TreeNodeIterator { - public: - explicit TreeNodeIterator(NodeType* node) { - if (node->GetChildCount() > 0) - positions_.push(Position<NodeType>(node, 0)); - } - - // Returns true if there are more descendants. - bool has_next() const { return !positions_.empty(); } - - // Returns the next descendant. - NodeType* Next() { - if (!has_next()) { - NOTREACHED(); - return NULL; - } - - NodeType* result = positions_.top().node->GetChild(positions_.top().index); - - // Make sure we don't attempt to visit result again. - positions_.top().index++; - - // Iterate over result's children. - positions_.push(Position<NodeType>(result, 0)); - - // Advance to next position. - while (!positions_.empty() && positions_.top().index >= - positions_.top().node->GetChildCount()) { - positions_.pop(); - } - - return result; - } - - private: - template <class PositionNodeType> - struct Position { - Position(PositionNodeType* node, int index) : node(node), index(index) {} - Position() : node(NULL), index(-1) {} - - PositionNodeType* node; - int index; - }; - - std::stack<Position<NodeType> > positions_; - - DISALLOW_COPY_AND_ASSIGN(TreeNodeIterator); -}; - -} // namespace views - -#endif // CHROME_VIEWS_CONTROLS_TREE_TREE_NODE_ITERATOR_H_ diff --git a/chrome/views/controls/tree/tree_node_iterator_unittest.cc b/chrome/views/controls/tree/tree_node_iterator_unittest.cc deleted file mode 100644 index 3aec1af..0000000 --- a/chrome/views/controls/tree/tree_node_iterator_unittest.cc +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "testing/gtest/include/gtest/gtest.h" - -#include "chrome/views/controls/tree/tree_node_iterator.h" -#include "chrome/views/controls/tree/tree_node_model.h" - -typedef testing::Test TreeNodeIteratorTest; - -using views::TreeNodeWithValue; - -TEST_F(TreeNodeIteratorTest, Test) { - TreeNodeWithValue<int> root; - root.Add(0, new TreeNodeWithValue<int>(1)); - root.Add(1, new TreeNodeWithValue<int>(2)); - TreeNodeWithValue<int>* f3 = new TreeNodeWithValue<int>(3); - root.Add(2, f3); - TreeNodeWithValue<int>* f4 = new TreeNodeWithValue<int>(4); - f3->Add(0, f4); - f4->Add(0, new TreeNodeWithValue<int>(5)); - - views::TreeNodeIterator<TreeNodeWithValue<int> > iterator(&root); - ASSERT_TRUE(iterator.has_next()); - ASSERT_EQ(root.GetChild(0), iterator.Next()); - - ASSERT_TRUE(iterator.has_next()); - ASSERT_EQ(root.GetChild(1), iterator.Next()); - - ASSERT_TRUE(iterator.has_next()); - ASSERT_EQ(root.GetChild(2), iterator.Next()); - - ASSERT_TRUE(iterator.has_next()); - ASSERT_EQ(f4, iterator.Next()); - - ASSERT_TRUE(iterator.has_next()); - ASSERT_EQ(f4->GetChild(0), iterator.Next()); - - ASSERT_FALSE(iterator.has_next()); -} diff --git a/chrome/views/controls/tree/tree_node_model.h b/chrome/views/controls/tree/tree_node_model.h deleted file mode 100644 index 14e5748..0000000 --- a/chrome/views/controls/tree/tree_node_model.h +++ /dev/null @@ -1,283 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_VIEWS_CONTROLS_TREE_TREE_NODE_MODEL_H_ -#define CHROME_VIEWS_CONTROLS_TREE_TREE_NODE_MODEL_H_ - -#include <algorithm> -#include <vector> - -#include "base/basictypes.h" -#include "base/scoped_ptr.h" -#include "base/scoped_vector.h" -#include "base/stl_util-inl.h" -#include "chrome/views/controls/tree/tree_model.h" - -namespace views { - -// TreeNodeModel and TreeNodes provide an implementation of TreeModel around -// TreeNodes. TreeNodes form a directed acyclic graph. -// -// TreeNodes own their children, so that deleting a node deletes all -// descendants. -// -// TreeNodes do NOT maintain a pointer back to the model. As such, if you -// are using TreeNodes with a TreeNodeModel you will need to notify the observer -// yourself any time you make any change directly to the TreeNodes. For example, -// if you directly invoke SetTitle on a node it does not notify the -// observer, you will need to do it yourself. This includes the following -// methods: SetTitle, Remove and Add. TreeNodeModel provides cover -// methods that mutate the TreeNodes and notify the observer. If you are using -// TreeNodes with a TreeNodeModel use the cover methods to save yourself the -// headache. -// -// The following example creates a TreeNode with two children and then -// creates a TreeNodeModel from it: -// -// TreeNodeWithValue<int> root = new TreeNodeWithValue<int>(0, L"root"); -// root.add(new TreeNodeWithValue<int>(1, L"child 1")); -// root.add(new TreeNodeWithValue<int>(1, L"child 2")); -// TreeNodeModel<TreeNodeWithValue<int>>* model = -// new TreeNodeModel<TreeNodeWithValue<int>>(root); -// -// Two variants of TreeNode are provided here: -// -// . TreeNode itself is intended for subclassing. It has one type parameter -// that corresponds to the type of the node. When subclassing use your class -// name as the type parameter, eg: -// class MyTreeNode : public TreeNode<MyTreeNode> . -// . TreeNodeWithValue is a trivial subclass of TreeNode that has one type -// type parameter: a value type that is associated with the node. -// -// Which you use depends upon the situation. If you want to subclass and add -// methods, then use TreeNode. If you don't need any extra methods and just -// want to associate a value with each node, then use TreeNodeWithValue. -// -// Regardless of which TreeNode you use, if you are using the nodes with a -// TreeView take care to notify the observer when mutating the nodes. - -template <class NodeType> -class TreeNodeModel; - -// TreeNode ------------------------------------------------------------------- - -template <class NodeType> -class TreeNode : public TreeModelNode { - public: - TreeNode() : parent_(NULL) { } - - explicit TreeNode(const std::wstring& title) - : title_(title), parent_(NULL) {} - - virtual ~TreeNode() { - } - - // Adds the specified child node. - virtual void Add(int index, NodeType* child) { - DCHECK(child && index >= 0 && index <= GetChildCount()); - // If the node has a parent, remove it from its parent. - NodeType* node_parent = child->GetParent(); - if (node_parent) - node_parent->Remove(node_parent->IndexOfChild(child)); - child->parent_ = static_cast<NodeType*>(this); - children_->insert(children_->begin() + index, child); - } - - // Removes the node by index. This does NOT delete the specified node, it is - // up to the caller to delete it when done. - virtual NodeType* Remove(int index) { - DCHECK(index >= 0 && index < GetChildCount()); - NodeType* node = GetChild(index); - node->parent_ = NULL; - children_->erase(index + children_->begin()); - return node; - } - - // Removes all the children from this node. This does NOT delete the nodes. - void RemoveAll() { - for (size_t i = 0; i < children_->size(); ++i) - children_[i]->parent_ = NULL; - children_->clear(); - } - - // Returns the number of children. - int GetChildCount() { - return static_cast<int>(children_->size()); - } - - // Returns a child by index. - NodeType* GetChild(int index) { - DCHECK(index >= 0 && index < GetChildCount()); - return children_[index]; - } - - // Returns the parent. - NodeType* GetParent() { - return parent_; - } - - // Returns the index of the specified child, or -1 if node is a not a child. - int IndexOfChild(const NodeType* node) { - DCHECK(node); - typename std::vector<NodeType*>::iterator i = - std::find(children_->begin(), children_->end(), node); - if (i != children_->end()) - return static_cast<int>(i - children_->begin()); - return -1; - } - - // Sets the title of the node. - void SetTitle(const std::wstring& string) { - title_ = string; - } - - // Returns the title of the node. - std::wstring GetTitle() { - return title_; - } - - // Returns true if this is the root. - bool IsRoot() { return (parent_ == NULL); } - - // Returns true if this == ancestor, or one of this nodes parents is - // ancestor. - bool HasAncestor(NodeType* ancestor) const { - if (ancestor == this) - return true; - if (!ancestor) - return false; - return parent_ ? parent_->HasAncestor(ancestor) : false; - } - - protected: - std::vector<NodeType*>& children() { return children_.get(); } - - private: - // Title displayed in the tree. - std::wstring title_; - - NodeType* parent_; - - // Children. - ScopedVector<NodeType> children_; - - DISALLOW_COPY_AND_ASSIGN(TreeNode); -}; - -// TreeNodeWithValue ---------------------------------------------------------- - -template <class ValueType> -class TreeNodeWithValue : public TreeNode< TreeNodeWithValue<ValueType> > { - private: - typedef TreeNode< TreeNodeWithValue<ValueType> > ParentType; - - public: - TreeNodeWithValue() { } - - TreeNodeWithValue(const ValueType& value) - : ParentType(std::wstring()), value(value) { } - - TreeNodeWithValue(const std::wstring& title, const ValueType& value) - : ParentType(title), value(value) { } - - ValueType value; - - private: - DISALLOW_COPY_AND_ASSIGN(TreeNodeWithValue); -}; - -// TreeNodeModel -------------------------------------------------------------- - -// TreeModel implementation intended to be used with TreeNodes. -template <class NodeType> -class TreeNodeModel : public TreeModel { - public: - // Creates a TreeNodeModel with the specified root node. The root is owned - // by the TreeNodeModel. - explicit TreeNodeModel(NodeType* root) - : root_(root), - observer_(NULL) { - } - - virtual ~TreeNodeModel() {} - - virtual void SetObserver(TreeModelObserver* observer) { - observer_ = observer; - } - - TreeModelObserver* GetObserver() { - return observer_; - } - - // TreeModel methods, all forward to the nodes. - virtual NodeType* GetRoot() { return root_.get(); } - - virtual int GetChildCount(TreeModelNode* parent) { - DCHECK(parent); - return AsNode(parent)->GetChildCount(); - } - - virtual NodeType* GetChild(TreeModelNode* parent, int index) { - DCHECK(parent); - return AsNode(parent)->GetChild(index); - } - - virtual TreeModelNode* GetParent(TreeModelNode* node) { - DCHECK(node); - return AsNode(node)->GetParent(); - } - - NodeType* AsNode(TreeModelNode* model_node) { - return reinterpret_cast<NodeType*>(model_node); - } - - // Sets the title of the specified node. - virtual void SetTitle(TreeModelNode* node, - const std::wstring& title) { - DCHECK(node); - AsNode(node)->SetTitle(title); - NotifyObserverTreeNodeChanged(node); - } - - void Add(NodeType* parent, int index, NodeType* child) { - DCHECK(parent && child); - parent->Add(index, child); - NotifyObserverTreeNodesAdded(parent, index, 1); - } - - NodeType* Remove(NodeType* parent, int index) { - DCHECK(parent); - NodeType* child = parent->Remove(index); - NotifyObserverTreeNodesRemoved(parent, index, 1); - return child; - } - - void NotifyObserverTreeNodesAdded(NodeType* parent, int start, int count) { - if (observer_) - observer_->TreeNodesAdded(this, parent, start, count); - } - - void NotifyObserverTreeNodesRemoved(NodeType* parent, int start, int count) { - if (observer_) - observer_->TreeNodesRemoved(this, parent, start, count); - } - - virtual void NotifyObserverTreeNodeChanged(TreeModelNode* node) { - if (observer_) - observer_->TreeNodeChanged(this, node); - } - - private: - // The root. - scoped_ptr<NodeType> root_; - - // The observer. - TreeModelObserver* observer_; - - DISALLOW_COPY_AND_ASSIGN(TreeNodeModel); -}; - -} // namespace views - -#endif // CHROME_VIEWS_CONTROLS_TREE_TREE_NODE_MODEL_H_ diff --git a/chrome/views/controls/tree/tree_view.cc b/chrome/views/controls/tree/tree_view.cc deleted file mode 100644 index 1bf668c..0000000 --- a/chrome/views/controls/tree/tree_view.cc +++ /dev/null @@ -1,745 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/views/controls/tree/tree_view.h" - -#include <shellapi.h> - -#include "app/gfx/chrome_canvas.h" -#include "app/gfx/icon_util.h" -#include "app/l10n_util.h" -#include "app/l10n_util_win.h" -#include "app/resource_bundle.h" -#include "base/stl_util-inl.h" -#include "base/win_util.h" -#include "chrome/views/focus/focus_manager.h" -#include "chrome/views/widget/widget.h" -#include "grit/theme_resources.h" - -namespace views { - -TreeView::TreeView() - : tree_view_(NULL), - model_(NULL), - editable_(true), - next_id_(0), - controller_(NULL), - editing_node_(NULL), - root_shown_(true), - process_enter_(false), - show_context_menu_only_when_node_selected_(true), - select_on_right_mouse_down_(true), - wrapper_(this), - original_handler_(NULL), - drag_enabled_(false), - has_custom_icons_(false), - image_list_(NULL) { -} - -TreeView::~TreeView() { - if (model_) - model_->SetObserver(NULL); - // Both param_to_details_map_ and node_to_details_map_ have the same value, - // as such only need to delete from one. - STLDeleteContainerPairSecondPointers(id_to_details_map_.begin(), - id_to_details_map_.end()); - if (image_list_) - ImageList_Destroy(image_list_); -} - -void TreeView::SetModel(TreeModel* model) { - if (model == model_) - return; - if(model_ && tree_view_) - DeleteRootItems(); - if (model_) - model_->SetObserver(NULL); - model_ = model; - if (tree_view_ && model_) { - CreateRootItems(); - model_->SetObserver(this); - HIMAGELIST last_image_list = image_list_; - image_list_ = CreateImageList(); - TreeView_SetImageList(tree_view_, image_list_, TVSIL_NORMAL); - if (last_image_list) - ImageList_Destroy(last_image_list); - } -} - -// Sets whether the user can edit the nodes. The default is true. -void TreeView::SetEditable(bool editable) { - if (editable == editable_) - return; - editable_ = editable; - if (!tree_view_) - return; - LONG_PTR style = GetWindowLongPtr(tree_view_, GWL_STYLE); - style &= ~TVS_EDITLABELS; - SetWindowLongPtr(tree_view_, GWL_STYLE, style); -} - -void TreeView::StartEditing(TreeModelNode* node) { - DCHECK(node && tree_view_); - // Cancel the current edit. - CancelEdit(); - // Make sure all ancestors are expanded. - if (model_->GetParent(node)) - Expand(model_->GetParent(node)); - const NodeDetails* details = GetNodeDetails(node); - // Tree needs focus for editing to work. - SetFocus(tree_view_); - // Select the node, else if the user commits the edit the selection reverts. - SetSelectedNode(node); - TreeView_EditLabel(tree_view_, details->tree_item); -} - -void TreeView::CancelEdit() { - DCHECK(tree_view_); - TreeView_EndEditLabelNow(tree_view_, TRUE); -} - -void TreeView::CommitEdit() { - DCHECK(tree_view_); - TreeView_EndEditLabelNow(tree_view_, FALSE); -} - -TreeModelNode* TreeView::GetEditingNode() { - // I couldn't find a way to dynamically query for this, so it is cached. - return editing_node_; -} - -void TreeView::SetSelectedNode(TreeModelNode* node) { - DCHECK(tree_view_); - if (!node) { - TreeView_SelectItem(tree_view_, NULL); - return; - } - if (node != model_->GetRoot()) - Expand(model_->GetParent(node)); - if (!root_shown_ && node == model_->GetRoot()) { - // If the root isn't shown, we can't select it, clear out the selection - // instead. - TreeView_SelectItem(tree_view_, NULL); - } else { - // Select the node and make sure it is visible. - TreeView_SelectItem(tree_view_, GetNodeDetails(node)->tree_item); - } -} - -TreeModelNode* TreeView::GetSelectedNode() { - if (!tree_view_) - return NULL; - HTREEITEM selected_item = TreeView_GetSelection(tree_view_); - if (!selected_item) - return NULL; - NodeDetails* details = GetNodeDetailsByTreeItem(selected_item); - DCHECK(details); - return details->node; -} - -void TreeView::Expand(TreeModelNode* node) { - DCHECK(model_ && node); - if (!root_shown_ && model_->GetRoot() == node) { - // Can only expand the root if it is showing. - return; - } - TreeModelNode* parent = model_->GetParent(node); - if (parent) { - // Make sure all the parents are expanded. - Expand(parent); - } - // And expand this item. - TreeView_Expand(tree_view_, GetNodeDetails(node)->tree_item, TVE_EXPAND); -} - -void TreeView::ExpandAll() { - DCHECK(model_); - ExpandAll(model_->GetRoot()); -} - -void TreeView::ExpandAll(TreeModelNode* node) { - DCHECK(node); - // Expand the node. - if (node != model_->GetRoot() || root_shown_) - TreeView_Expand(tree_view_, GetNodeDetails(node)->tree_item, TVE_EXPAND); - // And recursively expand all the children. - for (int i = model_->GetChildCount(node) - 1; i >= 0; --i) { - TreeModelNode* child = model_->GetChild(node, i); - ExpandAll(child); - } -} - -bool TreeView::IsExpanded(TreeModelNode* node) { - TreeModelNode* parent = model_->GetParent(node); - if (!parent) - return true; - if (!IsExpanded(parent)) - return false; - NodeDetails* details = GetNodeDetails(node); - return (TreeView_GetItemState(tree_view_, details->tree_item, TVIS_EXPANDED) & - TVIS_EXPANDED) != 0; -} - -void TreeView::SetRootShown(bool root_shown) { - if (root_shown_ == root_shown) - return; - root_shown_ = root_shown; - if (!model_) - return; - // Repopulate the tree. - DeleteRootItems(); - CreateRootItems(); -} - -void TreeView::TreeNodesAdded(TreeModel* model, - TreeModelNode* parent, - 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. - return; - } - HTREEITEM parent_tree_item = NULL; - if (root_shown_ || parent != model_->GetRoot()) { - const NodeDetails* details = GetNodeDetails(parent); - if (!details->loaded_children) { - if (count == model_->GetChildCount(parent)) { - // Reset the treeviews child count. This triggers the treeview to call - // us back. - TV_ITEM tv_item = {0}; - tv_item.mask = TVIF_CHILDREN; - tv_item.cChildren = count; - tv_item.hItem = details->tree_item; - TreeView_SetItem(tree_view_, &tv_item); - } - - // Ignore the change, we haven't actually created entries in the tree - // for the children. - return; - } - parent_tree_item = details->tree_item; - } - - // The user has expanded this node, add the items to it. - for (int i = 0; i < count; ++i) { - if (i == 0 && start == 0) { - CreateItem(parent_tree_item, TVI_FIRST, model_->GetChild(parent, 0)); - } else { - TreeModelNode* previous_sibling = model_->GetChild(parent, i + start - 1); - CreateItem(parent_tree_item, - GetNodeDetails(previous_sibling)->tree_item, - model_->GetChild(parent, i + start)); - } - } -} - -void TreeView::TreeNodesRemoved(TreeModel* model, - TreeModelNode* parent, - int start, - int count) { - DCHECK(parent && start >= 0 && count > 0); - HTREEITEM parent_tree_item = GetTreeItemForNodeDuringMutation(parent); - if (!parent_tree_item) - return; - - // 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); - for (int i = 0; i < (start + count - 1); ++i) { - tree_item = TreeView_GetNextSibling(tree_view_, tree_item); - } - // NOTE: the direction doesn't matter here. I've made it backwards to - // reinforce we're deleting from the end forward. - for (int i = count - 1; i >= 0; --i) { - HTREEITEM previous = (start + i) > 0 ? - TreeView_GetPrevSibling(tree_view_, tree_item) : NULL; - RecursivelyDelete(GetNodeDetailsByTreeItem(tree_item)); - tree_item = previous; - } -} - -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. - return; - } - const NodeDetails* details = GetNodeDetails(node); - TV_ITEM tv_item = {0}; - tv_item.mask = TVIF_TEXT; - tv_item.hItem = details->tree_item; - tv_item.pszText = LPSTR_TEXTCALLBACK; - TreeView_SetItem(tree_view_, &tv_item); -} - -gfx::Point TreeView::GetKeyboardContextMenuLocation() { - int y = height() / 2; - if (GetSelectedNode()) { - RECT bounds; - RECT client_rect; - if (TreeView_GetItemRect(tree_view_, - GetNodeDetails(GetSelectedNode())->tree_item, - &bounds, TRUE) && - GetClientRect(tree_view_, &client_rect) && - bounds.bottom >= 0 && bounds.bottom < client_rect.bottom) { - y = bounds.bottom; - } - } - gfx::Point screen_loc(0, y); - if (UILayoutIsRightToLeft()) - screen_loc.set_x(width()); - ConvertPointToScreen(this, &screen_loc); - return screen_loc; -} - -HWND TreeView::CreateNativeControl(HWND parent_container) { - int style = WS_CHILD | TVS_HASBUTTONS | TVS_HASLINES | TVS_SHOWSELALWAYS; - if (!drag_enabled_) - style |= TVS_DISABLEDRAGDROP; - if (editable_) - style |= TVS_EDITLABELS; - tree_view_ = ::CreateWindowEx(WS_EX_CLIENTEDGE | GetAdditionalExStyle(), - WC_TREEVIEW, - L"", - style, - 0, 0, width(), height(), - parent_container, NULL, NULL, NULL); - SetWindowLongPtr(tree_view_, GWLP_USERDATA, - reinterpret_cast<LONG_PTR>(&wrapper_)); - original_handler_ = win_util::SetWindowProc(tree_view_, - &TreeWndProc); - l10n_util::AdjustUIFontForWindow(tree_view_); - - if (model_) { - CreateRootItems(); - model_->SetObserver(this); - image_list_ = CreateImageList(); - TreeView_SetImageList(tree_view_, image_list_, TVSIL_NORMAL); - } - - // Bug 964884: detach the IME attached to this window. - // We should attach IMEs only when we need to input CJK strings. - ::ImmAssociateContextEx(tree_view_, NULL, 0); - return tree_view_; -} - -LRESULT TreeView::OnNotify(int w_param, LPNMHDR l_param) { - switch (l_param->code) { - case TVN_GETDISPINFO: { - // Windows is requesting more information about an item. - // WARNING: At the time this is called the tree_item of the NodeDetails - // in the maps is NULL. - DCHECK(model_); - NMTVDISPINFO* info = reinterpret_cast<NMTVDISPINFO*>(l_param); - const NodeDetails* details = - GetNodeDetailsByID(static_cast<int>(info->item.lParam)); - if (info->item.mask & TVIF_CHILDREN) - info->item.cChildren = model_->GetChildCount(details->node); - if (info->item.mask & TVIF_TEXT) { - std::wstring text = details->node->GetTitle(); - DCHECK(info->item.cchTextMax); - - // Adjust the string direction if such adjustment is required. - std::wstring localized_text; - if (l10n_util::AdjustStringForLocaleDirection(text, &localized_text)) - text.swap(localized_text); - - wcsncpy_s(info->item.pszText, info->item.cchTextMax, text.c_str(), - _TRUNCATE); - } - // Instructs windows to cache the values for this node. - info->item.mask |= TVIF_DI_SETITEM; - // Return value ignored. - return 0; - } - - case TVN_ITEMEXPANDING: { - // Notification that a node is expanding. If we haven't populated the - // tree view with the contents of the model, we do it here. - DCHECK(model_); - NMTREEVIEW* info = reinterpret_cast<NMTREEVIEW*>(l_param); - NodeDetails* details = - GetNodeDetailsByID(static_cast<int>(info->itemNew.lParam)); - if (!details->loaded_children) { - details->loaded_children = true; - for (int i = 0; i < model_->GetChildCount(details->node); ++i) - CreateItem(details->tree_item, TVI_LAST, - model_->GetChild(details->node, i)); - } - // Return FALSE to allow the item to be expanded. - return FALSE; - } - - case TVN_SELCHANGED: - if (controller_) - controller_->OnTreeViewSelectionChanged(this); - break; - - case TVN_BEGINLABELEDIT: { - NMTVDISPINFO* info = reinterpret_cast<NMTVDISPINFO*>(l_param); - NodeDetails* details = - GetNodeDetailsByID(static_cast<int>(info->item.lParam)); - // Return FALSE to allow editing. - if (!controller_ || controller_->CanEdit(this, details->node)) { - editing_node_ = details->node; - return FALSE; - } - return TRUE; - } - - case TVN_ENDLABELEDIT: { - NMTVDISPINFO* info = reinterpret_cast<NMTVDISPINFO*>(l_param); - if (info->item.pszText) { - // User accepted edit. - NodeDetails* details = - GetNodeDetailsByID(static_cast<int>(info->item.lParam)); - model_->SetTitle(details->node, info->item.pszText); - editing_node_ = NULL; - // Return FALSE so that the tree item doesn't change its text (if the - // model changed the value, it should have sent out notification which - // will have updated the value). - return FALSE; - } - editing_node_ = NULL; - // Return value ignored. - return 0; - } - - case TVN_KEYDOWN: - if (controller_) { - NMTVKEYDOWN* key_down_message = - reinterpret_cast<NMTVKEYDOWN*>(l_param); - controller_->OnTreeViewKeyDown(key_down_message->wVKey); - } - break; - - default: - break; - } - return 0; -} - -bool TreeView::OnKeyDown(int virtual_key_code) { - if (virtual_key_code == VK_F2) { - if (!GetEditingNode()) { - TreeModelNode* selected_node = GetSelectedNode(); - if (selected_node) - StartEditing(selected_node); - } - return true; - } else if (virtual_key_code == VK_RETURN && !process_enter_) { - Widget* widget = GetWidget(); - DCHECK(widget); - FocusManager* fm = FocusManager::GetFocusManager(widget->GetNativeView()); - DCHECK(fm); - Accelerator accelerator(Accelerator(static_cast<int>(virtual_key_code), - win_util::IsShiftPressed(), - win_util::IsCtrlPressed(), - win_util::IsAltPressed())); - fm->ProcessAccelerator(accelerator); - return true; - } - return false; -} - -void TreeView::OnContextMenu(const CPoint& location) { - if (!GetContextMenuController()) - return; - - if (location.x == -1 && location.y == -1) { - // Let NativeControl's implementation handle keyboard gesture. - NativeControl::OnContextMenu(location); - return; - } - - if (show_context_menu_only_when_node_selected_) { - if (!GetSelectedNode()) - return; - - // Make sure the mouse is over the selected node. - TVHITTESTINFO hit_info; - gfx::Point local_loc(location); - ConvertPointToView(NULL, this, &local_loc); - hit_info.pt.x = local_loc.x(); - hit_info.pt.y = local_loc.y(); - HTREEITEM hit_item = TreeView_HitTest(tree_view_, &hit_info); - if (!hit_item || - GetNodeDetails(GetSelectedNode())->tree_item != hit_item || - (hit_info.flags & (TVHT_ONITEM | TVHT_ONITEMRIGHT | - TVHT_ONITEMINDENT)) == 0) { - return; - } - } - ShowContextMenu(location.x, location.y, true); -} - -TreeModelNode* TreeView::GetNodeForTreeItem(HTREEITEM tree_item) { - NodeDetails* details = GetNodeDetailsByTreeItem(tree_item); - return details ? details->node : NULL; -} - -HTREEITEM TreeView::GetTreeItemForNode(TreeModelNode* node) { - NodeDetails* details = GetNodeDetails(node); - return details ? details->tree_item : NULL; -} - -void TreeView::DeleteRootItems() { - HTREEITEM root = TreeView_GetRoot(tree_view_); - if (root) { - if (root_shown_) { - RecursivelyDelete(GetNodeDetailsByTreeItem(root)); - } else { - do { - RecursivelyDelete(GetNodeDetailsByTreeItem(root)); - } while ((root = TreeView_GetRoot(tree_view_))); - } - } -} - -void TreeView::CreateRootItems() { - DCHECK(model_); - TreeModelNode* root = model_->GetRoot(); - if (root_shown_) { - CreateItem(NULL, TVI_LAST, root); - } else { - for (int i = 0; i < model_->GetChildCount(root); ++i) - CreateItem(NULL, TVI_LAST, model_->GetChild(root, i)); - } -} - -void TreeView::CreateItem(HTREEITEM parent_item, - HTREEITEM after, - TreeModelNode* node) { - DCHECK(node); - TVINSERTSTRUCT insert_struct = {0}; - insert_struct.hParent = parent_item; - insert_struct.hInsertAfter = after; - insert_struct.itemex.mask = TVIF_PARAM | TVIF_CHILDREN | TVIF_TEXT | - TVIF_SELECTEDIMAGE | TVIF_IMAGE; - // Call us back for the text. - insert_struct.itemex.pszText = LPSTR_TEXTCALLBACK; - // And the number of children. - insert_struct.itemex.cChildren = I_CHILDRENCALLBACK; - // Set the index of the icons to use. These are relative to the imagelist - // created in CreateImageList. - int icon_index = model_->GetIconIndex(node); - if (icon_index == -1) { - insert_struct.itemex.iImage = 0; - insert_struct.itemex.iSelectedImage = 1; - } else { - // The first two images are the default ones. - insert_struct.itemex.iImage = icon_index + 2; - insert_struct.itemex.iSelectedImage = icon_index + 2; - } - int node_id = next_id_++; - insert_struct.itemex.lParam = node_id; - - // Invoking TreeView_InsertItem triggers OnNotify to be called. As such, - // we set the map entries before adding the item. - NodeDetails* node_details = new NodeDetails(node_id, node); - - node_to_details_map_[node] = node_details; - id_to_details_map_[node_id] = node_details; - - node_details->tree_item = TreeView_InsertItem(tree_view_, &insert_struct); -} - -void TreeView::RecursivelyDelete(NodeDetails* node) { - DCHECK(node); - HTREEITEM item = node->tree_item; - DCHECK(item); - - // Recurse through children. - for (HTREEITEM child = TreeView_GetChild(tree_view_, item); - child ; child = TreeView_GetNextSibling(tree_view_, child)) { - RecursivelyDelete(GetNodeDetailsByTreeItem(child)); - } - - TreeView_DeleteItem(tree_view_, item); - - // finally, it is safe to delete the data for this node. - id_to_details_map_.erase(node->id); - node_to_details_map_.erase(node->node); - delete node; -} - -TreeView::NodeDetails* TreeView::GetNodeDetailsByTreeItem(HTREEITEM tree_item) { - DCHECK(tree_view_ && tree_item); - TV_ITEM tv_item = {0}; - tv_item.hItem = tree_item; - tv_item.mask = TVIF_PARAM; - if (TreeView_GetItem(tree_view_, &tv_item)) - return GetNodeDetailsByID(static_cast<int>(tv_item.lParam)); - return NULL; -} - -HIMAGELIST TreeView::CreateImageList() { - std::vector<SkBitmap> model_images; - model_->GetIcons(&model_images); - - bool rtl = UILayoutIsRightToLeft(); - // Creates the default image list used for trees. - SkBitmap* closed_icon = - ResourceBundle::GetSharedInstance().GetBitmapNamed( - (rtl ? IDR_FOLDER_CLOSED_RTL : IDR_FOLDER_CLOSED)); - SkBitmap* opened_icon = - ResourceBundle::GetSharedInstance().GetBitmapNamed( - (rtl ? IDR_FOLDER_OPEN_RTL : IDR_FOLDER_OPEN)); - int width = closed_icon->width(); - int height = closed_icon->height(); - DCHECK(opened_icon->width() == width && opened_icon->height() == height); - HIMAGELIST image_list = - ImageList_Create(width, height, ILC_COLOR32, model_images.size() + 2, - model_images.size() + 2); - if (image_list) { - // NOTE: the order the images are added in effects the selected - // image index when adding items to the tree. If you change the - // order you'll undoubtedly need to update itemex.iSelectedImage - // when the item is added. - HICON h_closed_icon = IconUtil::CreateHICONFromSkBitmap(*closed_icon); - HICON h_opened_icon = IconUtil::CreateHICONFromSkBitmap(*opened_icon); - ImageList_AddIcon(image_list, h_closed_icon); - ImageList_AddIcon(image_list, h_opened_icon); - DestroyIcon(h_closed_icon); - DestroyIcon(h_opened_icon); - for (size_t i = 0; i < model_images.size(); ++i) { - HICON model_icon = IconUtil::CreateHICONFromSkBitmap(model_images[i]); - ImageList_AddIcon(image_list, model_icon); - DestroyIcon(model_icon); - } - } - 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, - LPARAM l_param) { - TreeViewWrapper* wrapper = reinterpret_cast<TreeViewWrapper*>( - GetWindowLongPtr(window, GWLP_USERDATA)); - DCHECK(wrapper); - TreeView* tree = wrapper->tree_view; - - // We handle the messages WM_ERASEBKGND and WM_PAINT such that we paint into - // a DIB first and then perform a BitBlt from the DIB into the underlying - // window's DC. This double buffering code prevents the tree view from - // flickering during resize. - switch (message) { - case WM_ERASEBKGND: - return 1; - - case WM_PAINT: { - ChromeCanvasPaint canvas(window); - if (canvas.isEmpty()) - return 0; - - HDC dc = canvas.beginPlatformPaint(); - if (l10n_util::GetTextDirection() == l10n_util::RIGHT_TO_LEFT) { - // ChromeCanvas ends up configuring the DC with a mode of GM_ADVANCED. - // For some reason a graphics mode of ADVANCED triggers all the text - // to be mirrored when RTL. Set the mode back to COMPATIBLE and - // explicitly set the layout. Additionally SetWorldTransform and - // COMPATIBLE don't play nicely together. We need to use - // SetViewportOrgEx when using a mode of COMPATIBLE. - // - // Reset the transform to the identify transform. Even though - // SetWorldTransform and COMPATIBLE don't play nicely, bits of the - // transform still carry over when we set the mode. - XFORM xform = {0}; - xform.eM11 = xform.eM22 = 1; - SetWorldTransform(dc, &xform); - - // Set the mode and layout. - SetGraphicsMode(dc, GM_COMPATIBLE); - SetLayout(dc, LAYOUT_RTL); - - // Transform the viewport such that the origin of the dc is that of - // the dirty region. This way when we invoke WM_PRINTCLIENT tree-view - // draws the dirty region at the origin of the DC so that when we - // copy the bits everything lines up nicely. Without this we end up - // copying the upper-left corner to the redraw region. - SetViewportOrgEx(dc, -canvas.paintStruct().rcPaint.left, - -canvas.paintStruct().rcPaint.top, NULL); - } - SendMessage(window, WM_PRINTCLIENT, reinterpret_cast<WPARAM>(dc), 0); - if (l10n_util::GetTextDirection() == l10n_util::RIGHT_TO_LEFT) { - // Reset the origin of the dc back to 0. This way when we copy the bits - // over we copy the right bits. - SetViewportOrgEx(dc, 0, 0, NULL); - } - canvas.endPlatformPaint(); - return 0; - } - - case WM_RBUTTONDOWN: - if (tree->select_on_right_mouse_down_) { - TVHITTESTINFO hit_info; - hit_info.pt.x = GET_X_LPARAM(l_param); - hit_info.pt.y = GET_Y_LPARAM(l_param); - HTREEITEM hit_item = TreeView_HitTest(window, &hit_info); - if (hit_item && (hit_info.flags & (TVHT_ONITEM | TVHT_ONITEMRIGHT | - TVHT_ONITEMINDENT)) != 0) - TreeView_SelectItem(tree->tree_view_, hit_item); - } - // Fall through and let the default handler process as well. - break; - } - WNDPROC handler = tree->original_handler_; - DCHECK(handler); - return CallWindowProc(handler, window, message, w_param, l_param); -} - -} // namespace views diff --git a/chrome/views/controls/tree/tree_view.h b/chrome/views/controls/tree/tree_view.h deleted file mode 100644 index ca6f784..0000000 --- a/chrome/views/controls/tree/tree_view.h +++ /dev/null @@ -1,305 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_VIEWS_CONTROLS_TREE_TREE_VIEW_H_ -#define CHROME_VIEWS_CONTROLS_TREE_TREE_VIEW_H_ - -#include <map> - -#include "base/basictypes.h" -#include "base/logging.h" -#include "chrome/views/controls/native_control.h" -#include "chrome/views/controls/tree/tree_model.h" - -namespace views { - -class TreeView; - -// TreeViewController --------------------------------------------------------- - -// Controller for the treeview. -class TreeViewController { - public: - // Notification that the selection of the tree view has changed. Use - // GetSelectedNode to find the current selection. - virtual void OnTreeViewSelectionChanged(TreeView* tree_view) = 0; - - // Returns true if the node can be edited. This is only used if the - // TreeView is editable. - virtual bool CanEdit(TreeView* tree_view, TreeModelNode* node) { - return true; - } - - // Invoked when a key is pressed on the tree view. - virtual void OnTreeViewKeyDown(unsigned short virtual_keycode) {} -}; - -// TreeView ------------------------------------------------------------------- - -// TreeView displays hierarchical data as returned from a TreeModel. The user -// can expand, collapse and edit the items. A Controller may be attached to -// receive notification of selection changes and restrict editing. -class TreeView : public NativeControl, TreeModelObserver { - public: - TreeView(); - virtual ~TreeView(); - - // Is dragging enabled? The default is false. - void set_drag_enabled(bool drag_enabled) { drag_enabled_ = drag_enabled; } - bool drag_enabled() const { return drag_enabled_; } - - // Sets the model. TreeView does not take ownership of the model. - void SetModel(TreeModel* model); - TreeModel* model() const { return model_; } - - // Sets whether the user can edit the nodes. The default is true. If true, - // the Controller is queried to determine if a particular node can be edited. - void SetEditable(bool editable); - - // Edits the specified node. This cancels the current edit and expands - // all parents of node. - void StartEditing(TreeModelNode* node); - - // Cancels the current edit. Does nothing if not editing. - void CancelEdit(); - - // Commits the current edit. Does nothing if not editing. - void CommitEdit(); - - // If the user is editing a node, it is returned. If the user is not - // editing a node, NULL is returned. - TreeModelNode* GetEditingNode(); - - // Selects the specified node. This expands all the parents of node. - void SetSelectedNode(TreeModelNode* node); - - // Returns the selected node, or NULL if nothing is selected. - TreeModelNode* GetSelectedNode(); - - // Make sure node and all its parents are expanded. - void Expand(TreeModelNode* node); - - // Convenience to expand ALL nodes in the tree. - void ExpandAll(); - - // Invoked from ExpandAll(). Expands the supplied node and recursively - // invokes itself with all children. - void ExpandAll(TreeModelNode* node); - - // Returns true if the specified node is expanded. - bool IsExpanded(TreeModelNode* node); - - // Sets whether the root is shown. If true, the root node of the tree is - // shown, if false only the children of the root are shown. The default is - // true. - void SetRootShown(bool root_visible); - - // TreeModelObserver methods. Don't call these directly, instead your model - // should notify the observer TreeView adds to it. - virtual void TreeNodesAdded(TreeModel* model, - TreeModelNode* parent, - int start, - int count); - virtual void TreeNodesRemoved(TreeModel* model, - 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 - // of the controller. - void SetController(TreeViewController* controller) { - controller_ = controller; - } - - // Sets whether enter is processed when not editing. If true, enter will - // expand/collapse the node. If false, enter is passed to the focus manager - // so that an enter accelerator can be enabled. The default is false. - // - // NOTE: Changing this has no effect after the hwnd has been created. - void SetProcessesEnter(bool process_enter) { - process_enter_ = process_enter; - } - bool GetProcessedEnter() { return process_enter_; } - - // Sets when the ContextMenuController is notified. If true, the - // ContextMenuController is only notified when a node is selected and the - // mouse is over a node. The default is true. - void SetShowContextMenuOnlyWhenNodeSelected(bool value) { - show_context_menu_only_when_node_selected_ = value; - } - bool GetShowContextMenuOnlyWhenNodeSelected() { - return show_context_menu_only_when_node_selected_; - } - - // If true, a right click selects the node under the mouse. The default - // is true. - void SetSelectOnRightMouseDown(bool value) { - select_on_right_mouse_down_ = value; - } - bool GetSelectOnRightMouseDown() { return select_on_right_mouse_down_; } - - protected: - // Overriden to return a location based on the selected node. - virtual gfx::Point GetKeyboardContextMenuLocation(); - - // Creates and configures the tree_view. - virtual HWND CreateNativeControl(HWND parent_container); - - // Invoked when the native control sends a WM_NOTIFY message to its parent. - // Handles a variety of potential TreeView messages. - virtual LRESULT OnNotify(int w_param, LPNMHDR l_param); - - // Yes, we want to be notified of key down for two reasons. To circumvent - // VK_ENTER from toggling the expaned state when processes_enter_ is false, - // and to have F2 start editting. - virtual bool NotifyOnKeyDown() const { return true; } - virtual bool OnKeyDown(int virtual_key_code); - - virtual void OnContextMenu(const CPoint& location); - - // Returns the TreeModelNode for |tree_item|. - TreeModelNode* GetNodeForTreeItem(HTREEITEM tree_item); - - // Returns the tree item for |node|. - HTREEITEM GetTreeItemForNode(TreeModelNode* node); - - private: - // See notes in TableView::TableViewWrapper for why this is needed. - struct TreeViewWrapper { - explicit TreeViewWrapper(TreeView* view) : tree_view(view) { } - TreeView* tree_view; - }; - - // Internally used to track the state of nodes. NodeDetails are lazily created - // as the user expands nodes. - struct NodeDetails { - NodeDetails(int id, TreeModelNode* node) - : id(id), node(node), tree_item(NULL), loaded_children(false) {} - - // Unique identifier for the node. This corresponds to the lParam of - // the tree item. - const int id; - - // The node from the model. - TreeModelNode* node; - - // From the native TreeView. - // - // This should be treated as const, but can't due to timing in creating the - // entry. - HTREEITEM tree_item; - - // Whether the children have been loaded. - bool loaded_children; - }; - - // Deletes the root items from the treeview. This is used when the model - // changes. - void DeleteRootItems(); - - // Creates the root items in the treeview from the model. This is used when - // the model changes. - void CreateRootItems(); - - // Creates and adds an item to the treeview. parent_item identifies the - // parent and is null for root items. after dictates where among the - // children of parent_item the item is to be created. node is the node from - // the model. - void CreateItem(HTREEITEM parent_item, HTREEITEM after, TreeModelNode* node); - - // Removes entries from the map for item. This method will also - // remove the items from the TreeView because the process of - // deleting an item will send an TVN_GETDISPINFO message, consulting - // our internal map data. - void RecursivelyDelete(NodeDetails* node); - - // Returns the NodeDetails by node from the model. - NodeDetails* GetNodeDetails(TreeModelNode* node) { - DCHECK(node && - node_to_details_map_.find(node) != node_to_details_map_.end()); - return node_to_details_map_[node]; - } - - // Returns the NodeDetails by identifier (lparam of the HTREEITEM). - NodeDetails* GetNodeDetailsByID(int id) { - DCHECK(id_to_details_map_.find(id) != id_to_details_map_.end()); - return id_to_details_map_[id]; - } - - // Returns the NodeDetails by HTREEITEM. - NodeDetails* GetNodeDetailsByTreeItem(HTREEITEM tree_item); - - // 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, - WPARAM w_param, - LPARAM l_param); - - // Handle to the tree window. - HWND tree_view_; - - // The model, may be null. - TreeModel* model_; - - // Maps from id to NodeDetails. - std::map<int,NodeDetails*> id_to_details_map_; - - // Maps from model entry to NodeDetails. - std::map<TreeModelNode*,NodeDetails*> node_to_details_map_; - - // Whether the user can edit the items. - bool editable_; - - // Next id to create. Any time an item is added this is incremented by one. - int next_id_; - - // The controller. - TreeViewController* controller_; - - // Node being edited. If null, not editing. - TreeModelNode* editing_node_; - - // Whether or not the root is shown in the tree. - bool root_shown_; - - // Whether enter should be processed by the tree when not editing. - bool process_enter_; - - // Whether we notify context menu controller only when mouse is over node - // and node is selected. - bool show_context_menu_only_when_node_selected_; - - // Whether the selection is changed on right mouse down. - bool select_on_right_mouse_down_; - - // A wrapper around 'this', used for subclassing the TreeView control. - TreeViewWrapper wrapper_; - - // Original handler installed on the TreeView. - WNDPROC original_handler_; - - bool drag_enabled_; - - // Did the model return a non-empty set of icons from GetIcons? - bool has_custom_icons_; - - HIMAGELIST image_list_; - - DISALLOW_COPY_AND_ASSIGN(TreeView); -}; - -} // namespace views - -#endif // CHROME_VIEWS_CONTROLS_TREE_TREE_VIEW_H_ |