Home | History | Annotate | Download | only in src
      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 
     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 
     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 
     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 
     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 
     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:
     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 
    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:
    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 
    151 View::View() : visible_(true), owned_by_parent_(true), parent_(NULL) {
    152 }
    153 
    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 
    177 void View::AddObserver(ViewObserver* observer) {
    178   observers_.AddObserver(observer);
    179 }
    180 
    181 void View::RemoveObserver(ViewObserver* observer) {
    182   observers_.RemoveObserver(observer);
    183 }
    184 
    185 void View::SetPainter(Painter* painter) {
    186   painter_.reset(painter);
    187 }
    188 
    189 void View::SetLayout(Layout* layout) {
    190   layout_.reset(layout);
    191 }
    192 
    193 // Disposition -----------------------------------------------------------------
    194 
    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 
    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 
    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 
    236 void View::RemoveChild(View* child) {
    237   DCHECK_EQ(this, child->parent());
    238   ScopedTreeNotifier(child, this, NULL);
    239   RemoveChildImpl(child, &children_);
    240 }
    241 
    242 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 
    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 
    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 
    262 void View::StackChildAbove(View* child, View* other) {
    263   StackChildRelativeTo(this, &children_, child, other, STACK_ABOVE);
    264 }
    265 
    266 void View::StackChildBelow(View* child, View* other) {
    267   StackChildRelativeTo(this, &children_, child, other, STACK_BELOW);
    268 }
    269 
    270 // Layer -----------------------------------------------------------------------
    271 
    272 const ui::Layer* View::layer() const {
    273   return layer_owner_.get() ? layer_owner_->layer() : NULL;
    274 }
    275 
    276 ui::Layer* View::layer() {
    277   return const_cast<ui::Layer*>(const_cast<const View*>(this)->layer());
    278 }
    279 
    280 bool View::HasLayer() const {
    281   return !!layer();
    282 }
    283 
    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 
    292 void View::DestroyLayer() {
    293   DCHECK(layer_owner_.get());
    294   layer_owner_.reset();
    295 }
    296 
    297 ui::Layer* View::AcquireLayer() {
    298   DCHECK(layer_owner_.get());
    299   return layer_owner_->AcquireLayer();
    300 }
    301 
    302 }  // namespace v2
    303