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.
5 #include "ui/v2/public/view.h"
10 #include "ui/compositor/layer_owner.h"
11 #include "ui/v2/public/view_observer.h"
12 #include "ui/v2/src/view_private.h"
21 void StackChildRelativeTo(View
* parent
,
22 std::vector
<View
*>* children
,
25 StackDirection direction
) {
26 DCHECK_NE(child
, other
);
29 DCHECK_EQ(parent
, child
->parent());
30 DCHECK_EQ(parent
, other
->parent());
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
);
45 // TODO(beng): update layer.
46 // TODO(beng): Notify stacking changed.
49 void NotifyViewTreeChangeAtReceiver(
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
));
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
);
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
);
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
);
80 case ViewObserver::DISPOSITION_CHANGED
:
81 if (params
.new_parent
)
82 NotifyViewTreeChangeUp(params
.new_parent
, params
);
90 class ScopedTreeNotifier
{
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_
);
98 ~ScopedTreeNotifier() {
99 params_
.phase
= ViewObserver::DISPOSITION_CHANGED
;
100 NotifyViewTreeChange(params_
);
104 ViewObserver::TreeChangeParams params_
;
106 DISALLOW_COPY_AND_ASSIGN(ScopedTreeNotifier
);
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()) {
114 ViewPrivate(child
).ClearParent();
118 class ViewLayerOwner
: public ui::LayerOwner
,
119 public ui::LayerDelegate
{
121 explicit ViewLayerOwner(ui::Layer
* layer
) {
127 // Overridden from ui::LayerDelegate:
128 virtual void OnPaintLayer(gfx::Canvas
* canvas
) OVERRIDE
{
129 // TODO(beng): paint processor.
131 virtual void OnDeviceScaleFactorChanged(float device_scale_factor
) OVERRIDE
{
134 virtual base::Closure
PrepareForLayerBoundsChange() OVERRIDE
{
135 return base::Bind(&ViewLayerOwner::OnLayerBoundsChanged
,
136 base::Unretained(this));
139 void OnLayerBoundsChanged() {
143 DISALLOW_COPY_AND_ASSIGN(ViewLayerOwner
);
146 ////////////////////////////////////////////////////////////////////////////////
149 // Creation, configuration -----------------------------------------------------
151 View::View() : visible_(true), owned_by_parent_(true), parent_(NULL
) {
155 FOR_EACH_OBSERVER(ViewObserver
, observers_
,
156 OnViewDestroy(this, ViewObserver::DISPOSITION_CHANGING
));
158 while (!children_
.empty()) {
159 View
* child
= children_
.front();
160 if (child
->owned_by_parent_
) {
162 // Deleting the child also removes it from our child list.
163 DCHECK(std::find(children_
.begin(), children_
.end(), child
) ==
171 parent_
->RemoveChild(this);
173 FOR_EACH_OBSERVER(ViewObserver
, observers_
,
174 OnViewDestroy(this, ViewObserver::DISPOSITION_CHANGED
));
177 void View::AddObserver(ViewObserver
* observer
) {
178 observers_
.AddObserver(observer
);
181 void View::RemoveObserver(ViewObserver
* observer
) {
182 observers_
.RemoveObserver(observer
);
185 void View::SetPainter(Painter
* painter
) {
186 painter_
.reset(painter
);
189 void View::SetLayout(Layout
* layout
) {
190 layout_
.reset(layout
);
193 // Disposition -----------------------------------------------------------------
195 void View::SetBounds(const gfx::Rect
& bounds
) {
196 gfx::Rect old_bounds
= bounds_
;
197 // TODO(beng): consult layout manager
199 // TODO(beng): update layer
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_
));
209 void View::SetVisible(bool visible
) {
210 FOR_EACH_OBSERVER(ViewObserver
, observers_
, OnViewVisibilityChange(this,
211 ViewObserver::DISPOSITION_CHANGING
));
213 bool old_visible
= visible_
;
214 // TODO(beng): consult layout manager
216 // TODO(beng): update layer
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
));
226 // Tree ------------------------------------------------------------------------
228 void View::AddChild(View
* child
) {
229 ScopedTreeNotifier
notifier(child
, child
->parent(), this);
231 RemoveChildImpl(child
, &child
->parent_
->children_
);
232 children_
.push_back(child
);
233 child
->parent_
= this;
236 void View::RemoveChild(View
* child
) {
237 DCHECK_EQ(this, child
->parent());
238 ScopedTreeNotifier(child
, this, NULL
);
239 RemoveChildImpl(child
, &children_
);
242 bool View::Contains(View
* child
) const {
243 for (View
* p
= child
->parent(); p
; p
= p
->parent()) {
250 void View::StackChildAtTop(View
* child
) {
251 if (children_
.size() <= 1 || child
== children_
.back())
252 return; // On top already.
253 StackChildAbove(child
, children_
.back());
256 void View::StackChildAtBottom(View
* child
) {
257 if (children_
.size() <= 1 || child
== children_
.front())
258 return; // On bottom already.
259 StackChildBelow(child
, children_
.front());
262 void View::StackChildAbove(View
* child
, View
* other
) {
263 StackChildRelativeTo(this, &children_
, child
, other
, STACK_ABOVE
);
266 void View::StackChildBelow(View
* child
, View
* other
) {
267 StackChildRelativeTo(this, &children_
, child
, other
, STACK_BELOW
);
270 // Layer -----------------------------------------------------------------------
272 const ui::Layer
* View::layer() const {
273 return layer_owner_
.get() ? layer_owner_
->layer() : NULL
;
276 ui::Layer
* View::layer() {
277 return const_cast<ui::Layer
*>(const_cast<const View
*>(this)->layer());
280 bool View::HasLayer() const {
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?
292 void View::DestroyLayer() {
293 DCHECK(layer_owner_
.get());
294 layer_owner_
.reset();
297 ui::Layer
* View::AcquireLayer() {
298 DCHECK(layer_owner_
.get());
299 return layer_owner_
->AcquireLayer();