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
14namespace v2 {
15
16enum StackDirection {
17  STACK_ABOVE,
18  STACK_BELOW
19};
20
21void 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
49void 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
59void 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
65void 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
73void 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
90class ScopedTreeNotifier {
91 public:
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  }
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
109void 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
118class ViewLayerOwner : public ui::LayerOwner,
119                       public ui::LayerDelegate {
120 public:
121  explicit ViewLayerOwner(ui::Layer* layer) {
122    layer_ = layer;
123  }
124  ~ViewLayerOwner() {}
125
126 private:
127  // Overridden from ui::LayerDelegate:
128  virtual void OnPaintLayer(gfx::Canvas* canvas) OVERRIDE {
129    // TODO(beng): paint processor.
130  }
131  virtual void OnDeviceScaleFactorChanged(float device_scale_factor) OVERRIDE {
132    // TODO(beng): ???
133  }
134  virtual base::Closure PrepareForLayerBoundsChange() OVERRIDE {
135    return base::Bind(&ViewLayerOwner::OnLayerBoundsChanged,
136                      base::Unretained(this));
137  }
138
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
151View::View() : visible_(true), owned_by_parent_(true), parent_(NULL) {
152}
153
154View::~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
177void View::AddObserver(ViewObserver* observer) {
178  observers_.AddObserver(observer);
179}
180
181void View::RemoveObserver(ViewObserver* observer) {
182  observers_.RemoveObserver(observer);
183}
184
185void View::SetPainter(Painter* painter) {
186  painter_.reset(painter);
187}
188
189void View::SetLayout(Layout* layout) {
190  layout_.reset(layout);
191}
192
193// Disposition -----------------------------------------------------------------
194
195void 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
209void 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
228void 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
236void View::RemoveChild(View* child) {
237  DCHECK_EQ(this, child->parent());
238  ScopedTreeNotifier(child, this, NULL);
239  RemoveChildImpl(child, &children_);
240}
241
242bool 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
250void View::StackChildAtTop(View* child) {
251  if (children_.size() <= 1 || child == children_.back())
252    return;  // On top already.
253  StackChildAbove(child, children_.back());
254}
255
256void View::StackChildAtBottom(View* child) {
257  if (children_.size() <= 1 || child == children_.front())
258    return;  // On bottom already.
259  StackChildBelow(child, children_.front());
260}
261
262void View::StackChildAbove(View* child, View* other) {
263  StackChildRelativeTo(this, &children_, child, other, STACK_ABOVE);
264}
265
266void View::StackChildBelow(View* child, View* other) {
267  StackChildRelativeTo(this, &children_, child, other, STACK_BELOW);
268}
269
270// Layer -----------------------------------------------------------------------
271
272const ui::Layer* View::layer() const {
273  return layer_owner_.get() ? layer_owner_->layer() : NULL;
274}
275
276ui::Layer* View::layer() {
277  return const_cast<ui::Layer*>(const_cast<const View*>(this)->layer());
278}
279
280bool View::HasLayer() const {
281  return !!layer();
282}
283
284void 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
292void View::DestroyLayer() {
293  DCHECK(layer_owner_.get());
294  layer_owner_.reset();
295}
296
297ui::Layer* View::AcquireLayer() {
298  DCHECK(layer_owner_.get());
299  return layer_owner_->AcquireLayer();
300}
301
302}  // namespace v2
303