summaryrefslogtreecommitdiff
path: root/chromium/ui/views/animation/bounds_animator.h
blob: c0a6501fc0d726204e0fa6b021d7e29dfc5eb5fe (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
// 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.

#ifndef UI_VIEWS_ANIMATION_BOUNDS_ANIMATOR_H_
#define UI_VIEWS_ANIMATION_BOUNDS_ANIMATOR_H_

#include <map>
#include <memory>

#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/observer_list.h"
#include "ui/gfx/animation/animation_container_observer.h"
#include "ui/gfx/animation/animation_delegate.h"
#include "ui/gfx/animation/tween.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/views/views_export.h"

namespace gfx {
class SlideAnimation;
}

namespace views {

class BoundsAnimatorObserver;
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.
//
// BoundsAnimator internally creates an animation for each view. If you need
// a specific animation invoke SetAnimationForView after invoking AnimateViewTo.
// You can attach an AnimationDelegate to the individual animation for a view
// by way of SetAnimationDelegate. Additionally you can attach an observer to
// the BoundsAnimator that is notified when all animations are complete.
class VIEWS_EXPORT BoundsAnimator : public gfx::AnimationDelegate,
                                    public gfx::AnimationContainerObserver {
 public:
  explicit BoundsAnimator(View* view);
  ~BoundsAnimator() override;

  // Starts animating |view| from its current bounds to |target|. If there is
  // already an animation running for the view it's stopped and a new one
  // started. If an AnimationDelegate has been set for |view| it is removed
  // (after being notified that the animation was canceled).
  void AnimateViewTo(View* view, const gfx::Rect& target);

  // Similar to |AnimateViewTo|, but does not reset the animation, only the
  // target bounds. If |view| is not being animated this is the same as
  // invoking |AnimateViewTo|.
  void SetTargetBounds(View* view, const gfx::Rect& target);

  // Returns the target bounds for the specified view. If |view| is not
  // animating its current bounds is returned.
  gfx::Rect GetTargetBounds(const View* view) const;

  // Sets the animation for the specified view.
  void SetAnimationForView(View* view,
                           std::unique_ptr<gfx::SlideAnimation> animation);

  // Returns the animation for the specified view. BoundsAnimator owns the
  // returned Animation.
  const gfx::SlideAnimation* GetAnimationForView(View* view);

  // Stops animating the specified view.
  void StopAnimatingView(View* view);

  // Sets the delegate for the animation for the specified view.
  void SetAnimationDelegate(View* view,
                            std::unique_ptr<gfx::AnimationDelegate> delegate);

  // Returns true if BoundsAnimator is animating the bounds of |view|.
  bool IsAnimating(View* view) const;

  // Returns true if BoundsAnimator is animating any view.
  bool IsAnimating() const;

  // Cancels all animations, leaving the views at their current location and
  // size. Any views marked for deletion are deleted.
  void Cancel();

  // Overrides default animation duration. |duration_ms| is the new duration in
  // milliseconds.
  void SetAnimationDuration(int duration_ms);

  // Gets the currently used animation duration.
  int GetAnimationDuration() const { return animation_duration_ms_; }

  // Sets the tween type for new animations. Default is EASE_OUT.
  void set_tween_type(gfx::Tween::Type type) { tween_type_ = type; }

  void AddObserver(BoundsAnimatorObserver* observer);
  void RemoveObserver(BoundsAnimatorObserver* observer);

 protected:
  // Creates the animation to use for animating views.
  virtual std::unique_ptr<gfx::SlideAnimation> CreateAnimation();

 private:
  // Tracks data about the view being animated.
  struct Data {
    Data();
    Data(Data&&);
    Data& operator=(Data&&);
    ~Data();

    // The initial bounds.
    gfx::Rect start_bounds;

    // Target bounds.
    gfx::Rect target_bounds;

    // The animation.
    std::unique_ptr<gfx::SlideAnimation> animation;

    // Delegate for the animation, may be nullptr.
    std::unique_ptr<gfx::AnimationDelegate> delegate;
  };

  // Used by AnimationEndedOrCanceled.
  enum AnimationEndType {
    ANIMATION_ENDED,
    ANIMATION_CANCELED
  };

  typedef std::map<const View*, Data> ViewToDataMap;

  typedef std::map<const gfx::Animation*, View*> AnimationToViewMap;

  // Removes references to |view| and its animation. Returns the data for the
  // caller to handle cleanup.
  Data RemoveFromMaps(View* view);

  // Does the necessary cleanup for |data|. If |send_cancel| is true and a
  // delegate has been installed on |data| AnimationCanceled is invoked on it.
  void CleanupData(bool send_cancel, Data* data);

  // Used when changing the animation for a view. This resets the maps for
  // the animation used by view and returns the current animation. Ownership
  // of the returned animation passes to the caller.
  std::unique_ptr<gfx::Animation> ResetAnimationForView(View* view);

  // Invoked from AnimationEnded and AnimationCanceled.
  void AnimationEndedOrCanceled(const gfx::Animation* animation,
                                AnimationEndType type);

  // gfx::AnimationDelegate overrides.
  void AnimationProgressed(const gfx::Animation* animation) override;
  void AnimationEnded(const gfx::Animation* animation) override;
  void AnimationCanceled(const gfx::Animation* animation) override;

  // gfx::AnimationContainerObserver overrides.
  void AnimationContainerProgressed(
      gfx::AnimationContainer* container) override;
  void AnimationContainerEmpty(gfx::AnimationContainer* container) override;

  // Parent of all views being animated.
  View* parent_;

  base::ObserverList<BoundsAnimatorObserver> observers_;

  // All animations we create up with the same container.
  scoped_refptr<gfx::AnimationContainer> container_;

  // Maps from view being animated to info about the view.
  ViewToDataMap data_;

  // Maps from animation to view.
  AnimationToViewMap animation_to_view_;

  // As the animations we create update (AnimationProgressed is invoked) this
  // is updated. When all the animations have completed for a given tick of
  // the timer (AnimationContainerProgressed is invoked) the parent_ is asked
  // to repaint these bounds.
  gfx::Rect repaint_bounds_;

  int animation_duration_ms_ = 200;

  gfx::Tween::Type tween_type_ = gfx::Tween::EASE_OUT;

  DISALLOW_COPY_AND_ASSIGN(BoundsAnimator);
};

}  // namespace views

#endif  // UI_VIEWS_ANIMATION_BOUNDS_ANIMATOR_H_