diff options
author | sky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-02-11 04:55:07 +0000 |
---|---|---|
committer | sky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-02-11 04:55:07 +0000 |
commit | 1b1be7c0dafd41d2d66a6c6ec1790a43b676c1b0 (patch) | |
tree | 020c667ccae41bf9fa5d4856d635d71ab440b8b7 /views | |
parent | e7a1258df3b509726bc4dffe2a520c6318d45af3 (diff) | |
download | chromium_src-1b1be7c0dafd41d2d66a6c6ec1790a43b676c1b0.zip chromium_src-1b1be7c0dafd41d2d66a6c6ec1790a43b676c1b0.tar.gz chromium_src-1b1be7c0dafd41d2d66a6c6ec1790a43b676c1b0.tar.bz2 |
Adds a simple class for animating a views bounds from one location to
another. This is just a starting point, I need to integrate a lot of
other things to make this really useful, but it's a start and
something I'm going to use for the login manager.
BUG=none
TEST=none
Review URL: http://codereview.chromium.org/593051
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@38742 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'views')
-rw-r--r-- | views/animation/bounds_animator.cc | 110 | ||||
-rw-r--r-- | views/animation/bounds_animator.h | 88 | ||||
-rw-r--r-- | views/views.gyp | 2 |
3 files changed, 200 insertions, 0 deletions
diff --git a/views/animation/bounds_animator.cc b/views/animation/bounds_animator.cc new file mode 100644 index 0000000..4ea34b0 --- /dev/null +++ b/views/animation/bounds_animator.cc @@ -0,0 +1,110 @@ +// Copyright (c) 2010 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 "views/animation/bounds_animator.h" + +#include "app/slide_animation.h" +#include "base/compiler_specific.h" +#include "views/view.h" + +namespace views { + +BoundsAnimator::BoundsAnimator() + : ALLOW_THIS_IN_INITIALIZER_LIST(animation_(new SlideAnimation(this))), + is_slide_(true) { +} + +BoundsAnimator::~BoundsAnimator() { + data_.clear(); + animation_->set_delegate(NULL); + animation_.reset(); +} + +void BoundsAnimator::AnimateViewTo(View* view, + const gfx::Rect& target, + bool delete_when_done) { + Data& data = data_[view]; + data.start_bounds = view->bounds(); + data.target_bounds = target; + data.delete_when_done = delete_when_done; +} + +bool BoundsAnimator::IsAnimating(View* view) const { + return data_.find(view) != data_.end(); +} + +void BoundsAnimator::Start() { + // Unset the delegate so that we don't attempt to cleanup if the animation is + // running and we cancel it. + animation_->set_delegate(NULL); + + animation_->Stop(); + + if (is_slide_) { + // TODO(sky): this is yucky, need a better way to express this. + static_cast<SlideAnimation*>(animation_.get())->Hide(); + static_cast<SlideAnimation*>(animation_.get())->Reset(); + static_cast<SlideAnimation*>(animation_.get())->Show(); + } else { + animation_->Start(); + } + + animation_->set_delegate(this); +} + +void BoundsAnimator::Stop() { + animation_->set_delegate(NULL); + animation_->Stop(); + animation_->set_delegate(this); + + DeleteViews(); + data_.clear(); +} + +void BoundsAnimator::SetAnimation(Animation* animation, bool is_slide) { + animation_.reset(animation); + is_slide_ = is_slide; +} + +void BoundsAnimator::AnimationProgressed(const Animation* animation) { + gfx::Rect repaint_bounds; + + for (ViewToDataMap::const_iterator i = data_.begin(); i != data_.end(); ++i) { + View* view = i->first; + gfx::Rect new_bounds = + animation_->CurrentValueBetween(i->second.start_bounds, + i->second.target_bounds); + if (new_bounds != view->bounds()) { + gfx::Rect total_bounds = new_bounds.Union(view->bounds()); + if (repaint_bounds.IsEmpty()) + repaint_bounds = total_bounds; + else + repaint_bounds = repaint_bounds.Union(total_bounds); + view->SetBounds(new_bounds); + } + } + + if (!data_.empty() && !repaint_bounds.IsEmpty()) + data_.begin()->first->GetParent()->SchedulePaint(repaint_bounds, false); +} + +void BoundsAnimator::AnimationEnded(const Animation* animation) { + DeleteViews(); +} + +void BoundsAnimator::AnimationCanceled(const Animation* animation) { +} + +void BoundsAnimator::DeleteViews() { + for (ViewToDataMap::iterator i = data_.begin(); i != data_.end(); ++i) { + if (i->second.delete_when_done) { + View* view = i->first; + view->GetParent()->RemoveChildView(view); + delete view; + } + } + data_.clear(); +} + +} // namespace views diff --git a/views/animation/bounds_animator.h b/views/animation/bounds_animator.h new file mode 100644 index 0000000..2882819 --- /dev/null +++ b/views/animation/bounds_animator.h @@ -0,0 +1,88 @@ +// Copyright (c) 2010 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 VIEWS_ANIMATION_BOUNDS_ANIMATOR_H_ +#define VIEWS_ANIMATION_BOUNDS_ANIMATOR_H_ + +#include <map> + +#include "app/animation.h" +#include "base/gfx/rect.h" +#include "base/scoped_ptr.h" + +namespace views { + +class View; + +// Bounds animator is responsible for animating the bounds of a view from the +// the views current location and size to a target position and size. To use +// BoundsAnimator invoke AnimateViewTo for the set of views you want to +// animate, followed by Start to start the animation. +class BoundsAnimator : public AnimationDelegate { + public: + BoundsAnimator(); + ~BoundsAnimator(); + + // Schedules |view| to animate from it's current bounds to |target|. If + // |delete_when_done| is true the view is deleted when the animation + // completes. Invoke Start to start the animation. + void AnimateViewTo(View* view, + const gfx::Rect& target, + bool delete_when_done); + + // Returns true if BoundsAnimator is animating the bounds of |view|. + bool IsAnimating(View* view) const; + + // Starts the animation. + void Start(); + + // Stops the animation. + void Stop(); + + // Sets the animation to use when animating changes. BoundsAnimator takes + // ownership of |animation|. Set |is_slide| to true if |animation| is a + // SlideAnimation. + void SetAnimation(Animation* animation, bool is_slide); + + // AnimationDelegate overrides. + virtual void AnimationProgressed(const Animation* animation); + virtual void AnimationEnded(const Animation* animation); + virtual void AnimationCanceled(const Animation* animation); + + private: + // Tracks data about the view being animated. + struct Data { + Data() : delete_when_done(false) {} + + // Should the view be deleted when done? + bool delete_when_done; + + // The initial bounds. + gfx::Rect start_bounds; + + // Target bounds. + gfx::Rect target_bounds; + }; + + typedef std::map<View*, Data> ViewToDataMap; + + // Empties data_, deleting any views that have been marked as needing to be + // deleted. + void DeleteViews(); + + // Mapes from view being animated to info about the view. + ViewToDataMap data_; + + // The animation. + scoped_ptr<Animation> animation_; + + // Is |animation_| a SlideAnimation? + bool is_slide_; + + DISALLOW_COPY_AND_ASSIGN(BoundsAnimator); +}; + +} // namespace views + +#endif // VIEWS_ANIMATION_BOUNDS_ANIMATOR_H_ diff --git a/views/views.gyp b/views/views.gyp index 144f17f..9888628 100644 --- a/views/views.gyp +++ b/views/views.gyp @@ -55,6 +55,8 @@ 'accessibility/view_accessibility.h', 'accessibility/view_accessibility_wrapper.cc', 'accessibility/view_accessibility_wrapper.h', + 'animation/bounds_animator.cc', + 'animation/bounds_animator.h', 'background.cc', 'background.h', 'border.cc', |