blob: a0d904c30b8d44448fd71e93480b42b4c0dda6c9 [file] [log] [blame]
[email protected]b7a1b662012-01-18 14:12:181// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]710a98d2011-06-23 20:13:292// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]116302fc2012-05-05 21:45:415#include "ui/compositor/layer_animator.h"
[email protected]710a98d2011-06-23 20:13:296
[email protected]b4db9372011-10-24 14:44:197#include "base/debug/trace_event.h"
[email protected]710a98d2011-06-23 20:13:298#include "base/logging.h"
[email protected]b4db9372011-10-24 14:44:199#include "base/memory/scoped_ptr.h"
[email protected]710a98d2011-06-23 20:13:2910#include "ui/base/animation/animation_container.h"
[email protected]116302fc2012-05-05 21:45:4111#include "ui/compositor/compositor.h"
12#include "ui/compositor/layer.h"
13#include "ui/compositor/layer_animation_delegate.h"
14#include "ui/compositor/layer_animation_observer.h"
15#include "ui/compositor/layer_animation_sequence.h"
[email protected]0ed187e2011-10-21 20:07:4216
[email protected]21445e472011-10-21 20:36:3217namespace ui {
[email protected]0ed187e2011-10-21 20:07:4218
[email protected]b4db9372011-10-24 14:44:1919class LayerAnimator;
20
21namespace {
22
23static const base::TimeDelta kDefaultTransitionDuration =
[email protected]6e7c1562012-01-20 15:49:2424 base::TimeDelta::FromMilliseconds(120);
[email protected]b4db9372011-10-24 14:44:1925
26static const base::TimeDelta kTimerInterval =
27 base::TimeDelta::FromMilliseconds(10);
28
[email protected]9861f1752012-06-01 07:16:1429} // namespace
30
31// static
32bool LayerAnimator::disable_animations_for_test_ = false;
33// static
34bool LayerAnimator::slow_animation_mode_ = false;
[email protected]77ff4382012-06-25 23:20:4735// static
36int LayerAnimator::slow_animation_scale_factor_ = 4;
[email protected]b4db9372011-10-24 14:44:1937
38// LayerAnimator public --------------------------------------------------------
39
40LayerAnimator::LayerAnimator(base::TimeDelta transition_duration)
41 : delegate_(NULL),
42 preemption_strategy_(IMMEDIATELY_SET_NEW_TARGET),
43 transition_duration_(transition_duration),
[email protected]e4cbcc772012-03-07 18:59:3144 tween_type_(Tween::LINEAR),
[email protected]b4db9372011-10-24 14:44:1945 is_started_(false),
[email protected]aec12f822012-08-24 22:09:3546 disable_timer_for_test_(false) {
[email protected]710a98d2011-06-23 20:13:2947}
48
49LayerAnimator::~LayerAnimator() {
[email protected]0b3d7b62012-01-26 19:51:3050 for (size_t i = 0; i < running_animations_.size(); ++i)
51 running_animations_[i].sequence->OnAnimatorDestroyed();
[email protected]b4db9372011-10-24 14:44:1952 ClearAnimations();
[email protected]710a98d2011-06-23 20:13:2953}
54
[email protected]b4db9372011-10-24 14:44:1955// static
56LayerAnimator* LayerAnimator::CreateDefaultAnimator() {
57 return new LayerAnimator(base::TimeDelta::FromMilliseconds(0));
58}
59
60// static
61LayerAnimator* LayerAnimator::CreateImplicitAnimator() {
62 return new LayerAnimator(kDefaultTransitionDuration);
63}
64
65void LayerAnimator::SetTransform(const Transform& transform) {
[email protected]9861f1752012-06-01 07:16:1466 base::TimeDelta duration = GetTransitionDuration();
[email protected]e4cbcc772012-03-07 18:59:3167 scoped_ptr<LayerAnimationElement> element(
68 LayerAnimationElement::CreateTransformElement(transform, duration));
69 element->set_tween_type(tween_type_);
70 StartAnimation(new LayerAnimationSequence(element.release()));
[email protected]fe7074c62011-10-28 15:22:5471}
72
73Transform LayerAnimator::GetTargetTransform() const {
[email protected]f5cd9e52011-11-03 21:38:0874 LayerAnimationElement::TargetValue target(delegate());
[email protected]fe7074c62011-10-28 15:22:5475 GetTargetValue(&target);
76 return target.transform;
[email protected]b4db9372011-10-24 14:44:1977}
78
79void LayerAnimator::SetBounds(const gfx::Rect& bounds) {
[email protected]9861f1752012-06-01 07:16:1480 base::TimeDelta duration = GetTransitionDuration();
[email protected]e4cbcc772012-03-07 18:59:3181 scoped_ptr<LayerAnimationElement> element(
82 LayerAnimationElement::CreateBoundsElement(bounds, duration));
83 element->set_tween_type(tween_type_);
84 StartAnimation(new LayerAnimationSequence(element.release()));
[email protected]fe7074c62011-10-28 15:22:5485}
86
87gfx::Rect LayerAnimator::GetTargetBounds() const {
[email protected]f5cd9e52011-11-03 21:38:0888 LayerAnimationElement::TargetValue target(delegate());
[email protected]fe7074c62011-10-28 15:22:5489 GetTargetValue(&target);
90 return target.bounds;
[email protected]b4db9372011-10-24 14:44:1991}
92
93void LayerAnimator::SetOpacity(float opacity) {
[email protected]9861f1752012-06-01 07:16:1494 base::TimeDelta duration = GetTransitionDuration();
[email protected]e4cbcc772012-03-07 18:59:3195 scoped_ptr<LayerAnimationElement> element(
96 LayerAnimationElement::CreateOpacityElement(opacity, duration));
97 element->set_tween_type(tween_type_);
98 StartAnimation(new LayerAnimationSequence(element.release()));
[email protected]b4db9372011-10-24 14:44:1999}
100
[email protected]fe7074c62011-10-28 15:22:54101float LayerAnimator::GetTargetOpacity() const {
[email protected]f5cd9e52011-11-03 21:38:08102 LayerAnimationElement::TargetValue target(delegate());
[email protected]fe7074c62011-10-28 15:22:54103 GetTargetValue(&target);
104 return target.opacity;
105}
106
[email protected]a67935f2012-02-10 14:26:24107void LayerAnimator::SetVisibility(bool visibility) {
[email protected]9861f1752012-06-01 07:16:14108 base::TimeDelta duration = GetTransitionDuration();
[email protected]e4cbcc772012-03-07 18:59:31109
110 // Tween type doesn't matter for visibility.
[email protected]a67935f2012-02-10 14:26:24111 StartAnimation(new LayerAnimationSequence(
112 LayerAnimationElement::CreateVisibilityElement(
113 visibility, duration)));
114}
115
116bool LayerAnimator::GetTargetVisibility() const {
117 LayerAnimationElement::TargetValue target(delegate());
118 GetTargetValue(&target);
119 return target.visibility;
120}
121
[email protected]815d0c382012-07-21 08:13:44122void LayerAnimator::SetBrightness(float brightness) {
123 base::TimeDelta duration = GetTransitionDuration();
124 scoped_ptr<LayerAnimationElement> element(
125 LayerAnimationElement::CreateBrightnessElement(brightness, duration));
126 element->set_tween_type(tween_type_);
127 StartAnimation(new LayerAnimationSequence(element.release()));
128}
129
130float LayerAnimator::GetTargetBrightness() const {
131 LayerAnimationElement::TargetValue target(delegate());
132 GetTargetValue(&target);
133 return target.brightness;
134}
135
136void LayerAnimator::SetGrayscale(float grayscale) {
137 base::TimeDelta duration = GetTransitionDuration();
138 scoped_ptr<LayerAnimationElement> element(
139 LayerAnimationElement::CreateGrayscaleElement(grayscale, duration));
140 element->set_tween_type(tween_type_);
141 StartAnimation(new LayerAnimationSequence(element.release()));
142}
143
144float LayerAnimator::GetTargetGrayscale() const {
145 LayerAnimationElement::TargetValue target(delegate());
146 GetTargetValue(&target);
147 return target.grayscale;
148}
149
[email protected]e876c2712011-11-02 16:42:45150void LayerAnimator::SetDelegate(LayerAnimationDelegate* delegate) {
[email protected]b4db9372011-10-24 14:44:19151 DCHECK(delegate);
152 delegate_ = delegate;
153}
154
155void LayerAnimator::StartAnimation(LayerAnimationSequence* animation) {
[email protected]e876c2712011-11-02 16:42:45156 OnScheduled(animation);
[email protected]b4db9372011-10-24 14:44:19157 if (!StartSequenceImmediately(animation)) {
158 // Attempt to preempt a running animation.
159 switch (preemption_strategy_) {
160 case IMMEDIATELY_SET_NEW_TARGET:
161 ImmediatelySetNewTarget(animation);
162 break;
163 case IMMEDIATELY_ANIMATE_TO_NEW_TARGET:
164 ImmediatelyAnimateToNewTarget(animation);
165 break;
166 case ENQUEUE_NEW_ANIMATION:
167 EnqueueNewAnimation(animation);
168 break;
169 case REPLACE_QUEUED_ANIMATIONS:
170 ReplaceQueuedAnimations(animation);
171 break;
172 case BLEND_WITH_CURRENT_ANIMATION: {
173 // TODO(vollick) Add support for blended sequences and use them here.
174 NOTIMPLEMENTED();
175 break;
176 }
[email protected]7fca53d42011-09-29 15:38:12177 }
[email protected]b4db9372011-10-24 14:44:19178 }
179 FinishAnyAnimationWithZeroDuration();
[email protected]fe7074c62011-10-28 15:22:54180 UpdateAnimationState();
[email protected]b4db9372011-10-24 14:44:19181}
182
183void LayerAnimator::ScheduleAnimation(LayerAnimationSequence* animation) {
[email protected]e876c2712011-11-02 16:42:45184 OnScheduled(animation);
[email protected]b4db9372011-10-24 14:44:19185 if (is_animating()) {
186 animation_queue_.push_back(make_linked_ptr(animation));
187 ProcessQueue();
188 } else {
189 StartSequenceImmediately(animation);
[email protected]7fca53d42011-09-29 15:38:12190 }
[email protected]fe7074c62011-10-28 15:22:54191 UpdateAnimationState();
[email protected]710a98d2011-06-23 20:13:29192}
193
[email protected]b4db9372011-10-24 14:44:19194void LayerAnimator::ScheduleTogether(
195 const std::vector<LayerAnimationSequence*>& animations) {
196 // Collect all the affected properties.
197 LayerAnimationElement::AnimatableProperties animated_properties;
198 std::vector<LayerAnimationSequence*>::const_iterator iter;
199 for (iter = animations.begin(); iter != animations.end(); ++iter) {
200 animated_properties.insert((*iter)->properties().begin(),
201 (*iter)->properties().end());
202 }
[email protected]710a98d2011-06-23 20:13:29203
[email protected]b4db9372011-10-24 14:44:19204 // Scheduling a zero duration pause that affects all the animated properties
205 // will prevent any of the sequences from animating until there are no
206 // running animations that affect any of these properties.
[email protected]e4cbcc772012-03-07 18:59:31207 ScheduleAnimation(new LayerAnimationSequence(
208 LayerAnimationElement::CreatePauseElement(animated_properties,
209 base::TimeDelta())));
[email protected]710a98d2011-06-23 20:13:29210
[email protected]b4db9372011-10-24 14:44:19211 // These animations (provided they don't animate any common properties) will
212 // now animate together if trivially scheduled.
213 for (iter = animations.begin(); iter != animations.end(); ++iter) {
214 ScheduleAnimation(*iter);
[email protected]710a98d2011-06-23 20:13:29215 }
[email protected]fe7074c62011-10-28 15:22:54216
217 UpdateAnimationState();
218}
219
[email protected]e876c2712011-11-02 16:42:45220bool LayerAnimator::IsAnimatingProperty(
221 LayerAnimationElement::AnimatableProperty property) const {
222 for (AnimationQueue::const_iterator queue_iter = animation_queue_.begin();
223 queue_iter != animation_queue_.end(); ++queue_iter) {
224 if ((*queue_iter)->properties().find(property) !=
225 (*queue_iter)->properties().end()) {
226 return true;
227 }
228 }
229 return false;
[email protected]7fca53d42011-09-29 15:38:12230}
231
[email protected]b4db9372011-10-24 14:44:19232void LayerAnimator::StopAnimatingProperty(
233 LayerAnimationElement::AnimatableProperty property) {
234 while (true) {
235 RunningAnimation* running = GetRunningAnimation(property);
236 if (!running)
237 break;
238 FinishAnimation(running->sequence);
239 }
240}
241
242void LayerAnimator::StopAnimating() {
243 while (is_animating())
244 FinishAnimation(running_animations_[0].sequence);
245}
246
[email protected]e876c2712011-11-02 16:42:45247void LayerAnimator::AddObserver(LayerAnimationObserver* observer) {
248 if (!observers_.HasObserver(observer))
249 observers_.AddObserver(observer);
250}
251
252void LayerAnimator::RemoveObserver(LayerAnimationObserver* observer) {
253 observers_.RemoveObserver(observer);
[email protected]5cc8538d2011-11-07 15:24:54254 // Remove the observer from all sequences as well.
255 for (AnimationQueue::iterator queue_iter = animation_queue_.begin();
256 queue_iter != animation_queue_.end(); ++queue_iter) {
257 (*queue_iter)->RemoveObserver(observer);
258 }
[email protected]e876c2712011-11-02 16:42:45259}
260
[email protected]d59a3692012-04-10 20:27:31261// LayerAnimator protected -----------------------------------------------------
262
263bool LayerAnimator::ProgressAnimation(LayerAnimationSequence* sequence,
264 base::TimeDelta delta) {
265 return sequence->Progress(delta, delegate());
266}
267
268
269bool LayerAnimator::HasAnimation(LayerAnimationSequence* sequence) const {
270 for (AnimationQueue::const_iterator queue_iter = animation_queue_.begin();
271 queue_iter != animation_queue_.end(); ++queue_iter) {
272 if ((*queue_iter).get() == sequence)
273 return true;
274 }
275 return false;
276}
277
[email protected]b4db9372011-10-24 14:44:19278// LayerAnimator private -------------------------------------------------------
279
280void LayerAnimator::Step(base::TimeTicks now) {
[email protected]e4cbcc772012-03-07 18:59:31281 TRACE_EVENT0("ui", "LayerAnimator::Step");
282
[email protected]b4db9372011-10-24 14:44:19283 last_step_time_ = now;
[email protected]f5cd9e52011-11-03 21:38:08284 // We need to make a copy of the running animations because progressing them
285 // and finishing them may indirectly affect the collection of running
286 // animations.
287 RunningAnimations running_animations_copy = running_animations_;
[email protected]e4cbcc772012-03-07 18:59:31288 bool needs_redraw = false;
[email protected]f5cd9e52011-11-03 21:38:08289 for (size_t i = 0; i < running_animations_copy.size(); ++i) {
[email protected]d59a3692012-04-10 20:27:31290 if (!HasAnimation(running_animations_copy[i].sequence))
291 continue;
292
[email protected]f5cd9e52011-11-03 21:38:08293 base::TimeDelta delta = now - running_animations_copy[i].start_time;
294 if (delta >= running_animations_copy[i].sequence->duration() &&
295 !running_animations_copy[i].sequence->is_cyclic()) {
296 FinishAnimation(running_animations_copy[i].sequence);
[email protected]aec12f822012-08-24 22:09:35297 } else if (ProgressAnimation(running_animations_copy[i].sequence, delta))
[email protected]d59a3692012-04-10 20:27:31298 needs_redraw = true;
[email protected]b4db9372011-10-24 14:44:19299 }
[email protected]e4cbcc772012-03-07 18:59:31300
[email protected]a4234d92012-07-17 14:38:27301 if (needs_redraw && delegate())
[email protected]e4cbcc772012-03-07 18:59:31302 delegate()->ScheduleDrawForAnimation();
[email protected]b4db9372011-10-24 14:44:19303}
304
305void LayerAnimator::SetStartTime(base::TimeTicks start_time) {
[email protected]f5cd9e52011-11-03 21:38:08306 // Do nothing.
[email protected]b4db9372011-10-24 14:44:19307}
308
309base::TimeDelta LayerAnimator::GetTimerInterval() const {
310 return kTimerInterval;
311}
312
313void LayerAnimator::UpdateAnimationState() {
314 if (disable_timer_for_test_)
[email protected]7fca53d42011-09-29 15:38:12315 return;
316
[email protected]b4db9372011-10-24 14:44:19317 static ui::AnimationContainer* container = NULL;
318 if (!container) {
319 container = new AnimationContainer();
320 container->AddRef();
[email protected]710a98d2011-06-23 20:13:29321 }
[email protected]b4db9372011-10-24 14:44:19322
323 const bool should_start = is_animating();
324 if (should_start && !is_started_)
325 container->Start(this);
326 else if (!should_start && is_started_)
327 container->Stop(this);
328
329 is_started_ = should_start;
[email protected]710a98d2011-06-23 20:13:29330}
331
[email protected]f5cd9e52011-11-03 21:38:08332LayerAnimationSequence* LayerAnimator::RemoveAnimation(
333 LayerAnimationSequence* sequence) {
334 linked_ptr<LayerAnimationSequence> to_return;
335
336 // First remove from running animations
[email protected]b4db9372011-10-24 14:44:19337 for (RunningAnimations::iterator iter = running_animations_.begin();
338 iter != running_animations_.end(); ++iter) {
339 if ((*iter).sequence == sequence) {
340 running_animations_.erase(iter);
341 break;
[email protected]21445e472011-10-21 20:36:32342 }
343 }
[email protected]b4db9372011-10-24 14:44:19344
345 // Then remove from the queue
346 for (AnimationQueue::iterator queue_iter = animation_queue_.begin();
347 queue_iter != animation_queue_.end(); ++queue_iter) {
348 if ((*queue_iter) == sequence) {
[email protected]f5cd9e52011-11-03 21:38:08349 to_return = *queue_iter;
[email protected]b4db9372011-10-24 14:44:19350 animation_queue_.erase(queue_iter);
351 break;
352 }
353 }
[email protected]f5cd9e52011-11-03 21:38:08354
355 return to_return.release();
[email protected]0ed187e2011-10-21 20:07:42356}
357
[email protected]b4db9372011-10-24 14:44:19358void LayerAnimator::FinishAnimation(LayerAnimationSequence* sequence) {
[email protected]f5cd9e52011-11-03 21:38:08359 scoped_ptr<LayerAnimationSequence> removed(RemoveAnimation(sequence));
[email protected]b4db9372011-10-24 14:44:19360 sequence->Progress(sequence->duration(), delegate());
[email protected]b4db9372011-10-24 14:44:19361 ProcessQueue();
362 UpdateAnimationState();
[email protected]21445e472011-10-21 20:36:32363}
[email protected]0ed187e2011-10-21 20:07:42364
[email protected]b4db9372011-10-24 14:44:19365void LayerAnimator::FinishAnyAnimationWithZeroDuration() {
[email protected]2ddfe432011-11-07 19:26:30366 // Special case: if we've started a 0 duration animation, just finish it now
367 // and get rid of it. We need to make a copy because Progress may indirectly
368 // cause new animations to start running.
[email protected]f5cd9e52011-11-03 21:38:08369 RunningAnimations running_animations_copy = running_animations_;
370 for (size_t i = 0; i < running_animations_copy.size(); ++i) {
[email protected]d59a3692012-04-10 20:27:31371 if (!HasAnimation(running_animations_copy[i].sequence))
372 continue;
373
[email protected]f5cd9e52011-11-03 21:38:08374 if (running_animations_copy[i].sequence->duration() == base::TimeDelta()) {
375 running_animations_copy[i].sequence->Progress(
376 running_animations_copy[i].sequence->duration(), delegate());
377 scoped_ptr<LayerAnimationSequence> removed(
378 RemoveAnimation(running_animations_copy[i].sequence));
[email protected]b4db9372011-10-24 14:44:19379 }
380 }
381 ProcessQueue();
382 UpdateAnimationState();
[email protected]21445e472011-10-21 20:36:32383}
[email protected]0ed187e2011-10-21 20:07:42384
[email protected]b4db9372011-10-24 14:44:19385void LayerAnimator::ClearAnimations() {
[email protected]f5cd9e52011-11-03 21:38:08386 // Abort should never affect the set of running animations, but just in case
387 // clients are badly behaved, we will use a copy of the running animations.
388 RunningAnimations running_animations_copy = running_animations_;
389 for (size_t i = 0; i < running_animations_copy.size(); ++i) {
[email protected]d59a3692012-04-10 20:27:31390 if (!HasAnimation(running_animations_copy[i].sequence))
391 continue;
392
[email protected]f5cd9e52011-11-03 21:38:08393 scoped_ptr<LayerAnimationSequence> removed(
394 RemoveAnimation(running_animations_copy[i].sequence));
395 if (removed.get())
396 removed->Abort();
[email protected]b4db9372011-10-24 14:44:19397 }
[email protected]f5cd9e52011-11-03 21:38:08398 // This *should* have cleared the list of running animations.
399 DCHECK(running_animations_.empty());
[email protected]b4db9372011-10-24 14:44:19400 running_animations_.clear();
401 animation_queue_.clear();
402 UpdateAnimationState();
403}
404
405LayerAnimator::RunningAnimation* LayerAnimator::GetRunningAnimation(
406 LayerAnimationElement::AnimatableProperty property) {
407 for (RunningAnimations::iterator iter = running_animations_.begin();
408 iter != running_animations_.end(); ++iter) {
409 if ((*iter).sequence->properties().find(property) !=
410 (*iter).sequence->properties().end())
411 return &(*iter);
412 }
413 return NULL;
414}
415
416void LayerAnimator::AddToQueueIfNotPresent(LayerAnimationSequence* animation) {
417 // If we don't have the animation in the queue yet, add it.
418 bool found_sequence = false;
419 for (AnimationQueue::iterator queue_iter = animation_queue_.begin();
420 queue_iter != animation_queue_.end(); ++queue_iter) {
421 if ((*queue_iter) == animation) {
422 found_sequence = true;
423 break;
424 }
425 }
426
427 if (!found_sequence)
428 animation_queue_.push_front(make_linked_ptr(animation));
429}
430
431void LayerAnimator::RemoveAllAnimationsWithACommonProperty(
[email protected]f5cd9e52011-11-03 21:38:08432 LayerAnimationSequence* sequence, bool abort) {
[email protected]b4db9372011-10-24 14:44:19433 // For all the running animations, if they animate the same property,
[email protected]f5cd9e52011-11-03 21:38:08434 // progress them to the end and remove them. Note, Aborting or Progressing
435 // animations may affect the collection of running animations, so we need to
436 // operate on a copy.
437 RunningAnimations running_animations_copy = running_animations_;
438 for (size_t i = 0; i < running_animations_copy.size(); ++i) {
[email protected]d59a3692012-04-10 20:27:31439 if (!HasAnimation(running_animations_copy[i].sequence))
440 continue;
441
[email protected]f5cd9e52011-11-03 21:38:08442 if (running_animations_copy[i].sequence->HasCommonProperty(
[email protected]b4db9372011-10-24 14:44:19443 sequence->properties())) {
[email protected]f5cd9e52011-11-03 21:38:08444 scoped_ptr<LayerAnimationSequence> removed(
445 RemoveAnimation(running_animations_copy[i].sequence));
446 if (abort)
447 running_animations_copy[i].sequence->Abort();
448 else
449 running_animations_copy[i].sequence->Progress(
450 running_animations_copy[i].sequence->duration(), delegate());
[email protected]b4db9372011-10-24 14:44:19451 }
452 }
453
[email protected]f5cd9e52011-11-03 21:38:08454 // Same for the queued animations that haven't been started. Again, we'll
455 // need to operate on a copy.
456 std::vector<LayerAnimationSequence*> sequences;
457 for (AnimationQueue::iterator queue_iter = animation_queue_.begin();
458 queue_iter != animation_queue_.end(); ++queue_iter)
459 sequences.push_back((*queue_iter).get());
460
461 for (size_t i = 0; i < sequences.size(); ++i) {
[email protected]d59a3692012-04-10 20:27:31462 if (!HasAnimation(sequences[i]))
463 continue;
464
[email protected]f5cd9e52011-11-03 21:38:08465 if (sequences[i]->HasCommonProperty(sequence->properties())) {
466 scoped_ptr<LayerAnimationSequence> removed(
467 RemoveAnimation(sequences[i]));
[email protected]b4db9372011-10-24 14:44:19468 if (abort)
[email protected]f5cd9e52011-11-03 21:38:08469 sequences[i]->Abort();
[email protected]b4db9372011-10-24 14:44:19470 else
[email protected]f5cd9e52011-11-03 21:38:08471 sequences[i]->Progress(sequences[i]->duration(), delegate());
[email protected]b4db9372011-10-24 14:44:19472 }
473 }
474}
475
476void LayerAnimator::ImmediatelySetNewTarget(LayerAnimationSequence* sequence) {
[email protected]d3ba37ab2012-02-09 19:53:13477 // Ensure that sequence is disposed of when this function completes.
478 scoped_ptr<LayerAnimationSequence> to_dispose(sequence);
[email protected]b4db9372011-10-24 14:44:19479 const bool abort = false;
480 RemoveAllAnimationsWithACommonProperty(sequence, abort);
[email protected]d3ba37ab2012-02-09 19:53:13481 LayerAnimationSequence* removed = RemoveAnimation(sequence);
482 DCHECK(removed == NULL || removed == sequence);
[email protected]b4db9372011-10-24 14:44:19483 sequence->Progress(sequence->duration(), delegate());
[email protected]b4db9372011-10-24 14:44:19484}
485
486void LayerAnimator::ImmediatelyAnimateToNewTarget(
487 LayerAnimationSequence* sequence) {
488 const bool abort = true;
489 RemoveAllAnimationsWithACommonProperty(sequence, abort);
490 AddToQueueIfNotPresent(sequence);
491 StartSequenceImmediately(sequence);
492}
493
494void LayerAnimator::EnqueueNewAnimation(LayerAnimationSequence* sequence) {
495 // It is assumed that if there was no conflicting animation, we would
496 // not have been called. No need to check for a collision; just
497 // add to the queue.
498 animation_queue_.push_back(make_linked_ptr(sequence));
499 ProcessQueue();
500}
501
502void LayerAnimator::ReplaceQueuedAnimations(LayerAnimationSequence* sequence) {
503 // Remove all animations that aren't running. Note: at each iteration i is
504 // incremented or an element is removed from the queue, so
505 // animation_queue_.size() - i is always decreasing and we are always making
506 // progress towards the loop terminating.
507 for (size_t i = 0; i < animation_queue_.size();) {
508 bool is_running = false;
509 for (RunningAnimations::const_iterator iter = running_animations_.begin();
510 iter != running_animations_.end(); ++iter) {
511 if ((*iter).sequence == animation_queue_[i]) {
512 is_running = true;
513 break;
514 }
515 }
516 if (!is_running)
[email protected]300548c2012-06-17 08:54:55517 delete RemoveAnimation(animation_queue_[i].get());
[email protected]b4db9372011-10-24 14:44:19518 else
519 ++i;
520 }
521 animation_queue_.push_back(make_linked_ptr(sequence));
522 ProcessQueue();
523}
524
525void LayerAnimator::ProcessQueue() {
526 bool started_sequence = false;
527 do {
528 started_sequence = false;
[email protected]b4db9372011-10-24 14:44:19529 // Build a list of all currently animated properties.
530 LayerAnimationElement::AnimatableProperties animated;
[email protected]b4db9372011-10-24 14:44:19531 for (RunningAnimations::const_iterator iter = running_animations_.begin();
532 iter != running_animations_.end(); ++iter) {
533 animated.insert((*iter).sequence->properties().begin(),
534 (*iter).sequence->properties().end());
535 }
536
537 // Try to find an animation that doesn't conflict with an animated
[email protected]f5cd9e52011-11-03 21:38:08538 // property or a property that will be animated before it. Note: starting
539 // the animation may indirectly cause more animations to be started, so we
540 // need to operate on a copy.
541 std::vector<LayerAnimationSequence*> sequences;
[email protected]b4db9372011-10-24 14:44:19542 for (AnimationQueue::iterator queue_iter = animation_queue_.begin();
[email protected]f5cd9e52011-11-03 21:38:08543 queue_iter != animation_queue_.end(); ++queue_iter)
544 sequences.push_back((*queue_iter).get());
545
546 for (size_t i = 0; i < sequences.size(); ++i) {
547 if (!sequences[i]->HasCommonProperty(animated)) {
548 StartSequenceImmediately(sequences[i]);
[email protected]b4db9372011-10-24 14:44:19549 started_sequence = true;
550 break;
551 }
552
553 // Animation couldn't be started. Add its properties to the collection so
554 // that we don't start a conflicting animation. For example, if our queue
555 // has the elements { {T,B}, {B} } (that is, an element that animates both
556 // the transform and the bounds followed by an element that animates the
557 // bounds), and we're currently animating the transform, we can't start
558 // the first element because it animates the transform, too. We cannot
559 // start the second element, either, because the first element animates
560 // bounds too, and needs to go first.
[email protected]f5cd9e52011-11-03 21:38:08561 animated.insert(sequences[i]->properties().begin(),
562 sequences[i]->properties().end());
[email protected]b4db9372011-10-24 14:44:19563 }
564
565 // If we started a sequence, try again. We may be able to start several.
566 } while (started_sequence);
567}
568
569bool LayerAnimator::StartSequenceImmediately(LayerAnimationSequence* sequence) {
570 // Ensure that no one is animating one of the sequence's properties already.
571 for (RunningAnimations::const_iterator iter = running_animations_.begin();
572 iter != running_animations_.end(); ++iter) {
573 if ((*iter).sequence->HasCommonProperty(sequence->properties()))
574 return false;
575 }
576
577 // All clear, actually start the sequence. Note: base::TimeTicks::Now has
578 // a resolution that can be as bad as 15ms. If this causes glitches in the
579 // animations, this can be switched to HighResNow() (animation uses Now()
580 // internally).
581 base::TimeTicks start_time = is_animating()
582 ? last_step_time_
583 : base::TimeTicks::Now();
584
585 running_animations_.push_back(RunningAnimation(sequence, start_time));
586
587 // Need to keep a reference to the animation.
588 AddToQueueIfNotPresent(sequence);
589
590 // Ensure that animations get stepped at their start time.
591 Step(start_time);
592
593 return true;
[email protected]710a98d2011-06-23 20:13:29594}
595
[email protected]fe7074c62011-10-28 15:22:54596void LayerAnimator::GetTargetValue(
597 LayerAnimationElement::TargetValue* target) const {
[email protected]b1c37fc2012-03-22 03:36:13598 for (AnimationQueue::const_iterator iter = animation_queue_.begin();
599 iter != animation_queue_.end(); ++iter) {
600 (*iter)->GetTargetValue(target);
[email protected]fe7074c62011-10-28 15:22:54601 }
602}
603
[email protected]e876c2712011-11-02 16:42:45604void LayerAnimator::OnScheduled(LayerAnimationSequence* sequence) {
605 if (observers_.might_have_observers()) {
606 ObserverListBase<LayerAnimationObserver>::Iterator it(observers_);
607 LayerAnimationObserver* obs;
608 while ((obs = it.GetNext()) != NULL) {
609 sequence->AddObserver(obs);
610 }
611 }
612 sequence->OnScheduled();
613}
614
[email protected]9861f1752012-06-01 07:16:14615base::TimeDelta LayerAnimator::GetTransitionDuration() const {
[email protected]9861f1752012-06-01 07:16:14616 return transition_duration_;
617}
618
[email protected]710a98d2011-06-23 20:13:29619} // namespace ui