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/linear_animation.h"
6
7#include <math.h>
8
9#include "ui/gfx/animation/animation_container.h"
10#include "ui/gfx/animation/animation_delegate.h"
11
12using base::Time;
13using base::TimeDelta;
14
15namespace gfx {
16
17static TimeDelta CalculateInterval(int frame_rate) {
18  int timer_interval = 1000000 / frame_rate;
19  if (timer_interval < 10000)
20    timer_interval = 10000;
21  return TimeDelta::FromMicroseconds(timer_interval);
22}
23
24LinearAnimation::LinearAnimation(int frame_rate,
25                                 AnimationDelegate* delegate)
26    : Animation(CalculateInterval(frame_rate)),
27      state_(0.0),
28      in_end_(false) {
29  set_delegate(delegate);
30}
31
32LinearAnimation::LinearAnimation(int duration,
33                                 int frame_rate,
34                                 AnimationDelegate* delegate)
35    : Animation(CalculateInterval(frame_rate)),
36      duration_(TimeDelta::FromMilliseconds(duration)),
37      state_(0.0),
38      in_end_(false) {
39  set_delegate(delegate);
40  SetDuration(duration);
41}
42
43double LinearAnimation::GetCurrentValue() const {
44  // Default is linear relationship, subclass to adapt.
45  return state_;
46}
47
48void LinearAnimation::SetCurrentValue(double new_value) {
49  new_value = std::max(0.0, std::min(1.0, new_value));
50  base::TimeDelta time_delta = base::TimeDelta::FromMicroseconds(
51      duration_.InMicroseconds() * (new_value - state_));
52  SetStartTime(start_time() - time_delta);
53  state_ = new_value;
54}
55
56void LinearAnimation::End() {
57  if (!is_animating())
58    return;
59
60  // NOTE: We don't use AutoReset here as Stop may end up deleting us (by way
61  // of the delegate).
62  in_end_ = true;
63  Stop();
64}
65
66void LinearAnimation::SetDuration(int duration) {
67  duration_ = TimeDelta::FromMilliseconds(duration);
68  if (duration_ < timer_interval())
69    duration_ = timer_interval();
70  if (is_animating())
71    SetStartTime(container()->last_tick_time());
72}
73
74void LinearAnimation::Step(base::TimeTicks time_now) {
75  TimeDelta elapsed_time = time_now - start_time();
76  state_ = static_cast<double>(elapsed_time.InMicroseconds()) /
77           static_cast<double>(duration_.InMicroseconds());
78  if (state_ >= 1.0)
79    state_ = 1.0;
80
81  AnimateToState(state_);
82
83  if (delegate())
84    delegate()->AnimationProgressed(this);
85
86  if (state_ == 1.0)
87    Stop();
88}
89
90void LinearAnimation::AnimationStarted() {
91  state_ = 0.0;
92}
93
94void LinearAnimation::AnimationStopped() {
95  if (!in_end_)
96    return;
97
98  in_end_ = false;
99  // Set state_ to ensure we send ended to delegate and not canceled.
100  state_ = 1;
101  AnimateToState(1.0);
102}
103
104bool LinearAnimation::ShouldSendCanceledFromStop() {
105  return state_ != 1;
106}
107
108}  // namespace gfx
109