1 // Copyright (c) 2013 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 "ui/v2/public/view.h"
6
7 #include <algorithm>
8
9 #include "base/bind.h"
10 #include "ui/compositor/layer_owner.h"
11 #include "ui/v2/public/view_observer.h"
12 #include "ui/v2/src/view_private.h"
13
14 namespace v2 {
15
16 enum StackDirection {
17 STACK_ABOVE,
18 STACK_BELOW
19 };
20
StackChildRelativeTo(View * parent,std::vector<View * > * children,View * child,View * other,StackDirection direction)21 void StackChildRelativeTo(View* parent,
22 std::vector<View*>* children,
23 View* child,
24 View* other,
25 StackDirection direction) {
26 DCHECK_NE(child, other);
27 DCHECK(child);
28 DCHECK(other);
29 DCHECK_EQ(parent, child->parent());
30 DCHECK_EQ(parent, other->parent());
31
32 // TODO(beng): Notify stacking changing.
33 // TODO(beng): consult layout manager
34 const size_t child_i =
35 std::find(children->begin(), children->end(), child) - children->begin();
36 const size_t other_i =
37 std::find(children->begin(), children->end(), other) - children->begin();
38 const size_t destination_i =
39 direction == STACK_ABOVE ?
40 (child_i < other_i ? other_i : other_i + 1) :
41 (child_i < other_i ? other_i - 1 : other_i);
42 children->erase(children->begin() + child_i);
43 children->insert(children->begin() + destination_i, child);
44
45 // TODO(beng): update layer.
46 // TODO(beng): Notify stacking changed.
47 }
48
NotifyViewTreeChangeAtReceiver(View * receiver,const ViewObserver::TreeChangeParams & params)49 void NotifyViewTreeChangeAtReceiver(
50 View* receiver,
51 const ViewObserver::TreeChangeParams& params) {
52 ViewObserver::TreeChangeParams local_params = params;
53 local_params.receiver = receiver;
54 FOR_EACH_OBSERVER(ViewObserver,
55 *ViewPrivate(receiver).observers(),
56 OnViewTreeChange(local_params));
57 }
58
NotifyViewTreeChangeUp(View * start_at,const ViewObserver::TreeChangeParams & params)59 void NotifyViewTreeChangeUp(View* start_at,
60 const ViewObserver::TreeChangeParams& params) {
61 for (View* current = start_at; current; current = current->parent())
62 NotifyViewTreeChangeAtReceiver(current, params);
63 }
64
NotifyViewTreeChangeDown(View * start_at,const ViewObserver::TreeChangeParams & params)65 void NotifyViewTreeChangeDown(View* start_at,
66 const ViewObserver::TreeChangeParams& params) {
67 NotifyViewTreeChangeAtReceiver(start_at, params);
68 View::Children::const_iterator it = start_at->children().begin();
69 for (; it != start_at->children().end(); ++it)
70 NotifyViewTreeChangeDown(*it, params);
71 }
72
NotifyViewTreeChange(const ViewObserver::TreeChangeParams & params)73 void NotifyViewTreeChange(const ViewObserver::TreeChangeParams& params) {
74 NotifyViewTreeChangeDown(params.target, params);
75 switch (params.phase) {
76 case ViewObserver::DISPOSITION_CHANGING:
77 if (params.old_parent)
78 NotifyViewTreeChangeUp(params.old_parent, params);
79 break;
80 case ViewObserver::DISPOSITION_CHANGED:
81 if (params.new_parent)
82 NotifyViewTreeChangeUp(params.new_parent, params);
83 break;
84 default:
85 NOTREACHED();
86 break;
87 }
88 }
89
90 class ScopedTreeNotifier {
91 public:
ScopedTreeNotifier(View * target,View * old_parent,View * new_parent)92 ScopedTreeNotifier(View* target, View* old_parent, View* new_parent) {
93 params_.target = target;
94 params_.old_parent = old_parent;
95 params_.new_parent = new_parent;
96 NotifyViewTreeChange(params_);
97 }
~ScopedTreeNotifier()98 ~ScopedTreeNotifier() {
99 params_.phase = ViewObserver::DISPOSITION_CHANGED;
100 NotifyViewTreeChange(params_);
101 }
102
103 private:
104 ViewObserver::TreeChangeParams params_;
105
106 DISALLOW_COPY_AND_ASSIGN(ScopedTreeNotifier);
107 };
108
RemoveChildImpl(View * child,View::Children * children)109 void RemoveChildImpl(View* child, View::Children* children) {
110 std::vector<View*>::iterator it =
111 std::find(children->begin(), children->end(), child);
112 if (it != children->end()) {
113 children->erase(it);
114 ViewPrivate(child).ClearParent();
115 }
116 }
117
118 class ViewLayerOwner : public ui::LayerOwner,
119 public ui::LayerDelegate {
120 public:
ViewLayerOwner(ui::Layer * layer)121 explicit ViewLayerOwner(ui::Layer* layer) {
122 layer_ = layer;
123 }
~ViewLayerOwner()124 ~ViewLayerOwner() {}
125
126 private:
127 // Overridden from ui::LayerDelegate:
OnPaintLayer(gfx::Canvas * canvas)128 virtual void OnPaintLayer(gfx::Canvas* canvas) OVERRIDE {
129 // TODO(beng): paint processor.
130 }
OnDeviceScaleFactorChanged(float device_scale_factor)131 virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE {
132 // TODO(beng): ???
133 }
PrepareForLayerBoundsChange()134 virtual base::Closure PrepareForLayerBoundsChange() OVERRIDE {
135 return base::Bind(&ViewLayerOwner::OnLayerBoundsChanged,
136 base::Unretained(this));
137 }
138
OnLayerBoundsChanged()139 void OnLayerBoundsChanged() {
140 // TODO(beng): ???
141 }
142
143 DISALLOW_COPY_AND_ASSIGN(ViewLayerOwner);
144 };
145
146 ////////////////////////////////////////////////////////////////////////////////
147 // View, public:
148
149 // Creation, configuration -----------------------------------------------------
150
View()151 View::View() : visible_(true), owned_by_parent_(true), parent_(NULL) {
152 }
153
~View()154 View::~View() {
155 FOR_EACH_OBSERVER(ViewObserver, observers_,
156 OnViewDestroy(this, ViewObserver::DISPOSITION_CHANGING));
157
158 while (!children_.empty()) {
159 View* child = children_.front();
160 if (child->owned_by_parent_) {
161 delete child;
162 // Deleting the child also removes it from our child list.
163 DCHECK(std::find(children_.begin(), children_.end(), child) ==
164 children_.end());
165 } else {
166 RemoveChild(child);
167 }
168 }
169
170 if (parent_)
171 parent_->RemoveChild(this);
172
173 FOR_EACH_OBSERVER(ViewObserver, observers_,
174 OnViewDestroy(this, ViewObserver::DISPOSITION_CHANGED));
175 }
176
AddObserver(ViewObserver * observer)177 void View::AddObserver(ViewObserver* observer) {
178 observers_.AddObserver(observer);
179 }
180
RemoveObserver(ViewObserver * observer)181 void View::RemoveObserver(ViewObserver* observer) {
182 observers_.RemoveObserver(observer);
183 }
184
SetPainter(Painter * painter)185 void View::SetPainter(Painter* painter) {
186 painter_.reset(painter);
187 }
188
SetLayout(Layout * layout)189 void View::SetLayout(Layout* layout) {
190 layout_.reset(layout);
191 }
192
193 // Disposition -----------------------------------------------------------------
194
SetBounds(const gfx::Rect & bounds)195 void View::SetBounds(const gfx::Rect& bounds) {
196 gfx::Rect old_bounds = bounds_;
197 // TODO(beng): consult layout manager
198 bounds_ = bounds;
199 // TODO(beng): update layer
200
201 // TODO(beng): write tests for this where layoutmanager prevents a change
202 // and no changed notification is sent.
203 if (bounds_ != old_bounds) {
204 FOR_EACH_OBSERVER(ViewObserver, observers_, OnViewBoundsChanged(this,
205 old_bounds, bounds_));
206 }
207 }
208
SetVisible(bool visible)209 void View::SetVisible(bool visible) {
210 FOR_EACH_OBSERVER(ViewObserver, observers_, OnViewVisibilityChange(this,
211 ViewObserver::DISPOSITION_CHANGING));
212
213 bool old_visible = visible_;
214 // TODO(beng): consult layout manager
215 visible_ = visible;
216 // TODO(beng): update layer
217
218 // TODO(beng): write tests for this where layoutmanager prevents a change
219 // and no changed notification is sent.
220 if (old_visible != visible_) {
221 FOR_EACH_OBSERVER(ViewObserver, observers_, OnViewVisibilityChange(this,
222 ViewObserver::DISPOSITION_CHANGED));
223 }
224 }
225
226 // Tree ------------------------------------------------------------------------
227
AddChild(View * child)228 void View::AddChild(View* child) {
229 ScopedTreeNotifier notifier(child, child->parent(), this);
230 if (child->parent())
231 RemoveChildImpl(child, &child->parent_->children_);
232 children_.push_back(child);
233 child->parent_ = this;
234 }
235
RemoveChild(View * child)236 void View::RemoveChild(View* child) {
237 DCHECK_EQ(this, child->parent());
238 ScopedTreeNotifier(child, this, NULL);
239 RemoveChildImpl(child, &children_);
240 }
241
Contains(View * child) const242 bool View::Contains(View* child) const {
243 for (View* p = child->parent(); p; p = p->parent()) {
244 if (p == this)
245 return true;
246 }
247 return false;
248 }
249
StackChildAtTop(View * child)250 void View::StackChildAtTop(View* child) {
251 if (children_.size() <= 1 || child == children_.back())
252 return; // On top already.
253 StackChildAbove(child, children_.back());
254 }
255
StackChildAtBottom(View * child)256 void View::StackChildAtBottom(View* child) {
257 if (children_.size() <= 1 || child == children_.front())
258 return; // On bottom already.
259 StackChildBelow(child, children_.front());
260 }
261
StackChildAbove(View * child,View * other)262 void View::StackChildAbove(View* child, View* other) {
263 StackChildRelativeTo(this, &children_, child, other, STACK_ABOVE);
264 }
265
StackChildBelow(View * child,View * other)266 void View::StackChildBelow(View* child, View* other) {
267 StackChildRelativeTo(this, &children_, child, other, STACK_BELOW);
268 }
269
270 // Layer -----------------------------------------------------------------------
271
layer() const272 const ui::Layer* View::layer() const {
273 return layer_owner_.get() ? layer_owner_->layer() : NULL;
274 }
275
layer()276 ui::Layer* View::layer() {
277 return const_cast<ui::Layer*>(const_cast<const View*>(this)->layer());
278 }
279
HasLayer() const280 bool View::HasLayer() const {
281 return !!layer();
282 }
283
CreateLayer(ui::LayerType layer_type)284 void View::CreateLayer(ui::LayerType layer_type) {
285 layer_owner_.reset(new ViewLayerOwner(new ui::Layer(layer_type)));
286 layer()->SetVisible(visible_);
287 layer()->set_delegate(layer_owner_.get());
288 // TODO(beng): layer name?
289 // TODO(beng): SetFillsBoundsOpaquely?
290 }
291
DestroyLayer()292 void View::DestroyLayer() {
293 DCHECK(layer_owner_.get());
294 layer_owner_.reset();
295 }
296
AcquireLayer()297 ui::Layer* View::AcquireLayer() {
298 DCHECK(layer_owner_.get());
299 return layer_owner_->AcquireLayer();
300 }
301
302 } // namespace v2
303