blob: dc569e9d650e835ecac69dcaf811cb127caf2715 [file] [log] [blame]
// 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 view_manager {
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 mojo::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 view_manager