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.
5 #include "cc/animation/scrollbar_animation_controller_thinning.h"
9 #include "base/time/time.h"
10 #include "cc/layers/layer_impl.h"
11 #include "cc/layers/scrollbar_layer_impl_base.h"
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;
23 scoped_ptr
<ScrollbarAnimationControllerThinning
>
24 ScrollbarAnimationControllerThinning::Create(LayerImpl
* scroll_layer
) {
25 return make_scoped_ptr(new ScrollbarAnimationControllerThinning(
27 base::TimeDelta::FromMilliseconds(kDefaultAnimationDelay
),
28 base::TimeDelta::FromMilliseconds(kDefaultAnimationDuration
)));
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
));
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
);
56 ScrollbarAnimationControllerThinning::~ScrollbarAnimationControllerThinning() {
59 bool ScrollbarAnimationControllerThinning::IsAnimating() const {
60 return !last_awaken_time_
.is_null();
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_
);
72 bool ScrollbarAnimationControllerThinning::Animate(base::TimeTicks now
) {
73 float progress
= AnimationProgressAtTime(now
);
74 float opacity
= OpacityAtAnimationProgress(progress
);
75 float thumb_thickness_scale
= ThumbThicknessScaleAtAnimationProgress(
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();
83 return IsAnimating() && DelayBeforeStart(now
) == base::TimeDelta();
86 void ScrollbarAnimationControllerThinning::DidScrollGestureBegin() {
89 void ScrollbarAnimationControllerThinning::DidScrollGestureEnd(
90 base::TimeTicks now
) {
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
;
103 bool ScrollbarAnimationControllerThinning::DidScrollUpdate(
104 base::TimeTicks now
) {
105 ApplyOpacityAndThumbThicknessScale(
106 1, mouse_is_near_scrollbar_
? 1.f
: kIdleThicknessScale
);
108 last_awaken_time_
= now
;
109 should_delay_animation_
= true;
110 if (!mouse_is_over_scrollbar_
)
111 opacity_change_
= DECREASE
;
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_
;
121 if (mouse_is_over_scrollbar
== mouse_is_over_scrollbar_
&&
122 mouse_is_near_scrollbar
== mouse_is_near_scrollbar_
)
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
;
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
;
135 last_awaken_time_
= now
;
136 should_delay_animation_
= false;
140 float ScrollbarAnimationControllerThinning::AnimationProgressAtTime(
141 base::TimeTicks now
) {
142 if (last_awaken_time_
.is_null())
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
);
152 float ScrollbarAnimationControllerThinning::OpacityAtAnimationProgress(
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
;
162 ScrollbarAnimationControllerThinning::ThumbThicknessScaleAtAnimationProgress(
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
;
170 float ScrollbarAnimationControllerThinning::AdjustScale(
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
;
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(
190 thumb_thickness_scale
,
191 horizontal_scrollbar
->thumb_thickness_scale_factor(),
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(
202 thumb_thickness_scale
,
203 vertical_scrollbar
->thumb_thickness_scale_factor(),