Index: cc/top_controls_manager.cc |
diff --git a/cc/top_controls_manager.cc b/cc/top_controls_manager.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..a390d9774b9a2771d2d6302c0f9e4fe4844e78d5 |
--- /dev/null |
+++ b/cc/top_controls_manager.cc |
@@ -0,0 +1,219 @@ |
+// Copyright 2012 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/top_controls_manager.h" |
+ |
+#include <algorithm> |
+ |
+#include "base/bind.h" |
+#include "base/compiler_specific.h" |
+#include "base/logging.h" |
+#include "base/message_loop.h" |
+#include "base/time.h" |
+#include "cc/layer_tree_impl.h" |
+#include "cc/top_controls_animation.h" |
+#include "ui/gfx/transform.h" |
+#include "ui/gfx/vector2d_f.h" |
+ |
+namespace cc { |
+ |
+// static |
+scoped_ptr<TopControlsManager> TopControlsManager::create( |
+ TopControlsDelegate* delegate, bool enabled, float topControlsHeight) { |
+ return make_scoped_ptr(new TopControlsManager(delegate, enabled, |
+ topControlsHeight)); |
+} |
+ |
+TopControlsManager::TopControlsManager(TopControlsDelegate* delegate, |
+ bool enabled, float topControlsHeight) |
+ : ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)), |
+ delegate_(delegate), |
+ enabled_(enabled), |
+ is_overlay_mode_(false), |
+ top_controls_height_(topControlsHeight), |
+ controls_top_offset_(0), |
+ content_top_offset_(topControlsHeight), |
+ top_controls_auto_hide_trigger_time_(-1), |
+ previous_root_scroll_offset_(-1.f) { |
aelias_OOO_until_Jul13
2012/12/19 08:31:18
Use 0 here, not -1.
Ted C
2012/12/19 21:34:17
I need some value to ensure it doesn't update whil
|
+ CHECK(delegate_); |
+} |
+ |
+TopControlsManager::~TopControlsManager() { |
+} |
+ |
+void TopControlsManager::updateDrawPositions() { |
+ if (!enabled_ || !rootScrollLayer()) |
+ return; |
+ |
+ // If the scroll position has changed underneath us (i.e. a javascript |
+ // scroll), then simulate a scroll that covers the delta. |
+ float scrollTotalY = rootScrollLayerTotalScrollY(); |
+ if (previous_root_scroll_offset_ >= 0 |
+ && scrollTotalY != previous_root_scroll_offset_) { |
+ scrollBy(gfx::Vector2dF(0, scrollTotalY - previous_root_scroll_offset_)); |
+ startAnimationIfNecessary(); |
+ previous_root_scroll_offset_ = rootScrollLayerTotalScrollY(); |
+ } |
+ |
+ float offsetTop = is_overlay_mode_ ? 0 : content_top_offset_; |
+ |
+ // The two layers that need to be transformed are the clip layer and root |
+ // scrollbar layers, which are the only two children of the root layer. |
+ LayerImpl* rootLayer = delegate_->activeTree()->RootLayer(); |
+ for (size_t i = 0; i < rootLayer->children().size(); ++i) { |
+ LayerImpl* childLayer = rootLayer->children()[i]; |
+ gfx::Transform transform; |
+ transform.Translate(0, offsetTop); |
+ childLayer->setImplTransform(transform); |
+ } |
+ |
+ // TODO(tedchoc): Adjust fixed position layers as well. |
+} |
+ |
+void TopControlsManager::scrollBegin() { |
+ resetAnimations(); |
+ previous_root_scroll_offset_ = -1; |
aelias_OOO_until_Jul13
2012/12/19 08:31:18
I don't think it's a good idea to have -1 as a mag
|
+} |
+ |
+gfx::Vector2dF TopControlsManager::scrollBy(const gfx::Vector2dF pendingDelta) { |
+ if (!enabled_) |
+ return pendingDelta; |
+ |
+ float scrollTotalY = rootScrollLayerTotalScrollY(); |
+ float scrollDeltaY = pendingDelta.y(); |
+ |
+ float previousControlsOffset = controls_top_offset_; |
+ float previousContentOffset = content_top_offset_; |
+ bool previousWasOverlay = is_overlay_mode_; |
+ |
+ controls_top_offset_ -= scrollDeltaY; |
+ controls_top_offset_ = std::min( |
+ std::max(controls_top_offset_, -top_controls_height_), 0.f); |
+ |
+ if (scrollTotalY > 0 || (scrollTotalY == 0 |
+ && content_top_offset_ < scrollDeltaY)) { |
+ is_overlay_mode_ = true; |
+ content_top_offset_ = 0; |
+ } else if (scrollTotalY <= 0 && (scrollDeltaY < 0 |
+ || (scrollDeltaY > 0 && content_top_offset_ > 0))) { |
+ is_overlay_mode_ = false; |
+ content_top_offset_ -= scrollDeltaY; |
+ } |
+ content_top_offset_ = std::max( |
+ std::min(content_top_offset_, |
+ controls_top_offset_ + top_controls_height_), 0.f); |
+ |
+ gfx::Vector2dF appliedDelta; |
+ if (!previousWasOverlay) |
+ appliedDelta.set_y(previousContentOffset - content_top_offset_); |
+ |
+ if (is_overlay_mode_ != previousWasOverlay |
+ || previousControlsOffset != controls_top_offset_ |
+ || previousContentOffset != content_top_offset_) { |
+ delegate_->setNeedsRedraw(); |
+ delegate_->setNeedsUpdateDrawProperties(); |
+ } |
+ |
+ return pendingDelta - appliedDelta; |
+} |
+ |
+void TopControlsManager::scrollEnd() { |
+ if (!enabled_) |
+ return; |
+ startAnimationIfNecessary(); |
+ previous_root_scroll_offset_ = rootScrollLayerTotalScrollY(); |
+} |
+ |
+void TopControlsManager::animate(base::TimeTicks monotonicTime) { |
+ if (!enabled_) |
+ return; |
+ |
+ if (!top_controls_animation_ || !rootScrollLayer()) |
+ return; |
+ |
+ double time = (monotonicTime - base::TimeTicks()).InSecondsF(); |
+ float newOffset = top_controls_animation_->scrollOffsetAtTime(monotonicTime); |
+ gfx::Vector2dF scrollVector(0.f, -(newOffset - controls_top_offset_)); |
+ scrollBy(scrollVector); |
+ delegate_->setNeedsRedraw(); |
+ |
+ if (top_controls_animation_->isAnimationCompleteAtTime(monotonicTime)) { |
+ top_controls_animation_.reset(); |
+ startAnimationIfNecessary(); |
+ } |
+} |
+ |
+void TopControlsManager::resetAnimations() { |
+ if (!enabled_) |
+ return; |
+ if (top_controls_animation_) |
+ top_controls_animation_.reset(); |
+ top_controls_auto_hide_trigger_time_ = -1; |
+} |
+ |
+LayerImpl* TopControlsManager::rootScrollLayer() { |
+ return delegate_->activeTree()->root_scroll_layer(); |
+} |
+ |
+float TopControlsManager::rootScrollLayerTotalScrollY() { |
+ LayerImpl* layer = rootScrollLayer(); |
+ if (!layer) |
+ return 0; |
+ gfx::Vector2dF scrollTotal = layer->scrollOffset() + layer->scrollDelta(); |
+ return scrollTotal.y(); |
+} |
+ |
+void TopControlsManager::startAnimationIfNecessary() { |
+ if (!enabled_) |
+ return; |
+ |
+ if (!is_overlay_mode_) |
+ return; |
+ |
+ float scrollTotalY; |
aelias_OOO_until_Jul13
2012/12/19 08:31:18
This may be uninitialized. Just change it to:
flo
Ted C
2012/12/19 21:34:17
Done.
|
+ if (rootScrollLayer()) |
+ scrollTotalY = rootScrollLayerTotalScrollY(); |
+ |
+ if (controls_top_offset_ != 0 |
+ && controls_top_offset_ != -top_controls_height_) { |
+ top_controls_animation_ = TopControlsAnimation::create( |
+ controls_top_offset_, |
+ top_controls_height_, |
+ base::TimeTicks::Now(), |
+ base::TimeDelta::FromMilliseconds(kShowHideMaxDurationMs)); |
+ top_controls_animation_->setDirection( |
+ controls_top_offset_ >= -(top_controls_height_ * 0.75f)); |
aelias_OOO_until_Jul13
2012/12/19 08:31:18
Promote 0.75f to a constant at the top of this fil
Ted C
2012/12/19 21:34:17
Done.
|
+ delegate_->setNeedsRedraw(); |
+ } else if (controls_top_offset_ == 0 && scrollTotalY != 0) { |
+ MessageLoop* loop = MessageLoop::current(); |
+ DCHECK(loop); |
+ if (loop) { |
+ int64 triggerTime = top_controls_auto_hide_trigger_time_ = |
+ (base::TimeTicks::Now() - base::TimeTicks()).InMilliseconds(); |
+ loop->PostDelayedTask( |
+ FROM_HERE, |
+ base::Bind(&TopControlsManager::startAutoHideAnimation, |
+ weak_ptr_factory_.GetWeakPtr(), triggerTime), |
+ base::TimeDelta::FromMilliseconds(kAutoHideDelayMs)); |
+ } |
+ } |
+} |
+ |
+void TopControlsManager::startAutoHideAnimation(int64 triggeredTime) { |
+ if (!enabled_) |
+ return; |
+ |
+ if (triggeredTime != top_controls_auto_hide_trigger_time_) |
+ return; |
+ |
+ top_controls_animation_ = TopControlsAnimation::create( |
+ controls_top_offset_, |
+ top_controls_height_, |
+ base::TimeTicks::Now(), |
+ base::TimeDelta::FromMilliseconds(kShowHideMaxDurationMs)); |
+ top_controls_animation_->setDirection(false); |
+ delegate_->setNeedsRedraw(); |
+} |
+ |
+} // namespace cc |