diff options
author | phajdan.jr@chromium.org <phajdan.jr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-05-13 18:54:20 +0000 |
---|---|---|
committer | phajdan.jr@chromium.org <phajdan.jr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-05-13 18:54:20 +0000 |
commit | 992c625bf2d6dfaaa46cf5b45cdcd7de68e7817e (patch) | |
tree | ae6467a99cf17115e04af5bbe358a6219f9c9808 /app | |
parent | b83fed38db16e462afa3051dcad21318c62b2357 (diff) | |
download | chromium_src-992c625bf2d6dfaaa46cf5b45cdcd7de68e7817e.zip chromium_src-992c625bf2d6dfaaa46cf5b45cdcd7de68e7817e.tar.gz chromium_src-992c625bf2d6dfaaa46cf5b45cdcd7de68e7817e.tar.bz2 |
Move tree-related classes that Linux code depends on from views/ to app/
TEST=If it compiles and unit_tests pass, it's ok. Just moving files around.
http://crbug.com/11066
Review URL: http://codereview.chromium.org/115185
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@15982 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'app')
-rw-r--r-- | app/app.vcproj | 12 | ||||
-rw-r--r-- | app/tree_model.h | 87 | ||||
-rw-r--r-- | app/tree_node_iterator.h | 70 | ||||
-rw-r--r-- | app/tree_node_iterator_unittest.cc | 41 | ||||
-rw-r--r-- | app/tree_node_model.h | 279 |
5 files changed, 489 insertions, 0 deletions
diff --git a/app/app.vcproj b/app/app.vcproj index d940bf9..64b07d87 100644 --- a/app/app.vcproj +++ b/app/app.vcproj @@ -262,6 +262,18 @@ >
</File>
<File
+ RelativePath=".\tree_model.h"
+ >
+ </File>
+ <File
+ RelativePath=".\tree_node_iterator.h"
+ >
+ </File>
+ <File
+ RelativePath=".\tree_node_model.h"
+ >
+ </File>
+ <File
RelativePath=".\win_util.cc"
>
</File>
diff --git a/app/tree_model.h b/app/tree_model.h new file mode 100644 index 0000000..e7b93ee --- /dev/null +++ b/app/tree_model.h @@ -0,0 +1,87 @@ +// 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 APP_TREE_MODEL_H_ +#define APP_TREE_MODEL_H_ + +#include <string> + +#include "base/logging.h" + +class SkBitmap; + +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; } +}; + +#endif // APP_TREE_TREE_MODEL_H_ diff --git a/app/tree_node_iterator.h b/app/tree_node_iterator.h new file mode 100644 index 0000000..7e7398c --- /dev/null +++ b/app/tree_node_iterator.h @@ -0,0 +1,70 @@ +// 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 APP_TREE_NODE_ITERATOR_H_ +#define APP_TREE_NODE_ITERATOR_H_ + +#include <stack> + +#include "base/basictypes.h" +#include "base/logging.h" + +// 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); +}; + +#endif // APP_TREE_NODE_ITERATOR_H_ diff --git a/app/tree_node_iterator_unittest.cc b/app/tree_node_iterator_unittest.cc new file mode 100644 index 0000000..c20babe --- /dev/null +++ b/app/tree_node_iterator_unittest.cc @@ -0,0 +1,41 @@ +// 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 "app/tree_node_iterator.h" +#include "app/tree_node_model.h" + +namespace { + +TEST(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)); + + 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()); +} + +} // namespace diff --git a/app/tree_node_model.h b/app/tree_node_model.h new file mode 100644 index 0000000..69d5c8d --- /dev/null +++ b/app/tree_node_model.h @@ -0,0 +1,279 @@ +// 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 APP_TREE_NODE_MODEL_H_ +#define APP_TREE_NODE_MODEL_H_ + +#include <algorithm> +#include <vector> + +#include "app/tree_model.h" +#include "base/basictypes.h" +#include "base/scoped_ptr.h" +#include "base/scoped_vector.h" +#include "base/stl_util-inl.h" + +// 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); +}; + +#endif // APP_TREE_NODE_MODEL_H_ |