diff options
author | sky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-06-23 20:13:29 +0000 |
---|---|---|
committer | sky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-06-23 20:13:29 +0000 |
commit | 710a98ded8a324b8ef534cd2ef9ad6735b1ee21c (patch) | |
tree | 4cedde4b490786bfabfc1b6554ac18f6d01d951b /ui/gfx/compositor | |
parent | ca16a471056aafcba594c5ed81ca7b8389efd43b (diff) | |
download | chromium_src-710a98ded8a324b8ef534cd2ef9ad6735b1ee21c.zip chromium_src-710a98ded8a324b8ef534cd2ef9ad6735b1ee21c.tar.gz chromium_src-710a98ded8a324b8ef534cd2ef9ad6735b1ee21c.tar.bz2 |
Adds the ability to animate transforms/bounds to View.
BUG=none
TEST=none
R=ben@chromium.org,wjmaclean@chromium.org
Review URL: http://codereview.chromium.org/7242005
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@90254 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui/gfx/compositor')
-rw-r--r-- | ui/gfx/compositor/compositor.gyp | 2 | ||||
-rw-r--r-- | ui/gfx/compositor/layer_animator.cc | 175 | ||||
-rw-r--r-- | ui/gfx/compositor/layer_animator.h | 115 |
3 files changed, 292 insertions, 0 deletions
diff --git a/ui/gfx/compositor/compositor.gyp b/ui/gfx/compositor/compositor.gyp index 4122f11..72fe768 100644 --- a/ui/gfx/compositor/compositor.gyp +++ b/ui/gfx/compositor/compositor.gyp @@ -33,6 +33,8 @@ 'compositor_win.cc', 'layer.cc', 'layer.h', + 'layer_animator.cc', + 'layer_animator.h', ], 'conditions': [ ['os_posix == 1 and OS != "mac"', { diff --git a/ui/gfx/compositor/layer_animator.cc b/ui/gfx/compositor/layer_animator.cc new file mode 100644 index 0000000..9122975 --- /dev/null +++ b/ui/gfx/compositor/layer_animator.cc @@ -0,0 +1,175 @@ +// Copyright (c) 2011 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/gfx/compositor/layer_animator.h" + +#include "base/logging.h" +#include "base/stl_util-inl.h" +#include "ui/base/animation/animation_container.h" +#include "ui/base/animation/multi_animation.h" +#include "ui/gfx/compositor/compositor.h" +#include "ui/gfx/compositor/layer.h" +#include "ui/gfx/transform.h" +#include "ui/gfx/rect.h" + +namespace ui { + +LayerAnimator::LayerAnimator(Layer* layer) + : layer_(layer), + duration_in_ms_(200), + animation_type_(ui::Tween::EASE_IN) { +} + +LayerAnimator::~LayerAnimator() { + for (Elements::iterator i = elements_.begin(); i != elements_.end(); ++i) + delete i->second.animation; + elements_.clear(); +} + +void LayerAnimator::SetAnimationDurationAndType(int duration, + ui::Tween::Type tween_type) { + DCHECK_GT(duration, 0); + duration_in_ms_ = duration; + animation_type_ = tween_type; +} + +void LayerAnimator::AnimateToPoint(const gfx::Point& target) { + StopAnimating(LOCATION); + const gfx::Rect& layer_bounds = layer_->bounds(); + if (target == layer_bounds.origin()) + return; // Already there. + + Element& element = elements_[LOCATION]; + element.params.location.start_x = layer_bounds.origin().x(); + element.params.location.start_y = layer_bounds.origin().y(); + element.params.location.target_x = target.x(); + element.params.location.target_y = target.y(); + element.animation = CreateAndStartAnimation(); +} + +void LayerAnimator::AnimateTransform(const Transform& transform) { + StopAnimating(TRANSFORM); + const Transform& layer_transform = layer_->transform(); + bool all_equal = true; + // TODO: replace with == when we Transform supports ==. + for (int i = 0; i < 9; ++i) { + if (transform.matrix()[i] != layer_transform.matrix()[i]) { + all_equal = false; + break; + } + } + if (all_equal) + return; // Already there. + + Element& element = elements_[TRANSFORM]; + for (int i = 0; i < 9; ++i) { + element.params.transform.start[i] = layer_transform.matrix()[i]; + element.params.transform.target[i] = transform.matrix()[i]; + } + element.animation = CreateAndStartAnimation(); +} + +void LayerAnimator::AnimationProgressed(const ui::Animation* animation) { + Elements::iterator e = GetElementByAnimation( + static_cast<const ui::MultiAnimation*>(animation)); + DCHECK(e != elements_.end()); + switch (e->first) { + case LOCATION: { + const gfx::Rect& current_bounds(layer_->bounds()); + gfx::Rect new_bounds = e->second.animation->CurrentValueBetween( + gfx::Rect(gfx::Point(e->second.params.location.start_x, + e->second.params.location.start_y), + current_bounds.size()), + gfx::Rect(gfx::Point(e->second.params.location.target_x, + e->second.params.location.target_y), + current_bounds.size())); + layer_->set_bounds(new_bounds); + break; + } + + case TRANSFORM: { + Transform transform; + for (int i = 0; i < 9; ++i) { + transform.matrix()[i] = e->second.animation->CurrentValueBetween( + e->second.params.transform.start[i], + e->second.params.transform.target[i]); + } + layer_->set_transform(transform); + break; + } + + default: + NOTREACHED(); + } + layer_->compositor()->SchedulePaint(); +} + +void LayerAnimator::AnimationEnded(const ui::Animation* animation) { + Elements::iterator e = GetElementByAnimation( + static_cast<const ui::MultiAnimation*>(animation)); + DCHECK(e != elements_.end()); + switch (e->first) { + case LOCATION: { + gfx::Rect new_bounds( + gfx::Point(e->second.params.location.target_x, + e->second.params.location.target_y), + layer_->bounds().size()); + layer_->set_bounds(new_bounds); + break; + } + + case TRANSFORM: { + Transform transform; + for (int i = 0; i < 9; ++i) + transform.matrix()[i] = e->second.params.transform.target[i]; + layer_->set_transform(transform); + break; + } + + default: + NOTREACHED(); + } + StopAnimating(e->first); + // StopAnimating removes from the map, invalidating 'e'. + e = elements_.end(); + layer_->compositor()->SchedulePaint(); +} + +void LayerAnimator::StopAnimating(AnimationProperty property) { + if (elements_.count(property) == 0) + return; + + // Reset the delegate so that we don't attempt to update the layer. + elements_[property].animation->set_delegate(NULL); + delete elements_[property].animation; + elements_.erase(property); +} + +ui::MultiAnimation* LayerAnimator::CreateAndStartAnimation() { + static ui::AnimationContainer* container = NULL; + if (!container) { + container = new AnimationContainer; + container->AddRef(); + } + ui::MultiAnimation::Parts parts; + parts.push_back(ui::MultiAnimation::Part(duration_in_ms_, animation_type_)); + ui::MultiAnimation* animation = new ui::MultiAnimation(parts); + animation->SetContainer(container); + animation->set_delegate(this); + animation->set_continuous(false); + animation->Start(); + return animation; +} + +LayerAnimator::Elements::iterator LayerAnimator::GetElementByAnimation( + const ui::MultiAnimation* animation) { + for (Elements::iterator i = elements_.begin(); i != elements_.end(); ++i) { + if (i->second.animation == animation) + return i; + } + NOTREACHED(); + return elements_.end(); +} + +} // namespace ui diff --git a/ui/gfx/compositor/layer_animator.h b/ui/gfx/compositor/layer_animator.h new file mode 100644 index 0000000..da86766 --- /dev/null +++ b/ui/gfx/compositor/layer_animator.h @@ -0,0 +1,115 @@ +// Copyright (c) 2011 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. + +#ifndef UI_GFX_COMPOSITOR_LAYER_ANIMATOR_H_ +#define UI_GFX_COMPOSITOR_LAYER_ANIMATOR_H_ +#pragma once + +#include <map> + +#include "base/basictypes.h" +#include "base/compiler_specific.h" +#include "third_party/skia/include/core/SkScalar.h" +#include "ui/base/animation/animation_delegate.h" +#include "ui/base/animation/tween.h" +#include "ui/gfx/point.h" + +namespace ui { + +class Layer; +class MultiAnimation; +class Transform; + +// LayerAnimator manages animating various properties of a Layer. +class LayerAnimator : public ui::AnimationDelegate { + public: + explicit LayerAnimator(Layer* layer); + virtual ~LayerAnimator(); + + ui::Layer* layer() { return layer_; } + + // Sets the duration (in ms) and type of animation. This does not effect + // existing animations, only newly created animations. + void SetAnimationDurationAndType(int duration, ui::Tween::Type tween_type); + + // Animates the layer to the specified point. The point is relative to the + // parent layer. + void AnimateToPoint(const gfx::Point& target); + void StopAnimatingToPoint() { + StopAnimating(LOCATION); + } + + // Animates the transform from from the current transform to |transform|. + void AnimateTransform(const Transform& transform); + void StopAnimatingTransform() { + StopAnimating(TRANSFORM); + } + + // AnimationDelegate: + virtual void AnimationProgressed(const Animation* animation) OVERRIDE; + virtual void AnimationEnded(const Animation* animation) OVERRIDE; + + private: + // Types of properties that can be animated. + enum AnimationProperty { + LOCATION, + TRANSFORM + }; + + // Parameters used when animating the location. + struct LocationParams { + int start_x; + int start_y; + int target_x; + int target_y; + }; + + // Parameters used whe animating the transform. + struct TransformParams { + // TODO: make 4x4 whe Transform is updated. + SkScalar start[9]; + SkScalar target[9]; + }; + + union Params { + LocationParams location; + TransformParams transform; + }; + + // Used for tracking the animation of a particular property. + struct Element { + Params params; + ui::MultiAnimation* animation; + }; + + typedef std::map<AnimationProperty, Element> Elements; + + // Stops animating the specified property. This does not set the property + // being animated to its final value. + void StopAnimating(AnimationProperty property); + + // Creates an animation. + ui::MultiAnimation* CreateAndStartAnimation(); + + // Returns an iterator into |elements_| that matches the specified animation. + Elements::iterator GetElementByAnimation(const ui::MultiAnimation* animation); + + // The layer. + Layer* layer_; + + // Properties being animated. + Elements elements_; + + // Duration in ms for newly created animations. + int duration_in_ms_; + + // Type of animation for newly created animations. + ui::Tween::Type animation_type_; + + DISALLOW_COPY_AND_ASSIGN(LayerAnimator); +}; + +} // namespace ui + +#endif // UI_GFX_COMPOSITOR_LAYER_ANIMATOR_H_ |