15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/controls/scroll_view.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 8d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "ui/events/event.h" 96e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "ui/gfx/canvas.h" 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/native_theme/native_theme.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/border.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/controls/scrollbar/native_scroll_bar.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/widget/root_view.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace views { 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)const char ScrollView::kViewClassName[] = "ScrollView"; 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Subclass of ScrollView that resets the border when the theme changes. 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ScrollViewWithBorder : public views::ScrollView { 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ScrollViewWithBorder() {} 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // View overrides; 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnNativeThemeChanged(const ui::NativeTheme* theme) OVERRIDE { 285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SetBorder(Border::CreateSolidBorder( 295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1, 305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu theme->GetSystemColor(ui::NativeTheme::kColorId_UnfocusedBorderColor))); 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu private: 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(ScrollViewWithBorder); 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)class ScrollCornerView : public views::View { 386e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) public: 396e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) ScrollCornerView() {} 406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE { 426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) ui::NativeTheme::ExtraParams ignored; 436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) GetNativeTheme()->Paint(canvas->sk_canvas(), 446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) ui::NativeTheme::kScrollbarCorner, 456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) ui::NativeTheme::kNormal, 466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) GetLocalBounds(), 476e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) ignored); 486e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 496e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 506e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) private: 516e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(ScrollCornerView); 526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}; 536e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Returns the position for the view so that it isn't scrolled off the visible 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// region. 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int CheckScrollBounds(int viewport_size, int content_size, int current_pos) { 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int max = std::max(content_size - viewport_size, 0); 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (current_pos < 0) 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return 0; 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (current_pos > max) 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return max; 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return current_pos; 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Make sure the content is not scrolled out of bounds 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void CheckScrollBounds(View* viewport, View* view) { 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!view) 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int x = CheckScrollBounds(viewport->width(), view->width(), -view->x()); 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int y = CheckScrollBounds(viewport->height(), view->height(), -view->y()); 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // This is no op if bounds are the same 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) view->SetBounds(-x, -y, view->width(), view->height()); 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Used by ScrollToPosition() to make sure the new position fits within the 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// allowed scroll range. 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int AdjustPosition(int current_position, 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int new_position, 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int content_size, 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int viewport_size) { 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (-current_position == new_position) 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return new_position; 852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (new_position < 0) 862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return 0; 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const int max_position = std::max(0, content_size - viewport_size); 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return (new_position > max_position) ? max_position : new_position; 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Viewport contains the contents View of the ScrollView. 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class ScrollView::Viewport : public View { 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Viewport() {} 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~Viewport() {} 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 99b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) virtual const char* GetClassName() const OVERRIDE { 100b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return "ScrollView::Viewport"; 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void ScrollRectToVisible(const gfx::Rect& rect) OVERRIDE { 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!has_children() || !parent()) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) View* contents = child_at(0); 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Rect scroll_rect(rect); 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scroll_rect.Offset(-contents->x(), -contents->y()); 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<ScrollView*>(parent())->ScrollContentsRegionToBeVisible( 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scroll_rect); 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void ChildPreferredSizeChanged(View* child) OVERRIDE { 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (parent()) 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parent()->Layout(); 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(Viewport); 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ScrollView::ScrollView() 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : contents_(NULL), 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) contents_viewport_(new Viewport()), 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) header_(NULL), 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) header_viewport_(new Viewport()), 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) horiz_sb_(new NativeScrollBar(true)), 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) vert_sb_(new NativeScrollBar(false)), 1306e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) corner_view_(new ScrollCornerView()), 131effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch min_height_(-1), 132effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch max_height_(-1), 133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) hide_horizontal_scrollbar_(false) { 1345e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) set_notify_enter_exit_on_child(true); 1355e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AddChildView(contents_viewport_); 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AddChildView(header_viewport_); 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Don't add the scrollbars as children until we discover we need them 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // (ShowOrHideScrollBar). 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) horiz_sb_->SetVisible(false); 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) horiz_sb_->set_controller(this); 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) vert_sb_->SetVisible(false); 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) vert_sb_->set_controller(this); 1456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) corner_view_->SetVisible(false); 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ScrollView::~ScrollView() { 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The scrollbars may not have been added, delete them to ensure they get 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // deleted. 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delete horiz_sb_; 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delete vert_sb_; 1536e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) delete corner_view_; 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ScrollView* ScrollView::CreateScrollViewWithBorder() { 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return new ScrollViewWithBorder(); 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ScrollView::SetContents(View* a_view) { 1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SetHeaderOrContents(contents_viewport_, a_view, &contents_); 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ScrollView::SetHeader(View* header) { 1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SetHeaderOrContents(header_viewport_, header, &header_); 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)gfx::Rect ScrollView::GetVisibleRect() const { 1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!contents_) 1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return gfx::Rect(); 1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return gfx::Rect(-contents_->x(), -contents_->y(), 1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) contents_viewport_->width(), contents_viewport_->height()); 1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 176effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid ScrollView::ClipHeightTo(int min_height, int max_height) { 177effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch min_height_ = min_height; 178effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch max_height_ = max_height; 179effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 180effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int ScrollView::GetScrollBarWidth() const { 1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return vert_sb_ ? vert_sb_->GetLayoutSize() : 0; 1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int ScrollView::GetScrollBarHeight() const { 1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return horiz_sb_ ? horiz_sb_->GetLayoutSize() : 0; 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ScrollView::SetHorizontalScrollBar(ScrollBar* horiz_sb) { 1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(horiz_sb); 1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) horiz_sb->SetVisible(horiz_sb_->visible()); 1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delete horiz_sb_; 1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) horiz_sb->set_controller(this); 1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) horiz_sb_ = horiz_sb; 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ScrollView::SetVerticalScrollBar(ScrollBar* vert_sb) { 1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(vert_sb); 1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) vert_sb->SetVisible(vert_sb_->visible()); 2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delete vert_sb_; 2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) vert_sb->set_controller(this); 2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) vert_sb_ = vert_sb; 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 205cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)gfx::Size ScrollView::GetPreferredSize() const { 206effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (!is_bounded()) 207effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return View::GetPreferredSize(); 208effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 209effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch gfx::Size size = contents()->GetPreferredSize(); 210effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch size.SetToMax(gfx::Size(size.width(), min_height_)); 211effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch size.SetToMin(gfx::Size(size.width(), max_height_)); 212effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch gfx::Insets insets = GetInsets(); 213effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch size.Enlarge(insets.width(), insets.height()); 214effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return size; 215effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 216effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 217cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)int ScrollView::GetHeightForWidth(int width) const { 218effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (!is_bounded()) 219effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return View::GetHeightForWidth(width); 220effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 221effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch gfx::Insets insets = GetInsets(); 222effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch width = std::max(0, width - insets.width()); 223effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch int height = contents()->GetHeightForWidth(width) + insets.height(); 224effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return std::min(std::max(height, min_height_), max_height_); 225effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 226effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ScrollView::Layout() { 228effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (is_bounded()) { 229effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch int content_width = width(); 230effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch int content_height = contents()->GetHeightForWidth(content_width); 231effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (content_height > height()) { 232effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch content_width = std::max(content_width - GetScrollBarWidth(), 0); 233effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch content_height = contents()->GetHeightForWidth(content_width); 234effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 235effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (contents()->bounds().size() != gfx::Size(content_width, content_height)) 236effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch contents()->SetBounds(0, 0, content_width, content_height); 237effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 238effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Most views will want to auto-fit the available space. Most of them want to 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // use all available width (without overflowing) and only overflow in 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // height. Examples are HistoryView, MostVisitedView, DownloadTabView, etc. 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Other views want to fit in both ways. An example is PrintView. To make both 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // happy, assume a vertical scrollbar but no horizontal scrollbar. To override 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // this default behavior, the inner view has to calculate the available space, 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // used ComputeScrollBarsVisibility() to use the same calculation that is done 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // here and sets its bound to fit within. 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Rect viewport_bounds = GetContentsBounds(); 2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const int contents_x = viewport_bounds.x(); 2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const int contents_y = viewport_bounds.y(); 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (viewport_bounds.IsEmpty()) { 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // There's nothing to layout. 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const int header_height = 2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::min(viewport_bounds.height(), 2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) header_ ? header_->GetPreferredSize().height() : 0); 2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) viewport_bounds.set_height( 2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::max(0, viewport_bounds.height() - header_height)); 2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) viewport_bounds.set_y(viewport_bounds.y() + header_height); 2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // viewport_size is the total client space available. 2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gfx::Size viewport_size = viewport_bounds.size(); 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Assumes a vertical scrollbar since most of the current views are designed 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // for this. 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int horiz_sb_height = GetScrollBarHeight(); 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int vert_sb_width = GetScrollBarWidth(); 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) viewport_bounds.set_width(viewport_bounds.width() - vert_sb_width); 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Update the bounds right now so the inner views can fit in it. 2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) contents_viewport_->SetBoundsRect(viewport_bounds); 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Give |contents_| a chance to update its bounds if it depends on the 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // viewport. 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (contents_) 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) contents_->Layout(); 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool should_layout_contents = false; 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool horiz_sb_required = false; 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool vert_sb_required = false; 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (contents_) { 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Size content_size = contents_->size(); 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ComputeScrollBarsVisibility(viewport_size, 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content_size, 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &horiz_sb_required, 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &vert_sb_required); 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2866e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) bool corner_view_required = horiz_sb_required && vert_sb_required; 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Take action. 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetControlVisibility(horiz_sb_, horiz_sb_required); 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetControlVisibility(vert_sb_, vert_sb_required); 2906e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) SetControlVisibility(corner_view_, corner_view_required); 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Non-default. 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (horiz_sb_required) { 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) viewport_bounds.set_height( 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::max(0, viewport_bounds.height() - horiz_sb_height)); 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) should_layout_contents = true; 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Default. 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!vert_sb_required) { 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) viewport_bounds.set_width(viewport_bounds.width() + vert_sb_width); 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) should_layout_contents = true; 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (horiz_sb_required) { 3055e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) int height_offset = horiz_sb_->GetContentOverlapSize(); 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) horiz_sb_->SetBounds(0, 3075e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) viewport_bounds.bottom() - height_offset, 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) viewport_bounds.right(), 3095e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) horiz_sb_height + height_offset); 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (vert_sb_required) { 3125e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) int width_offset = vert_sb_->GetContentOverlapSize(); 3135e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) vert_sb_->SetBounds(viewport_bounds.right() - width_offset, 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, 3155e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) vert_sb_width + width_offset, 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) viewport_bounds.bottom()); 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3186e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (corner_view_required) { 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Show the resize corner. 3206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) corner_view_->SetBounds(viewport_bounds.right(), 3216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) viewport_bounds.bottom(), 3226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) vert_sb_width, 3236e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) horiz_sb_height); 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Update to the real client size with the visible scrollbars. 3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) contents_viewport_->SetBoundsRect(viewport_bounds); 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (should_layout_contents && contents_) 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) contents_->Layout(); 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) header_viewport_->SetBounds(contents_x, contents_y, 3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) viewport_bounds.width(), header_height); 3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (header_) 3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) header_->Layout(); 3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CheckScrollBounds(header_viewport_, header_); 3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CheckScrollBounds(contents_viewport_, contents_); 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SchedulePaint(); 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateScrollBarPositions(); 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool ScrollView::OnKeyPressed(const ui::KeyEvent& event) { 3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool processed = false; 3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Give vertical scrollbar priority 3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (vert_sb_->visible()) 3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) processed = vert_sb_->OnKeyPressed(event); 3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!processed && horiz_sb_->visible()) 3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) processed = horiz_sb_->OnKeyPressed(event); 3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return processed; 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool ScrollView::OnMouseWheel(const ui::MouseWheelEvent& e) { 3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool processed = false; 3571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (vert_sb_->visible()) 3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) processed = vert_sb_->OnMouseWheel(e); 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (horiz_sb_->visible()) 3621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci processed = horiz_sb_->OnMouseWheel(e) || processed; 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return processed; 3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3675e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)void ScrollView::OnMouseEntered(const ui::MouseEvent& event) { 3685e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) if (horiz_sb_) 3695e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) horiz_sb_->OnMouseEnteredScrollView(event); 3705e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) if (vert_sb_) 3715e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) vert_sb_->OnMouseEnteredScrollView(event); 3725e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)} 3735e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) 3745e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)void ScrollView::OnMouseExited(const ui::MouseEvent& event) { 3755e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) if (horiz_sb_) 3765e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) horiz_sb_->OnMouseExitedScrollView(event); 3775e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) if (vert_sb_) 3785e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) vert_sb_->OnMouseExitedScrollView(event); 3795e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)} 3805e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles) 3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ScrollView::OnGestureEvent(ui::GestureEvent* event) { 3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If the event happened on one of the scrollbars, then those events are 3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // sent directly to the scrollbars. Otherwise, only scroll events are sent to 3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // the scrollbars. 3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool scroll_event = event->type() == ui::ET_GESTURE_SCROLL_UPDATE || 3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) event->type() == ui::ET_GESTURE_SCROLL_BEGIN || 3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) event->type() == ui::ET_GESTURE_SCROLL_END || 3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) event->type() == ui::ET_SCROLL_FLING_START; 3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (vert_sb_->visible()) { 3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (vert_sb_->bounds().Contains(event->location()) || scroll_event) 3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) vert_sb_->OnGestureEvent(event); 3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!event->handled() && horiz_sb_->visible()) { 3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (horiz_sb_->bounds().Contains(event->location()) || scroll_event) 3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) horiz_sb_->OnGestureEvent(event); 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 400b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)const char* ScrollView::GetClassName() const { 4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return kViewClassName; 4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ScrollView::ScrollToPosition(ScrollBar* source, int position) { 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!contents_) 4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (source == horiz_sb_ && horiz_sb_->visible()) { 4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) position = AdjustPosition(contents_->x(), position, contents_->width(), 4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) contents_viewport_->width()); 4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (-contents_->x() == position) 4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) contents_->SetX(-position); 4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (header_) { 4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) header_->SetX(-position); 4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) header_->SchedulePaintInRect(header_->GetVisibleBounds()); 4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else if (source == vert_sb_ && vert_sb_->visible()) { 4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) position = AdjustPosition(contents_->y(), position, contents_->height(), 4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) contents_viewport_->height()); 4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (-contents_->y() == position) 4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) contents_->SetY(-position); 4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) contents_->SchedulePaintInRect(contents_->GetVisibleBounds()); 4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int ScrollView::GetScrollIncrement(ScrollBar* source, bool is_page, 4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool is_positive) { 4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool is_horizontal = source->IsHorizontal(); 4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int amount = 0; 4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (contents_) { 4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (is_page) { 4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) amount = contents_->GetPageScrollIncrement( 4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this, is_horizontal, is_positive); 4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) amount = contents_->GetLineScrollIncrement( 4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this, is_horizontal, is_positive); 4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (amount > 0) 4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return amount; 4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // No view, or the view didn't return a valid amount. 4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (is_page) { 4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return is_horizontal ? contents_viewport_->width() : 4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) contents_viewport_->height(); 4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return is_horizontal ? contents_viewport_->width() / 5 : 4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) contents_viewport_->height() / 5; 4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ScrollView::SetHeaderOrContents(View* parent, 4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) View* new_view, 4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) View** member) { 4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (*member == new_view) 4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delete *member; 4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *member = new_view; 4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (*member) 4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) parent->AddChildView(*member); 4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Layout(); 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ScrollView::ScrollContentsRegionToBeVisible(const gfx::Rect& rect) { 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!contents_ || (!horiz_sb_->visible() && !vert_sb_->visible())) 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Figure out the maximums for this scroll view. 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int contents_max_x = 4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::max(contents_viewport_->width(), contents_->width()); 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int contents_max_y = 4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::max(contents_viewport_->height(), contents_->height()); 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make sure x and y are within the bounds of [0,contents_max_*]. 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int x = std::max(0, std::min(contents_max_x, rect.x())); 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int y = std::max(0, std::min(contents_max_y, rect.y())); 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Figure out how far and down the rectangle will go taking width 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and height into account. This will be "clipped" by the viewport. 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int max_x = std::min(contents_max_x, 4822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) x + std::min(rect.width(), contents_viewport_->width())); 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int max_y = std::min(contents_max_y, 4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) y + std::min(rect.height(), contents_viewport_->height())); 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // See if the rect is already visible. Note the width is (max_x - x) 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and the height is (max_y - y) to take into account the clipping of 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // either viewport or the content size. 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Rect vis_rect = GetVisibleRect(); 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (vis_rect.Contains(gfx::Rect(x, y, max_x - x, max_y - y))) 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Shift contents_'s X and Y so that the region is visible. If we 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // need to shift up or left from where we currently are then we need 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to get it so that the content appears in the upper/left 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // corner. This is done by setting the offset to -X or -Y. For down 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // or right shifts we need to make sure it appears in the 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // lower/right corner. This is calculated by taking max_x or max_y 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and scaling it back by the size of the viewport. 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int new_x = 5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (vis_rect.x() > x) ? x : std::max(0, max_x - contents_viewport_->width()); 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int new_y = 5032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (vis_rect.y() > y) ? y : std::max(0, max_y - 5042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) contents_viewport_->height()); 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) contents_->SetX(-new_x); 5072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (header_) 5082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) header_->SetX(-new_x); 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) contents_->SetY(-new_y); 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateScrollBarPositions(); 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ScrollView::ComputeScrollBarsVisibility(const gfx::Size& vp_size, 5142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const gfx::Size& content_size, 5152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool* horiz_is_shown, 5162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool* vert_is_shown) const { 5172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Try to fit both ways first, then try vertical bar only, then horizontal 5182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // bar only, then defaults to both shown. 5192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (content_size.width() <= vp_size.width() && 5202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) content_size.height() <= vp_size.height()) { 5212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *horiz_is_shown = false; 5222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *vert_is_shown = false; 5232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else if (content_size.width() <= vp_size.width() - GetScrollBarWidth()) { 5242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *horiz_is_shown = false; 5252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *vert_is_shown = true; 5262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else if (content_size.height() <= vp_size.height() - GetScrollBarHeight()) { 5272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *horiz_is_shown = true; 5282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *vert_is_shown = false; 5292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 5302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *horiz_is_shown = true; 5312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *vert_is_shown = true; 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 533c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 534c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (hide_horizontal_scrollbar_) 535c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *horiz_is_shown = false; 5362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Make sure that a single scrollbar is created and visible as needed 5392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ScrollView::SetControlVisibility(View* control, bool should_show) { 5402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!control) 5412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 5422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (should_show) { 5432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!control->visible()) { 5442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AddChildView(control); 5452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) control->SetVisible(true); 5462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 5472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 5482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RemoveChildView(control); 5492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) control->SetVisible(false); 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ScrollView::UpdateScrollBarPositions() { 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!contents_) 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (horiz_sb_->visible()) { 5582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int vw = contents_viewport_->width(); 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int cw = contents_->width(); 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int origin = contents_->x(); 5612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) horiz_sb_->Update(vw, cw, -origin); 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (vert_sb_->visible()) { 5642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int vh = contents_viewport_->height(); 5652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int ch = contents_->height(); 5662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int origin = contents_->y(); 5672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) vert_sb_->Update(vh, ch, -origin); 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// VariableRowHeightScrollHelper ---------------------------------------------- 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)VariableRowHeightScrollHelper::VariableRowHeightScrollHelper( 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Controller* controller) : controller_(controller) { 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)VariableRowHeightScrollHelper::~VariableRowHeightScrollHelper() { 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int VariableRowHeightScrollHelper::GetPageScrollIncrement( 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScrollView* scroll_view, bool is_horizontal, bool is_positive) { 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (is_horizontal) 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // y coordinate is most likely negative. 5852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int y = abs(scroll_view->contents()->y()); 5862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int vis_height = scroll_view->contents()->parent()->height(); 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (is_positive) { 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Align the bottom most row to the top of the view. 5892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int bottom = std::min(scroll_view->contents()->height() - 1, 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) y + vis_height); 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RowInfo bottom_row_info = GetRowInfo(bottom); 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If 0, ScrollView will provide a default value. 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return std::max(0, bottom_row_info.origin - y); 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Align the row on the previous page to to the top of the view. 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int last_page_y = y - vis_height; 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RowInfo last_page_info = GetRowInfo(std::max(0, last_page_y)); 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (last_page_y != last_page_info.origin) 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return std::max(0, y - last_page_info.origin - last_page_info.height); 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return std::max(0, y - last_page_info.origin); 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int VariableRowHeightScrollHelper::GetLineScrollIncrement( 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScrollView* scroll_view, bool is_horizontal, bool is_positive) { 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (is_horizontal) 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // y coordinate is most likely negative. 6092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int y = abs(scroll_view->contents()->y()); 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RowInfo row = GetRowInfo(y); 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (is_positive) { 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return row.height - (y - row.origin); 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (y == row.origin) { 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) row = GetRowInfo(std::max(0, row.origin - 1)); 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return y - row.origin; 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return y - row.origin; 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)VariableRowHeightScrollHelper::RowInfo 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VariableRowHeightScrollHelper::GetRowInfo(int y) { 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return controller_->GetRowInfo(y); 6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// FixedRowHeightScrollHelper ----------------------------------------------- 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FixedRowHeightScrollHelper::FixedRowHeightScrollHelper(int top_margin, 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int row_height) 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : VariableRowHeightScrollHelper(NULL), 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) top_margin_(top_margin), 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) row_height_(row_height) { 6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_GT(row_height, 0); 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)VariableRowHeightScrollHelper::RowInfo 6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FixedRowHeightScrollHelper::GetRowInfo(int y) { 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (y < top_margin_) 6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return RowInfo(0, top_margin_); 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return RowInfo((y - top_margin_) / row_height_ * row_height_ + top_margin_, 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) row_height_); 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace views 645