• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2011 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 "ui/gfx/animation/animation_container.h"
6 
7 #include "ui/gfx/animation/animation_container_element.h"
8 #include "ui/gfx/animation/animation_container_observer.h"
9 #include "ui/gfx/frame_time.h"
10 
11 using base::TimeDelta;
12 using base::TimeTicks;
13 
14 namespace gfx {
15 
AnimationContainer()16 AnimationContainer::AnimationContainer()
17     : last_tick_time_(gfx::FrameTime::Now()),
18       observer_(NULL) {
19 }
20 
~AnimationContainer()21 AnimationContainer::~AnimationContainer() {
22   // The animations own us and stop themselves before being deleted. If
23   // elements_ is not empty, something is wrong.
24   DCHECK(elements_.empty());
25 }
26 
Start(AnimationContainerElement * element)27 void AnimationContainer::Start(AnimationContainerElement* element) {
28   DCHECK(elements_.count(element) == 0);  // Start should only be invoked if the
29                                           // element isn't running.
30 
31   if (elements_.empty()) {
32     last_tick_time_ = gfx::FrameTime::Now();
33     SetMinTimerInterval(element->GetTimerInterval());
34   } else if (element->GetTimerInterval() < min_timer_interval_) {
35     SetMinTimerInterval(element->GetTimerInterval());
36   }
37 
38   element->SetStartTime(last_tick_time_);
39   elements_.insert(element);
40 }
41 
Stop(AnimationContainerElement * element)42 void AnimationContainer::Stop(AnimationContainerElement* element) {
43   DCHECK(elements_.count(element) > 0);  // The element must be running.
44 
45   elements_.erase(element);
46 
47   if (elements_.empty()) {
48     timer_.Stop();
49     if (observer_)
50       observer_->AnimationContainerEmpty(this);
51   } else {
52     TimeDelta min_timer_interval = GetMinInterval();
53     if (min_timer_interval > min_timer_interval_)
54       SetMinTimerInterval(min_timer_interval);
55   }
56 }
57 
Run()58 void AnimationContainer::Run() {
59   // We notify the observer after updating all the elements. If all the elements
60   // are deleted as a result of updating then our ref count would go to zero and
61   // we would be deleted before we notify our observer. We add a reference to
62   // ourself here to make sure we're still valid after running all the elements.
63   scoped_refptr<AnimationContainer> this_ref(this);
64 
65   TimeTicks current_time = gfx::FrameTime::Now();
66 
67   last_tick_time_ = current_time;
68 
69   // Make a copy of the elements to iterate over so that if any elements are
70   // removed as part of invoking Step there aren't any problems.
71   Elements elements = elements_;
72 
73   for (Elements::const_iterator i = elements.begin();
74        i != elements.end(); ++i) {
75     // Make sure the element is still valid.
76     if (elements_.find(*i) != elements_.end())
77       (*i)->Step(current_time);
78   }
79 
80   if (observer_)
81     observer_->AnimationContainerProgressed(this);
82 }
83 
SetMinTimerInterval(base::TimeDelta delta)84 void AnimationContainer::SetMinTimerInterval(base::TimeDelta delta) {
85   // This doesn't take into account how far along the current element is, but
86   // that shouldn't be a problem for uses of Animation/AnimationContainer.
87   timer_.Stop();
88   min_timer_interval_ = delta;
89   timer_.Start(FROM_HERE, min_timer_interval_, this, &AnimationContainer::Run);
90 }
91 
GetMinInterval()92 TimeDelta AnimationContainer::GetMinInterval() {
93   DCHECK(!elements_.empty());
94 
95   TimeDelta min;
96   Elements::const_iterator i = elements_.begin();
97   min = (*i)->GetTimerInterval();
98   for (++i; i != elements_.end(); ++i) {
99     if ((*i)->GetTimerInterval() < min)
100       min = (*i)->GetTimerInterval();
101   }
102   return min;
103 }
104 
105 }  // namespace gfx
106