Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / ui / views / controls / scroll_view_unittest.cc
blobcac64be0991c7b9b24fcda1675da81b635bcd7ab
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"
8 #include "ui/views/controls/scrollbar/overlay_scroll_bar.h"
9 #include "ui/views/test/test_views.h"
11 namespace views {
13 namespace {
15 const int kWidth = 100;
16 const int kMinHeight = 50;
17 const int kMaxHeight = 100;
19 // View implementation that allows setting the preferred size.
20 class CustomView : public View {
21 public:
22 CustomView() {}
24 void SetPreferredSize(const gfx::Size& size) {
25 preferred_size_ = size;
26 PreferredSizeChanged();
29 gfx::Size GetPreferredSize() const override { return preferred_size_; }
31 void Layout() override {
32 gfx::Size pref = GetPreferredSize();
33 int width = pref.width();
34 int height = pref.height();
35 if (parent()) {
36 width = std::max(parent()->width(), width);
37 height = std::max(parent()->height(), height);
39 SetBounds(x(), y(), width, height);
42 private:
43 gfx::Size preferred_size_;
45 DISALLOW_COPY_AND_ASSIGN(CustomView);
48 } // namespace
50 // Verifies the viewport is sized to fit the available space.
51 TEST(ScrollViewTest, ViewportSizedToFit) {
52 ScrollView scroll_view;
53 View* contents = new View;
54 scroll_view.SetContents(contents);
55 scroll_view.SetBoundsRect(gfx::Rect(0, 0, 100, 100));
56 scroll_view.Layout();
57 EXPECT_EQ("0,0 100x100", contents->parent()->bounds().ToString());
60 // Verifies the scrollbars are added as necessary.
61 TEST(ScrollViewTest, ScrollBars) {
62 ScrollView scroll_view;
63 View* contents = new View;
64 scroll_view.SetContents(contents);
65 scroll_view.SetBoundsRect(gfx::Rect(0, 0, 100, 100));
67 // Size the contents such that vertical scrollbar is needed.
68 contents->SetBounds(0, 0, 50, 400);
69 scroll_view.Layout();
70 EXPECT_EQ(100 - scroll_view.GetScrollBarWidth(), contents->parent()->width());
71 EXPECT_EQ(100, contents->parent()->height());
72 EXPECT_TRUE(!scroll_view.horizontal_scroll_bar() ||
73 !scroll_view.horizontal_scroll_bar()->visible());
74 ASSERT_TRUE(scroll_view.vertical_scroll_bar() != NULL);
75 EXPECT_TRUE(scroll_view.vertical_scroll_bar()->visible());
77 // Size the contents such that horizontal scrollbar is needed.
78 contents->SetBounds(0, 0, 400, 50);
79 scroll_view.Layout();
80 EXPECT_EQ(100, contents->parent()->width());
81 EXPECT_EQ(100 - scroll_view.GetScrollBarHeight(),
82 contents->parent()->height());
83 ASSERT_TRUE(scroll_view.horizontal_scroll_bar() != NULL);
84 EXPECT_TRUE(scroll_view.horizontal_scroll_bar()->visible());
85 EXPECT_TRUE(!scroll_view.vertical_scroll_bar() ||
86 !scroll_view.vertical_scroll_bar()->visible());
88 // Both horizontal and vertical.
89 contents->SetBounds(0, 0, 300, 400);
90 scroll_view.Layout();
91 EXPECT_EQ(100 - scroll_view.GetScrollBarWidth(), contents->parent()->width());
92 EXPECT_EQ(100 - scroll_view.GetScrollBarHeight(),
93 contents->parent()->height());
94 ASSERT_TRUE(scroll_view.horizontal_scroll_bar() != NULL);
95 EXPECT_TRUE(scroll_view.horizontal_scroll_bar()->visible());
96 ASSERT_TRUE(scroll_view.vertical_scroll_bar() != NULL);
97 EXPECT_TRUE(scroll_view.vertical_scroll_bar()->visible());
100 // Assertions around adding a header.
101 TEST(ScrollViewTest, Header) {
102 ScrollView scroll_view;
103 View* contents = new View;
104 CustomView* header = new CustomView;
105 scroll_view.SetHeader(header);
106 View* header_parent = header->parent();
107 scroll_view.SetContents(contents);
108 scroll_view.SetBoundsRect(gfx::Rect(0, 0, 100, 100));
109 scroll_view.Layout();
110 // |header|s preferred size is empty, which should result in all space going
111 // to contents.
112 EXPECT_EQ("0,0 100x0", header->parent()->bounds().ToString());
113 EXPECT_EQ("0,0 100x100", contents->parent()->bounds().ToString());
115 // Get the header a height of 20.
116 header->SetPreferredSize(gfx::Size(10, 20));
117 EXPECT_EQ("0,0 100x20", header->parent()->bounds().ToString());
118 EXPECT_EQ("0,20 100x80", contents->parent()->bounds().ToString());
120 // Remove the header.
121 scroll_view.SetHeader(NULL);
122 // SetHeader(NULL) deletes header.
123 header = NULL;
124 EXPECT_EQ("0,0 100x0", header_parent->bounds().ToString());
125 EXPECT_EQ("0,0 100x100", contents->parent()->bounds().ToString());
128 // Verifies the scrollbars are added as necessary when a header is present.
129 TEST(ScrollViewTest, ScrollBarsWithHeader) {
130 ScrollView scroll_view;
131 View* contents = new View;
132 scroll_view.SetContents(contents);
133 CustomView* header = new CustomView;
134 scroll_view.SetHeader(header);
135 scroll_view.SetBoundsRect(gfx::Rect(0, 0, 100, 100));
137 header->SetPreferredSize(gfx::Size(10, 20));
139 // Size the contents such that vertical scrollbar is needed.
140 contents->SetBounds(0, 0, 50, 400);
141 scroll_view.Layout();
142 EXPECT_EQ(0, contents->parent()->x());
143 EXPECT_EQ(20, contents->parent()->y());
144 EXPECT_EQ(100 - scroll_view.GetScrollBarWidth(), contents->parent()->width());
145 EXPECT_EQ(80, contents->parent()->height());
146 EXPECT_EQ(0, header->parent()->x());
147 EXPECT_EQ(0, header->parent()->y());
148 EXPECT_EQ(100 - scroll_view.GetScrollBarWidth(), header->parent()->width());
149 EXPECT_EQ(20, header->parent()->height());
150 EXPECT_TRUE(!scroll_view.horizontal_scroll_bar() ||
151 !scroll_view.horizontal_scroll_bar()->visible());
152 ASSERT_TRUE(scroll_view.vertical_scroll_bar() != NULL);
153 EXPECT_TRUE(scroll_view.vertical_scroll_bar()->visible());
155 // Size the contents such that horizontal scrollbar is needed.
156 contents->SetBounds(0, 0, 400, 50);
157 scroll_view.Layout();
158 EXPECT_EQ(0, contents->parent()->x());
159 EXPECT_EQ(20, contents->parent()->y());
160 EXPECT_EQ(100, contents->parent()->width());
161 EXPECT_EQ(100 - scroll_view.GetScrollBarHeight() - 20,
162 contents->parent()->height());
163 EXPECT_EQ(0, header->parent()->x());
164 EXPECT_EQ(0, header->parent()->y());
165 EXPECT_EQ(100, header->parent()->width());
166 EXPECT_EQ(20, header->parent()->height());
167 ASSERT_TRUE(scroll_view.horizontal_scroll_bar() != NULL);
168 EXPECT_TRUE(scroll_view.horizontal_scroll_bar()->visible());
169 EXPECT_TRUE(!scroll_view.vertical_scroll_bar() ||
170 !scroll_view.vertical_scroll_bar()->visible());
172 // Both horizontal and vertical.
173 contents->SetBounds(0, 0, 300, 400);
174 scroll_view.Layout();
175 EXPECT_EQ(0, contents->parent()->x());
176 EXPECT_EQ(20, contents->parent()->y());
177 EXPECT_EQ(100 - scroll_view.GetScrollBarWidth(), contents->parent()->width());
178 EXPECT_EQ(100 - scroll_view.GetScrollBarHeight() - 20,
179 contents->parent()->height());
180 EXPECT_EQ(0, header->parent()->x());
181 EXPECT_EQ(0, header->parent()->y());
182 EXPECT_EQ(100 - scroll_view.GetScrollBarWidth(), header->parent()->width());
183 EXPECT_EQ(20, header->parent()->height());
184 ASSERT_TRUE(scroll_view.horizontal_scroll_bar() != NULL);
185 EXPECT_TRUE(scroll_view.horizontal_scroll_bar()->visible());
186 ASSERT_TRUE(scroll_view.vertical_scroll_bar() != NULL);
187 EXPECT_TRUE(scroll_view.vertical_scroll_bar()->visible());
190 // Verifies the header scrolls horizontally with the content.
191 TEST(ScrollViewTest, HeaderScrollsWithContent) {
192 ScrollView scroll_view;
193 CustomView* contents = new CustomView;
194 scroll_view.SetContents(contents);
195 contents->SetPreferredSize(gfx::Size(500, 500));
197 CustomView* header = new CustomView;
198 scroll_view.SetHeader(header);
199 header->SetPreferredSize(gfx::Size(500, 20));
201 scroll_view.SetBoundsRect(gfx::Rect(0, 0, 100, 100));
202 EXPECT_EQ("0,0", contents->bounds().origin().ToString());
203 EXPECT_EQ("0,0", header->bounds().origin().ToString());
205 // Scroll the horizontal scrollbar.
206 ASSERT_TRUE(scroll_view.horizontal_scroll_bar());
207 scroll_view.ScrollToPosition(
208 const_cast<ScrollBar*>(scroll_view.horizontal_scroll_bar()), 1);
209 EXPECT_EQ("-1,0", contents->bounds().origin().ToString());
210 EXPECT_EQ("-1,0", header->bounds().origin().ToString());
212 // Scrolling the vertical scrollbar shouldn't effect the header.
213 ASSERT_TRUE(scroll_view.vertical_scroll_bar());
214 scroll_view.ScrollToPosition(
215 const_cast<ScrollBar*>(scroll_view.vertical_scroll_bar()), 1);
216 EXPECT_EQ("-1,-1", contents->bounds().origin().ToString());
217 EXPECT_EQ("-1,0", header->bounds().origin().ToString());
220 // Verifies ScrollRectToVisible() on the child works.
221 TEST(ScrollViewTest, ScrollRectToVisible) {
222 ScrollView scroll_view;
223 CustomView* contents = new CustomView;
224 scroll_view.SetContents(contents);
225 contents->SetPreferredSize(gfx::Size(500, 1000));
227 scroll_view.SetBoundsRect(gfx::Rect(0, 0, 100, 100));
228 scroll_view.Layout();
229 EXPECT_EQ("0,0", contents->bounds().origin().ToString());
231 // Scroll to y=405 height=10, this should make the y position of the content
232 // at (405 + 10) - viewport_height (scroll region bottom aligned).
233 contents->ScrollRectToVisible(gfx::Rect(0, 405, 10, 10));
234 const int viewport_height = contents->parent()->height();
235 EXPECT_EQ(-(415 - viewport_height), contents->y());
237 // Scroll to the current y-location and 10x10; should do nothing.
238 contents->ScrollRectToVisible(gfx::Rect(0, -contents->y(), 10, 10));
239 EXPECT_EQ(-(415 - viewport_height), contents->y());
242 // Verifies ClipHeightTo() uses the height of the content when it is between the
243 // minimum and maximum height values.
244 TEST(ScrollViewTest, ClipHeightToNormalContentHeight) {
245 ScrollView scroll_view;
247 scroll_view.ClipHeightTo(kMinHeight, kMaxHeight);
249 const int kNormalContentHeight = 75;
250 scroll_view.SetContents(
251 new views::StaticSizedView(gfx::Size(kWidth, kNormalContentHeight)));
253 EXPECT_EQ(gfx::Size(kWidth, kNormalContentHeight),
254 scroll_view.GetPreferredSize());
256 scroll_view.SizeToPreferredSize();
257 scroll_view.Layout();
259 EXPECT_EQ(gfx::Size(kWidth, kNormalContentHeight),
260 scroll_view.contents()->size());
261 EXPECT_EQ(gfx::Size(kWidth, kNormalContentHeight), scroll_view.size());
264 // Verifies ClipHeightTo() uses the minimum height when the content is shorter
265 // thamn the minimum height value.
266 TEST(ScrollViewTest, ClipHeightToShortContentHeight) {
267 ScrollView scroll_view;
269 scroll_view.ClipHeightTo(kMinHeight, kMaxHeight);
271 const int kShortContentHeight = 10;
272 scroll_view.SetContents(
273 new views::StaticSizedView(gfx::Size(kWidth, kShortContentHeight)));
275 EXPECT_EQ(gfx::Size(kWidth, kMinHeight), scroll_view.GetPreferredSize());
277 scroll_view.SizeToPreferredSize();
278 scroll_view.Layout();
280 EXPECT_EQ(gfx::Size(kWidth, kShortContentHeight),
281 scroll_view.contents()->size());
282 EXPECT_EQ(gfx::Size(kWidth, kMinHeight), scroll_view.size());
285 // Verifies ClipHeightTo() uses the maximum height when the content is longer
286 // thamn the maximum height value.
287 TEST(ScrollViewTest, ClipHeightToTallContentHeight) {
288 ScrollView scroll_view;
290 // Use a scrollbar that is disabled by default, so the width of the content is
291 // not affected.
292 scroll_view.SetVerticalScrollBar(new views::OverlayScrollBar(false));
294 scroll_view.ClipHeightTo(kMinHeight, kMaxHeight);
296 const int kTallContentHeight = 1000;
297 scroll_view.SetContents(
298 new views::StaticSizedView(gfx::Size(kWidth, kTallContentHeight)));
300 EXPECT_EQ(gfx::Size(kWidth, kMaxHeight), scroll_view.GetPreferredSize());
302 scroll_view.SizeToPreferredSize();
303 scroll_view.Layout();
305 EXPECT_EQ(gfx::Size(kWidth, kTallContentHeight),
306 scroll_view.contents()->size());
307 EXPECT_EQ(gfx::Size(kWidth, kMaxHeight), scroll_view.size());
310 // Verifies that when ClipHeightTo() produces a scrollbar, it reduces the width
311 // of the inner content of the ScrollView.
312 TEST(ScrollViewTest, ClipHeightToScrollbarUsesWidth) {
313 ScrollView scroll_view;
315 scroll_view.ClipHeightTo(kMinHeight, kMaxHeight);
317 // Create a view that will be much taller than it is wide.
318 scroll_view.SetContents(new views::ProportionallySizedView(1000));
320 // Without any width, it will default to 0,0 but be overridden by min height.
321 scroll_view.SizeToPreferredSize();
322 EXPECT_EQ(gfx::Size(0, kMinHeight), scroll_view.GetPreferredSize());
324 gfx::Size new_size(kWidth, scroll_view.GetHeightForWidth(kWidth));
325 scroll_view.SetSize(new_size);
326 scroll_view.Layout();
328 int scroll_bar_width = scroll_view.GetScrollBarWidth();
329 int expected_width = kWidth - scroll_bar_width;
330 EXPECT_EQ(scroll_view.contents()->size().width(), expected_width);
331 EXPECT_EQ(scroll_view.contents()->size().height(), 1000 * expected_width);
332 EXPECT_EQ(gfx::Size(kWidth, kMaxHeight), scroll_view.size());
335 TEST(ScrollViewTest, CornerViewVisibility) {
336 ScrollView scroll_view;
337 View* contents = new View;
338 scroll_view.SetContents(contents);
339 scroll_view.SetBoundsRect(gfx::Rect(0, 0, 100, 100));
340 View* corner_view = scroll_view.corner_view_;
342 // Corner view should be visible when both scrollbars are visible.
343 contents->SetBounds(0, 0, 200, 200);
344 scroll_view.Layout();
345 EXPECT_EQ(&scroll_view, corner_view->parent());
346 EXPECT_TRUE(corner_view->visible());
348 // Corner view should be aligned to the scrollbars.
349 EXPECT_EQ(scroll_view.vertical_scroll_bar()->x(), corner_view->x());
350 EXPECT_EQ(scroll_view.horizontal_scroll_bar()->y(), corner_view->y());
351 EXPECT_EQ(scroll_view.GetScrollBarWidth(), corner_view->width());
352 EXPECT_EQ(scroll_view.GetScrollBarHeight(), corner_view->height());
354 // Corner view should be removed when only the vertical scrollbar is visible.
355 contents->SetBounds(0, 0, 50, 200);
356 scroll_view.Layout();
357 EXPECT_FALSE(corner_view->parent());
359 // ... or when only the horizontal scrollbar is visible.
360 contents->SetBounds(0, 0, 200, 50);
361 scroll_view.Layout();
362 EXPECT_FALSE(corner_view->parent());
364 // ... or when no scrollbar is visible.
365 contents->SetBounds(0, 0, 50, 50);
366 scroll_view.Layout();
367 EXPECT_FALSE(corner_view->parent());
369 // Corner view should reappear when both scrollbars reappear.
370 contents->SetBounds(0, 0, 200, 200);
371 scroll_view.Layout();
372 EXPECT_EQ(&scroll_view, corner_view->parent());
373 EXPECT_TRUE(corner_view->visible());
376 } // namespace views