scoped_layer_animation_settings.cc revision d0247b1b59f9c528cb6df88b4f2b9afaf80d181e
1// Copyright (c) 2012 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/compositor/scoped_layer_animation_settings.h"
6
7#include "ui/compositor/layer.h"
8#include "ui/compositor/layer_animation_observer.h"
9#include "ui/compositor/layer_animation_sequence.h"
10#include "ui/compositor/layer_animator.h"
11
12namespace {
13
14const int kDefaultTransitionDurationMs = 200;
15
16}  // namespace
17
18namespace ui {
19
20// InvertingObserver -----------------------------------------------------------
21class InvertingObserver : public ImplicitAnimationObserver {
22  public:
23    InvertingObserver()
24      : base_layer_(NULL) {
25    }
26
27    virtual ~InvertingObserver() {}
28
29    void SetLayer(Layer* base_layer) { base_layer_ = base_layer; }
30
31    Layer* layer() { return base_layer_; }
32
33    void AddInverselyAnimatedLayer(Layer* inverse_layer) {
34      inverse_layers_.push_back(inverse_layer);
35    }
36
37    virtual void OnImplicitAnimationsCompleted() OVERRIDE {}
38
39    virtual void OnLayerAnimationScheduled(
40        LayerAnimationSequence* sequence) OVERRIDE {
41      DCHECK(base_layer_  != NULL)
42        << "Must set base layer with ScopedLayerAnimationSettings::"
43        << "SetInverslyAnimatedBaseLayer";
44      gfx::Transform base_transform = base_layer_->transform();
45      scoped_ptr<LayerAnimationElement> inverse = GetInverseElement(sequence,
46          base_transform);
47
48      for (std::vector<Layer*>::const_iterator i =
49          inverse_layers_.begin(); i != inverse_layers_.end(); ++i) {
50        (*i)->GetAnimator()->StartAnimation(new LayerAnimationSequence(
51            LayerAnimationElement::CloneInverseTransformElement(
52                inverse.get())));
53      }
54    }
55  private:
56    scoped_ptr<LayerAnimationElement> GetInverseElement(
57        LayerAnimationSequence* sequence,
58        gfx::Transform base) const {
59      const size_t expected_size = 1;
60      DCHECK_EQ(expected_size, sequence->size()) <<
61        "Inverse supported only for single element sequences.";
62
63      LayerAnimationElement* element = sequence->FirstElement();
64      LayerAnimationElement::AnimatableProperties transform_property;
65      transform_property.insert(LayerAnimationElement::TRANSFORM);
66      DCHECK(transform_property == element->properties())
67        << "Only transform animations are currently invertible.";
68
69      scoped_ptr<LayerAnimationElement> to_return(
70          LayerAnimationElement::CreateInverseTransformElement(base, element));
71      return to_return.Pass();
72    }
73
74    Layer* base_layer_;
75    // child layers
76    std::vector<Layer*> inverse_layers_;
77};
78
79
80// ScoperLayerAnimationSettings ------------------------------------------------
81ScopedLayerAnimationSettings::ScopedLayerAnimationSettings(
82    LayerAnimator* animator)
83    : animator_(animator),
84      old_transition_duration_(animator->transition_duration_),
85      old_tween_type_(animator->tween_type()),
86      old_preemption_strategy_(animator->preemption_strategy()),
87      inverse_observer_(new InvertingObserver()) {
88  SetTransitionDuration(
89      base::TimeDelta::FromMilliseconds(kDefaultTransitionDurationMs));
90}
91
92ScopedLayerAnimationSettings::~ScopedLayerAnimationSettings() {
93  animator_->transition_duration_ = old_transition_duration_;
94  animator_->set_tween_type(old_tween_type_);
95  animator_->set_preemption_strategy(old_preemption_strategy_);
96
97  for (std::set<ImplicitAnimationObserver*>::const_iterator i =
98       observers_.begin(); i != observers_.end(); ++i) {
99    animator_->observers_.RemoveObserver(*i);
100    (*i)->SetActive(true);
101  }
102
103  if (inverse_observer_->layer()) {
104    animator_->observers_.RemoveObserver(inverse_observer_.get());
105  }
106}
107
108void ScopedLayerAnimationSettings::AddObserver(
109    ImplicitAnimationObserver* observer) {
110  observers_.insert(observer);
111  animator_->AddObserver(observer);
112}
113
114void ScopedLayerAnimationSettings::SetTransitionDuration(
115    base::TimeDelta duration) {
116  animator_->transition_duration_ = duration;
117}
118
119base::TimeDelta ScopedLayerAnimationSettings::GetTransitionDuration() const {
120  return animator_->transition_duration_;
121}
122
123void ScopedLayerAnimationSettings::SetTweenType(gfx::Tween::Type tween_type) {
124  animator_->set_tween_type(tween_type);
125}
126
127gfx::Tween::Type ScopedLayerAnimationSettings::GetTweenType() const {
128  return animator_->tween_type();
129}
130
131void ScopedLayerAnimationSettings::SetPreemptionStrategy(
132    LayerAnimator::PreemptionStrategy strategy) {
133  animator_->set_preemption_strategy(strategy);
134}
135
136LayerAnimator::PreemptionStrategy
137ScopedLayerAnimationSettings::GetPreemptionStrategy() const {
138  return animator_->preemption_strategy();
139}
140
141void ScopedLayerAnimationSettings::SetInverselyAnimatedBaseLayer(Layer* base) {
142  if (inverse_observer_->layer() && !base) {
143      animator_->RemoveObserver(inverse_observer_.get());
144  } else if (base && !(inverse_observer_->layer())) {
145      animator_->AddObserver(inverse_observer_.get());
146  }
147  inverse_observer_->SetLayer(base);
148}
149
150void ScopedLayerAnimationSettings::AddInverselyAnimatedLayer(
151    Layer* inverse_layer) {
152  inverse_observer_->AddInverselyAnimatedLayer(inverse_layer);
153}
154
155}  // namespace ui
156