Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(379)

Side by Side Diff: views/animation/bounds_animator.cc

Issue 8572016: views: Move more two directories into ui/views/. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 9 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « views/animation/bounds_animator.h ('k') | views/animation/bounds_animator_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2011 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 #include "views/animation/bounds_animator.h"
6
7 #include "base/memory/scoped_ptr.h"
8 #include "ui/base/animation/animation_container.h"
9 #include "ui/base/animation/slide_animation.h"
10 #include "views/view.h"
11
12 // Duration in milliseconds for animations.
13 static const int kAnimationDuration = 200;
14
15 using ui::Animation;
16 using ui::AnimationContainer;
17 using ui::SlideAnimation;
18 using ui::Tween;
19
20 namespace views {
21
22 BoundsAnimator::BoundsAnimator(View* parent)
23 : parent_(parent),
24 observer_(NULL),
25 container_(new AnimationContainer()) {
26 container_->set_observer(this);
27 }
28
29 BoundsAnimator::~BoundsAnimator() {
30 // Reset the delegate so that we don't attempt to notify our observer from
31 // the destructor.
32 container_->set_observer(NULL);
33
34 // Delete all the animations, but don't remove any child views. We assume the
35 // view owns us and is going to be deleted anyway.
36 for (ViewToDataMap::iterator i = data_.begin(); i != data_.end(); ++i)
37 CleanupData(false, &(i->second), i->first);
38 }
39
40 void BoundsAnimator::AnimateViewTo(View* view, const gfx::Rect& target) {
41 DCHECK(view);
42 DCHECK_EQ(view->parent(), parent_);
43
44 Data existing_data;
45
46 if (IsAnimating(view)) {
47 // Don't immediatly delete the animation, that might trigger a callback from
48 // the animationcontainer.
49 existing_data = data_[view];
50
51 RemoveFromMaps(view);
52 }
53
54 // NOTE: we don't check if the view is already at the target location. Doing
55 // so leads to odd cases where no animations may be present after invoking
56 // AnimateViewTo. AnimationProgressed does nothing when the bounds of the
57 // view don't change.
58
59 Data& data = data_[view];
60 data.start_bounds = view->bounds();
61 data.target_bounds = target;
62 data.animation = CreateAnimation();
63
64 animation_to_view_[data.animation] = view;
65
66 data.animation->Show();
67
68 CleanupData(true, &existing_data, NULL);
69 }
70
71 void BoundsAnimator::SetTargetBounds(View* view, const gfx::Rect& target) {
72 if (!IsAnimating(view)) {
73 AnimateViewTo(view, target);
74 return;
75 }
76
77 data_[view].target_bounds = target;
78 }
79
80 void BoundsAnimator::SetAnimationForView(View* view,
81 SlideAnimation* animation) {
82 DCHECK(animation);
83
84 scoped_ptr<SlideAnimation> animation_wrapper(animation);
85
86 if (!IsAnimating(view))
87 return;
88
89 // We delay deleting the animation until the end so that we don't prematurely
90 // send out notification that we're done.
91 scoped_ptr<Animation> old_animation(ResetAnimationForView(view));
92
93 data_[view].animation = animation_wrapper.release();
94 animation_to_view_[animation] = view;
95
96 animation->set_delegate(this);
97 animation->SetContainer(container_.get());
98 animation->Show();
99 }
100
101 const SlideAnimation* BoundsAnimator::GetAnimationForView(View* view) {
102 return !IsAnimating(view) ? NULL : data_[view].animation;
103 }
104
105 void BoundsAnimator::SetAnimationDelegate(View* view,
106 AnimationDelegate* delegate,
107 bool delete_when_done) {
108 DCHECK(IsAnimating(view));
109
110 data_[view].delegate = delegate;
111 data_[view].delete_delegate_when_done = delete_when_done;
112 }
113
114 void BoundsAnimator::StopAnimatingView(View* view) {
115 if (!IsAnimating(view))
116 return;
117
118 data_[view].animation->Stop();
119 }
120
121 bool BoundsAnimator::IsAnimating(View* view) const {
122 return data_.find(view) != data_.end();
123 }
124
125 bool BoundsAnimator::IsAnimating() const {
126 return !data_.empty();
127 }
128
129 void BoundsAnimator::Cancel() {
130 if (data_.empty())
131 return;
132
133 while (!data_.empty())
134 data_.begin()->second.animation->Stop();
135
136 // Invoke AnimationContainerProgressed to force a repaint and notify delegate.
137 AnimationContainerProgressed(container_.get());
138 }
139
140 SlideAnimation* BoundsAnimator::CreateAnimation() {
141 SlideAnimation* animation = new SlideAnimation(this);
142 animation->SetContainer(container_.get());
143 animation->SetSlideDuration(kAnimationDuration);
144 animation->SetTweenType(Tween::EASE_OUT);
145 return animation;
146 }
147
148 void BoundsAnimator::RemoveFromMaps(View* view) {
149 DCHECK(data_.count(view) > 0);
150 DCHECK(animation_to_view_.count(data_[view].animation) > 0);
151
152 animation_to_view_.erase(data_[view].animation);
153 data_.erase(view);
154 }
155
156 void BoundsAnimator::CleanupData(bool send_cancel, Data* data, View* view) {
157 if (send_cancel && data->delegate)
158 data->delegate->AnimationCanceled(data->animation);
159
160 if (data->delete_delegate_when_done) {
161 delete static_cast<OwnedAnimationDelegate*>(data->delegate);
162 data->delegate = NULL;
163 }
164
165 if (data->animation) {
166 data->animation->set_delegate(NULL);
167 delete data->animation;
168 data->animation = NULL;
169 }
170 }
171
172 Animation* BoundsAnimator::ResetAnimationForView(View* view) {
173 if (!IsAnimating(view))
174 return NULL;
175
176 Animation* old_animation = data_[view].animation;
177 animation_to_view_.erase(old_animation);
178 data_[view].animation = NULL;
179 // Reset the delegate so that we don't attempt any processing when the
180 // animation calls us back.
181 old_animation->set_delegate(NULL);
182 return old_animation;
183 }
184
185 void BoundsAnimator::AnimationEndedOrCanceled(const Animation* animation,
186 AnimationEndType type) {
187 DCHECK(animation_to_view_.find(animation) != animation_to_view_.end());
188
189 View* view = animation_to_view_[animation];
190 DCHECK(view);
191
192 // Make a copy of the data as Remove empties out the maps.
193 Data data = data_[view];
194
195 RemoveFromMaps(view);
196
197 if (data.delegate) {
198 if (type == ANIMATION_ENDED) {
199 data.delegate->AnimationEnded(animation);
200 } else {
201 DCHECK_EQ(ANIMATION_CANCELED, type);
202 data.delegate->AnimationCanceled(animation);
203 }
204 }
205
206 CleanupData(false, &data, view);
207 }
208
209 void BoundsAnimator::AnimationProgressed(const Animation* animation) {
210 DCHECK(animation_to_view_.find(animation) != animation_to_view_.end());
211
212 View* view = animation_to_view_[animation];
213 DCHECK(view);
214 const Data& data = data_[view];
215 gfx::Rect new_bounds =
216 animation->CurrentValueBetween(data.start_bounds, data.target_bounds);
217 if (new_bounds != view->bounds()) {
218 gfx::Rect total_bounds = new_bounds.Union(view->bounds());
219
220 // Build up the region to repaint in repaint_bounds_. We'll do the repaint
221 // when all animations complete (in AnimationContainerProgressed).
222 if (repaint_bounds_.IsEmpty())
223 repaint_bounds_ = total_bounds;
224 else
225 repaint_bounds_ = repaint_bounds_.Union(total_bounds);
226
227 view->SetBoundsRect(new_bounds);
228 }
229
230 if (data.delegate)
231 data.delegate->AnimationProgressed(animation);
232 }
233
234 void BoundsAnimator::AnimationEnded(const Animation* animation) {
235 AnimationEndedOrCanceled(animation, ANIMATION_ENDED);
236 }
237
238 void BoundsAnimator::AnimationCanceled(const Animation* animation) {
239 AnimationEndedOrCanceled(animation, ANIMATION_CANCELED);
240 }
241
242 void BoundsAnimator::AnimationContainerProgressed(
243 AnimationContainer* container) {
244 if (!repaint_bounds_.IsEmpty()) {
245 // Adjust for rtl.
246 repaint_bounds_.set_x(parent_->GetMirroredXWithWidthInView(
247 repaint_bounds_.x(), repaint_bounds_.width()));
248 parent_->SchedulePaintInRect(repaint_bounds_);
249 repaint_bounds_.SetRect(0, 0, 0, 0);
250 }
251
252 if (observer_ && !IsAnimating()) {
253 // Notify here rather than from AnimationXXX to avoid deleting the animation
254 // while the animation is calling us.
255 observer_->OnBoundsAnimatorDone(this);
256 }
257 }
258
259 void BoundsAnimator::AnimationContainerEmpty(AnimationContainer* container) {
260 }
261
262 } // namespace views
OLDNEW
« no previous file with comments | « views/animation/bounds_animator.h ('k') | views/animation/bounds_animator_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698