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#ifndef UI_VIEWS_ANIMATION_BOUNDS_ANIMATOR_H_
6#define UI_VIEWS_ANIMATION_BOUNDS_ANIMATOR_H_
7
8#include <map>
9
10#include "base/compiler_specific.h"
11#include "base/memory/ref_counted.h"
12#include "base/observer_list.h"
13#include "ui/gfx/animation/animation_container_observer.h"
14#include "ui/gfx/animation/animation_delegate.h"
15#include "ui/gfx/animation/tween.h"
16#include "ui/gfx/rect.h"
17#include "ui/views/views_export.h"
18
19namespace gfx {
20class SlideAnimation;
21}
22
23namespace views {
24
25class BoundsAnimatorObserver;
26class View;
27
28// Bounds animator is responsible for animating the bounds of a view from the
29// the views current location and size to a target position and size. To use
30// BoundsAnimator invoke AnimateViewTo for the set of views you want to
31// animate.
32//
33// BoundsAnimator internally creates an animation for each view. If you need
34// a specific animation invoke SetAnimationForView after invoking AnimateViewTo.
35// You can attach an AnimationDelegate to the individual animation for a view
36// by way of SetAnimationDelegate. Additionally you can attach an observer to
37// the BoundsAnimator that is notified when all animations are complete.
38class VIEWS_EXPORT BoundsAnimator : public gfx::AnimationDelegate,
39                                    public gfx::AnimationContainerObserver {
40 public:
41  explicit BoundsAnimator(View* view);
42  virtual ~BoundsAnimator();
43
44  // Starts animating |view| from its current bounds to |target|. If there is
45  // already an animation running for the view it's stopped and a new one
46  // started. If an AnimationDelegate has been set for |view| it is removed
47  // (after being notified that the animation was canceled).
48  void AnimateViewTo(View* view, const gfx::Rect& target);
49
50  // Similar to |AnimateViewTo|, but does not reset the animation, only the
51  // target bounds. If |view| is not being animated this is the same as
52  // invoking |AnimateViewTo|.
53  void SetTargetBounds(View* view, const gfx::Rect& target);
54
55  // Returns the target bounds for the specified view. If |view| is not
56  // animating its current bounds is returned.
57  gfx::Rect GetTargetBounds(View* view);
58
59  // Sets the animation for the specified view. BoundsAnimator takes ownership
60  // of the specified animation.
61  void SetAnimationForView(View* view, gfx::SlideAnimation* animation);
62
63  // Returns the animation for the specified view. BoundsAnimator owns the
64  // returned Animation.
65  const gfx::SlideAnimation* GetAnimationForView(View* view);
66
67  // Stops animating the specified view.
68  void StopAnimatingView(View* view);
69
70  // Sets the delegate for the animation for the specified view.
71  void SetAnimationDelegate(View* view,
72                            scoped_ptr<gfx::AnimationDelegate> delegate);
73
74  // Returns true if BoundsAnimator is animating the bounds of |view|.
75  bool IsAnimating(View* view) const;
76
77  // Returns true if BoundsAnimator is animating any view.
78  bool IsAnimating() const;
79
80  // Cancels all animations, leaving the views at their current location and
81  // size. Any views marked for deletion are deleted.
82  void Cancel();
83
84  // Overrides default animation duration. |duration_ms| is the new duration in
85  // milliseconds.
86  void SetAnimationDuration(int duration_ms);
87
88  // Gets the currently used animation duration.
89  int GetAnimationDuration() const { return animation_duration_ms_; }
90
91  // Sets the tween type for new animations. Default is EASE_OUT.
92  void set_tween_type(gfx::Tween::Type type) { tween_type_ = type; }
93
94  void AddObserver(BoundsAnimatorObserver* observer);
95  void RemoveObserver(BoundsAnimatorObserver* observer);
96
97 protected:
98  // Creates the animation to use for animating views.
99  virtual gfx::SlideAnimation* CreateAnimation();
100
101 private:
102  // Tracks data about the view being animated.
103  struct Data {
104    Data() : animation(NULL), delegate(NULL) {}
105
106    // The initial bounds.
107    gfx::Rect start_bounds;
108
109    // Target bounds.
110    gfx::Rect target_bounds;
111
112    // The animation. We own this.
113    gfx::SlideAnimation* animation;
114
115    // Delegate for the animation, may be null. We own this.
116    gfx::AnimationDelegate* delegate;
117  };
118
119  // Used by AnimationEndedOrCanceled.
120  enum AnimationEndType {
121    ANIMATION_ENDED,
122    ANIMATION_CANCELED
123  };
124
125  typedef std::map<View*, Data> ViewToDataMap;
126
127  typedef std::map<const gfx::Animation*, View*> AnimationToViewMap;
128
129  // Removes references to |view| and its animation. This does NOT delete the
130  // animation or delegate.
131  void RemoveFromMaps(View* view);
132
133  // Does the necessary cleanup for |data|. If |send_cancel| is true and a
134  // delegate has been installed on |data| AnimationCanceled is invoked on it.
135  void CleanupData(bool send_cancel, Data* data, View* view);
136
137  // Used when changing the animation for a view. This resets the maps for
138  // the animation used by view and returns the current animation. Ownership
139  // of the returned animation passes to the caller.
140  gfx::Animation* ResetAnimationForView(View* view);
141
142  // Invoked from AnimationEnded and AnimationCanceled.
143  void AnimationEndedOrCanceled(const gfx::Animation* animation,
144                                AnimationEndType type);
145
146  // gfx::AnimationDelegate overrides.
147  virtual void AnimationProgressed(const gfx::Animation* animation) OVERRIDE;
148  virtual void AnimationEnded(const gfx::Animation* animation) OVERRIDE;
149  virtual void AnimationCanceled(const gfx::Animation* animation) OVERRIDE;
150
151  // gfx::AnimationContainerObserver overrides.
152  virtual void AnimationContainerProgressed(
153      gfx::AnimationContainer* container) OVERRIDE;
154  virtual void AnimationContainerEmpty(
155      gfx::AnimationContainer* container) OVERRIDE;
156
157  // Parent of all views being animated.
158  View* parent_;
159
160  ObserverList<BoundsAnimatorObserver> observers_;
161
162  // All animations we create up with the same container.
163  scoped_refptr<gfx::AnimationContainer> container_;
164
165  // Maps from view being animated to info about the view.
166  ViewToDataMap data_;
167
168  // Maps from animation to view.
169  AnimationToViewMap animation_to_view_;
170
171  // As the animations we create update (AnimationProgressed is invoked) this
172  // is updated. When all the animations have completed for a given tick of
173  // the timer (AnimationContainerProgressed is invoked) the parent_ is asked
174  // to repaint these bounds.
175  gfx::Rect repaint_bounds_;
176
177  int animation_duration_ms_;
178
179  gfx::Tween::Type tween_type_;
180
181  DISALLOW_COPY_AND_ASSIGN(BoundsAnimator);
182};
183
184}  // namespace views
185
186#endif  // UI_VIEWS_ANIMATION_BOUNDS_ANIMATOR_H_
187