Index: mojo/services/public/cpp/view_manager/lib/view_tree_node.cc |
diff --git a/mojo/services/public/cpp/view_manager/lib/view_tree_node.cc b/mojo/services/public/cpp/view_manager/lib/view_tree_node.cc |
index 27848a37d7d917e24d9e7fb5f807ad2d63186156..5a6c1d283f08eb5df71c91beced0a1419b0a96da 100644 |
--- a/mojo/services/public/cpp/view_manager/lib/view_tree_node.cc |
+++ b/mojo/services/public/cpp/view_manager/lib/view_tree_node.cc |
@@ -80,6 +80,72 @@ void RemoveChildImpl(ViewTreeNode* child, ViewTreeNode::Children* children) { |
} |
} |
+class ScopedOrderChangedNotifier { |
+ public: |
+ ScopedOrderChangedNotifier(ViewTreeNode* node, |
+ ViewTreeNode* relative_node, |
+ OrderDirection direction) |
+ : node_(node), |
+ relative_node_(relative_node), |
+ direction_(direction) { |
+ FOR_EACH_OBSERVER( |
+ ViewTreeNodeObserver, |
+ *ViewTreeNodePrivate(node_).observers(), |
+ OnNodeReordered(node_, |
+ relative_node_, |
+ direction_, |
+ ViewTreeNodeObserver::DISPOSITION_CHANGING)); |
+ |
+ } |
+ ~ScopedOrderChangedNotifier() { |
+ FOR_EACH_OBSERVER( |
+ ViewTreeNodeObserver, |
+ *ViewTreeNodePrivate(node_).observers(), |
+ OnNodeReordered(node_, |
+ relative_node_, |
+ direction_, |
+ ViewTreeNodeObserver::DISPOSITION_CHANGED)); |
+ } |
+ |
+ private: |
+ ViewTreeNode* node_; |
+ ViewTreeNode* relative_node_; |
+ OrderDirection direction_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(ScopedOrderChangedNotifier); |
+}; |
+ |
+// Returns true if the order actually changed. |
+bool ReorderImpl(ViewTreeNode::Children* children, |
+ ViewTreeNode* node, |
+ ViewTreeNode* relative, |
+ OrderDirection direction) { |
+ DCHECK(relative); |
+ DCHECK_NE(node, relative); |
+ DCHECK_EQ(node->parent(), relative->parent()); |
+ |
+ const size_t child_i = |
+ std::find(children->begin(), children->end(), node) - children->begin(); |
+ const size_t target_i = |
+ std::find(children->begin(), children->end(), relative) - |
+ children->begin(); |
+ if ((direction == ORDER_ABOVE && child_i == target_i + 1) || |
+ (direction == ORDER_BELOW && child_i + 1 == target_i)) { |
+ return false; |
+ } |
+ |
+ ScopedOrderChangedNotifier notifier(node, relative, direction); |
+ |
+ const size_t dest_i = |
+ direction == ORDER_ABOVE ? |
+ (child_i < target_i ? target_i : target_i + 1) : |
+ (child_i < target_i ? target_i - 1 : target_i); |
+ children->erase(children->begin() + child_i); |
+ children->insert(children->begin() + dest_i, node); |
+ |
+ return true; |
+} |
+ |
class ScopedSetActiveViewNotifier { |
public: |
ScopedSetActiveViewNotifier(ViewTreeNode* node, |
@@ -238,6 +304,24 @@ void ViewTreeNode::RemoveChild(ViewTreeNode* child) { |
} |
} |
+void ViewTreeNode::MoveToFront() { |
+ Reorder(parent_->children_.back(), ORDER_ABOVE); |
+} |
+ |
+void ViewTreeNode::MoveToBack() { |
+ Reorder(parent_->children_.front(), ORDER_BELOW); |
+} |
+ |
+void ViewTreeNode::Reorder(ViewTreeNode* relative, OrderDirection direction) { |
+ if (!LocalReorder(relative, direction)) |
+ return; |
+ if (manager_) { |
+ static_cast<ViewManagerSynchronizer*>(manager_)->Reorder(id_, |
+ relative->id(), |
+ direction); |
+ } |
+} |
+ |
bool ViewTreeNode::Contains(ViewTreeNode* child) const { |
if (manager_) |
CHECK_EQ(ViewTreeNodePrivate(child).view_manager(), manager_); |
@@ -324,6 +408,11 @@ void ViewTreeNode::LocalRemoveChild(ViewTreeNode* child) { |
RemoveChildImpl(child, &children_); |
} |
+bool ViewTreeNode::LocalReorder(ViewTreeNode* relative, |
+ OrderDirection direction) { |
+ return ReorderImpl(&parent_->children_, this, relative, direction); |
+} |
+ |
void ViewTreeNode::LocalSetActiveView(View* view) { |
ScopedSetActiveViewNotifier notifier(this, active_view_, view); |
if (active_view_) |