diff options
author | wjmaclean@chromium.org <wjmaclean@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-08-30 20:25:33 +0000 |
---|---|---|
committer | wjmaclean@chromium.org <wjmaclean@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-08-30 20:25:33 +0000 |
commit | 80413d78d7c48360fbcb5a891d05841298e07d3d (patch) | |
tree | 94bd11f2d6f4881cbd6382ca45bd5c35c9fd9c65 /cc/layers/scrollbar_layer_impl_base.cc | |
parent | 2d6a5a2fb1e111096d625bc4021c54d0988ae847 (diff) | |
download | chromium_src-80413d78d7c48360fbcb5a891d05841298e07d3d.zip chromium_src-80413d78d7c48360fbcb5a891d05841298e07d3d.tar.gz chromium_src-80413d78d7c48360fbcb5a891d05841298e07d3d.tar.bz2 |
Refactor cc scrollbar layers architecture.
This CL separates the solid-color scrollbar functionality into its own class structure, resulting in the following hierarchy:
ScrollbarLayerInterface (pure-virtual)
|
-------- PaintedScrollbarLayer (for outer-viewport)
|
--------- SolidColorScrollbarLayer (for inner-viewport)
(Android, pinch-zoom)
ScrollbarLayerImplBase
|
----- PaintedScrollbarLayerImpl (for outer-viewport)
|
----- SolidColorScrollbarLayerImpl (for inner-viewport)
(Android, pinch-zoom)
In this architecture, solid-color scrollbars can live side-by side with regular desktop scrollbars, and no longer require a WebScrollbar in order to be created. The scrolling LayerImpl's only know about ScrollbarLayerImplBase, and the TreeSynchronizer & LTI only deal with *Base layer types.
The ScrollbarLayerImplBase layer is not pure virtual, but rather attempts to collect any common functionality, and the result is much simpler classes for SolidColorScrollbarLayerImpl.
Work remaining:
1) Once the pinch-viewport layers are in place in CC, we can get rid of vertical adjust (I think), and so LTI::UpdateSolidColorScrollbars() can go away. When this goes away, some of the interface for ScrollbarLayerImplBase can be simplified as well.
Review URL: https://chromiumcodereview.appspot.com/18341009
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@220637 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'cc/layers/scrollbar_layer_impl_base.cc')
-rw-r--r-- | cc/layers/scrollbar_layer_impl_base.cc | 156 |
1 files changed, 156 insertions, 0 deletions
diff --git a/cc/layers/scrollbar_layer_impl_base.cc b/cc/layers/scrollbar_layer_impl_base.cc new file mode 100644 index 0000000..9fa32b7 --- /dev/null +++ b/cc/layers/scrollbar_layer_impl_base.cc @@ -0,0 +1,156 @@ +// 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/layers/scrollbar_layer_impl_base.h" + +#include <algorithm> +#include "cc/layers/layer.h" +#include "ui/gfx/rect_conversions.h" + +namespace cc { + +ScrollbarLayerImplBase::ScrollbarLayerImplBase(LayerTreeImpl* tree_impl, + int id, + ScrollbarOrientation orientation) + : LayerImpl(tree_impl, id), + scroll_layer_id_(Layer::INVALID_ID), + is_overlay_scrollbar_(false), + current_pos_(0.f), + maximum_(0), + orientation_(orientation), + vertical_adjust_(0.f), + visible_to_total_length_ratio_(1.f) {} + +void ScrollbarLayerImplBase::PushPropertiesTo(LayerImpl* layer) { + LayerImpl::PushPropertiesTo(layer); +} + +ScrollbarLayerImplBase* ScrollbarLayerImplBase::ToScrollbarLayer() { + return this; +} + +gfx::Rect ScrollbarLayerImplBase::ScrollbarLayerRectToContentRect( + gfx::RectF layer_rect) const { + // Don't intersect with the bounds as in LayerRectToContentRect() because + // layer_rect here might be in coordinates of the containing layer. + gfx::RectF content_rect = gfx::ScaleRect(layer_rect, + contents_scale_x(), + contents_scale_y()); + return gfx::ToEnclosingRect(content_rect); +} + +void ScrollbarLayerImplBase::SetCurrentPos(float current_pos) { + if (current_pos_ == current_pos) + return; + current_pos_ = current_pos; + NoteLayerPropertyChanged(); +} + +void ScrollbarLayerImplBase::SetMaximum(int maximum) { + if (maximum_ == maximum) + return; + maximum_ = maximum; + NoteLayerPropertyChanged(); +} + +void ScrollbarLayerImplBase::SetVerticalAdjust(float vertical_adjust) { + if (vertical_adjust_ == vertical_adjust) + return; + vertical_adjust_ = vertical_adjust; + NoteLayerPropertyChanged(); +} + +void ScrollbarLayerImplBase::SetVisibleToTotalLengthRatio(float ratio) { + if (visible_to_total_length_ratio_ == ratio) + return; + visible_to_total_length_ratio_ = ratio; + NoteLayerPropertyChanged(); +} + +gfx::Rect ScrollbarLayerImplBase::ComputeThumbQuadRect() const { + // Thumb extent is the length of the thumb in the scrolling direction, thumb + // thickness is in the perpendicular direction. Here's an example of a + // horizontal scrollbar - inputs are above the scrollbar, computed values + // below: + // + // |<------------------- track_length_ ------------------->| + // + // |--| <-- start_offset + // + // +--+----------------------------+------------------+-------+--+ + // |<|| |##################| ||>| + // +--+----------------------------+------------------+-------+--+ + // + // |<- thumb_length ->| + // + // |<------- thumb_offset -------->| + // + // For painted, scrollbars, the length is fixed. For solid color scrollbars we + // have to compute it. The ratio of the thumb's length to the track's length + // is the same as that of the visible viewport to the total viewport, unless + // that would make the thumb's length less than its thickness. + // + // vertical_adjust_ is used when the layer geometry from the main thread is + // not in sync with what the user sees. For instance on Android scrolling the + // top bar controls out of view reveals more of the page content. We want the + // root layer scrollbars to reflect what the user sees even if we haven't + // received new layer geometry from the main thread. If the user has scrolled + // down by 50px and the initial viewport size was 950px the geometry would + // look something like this: + // + // vertical_adjust_ = 50, scroll position 0, visible ratios 99% + // Layer geometry: Desired thumb positions: + // +--------------------+-+ +----------------------+ <-- 0px + // | |v| | #| + // | |e| | #| + // | |r| | #| + // | |t| | #| + // | |i| | #| + // | |c| | #| + // | |a| | #| + // | |l| | #| + // | | | | #| + // | |l| | #| + // | |a| | #| + // | |y| | #| + // | |e| | #| + // | |r| | #| + // +--------------------+-+ | #| + // | horizontal layer | | | #| + // +--------------------+-+ | #| <-- 950px + // | | | #| + // | | |##################### | + // +----------------------+ +----------------------+ <-- 1000px + // + // The layer geometry is set up for a 950px tall viewport, but the user can + // actually see down to 1000px. Thus we have to move the quad for the + // horizontal scrollbar down by the vertical_adjust_ factor and lay the + // vertical thumb out on a track lengthed by the vertical_adjust_ factor. This + // means the quads may extend outside the layer's bounds. + + // With the length known, we can compute the thumb's position. + float track_length = TrackLength(); + int thumb_length = ThumbLength(); + int thumb_thickness = ThumbThickness(); + + // With the length known, we can compute the thumb's position. + float clamped_current_pos = + std::min(std::max(current_pos_, 0.f), static_cast<float>(maximum_)); + float ratio = clamped_current_pos / maximum_; + float max_offset = track_length - thumb_length; + int thumb_offset = static_cast<int>(ratio * max_offset) + TrackStart(); + + gfx::RectF thumb_rect; + if (orientation() == HORIZONTAL) { + thumb_rect = gfx::RectF(thumb_offset, vertical_adjust_, + thumb_length, thumb_thickness); + } else { + thumb_rect = gfx::RectF(0.f, thumb_offset, + thumb_thickness, thumb_length); + } + + return ScrollbarLayerRectToContentRect(thumb_rect); +} + +} // namespace cc |