Chromium Code Reviews| OLD | NEW |
|---|---|
| 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(), |
|
sky
2016/09/29 22:06:48
Same code exists on 141-144. Move to a common func
Avi (use Gerrit)
2016/09/29 22:59:58
FYI the two callers are of different const-ness. E
Avi (use Gerrit)
2016/09/30 00:16:48
aaaaaand I can't const_cast. I'm stuck with a cons
sky
2016/09/30 03:07:05
<rant>
I like the thought of containers with std::
| |
| 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 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 Loading... | |
| 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_ |
| OLD | NEW |