scoped_layer_animation_settings.cc revision a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7
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_is_transition_duration_locked_(
85          animator->is_transition_duration_locked_),
86      old_transition_duration_(animator->GetTransitionDuration()),
87      old_tween_type_(animator->tween_type()),
88      old_preemption_strategy_(animator->preemption_strategy()),
89      inverse_observer_(new InvertingObserver()) {
90  SetTransitionDuration(
91      base::TimeDelta::FromMilliseconds(kDefaultTransitionDurationMs));
92}
93
94ScopedLayerAnimationSettings::~ScopedLayerAnimationSettings() {
95  animator_->is_transition_duration_locked_ =
96      old_is_transition_duration_locked_;
97  animator_->SetTransitionDuration(old_transition_duration_);
98  animator_->set_tween_type(old_tween_type_);
99  animator_->set_preemption_strategy(old_preemption_strategy_);
100
101  for (std::set<ImplicitAnimationObserver*>::const_iterator i =
102       observers_.begin(); i != observers_.end(); ++i) {
103    animator_->observers_.RemoveObserver(*i);
104    (*i)->SetActive(true);
105  }
106
107  if (inverse_observer_->layer()) {
108    animator_->observers_.RemoveObserver(inverse_observer_.get());
109  }
110}
111
112void ScopedLayerAnimationSettings::AddObserver(
113    ImplicitAnimationObserver* observer) {
114  observers_.insert(observer);
115  animator_->AddObserver(observer);
116}
117
118void ScopedLayerAnimationSettings::SetTransitionDuration(
119    base::TimeDelta duration) {
120  animator_->SetTransitionDuration(duration);
121}
122
123void ScopedLayerAnimationSettings::LockTransitionDuration() {
124  animator_->is_transition_duration_locked_ = true;
125}
126
127base::TimeDelta ScopedLayerAnimationSettings::GetTransitionDuration() const {
128  return animator_->GetTransitionDuration();
129}
130
131void ScopedLayerAnimationSettings::SetTweenType(gfx::Tween::Type tween_type) {
132  animator_->set_tween_type(tween_type);
133}
134
135gfx::Tween::Type ScopedLayerAnimationSettings::GetTweenType() const {
136  return animator_->tween_type();
137}
138
139void ScopedLayerAnimationSettings::SetPreemptionStrategy(
140    LayerAnimator::PreemptionStrategy strategy) {
141  animator_->set_preemption_strategy(strategy);
142}
143
144LayerAnimator::PreemptionStrategy
145ScopedLayerAnimationSettings::GetPreemptionStrategy() const {
146  return animator_->preemption_strategy();
147}
148
149void ScopedLayerAnimationSettings::SetInverselyAnimatedBaseLayer(Layer* base) {
150  if (inverse_observer_->layer() && !base) {
151      animator_->RemoveObserver(inverse_observer_.get());
152  } else if (base && !(inverse_observer_->layer())) {
153      animator_->AddObserver(inverse_observer_.get());
154  }
155  inverse_observer_->SetLayer(base);
156}
157
158void ScopedLayerAnimationSettings::AddInverselyAnimatedLayer(
159    Layer* inverse_layer) {
160  inverse_observer_->AddInverselyAnimatedLayer(inverse_layer);
161}
162
163}  // namespace ui
164