WebKit merge 94748:94770
[chromium-blink-merge.git] / views / layout / grid_layout_unittest.cc
blob542d7c5ec15c5d596d43a716df3fdc5929bdc414
1 // Copyright (c) 2011 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 "testing/gtest/include/gtest/gtest.h"
6 #include "views/layout/grid_layout.h"
7 #include "views/view.h"
9 using views::ColumnSet;
10 using views::GridLayout;
11 using views::View;
13 static void ExpectViewBoundsEquals(int x, int y, int w, int h,
14 const View* view) {
15 EXPECT_EQ(x, view->x());
16 EXPECT_EQ(y, view->y());
17 EXPECT_EQ(w, view->width());
18 EXPECT_EQ(h, view->height());
21 class SettableSizeView : public View {
22 public:
23 explicit SettableSizeView(const gfx::Size& pref) {
24 pref_ = pref;
27 virtual gfx::Size GetPreferredSize() {
28 return pref_;
31 private:
32 gfx::Size pref_;
35 // A view with fixed circumference that trades height for width.
36 class FlexibleView : public View {
37 public:
38 explicit FlexibleView(int circumference) {
39 circumference_ = circumference;
42 virtual gfx::Size GetPreferredSize() {
43 return gfx::Size(0, circumference_ / 2);
46 virtual int GetHeightForWidth(int width) {
47 return std::max(0, circumference_ / 2 - width);
50 private:
51 int circumference_;
54 class GridLayoutTest : public testing::Test {
55 public:
56 virtual void SetUp() {
57 layout = new GridLayout(&host);
60 virtual void TearDown() {
61 delete layout;
64 virtual void RemoveAll() {
65 for (int i = host.child_count() - 1; i >= 0; i--)
66 host.RemoveChildView(host.child_at(i));
69 void GetPreferredSize() {
70 pref = layout->GetPreferredSize(&host);
73 gfx::Size pref;
74 gfx::Rect bounds;
75 View host;
76 GridLayout* layout;
79 class GridLayoutAlignmentTest : public testing::Test {
80 public:
81 GridLayoutAlignmentTest() :
82 host(),
83 v1(gfx::Size(10, 20)),
84 layout(new GridLayout(&host)) {}
86 virtual void SetUp() {
89 virtual void TearDown() {
90 delete layout;
93 virtual void RemoveAll() {
94 for (int i = host.child_count() - 1; i >= 0; i--)
95 host.RemoveChildView(host.child_at(i));
98 void TestAlignment(GridLayout::Alignment alignment, gfx::Rect* bounds) {
99 ColumnSet* c1 = layout->AddColumnSet(0);
100 c1->AddColumn(alignment, alignment, 1, GridLayout::USE_PREF, 0, 0);
101 layout->StartRow(1, 0);
102 layout->AddView(&v1);
103 gfx::Size pref = layout->GetPreferredSize(&host);
104 EXPECT_EQ(gfx::Size(10, 20), pref);
105 host.SetBounds(0, 0, 100, 100);
106 layout->Layout(&host);
107 *bounds = v1.bounds();
108 RemoveAll();
111 View host;
112 SettableSizeView v1;
113 GridLayout* layout;
116 TEST_F(GridLayoutAlignmentTest, Fill) {
117 gfx::Rect bounds;
118 TestAlignment(GridLayout::FILL, &bounds);
119 EXPECT_EQ(gfx::Rect(0, 0, 100, 100), bounds);
122 TEST_F(GridLayoutAlignmentTest, Leading) {
123 gfx::Rect bounds;
124 TestAlignment(GridLayout::LEADING, &bounds);
125 EXPECT_EQ(gfx::Rect(0, 0, 10, 20), bounds);
128 TEST_F(GridLayoutAlignmentTest, Center) {
129 gfx::Rect bounds;
130 TestAlignment(GridLayout::CENTER, &bounds);
131 EXPECT_EQ(gfx::Rect(45, 40, 10, 20), bounds);
134 TEST_F(GridLayoutAlignmentTest, Trailing) {
135 gfx::Rect bounds;
136 TestAlignment(GridLayout::TRAILING, &bounds);
137 EXPECT_EQ(gfx::Rect(90, 80, 10, 20), bounds);
140 TEST_F(GridLayoutTest, TwoColumns) {
141 SettableSizeView v1(gfx::Size(10, 20));
142 SettableSizeView v2(gfx::Size(20, 20));
143 ColumnSet* c1 = layout->AddColumnSet(0);
144 c1->AddColumn(GridLayout::LEADING, GridLayout::LEADING,
145 0, GridLayout::USE_PREF, 0, 0);
146 c1->AddColumn(GridLayout::LEADING, GridLayout::LEADING,
147 0, GridLayout::USE_PREF, 0, 0);
148 layout->StartRow(0, 0);
149 layout->AddView(&v1);
150 layout->AddView(&v2);
152 GetPreferredSize();
153 EXPECT_EQ(gfx::Size(30, 20), pref);
155 host.SetBounds(0, 0, pref.width(), pref.height());
156 layout->Layout(&host);
157 ExpectViewBoundsEquals(0, 0, 10, 20, &v1);
158 ExpectViewBoundsEquals(10, 0, 20, 20, &v2);
160 RemoveAll();
163 TEST_F(GridLayoutTest, ColSpan1) {
164 SettableSizeView v1(gfx::Size(100, 20));
165 SettableSizeView v2(gfx::Size(10, 40));
166 ColumnSet* c1 = layout->AddColumnSet(0);
167 c1->AddColumn(GridLayout::LEADING, GridLayout::LEADING,
168 0, GridLayout::USE_PREF, 0, 0);
169 c1->AddColumn(GridLayout::LEADING, GridLayout::LEADING,
170 1, GridLayout::USE_PREF, 0, 0);
171 layout->StartRow(0, 0);
172 layout->AddView(&v1, 2, 1);
173 layout->StartRow(0, 0);
174 layout->AddView(&v2);
176 GetPreferredSize();
177 EXPECT_EQ(gfx::Size(100, 60), pref);
179 host.SetBounds(0, 0, pref.width(), pref.height());
180 layout->Layout(&host);
181 ExpectViewBoundsEquals(0, 0, 100, 20, &v1);
182 ExpectViewBoundsEquals(0, 20, 10, 40, &v2);
184 RemoveAll();
187 TEST_F(GridLayoutTest, ColSpan2) {
188 SettableSizeView v1(gfx::Size(100, 20));
189 SettableSizeView v2(gfx::Size(10, 20));
190 ColumnSet* c1 = layout->AddColumnSet(0);
191 c1->AddColumn(GridLayout::LEADING, GridLayout::LEADING,
192 1, GridLayout::USE_PREF, 0, 0);
193 c1->AddColumn(GridLayout::LEADING, GridLayout::LEADING,
194 0, GridLayout::USE_PREF, 0, 0);
195 layout->StartRow(0, 0);
196 layout->AddView(&v1, 2, 1);
197 layout->StartRow(0, 0);
198 layout->SkipColumns(1);
199 layout->AddView(&v2);
201 GetPreferredSize();
202 EXPECT_EQ(gfx::Size(100, 40), pref);
204 host.SetBounds(0, 0, pref.width(), pref.height());
205 layout->Layout(&host);
206 ExpectViewBoundsEquals(0, 0, 100, 20, &v1);
207 ExpectViewBoundsEquals(90, 20, 10, 20, &v2);
209 RemoveAll();
212 TEST_F(GridLayoutTest, ColSpan3) {
213 SettableSizeView v1(gfx::Size(100, 20));
214 SettableSizeView v2(gfx::Size(10, 20));
215 SettableSizeView v3(gfx::Size(10, 20));
216 ColumnSet* c1 = layout->AddColumnSet(0);
217 c1->AddColumn(GridLayout::LEADING, GridLayout::LEADING,
218 0, GridLayout::USE_PREF, 0, 0);
219 c1->AddColumn(GridLayout::LEADING, GridLayout::LEADING,
220 0, GridLayout::USE_PREF, 0, 0);
221 layout->StartRow(0, 0);
222 layout->AddView(&v1, 2, 1);
223 layout->StartRow(0, 0);
224 layout->AddView(&v2);
225 layout->AddView(&v3);
227 GetPreferredSize();
228 EXPECT_EQ(gfx::Size(100, 40), pref);
230 host.SetBounds(0, 0, pref.width(), pref.height());
231 layout->Layout(&host);
232 ExpectViewBoundsEquals(0, 0, 100, 20, &v1);
233 ExpectViewBoundsEquals(0, 20, 10, 20, &v2);
234 ExpectViewBoundsEquals(50, 20, 10, 20, &v3);
236 RemoveAll();
240 TEST_F(GridLayoutTest, ColSpan4) {
241 views::ColumnSet* set = layout->AddColumnSet(0);
243 set->AddColumn(GridLayout::LEADING, GridLayout::LEADING, 0,
244 GridLayout::USE_PREF, 0, 0);
245 set->AddColumn(GridLayout::LEADING, GridLayout::LEADING, 0,
246 GridLayout::USE_PREF, 0, 0);
248 SettableSizeView v1(gfx::Size(10, 10));
249 SettableSizeView v2(gfx::Size(10, 10));
250 SettableSizeView v3(gfx::Size(25, 20));
251 layout->StartRow(0, 0);
252 layout->AddView(&v1);
253 layout->AddView(&v2);
254 layout->StartRow(0, 0);
255 layout->AddView(&v3, 2, 1);
257 GetPreferredSize();
258 EXPECT_EQ(gfx::Size(25, 30), pref);
260 host.SetBounds(0, 0, pref.width(), pref.height());
261 layout->Layout(&host);
262 ExpectViewBoundsEquals(0, 0, 10, 10, &v1);
263 ExpectViewBoundsEquals(12, 0, 10, 10, &v2);
264 ExpectViewBoundsEquals(0, 10, 25, 20, &v3);
266 RemoveAll();
269 TEST_F(GridLayoutTest, SameSizeColumns) {
270 SettableSizeView v1(gfx::Size(50, 20));
271 SettableSizeView v2(gfx::Size(10, 10));
272 ColumnSet* c1 = layout->AddColumnSet(0);
273 c1->AddColumn(GridLayout::LEADING, GridLayout::LEADING,
274 0, GridLayout::USE_PREF, 0, 0);
275 c1->AddColumn(GridLayout::LEADING, GridLayout::LEADING,
276 0, GridLayout::USE_PREF, 0, 0);
277 c1->LinkColumnSizes(0, 1, -1);
278 layout->StartRow(0, 0);
279 layout->AddView(&v1);
280 layout->AddView(&v2);
282 gfx::Size pref = layout->GetPreferredSize(&host);
283 EXPECT_EQ(gfx::Size(100, 20), pref);
285 host.SetBounds(0, 0, pref.width(), pref.height());
286 layout->Layout(&host);
287 ExpectViewBoundsEquals(0, 0, 50, 20, &v1);
288 ExpectViewBoundsEquals(50, 0, 10, 10, &v2);
290 RemoveAll();
293 TEST_F(GridLayoutTest, HorizontalResizeTest1) {
294 SettableSizeView v1(gfx::Size(50, 20));
295 SettableSizeView v2(gfx::Size(10, 10));
296 ColumnSet* c1 = layout->AddColumnSet(0);
297 c1->AddColumn(GridLayout::FILL, GridLayout::LEADING,
298 1, GridLayout::USE_PREF, 0, 0);
299 c1->AddColumn(GridLayout::LEADING, GridLayout::LEADING,
300 0, GridLayout::USE_PREF, 0, 0);
301 layout->StartRow(0, 0);
302 layout->AddView(&v1);
303 layout->AddView(&v2);
305 host.SetBounds(0, 0, 110, 20);
306 layout->Layout(&host);
307 ExpectViewBoundsEquals(0, 0, 100, 20, &v1);
308 ExpectViewBoundsEquals(100, 0, 10, 10, &v2);
310 RemoveAll();
313 TEST_F(GridLayoutTest, HorizontalResizeTest2) {
314 SettableSizeView v1(gfx::Size(50, 20));
315 SettableSizeView v2(gfx::Size(10, 10));
316 ColumnSet* c1 = layout->AddColumnSet(0);
317 c1->AddColumn(GridLayout::FILL, GridLayout::LEADING,
318 1, GridLayout::USE_PREF, 0, 0);
319 c1->AddColumn(GridLayout::TRAILING, GridLayout::LEADING,
320 1, GridLayout::USE_PREF, 0, 0);
321 layout->StartRow(0, 0);
322 layout->AddView(&v1);
323 layout->AddView(&v2);
325 host.SetBounds(0, 0, 120, 20);
326 layout->Layout(&host);
327 ExpectViewBoundsEquals(0, 0, 80, 20, &v1);
328 ExpectViewBoundsEquals(110, 0, 10, 10, &v2);
330 RemoveAll();
333 TEST_F(GridLayoutTest, TestVerticalResize1) {
334 SettableSizeView v1(gfx::Size(50, 20));
335 SettableSizeView v2(gfx::Size(10, 10));
336 ColumnSet* c1 = layout->AddColumnSet(0);
337 c1->AddColumn(GridLayout::FILL, GridLayout::FILL,
338 1, GridLayout::USE_PREF, 0, 0);
339 layout->StartRow(1, 0);
340 layout->AddView(&v1);
341 layout->StartRow(0, 0);
342 layout->AddView(&v2);
344 GetPreferredSize();
345 EXPECT_EQ(gfx::Size(50, 30), pref);
347 host.SetBounds(0, 0, 50, 100);
348 layout->Layout(&host);
349 ExpectViewBoundsEquals(0, 0, 50, 90, &v1);
350 ExpectViewBoundsEquals(0, 90, 50, 10, &v2);
352 RemoveAll();
355 TEST_F(GridLayoutTest, Insets) {
356 SettableSizeView v1(gfx::Size(10, 20));
357 ColumnSet* c1 = layout->AddColumnSet(0);
358 layout->SetInsets(1, 2, 3, 4);
359 c1->AddColumn(GridLayout::LEADING, GridLayout::LEADING,
360 0, GridLayout::USE_PREF, 0, 0);
361 layout->StartRow(0, 0);
362 layout->AddView(&v1);
364 GetPreferredSize();
365 EXPECT_EQ(gfx::Size(16, 24), pref);
367 host.SetBounds(0, 0, pref.width(), pref.height());
368 layout->Layout(&host);
369 ExpectViewBoundsEquals(2, 1, 10, 20, &v1);
371 RemoveAll();
374 TEST_F(GridLayoutTest, FixedSize) {
375 layout->SetInsets(2, 2, 2, 2);
377 views::ColumnSet* set = layout->AddColumnSet(0);
379 int column_count = 4;
380 int title_width = 100;
381 int row_count = 2;
382 int pref_width = 10;
383 int pref_height = 20;
385 for (int i = 0; i < column_count; ++i) {
386 set->AddColumn(views::GridLayout::CENTER,
387 views::GridLayout::CENTER,
389 views::GridLayout::FIXED,
390 title_width,
391 title_width);
394 for (int row = 0; row < row_count; ++row) {
395 layout->StartRow(0, 0);
396 for (int col = 0; col < column_count; ++col) {
397 layout->AddView(new SettableSizeView(gfx::Size(pref_width, pref_height)));
401 layout->Layout(&host);
403 for (int i = 0; i < column_count; ++i) {
404 for (int row = 0; row < row_count; ++row) {
405 View* view = host.child_at(row * column_count + i);
406 ExpectViewBoundsEquals(
407 2 + title_width * i + (title_width - pref_width) / 2,
408 2 + pref_height * row,
409 pref_width,
410 pref_height, view);
414 GetPreferredSize();
415 EXPECT_EQ(gfx::Size(column_count * title_width + 4,
416 row_count * pref_height + 4), pref);
419 TEST_F(GridLayoutTest, RowSpanWithPaddingRow) {
420 views::ColumnSet* set = layout->AddColumnSet(0);
422 set->AddColumn(views::GridLayout::CENTER,
423 views::GridLayout::CENTER,
425 views::GridLayout::FIXED,
427 10);
429 layout->StartRow(0, 0);
430 layout->AddView(new SettableSizeView(gfx::Size(10, 10)), 1, 2);
431 layout->AddPaddingRow(0, 10);
434 TEST_F(GridLayoutTest, RowSpan) {
435 views::ColumnSet* set = layout->AddColumnSet(0);
437 set->AddColumn(views::GridLayout::LEADING,
438 views::GridLayout::LEADING,
440 views::GridLayout::USE_PREF,
443 set->AddColumn(views::GridLayout::LEADING,
444 views::GridLayout::LEADING,
446 views::GridLayout::USE_PREF,
450 layout->StartRow(0, 0);
451 layout->AddView(new SettableSizeView(gfx::Size(20, 10)));
452 layout->AddView(new SettableSizeView(gfx::Size(20, 40)), 1, 2);
453 layout->StartRow(1, 0);
454 views::View* s3 = new SettableSizeView(gfx::Size(20, 10));
455 layout->AddView(s3);
457 GetPreferredSize();
458 EXPECT_EQ(gfx::Size(40, 40), pref);
460 host.SetBounds(0, 0, pref.width(), pref.height());
461 layout->Layout(&host);
462 ExpectViewBoundsEquals(0, 10, 20, 10, s3);
465 TEST_F(GridLayoutTest, RowSpan2) {
466 views::ColumnSet* set = layout->AddColumnSet(0);
468 set->AddColumn(GridLayout::LEADING, GridLayout::LEADING,
469 0, GridLayout::USE_PREF, 0, 0);
470 set->AddColumn(GridLayout::LEADING, GridLayout::LEADING,
471 0,GridLayout::USE_PREF, 0, 0);
473 layout->StartRow(0, 0);
474 layout->AddView(new SettableSizeView(gfx::Size(20, 20)));
475 views::View* s3 = new SettableSizeView(gfx::Size(64, 64));
476 layout->AddView(s3, 1, 3);
478 layout->AddPaddingRow(0, 10);
480 layout->StartRow(0, 0);
481 layout->AddView(new SettableSizeView(gfx::Size(10, 20)));
483 GetPreferredSize();
484 EXPECT_EQ(gfx::Size(84, 64), pref);
486 host.SetBounds(0, 0, pref.width(), pref.height());
487 layout->Layout(&host);
488 ExpectViewBoundsEquals(20, 0, 64, 64, s3);
491 TEST_F(GridLayoutTest, FixedViewWidth) {
492 views::ColumnSet* set = layout->AddColumnSet(0);
494 set->AddColumn(GridLayout::LEADING, GridLayout::LEADING,
495 0, GridLayout::USE_PREF, 0, 0);
496 set->AddColumn(GridLayout::LEADING, GridLayout::LEADING,
497 0,GridLayout::USE_PREF, 0, 0);
499 layout->StartRow(0, 0);
500 View* view = new SettableSizeView(gfx::Size(30, 40));
501 layout->AddView(view, 1, 1, GridLayout::LEADING, GridLayout::LEADING, 10, 0);
503 GetPreferredSize();
504 EXPECT_EQ(10, pref.width());
505 EXPECT_EQ(40, pref.height());
507 host.SetBounds(0, 0, pref.width(), pref.height());
508 layout->Layout(&host);
509 ExpectViewBoundsEquals(0, 0, 10, 40, view);
512 TEST_F(GridLayoutTest, FixedViewHeight) {
513 views::ColumnSet* set = layout->AddColumnSet(0);
515 set->AddColumn(GridLayout::LEADING, GridLayout::LEADING,
516 0, GridLayout::USE_PREF, 0, 0);
517 set->AddColumn(GridLayout::LEADING, GridLayout::LEADING,
518 0,GridLayout::USE_PREF, 0, 0);
520 layout->StartRow(0, 0);
521 View* view = new SettableSizeView(gfx::Size(30, 40));
522 layout->AddView(view, 1, 1, GridLayout::LEADING, GridLayout::LEADING, 0, 10);
524 GetPreferredSize();
525 EXPECT_EQ(30, pref.width());
526 EXPECT_EQ(10, pref.height());
528 host.SetBounds(0, 0, pref.width(), pref.height());
529 layout->Layout(&host);
530 ExpectViewBoundsEquals(0, 0, 30, 10, view);
533 // Make sure that for views that span columns the underlying columns are resized
534 // based on the resize percent of the column.
535 TEST_F(GridLayoutTest, ColumnSpanResizing) {
536 views::ColumnSet* set = layout->AddColumnSet(0);
538 set->AddColumn(views::GridLayout::FILL, views::GridLayout::CENTER,
539 2, views::GridLayout::USE_PREF, 0, 0);
540 set->AddColumn(views::GridLayout::FILL, views::GridLayout::CENTER,
541 4, views::GridLayout::USE_PREF, 0, 0);
543 layout->StartRow(0, 0);
544 // span_view spans two columns and is twice as big the views added below.
545 View* span_view = new SettableSizeView(gfx::Size(12, 40));
546 layout->AddView(span_view, 2, 1, GridLayout::LEADING, GridLayout::LEADING);
548 layout->StartRow(0, 0);
549 View* view1 = new SettableSizeView(gfx::Size(2, 40));
550 View* view2 = new SettableSizeView(gfx::Size(4, 40));
551 layout->AddView(view1);
552 layout->AddView(view2);
554 host.SetBounds(0, 0, 12, 80);
555 layout->Layout(&host);
557 ExpectViewBoundsEquals(0, 0, 12, 40, span_view);
559 // view1 should be 4 pixels wide
560 // column_pref + (remaining_width * column_resize / total_column_resize) =
561 // 2 + (6 * 2 / 6).
562 ExpectViewBoundsEquals(0, 40, 4, 40, view1);
564 // And view2 should be 8 pixels wide:
565 // 4 + (6 * 4 / 6).
566 ExpectViewBoundsEquals(4, 40, 8, 40, view2);
569 // Check that GetPreferredSize() takes resizing of columns into account when
570 // there is additional space in the case we have column sets of different
571 // preferred sizes.
572 TEST_F(GridLayoutTest, ColumnResizingOnGetPreferredSize) {
573 views::ColumnSet* set = layout->AddColumnSet(0);
574 set->AddColumn(views::GridLayout::FILL, views::GridLayout::CENTER,
575 1, views::GridLayout::USE_PREF, 0, 0);
577 set = layout->AddColumnSet(1);
578 set->AddColumn(views::GridLayout::FILL, views::GridLayout::CENTER,
579 1, views::GridLayout::USE_PREF, 0, 0);
581 set = layout->AddColumnSet(2);
582 set->AddColumn(views::GridLayout::FILL, views::GridLayout::CENTER,
583 1, views::GridLayout::USE_PREF, 0, 0);
585 // Make a row containing a flexible view that trades width for height.
586 layout->StartRow(0, 0);
587 View* view1 = new FlexibleView(100);
588 layout->AddView(view1, 1, 1, GridLayout::FILL, GridLayout::LEADING);
590 // The second row contains a view of fixed size that will enforce a column
591 // width of 20 pixels.
592 layout->StartRow(0, 1);
593 View* view2 = new SettableSizeView(gfx::Size(20, 20));
594 layout->AddView(view2, 1, 1, GridLayout::FILL, GridLayout::LEADING);
596 // Add another flexible view in row three in order to ensure column set
597 // ordering doesn't influence sizing behaviour.
598 layout->StartRow(0, 2);
599 View* view3 = new FlexibleView(40);
600 layout->AddView(view3, 1, 1, GridLayout::FILL, GridLayout::LEADING);
602 // We expect a height of 50: 30 from the variable width view in the first row
603 // plus 20 from the statically sized view in the second row. The flexible
604 // view in the third row should contribute no height.
605 EXPECT_EQ(gfx::Size(20, 50), layout->GetPreferredSize(&host));