• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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