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..4fcb707e518b692c2e904fc60ee2259d0c63d99b |
| --- /dev/null |
| +++ b/cc/top_controls_manager.cc |
| @@ -0,0 +1,203 @@ |
| +// 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/location.h" |
| +#include "base/logging.h" |
| +#include "base/time.h" |
| +#include "cc/layer_tree_impl.h" |
| +#include "cc/top_controls_animation.h" |
| +#include "cc/top_controls_manager_client.h" |
| +#include "ui/gfx/transform.h" |
| +#include "ui/gfx/vector2d_f.h" |
| + |
| +namespace cc { |
| +namespace { |
| +const float kShowHideThreshold = 0.75f; |
|
jamesr
2013/01/08 02:26:48
can you leave a comment here saying where these nu
Ted C
2013/01/08 18:17:33
Done.
|
| +const int64 kAutoHideDelayMs = 1500; |
| +const int64 kShowHideMaxDurationMs = 500; |
| +} |
| + |
| +// static |
| +scoped_ptr<TopControlsManager> TopControlsManager::Create( |
| + TopControlsManagerClient* client, float top_controls_height) { |
| + return make_scoped_ptr(new TopControlsManager(client, top_controls_height)); |
| +} |
| + |
| +TopControlsManager::TopControlsManager(TopControlsManagerClient* client, |
| + float top_controls_height) |
| + : client_(client), |
| + is_overlay_mode_(false), |
| + top_controls_height_(top_controls_height), |
| + controls_top_offset_(0), |
| + content_top_offset_(top_controls_height), |
| + previous_root_scroll_offset_(0.f), |
| + scroll_readjustment_enabled_(false) { |
| + CHECK(client_); |
| +} |
| + |
| +TopControlsManager::~TopControlsManager() { |
| +} |
| + |
| +void TopControlsManager::UpdateDrawPositions() { |
| + if (!RootScrollLayer()) |
| + return; |
| + |
| + // If the scroll position has changed underneath us (i.e. a javascript |
| + // scroll), then simulate a scroll that covers the delta. |
| + float scroll_total_y = RootScrollLayerTotalScrollY(); |
| + if (scroll_readjustment_enabled_ |
| + && scroll_total_y != previous_root_scroll_offset_) { |
| + ScrollBy(gfx::Vector2dF(0, scroll_total_y - previous_root_scroll_offset_)); |
| + StartAnimationIfNecessary(); |
| + previous_root_scroll_offset_ = RootScrollLayerTotalScrollY(); |
| + } |
| + |
| + float offset_top = 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* root_layer = client_->activeTree()->RootLayer(); |
| + for (size_t i = 0; i < root_layer->children().size(); ++i) { |
| + LayerImpl* child_layer = root_layer->children()[i]; |
| + gfx::Transform transform; |
| + transform.Translate(0, offset_top); |
| + child_layer->setImplTransform(transform); |
|
enne (OOO)
2013/01/08 06:23:05
It seems more than a little dangerous that the top
Ted C
2013/01/08 18:17:33
For adjusting the fixed position layers, that migh
|
| + } |
| + |
| + // TODO(tedchoc): Adjust fixed position layers as well. |
| +} |
| + |
| +void TopControlsManager::ScrollBegin() { |
| + ResetAnimations(); |
| + scroll_readjustment_enabled_ = false; |
| +} |
| + |
| +gfx::Vector2dF TopControlsManager::ScrollBy( |
| + const gfx::Vector2dF pending_delta) { |
| + ResetAnimations(); |
| + return ScrollInternal(pending_delta); |
| +} |
| + |
| +gfx::Vector2dF TopControlsManager::ScrollInternal( |
| + const gfx::Vector2dF pending_delta) { |
| + float scroll_total_y = RootScrollLayerTotalScrollY(); |
| + float scroll_delta_y = pending_delta.y(); |
| + |
| + float previous_controls_offset = controls_top_offset_; |
| + float previous_content_offset = content_top_offset_; |
| + bool previous_was_overlay = is_overlay_mode_; |
| + |
| + controls_top_offset_ -= scroll_delta_y; |
| + controls_top_offset_ = std::min( |
| + std::max(controls_top_offset_, -top_controls_height_), 0.f); |
| + |
| + if (scroll_total_y > 0 || (scroll_total_y == 0 |
| + && content_top_offset_ < scroll_delta_y)) { |
| + is_overlay_mode_ = true; |
| + content_top_offset_ = 0; |
| + } else if (scroll_total_y <= 0 && (scroll_delta_y < 0 |
| + || (scroll_delta_y > 0 && content_top_offset_ > 0))) { |
| + is_overlay_mode_ = false; |
| + content_top_offset_ -= scroll_delta_y; |
| + } |
| + content_top_offset_ = std::max( |
| + std::min(content_top_offset_, |
| + controls_top_offset_ + top_controls_height_), 0.f); |
| + |
| + gfx::Vector2dF applied_delta; |
| + if (!previous_was_overlay) |
| + applied_delta.set_y(previous_content_offset - content_top_offset_); |
| + |
| + if (is_overlay_mode_ != previous_was_overlay |
| + || previous_controls_offset != controls_top_offset_ |
| + || previous_content_offset != content_top_offset_) { |
| + client_->setNeedsRedraw(); |
| + client_->setNeedsUpdateDrawProperties(); |
| + } |
| + |
| + return pending_delta - applied_delta; |
| +} |
| + |
| +void TopControlsManager::ScrollEnd() { |
| + StartAnimationIfNecessary(); |
| + previous_root_scroll_offset_ = RootScrollLayerTotalScrollY(); |
| + scroll_readjustment_enabled_ = true; |
| +} |
| + |
| +void TopControlsManager::Animate(base::TimeTicks monotonic_time) { |
| + if (!top_controls_animation_ || !RootScrollLayer()) |
| + return; |
| + |
| + double time = (monotonic_time - base::TimeTicks()).InSecondsF(); |
| + float new_offset = |
| + top_controls_animation_->ScrollOffsetAtTime(monotonic_time); |
| + gfx::Vector2dF scroll_vector(0.f, -(new_offset - controls_top_offset_)); |
| + ScrollInternal(scroll_vector); |
| + client_->setNeedsRedraw(); |
| + |
| + if (top_controls_animation_->IsAnimationCompleteAtTime(monotonic_time)) { |
| + top_controls_animation_.reset(); |
| + StartAnimationIfNecessary(); |
| + } |
| +} |
| + |
| +void TopControlsManager::ResetAnimations() { |
| + if (top_controls_animation_) |
| + top_controls_animation_.reset(); |
| + auto_hide_timer_.Stop(); |
| +} |
| + |
| +LayerImpl* TopControlsManager::RootScrollLayer() { |
| + return client_->activeTree()->root_scroll_layer(); |
| +} |
| + |
| +float TopControlsManager::RootScrollLayerTotalScrollY() { |
| + LayerImpl* layer = RootScrollLayer(); |
| + if (!layer) |
| + return 0; |
| + gfx::Vector2dF scroll_total = layer->scrollOffset() + layer->scrollDelta(); |
| + return scroll_total.y(); |
| +} |
| + |
| +void TopControlsManager::StartAnimationIfNecessary() { |
| + if (!is_overlay_mode_) |
| + return; |
| + |
| + float scroll_total_y = 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_ * kShowHideThreshold)); |
| + client_->setNeedsRedraw(); |
| + } else if (controls_top_offset_ == 0 && scroll_total_y != 0) { |
| + auto_hide_timer_.Stop(); |
| + auto_hide_timer_.Start(FROM_HERE, |
| + base::TimeDelta::FromMilliseconds(kAutoHideDelayMs), |
| + this, |
| + &TopControlsManager::StartAutoHideAnimation); |
| + } |
| +} |
| + |
| +void TopControlsManager::StartAutoHideAnimation() { |
| + top_controls_animation_ = TopControlsAnimation::Create( |
| + controls_top_offset_, |
| + top_controls_height_, |
| + base::TimeTicks::Now(), |
| + base::TimeDelta::FromMilliseconds(kShowHideMaxDurationMs)); |
| + top_controls_animation_->SetDirection(false); |
| + client_->setNeedsRedraw(); |
| +} |
| + |
| +} // namespace cc |