1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef UI_VIEWS_CONTROLS_SCROLL_VIEW_H_
6#define UI_VIEWS_CONTROLS_SCROLL_VIEW_H_
7
8#include <string>
9
10#include "base/compiler_specific.h"
11#include "ui/views/controls/scrollbar/scroll_bar.h"
12
13namespace views {
14
15/////////////////////////////////////////////////////////////////////////////
16//
17// ScrollView class
18//
19// A ScrollView is used to make any View scrollable. The view is added to
20// a viewport which takes care of clipping.
21//
22// In this current implementation both horizontal and vertical scrollbars are
23// added as needed.
24//
25// The scrollview supports keyboard UI and mousewheel.
26//
27/////////////////////////////////////////////////////////////////////////////
28
29class VIEWS_EXPORT ScrollView : public View, public ScrollBarController {
30 public:
31  static const char kViewClassName[];
32
33  ScrollView();
34
35  virtual ~ScrollView();
36
37  // Creates a ScrollView with a theme specific border.
38  static ScrollView* CreateScrollViewWithBorder();
39
40  // Set the contents. Any previous contents will be deleted. The contents
41  // is the view that needs to scroll.
42  void SetContents(View* a_view);
43  const View* contents() const { return contents_; }
44  View* contents() { return contents_; }
45
46  // Sets the header, deleting the previous header.
47  void SetHeader(View* header);
48
49  // Returns the visible region of the content View.
50  gfx::Rect GetVisibleRect() const;
51
52  void set_hide_horizontal_scrollbar(bool visible) {
53    hide_horizontal_scrollbar_ = visible;
54  }
55
56  // Turns this scroll view into a bounded scroll view, with a fixed height.
57  // By default, a ScrollView will stretch to fill its outer container.
58  void ClipHeightTo(int min_height, int max_height);
59
60  // Returns whether or not the ScrollView is bounded (as set by ClipHeightTo).
61  bool is_bounded() const { return max_height_ >= 0 && min_height_ >= 0; }
62
63  // Retrieves the width/height of scrollbars. These return 0 if the scrollbar
64  // has not yet been created.
65  int GetScrollBarWidth() const;
66  int GetScrollBarHeight() const;
67
68  // Returns the horizontal/vertical scrollbar. This may return NULL.
69  const ScrollBar* horizontal_scroll_bar() const { return horiz_sb_; }
70  const ScrollBar* vertical_scroll_bar() const { return vert_sb_; }
71
72  // Customize the scrollbar design. ScrollView takes the ownership of the
73  // specified ScrollBar. |horiz_sb| and |vert_sb| cannot be NULL.
74  void SetHorizontalScrollBar(ScrollBar* horiz_sb);
75  void SetVerticalScrollBar(ScrollBar* vert_sb);
76
77  // View overrides:
78  virtual gfx::Size GetPreferredSize() const OVERRIDE;
79  virtual int GetHeightForWidth(int width) const OVERRIDE;
80  virtual void Layout() OVERRIDE;
81  virtual bool OnKeyPressed(const ui::KeyEvent& event) OVERRIDE;
82  virtual bool OnMouseWheel(const ui::MouseWheelEvent& e) OVERRIDE;
83  virtual void OnMouseEntered(const ui::MouseEvent& event) OVERRIDE;
84  virtual void OnMouseExited(const ui::MouseEvent& event) OVERRIDE;
85  virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE;
86  virtual const char* GetClassName() const OVERRIDE;
87
88  // ScrollBarController overrides:
89  virtual void ScrollToPosition(ScrollBar* source, int position) OVERRIDE;
90  virtual int GetScrollIncrement(ScrollBar* source,
91                                 bool is_page,
92                                 bool is_positive) OVERRIDE;
93
94 private:
95  FRIEND_TEST_ALL_PREFIXES(ScrollViewTest, CornerViewVisibility);
96  class Viewport;
97
98  // Used internally by SetHeader() and SetContents() to reset the view.  Sets
99  // |member| to |new_view|. If |new_view| is non-null it is added to |parent|.
100  void SetHeaderOrContents(View* parent, View* new_view, View** member);
101
102  // Scrolls the minimum amount necessary to make the specified rectangle
103  // visible, in the coordinates of the contents view. The specified rectangle
104  // is constrained by the bounds of the contents view. This has no effect if
105  // the contents have not been set.
106  void ScrollContentsRegionToBeVisible(const gfx::Rect& rect);
107
108  // Computes the visibility of both scrollbars, taking in account the view port
109  // and content sizes.
110  void ComputeScrollBarsVisibility(const gfx::Size& viewport_size,
111                                   const gfx::Size& content_size,
112                                   bool* horiz_is_shown,
113                                   bool* vert_is_shown) const;
114
115  // Shows or hides the scrollbar/corner_view based on the value of
116  // |should_show|.
117  void SetControlVisibility(View* control, bool should_show);
118
119  // Update the scrollbars positions given viewport and content sizes.
120  void UpdateScrollBarPositions();
121
122  // The current contents and its viewport. |contents_| is contained in
123  // |contents_viewport_|.
124  View* contents_;
125  View* contents_viewport_;
126
127  // The current header and its viewport. |header_| is contained in
128  // |header_viewport_|.
129  View* header_;
130  View* header_viewport_;
131
132  // Horizontal scrollbar.
133  ScrollBar* horiz_sb_;
134
135  // Vertical scrollbar.
136  ScrollBar* vert_sb_;
137
138  // Corner view.
139  View* corner_view_;
140
141  // The min and max height for the bounded scroll view. These are negative
142  // values if the view is not bounded.
143  int min_height_;
144  int max_height_;
145
146  // If true, never show the horizontal scrollbar (even if the contents is wider
147  // than the viewport).
148  bool hide_horizontal_scrollbar_;
149
150  DISALLOW_COPY_AND_ASSIGN(ScrollView);
151};
152
153// VariableRowHeightScrollHelper is intended for views that contain rows of
154// varying height. To use a VariableRowHeightScrollHelper create one supplying
155// a Controller and delegate GetPageScrollIncrement and GetLineScrollIncrement
156// to the helper. VariableRowHeightScrollHelper calls back to the
157// Controller to determine row boundaries.
158class VariableRowHeightScrollHelper {
159 public:
160  // The origin and height of a row.
161  struct RowInfo {
162    RowInfo(int origin, int height) : origin(origin), height(height) {}
163
164    // Origin of the row.
165    int origin;
166
167    // Height of the row.
168    int height;
169  };
170
171  // Used to determine row boundaries.
172  class Controller {
173   public:
174    // Returns the origin and size of the row at the specified location.
175    virtual VariableRowHeightScrollHelper::RowInfo GetRowInfo(int y) = 0;
176  };
177
178  // Creates a new VariableRowHeightScrollHelper. Controller is
179  // NOT deleted by this VariableRowHeightScrollHelper.
180  explicit VariableRowHeightScrollHelper(Controller* controller);
181  virtual ~VariableRowHeightScrollHelper();
182
183  // Delegate the View methods of the same name to these. The scroll amount is
184  // determined by querying the Controller for the appropriate row to scroll
185  // to.
186  int GetPageScrollIncrement(ScrollView* scroll_view,
187                             bool is_horizontal, bool is_positive);
188  int GetLineScrollIncrement(ScrollView* scroll_view,
189                             bool is_horizontal, bool is_positive);
190
191 protected:
192  // Returns the row information for the row at the specified location. This
193  // calls through to the method of the same name on the controller.
194  virtual RowInfo GetRowInfo(int y);
195
196 private:
197  Controller* controller_;
198
199  DISALLOW_COPY_AND_ASSIGN(VariableRowHeightScrollHelper);
200};
201
202// FixedRowHeightScrollHelper is intended for views that contain fixed height
203// height rows. To use a FixedRowHeightScrollHelper delegate
204// GetPageScrollIncrement and GetLineScrollIncrement to it.
205class FixedRowHeightScrollHelper : public VariableRowHeightScrollHelper {
206 public:
207  // Creates a FixedRowHeightScrollHelper. top_margin gives the distance from
208  // the top of the view to the first row, and may be 0. row_height gives the
209  // height of each row.
210  FixedRowHeightScrollHelper(int top_margin, int row_height);
211
212 protected:
213  // Calculates the bounds of the row from the top margin and row height.
214  virtual RowInfo GetRowInfo(int y) OVERRIDE;
215
216 private:
217  int top_margin_;
218  int row_height_;
219
220  DISALLOW_COPY_AND_ASSIGN(FixedRowHeightScrollHelper);
221};
222
223}  // namespace views
224
225#endif  // UI_VIEWS_CONTROLS_SCROLL_VIEW_H_
226