summaryrefslogtreecommitdiffstats
path: root/app/animation_container.cc
diff options
context:
space:
mode:
Diffstat (limited to 'app/animation_container.cc')
-rw-r--r--app/animation_container.cc93
1 files changed, 93 insertions, 0 deletions
diff --git a/app/animation_container.cc b/app/animation_container.cc
new file mode 100644
index 0000000..b0cc86a
--- /dev/null
+++ b/app/animation_container.cc
@@ -0,0 +1,93 @@
+// 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 "app/animation_container.h"
+
+#include "app/animation.h"
+
+using base::TimeDelta;
+using base::TimeTicks;
+
+AnimationContainer::AnimationContainer()
+ : last_tick_time_(TimeTicks::Now()),
+ observer_(NULL) {
+}
+
+AnimationContainer::~AnimationContainer() {
+ // The animations own us and stop themselves before being deleted. If
+ // animations_ is not empty, something is wrong.
+ DCHECK(animations_.empty());
+}
+
+void AnimationContainer::Start(Animation* animation) {
+ DCHECK(animations_.count(animation) == 0); // Start should only be invoked
+ // if the animation isn't running.
+
+ if (animations_.empty()) {
+ last_tick_time_ = TimeTicks::Now();
+ SetMinTimerInterval(animation->timer_interval());
+ } else if (animation->timer_interval() < min_timer_interval_) {
+ SetMinTimerInterval(animation->timer_interval());
+ }
+
+ animation->set_start_time(last_tick_time_);
+ animations_.insert(animation);
+}
+
+void AnimationContainer::Stop(Animation* animation) {
+ DCHECK(animations_.count(animation) > 0); // The animation must be running.
+
+ animations_.erase(animation);
+
+ if (animations_.empty()) {
+ timer_.Stop();
+ if (observer_)
+ observer_->AnimationContainerEmpty(this);
+ } else {
+ TimeDelta min_timer_interval = GetMinInterval();
+ if (min_timer_interval > min_timer_interval_)
+ SetMinTimerInterval(min_timer_interval);
+ }
+}
+
+void AnimationContainer::Run() {
+ TimeTicks current_time = TimeTicks::Now();
+
+ last_tick_time_ = current_time;
+
+ // Make a copy of the animations to iterate over so that if any animations
+ // are removed as part of invoking Step there aren't any problems.
+ Animations animations = animations_;
+
+ for (Animations::const_iterator i = animations.begin();
+ i != animations.end(); ++i) {
+ // Make sure the animation is still valid.
+ if (animations_.find(*i) != animations_.end())
+ (*i)->Step(current_time);
+ }
+
+ if (observer_)
+ observer_->AnimationContainerProgressed(this);
+}
+
+void AnimationContainer::SetMinTimerInterval(base::TimeDelta delta) {
+ // This doesn't take into account how far along current animation is, but that
+ // shouldn't be a problem for uses of Animation/AnimationContainer.
+ timer_.Stop();
+ min_timer_interval_ = delta;
+ timer_.Start(min_timer_interval_, this, &AnimationContainer::Run);
+}
+
+TimeDelta AnimationContainer::GetMinInterval() {
+ DCHECK(!animations_.empty());
+
+ TimeDelta min;
+ Animations::const_iterator i = animations_.begin();
+ min = (*i)->timer_interval();
+ for (++i; i != animations_.end(); ++i) {
+ if ((*i)->timer_interval() < min)
+ min = (*i)->timer_interval();
+ }
+ return min;
+}