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

Side by Side Diff: mojo/services/public/cpp/view_manager/lib/node.cc

Issue 460863002: Rename Node to View in the View Manager mojom & client lib. Service TBD. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: . Created 6 years, 4 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 | Annotate | Revision Log
OLDNEW
(Empty)
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/node.h"
6
7 #include "mojo/public/cpp/application/service_provider_impl.h"
8 #include "mojo/services/public/cpp/view_manager/lib/node_private.h"
9 #include "mojo/services/public/cpp/view_manager/lib/view_manager_client_impl.h"
10 #include "mojo/services/public/cpp/view_manager/node_observer.h"
11 #include "ui/gfx/canvas.h"
12
13 namespace mojo {
14
15 namespace {
16
17 void NotifyViewTreeChangeAtReceiver(
18 Node* receiver,
19 const NodeObserver::TreeChangeParams& params,
20 bool change_applied) {
21 NodeObserver::TreeChangeParams local_params = params;
22 local_params.receiver = receiver;
23 if (change_applied) {
24 FOR_EACH_OBSERVER(NodeObserver,
25 *NodePrivate(receiver).observers(),
26 OnTreeChanged(local_params));
27 } else {
28 FOR_EACH_OBSERVER(NodeObserver,
29 *NodePrivate(receiver).observers(),
30 OnTreeChanging(local_params));
31 }
32 }
33
34 void NotifyViewTreeChangeUp(
35 Node* start_at,
36 const NodeObserver::TreeChangeParams& params,
37 bool change_applied) {
38 for (Node* current = start_at; current; current = current->parent())
39 NotifyViewTreeChangeAtReceiver(current, params, change_applied);
40 }
41
42 void NotifyViewTreeChangeDown(
43 Node* start_at,
44 const NodeObserver::TreeChangeParams& params,
45 bool change_applied) {
46 NotifyViewTreeChangeAtReceiver(start_at, params, change_applied);
47 Node::Children::const_iterator it = start_at->children().begin();
48 for (; it != start_at->children().end(); ++it)
49 NotifyViewTreeChangeDown(*it, params, change_applied);
50 }
51
52 void NotifyViewTreeChange(
53 const NodeObserver::TreeChangeParams& params,
54 bool change_applied) {
55 NotifyViewTreeChangeDown(params.target, params, change_applied);
56 if (params.old_parent)
57 NotifyViewTreeChangeUp(params.old_parent, params, change_applied);
58 if (params.new_parent)
59 NotifyViewTreeChangeUp(params.new_parent, params, change_applied);
60 }
61
62 class ScopedTreeNotifier {
63 public:
64 ScopedTreeNotifier(Node* target, Node* old_parent, Node* new_parent) {
65 params_.target = target;
66 params_.old_parent = old_parent;
67 params_.new_parent = new_parent;
68 NotifyViewTreeChange(params_, false);
69 }
70 ~ScopedTreeNotifier() {
71 NotifyViewTreeChange(params_, true);
72 }
73
74 private:
75 NodeObserver::TreeChangeParams params_;
76
77 DISALLOW_COPY_AND_ASSIGN(ScopedTreeNotifier);
78 };
79
80 void RemoveChildImpl(Node* child, Node::Children* children) {
81 Node::Children::iterator it =
82 std::find(children->begin(), children->end(), child);
83 if (it != children->end()) {
84 children->erase(it);
85 NodePrivate(child).ClearParent();
86 }
87 }
88
89 class ScopedOrderChangedNotifier {
90 public:
91 ScopedOrderChangedNotifier(Node* node,
92 Node* relative_node,
93 OrderDirection direction)
94 : node_(node),
95 relative_node_(relative_node),
96 direction_(direction) {
97 FOR_EACH_OBSERVER(NodeObserver,
98 *NodePrivate(node_).observers(),
99 OnNodeReordering(node_, relative_node_, direction_));
100 }
101 ~ScopedOrderChangedNotifier() {
102 FOR_EACH_OBSERVER(NodeObserver,
103 *NodePrivate(node_).observers(),
104 OnNodeReordered(node_, relative_node_, direction_));
105 }
106
107 private:
108 Node* node_;
109 Node* relative_node_;
110 OrderDirection direction_;
111
112 DISALLOW_COPY_AND_ASSIGN(ScopedOrderChangedNotifier);
113 };
114
115 // Returns true if the order actually changed.
116 bool ReorderImpl(Node::Children* children,
117 Node* node,
118 Node* relative,
119 OrderDirection direction) {
120 DCHECK(relative);
121 DCHECK_NE(node, relative);
122 DCHECK_EQ(node->parent(), relative->parent());
123
124 const size_t child_i =
125 std::find(children->begin(), children->end(), node) - children->begin();
126 const size_t target_i =
127 std::find(children->begin(), children->end(), relative) -
128 children->begin();
129 if ((direction == ORDER_DIRECTION_ABOVE && child_i == target_i + 1) ||
130 (direction == ORDER_DIRECTION_BELOW && child_i + 1 == target_i)) {
131 return false;
132 }
133
134 ScopedOrderChangedNotifier notifier(node, relative, direction);
135
136 const size_t dest_i = direction == ORDER_DIRECTION_ABOVE
137 ? (child_i < target_i ? target_i : target_i + 1)
138 : (child_i < target_i ? target_i - 1 : target_i);
139 children->erase(children->begin() + child_i);
140 children->insert(children->begin() + dest_i, node);
141
142 return true;
143 }
144
145 class ScopedSetBoundsNotifier {
146 public:
147 ScopedSetBoundsNotifier(Node* node,
148 const gfx::Rect& old_bounds,
149 const gfx::Rect& new_bounds)
150 : node_(node),
151 old_bounds_(old_bounds),
152 new_bounds_(new_bounds) {
153 FOR_EACH_OBSERVER(NodeObserver,
154 *NodePrivate(node_).observers(),
155 OnNodeBoundsChanging(node_, old_bounds_, new_bounds_));
156 }
157 ~ScopedSetBoundsNotifier() {
158 FOR_EACH_OBSERVER(NodeObserver,
159 *NodePrivate(node_).observers(),
160 OnNodeBoundsChanged(node_, old_bounds_, new_bounds_));
161 }
162
163 private:
164 Node* node_;
165 const gfx::Rect old_bounds_;
166 const gfx::Rect new_bounds_;
167
168 DISALLOW_COPY_AND_ASSIGN(ScopedSetBoundsNotifier);
169 };
170
171 // Some operations are only permitted in the connection that created the node.
172 bool OwnsNode(ViewManager* manager, Node* node) {
173 return !manager ||
174 static_cast<ViewManagerClientImpl*>(manager)->OwnsNode(node->id());
175 }
176
177 } // namespace
178
179 ////////////////////////////////////////////////////////////////////////////////
180 // Node, public:
181
182 // static
183 Node* Node::Create(ViewManager* view_manager) {
184 Node* node = new Node(view_manager);
185 static_cast<ViewManagerClientImpl*>(view_manager)->AddNode(node);
186 return node;
187 }
188
189 void Node::Destroy() {
190 if (!OwnsNode(manager_, this))
191 return;
192
193 if (manager_)
194 static_cast<ViewManagerClientImpl*>(manager_)->DestroyNode(id_);
195 while (!children_.empty()) {
196 Node* child = children_.front();
197 if (!OwnsNode(manager_, child)) {
198 NodePrivate(child).ClearParent();
199 children_.erase(children_.begin());
200 } else {
201 child->Destroy();
202 DCHECK(std::find(children_.begin(), children_.end(), child) ==
203 children_.end());
204 }
205 }
206 LocalDestroy();
207 }
208
209 void Node::SetBounds(const gfx::Rect& bounds) {
210 if (!OwnsNode(manager_, this))
211 return;
212
213 if (manager_)
214 static_cast<ViewManagerClientImpl*>(manager_)->SetBounds(id_, bounds);
215 LocalSetBounds(bounds_, bounds);
216 }
217
218 void Node::SetVisible(bool value) {
219 if (manager_)
220 static_cast<ViewManagerClientImpl*>(manager_)->SetVisible(id_, value);
221 }
222
223 void Node::AddObserver(NodeObserver* observer) {
224 observers_.AddObserver(observer);
225 }
226
227 void Node::RemoveObserver(NodeObserver* observer) {
228 observers_.RemoveObserver(observer);
229 }
230
231 void Node::AddChild(Node* child) {
232 // TODO(beng): not necessarily valid to all connections, but possibly to the
233 // embeddee in an embedder-embeddee relationship.
234 if (manager_)
235 CHECK_EQ(NodePrivate(child).view_manager(), manager_);
236 LocalAddChild(child);
237 if (manager_)
238 static_cast<ViewManagerClientImpl*>(manager_)->AddChild(child->id(), id_);
239 }
240
241 void Node::RemoveChild(Node* child) {
242 // TODO(beng): not necessarily valid to all connections, but possibly to the
243 // embeddee in an embedder-embeddee relationship.
244 if (manager_)
245 CHECK_EQ(NodePrivate(child).view_manager(), manager_);
246 LocalRemoveChild(child);
247 if (manager_) {
248 static_cast<ViewManagerClientImpl*>(manager_)->RemoveChild(child->id(),
249 id_);
250 }
251 }
252
253 void Node::MoveToFront() {
254 Reorder(parent_->children_.back(), ORDER_DIRECTION_ABOVE);
255 }
256
257 void Node::MoveToBack() {
258 Reorder(parent_->children_.front(), ORDER_DIRECTION_BELOW);
259 }
260
261 void Node::Reorder(Node* relative, OrderDirection direction) {
262 if (!LocalReorder(relative, direction))
263 return;
264 if (manager_) {
265 static_cast<ViewManagerClientImpl*>(manager_)->Reorder(id_,
266 relative->id(),
267 direction);
268 }
269 }
270
271 bool Node::Contains(Node* child) const {
272 if (manager_)
273 CHECK_EQ(NodePrivate(child).view_manager(), manager_);
274 for (Node* p = child->parent(); p; p = p->parent()) {
275 if (p == this)
276 return true;
277 }
278 return false;
279 }
280
281 Node* Node::GetChildById(Id id) {
282 if (id == id_)
283 return this;
284 // TODO(beng): this could be improved depending on how we decide to own nodes.
285 Children::const_iterator it = children_.begin();
286 for (; it != children_.end(); ++it) {
287 Node* node = (*it)->GetChildById(id);
288 if (node)
289 return node;
290 }
291 return NULL;
292 }
293
294 void Node::SetContents(const SkBitmap& contents) {
295 if (manager_) {
296 static_cast<ViewManagerClientImpl*>(manager_)->SetNodeContents(id_,
297 contents);
298 }
299 }
300
301 void Node::SetColor(SkColor color) {
302 gfx::Canvas canvas(bounds_.size(), 1.0f, true);
303 canvas.DrawColor(color);
304 SetContents(skia::GetTopDevice(*canvas.sk_canvas())->accessBitmap(true));
305 }
306
307 void Node::SetFocus() {
308 if (manager_)
309 static_cast<ViewManagerClientImpl*>(manager_)->SetFocus(id_);
310 }
311
312 void Node::Embed(const String& url) {
313 static_cast<ViewManagerClientImpl*>(manager_)->Embed(url, id_);
314 }
315
316 scoped_ptr<ServiceProvider>
317 Node::Embed(const String& url,
318 scoped_ptr<ServiceProviderImpl> exported_services) {
319 scoped_ptr<ServiceProvider> imported_services;
320 // BindToProxy() takes ownership of |exported_services|.
321 ServiceProviderImpl* registry = exported_services.release();
322 ServiceProviderPtr sp;
323 if (registry) {
324 BindToProxy(registry, &sp);
325 imported_services.reset(registry->CreateRemoteServiceProvider());
326 }
327 static_cast<ViewManagerClientImpl*>(manager_)->Embed(url, id_, sp.Pass());
328 return imported_services.Pass();
329 }
330
331 ////////////////////////////////////////////////////////////////////////////////
332 // Node, protected:
333
334 Node::Node()
335 : manager_(NULL),
336 id_(static_cast<Id>(-1)),
337 parent_(NULL) {}
338
339 Node::~Node() {
340 FOR_EACH_OBSERVER(NodeObserver, observers_, OnNodeDestroying(this));
341 if (parent_)
342 parent_->LocalRemoveChild(this);
343 // TODO(beng): It'd be better to do this via a destruction observer in the
344 // ViewManagerClientImpl.
345 if (manager_)
346 static_cast<ViewManagerClientImpl*>(manager_)->RemoveNode(id_);
347 FOR_EACH_OBSERVER(NodeObserver, observers_, OnNodeDestroyed(this));
348 }
349
350 ////////////////////////////////////////////////////////////////////////////////
351 // Node, private:
352
353 Node::Node(ViewManager* manager)
354 : manager_(manager),
355 id_(static_cast<ViewManagerClientImpl*>(manager_)->CreateNode()),
356 parent_(NULL) {}
357
358 void Node::LocalDestroy() {
359 delete this;
360 }
361
362 void Node::LocalAddChild(Node* child) {
363 ScopedTreeNotifier notifier(child, child->parent(), this);
364 if (child->parent())
365 RemoveChildImpl(child, &child->parent_->children_);
366 children_.push_back(child);
367 child->parent_ = this;
368 }
369
370 void Node::LocalRemoveChild(Node* child) {
371 DCHECK_EQ(this, child->parent());
372 ScopedTreeNotifier notifier(child, this, NULL);
373 RemoveChildImpl(child, &children_);
374 }
375
376 bool Node::LocalReorder(Node* relative, OrderDirection direction) {
377 return ReorderImpl(&parent_->children_, this, relative, direction);
378 }
379
380 void Node::LocalSetBounds(const gfx::Rect& old_bounds,
381 const gfx::Rect& new_bounds) {
382 DCHECK(old_bounds == bounds_);
383 ScopedSetBoundsNotifier notifier(this, old_bounds, new_bounds);
384 bounds_ = new_bounds;
385 }
386
387 } // namespace mojo
OLDNEW
« no previous file with comments | « mojo/services/public/cpp/view_manager/BUILD.gn ('k') | mojo/services/public/cpp/view_manager/lib/node_observer.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698