Chromium Code Reviews| 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 |