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 "cc/animation/scrollbar_animation_controller.h"
6
7#include <algorithm>
8
9#include "base/time/time.h"
10
11namespace cc {
12
13ScrollbarAnimationController::ScrollbarAnimationController(
14    ScrollbarAnimationControllerClient* client,
15    base::TimeDelta delay_before_starting,
16    base::TimeDelta duration)
17    : client_(client),
18      delay_before_starting_(delay_before_starting),
19      duration_(duration),
20      is_animating_(false),
21      currently_scrolling_(false),
22      scroll_gesture_has_scrolled_(false),
23      weak_factory_(this) {
24}
25
26ScrollbarAnimationController::~ScrollbarAnimationController() {
27}
28
29void ScrollbarAnimationController::Animate(base::TimeTicks now) {
30  if (!is_animating_)
31    return;
32
33  if (last_awaken_time_.is_null())
34    last_awaken_time_ = now;
35
36  float progress = AnimationProgressAtTime(now);
37  RunAnimationFrame(progress);
38
39  if (is_animating_) {
40    delayed_scrollbar_fade_.Cancel();
41    client_->SetNeedsScrollbarAnimationFrame();
42  }
43}
44
45float ScrollbarAnimationController::AnimationProgressAtTime(
46    base::TimeTicks now) {
47  base::TimeDelta delta = now - last_awaken_time_;
48  float progress = delta.InSecondsF() / duration_.InSecondsF();
49  return std::max(std::min(progress, 1.f), 0.f);
50}
51
52void ScrollbarAnimationController::DidScrollBegin() {
53  currently_scrolling_ = true;
54}
55
56void ScrollbarAnimationController::DidScrollUpdate() {
57  StopAnimation();
58  delayed_scrollbar_fade_.Cancel();
59
60  // As an optimization, we avoid spamming fade delay tasks during active fast
61  // scrolls.  But if we're not within one, we need to post every scroll update.
62  if (!currently_scrolling_)
63    PostDelayedFade();
64  else
65    scroll_gesture_has_scrolled_ = true;
66}
67
68void ScrollbarAnimationController::DidScrollEnd() {
69  if (scroll_gesture_has_scrolled_) {
70    PostDelayedFade();
71    scroll_gesture_has_scrolled_ = false;
72  }
73
74  currently_scrolling_ = false;
75}
76
77void ScrollbarAnimationController::PostDelayedFade() {
78  delayed_scrollbar_fade_.Reset(
79      base::Bind(&ScrollbarAnimationController::StartAnimation,
80                 weak_factory_.GetWeakPtr()));
81  client_->PostDelayedScrollbarFade(delayed_scrollbar_fade_.callback(),
82                                    delay_before_starting_);
83}
84
85void ScrollbarAnimationController::StartAnimation() {
86  delayed_scrollbar_fade_.Cancel();
87  is_animating_ = true;
88  last_awaken_time_ = base::TimeTicks();
89  client_->SetNeedsScrollbarAnimationFrame();
90}
91
92void ScrollbarAnimationController::StopAnimation() {
93  is_animating_ = false;
94}
95
96}  // namespace cc
97