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.
5 #include "ui/views/controls/scroll_view.h"
7 #include "testing/gtest/include/gtest/gtest.h"
13 // View implementation that allows setting the preferred size.
14 class CustomView : public View {
18 void SetPreferredSize(const gfx::Size& size) {
19 preferred_size_ = size;
20 PreferredSizeChanged();
23 virtual gfx::Size GetPreferredSize() OVERRIDE {
24 return preferred_size_;
27 virtual void Layout() OVERRIDE {
28 gfx::Size pref = GetPreferredSize();
29 int width = pref.width();
30 int height = pref.height();
32 width = std::max(parent()->width(), width);
33 height = std::max(parent()->height(), height);
35 SetBounds(x(), y(), width, height);
39 gfx::Size preferred_size_;
41 DISALLOW_COPY_AND_ASSIGN(CustomView);
46 // Verifies the viewport is sized to fit the available space.
47 TEST(ScrollViewTest, ViewportSizedToFit) {
48 ScrollView scroll_view;
49 View* contents = new View;
50 scroll_view.SetContents(contents);
51 scroll_view.SetBoundsRect(gfx::Rect(0, 0, 100, 100));
53 EXPECT_EQ("0,0 100x100", contents->parent()->bounds().ToString());
56 // Verifies the scrollbars are added as necessary.
57 TEST(ScrollViewTest, ScrollBars) {
58 ScrollView scroll_view;
59 View* contents = new View;
60 scroll_view.SetContents(contents);
61 scroll_view.SetBoundsRect(gfx::Rect(0, 0, 100, 100));
63 // Size the contents such that vertical scrollbar is needed.
64 contents->SetBounds(0, 0, 50, 400);
66 EXPECT_EQ(100 - scroll_view.GetScrollBarWidth(), contents->parent()->width());
67 EXPECT_EQ(100, contents->parent()->height());
68 EXPECT_TRUE(!scroll_view.horizontal_scroll_bar() ||
69 !scroll_view.horizontal_scroll_bar()->visible());
70 ASSERT_TRUE(scroll_view.vertical_scroll_bar() != NULL);
71 EXPECT_TRUE(scroll_view.vertical_scroll_bar()->visible());
73 // Size the contents such that horizontal scrollbar is needed.
74 contents->SetBounds(0, 0, 400, 50);
76 EXPECT_EQ(100, contents->parent()->width());
77 EXPECT_EQ(100 - scroll_view.GetScrollBarHeight(),
78 contents->parent()->height());
79 ASSERT_TRUE(scroll_view.horizontal_scroll_bar() != NULL);
80 EXPECT_TRUE(scroll_view.horizontal_scroll_bar()->visible());
81 EXPECT_TRUE(!scroll_view.vertical_scroll_bar() ||
82 !scroll_view.vertical_scroll_bar()->visible());
84 // Both horizontal and vertical.
85 contents->SetBounds(0, 0, 300, 400);
87 EXPECT_EQ(100 - scroll_view.GetScrollBarWidth(), contents->parent()->width());
88 EXPECT_EQ(100 - scroll_view.GetScrollBarHeight(),
89 contents->parent()->height());
90 ASSERT_TRUE(scroll_view.horizontal_scroll_bar() != NULL);
91 EXPECT_TRUE(scroll_view.horizontal_scroll_bar()->visible());
92 ASSERT_TRUE(scroll_view.vertical_scroll_bar() != NULL);
93 EXPECT_TRUE(scroll_view.vertical_scroll_bar()->visible());
96 // Assertions around adding a header.
97 TEST(ScrollViewTest, Header) {
98 ScrollView scroll_view;
99 View* contents = new View;
100 CustomView* header = new CustomView;
101 scroll_view.SetHeader(header);
102 View* header_parent = header->parent();
103 scroll_view.SetContents(contents);
104 scroll_view.SetBoundsRect(gfx::Rect(0, 0, 100, 100));
105 scroll_view.Layout();
106 // |header|s preferred size is empty, which should result in all space going
108 EXPECT_EQ("0,0 100x0", header->parent()->bounds().ToString());
109 EXPECT_EQ("0,0 100x100", contents->parent()->bounds().ToString());
111 // Get the header a height of 20.
112 header->SetPreferredSize(gfx::Size(10, 20));
113 EXPECT_EQ("0,0 100x20", header->parent()->bounds().ToString());
114 EXPECT_EQ("0,20 100x80", contents->parent()->bounds().ToString());
116 // Remove the header.
117 scroll_view.SetHeader(NULL);
118 // SetHeader(NULL) deletes header.
120 EXPECT_EQ("0,0 100x0", header_parent->bounds().ToString());
121 EXPECT_EQ("0,0 100x100", contents->parent()->bounds().ToString());
124 // Verifies the scrollbars are added as necessary when a header is present.
125 TEST(ScrollViewTest, ScrollBarsWithHeader) {
126 ScrollView scroll_view;
127 View* contents = new View;
128 scroll_view.SetContents(contents);
129 CustomView* header = new CustomView;
130 scroll_view.SetHeader(header);
131 scroll_view.SetBoundsRect(gfx::Rect(0, 0, 100, 100));
133 header->SetPreferredSize(gfx::Size(10, 20));
135 // Size the contents such that vertical scrollbar is needed.
136 contents->SetBounds(0, 0, 50, 400);
137 scroll_view.Layout();
138 EXPECT_EQ(0, contents->parent()->x());
139 EXPECT_EQ(20, contents->parent()->y());
140 EXPECT_EQ(100 - scroll_view.GetScrollBarWidth(), contents->parent()->width());
141 EXPECT_EQ(80, contents->parent()->height());
142 EXPECT_EQ(0, header->parent()->x());
143 EXPECT_EQ(0, header->parent()->y());
144 EXPECT_EQ(100 - scroll_view.GetScrollBarWidth(), header->parent()->width());
145 EXPECT_EQ(20, header->parent()->height());
146 EXPECT_TRUE(!scroll_view.horizontal_scroll_bar() ||
147 !scroll_view.horizontal_scroll_bar()->visible());
148 ASSERT_TRUE(scroll_view.vertical_scroll_bar() != NULL);
149 EXPECT_TRUE(scroll_view.vertical_scroll_bar()->visible());
152 // Size the contents such that horizontal scrollbar is needed.
153 contents->SetBounds(0, 0, 400, 50);
154 scroll_view.Layout();
155 EXPECT_EQ(0, contents->parent()->x());
156 EXPECT_EQ(20, contents->parent()->y());
157 EXPECT_EQ(100, contents->parent()->width());
158 EXPECT_EQ(100 - scroll_view.GetScrollBarHeight() - 20,
159 contents->parent()->height());
160 EXPECT_EQ(0, header->parent()->x());
161 EXPECT_EQ(0, header->parent()->y());
162 EXPECT_EQ(100, header->parent()->width());
163 EXPECT_EQ(20, header->parent()->height());
164 ASSERT_TRUE(scroll_view.horizontal_scroll_bar() != NULL);
165 EXPECT_TRUE(scroll_view.horizontal_scroll_bar()->visible());
166 EXPECT_TRUE(!scroll_view.vertical_scroll_bar() ||
167 !scroll_view.vertical_scroll_bar()->visible());
169 // Both horizontal and vertical.
170 contents->SetBounds(0, 0, 300, 400);
171 scroll_view.Layout();
172 EXPECT_EQ(0, contents->parent()->x());
173 EXPECT_EQ(20, contents->parent()->y());
174 EXPECT_EQ(100 - scroll_view.GetScrollBarWidth(), contents->parent()->width());
175 EXPECT_EQ(100 - scroll_view.GetScrollBarHeight() - 20,
176 contents->parent()->height());
177 EXPECT_EQ(0, header->parent()->x());
178 EXPECT_EQ(0, header->parent()->y());
179 EXPECT_EQ(100 - scroll_view.GetScrollBarWidth(), header->parent()->width());
180 EXPECT_EQ(20, header->parent()->height());
181 ASSERT_TRUE(scroll_view.horizontal_scroll_bar() != NULL);
182 EXPECT_TRUE(scroll_view.horizontal_scroll_bar()->visible());
183 ASSERT_TRUE(scroll_view.vertical_scroll_bar() != NULL);
184 EXPECT_TRUE(scroll_view.vertical_scroll_bar()->visible());
187 // Verifies the header scrolls horizontally with the content.
188 TEST(ScrollViewTest, HeaderScrollsWithContent) {
189 ScrollView scroll_view;
190 CustomView* contents = new CustomView;
191 scroll_view.SetContents(contents);
192 contents->SetPreferredSize(gfx::Size(500, 500));
194 CustomView* header = new CustomView;
195 scroll_view.SetHeader(header);
196 header->SetPreferredSize(gfx::Size(500, 20));
198 scroll_view.SetBoundsRect(gfx::Rect(0, 0, 100, 100));
199 EXPECT_EQ("0,0", contents->bounds().origin().ToString());
200 EXPECT_EQ("0,0", header->bounds().origin().ToString());
202 // Scroll the horizontal scrollbar.
203 ASSERT_TRUE(scroll_view.horizontal_scroll_bar());
204 scroll_view.ScrollToPosition(
205 const_cast<ScrollBar*>(scroll_view.horizontal_scroll_bar()), 1);
206 EXPECT_EQ("-1,0", contents->bounds().origin().ToString());
207 EXPECT_EQ("-1,0", header->bounds().origin().ToString());
209 // Scrolling the vertical scrollbar shouldn't effect the header.
210 ASSERT_TRUE(scroll_view.vertical_scroll_bar());
211 scroll_view.ScrollToPosition(
212 const_cast<ScrollBar*>(scroll_view.vertical_scroll_bar()), 1);
213 EXPECT_EQ("-1,-1", contents->bounds().origin().ToString());
214 EXPECT_EQ("-1,0", header->bounds().origin().ToString());
218 // Verifies ScrollRectToVisible() on the child works.
219 TEST(ScrollViewTest, ScrollRectToVisible) {
220 ScrollView scroll_view;
221 CustomView* contents = new CustomView;
222 scroll_view.SetContents(contents);
223 contents->SetPreferredSize(gfx::Size(500, 1000));
225 scroll_view.SetBoundsRect(gfx::Rect(0, 0, 100, 100));
226 scroll_view.Layout();
227 EXPECT_EQ("0,0", contents->bounds().origin().ToString());
229 // Scroll to y=405 height=10, this should make the y position of the content
230 // at (405 + 10) - viewport_height (scroll region bottom aligned).
231 contents->ScrollRectToVisible(gfx::Rect(0, 405, 10, 10));
232 const int viewport_height = contents->parent()->height();
233 EXPECT_EQ(-(415 - viewport_height), contents->y());
235 // Scroll to the current y-location and 10x10; should do nothing.
236 contents->ScrollRectToVisible(gfx::Rect(0, -contents->y(), 10, 10));
237 EXPECT_EQ(-(415 - viewport_height), contents->y());