Index: services/view_manager/animation_runner.cc |
diff --git a/services/view_manager/animation_runner.cc b/services/view_manager/animation_runner.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..df0fefdc2e71a4d4e206bce8adcc9ce3e1e1329d |
--- /dev/null |
+++ b/services/view_manager/animation_runner.cc |
@@ -0,0 +1,112 @@ |
+// Copyright 2014 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 "services/view_manager/animation_runner.h" |
+ |
+#include <set> |
+ |
+#include "services/view_manager/animation_runner_observer.h" |
+#include "services/view_manager/scheduled_animation_group.h" |
+#include "services/view_manager/server_view.h" |
+ |
+namespace mojo { |
+namespace service { |
+namespace { |
+ |
+struct AnimationDoneState { |
+ ServerView* view; |
+ uint32_t animation_id; |
+}; |
+ |
+} // namespace |
+ |
+AnimationRunner::AnimationRunner(base::TimeTicks now) |
+ : next_id_(1), last_tick_time_(now) { |
+} |
+ |
+AnimationRunner::~AnimationRunner() { |
+} |
+ |
+void AnimationRunner::AddObserver(AnimationRunnerObserver* observer) { |
+ observers_.AddObserver(observer); |
+} |
+ |
+void AnimationRunner::RemoveObserver(AnimationRunnerObserver* observer) { |
+ observers_.RemoveObserver(observer); |
+} |
+ |
+uint32_t AnimationRunner::Schedule(ServerView* view, |
+ const AnimationGroup& transport_group) { |
+ scoped_ptr<ScheduledAnimationGroup> group(ScheduledAnimationGroup::Create( |
+ view, last_tick_time_, next_id_++, transport_group)); |
+ if (!group.get()) |
+ return 0; |
+ |
+ if (animation_map_.contains(view)) { |
+ animation_map_.get(view)->SetValuesToTargetValuesForPropertiesNotIn(*group); |
+ const uint32_t animation_id = animation_map_.get(view)->id(); |
+ animation_map_.erase(view); |
+ FOR_EACH_OBSERVER(AnimationRunnerObserver, observers_, |
+ OnAnimationInterrupted(view, animation_id)); |
+ } |
+ |
+ group->ObtainStartValues(); |
+ |
+ const uint32_t id = group->id(); |
+ animation_map_.set(view, group.Pass()); |
+ |
+ FOR_EACH_OBSERVER(AnimationRunnerObserver, observers_, |
+ OnAnimationScheduled(view, id)); |
+ return id; |
+} |
+ |
+ServerView* AnimationRunner::GetViewForAnimation(uint32_t id) { |
+ for (ViewAnimationMap::iterator i = animation_map_.begin(); |
+ i != animation_map_.end(); ++i) { |
+ if (i->second->id() == id) |
+ return i->first; |
+ } |
+ return nullptr; |
+} |
+ |
+void AnimationRunner::CancelAnimationForView(ServerView* view) { |
+ if (!animation_map_.contains(view)) |
+ return; |
+ |
+ const uint32_t id = animation_map_.get(view)->id(); |
+ animation_map_.erase(view); |
+ FOR_EACH_OBSERVER(AnimationRunnerObserver, observers_, |
+ OnAnimationCanceled(view, id)); |
+} |
+ |
+void AnimationRunner::Tick(base::TimeTicks time) { |
+ DCHECK(time >= last_tick_time_); |
+ last_tick_time_ = time; |
+ if (animation_map_.empty()) |
+ return; |
+ |
+ std::vector<AnimationDoneState> animations_done; |
+ for (ViewAnimationMap::iterator i = animation_map_.begin(); |
+ i != animation_map_.end(); ) { |
+ // Any animations that complete are notified at the end of the loop. This |
+ // way if the obsevert attempts to schedule another animation or mutate us |
+ // in some other way we aren't in a bad state. |
+ if (i->second->Tick(time)) { |
+ AnimationDoneState done_state; |
+ done_state.view = i->first; |
+ done_state.animation_id = i->second->id(); |
+ animations_done.push_back(done_state); |
+ animation_map_.erase(i++); |
+ } else { |
+ ++i; |
+ } |
+ } |
+ for (const AnimationDoneState& done : animations_done) { |
+ FOR_EACH_OBSERVER(AnimationRunnerObserver, observers_, |
+ OnAnimationDone(done.view, done.animation_id)); |
+ } |
+} |
+ |
+} // namespace service |
+} // namespace mojo |