| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "ui/compositor/scoped_layer_animation_settings.h" |
| |
| #include "ui/compositor/layer.h" |
| #include "ui/compositor/layer_animation_observer.h" |
| #include "ui/compositor/layer_animation_sequence.h" |
| #include "ui/compositor/layer_animator.h" |
| |
| namespace { |
| |
| const int kDefaultTransitionDurationMs = 200; |
| |
| } // namespace |
| |
| namespace ui { |
| |
| // InvertingObserver ----------------------------------------------------------- |
| class InvertingObserver : public ImplicitAnimationObserver { |
| public: |
| InvertingObserver() |
| : base_layer_(NULL) { |
| } |
| |
| ~InvertingObserver() override {} |
| |
| void SetLayer(Layer* base_layer) { base_layer_ = base_layer; } |
| |
| Layer* layer() { return base_layer_; } |
| |
| void AddInverselyAnimatedLayer(Layer* inverse_layer) { |
| inverse_layers_.push_back(inverse_layer); |
| } |
| |
| void OnImplicitAnimationsCompleted() override {} |
| |
| void OnLayerAnimationScheduled(LayerAnimationSequence* sequence) override { |
| DCHECK(base_layer_ != NULL) |
| << "Must set base layer with ScopedLayerAnimationSettings::" |
| << "SetInverslyAnimatedBaseLayer"; |
| gfx::Transform base_transform = base_layer_->transform(); |
| scoped_ptr<LayerAnimationElement> inverse = GetInverseElement(sequence, |
| base_transform); |
| |
| for (std::vector<Layer*>::const_iterator i = |
| inverse_layers_.begin(); i != inverse_layers_.end(); ++i) { |
| (*i)->GetAnimator()->StartAnimation(new LayerAnimationSequence( |
| LayerAnimationElement::CloneInverseTransformElement( |
| inverse.get()))); |
| } |
| } |
| private: |
| scoped_ptr<LayerAnimationElement> GetInverseElement( |
| LayerAnimationSequence* sequence, |
| gfx::Transform base) const { |
| const size_t expected_size = 1; |
| DCHECK_EQ(expected_size, sequence->size()) << |
| "Inverse supported only for single element sequences."; |
| |
| LayerAnimationElement* element = sequence->FirstElement(); |
| DCHECK_EQ(static_cast<LayerAnimationElement::AnimatableProperties>( |
| LayerAnimationElement::TRANSFORM), |
| element->properties()) |
| << "Only transform animations are currently invertible."; |
| |
| scoped_ptr<LayerAnimationElement> to_return( |
| LayerAnimationElement::CreateInverseTransformElement(base, element)); |
| return to_return.Pass(); |
| } |
| |
| Layer* base_layer_; |
| // child layers |
| std::vector<Layer*> inverse_layers_; |
| }; |
| |
| |
| // ScopedLayerAnimationSettings ------------------------------------------------ |
| ScopedLayerAnimationSettings::ScopedLayerAnimationSettings( |
| scoped_refptr<LayerAnimator> animator) |
| : animator_(animator), |
| old_is_transition_duration_locked_( |
| animator->is_transition_duration_locked_), |
| old_transition_duration_(animator->GetTransitionDuration()), |
| old_tween_type_(animator->tween_type()), |
| old_preemption_strategy_(animator->preemption_strategy()), |
| inverse_observer_(new InvertingObserver()) { |
| SetTransitionDuration( |
| base::TimeDelta::FromMilliseconds(kDefaultTransitionDurationMs)); |
| } |
| |
| ScopedLayerAnimationSettings::~ScopedLayerAnimationSettings() { |
| animator_->is_transition_duration_locked_ = |
| old_is_transition_duration_locked_; |
| animator_->SetTransitionDuration(old_transition_duration_); |
| animator_->set_tween_type(old_tween_type_); |
| animator_->set_preemption_strategy(old_preemption_strategy_); |
| |
| for (std::set<ImplicitAnimationObserver*>::const_iterator i = |
| observers_.begin(); i != observers_.end(); ++i) { |
| animator_->observers_.RemoveObserver(*i); |
| (*i)->SetActive(true); |
| } |
| |
| if (inverse_observer_->layer()) { |
| animator_->observers_.RemoveObserver(inverse_observer_.get()); |
| } |
| } |
| |
| void ScopedLayerAnimationSettings::AddObserver( |
| ImplicitAnimationObserver* observer) { |
| observers_.insert(observer); |
| animator_->AddObserver(observer); |
| } |
| |
| void ScopedLayerAnimationSettings::SetTransitionDuration( |
| base::TimeDelta duration) { |
| animator_->SetTransitionDuration(duration); |
| } |
| |
| void ScopedLayerAnimationSettings::LockTransitionDuration() { |
| animator_->is_transition_duration_locked_ = true; |
| } |
| |
| base::TimeDelta ScopedLayerAnimationSettings::GetTransitionDuration() const { |
| return animator_->GetTransitionDuration(); |
| } |
| |
| void ScopedLayerAnimationSettings::SetTweenType(gfx::Tween::Type tween_type) { |
| animator_->set_tween_type(tween_type); |
| } |
| |
| gfx::Tween::Type ScopedLayerAnimationSettings::GetTweenType() const { |
| return animator_->tween_type(); |
| } |
| |
| void ScopedLayerAnimationSettings::SetPreemptionStrategy( |
| LayerAnimator::PreemptionStrategy strategy) { |
| animator_->set_preemption_strategy(strategy); |
| } |
| |
| LayerAnimator::PreemptionStrategy |
| ScopedLayerAnimationSettings::GetPreemptionStrategy() const { |
| return animator_->preemption_strategy(); |
| } |
| |
| void ScopedLayerAnimationSettings::SetInverselyAnimatedBaseLayer(Layer* base) { |
| if (inverse_observer_->layer() && !base) { |
| animator_->RemoveObserver(inverse_observer_.get()); |
| } else if (base && !(inverse_observer_->layer())) { |
| animator_->AddObserver(inverse_observer_.get()); |
| } |
| inverse_observer_->SetLayer(base); |
| } |
| |
| void ScopedLayerAnimationSettings::AddInverselyAnimatedLayer( |
| Layer* inverse_layer) { |
| inverse_observer_->AddInverselyAnimatedLayer(inverse_layer); |
| } |
| |
| } // namespace ui |