OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #include "services/view_manager/animation_runner.h" | |
6 | |
7 #include "base/memory/scoped_vector.h" | |
8 #include "services/view_manager/animation_runner_observer.h" | |
9 #include "services/view_manager/scheduled_animation_group.h" | |
10 #include "services/view_manager/server_view.h" | |
11 | |
12 namespace view_manager { | |
13 namespace { | |
14 | |
15 bool ConvertViewAndAnimationPairToScheduledAnimationGroup( | |
16 const std::vector<AnimationRunner::ViewAndAnimationPair>& views, | |
17 AnimationRunner::AnimationId id, | |
18 base::TimeTicks now, | |
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))); | |
24 if (!group.get()) | |
25 return false; | |
26 groups->push_back(group.release()); | |
27 } | |
28 return true; | |
29 } | |
30 | |
31 } // namespace | |
32 | |
33 AnimationRunner::AnimationRunner(base::TimeTicks now) | |
34 : next_id_(1), last_tick_time_(now) { | |
35 } | |
36 | |
37 AnimationRunner::~AnimationRunner() { | |
38 } | |
39 | |
40 void AnimationRunner::AddObserver(AnimationRunnerObserver* observer) { | |
41 observers_.AddObserver(observer); | |
42 } | |
43 | |
44 void AnimationRunner::RemoveObserver(AnimationRunnerObserver* observer) { | |
45 observers_.RemoveObserver(observer); | |
46 } | |
47 | |
48 AnimationRunner::AnimationId AnimationRunner::Schedule( | |
49 const std::vector<ViewAndAnimationPair>& views, | |
50 base::TimeTicks now) { | |
51 DCHECK_GE(now, last_tick_time_); | |
52 | |
53 const AnimationId animation_id = next_id_++; | |
54 ScopedVector<ScheduledAnimationGroup> groups; | |
55 if (!ConvertViewAndAnimationPairToScheduledAnimationGroup(views, animation_id, | |
56 now, &groups)) { | |
57 return 0; | |
58 } | |
59 | |
60 // Cancel any animations for the views. | |
61 for (auto* group : groups) { | |
62 ScheduledAnimationGroup* current_group = | |
63 view_to_animation_map_.get(group->view()); | |
64 if (current_group) | |
65 current_group->SetValuesToTargetValuesForPropertiesNotIn(*group); | |
66 | |
67 CancelAnimationForViewImpl(group->view(), CANCEL_SOURCE_SCHEDULE); | |
68 } | |
69 | |
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()); | |
75 } | |
76 // |view_to_animation_map_| owns the groups. | |
77 groups.weak_clear(); | |
78 | |
79 FOR_EACH_OBSERVER(AnimationRunnerObserver, observers_, | |
80 OnAnimationScheduled(animation_id)); | |
81 return animation_id; | |
82 } | |
83 | |
84 void AnimationRunner::CancelAnimation(AnimationId id) { | |
85 if (id_to_views_map_.count(id) == 0) | |
86 return; | |
87 | |
88 std::set<ServerView*> views(id_to_views_map_[id]); | |
89 for (ServerView* view : views) | |
90 CancelAnimationForView(view); | |
91 } | |
92 | |
93 void AnimationRunner::CancelAnimationForView(ServerView* view) { | |
94 CancelAnimationForViewImpl(view, CANCEL_SOURCE_CANCEL); | |
95 } | |
96 | |
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()) | |
101 return; | |
102 | |
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; | |
112 ++i; | |
113 if (RemoveViewFromMaps(view)) | |
114 animations_completed.insert(animation_id); | |
115 } else { | |
116 ++i; | |
117 } | |
118 } | |
119 for (const AnimationId& id : animations_completed) | |
120 FOR_EACH_OBSERVER(AnimationRunnerObserver, observers_, OnAnimationDone(id)); | |
121 } | |
122 | |
123 void AnimationRunner::CancelAnimationForViewImpl(ServerView* view, | |
124 CancelSource source) { | |
125 if (!view_to_animation_map_.contains(view)) | |
126 return; | |
127 | |
128 const AnimationId animation_id = view_to_animation_map_.get(view)->id(); | |
129 if (RemoveViewFromMaps(view)) { | |
130 // This was the last view in the group. | |
131 if (source == CANCEL_SOURCE_CANCEL) { | |
132 FOR_EACH_OBSERVER(AnimationRunnerObserver, observers_, | |
133 OnAnimationCanceled(animation_id)); | |
134 } else { | |
135 FOR_EACH_OBSERVER(AnimationRunnerObserver, observers_, | |
136 OnAnimationInterrupted(animation_id)); | |
137 } | |
138 } | |
139 } | |
140 | |
141 bool AnimationRunner::RemoveViewFromMaps(ServerView* view) { | |
142 DCHECK(view_to_animation_map_.contains(view)); | |
143 | |
144 const AnimationId animation_id = view_to_animation_map_.get(view)->id(); | |
145 view_to_animation_map_.erase(view); | |
146 | |
147 DCHECK(id_to_views_map_.count(animation_id)); | |
148 id_to_views_map_[animation_id].erase(view); | |
149 if (!id_to_views_map_[animation_id].empty()) | |
150 return false; | |
151 | |
152 id_to_views_map_.erase(animation_id); | |
153 return true; | |
154 } | |
155 | |
156 } // namespace view_manager | |
OLD | NEW |