Index: chrome/browser/ui/views/frame/scroll_end_effect_controller_ash.cc |
diff --git a/chrome/browser/ui/views/frame/scroll_end_effect_controller_ash.cc b/chrome/browser/ui/views/frame/scroll_end_effect_controller_ash.cc |
index aa0642821e61bc5cfe4d5932bf978aca44f60377..fcb8f964e6107fa225809ba8f773ad8a90ee0b2e 100644 |
--- a/chrome/browser/ui/views/frame/scroll_end_effect_controller_ash.cc |
+++ b/chrome/browser/ui/views/frame/scroll_end_effect_controller_ash.cc |
@@ -4,16 +4,122 @@ |
#include "chrome/browser/ui/views/frame/scroll_end_effect_controller_ash.h" |
-ScrollEndEffectController* ScrollEndEffectController::Create() { |
- return new ScrollEndEffectControllerAsh(); |
+#include "chrome/browser/ui/views/download/download_shelf_view.h" |
+#include "chrome/browser/ui/views/frame/browser_frame.h" |
+#include "chrome/browser/ui/views/frame/browser_view.h" |
+#include "chrome/browser/ui/views/frame/contents_container.h" |
+#include "content/public/browser/web_contents.h" |
+#include "content/public/browser/web_contents_view.h" |
+#include "ui/aura/window.h" |
+#include "ui/compositor/layer_type.h" |
+#include "ui/gfx/animation/tween.h" |
+#include "ui/gfx/rect_conversions.h" |
+#include "ui/gfx/safe_integer_conversions.h" |
+#include "ui/views/controls/single_split_view.h" |
+#include "ui/views/controls/webview/webview.h" |
+ |
+namespace { |
+// This factor is used to control how much translation is applied relative to |
+// the size of the window. Specifically translation is limited to a max of |
+// window_size * factor. |
+const float kScrollEndEffectFactor = 0.05f; |
+} // namespace |
+ |
+ScrollEndEffectController* ScrollEndEffectController::Create( |
+ ScrollEndEffectControllerDelegate* delegate) { |
+ return new ScrollEndEffectControllerAsh(delegate); |
} |
-ScrollEndEffectControllerAsh::ScrollEndEffectControllerAsh() { |
+ScrollEndEffectControllerAsh::ScrollEndEffectControllerAsh( |
+ ScrollEndEffectControllerDelegate* delegate) |
+ : delegate_(delegate), |
+ is_effect_active_(false), |
+ start_delta_y_(0), |
+ current_delta_y_(0), |
+ end_delta_y_(0) { |
+ animation_.reset(new gfx::SlideAnimation(this)); |
+ animation_->SetSlideDuration(100); |
+ animation_->SetTweenType(gfx::Tween::EASE_OUT); |
} |
ScrollEndEffectControllerAsh::~ScrollEndEffectControllerAsh() { |
} |
void ScrollEndEffectControllerAsh::OverscrollUpdate(int delta_y) { |
- // TODO(rharrison): Implement initial version of scroll end effect |
+ if (!is_effect_active_ && delta_y == 0) |
+ return; |
+ |
+ if (!is_effect_active_) |
+ ActivateEffect(); |
+ |
+ int capped_delta_y = delta_y; |
+ // Limiting the delta size being a proportion of the frame bounds size. |
+ if (capped_delta_y > 0) { |
+ capped_delta_y = std::min(gfx::ToRoundedInt((frame_bounds_.height() * |
+ kScrollEndEffectFactor)), |
+ capped_delta_y); |
+ } else if (capped_delta_y < 0) { |
+ capped_delta_y = -std::min(gfx::ToRoundedInt((frame_bounds_.height() * |
+ kScrollEndEffectFactor)), |
+ -capped_delta_y); |
+ } |
+ |
+ start_delta_y_ = current_delta_y_; |
+ end_delta_y_ = capped_delta_y; |
+ if (end_delta_y_ == 0) { |
+ animation_->Reset(); |
+ animation_->Show(); |
+ if (animation_->GetSlideDuration() == 0) { |
+ AnimationProgressed(animation_.get()); |
+ AnimationEnded(animation_.get()); |
+ } |
+ } else { |
+ animation_->Reset(); |
+ ApplyDelta(end_delta_y_); |
+ } |
+} |
+ |
+void ScrollEndEffectControllerAsh::AnimationEnded( |
+ const gfx::Animation* animation) { |
+ if (current_delta_y_ == 0) |
+ DeactivateEffect(); |
+} |
+ |
+void ScrollEndEffectControllerAsh::AnimationProgressed( |
+ const gfx::Animation* animation) { |
+ ApplyDelta(gfx::Tween::IntValueBetween(animation_->GetCurrentValue(), |
+ start_delta_y_, |
+ end_delta_y_)); |
+} |
+ |
+void ScrollEndEffectControllerAsh::ActivateEffect() { |
+ is_effect_active_ = true; |
+ frame_bounds_ = delegate_->GetFrameBounds(); |
+ delegate_->GetContentsContainer()->ActivateScrollEndEffect(); |
+} |
+ |
+void ScrollEndEffectControllerAsh::DeactivateEffect() { |
+ is_effect_active_ = false; |
+ delegate_->SetFrameBounds(frame_bounds_); |
+ delegate_->GetContentsContainer()->DeactivateScrollEndEffect(); |
+} |
+ |
+void ScrollEndEffectControllerAsh::ApplyDelta(int delta_y) { |
+ current_delta_y_ = delta_y; |
+ gfx::Rect bounds = frame_bounds_; |
+ |
+ float scale_factor = 1.0f - static_cast<float>(std::abs(current_delta_y_)) / |
+ static_cast<float>(bounds.height()); |
+ |
+ bounds.set_height(gfx::ToRoundedInt(bounds.height() * scale_factor)); |
+ bool scrolling_down = current_delta_y_ > 0; |
+ if (scrolling_down) { |
+ gfx::Point bounds_orig = bounds.origin(); |
+ bounds_orig.set_y(bounds_orig.y() + current_delta_y_); |
+ bounds.set_origin(bounds_orig); |
+ } |
+ delegate_->SetFrameBounds(bounds); |
+ delegate_->GetContentsContainer()-> |
+ UpdateScrollEndEffectHeightDelta(frame_bounds_.height() - bounds.height(), |
+ scrolling_down); |
} |