root/cc/animation/scrollbar_animation_controller_thinning.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. Create
  2. CreateForTest
  3. mouse_move_distance_to_trigger_animation_
  4. IsAnimating
  5. DelayBeforeStart
  6. Animate
  7. DidScrollGestureBegin
  8. DidScrollGestureEnd
  9. DidMouseMoveOffScrollbar
  10. DidScrollUpdate
  11. DidMouseMoveNear
  12. AnimationProgressAtTime
  13. OpacityAtAnimationProgress
  14. ThumbThicknessScaleAtAnimationProgress
  15. AdjustScale
  16. ApplyOpacityAndThumbThicknessScale

// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "cc/animation/scrollbar_animation_controller_thinning.h"

#include <algorithm>

#include "base/time/time.h"
#include "cc/layers/layer_impl.h"
#include "cc/layers/scrollbar_layer_impl_base.h"

namespace {
const float kIdleThicknessScale = 0.4f;
const float kIdleOpacity = 0.7f;
const float kDefaultMouseMoveDistanceToTriggerAnimation = 25.f;
const int kDefaultAnimationDelay = 500;
const int kDefaultAnimationDuration = 300;
}

namespace cc {

scoped_ptr<ScrollbarAnimationControllerThinning>
ScrollbarAnimationControllerThinning::Create(LayerImpl* scroll_layer) {
  return make_scoped_ptr(new ScrollbarAnimationControllerThinning(
      scroll_layer,
      base::TimeDelta::FromMilliseconds(kDefaultAnimationDelay),
      base::TimeDelta::FromMilliseconds(kDefaultAnimationDuration)));
}

scoped_ptr<ScrollbarAnimationControllerThinning>
ScrollbarAnimationControllerThinning::CreateForTest(LayerImpl* scroll_layer,
    base::TimeDelta animation_delay, base::TimeDelta animation_duration) {
  return make_scoped_ptr(new ScrollbarAnimationControllerThinning(
      scroll_layer, animation_delay, animation_duration));
}

ScrollbarAnimationControllerThinning::ScrollbarAnimationControllerThinning(
    LayerImpl* scroll_layer,
    base::TimeDelta animation_delay,
    base::TimeDelta animation_duration)
    : ScrollbarAnimationController(),
      scroll_layer_(scroll_layer),
      mouse_is_over_scrollbar_(false),
      mouse_is_near_scrollbar_(false),
      thickness_change_(NONE),
      opacity_change_(NONE),
      should_delay_animation_(false),
      animation_delay_(animation_delay),
      animation_duration_(animation_duration),
      mouse_move_distance_to_trigger_animation_(
          kDefaultMouseMoveDistanceToTriggerAnimation) {
  ApplyOpacityAndThumbThicknessScale(kIdleOpacity, kIdleThicknessScale);
}

ScrollbarAnimationControllerThinning::~ScrollbarAnimationControllerThinning() {
}

bool ScrollbarAnimationControllerThinning::IsAnimating() const {
  return !last_awaken_time_.is_null();
}

base::TimeDelta ScrollbarAnimationControllerThinning::DelayBeforeStart(
    base::TimeTicks now) const {
  if (!should_delay_animation_)
    return base::TimeDelta();
  if (now > last_awaken_time_ + animation_delay_)
    return base::TimeDelta();
  return animation_delay_ - (now - last_awaken_time_);
}

bool ScrollbarAnimationControllerThinning::Animate(base::TimeTicks now) {
  float progress = AnimationProgressAtTime(now);
  float opacity = OpacityAtAnimationProgress(progress);
  float thumb_thickness_scale = ThumbThicknessScaleAtAnimationProgress(
      progress);
  ApplyOpacityAndThumbThicknessScale(opacity, thumb_thickness_scale);
  if (progress == 1.f) {
    opacity_change_ = NONE;
    thickness_change_ = NONE;
    last_awaken_time_ = base::TimeTicks();
  }
  return IsAnimating() && DelayBeforeStart(now) == base::TimeDelta();
}

void ScrollbarAnimationControllerThinning::DidScrollGestureBegin() {
}

void ScrollbarAnimationControllerThinning::DidScrollGestureEnd(
    base::TimeTicks now) {
}

void ScrollbarAnimationControllerThinning::DidMouseMoveOffScrollbar(
    base::TimeTicks now) {
  mouse_is_over_scrollbar_ = false;
  mouse_is_near_scrollbar_ = false;
  last_awaken_time_ = now;
  should_delay_animation_ = false;
  opacity_change_ = DECREASE;
  thickness_change_ = DECREASE;
}

bool ScrollbarAnimationControllerThinning::DidScrollUpdate(
    base::TimeTicks now) {
  ApplyOpacityAndThumbThicknessScale(
    1, mouse_is_near_scrollbar_ ? 1.f : kIdleThicknessScale);

  last_awaken_time_ = now;
  should_delay_animation_ = true;
  if (!mouse_is_over_scrollbar_)
    opacity_change_ = DECREASE;
  return true;
}

bool ScrollbarAnimationControllerThinning::DidMouseMoveNear(
    base::TimeTicks now, float distance) {
  bool mouse_is_over_scrollbar = distance == 0.0;
  bool mouse_is_near_scrollbar =
      distance < mouse_move_distance_to_trigger_animation_;

  if (mouse_is_over_scrollbar == mouse_is_over_scrollbar_ &&
      mouse_is_near_scrollbar == mouse_is_near_scrollbar_)
    return false;

  if (mouse_is_over_scrollbar_ != mouse_is_over_scrollbar) {
    mouse_is_over_scrollbar_ = mouse_is_over_scrollbar;
    opacity_change_ = mouse_is_over_scrollbar_ ? INCREASE : DECREASE;
  }

  if (mouse_is_near_scrollbar_ != mouse_is_near_scrollbar) {
    mouse_is_near_scrollbar_ = mouse_is_near_scrollbar;
    thickness_change_ = mouse_is_near_scrollbar_ ? INCREASE : DECREASE;
  }

  last_awaken_time_ = now;
  should_delay_animation_ = false;
  return true;
}

float ScrollbarAnimationControllerThinning::AnimationProgressAtTime(
    base::TimeTicks now) {
  if (last_awaken_time_.is_null())
    return 1;

  base::TimeDelta delta = now - last_awaken_time_;
  if (should_delay_animation_)
    delta -= animation_delay_;
  float progress = delta.InSecondsF() / animation_duration_.InSecondsF();
  return std::max(std::min(progress, 1.f), 0.f);
}

float ScrollbarAnimationControllerThinning::OpacityAtAnimationProgress(
    float progress) {
  if (opacity_change_ == NONE)
    return mouse_is_over_scrollbar_ ? 1.f : kIdleOpacity;
  float factor = opacity_change_ == INCREASE ? progress : (1.f - progress);
  float ret = ((1.f - kIdleOpacity) * factor) + kIdleOpacity;
  return ret;
}

float
ScrollbarAnimationControllerThinning::ThumbThicknessScaleAtAnimationProgress(
    float progress) {
  if (thickness_change_ == NONE)
    return mouse_is_near_scrollbar_ ? 1.f : kIdleThicknessScale;
  float factor = thickness_change_ == INCREASE ? progress : (1.f - progress);
  return ((1.f - kIdleThicknessScale) * factor) + kIdleThicknessScale;
}

float ScrollbarAnimationControllerThinning::AdjustScale(
    float new_value,
    float current_value,
    AnimationChange animation_change) {
  if (animation_change == INCREASE && current_value > new_value)
    return current_value;
  if (animation_change == DECREASE && current_value < new_value)
    return current_value;
  return new_value;
}

void ScrollbarAnimationControllerThinning::ApplyOpacityAndThumbThicknessScale(
    float opacity, float thumb_thickness_scale) {
  if (!scroll_layer_->scrollbars())
    return;

  LayerImpl::ScrollbarSet* scrollbars = scroll_layer_->scrollbars();
  for (LayerImpl::ScrollbarSet::iterator it = scrollbars->begin();
       it != scrollbars->end();
       ++it) {
    ScrollbarLayerImplBase* scrollbar = *it;
    if (scrollbar->is_overlay_scrollbar()) {
      scrollbar->SetOpacity(
          AdjustScale(opacity, scrollbar->opacity(), opacity_change_));
      scrollbar->SetThumbThicknessScaleFactor(
          AdjustScale(thumb_thickness_scale,
                      scrollbar->thumb_thickness_scale_factor(),
                      thickness_change_));
    }
  }
}

}  // namespace cc

/* [<][>][^][v][top][bottom][index][help] */