| Index: views/controls/scroll_view.cc
|
| diff --git a/views/controls/scroll_view.cc b/views/controls/scroll_view.cc
|
| deleted file mode 100644
|
| index 43d8377c0430c36f1e5787efe84993f91cfa6de5..0000000000000000000000000000000000000000
|
| --- a/views/controls/scroll_view.cc
|
| +++ /dev/null
|
| @@ -1,501 +0,0 @@
|
| -// Copyright (c) 2011 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 "views/controls/scroll_view.h"
|
| -
|
| -#include "base/logging.h"
|
| -#include "ui/views/controls/scrollbar/native_scroll_bar.h"
|
| -#include "ui/views/widget/root_view.h"
|
| -
|
| -namespace views {
|
| -
|
| -const char* const ScrollView::kViewClassName = "views/ScrollView";
|
| -
|
| -// Viewport contains the contents View of the ScrollView.
|
| -class Viewport : public View {
|
| - public:
|
| - Viewport() {}
|
| - virtual ~Viewport() {}
|
| -
|
| - virtual std::string GetClassName() const {
|
| - return "views/Viewport";
|
| - }
|
| -
|
| - virtual void ScrollRectToVisible(const gfx::Rect& rect) {
|
| - if (!has_children() || !parent())
|
| - return;
|
| -
|
| - View* contents = child_at(0);
|
| - gfx::Rect scroll_rect(rect);
|
| - scroll_rect.Offset(-contents->x(), -contents->y());
|
| - static_cast<ScrollView*>(parent())->ScrollContentsRegionToBeVisible(
|
| - scroll_rect);
|
| - }
|
| -
|
| - private:
|
| - DISALLOW_COPY_AND_ASSIGN(Viewport);
|
| -};
|
| -
|
| -
|
| -ScrollView::ScrollView() {
|
| - Init(new NativeScrollBar(true), new NativeScrollBar(false), NULL);
|
| -}
|
| -
|
| -ScrollView::ScrollView(ScrollBar* horizontal_scrollbar,
|
| - ScrollBar* vertical_scrollbar,
|
| - View* resize_corner) {
|
| - Init(horizontal_scrollbar, vertical_scrollbar, resize_corner);
|
| -}
|
| -
|
| -ScrollView::~ScrollView() {
|
| - // If scrollbars are currently not used, delete them
|
| - if (!horiz_sb_->parent())
|
| - delete horiz_sb_;
|
| -
|
| - if (!vert_sb_->parent())
|
| - delete vert_sb_;
|
| -
|
| - if (resize_corner_ && !resize_corner_->parent())
|
| - delete resize_corner_;
|
| -}
|
| -
|
| -void ScrollView::SetContents(View* a_view) {
|
| - if (contents_ && contents_ != a_view) {
|
| - viewport_->RemoveChildView(contents_);
|
| - delete contents_;
|
| - contents_ = NULL;
|
| - }
|
| -
|
| - if (a_view) {
|
| - contents_ = a_view;
|
| - viewport_->AddChildView(contents_);
|
| - }
|
| -
|
| - Layout();
|
| -}
|
| -
|
| -View* ScrollView::GetContents() const {
|
| - return contents_;
|
| -}
|
| -
|
| -void ScrollView::Init(ScrollBar* horizontal_scrollbar,
|
| - ScrollBar* vertical_scrollbar,
|
| - View* resize_corner) {
|
| - DCHECK(horizontal_scrollbar && vertical_scrollbar);
|
| -
|
| - contents_ = NULL;
|
| - horiz_sb_ = horizontal_scrollbar;
|
| - vert_sb_ = vertical_scrollbar;
|
| - resize_corner_ = resize_corner;
|
| -
|
| - viewport_ = new Viewport();
|
| - AddChildView(viewport_);
|
| -
|
| - // Don't add the scrollbars as children until we discover we need them
|
| - // (ShowOrHideScrollBar).
|
| - horiz_sb_->SetVisible(false);
|
| - horiz_sb_->set_controller(this);
|
| - vert_sb_->SetVisible(false);
|
| - vert_sb_->set_controller(this);
|
| - if (resize_corner_)
|
| - resize_corner_->SetVisible(false);
|
| -}
|
| -
|
| -// Make sure that a single scrollbar is created and visible as needed
|
| -void ScrollView::SetControlVisibility(View* control, bool should_show) {
|
| - if (!control)
|
| - return;
|
| - if (should_show) {
|
| - if (!control->IsVisible()) {
|
| - AddChildView(control);
|
| - control->SetVisible(true);
|
| - }
|
| - } else {
|
| - RemoveChildView(control);
|
| - control->SetVisible(false);
|
| - }
|
| -}
|
| -
|
| -void ScrollView::ComputeScrollBarsVisibility(const gfx::Size& vp_size,
|
| - const gfx::Size& content_size,
|
| - bool* horiz_is_shown,
|
| - bool* vert_is_shown) const {
|
| - // Try to fit both ways first, then try vertical bar only, then horizontal
|
| - // bar only, then defaults to both shown.
|
| - if (content_size.width() <= vp_size.width() &&
|
| - content_size.height() <= vp_size.height()) {
|
| - *horiz_is_shown = false;
|
| - *vert_is_shown = false;
|
| - } else if (content_size.width() <= vp_size.width() - GetScrollBarWidth()) {
|
| - *horiz_is_shown = false;
|
| - *vert_is_shown = true;
|
| - } else if (content_size.height() <= vp_size.height() - GetScrollBarHeight()) {
|
| - *horiz_is_shown = true;
|
| - *vert_is_shown = false;
|
| - } else {
|
| - *horiz_is_shown = true;
|
| - *vert_is_shown = true;
|
| - }
|
| -}
|
| -
|
| -void ScrollView::Layout() {
|
| - // Most views will want to auto-fit the available space. Most of them want to
|
| - // use the all available width (without overflowing) and only overflow in
|
| - // height. Examples are HistoryView, MostVisitedView, DownloadTabView, etc.
|
| - // Other views want to fit in both ways. An example is PrintView. To make both
|
| - // happy, assume a vertical scrollbar but no horizontal scrollbar. To
|
| - // override this default behavior, the inner view has to calculate the
|
| - // available space, used ComputeScrollBarsVisibility() to use the same
|
| - // calculation that is done here and sets its bound to fit within.
|
| - gfx::Rect viewport_bounds = GetLocalBounds();
|
| - // Realign it to 0 so it can be used as-is for SetBounds().
|
| - viewport_bounds.set_origin(gfx::Point(0, 0));
|
| - // viewport_size is the total client space available.
|
| - gfx::Size viewport_size = viewport_bounds.size();
|
| - if (viewport_bounds.IsEmpty()) {
|
| - // There's nothing to layout.
|
| - return;
|
| - }
|
| -
|
| - // Assumes a vertical scrollbar since most the current views are designed for
|
| - // this.
|
| - int horiz_sb_height = GetScrollBarHeight();
|
| - int vert_sb_width = GetScrollBarWidth();
|
| - viewport_bounds.set_width(viewport_bounds.width() - vert_sb_width);
|
| - // Update the bounds right now so the inner views can fit in it.
|
| - viewport_->SetBoundsRect(viewport_bounds);
|
| -
|
| - // Give contents_ a chance to update its bounds if it depends on the
|
| - // viewport.
|
| - if (contents_)
|
| - contents_->Layout();
|
| -
|
| - bool should_layout_contents = false;
|
| - bool horiz_sb_required = false;
|
| - bool vert_sb_required = false;
|
| - if (contents_) {
|
| - gfx::Size content_size = contents_->size();
|
| - ComputeScrollBarsVisibility(viewport_size,
|
| - content_size,
|
| - &horiz_sb_required,
|
| - &vert_sb_required);
|
| - }
|
| - bool resize_corner_required = resize_corner_ && horiz_sb_required &&
|
| - vert_sb_required;
|
| - // Take action.
|
| - SetControlVisibility(horiz_sb_, horiz_sb_required);
|
| - SetControlVisibility(vert_sb_, vert_sb_required);
|
| - SetControlVisibility(resize_corner_, resize_corner_required);
|
| -
|
| - // Non-default.
|
| - if (horiz_sb_required) {
|
| - viewport_bounds.set_height(
|
| - std::max(0, viewport_bounds.height() - horiz_sb_height));
|
| - should_layout_contents = true;
|
| - }
|
| - // Default.
|
| - if (!vert_sb_required) {
|
| - viewport_bounds.set_width(viewport_bounds.width() + vert_sb_width);
|
| - should_layout_contents = true;
|
| - }
|
| -
|
| - if (horiz_sb_required) {
|
| - horiz_sb_->SetBounds(0,
|
| - viewport_bounds.bottom(),
|
| - viewport_bounds.right(),
|
| - horiz_sb_height);
|
| - }
|
| - if (vert_sb_required) {
|
| - vert_sb_->SetBounds(viewport_bounds.right(),
|
| - 0,
|
| - vert_sb_width,
|
| - viewport_bounds.bottom());
|
| - }
|
| - if (resize_corner_required) {
|
| - // Show the resize corner.
|
| - resize_corner_->SetBounds(viewport_bounds.right(),
|
| - viewport_bounds.bottom(),
|
| - vert_sb_width,
|
| - horiz_sb_height);
|
| - }
|
| -
|
| - // Update to the real client size with the visible scrollbars.
|
| - viewport_->SetBoundsRect(viewport_bounds);
|
| - if (should_layout_contents && contents_)
|
| - contents_->Layout();
|
| -
|
| - CheckScrollBounds();
|
| - SchedulePaint();
|
| - UpdateScrollBarPositions();
|
| -}
|
| -
|
| -int ScrollView::CheckScrollBounds(int viewport_size,
|
| - int content_size,
|
| - int current_pos) {
|
| - int max = std::max(content_size - viewport_size, 0);
|
| - if (current_pos < 0)
|
| - current_pos = 0;
|
| - else if (current_pos > max)
|
| - current_pos = max;
|
| - return current_pos;
|
| -}
|
| -
|
| -void ScrollView::CheckScrollBounds() {
|
| - if (contents_) {
|
| - int x, y;
|
| -
|
| - x = CheckScrollBounds(viewport_->width(),
|
| - contents_->width(),
|
| - -contents_->x());
|
| - y = CheckScrollBounds(viewport_->height(),
|
| - contents_->height(),
|
| - -contents_->y());
|
| -
|
| - // This is no op if bounds are the same
|
| - contents_->SetBounds(-x, -y, contents_->width(), contents_->height());
|
| - }
|
| -}
|
| -
|
| -gfx::Rect ScrollView::GetVisibleRect() const {
|
| - if (!contents_)
|
| - return gfx::Rect();
|
| -
|
| - const int x =
|
| - (horiz_sb_ && horiz_sb_->IsVisible()) ? horiz_sb_->GetPosition() : 0;
|
| - const int y =
|
| - (vert_sb_ && vert_sb_->IsVisible()) ? vert_sb_->GetPosition() : 0;
|
| - return gfx::Rect(x, y, viewport_->width(), viewport_->height());
|
| -}
|
| -
|
| -void ScrollView::ScrollContentsRegionToBeVisible(const gfx::Rect& rect) {
|
| - if (!contents_ || ((!horiz_sb_ || !horiz_sb_->IsVisible()) &&
|
| - (!vert_sb_ || !vert_sb_->IsVisible()))) {
|
| - return;
|
| - }
|
| -
|
| - // Figure out the maximums for this scroll view.
|
| - const int contents_max_x =
|
| - std::max(viewport_->width(), contents_->width());
|
| - const int contents_max_y =
|
| - std::max(viewport_->height(), contents_->height());
|
| -
|
| - // Make sure x and y are within the bounds of [0,contents_max_*].
|
| - int x = std::max(0, std::min(contents_max_x, rect.x()));
|
| - int y = std::max(0, std::min(contents_max_y, rect.y()));
|
| -
|
| - // Figure out how far and down the rectangle will go taking width
|
| - // and height into account. This will be "clipped" by the viewport.
|
| - const int max_x = std::min(contents_max_x,
|
| - x + std::min(rect.width(), viewport_->width()));
|
| - const int max_y = std::min(contents_max_y,
|
| - y + std::min(rect.height(), viewport_->height()));
|
| -
|
| - // See if the rect is already visible. Note the width is (max_x - x)
|
| - // and the height is (max_y - y) to take into account the clipping of
|
| - // either viewport or the content size.
|
| - const gfx::Rect vis_rect = GetVisibleRect();
|
| - if (vis_rect.Contains(gfx::Rect(x, y, max_x - x, max_y - y)))
|
| - return;
|
| -
|
| - // Shift contents_'s X and Y so that the region is visible. If we
|
| - // need to shift up or left from where we currently are then we need
|
| - // to get it so that the content appears in the upper/left
|
| - // corner. This is done by setting the offset to -X or -Y. For down
|
| - // or right shifts we need to make sure it appears in the
|
| - // lower/right corner. This is calculated by taking max_x or max_y
|
| - // and scaling it back by the size of the viewport.
|
| - const int new_x =
|
| - (vis_rect.x() > x) ? x : std::max(0, max_x - viewport_->width());
|
| - const int new_y =
|
| - (vis_rect.y() > y) ? y : std::max(0, max_y - viewport_->height());
|
| -
|
| - contents_->SetX(-new_x);
|
| - contents_->SetY(-new_y);
|
| - UpdateScrollBarPositions();
|
| -}
|
| -
|
| -void ScrollView::UpdateScrollBarPositions() {
|
| - if (!contents_) {
|
| - return;
|
| - }
|
| -
|
| - if (horiz_sb_->IsVisible()) {
|
| - int vw = viewport_->width();
|
| - int cw = contents_->width();
|
| - int origin = contents_->x();
|
| - horiz_sb_->Update(vw, cw, -origin);
|
| - }
|
| - if (vert_sb_->IsVisible()) {
|
| - int vh = viewport_->height();
|
| - int ch = contents_->height();
|
| - int origin = contents_->y();
|
| - vert_sb_->Update(vh, ch, -origin);
|
| - }
|
| -}
|
| -
|
| -// TODO(ACW): We should really use ScrollWindowEx as needed
|
| -void ScrollView::ScrollToPosition(ScrollBar* source, int position) {
|
| - if (!contents_)
|
| - return;
|
| -
|
| - if (source == horiz_sb_ && horiz_sb_->IsVisible()) {
|
| - int vw = viewport_->width();
|
| - int cw = contents_->width();
|
| - int origin = contents_->x();
|
| - if (-origin != position) {
|
| - int max_pos = std::max(0, cw - vw);
|
| - if (position < 0)
|
| - position = 0;
|
| - else if (position > max_pos)
|
| - position = max_pos;
|
| - contents_->SetX(-position);
|
| - contents_->SchedulePaintInRect(contents_->GetVisibleBounds());
|
| - }
|
| - } else if (source == vert_sb_ && vert_sb_->IsVisible()) {
|
| - int vh = viewport_->height();
|
| - int ch = contents_->height();
|
| - int origin = contents_->y();
|
| - if (-origin != position) {
|
| - int max_pos = std::max(0, ch - vh);
|
| - if (position < 0)
|
| - position = 0;
|
| - else if (position > max_pos)
|
| - position = max_pos;
|
| - contents_->SetY(-position);
|
| - contents_->SchedulePaintInRect(contents_->GetVisibleBounds());
|
| - }
|
| - }
|
| -}
|
| -
|
| -int ScrollView::GetScrollIncrement(ScrollBar* source, bool is_page,
|
| - bool is_positive) {
|
| - bool is_horizontal = source->IsHorizontal();
|
| - int amount = 0;
|
| - View* view = GetContents();
|
| - if (view) {
|
| - if (is_page)
|
| - amount = view->GetPageScrollIncrement(this, is_horizontal, is_positive);
|
| - else
|
| - amount = view->GetLineScrollIncrement(this, is_horizontal, is_positive);
|
| - if (amount > 0)
|
| - return amount;
|
| - }
|
| - // No view, or the view didn't return a valid amount.
|
| - if (is_page)
|
| - return is_horizontal ? viewport_->width() : viewport_->height();
|
| - return is_horizontal ? viewport_->width() / 5 : viewport_->height() / 5;
|
| -}
|
| -
|
| -bool ScrollView::OnKeyPressed(const KeyEvent& event) {
|
| - bool processed = false;
|
| -
|
| - // Give vertical scrollbar priority
|
| - if (vert_sb_->IsVisible()) {
|
| - processed = vert_sb_->OnKeyPressed(event);
|
| - }
|
| -
|
| - if (!processed && horiz_sb_->IsVisible()) {
|
| - processed = horiz_sb_->OnKeyPressed(event);
|
| - }
|
| - return processed;
|
| -}
|
| -
|
| -bool ScrollView::OnMouseWheel(const MouseWheelEvent& e) {
|
| - bool processed = false;
|
| - // Give vertical scrollbar priority
|
| - if (vert_sb_->IsVisible()) {
|
| - processed = vert_sb_->OnMouseWheel(e);
|
| - }
|
| - if (!processed && horiz_sb_->IsVisible()) {
|
| - processed = horiz_sb_->OnMouseWheel(e);
|
| - }
|
| - return processed;
|
| -}
|
| -
|
| -std::string ScrollView::GetClassName() const {
|
| - return kViewClassName;
|
| -}
|
| -
|
| -int ScrollView::GetScrollBarWidth() const {
|
| - return vert_sb_->GetLayoutSize();
|
| -}
|
| -
|
| -int ScrollView::GetScrollBarHeight() const {
|
| - return horiz_sb_->GetLayoutSize();
|
| -}
|
| -
|
| -// VariableRowHeightScrollHelper ----------------------------------------------
|
| -
|
| -VariableRowHeightScrollHelper::VariableRowHeightScrollHelper(
|
| - Controller* controller) : controller_(controller) {
|
| -}
|
| -
|
| -VariableRowHeightScrollHelper::~VariableRowHeightScrollHelper() {
|
| -}
|
| -
|
| -int VariableRowHeightScrollHelper::GetPageScrollIncrement(
|
| - ScrollView* scroll_view, bool is_horizontal, bool is_positive) {
|
| - if (is_horizontal)
|
| - return 0;
|
| - // y coordinate is most likely negative.
|
| - int y = abs(scroll_view->GetContents()->y());
|
| - int vis_height = scroll_view->GetContents()->parent()->height();
|
| - if (is_positive) {
|
| - // Align the bottom most row to the top of the view.
|
| - int bottom = std::min(scroll_view->GetContents()->height() - 1,
|
| - y + vis_height);
|
| - RowInfo bottom_row_info = GetRowInfo(bottom);
|
| - // If 0, ScrollView will provide a default value.
|
| - return std::max(0, bottom_row_info.origin - y);
|
| - } else {
|
| - // Align the row on the previous page to to the top of the view.
|
| - int last_page_y = y - vis_height;
|
| - RowInfo last_page_info = GetRowInfo(std::max(0, last_page_y));
|
| - if (last_page_y != last_page_info.origin)
|
| - return std::max(0, y - last_page_info.origin - last_page_info.height);
|
| - return std::max(0, y - last_page_info.origin);
|
| - }
|
| -}
|
| -
|
| -int VariableRowHeightScrollHelper::GetLineScrollIncrement(
|
| - ScrollView* scroll_view, bool is_horizontal, bool is_positive) {
|
| - if (is_horizontal)
|
| - return 0;
|
| - // y coordinate is most likely negative.
|
| - int y = abs(scroll_view->GetContents()->y());
|
| - RowInfo row = GetRowInfo(y);
|
| - if (is_positive) {
|
| - return row.height - (y - row.origin);
|
| - } else if (y == row.origin) {
|
| - row = GetRowInfo(std::max(0, row.origin - 1));
|
| - return y - row.origin;
|
| - } else {
|
| - return y - row.origin;
|
| - }
|
| -}
|
| -
|
| -VariableRowHeightScrollHelper::RowInfo
|
| - VariableRowHeightScrollHelper::GetRowInfo(int y) {
|
| - return controller_->GetRowInfo(y);
|
| -}
|
| -
|
| -// FixedRowHeightScrollHelper -----------------------------------------------
|
| -
|
| -FixedRowHeightScrollHelper::FixedRowHeightScrollHelper(int top_margin,
|
| - int row_height)
|
| - : VariableRowHeightScrollHelper(NULL),
|
| - top_margin_(top_margin),
|
| - row_height_(row_height) {
|
| - DCHECK_GT(row_height, 0);
|
| -}
|
| -
|
| -VariableRowHeightScrollHelper::RowInfo
|
| - FixedRowHeightScrollHelper::GetRowInfo(int y) {
|
| - if (y < top_margin_)
|
| - return RowInfo(0, top_margin_);
|
| - return RowInfo((y - top_margin_) / row_height_ * row_height_ + top_margin_,
|
| - row_height_);
|
| -}
|
| -
|
| -} // namespace views
|
|
|