- add sources.
[platform/framework/web/crosswalk.git] / src / cc / animation / scrollbar_animation_controller_thinning.cc
1 // Copyright 2013 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_thinning.h"
6
7 #include <algorithm>
8
9 #include "base/time/time.h"
10 #include "cc/layers/layer_impl.h"
11 #include "cc/layers/scrollbar_layer_impl_base.h"
12
13 namespace {
14 const float kIdleThicknessScale = 0.4f;
15 const float kIdleOpacity = 0.7f;
16 const float kDefaultMouseMoveDistanceToTriggerAnimation = 25.f;
17 const int kDefaultAnimationDelay = 500;
18 const int kDefaultAnimationDuration = 300;
19 }
20
21 namespace cc {
22
23 scoped_ptr<ScrollbarAnimationControllerThinning>
24 ScrollbarAnimationControllerThinning::Create(LayerImpl* scroll_layer) {
25   return make_scoped_ptr(new ScrollbarAnimationControllerThinning(
26       scroll_layer,
27       base::TimeDelta::FromMilliseconds(kDefaultAnimationDelay),
28       base::TimeDelta::FromMilliseconds(kDefaultAnimationDuration)));
29 }
30
31 scoped_ptr<ScrollbarAnimationControllerThinning>
32 ScrollbarAnimationControllerThinning::CreateForTest(LayerImpl* scroll_layer,
33     base::TimeDelta animation_delay, base::TimeDelta animation_duration) {
34   return make_scoped_ptr(new ScrollbarAnimationControllerThinning(
35       scroll_layer, animation_delay, animation_duration));
36 }
37
38 ScrollbarAnimationControllerThinning::ScrollbarAnimationControllerThinning(
39     LayerImpl* scroll_layer,
40     base::TimeDelta animation_delay,
41     base::TimeDelta animation_duration)
42     : ScrollbarAnimationController(),
43       scroll_layer_(scroll_layer),
44       mouse_is_over_scrollbar_(false),
45       mouse_is_near_scrollbar_(false),
46       thickness_change_(NONE),
47       opacity_change_(NONE),
48       should_delay_animation_(false),
49       animation_delay_(animation_delay),
50       animation_duration_(animation_duration),
51       mouse_move_distance_to_trigger_animation_(
52           kDefaultMouseMoveDistanceToTriggerAnimation) {
53   ApplyOpacityAndThumbThicknessScale(kIdleOpacity, kIdleThicknessScale);
54 }
55
56 ScrollbarAnimationControllerThinning::~ScrollbarAnimationControllerThinning() {
57 }
58
59 bool ScrollbarAnimationControllerThinning::IsAnimating() const {
60   return !last_awaken_time_.is_null();
61 }
62
63 base::TimeDelta ScrollbarAnimationControllerThinning::DelayBeforeStart(
64     base::TimeTicks now) const {
65   if (!should_delay_animation_)
66     return base::TimeDelta();
67   if (now > last_awaken_time_ + animation_delay_)
68     return base::TimeDelta();
69   return animation_delay_ - (now - last_awaken_time_);
70 }
71
72 bool ScrollbarAnimationControllerThinning::Animate(base::TimeTicks now) {
73   float progress = AnimationProgressAtTime(now);
74   float opacity = OpacityAtAnimationProgress(progress);
75   float thumb_thickness_scale = ThumbThicknessScaleAtAnimationProgress(
76       progress);
77   ApplyOpacityAndThumbThicknessScale(opacity, thumb_thickness_scale);
78   if (progress == 1.f) {
79     opacity_change_ = NONE;
80     thickness_change_ = NONE;
81     last_awaken_time_ = base::TimeTicks();
82   }
83   return IsAnimating() && DelayBeforeStart(now) == base::TimeDelta();
84 }
85
86 void ScrollbarAnimationControllerThinning::DidScrollGestureBegin() {
87 }
88
89 void ScrollbarAnimationControllerThinning::DidScrollGestureEnd(
90     base::TimeTicks now) {
91 }
92
93 void ScrollbarAnimationControllerThinning::DidMouseMoveOffScrollbar(
94     base::TimeTicks now) {
95   mouse_is_over_scrollbar_ = false;
96   mouse_is_near_scrollbar_ = false;
97   last_awaken_time_ = now;
98   should_delay_animation_ = false;
99   opacity_change_ = DECREASE;
100   thickness_change_ = DECREASE;
101 }
102
103 bool ScrollbarAnimationControllerThinning::DidScrollUpdate(
104     base::TimeTicks now) {
105   ApplyOpacityAndThumbThicknessScale(
106     1, mouse_is_near_scrollbar_ ? 1.f : kIdleThicknessScale);
107
108   last_awaken_time_ = now;
109   should_delay_animation_ = true;
110   if (!mouse_is_over_scrollbar_)
111     opacity_change_ = DECREASE;
112   return true;
113 }
114
115 bool ScrollbarAnimationControllerThinning::DidMouseMoveNear(
116     base::TimeTicks now, float distance) {
117   bool mouse_is_over_scrollbar = distance == 0.0;
118   bool mouse_is_near_scrollbar =
119       distance < mouse_move_distance_to_trigger_animation_;
120
121   if (mouse_is_over_scrollbar == mouse_is_over_scrollbar_ &&
122       mouse_is_near_scrollbar == mouse_is_near_scrollbar_)
123     return false;
124
125   if (mouse_is_over_scrollbar_ != mouse_is_over_scrollbar) {
126     mouse_is_over_scrollbar_ = mouse_is_over_scrollbar;
127     opacity_change_ = mouse_is_over_scrollbar_ ? INCREASE : DECREASE;
128   }
129
130   if (mouse_is_near_scrollbar_ != mouse_is_near_scrollbar) {
131     mouse_is_near_scrollbar_ = mouse_is_near_scrollbar;
132     thickness_change_ = mouse_is_near_scrollbar_ ? INCREASE : DECREASE;
133   }
134
135   last_awaken_time_ = now;
136   should_delay_animation_ = false;
137   return true;
138 }
139
140 float ScrollbarAnimationControllerThinning::AnimationProgressAtTime(
141     base::TimeTicks now) {
142   if (last_awaken_time_.is_null())
143     return 1;
144
145   base::TimeDelta delta = now - last_awaken_time_;
146   if (should_delay_animation_)
147     delta -= animation_delay_;
148   float progress = delta.InSecondsF() / animation_duration_.InSecondsF();
149   return std::max(std::min(progress, 1.f), 0.f);
150 }
151
152 float ScrollbarAnimationControllerThinning::OpacityAtAnimationProgress(
153     float progress) {
154   if (opacity_change_ == NONE)
155     return mouse_is_over_scrollbar_ ? 1.f : kIdleOpacity;
156   float factor = opacity_change_ == INCREASE ? progress : (1.f - progress);
157   float ret = ((1.f - kIdleOpacity) * factor) + kIdleOpacity;
158   return ret;
159 }
160
161 float
162 ScrollbarAnimationControllerThinning::ThumbThicknessScaleAtAnimationProgress(
163     float progress) {
164   if (thickness_change_ == NONE)
165     return mouse_is_near_scrollbar_ ? 1.f : kIdleThicknessScale;
166   float factor = thickness_change_ == INCREASE ? progress : (1.f - progress);
167   return ((1.f - kIdleThicknessScale) * factor) + kIdleThicknessScale;
168 }
169
170 float ScrollbarAnimationControllerThinning::AdjustScale(
171     float new_value,
172     float current_value,
173     AnimationChange animation_change) {
174   if (animation_change == INCREASE && current_value > new_value)
175     return current_value;
176   if (animation_change == DECREASE && current_value < new_value)
177     return current_value;
178   return new_value;
179 }
180
181 void ScrollbarAnimationControllerThinning::ApplyOpacityAndThumbThicknessScale(
182     float opacity, float thumb_thickness_scale) {
183   ScrollbarLayerImplBase* horizontal_scrollbar =
184       scroll_layer_->horizontal_scrollbar_layer();
185   if (horizontal_scrollbar) {
186     horizontal_scrollbar->SetOpacity(
187         AdjustScale(opacity, horizontal_scrollbar->opacity(), opacity_change_));
188     horizontal_scrollbar->SetThumbThicknessScaleFactor(
189         AdjustScale(
190           thumb_thickness_scale,
191           horizontal_scrollbar->thumb_thickness_scale_factor(),
192           thickness_change_));
193   }
194
195   ScrollbarLayerImplBase* vertical_scrollbar =
196       scroll_layer_->vertical_scrollbar_layer();
197   if (vertical_scrollbar) {
198     vertical_scrollbar->SetOpacity(
199         AdjustScale(opacity, vertical_scrollbar->opacity(), opacity_change_));
200     vertical_scrollbar->SetThumbThicknessScaleFactor(
201         AdjustScale(
202           thumb_thickness_scale,
203           vertical_scrollbar->thumb_thickness_scale_factor(),
204           thickness_change_));
205   }
206 }
207
208 }  // namespace cc