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

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

Issue 2379863002: Fix object ownership in ui/base/models. (Closed)
Patch Set: fix Created 4 years, 2 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
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef UI_BASE_MODELS_TREE_NODE_MODEL_H_ 5 #ifndef UI_BASE_MODELS_TREE_NODE_MODEL_H_
6 #define UI_BASE_MODELS_TREE_NODE_MODEL_H_ 6 #define UI_BASE_MODELS_TREE_NODE_MODEL_H_
7 7
8 #include <stddef.h> 8 #include <stddef.h>
9 9
10 #include <algorithm> 10 #include <algorithm>
11 #include <memory> 11 #include <memory>
12 #include <vector> 12 #include <vector>
13 13
14 #include "base/logging.h" 14 #include "base/logging.h"
15 #include "base/macros.h" 15 #include "base/macros.h"
16 #include "base/observer_list.h" 16 #include "base/observer_list.h"
17 #include "base/stl_util.h"
18 #include "base/strings/string16.h" 17 #include "base/strings/string16.h"
19 #include "ui/base/models/tree_model.h" 18 #include "ui/base/models/tree_model.h"
20 19
21 namespace ui { 20 namespace ui {
22 21
23 // TreeNodeModel and TreeNodes provide an implementation of TreeModel around 22 // TreeNodeModel and TreeNodes provide an implementation of TreeModel around
24 // TreeNodes. 23 // TreeNodes.
25 // 24 //
26 // TreeNodes own their children, so that deleting a node deletes all 25 // TreeNodes own their children, so that deleting a node deletes all
27 // descendants. 26 // descendants.
28 // 27 //
29 // TreeNodes do NOT maintain a pointer back to the model. As such, if you 28 // TreeNodes do NOT maintain a pointer back to the model. As such, if you
30 // are using TreeNodes with a TreeNodeModel you will need to notify the observer 29 // are using TreeNodes with a TreeNodeModel you will need to notify the observer
31 // yourself any time you make any change directly to the TreeNodes. For example, 30 // yourself any time you make any change directly to the TreeNodes. For example,
32 // if you directly invoke set_title on a node it does not notify the observer, 31 // if you directly invoke set_title on a node it does not notify the observer,
33 // you will need to do it yourself. This includes the following methods: Add, 32 // you will need to do it yourself. This includes the following methods: Add,
34 // Remove and set_title. TreeNodeModel provides cover methods that mutate the 33 // Remove and set_title. TreeNodeModel provides cover methods that mutate the
35 // TreeNodes and notify the observer. If you are using TreeNodes with a 34 // TreeNodes and notify the observer. If you are using TreeNodes with a
36 // TreeNodeModel use the cover methods to save yourself the headache. 35 // TreeNodeModel use the cover methods to save yourself the headache.
37 // 36 //
38 // The following example creates a TreeNode with two children and then 37 // The following example creates a TreeNode with two children and then
39 // creates a TreeNodeModel from it: 38 // creates a TreeNodeModel from it:
40 // 39 //
41 // TreeNodeWithValue<int>* root = new TreeNodeWithValue<int>(); 40 // std::unique_ptr<TreeNodeWithValue<int>> root =
42 // root->Add(new TreeNodeWithValue<int>(ASCIIToUTF16("child 1"), 0)); 41 // base::MakeUnique<TreeNodeWithValue<int>>();
43 // root->Add(new TreeNodeWithValue<int>(ASCIIToUTF16("child 2"), 1)); 42 // root->Add(
44 // TreeNodeModel<TreeNodeWithValue<int> > model(root); 43 // base::MakeUnique<TreeNodeWithValue<int>>(ASCIIToUTF16("child 1"), 0));
44 // root->Add(
45 // base::MakeUnique<TreeNodeWithValue<int>>(ASCIIToUTF16("child 2"), 1));
46 // TreeNodeModel<TreeNodeWithValue<int>> model(std::move(root));
45 // 47 //
46 // Two variants of TreeNode are provided here: 48 // Two variants of TreeNode are provided here:
47 // 49 //
48 // . TreeNode itself is intended for subclassing. It has one type parameter 50 // . TreeNode itself is intended for subclassing. It has one type parameter
49 // that corresponds to the type of the node. When subclassing use your class 51 // that corresponds to the type of the node. When subclassing use your class
50 // name as the type parameter, eg: 52 // name as the type parameter, e.g.:
51 // class MyTreeNode : public TreeNode<MyTreeNode> . 53 // class MyTreeNode : public TreeNode<MyTreeNode> .
52 // . TreeNodeWithValue is a trivial subclass of TreeNode that has one type 54 // . TreeNodeWithValue is a trivial subclass of TreeNode that has one type
53 // type parameter: a value type that is associated with the node. 55 // type parameter: a value type that is associated with the node.
54 // 56 //
55 // Which you use depends upon the situation. If you want to subclass and add 57 // Which you use depends upon the situation. If you want to subclass and add
56 // methods, then use TreeNode. If you don't need any extra methods and just 58 // methods, then use TreeNode. If you don't need any extra methods and just
57 // want to associate a value with each node, then use TreeNodeWithValue. 59 // want to associate a value with each node, then use TreeNodeWithValue.
58 // 60 //
59 // Regardless of which TreeNode you use, if you are using the nodes with a 61 // Regardless of which TreeNode you use, if you are using the nodes with a
60 // TreeView take care to notify the observer when mutating the nodes. 62 // TreeView take care to notify the observer when mutating the nodes.
61 63
62 // TreeNode ------------------------------------------------------------------- 64 // TreeNode -------------------------------------------------------------------
63 65
64 template <class NodeType> 66 template <class NodeType>
65 class TreeNode : public TreeModelNode { 67 class TreeNode : public TreeModelNode {
66 public: 68 public:
67 TreeNode() : parent_(NULL) {} 69 TreeNode() : parent_(nullptr) {}
68 70
69 explicit TreeNode(const base::string16& title) 71 explicit TreeNode(const base::string16& title)
70 : title_(title), parent_(NULL) {} 72 : title_(title), parent_(nullptr) {}
71 73
72 ~TreeNode() override { base::STLDeleteElements(&children_); } 74 ~TreeNode() override {}
73 75
74 // Adds |node| as a child of this node, at |index|. 76 // Adds |node| as a child of this node, at |index|. Returns a raw pointer to
75 virtual void Add(NodeType* node, int index) { 77 // the node.
78 virtual NodeType* Add(std::unique_ptr<NodeType> node, int index) {
76 DCHECK(node); 79 DCHECK(node);
77 DCHECK_GE(index, 0); 80 DCHECK_GE(index, 0);
78 DCHECK_LE(index, child_count()); 81 DCHECK_LE(index, child_count());
79 // If |node| has a parent, remove it from its parent. 82 DCHECK(!node->parent_);
80 NodeType* parent = node->parent_;
81 if (parent)
82 parent->Remove(node);
83 node->parent_ = static_cast<NodeType*>(this); 83 node->parent_ = static_cast<NodeType*>(this);
84 children_.insert(children_.begin() + index, node); 84 NodeType* node_ptr = node.get();
85 children_.insert(children_.begin() + index, std::move(node));
86 return node_ptr;
85 } 87 }
86 88
87 // Removes |node| from this node and returns it. It's up to the caller to 89 // Removes |node| from this node and returns it.
88 // delete it. 90 virtual std::unique_ptr<NodeType> Remove(NodeType* node) {
89 virtual NodeType* Remove(NodeType* node) { 91 auto i = std::find_if(children_.begin(), children_.end(),
90 typename std::vector<NodeType*>::iterator i = 92 [node](const std::unique_ptr<NodeType>& ptr) {
91 std::find(children_.begin(), children_.end(), node); 93 return ptr.get() == node;
94 });
92 DCHECK(i != children_.end()); 95 DCHECK(i != children_.end());
93 node->parent_ = NULL; 96 node->parent_ = nullptr;
97 std::unique_ptr<NodeType> ptr = std::move(*i);
94 children_.erase(i); 98 children_.erase(i);
95 return node; 99 return ptr;
96 } 100 }
97 101
98 // Removes all the children from this node. This does NOT delete the nodes. 102 // Removes all the children from this node.
99 void RemoveAll() { 103 void DeleteAll() { children_.clear(); }
100 for (size_t i = 0; i < children_.size(); ++i)
101 children_[i]->parent_ = NULL;
102 children_.clear();
103 }
104 104
105 // Removes all existing children without deleting the nodes and adds all nodes 105 // Returns the parent node, or nullptr if this is the root node.
106 // contained in |children| into this node as children.
107 void SetChildren(const std::vector<NodeType*>& children) {
108 RemoveAll();
109 for (size_t i = 0; i < children.size(); ++i)
110 Add(children[i], static_cast<int>(i));
111 }
112
113 // Returns the parent node, or NULL if this is the root node.
114 const NodeType* parent() const { return parent_; } 106 const NodeType* parent() const { return parent_; }
115 NodeType* parent() { return parent_; } 107 NodeType* parent() { return parent_; }
116 108
117 // Returns true if this is the root node. 109 // Returns true if this is the root node.
118 bool is_root() const { return parent_ == NULL; } 110 bool is_root() const { return parent_ == nullptr; }
119 111
120 // Returns the number of children. 112 // Returns the number of children.
121 int child_count() const { return static_cast<int>(children_.size()); } 113 int child_count() const { return static_cast<int>(children_.size()); }
122 114
123 // Returns true if this node has no children. 115 // Returns true if this node has no children.
124 bool empty() const { return children_.empty(); } 116 bool empty() const { return children_.empty(); }
125 117
126 // Returns the number of all nodes in the subtree rooted at this node, 118 // Returns the number of all nodes in the subtree rooted at this node,
127 // including this node. 119 // including this node.
128 int GetTotalNodeCount() const { 120 int GetTotalNodeCount() const {
129 int count = 1; // Start with one to include the node itself. 121 int count = 1; // Start with one to include the node itself.
130 for (size_t i = 0; i < children_.size(); ++i) 122 for (const auto& child : children_)
131 count += children_[i]->GetTotalNodeCount(); 123 count += child->GetTotalNodeCount();
132 return count; 124 return count;
133 } 125 }
134 126
135 // Returns the node at |index|. 127 // Returns the node at |index|.
136 const NodeType* GetChild(int index) const { 128 const NodeType* GetChild(int index) const {
137 DCHECK_GE(index, 0); 129 DCHECK_GE(index, 0);
138 DCHECK_LT(index, child_count()); 130 DCHECK_LT(index, child_count());
139 return children_[index]; 131 return children_[index].get();
140 } 132 }
141 NodeType* GetChild(int index) { 133 NodeType* GetChild(int index) {
142 return const_cast<NodeType*>( 134 return const_cast<NodeType*>(
143 static_cast<const NodeType&>(*this).GetChild(index)); 135 static_cast<const NodeType&>(*this).GetChild(index));
144 } 136 }
145 137
146 // Returns the index of |node|, or -1 if |node| is not a child of this. 138 // Returns the index of |node|, or -1 if |node| is not a child of this.
147 int GetIndexOf(const NodeType* node) const { 139 int GetIndexOf(const NodeType* node) const {
148 DCHECK(node); 140 DCHECK(node);
149 typename std::vector<NodeType*>::const_iterator i = 141 auto i = std::find_if(children_.begin(), children_.end(),
150 std::find(children_.begin(), children_.end(), node); 142 [node](const std::unique_ptr<NodeType>& ptr) {
143 return ptr.get() == node;
144 });
151 return i != children_.end() ? static_cast<int>(i - children_.begin()) : -1; 145 return i != children_.end() ? static_cast<int>(i - children_.begin()) : -1;
152 } 146 }
153 147
154 // Sets the title of the node. 148 // Sets the title of the node.
155 virtual void SetTitle(const base::string16& title) { title_ = title; } 149 virtual void SetTitle(const base::string16& title) { title_ = title; }
156 150
157 // TreeModelNode: 151 // TreeModelNode:
158 const base::string16& GetTitle() const override { return title_; } 152 const base::string16& GetTitle() const override { return title_; }
159 153
160 // Returns true if this == ancestor, or one of this nodes parents is 154 // Returns true if this == ancestor, or one of this nodes parents is
161 // ancestor. 155 // ancestor.
162 bool HasAncestor(const NodeType* ancestor) const { 156 bool HasAncestor(const NodeType* ancestor) const {
163 if (ancestor == this) 157 if (ancestor == this)
164 return true; 158 return true;
165 if (!ancestor) 159 if (!ancestor)
166 return false; 160 return false;
167 return parent_ ? parent_->HasAncestor(ancestor) : false; 161 return parent_ ? parent_->HasAncestor(ancestor) : false;
168 } 162 }
169 163
170 protected: 164 protected:
171 std::vector<NodeType*>& children() { return children_; } 165 std::vector<std::unique_ptr<NodeType>>& children() { return children_; }
172 166
173 private: 167 private:
174 // Title displayed in the tree. 168 // Title displayed in the tree.
175 base::string16 title_; 169 base::string16 title_;
176 170
177 // This node's parent. 171 // This node's parent.
178 NodeType* parent_; 172 NodeType* parent_;
179 173
180 // This node's children. 174 // This node's children.
181 std::vector<NodeType*> children_; 175 typename std::vector<std::unique_ptr<NodeType>> children_;
182 176
183 DISALLOW_COPY_AND_ASSIGN(TreeNode); 177 DISALLOW_COPY_AND_ASSIGN(TreeNode);
184 }; 178 };
185 179
186 // TreeNodeWithValue ---------------------------------------------------------- 180 // TreeNodeWithValue ----------------------------------------------------------
187 181
188 template <class ValueType> 182 template <class ValueType>
189 class TreeNodeWithValue : public TreeNode< TreeNodeWithValue<ValueType> > { 183 class TreeNodeWithValue : public TreeNode<TreeNodeWithValue<ValueType>> {
190 public: 184 public:
191 TreeNodeWithValue() {} 185 TreeNodeWithValue() {}
192 186
193 explicit TreeNodeWithValue(const ValueType& value) 187 explicit TreeNodeWithValue(const ValueType& value)
194 : ParentType(base::string16()), value(value) {} 188 : ParentType(base::string16()), value(value) {}
195 189
196 TreeNodeWithValue(const base::string16& title, const ValueType& value) 190 TreeNodeWithValue(const base::string16& title, const ValueType& value)
197 : ParentType(title), value(value) {} 191 : ParentType(title), value(value) {}
198 192
199 ValueType value; 193 ValueType value;
200 194
201 private: 195 private:
202 typedef TreeNode< TreeNodeWithValue<ValueType> > ParentType; 196 using ParentType = TreeNode<TreeNodeWithValue<ValueType>>;
203 197
204 DISALLOW_COPY_AND_ASSIGN(TreeNodeWithValue); 198 DISALLOW_COPY_AND_ASSIGN(TreeNodeWithValue);
205 }; 199 };
206 200
207 // TreeNodeModel -------------------------------------------------------------- 201 // TreeNodeModel --------------------------------------------------------------
208 202
209 // TreeModel implementation intended to be used with TreeNodes. 203 // TreeModel implementation intended to be used with TreeNodes.
210 template <class NodeType> 204 template <class NodeType>
211 class TreeNodeModel : public TreeModel { 205 class TreeNodeModel : public TreeModel {
212 public: 206 public:
213 // Creates a TreeNodeModel with the specified root node. The root is owned 207 // Creates a TreeNodeModel with the specified root node.
214 // by the TreeNodeModel. 208 explicit TreeNodeModel(std::unique_ptr<NodeType> root)
215 explicit TreeNodeModel(NodeType* root) : root_(root) {} 209 : root_(std::move(root)) {}
216 virtual ~TreeNodeModel() override {} 210 virtual ~TreeNodeModel() override {}
217 211
218 NodeType* AsNode(TreeModelNode* model_node) { 212 NodeType* AsNode(TreeModelNode* model_node) {
219 return static_cast<NodeType*>(model_node); 213 return static_cast<NodeType*>(model_node);
220 } 214 }
221 215
222 void Add(NodeType* parent, NodeType* node, int index) { 216 NodeType* Add(NodeType* parent, std::unique_ptr<NodeType> node, int index) {
223 DCHECK(parent && node); 217 DCHECK(parent && node);
224 parent->Add(node, index); 218 NodeType* node_ptr = parent->Add(std::move(node), index);
225 NotifyObserverTreeNodesAdded(parent, index, 1); 219 NotifyObserverTreeNodesAdded(parent, index, 1);
220 return node_ptr;
226 } 221 }
227 222
228 NodeType* Remove(NodeType* parent, NodeType* node) { 223 std::unique_ptr<NodeType> Remove(NodeType* parent, NodeType* node) {
229 DCHECK(parent); 224 DCHECK(parent);
230 int index = parent->GetIndexOf(node); 225 int index = parent->GetIndexOf(node);
231 NodeType* delete_node = parent->Remove(node); 226 std::unique_ptr<NodeType> owned_node = parent->Remove(node);
232 NotifyObserverTreeNodesRemoved(parent, index, 1); 227 NotifyObserverTreeNodesRemoved(parent, index, 1);
233 return delete_node; 228 return owned_node;
234 } 229 }
235 230
236 void NotifyObserverTreeNodesAdded(NodeType* parent, int start, int count) { 231 void NotifyObserverTreeNodesAdded(NodeType* parent, int start, int count) {
237 FOR_EACH_OBSERVER(TreeModelObserver, 232 FOR_EACH_OBSERVER(TreeModelObserver,
238 observer_list_, 233 observer_list_,
239 TreeNodesAdded(this, parent, start, count)); 234 TreeNodesAdded(this, parent, start, count));
240 } 235 }
241 236
242 void NotifyObserverTreeNodesRemoved(NodeType* parent, int start, int count) { 237 void NotifyObserverTreeNodesRemoved(NodeType* parent, int start, int count) {
243 FOR_EACH_OBSERVER(TreeModelObserver, 238 FOR_EACH_OBSERVER(TreeModelObserver,
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
297 292
298 // The root. 293 // The root.
299 std::unique_ptr<NodeType> root_; 294 std::unique_ptr<NodeType> root_;
300 295
301 DISALLOW_COPY_AND_ASSIGN(TreeNodeModel); 296 DISALLOW_COPY_AND_ASSIGN(TreeNodeModel);
302 }; 297 };
303 298
304 } // namespace ui 299 } // namespace ui
305 300
306 #endif // UI_BASE_MODELS_TREE_NODE_MODEL_H_ 301 #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