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
12 namespace {
13
14 const int kDefaultTransitionDurationMs = 200;
15
16 } // namespace
17
18 namespace ui {
19
20 // InvertingObserver -----------------------------------------------------------
21 class InvertingObserver : public ImplicitAnimationObserver {
22 public:
InvertingObserver()23 InvertingObserver()
24 : base_layer_(NULL) {
25 }
26
~InvertingObserver()27 virtual ~InvertingObserver() {}
28
SetLayer(Layer * base_layer)29 void SetLayer(Layer* base_layer) { base_layer_ = base_layer; }
30
layer()31 Layer* layer() { return base_layer_; }
32
AddInverselyAnimatedLayer(Layer * inverse_layer)33 void AddInverselyAnimatedLayer(Layer* inverse_layer) {
34 inverse_layers_.push_back(inverse_layer);
35 }
36
OnImplicitAnimationsCompleted()37 virtual void OnImplicitAnimationsCompleted() OVERRIDE {}
38
OnLayerAnimationScheduled(LayerAnimationSequence * sequence)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:
GetInverseElement(LayerAnimationSequence * sequence,gfx::Transform base) const56 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 DCHECK_EQ(static_cast<LayerAnimationElement::AnimatableProperties>(
65 LayerAnimationElement::TRANSFORM),
66 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 // ScopedLayerAnimationSettings ------------------------------------------------
ScopedLayerAnimationSettings(scoped_refptr<LayerAnimator> animator)81 ScopedLayerAnimationSettings::ScopedLayerAnimationSettings(
82 scoped_refptr<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
~ScopedLayerAnimationSettings()94 ScopedLayerAnimationSettings::~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
AddObserver(ImplicitAnimationObserver * observer)112 void ScopedLayerAnimationSettings::AddObserver(
113 ImplicitAnimationObserver* observer) {
114 observers_.insert(observer);
115 animator_->AddObserver(observer);
116 }
117
SetTransitionDuration(base::TimeDelta duration)118 void ScopedLayerAnimationSettings::SetTransitionDuration(
119 base::TimeDelta duration) {
120 animator_->SetTransitionDuration(duration);
121 }
122
LockTransitionDuration()123 void ScopedLayerAnimationSettings::LockTransitionDuration() {
124 animator_->is_transition_duration_locked_ = true;
125 }
126
GetTransitionDuration() const127 base::TimeDelta ScopedLayerAnimationSettings::GetTransitionDuration() const {
128 return animator_->GetTransitionDuration();
129 }
130
SetTweenType(gfx::Tween::Type tween_type)131 void ScopedLayerAnimationSettings::SetTweenType(gfx::Tween::Type tween_type) {
132 animator_->set_tween_type(tween_type);
133 }
134
GetTweenType() const135 gfx::Tween::Type ScopedLayerAnimationSettings::GetTweenType() const {
136 return animator_->tween_type();
137 }
138
SetPreemptionStrategy(LayerAnimator::PreemptionStrategy strategy)139 void ScopedLayerAnimationSettings::SetPreemptionStrategy(
140 LayerAnimator::PreemptionStrategy strategy) {
141 animator_->set_preemption_strategy(strategy);
142 }
143
144 LayerAnimator::PreemptionStrategy
GetPreemptionStrategy() const145 ScopedLayerAnimationSettings::GetPreemptionStrategy() const {
146 return animator_->preemption_strategy();
147 }
148
SetInverselyAnimatedBaseLayer(Layer * base)149 void 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
AddInverselyAnimatedLayer(Layer * inverse_layer)158 void ScopedLayerAnimationSettings::AddInverselyAnimatedLayer(
159 Layer* inverse_layer) {
160 inverse_observer_->AddInverselyAnimatedLayer(inverse_layer);
161 }
162
163 } // namespace ui
164