summaryrefslogtreecommitdiffstats
path: root/ui/gfx/compositor
diff options
context:
space:
mode:
authorsky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-06-23 20:13:29 +0000
committersky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-06-23 20:13:29 +0000
commit710a98ded8a324b8ef534cd2ef9ad6735b1ee21c (patch)
tree4cedde4b490786bfabfc1b6554ac18f6d01d951b /ui/gfx/compositor
parentca16a471056aafcba594c5ed81ca7b8389efd43b (diff)
downloadchromium_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.gyp2
-rw-r--r--ui/gfx/compositor/layer_animator.cc175
-rw-r--r--ui/gfx/compositor/layer_animator.h115
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_