blob: 04aa99726a187e8a7dd15db4cf772285a1405dcf [file] [log] [blame]
license.botbf09a502008-08-24 00:55:551// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit09911bf2008-07-26 23:55:294
[email protected]992c6252009-05-13 18:54:205#ifndef APP_TREE_NODE_MODEL_H_
6#define APP_TREE_NODE_MODEL_H_
initial.commit09911bf2008-07-26 23:55:297
[email protected]775cfd762008-12-09 17:12:128#include <algorithm>
initial.commit09911bf2008-07-26 23:55:299#include <vector>
10
[email protected]992c6252009-05-13 18:54:2011#include "app/tree_model.h"
initial.commit09911bf2008-07-26 23:55:2912#include "base/basictypes.h"
[email protected]1fec8402009-03-13 19:11:5913#include "base/scoped_ptr.h"
[email protected]807204142009-05-05 03:31:4414#include "base/scoped_vector.h"
15#include "base/stl_util-inl.h"
initial.commit09911bf2008-07-26 23:55:2916
17// TreeNodeModel and TreeNodes provide an implementation of TreeModel around
18// TreeNodes. TreeNodes form a directed acyclic graph.
19//
20// TreeNodes own their children, so that deleting a node deletes all
21// descendants.
22//
23// TreeNodes do NOT maintain a pointer back to the model. As such, if you
24// are using TreeNodes with a TreeNodeModel you will need to notify the observer
25// yourself any time you make any change directly to the TreeNodes. For example,
26// if you directly invoke SetTitle on a node it does not notify the
27// observer, you will need to do it yourself. This includes the following
28// methods: SetTitle, Remove and Add. TreeNodeModel provides cover
29// methods that mutate the TreeNodes and notify the observer. If you are using
30// TreeNodes with a TreeNodeModel use the cover methods to save yourself the
31// headache.
32//
33// The following example creates a TreeNode with two children and then
34// creates a TreeNodeModel from it:
35//
36// TreeNodeWithValue<int> root = new TreeNodeWithValue<int>(0, L"root");
37// root.add(new TreeNodeWithValue<int>(1, L"child 1"));
38// root.add(new TreeNodeWithValue<int>(1, L"child 2"));
39// TreeNodeModel<TreeNodeWithValue<int>>* model =
40// new TreeNodeModel<TreeNodeWithValue<int>>(root);
41//
42// Two variants of TreeNode are provided here:
43//
44// . TreeNode itself is intended for subclassing. It has one type parameter
45// that corresponds to the type of the node. When subclassing use your class
46// name as the type parameter, eg:
47// class MyTreeNode : public TreeNode<MyTreeNode> .
48// . TreeNodeWithValue is a trivial subclass of TreeNode that has one type
49// type parameter: a value type that is associated with the node.
50//
51// Which you use depends upon the situation. If you want to subclass and add
52// methods, then use TreeNode. If you don't need any extra methods and just
53// want to associate a value with each node, then use TreeNodeWithValue.
54//
55// Regardless of which TreeNode you use, if you are using the nodes with a
56// TreeView take care to notify the observer when mutating the nodes.
57
58template <class NodeType>
59class TreeNodeModel;
60
61// TreeNode -------------------------------------------------------------------
62
63template <class NodeType>
64class TreeNode : public TreeModelNode {
65 public:
66 TreeNode() : parent_(NULL) { }
67
68 explicit TreeNode(const std::wstring& title)
69 : title_(title), parent_(NULL) {}
70
71 virtual ~TreeNode() {
72 }
73
74 // Adds the specified child node.
75 virtual void Add(int index, NodeType* child) {
76 DCHECK(child && index >= 0 && index <= GetChildCount());
77 // If the node has a parent, remove it from its parent.
78 NodeType* node_parent = child->GetParent();
79 if (node_parent)
80 node_parent->Remove(node_parent->IndexOfChild(child));
81 child->parent_ = static_cast<NodeType*>(this);
82 children_->insert(children_->begin() + index, child);
83 }
84
85 // Removes the node by index. This does NOT delete the specified node, it is
86 // up to the caller to delete it when done.
87 virtual NodeType* Remove(int index) {
88 DCHECK(index >= 0 && index < GetChildCount());
89 NodeType* node = GetChild(index);
90 node->parent_ = NULL;
91 children_->erase(index + children_->begin());
92 return node;
93 }
94
[email protected]58b359d2009-02-27 22:05:0895 // Removes all the children from this node. This does NOT delete the nodes.
96 void RemoveAll() {
97 for (size_t i = 0; i < children_->size(); ++i)
98 children_[i]->parent_ = NULL;
99 children_->clear();
100 }
101
initial.commit09911bf2008-07-26 23:55:29102 // Returns the number of children.
[email protected]b3c33d462009-06-26 22:29:20103 int GetChildCount() const {
initial.commit09911bf2008-07-26 23:55:29104 return static_cast<int>(children_->size());
105 }
106
[email protected]9ff22ee42009-10-25 06:03:03107 // Returns the number of all nodes in teh subtree rooted at this node,
108 // including this node.
109 int GetTotalNodeCount() const {
110 int count = 1; // Start with one to include the node itself.
111 for (size_t i = 0; i < children_->size(); ++i) {
[email protected]dce51622009-11-06 04:58:48112 const TreeNode<NodeType>* child = children_[i];
[email protected]9ff22ee42009-10-25 06:03:03113 count += child->GetTotalNodeCount();
114 }
115 return count;
116 }
117
initial.commit09911bf2008-07-26 23:55:29118 // Returns a child by index.
119 NodeType* GetChild(int index) {
120 DCHECK(index >= 0 && index < GetChildCount());
121 return children_[index];
122 }
[email protected]b3c33d462009-06-26 22:29:20123 const NodeType* GetChild(int index) const {
124 DCHECK(index >= 0 && index < GetChildCount());
125 return children_[index];
126 }
initial.commit09911bf2008-07-26 23:55:29127
128 // Returns the parent.
129 NodeType* GetParent() {
130 return parent_;
131 }
[email protected]b3c33d462009-06-26 22:29:20132 const NodeType* GetParent() const {
133 return parent_;
134 }
initial.commit09911bf2008-07-26 23:55:29135
136 // Returns the index of the specified child, or -1 if node is a not a child.
[email protected]b3c33d462009-06-26 22:29:20137 int IndexOfChild(const NodeType* node) const {
initial.commit09911bf2008-07-26 23:55:29138 DCHECK(node);
[email protected]b3c33d462009-06-26 22:29:20139 typename std::vector<NodeType*>::const_iterator i =
[email protected]775cfd762008-12-09 17:12:12140 std::find(children_->begin(), children_->end(), node);
initial.commit09911bf2008-07-26 23:55:29141 if (i != children_->end())
142 return static_cast<int>(i - children_->begin());
143 return -1;
144 }
145
146 // Sets the title of the node.
147 void SetTitle(const std::wstring& string) {
148 title_ = string;
149 }
150
151 // Returns the title of the node.
[email protected]cf6c7fd32009-06-17 17:47:00152 virtual const std::wstring& GetTitle() const {
initial.commit09911bf2008-07-26 23:55:29153 return title_;
154 }
155
156 // Returns true if this is the root.
[email protected]b3c33d462009-06-26 22:29:20157 bool IsRoot() const { return (parent_ == NULL); }
initial.commit09911bf2008-07-26 23:55:29158
159 // Returns true if this == ancestor, or one of this nodes parents is
160 // ancestor.
[email protected]b3c33d462009-06-26 22:29:20161 bool HasAncestor(const NodeType* ancestor) const {
initial.commit09911bf2008-07-26 23:55:29162 if (ancestor == this)
163 return true;
164 if (!ancestor)
165 return false;
166 return parent_ ? parent_->HasAncestor(ancestor) : false;
167 }
168
[email protected]e2f86d92009-02-25 00:22:01169 protected:
170 std::vector<NodeType*>& children() { return children_.get(); }
171
initial.commit09911bf2008-07-26 23:55:29172 private:
173 // Title displayed in the tree.
174 std::wstring title_;
175
176 NodeType* parent_;
177
178 // Children.
179 ScopedVector<NodeType> children_;
180
[email protected]405ed122008-11-14 17:48:40181 DISALLOW_COPY_AND_ASSIGN(TreeNode);
initial.commit09911bf2008-07-26 23:55:29182};
183
184// TreeNodeWithValue ----------------------------------------------------------
185
186template <class ValueType>
[email protected]405ed122008-11-14 17:48:40187class TreeNodeWithValue : public TreeNode< TreeNodeWithValue<ValueType> > {
188 private:
189 typedef TreeNode< TreeNodeWithValue<ValueType> > ParentType;
190
initial.commit09911bf2008-07-26 23:55:29191 public:
192 TreeNodeWithValue() { }
193
[email protected]a5b58f52009-11-17 22:15:44194 explicit TreeNodeWithValue(const ValueType& value)
[email protected]405ed122008-11-14 17:48:40195 : ParentType(std::wstring()), value(value) { }
initial.commit09911bf2008-07-26 23:55:29196
197 TreeNodeWithValue(const std::wstring& title, const ValueType& value)
[email protected]405ed122008-11-14 17:48:40198 : ParentType(title), value(value) { }
initial.commit09911bf2008-07-26 23:55:29199
200 ValueType value;
201
202 private:
[email protected]405ed122008-11-14 17:48:40203 DISALLOW_COPY_AND_ASSIGN(TreeNodeWithValue);
initial.commit09911bf2008-07-26 23:55:29204};
205
206// TreeNodeModel --------------------------------------------------------------
207
208// TreeModel implementation intended to be used with TreeNodes.
209template <class NodeType>
210class TreeNodeModel : public TreeModel {
211 public:
212 // Creates a TreeNodeModel with the specified root node. The root is owned
213 // by the TreeNodeModel.
214 explicit TreeNodeModel(NodeType* root)
[email protected]1baa4f02009-01-26 09:29:08215 : root_(root),
216 observer_(NULL) {
initial.commit09911bf2008-07-26 23:55:29217 }
218
219 virtual ~TreeNodeModel() {}
220
221 virtual void SetObserver(TreeModelObserver* observer) {
222 observer_ = observer;
223 }
224
225 TreeModelObserver* GetObserver() {
226 return observer_;
227 }
228
229 // TreeModel methods, all forward to the nodes.
230 virtual NodeType* GetRoot() { return root_.get(); }
231
232 virtual int GetChildCount(TreeModelNode* parent) {
233 DCHECK(parent);
234 return AsNode(parent)->GetChildCount();
235 }
236
237 virtual NodeType* GetChild(TreeModelNode* parent, int index) {
238 DCHECK(parent);
239 return AsNode(parent)->GetChild(index);
240 }
241
[email protected]42062e72009-11-11 23:07:58242 virtual int IndexOfChild(TreeModelNode* parent, TreeModelNode* child) {
243 DCHECK(parent);
244 return AsNode(parent)->IndexOfChild(AsNode(child));
245 }
246
initial.commit09911bf2008-07-26 23:55:29247 virtual TreeModelNode* GetParent(TreeModelNode* node) {
248 DCHECK(node);
249 return AsNode(node)->GetParent();
250 }
251
252 NodeType* AsNode(TreeModelNode* model_node) {
[email protected]dce51622009-11-06 04:58:48253 return static_cast<NodeType*>(model_node);
initial.commit09911bf2008-07-26 23:55:29254 }
255
256 // Sets the title of the specified node.
257 virtual void SetTitle(TreeModelNode* node,
258 const std::wstring& title) {
259 DCHECK(node);
260 AsNode(node)->SetTitle(title);
261 NotifyObserverTreeNodeChanged(node);
262 }
263
264 void Add(NodeType* parent, int index, NodeType* child) {
265 DCHECK(parent && child);
266 parent->Add(index, child);
267 NotifyObserverTreeNodesAdded(parent, index, 1);
268 }
269
270 NodeType* Remove(NodeType* parent, int index) {
271 DCHECK(parent);
[email protected]776e7492008-10-23 16:47:41272 NodeType* child = parent->Remove(index);
initial.commit09911bf2008-07-26 23:55:29273 NotifyObserverTreeNodesRemoved(parent, index, 1);
[email protected]776e7492008-10-23 16:47:41274 return child;
initial.commit09911bf2008-07-26 23:55:29275 }
276
277 void NotifyObserverTreeNodesAdded(NodeType* parent, int start, int count) {
278 if (observer_)
279 observer_->TreeNodesAdded(this, parent, start, count);
280 }
281
282 void NotifyObserverTreeNodesRemoved(NodeType* parent, int start, int count) {
283 if (observer_)
284 observer_->TreeNodesRemoved(this, parent, start, count);
285 }
286
287 virtual void NotifyObserverTreeNodeChanged(TreeModelNode* node) {
288 if (observer_)
289 observer_->TreeNodeChanged(this, node);
290 }
291
292 private:
293 // The root.
294 scoped_ptr<NodeType> root_;
295
296 // The observer.
297 TreeModelObserver* observer_;
298
[email protected]405ed122008-11-14 17:48:40299 DISALLOW_COPY_AND_ASSIGN(TreeNodeModel);
initial.commit09911bf2008-07-26 23:55:29300};
301
[email protected]992c6252009-05-13 18:54:20302#endif // APP_TREE_NODE_MODEL_H_