Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / mojo / services / public / cpp / view_manager / lib / view_tree_node.cc
1 // Copyright 2014 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 #include "mojo/services/public/cpp/view_manager/view_tree_node.h"
6
7 #include "mojo/services/public/cpp/view_manager/lib/view_manager_private.h"
8 #include "mojo/services/public/cpp/view_manager/lib/view_manager_synchronizer.h"
9 #include "mojo/services/public/cpp/view_manager/lib/view_tree_node_private.h"
10 #include "mojo/services/public/cpp/view_manager/view_tree_node_observer.h"
11
12 namespace mojo {
13 namespace services {
14 namespace view_manager {
15
16 void NotifyViewTreeChangeAtReceiver(
17     ViewTreeNode* receiver,
18     const ViewTreeNodeObserver::TreeChangeParams& params) {
19   ViewTreeNodeObserver::TreeChangeParams local_params = params;
20   local_params.receiver = receiver;
21   FOR_EACH_OBSERVER(ViewTreeNodeObserver,
22                     *ViewTreeNodePrivate(receiver).observers(),
23                     OnTreeChange(local_params));
24 }
25
26 void NotifyViewTreeChangeUp(
27     ViewTreeNode* start_at,
28     const ViewTreeNodeObserver::TreeChangeParams& params) {
29   for (ViewTreeNode* current = start_at; current; current = current->parent())
30     NotifyViewTreeChangeAtReceiver(current, params);
31 }
32
33 void NotifyViewTreeChangeDown(
34     ViewTreeNode* start_at,
35     const ViewTreeNodeObserver::TreeChangeParams& params) {
36   NotifyViewTreeChangeAtReceiver(start_at, params);
37   ViewTreeNode::Children::const_iterator it = start_at->children().begin();
38   for (; it != start_at->children().end(); ++it)
39     NotifyViewTreeChangeDown(*it, params);
40 }
41
42 void NotifyViewTreeChange(
43     const ViewTreeNodeObserver::TreeChangeParams& params) {
44   NotifyViewTreeChangeDown(params.target, params);
45   switch (params.phase) {
46   case ViewTreeNodeObserver::DISPOSITION_CHANGING:
47     if (params.old_parent)
48       NotifyViewTreeChangeUp(params.old_parent, params);
49     break;
50   case ViewTreeNodeObserver::DISPOSITION_CHANGED:
51     if (params.new_parent)
52       NotifyViewTreeChangeUp(params.new_parent, params);
53     break;
54   default:
55     NOTREACHED();
56     break;
57   }
58 }
59
60 class ScopedTreeNotifier {
61  public:
62   ScopedTreeNotifier(ViewTreeNode* target,
63                      ViewTreeNode* old_parent,
64                      ViewTreeNode* new_parent) {
65     params_.target = target;
66     params_.old_parent = old_parent;
67     params_.new_parent = new_parent;
68     NotifyViewTreeChange(params_);
69   }
70   ~ScopedTreeNotifier() {
71     params_.phase = ViewTreeNodeObserver::DISPOSITION_CHANGED;
72     NotifyViewTreeChange(params_);
73   }
74
75  private:
76   ViewTreeNodeObserver::TreeChangeParams params_;
77
78   DISALLOW_COPY_AND_ASSIGN(ScopedTreeNotifier);
79 };
80
81 void RemoveChildImpl(ViewTreeNode* child, ViewTreeNode::Children* children) {
82   ViewTreeNode::Children::iterator it =
83       std::find(children->begin(), children->end(), child);
84   if (it != children->end()) {
85     children->erase(it);
86     ViewTreeNodePrivate(child).ClearParent();
87   }
88 }
89
90 ////////////////////////////////////////////////////////////////////////////////
91 // ViewTreeNode, public:
92
93 // static
94 ViewTreeNode* ViewTreeNode::Create(ViewManager* view_manager) {
95   ViewTreeNode* node = new ViewTreeNode(view_manager);
96   ViewManagerPrivate(view_manager).AddNode(node->id(), node);
97   return node;
98 }
99
100 void ViewTreeNode::Destroy() {
101   if (manager_)
102     ViewManagerPrivate(manager_).synchronizer()->DestroyViewTreeNode(id_);
103   while (!children_.empty())
104     children_.front()->Destroy();
105   LocalDestroy();
106 }
107
108 void ViewTreeNode::AddObserver(ViewTreeNodeObserver* observer) {
109   observers_.AddObserver(observer);
110 }
111
112 void ViewTreeNode::RemoveObserver(ViewTreeNodeObserver* observer) {
113   observers_.RemoveObserver(observer);
114 }
115
116 void ViewTreeNode::AddChild(ViewTreeNode* child) {
117   LocalAddChild(child);
118   if (manager_)
119     ViewManagerPrivate(manager_).synchronizer()->AddChild(child->id(), id_);
120 }
121
122 void ViewTreeNode::RemoveChild(ViewTreeNode* child) {
123   LocalRemoveChild(child);
124   if (manager_)
125     ViewManagerPrivate(manager_).synchronizer()->RemoveChild(child->id(), id_);
126 }
127
128 bool ViewTreeNode::Contains(ViewTreeNode* child) const {
129   for (ViewTreeNode* p = child->parent(); p; p = p->parent()) {
130     if (p == this)
131       return true;
132   }
133   return false;
134 }
135
136 ViewTreeNode* ViewTreeNode::GetChildById(TransportNodeId id) {
137   if (id == id_)
138     return this;
139   // TODO(beng): this could be improved depending on how we decide to own nodes.
140   Children::const_iterator it = children_.begin();
141   for (; it != children_.end(); ++it) {
142     ViewTreeNode* node = (*it)->GetChildById(id);
143     if (node)
144       return node;
145   }
146   return NULL;
147 }
148
149 ////////////////////////////////////////////////////////////////////////////////
150 // ViewTreeNode, protected:
151
152 ViewTreeNode::ViewTreeNode()
153     : manager_(NULL),
154       id_(-1),
155       parent_(NULL) {}
156
157 ViewTreeNode::~ViewTreeNode() {
158   FOR_EACH_OBSERVER(
159       ViewTreeNodeObserver,
160       observers_,
161       OnNodeDestroy(this, ViewTreeNodeObserver::DISPOSITION_CHANGING));
162   if (parent_)
163     parent_->LocalRemoveChild(this);
164   FOR_EACH_OBSERVER(
165       ViewTreeNodeObserver,
166       observers_,
167       OnNodeDestroy(this, ViewTreeNodeObserver::DISPOSITION_CHANGED));
168   if (manager_)
169     ViewManagerPrivate(manager_).RemoveNode(id_);
170 }
171
172 ////////////////////////////////////////////////////////////////////////////////
173 // ViewTreeNode, private:
174
175 ViewTreeNode::ViewTreeNode(ViewManager* manager)
176     : manager_(manager),
177       id_(ViewManagerPrivate(manager).synchronizer()->CreateViewTreeNode()),
178       parent_(NULL) {}
179
180 void ViewTreeNode::LocalDestroy() {
181   delete this;
182 }
183
184 void ViewTreeNode::LocalAddChild(ViewTreeNode* child) {
185   ScopedTreeNotifier notifier(child, child->parent(), this);
186   if (child->parent())
187     RemoveChildImpl(child, &child->parent_->children_);
188   children_.push_back(child);
189   child->parent_ = this;
190 }
191
192 void ViewTreeNode::LocalRemoveChild(ViewTreeNode* child) {
193   DCHECK_EQ(this, child->parent());
194   ScopedTreeNotifier(child, this, NULL);
195   RemoveChildImpl(child, &children_);
196 }
197
198 }  // namespace view_manager
199 }  // namespace services
200 }  // namespace mojo
201