1 // Copyright 2014 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.
5 #include "components/view_manager/animation_runner.h"
7 #include "base/memory/scoped_vector.h"
8 #include "components/view_manager/animation_runner_observer.h"
9 #include "components/view_manager/scheduled_animation_group.h"
10 #include "components/view_manager/server_view.h"
12 namespace view_manager
{
15 bool ConvertViewAndAnimationPairToScheduledAnimationGroup(
16 const std::vector
<AnimationRunner::ViewAndAnimationPair
>& views
,
17 AnimationRunner::AnimationId id
,
19 ScopedVector
<ScheduledAnimationGroup
>* groups
) {
20 for (const auto& view_animation_pair
: views
) {
21 DCHECK(view_animation_pair
.second
);
22 scoped_ptr
<ScheduledAnimationGroup
> group(ScheduledAnimationGroup::Create(
23 view_animation_pair
.first
, now
, id
, *(view_animation_pair
.second
)));
26 groups
->push_back(group
.release());
33 AnimationRunner::AnimationRunner(base::TimeTicks now
)
34 : next_id_(1), last_tick_time_(now
) {
37 AnimationRunner::~AnimationRunner() {
40 void AnimationRunner::AddObserver(AnimationRunnerObserver
* observer
) {
41 observers_
.AddObserver(observer
);
44 void AnimationRunner::RemoveObserver(AnimationRunnerObserver
* observer
) {
45 observers_
.RemoveObserver(observer
);
48 AnimationRunner::AnimationId
AnimationRunner::Schedule(
49 const std::vector
<ViewAndAnimationPair
>& views
,
50 base::TimeTicks now
) {
51 DCHECK_GE(now
, last_tick_time_
);
53 const AnimationId animation_id
= next_id_
++;
54 ScopedVector
<ScheduledAnimationGroup
> groups
;
55 if (!ConvertViewAndAnimationPairToScheduledAnimationGroup(views
, animation_id
,
60 // Cancel any animations for the views.
61 for (auto* group
: groups
) {
62 ScheduledAnimationGroup
* current_group
=
63 view_to_animation_map_
.get(group
->view());
65 current_group
->SetValuesToTargetValuesForPropertiesNotIn(*group
);
67 CancelAnimationForViewImpl(group
->view(), CANCEL_SOURCE_SCHEDULE
);
70 for (auto* group
: groups
) {
71 group
->ObtainStartValues();
72 view_to_animation_map_
.set(group
->view(), make_scoped_ptr(group
));
73 DCHECK(!id_to_views_map_
[animation_id
].count(group
->view()));
74 id_to_views_map_
[animation_id
].insert(group
->view());
76 // |view_to_animation_map_| owns the groups.
79 FOR_EACH_OBSERVER(AnimationRunnerObserver
, observers_
,
80 OnAnimationScheduled(animation_id
));
84 void AnimationRunner::CancelAnimation(AnimationId id
) {
85 if (id_to_views_map_
.count(id
) == 0)
88 std::set
<ServerView
*> views(id_to_views_map_
[id
]);
89 for (ServerView
* view
: views
)
90 CancelAnimationForView(view
);
93 void AnimationRunner::CancelAnimationForView(ServerView
* view
) {
94 CancelAnimationForViewImpl(view
, CANCEL_SOURCE_CANCEL
);
97 void AnimationRunner::Tick(base::TimeTicks time
) {
98 DCHECK(time
>= last_tick_time_
);
99 last_tick_time_
= time
;
100 if (view_to_animation_map_
.empty())
103 // The animation ids of any views whose animation completes are added here. We
104 // notify after processing all views so that if an observer mutates us in some
105 // way we're aren't left in a weird state.
106 std::set
<AnimationId
> animations_completed
;
107 for (ViewToAnimationMap::iterator i
= view_to_animation_map_
.begin();
108 i
!= view_to_animation_map_
.end();) {
109 if (i
->second
->Tick(time
)) {
110 const AnimationId animation_id
= i
->second
->id();
111 ServerView
* view
= i
->first
;
113 if (RemoveViewFromMaps(view
))
114 animations_completed
.insert(animation_id
);
119 for (const AnimationId
& id
: animations_completed
) {
120 FOR_EACH_OBSERVER(AnimationRunnerObserver
, observers_
, OnAnimationDone(id
));
124 void AnimationRunner::CancelAnimationForViewImpl(ServerView
* view
,
125 CancelSource source
) {
126 if (!view_to_animation_map_
.contains(view
))
129 const AnimationId animation_id
= view_to_animation_map_
.get(view
)->id();
130 if (RemoveViewFromMaps(view
)) {
131 // This was the last view in the group.
132 if (source
== CANCEL_SOURCE_CANCEL
) {
133 FOR_EACH_OBSERVER(AnimationRunnerObserver
, observers_
,
134 OnAnimationCanceled(animation_id
));
136 FOR_EACH_OBSERVER(AnimationRunnerObserver
, observers_
,
137 OnAnimationInterrupted(animation_id
));
142 bool AnimationRunner::RemoveViewFromMaps(ServerView
* view
) {
143 DCHECK(view_to_animation_map_
.contains(view
));
145 const AnimationId animation_id
= view_to_animation_map_
.get(view
)->id();
146 view_to_animation_map_
.erase(view
);
148 DCHECK(id_to_views_map_
.count(animation_id
));
149 id_to_views_map_
[animation_id
].erase(view
);
150 if (!id_to_views_map_
[animation_id
].empty())
153 id_to_views_map_
.erase(animation_id
);
157 } // namespace view_manager