Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(908)

Side by Side Diff: ui/base/models/tree_node_model.h

Issue 851853002: It is time. (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Trying to reup because the last upload failed. Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2012 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.
4
5 #ifndef UI_BASE_MODELS_TREE_NODE_MODEL_H_
6 #define UI_BASE_MODELS_TREE_NODE_MODEL_H_
7
8 #include <algorithm>
9 #include <vector>
10
11 #include "base/basictypes.h"
12 #include "base/compiler_specific.h"
13 #include "base/logging.h"
14 #include "base/memory/scoped_ptr.h"
15 #include "base/memory/scoped_vector.h"
16 #include "base/observer_list.h"
17 #include "base/strings/string16.h"
18 #include "ui/base/models/tree_model.h"
19
20 namespace ui {
21
22 // TreeNodeModel and TreeNodes provide an implementation of TreeModel around
23 // TreeNodes.
24 //
25 // TreeNodes own their children, so that deleting a node deletes all
26 // descendants.
27 //
28 // TreeNodes do NOT maintain a pointer back to the model. As such, if you
29 // are using TreeNodes with a TreeNodeModel you will need to notify the observer
30 // yourself any time you make any change directly to the TreeNodes. For example,
31 // if you directly invoke set_title on a node it does not notify the observer,
32 // you will need to do it yourself. This includes the following methods: Add,
33 // Remove and set_title. TreeNodeModel provides cover methods that mutate the
34 // TreeNodes and notify the observer. If you are using TreeNodes with a
35 // TreeNodeModel use the cover methods to save yourself the headache.
36 //
37 // The following example creates a TreeNode with two children and then
38 // creates a TreeNodeModel from it:
39 //
40 // TreeNodeWithValue<int>* root = new TreeNodeWithValue<int>();
41 // root->Add(new TreeNodeWithValue<int>(ASCIIToUTF16("child 1"), 0));
42 // root->Add(new TreeNodeWithValue<int>(ASCIIToUTF16("child 2"), 1));
43 // TreeNodeModel<TreeNodeWithValue<int> > model(root);
44 //
45 // Two variants of TreeNode are provided here:
46 //
47 // . TreeNode itself is intended for subclassing. It has one type parameter
48 // that corresponds to the type of the node. When subclassing use your class
49 // name as the type parameter, eg:
50 // class MyTreeNode : public TreeNode<MyTreeNode> .
51 // . TreeNodeWithValue is a trivial subclass of TreeNode that has one type
52 // type parameter: a value type that is associated with the node.
53 //
54 // Which you use depends upon the situation. If you want to subclass and add
55 // methods, then use TreeNode. If you don't need any extra methods and just
56 // want to associate a value with each node, then use TreeNodeWithValue.
57 //
58 // Regardless of which TreeNode you use, if you are using the nodes with a
59 // TreeView take care to notify the observer when mutating the nodes.
60
61 // TreeNode -------------------------------------------------------------------
62
63 template <class NodeType>
64 class TreeNode : public TreeModelNode {
65 public:
66 TreeNode() : parent_(NULL) {}
67
68 explicit TreeNode(const base::string16& title)
69 : title_(title), parent_(NULL) {}
70
71 virtual ~TreeNode() {}
72
73 // Adds |node| as a child of this node, at |index|.
74 virtual void Add(NodeType* node, int index) {
75 DCHECK(node);
76 DCHECK_GE(index, 0);
77 DCHECK_LE(index, child_count());
78 // If |node| has a parent, remove it from its parent.
79 NodeType* parent = node->parent_;
80 if (parent)
81 parent->Remove(node);
82 node->parent_ = static_cast<NodeType*>(this);
83 children_.insert(children_.begin() + index, node);
84 }
85
86 // Removes |node| from this node and returns it. It's up to the caller to
87 // delete it.
88 virtual NodeType* Remove(NodeType* node) {
89 typename std::vector<NodeType*>::iterator i =
90 std::find(children_.begin(), children_.end(), node);
91 DCHECK(i != children_.end());
92 node->parent_ = NULL;
93 children_.weak_erase(i);
94 return node;
95 }
96
97 // Removes all the children from this node. This does NOT delete the nodes.
98 void RemoveAll() {
99 for (size_t i = 0; i < children_.size(); ++i)
100 children_[i]->parent_ = NULL;
101 children_.weak_clear();
102 }
103
104 // Removes all existing children without deleting the nodes and adds all nodes
105 // contained in |children| into this node as children.
106 void SetChildren(const std::vector<NodeType*>& children) {
107 RemoveAll();
108 for (size_t i = 0; i < children.size(); ++i)
109 Add(children[i], static_cast<int>(i));
110 }
111
112 // Returns the parent node, or NULL if this is the root node.
113 const NodeType* parent() const { return parent_; }
114 NodeType* parent() { return parent_; }
115
116 // Returns true if this is the root node.
117 bool is_root() const { return parent_ == NULL; }
118
119 // Returns the number of children.
120 int child_count() const { return static_cast<int>(children_.size()); }
121
122 // Returns true if this node has no children.
123 bool empty() const { return children_.empty(); }
124
125 // Returns the number of all nodes in the subtree rooted at this node,
126 // including this node.
127 int GetTotalNodeCount() const {
128 int count = 1; // Start with one to include the node itself.
129 for (size_t i = 0; i < children_.size(); ++i)
130 count += children_[i]->GetTotalNodeCount();
131 return count;
132 }
133
134 // Returns the node at |index|.
135 const NodeType* GetChild(int index) const {
136 DCHECK_GE(index, 0);
137 DCHECK_LT(index, child_count());
138 return children_[index];
139 }
140 NodeType* GetChild(int index) {
141 return const_cast<NodeType*>(
142 static_cast<const NodeType&>(*this).GetChild(index));
143 }
144
145 // Returns the index of |node|, or -1 if |node| is not a child of this.
146 int GetIndexOf(const NodeType* node) const {
147 DCHECK(node);
148 typename std::vector<NodeType*>::const_iterator i =
149 std::find(children_.begin(), children_.end(), node);
150 return i != children_.end() ? static_cast<int>(i - children_.begin()) : -1;
151 }
152
153 // Sets the title of the node.
154 virtual void SetTitle(const base::string16& title) { title_ = title; }
155
156 // TreeModelNode:
157 virtual const base::string16& GetTitle() const override { return title_; }
158
159 // Returns true if this == ancestor, or one of this nodes parents is
160 // ancestor.
161 bool HasAncestor(const NodeType* ancestor) const {
162 if (ancestor == this)
163 return true;
164 if (!ancestor)
165 return false;
166 return parent_ ? parent_->HasAncestor(ancestor) : false;
167 }
168
169 protected:
170 std::vector<NodeType*>& children() { return children_.get(); }
171
172 private:
173 // Title displayed in the tree.
174 base::string16 title_;
175
176 // This node's parent.
177 NodeType* parent_;
178
179 // This node's children.
180 ScopedVector<NodeType> children_;
181
182 DISALLOW_COPY_AND_ASSIGN(TreeNode);
183 };
184
185 // TreeNodeWithValue ----------------------------------------------------------
186
187 template <class ValueType>
188 class TreeNodeWithValue : public TreeNode< TreeNodeWithValue<ValueType> > {
189 public:
190 TreeNodeWithValue() {}
191
192 explicit TreeNodeWithValue(const ValueType& value)
193 : ParentType(base::string16()), value(value) {}
194
195 TreeNodeWithValue(const base::string16& title, const ValueType& value)
196 : ParentType(title), value(value) {}
197
198 ValueType value;
199
200 private:
201 typedef TreeNode< TreeNodeWithValue<ValueType> > ParentType;
202
203 DISALLOW_COPY_AND_ASSIGN(TreeNodeWithValue);
204 };
205
206 // TreeNodeModel --------------------------------------------------------------
207
208 // TreeModel implementation intended to be used with TreeNodes.
209 template <class NodeType>
210 class 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) : root_(root) {}
215 virtual ~TreeNodeModel() {}
216
217 NodeType* AsNode(TreeModelNode* model_node) {
218 return static_cast<NodeType*>(model_node);
219 }
220
221 void Add(NodeType* parent, NodeType* node, int index) {
222 DCHECK(parent && node);
223 parent->Add(node, index);
224 NotifyObserverTreeNodesAdded(parent, index, 1);
225 }
226
227 NodeType* Remove(NodeType* parent, NodeType* node) {
228 DCHECK(parent);
229 int index = parent->GetIndexOf(node);
230 NodeType* delete_node = parent->Remove(node);
231 NotifyObserverTreeNodesRemoved(parent, index, 1);
232 return delete_node;
233 }
234
235 void NotifyObserverTreeNodesAdded(NodeType* parent, int start, int count) {
236 FOR_EACH_OBSERVER(TreeModelObserver,
237 observer_list_,
238 TreeNodesAdded(this, parent, start, count));
239 }
240
241 void NotifyObserverTreeNodesRemoved(NodeType* parent, int start, int count) {
242 FOR_EACH_OBSERVER(TreeModelObserver,
243 observer_list_,
244 TreeNodesRemoved(this, parent, start, count));
245 }
246
247 void NotifyObserverTreeNodeChanged(TreeModelNode* node) {
248 FOR_EACH_OBSERVER(TreeModelObserver,
249 observer_list_,
250 TreeNodeChanged(this, node));
251 }
252
253 // TreeModel:
254 virtual NodeType* GetRoot() override {
255 return root_.get();
256 }
257
258 virtual int GetChildCount(TreeModelNode* parent) override {
259 DCHECK(parent);
260 return AsNode(parent)->child_count();
261 }
262
263 virtual NodeType* GetChild(TreeModelNode* parent, int index) override {
264 DCHECK(parent);
265 return AsNode(parent)->GetChild(index);
266 }
267
268 virtual int GetIndexOf(TreeModelNode* parent, TreeModelNode* child) override {
269 DCHECK(parent);
270 return AsNode(parent)->GetIndexOf(AsNode(child));
271 }
272
273 virtual TreeModelNode* GetParent(TreeModelNode* node) override {
274 DCHECK(node);
275 return AsNode(node)->parent();
276 }
277
278 virtual void AddObserver(TreeModelObserver* observer) override {
279 observer_list_.AddObserver(observer);
280 }
281
282 virtual void RemoveObserver(TreeModelObserver* observer) override {
283 observer_list_.RemoveObserver(observer);
284 }
285
286 virtual void SetTitle(TreeModelNode* node,
287 const base::string16& title) override {
288 DCHECK(node);
289 AsNode(node)->SetTitle(title);
290 NotifyObserverTreeNodeChanged(node);
291 }
292
293 private:
294 // The observers.
295 ObserverList<TreeModelObserver> observer_list_;
296
297 // The root.
298 scoped_ptr<NodeType> root_;
299
300 DISALLOW_COPY_AND_ASSIGN(TreeNodeModel);
301 };
302
303 } // namespace ui
304
305 #endif // UI_BASE_MODELS_TREE_NODE_MODEL_H_
OLDNEW
« no previous file with comments | « ui/base/models/tree_node_iterator_unittest.cc ('k') | ui/base/models/tree_node_model_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698