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 #include "ui/views/layout/box_layout.h"
6
7 #include <stddef.h>
8
9 #include <memory>
10 #include <utility>
11 #include <vector>
12
13 #include "testing/gtest/include/gtest/gtest.h"
14 #include "ui/gfx/geometry/insets.h"
15 #include "ui/views/test/test_views.h"
16 #include "ui/views/view.h"
17 #include "ui/views/view_class_properties.h"
18
19 namespace views {
20
21 namespace {
22
23 constexpr BoxLayout::MainAxisAlignment kMainAlignments[3] = {
24 BoxLayout::MainAxisAlignment::kStart,
25 BoxLayout::MainAxisAlignment::kCenter,
26 BoxLayout::MainAxisAlignment::kEnd,
27 };
28
29 class BoxLayoutTest : public testing::Test {
30 public:
SetUp()31 void SetUp() override { host_ = std::make_unique<View>(); }
32
33 std::unique_ptr<View> host_;
34 };
35
36 } // namespace
37
TEST_F(BoxLayoutTest,Empty)38 TEST_F(BoxLayoutTest, Empty) {
39 BoxLayout* layout = host_->SetLayoutManager(std::make_unique<BoxLayout>(
40 BoxLayout::Orientation::kHorizontal, gfx::Insets(10), 20));
41 EXPECT_EQ(gfx::Size(20, 20), layout->GetPreferredSize(host_.get()));
42 }
43
TEST_F(BoxLayoutTest,AlignmentHorizontal)44 TEST_F(BoxLayoutTest, AlignmentHorizontal) {
45 BoxLayout* layout = host_->SetLayoutManager(
46 std::make_unique<BoxLayout>(BoxLayout::Orientation::kHorizontal));
47 View* v1 = new StaticSizedView(gfx::Size(10, 20));
48 host_->AddChildView(v1);
49 View* v2 = new StaticSizedView(gfx::Size(10, 10));
50 host_->AddChildView(v2);
51 EXPECT_EQ(gfx::Size(20, 20), layout->GetPreferredSize(host_.get()));
52 host_->SetBounds(0, 0, 20, 20);
53 host_->Layout();
54 EXPECT_EQ(gfx::Rect(0, 0, 10, 20), v1->bounds());
55 EXPECT_EQ(gfx::Rect(10, 0, 10, 20), v2->bounds());
56 }
57
TEST_F(BoxLayoutTest,AlignmentVertical)58 TEST_F(BoxLayoutTest, AlignmentVertical) {
59 BoxLayout* layout = host_->SetLayoutManager(
60 std::make_unique<BoxLayout>(BoxLayout::Orientation::kVertical));
61 View* v1 = new StaticSizedView(gfx::Size(20, 10));
62 host_->AddChildView(v1);
63 View* v2 = new StaticSizedView(gfx::Size(10, 10));
64 host_->AddChildView(v2);
65 EXPECT_EQ(gfx::Size(20, 20), layout->GetPreferredSize(host_.get()));
66 host_->SetBounds(0, 0, 20, 20);
67 host_->Layout();
68 EXPECT_EQ(gfx::Rect(0, 0, 20, 10), v1->bounds());
69 EXPECT_EQ(gfx::Rect(0, 10, 20, 10), v2->bounds());
70 }
71
TEST_F(BoxLayoutTest,SetInsideBorderInsets)72 TEST_F(BoxLayoutTest, SetInsideBorderInsets) {
73 BoxLayout* layout = host_->SetLayoutManager(std::make_unique<BoxLayout>(
74 BoxLayout::Orientation::kHorizontal, gfx::Insets(20, 10)));
75 View* v1 = new StaticSizedView(gfx::Size(10, 20));
76 host_->AddChildView(v1);
77 View* v2 = new StaticSizedView(gfx::Size(10, 10));
78 host_->AddChildView(v2);
79 EXPECT_EQ(gfx::Size(40, 60), layout->GetPreferredSize(host_.get()));
80 host_->SetBounds(0, 0, 40, 60);
81 host_->Layout();
82 EXPECT_EQ(gfx::Rect(10, 20, 10, 20), v1->bounds());
83 EXPECT_EQ(gfx::Rect(20, 20, 10, 20), v2->bounds());
84
85 layout->set_inside_border_insets(gfx::Insets(5, 10, 15, 20));
86 EXPECT_EQ(gfx::Size(50, 40), layout->GetPreferredSize(host_.get()));
87 host_->SetBounds(0, 0, 50, 40);
88 host_->Layout();
89 EXPECT_EQ(gfx::Rect(10, 5, 10, 20), v1->bounds());
90 EXPECT_EQ(gfx::Rect(20, 5, 10, 20), v2->bounds());
91 }
92
TEST_F(BoxLayoutTest,Spacing)93 TEST_F(BoxLayoutTest, Spacing) {
94 BoxLayout* layout = host_->SetLayoutManager(std::make_unique<BoxLayout>(
95 BoxLayout::Orientation::kHorizontal, gfx::Insets(7), 8));
96 View* v1 = new StaticSizedView(gfx::Size(10, 20));
97 host_->AddChildView(v1);
98 View* v2 = new StaticSizedView(gfx::Size(10, 20));
99 host_->AddChildView(v2);
100 EXPECT_EQ(gfx::Size(42, 34), layout->GetPreferredSize(host_.get()));
101 host_->SetBounds(0, 0, 100, 100);
102 host_->Layout();
103 EXPECT_EQ(gfx::Rect(7, 7, 10, 86), v1->bounds());
104 EXPECT_EQ(gfx::Rect(25, 7, 10, 86), v2->bounds());
105 }
106
TEST_F(BoxLayoutTest,Overflow)107 TEST_F(BoxLayoutTest, Overflow) {
108 BoxLayout* layout = host_->SetLayoutManager(
109 std::make_unique<BoxLayout>(BoxLayout::Orientation::kHorizontal));
110 View* v1 = new StaticSizedView(gfx::Size(20, 20));
111 host_->AddChildView(v1);
112 View* v2 = new StaticSizedView(gfx::Size(10, 20));
113 host_->AddChildView(v2);
114 host_->SetBounds(0, 0, 15, 10);
115
116 // Overflows by positioning views at the start and truncating anything that
117 // doesn't fit.
118 host_->Layout();
119 EXPECT_EQ(gfx::Rect(0, 0, 15, 10), v1->bounds());
120 EXPECT_EQ(gfx::Rect(0, 0, 0, 0), v2->bounds());
121
122 // Clipping of children should occur at the opposite end(s) to the main axis
123 // alignment position.
124 layout->set_main_axis_alignment(BoxLayout::MainAxisAlignment::kStart);
125 host_->Layout();
126 EXPECT_EQ(gfx::Rect(0, 0, 15, 10), v1->bounds());
127 EXPECT_EQ(gfx::Rect(0, 0, 0, 0), v2->bounds());
128
129 layout->set_main_axis_alignment(BoxLayout::MainAxisAlignment::kCenter);
130 host_->Layout();
131 EXPECT_EQ(gfx::Rect(0, 0, 13, 10), v1->bounds());
132 EXPECT_EQ(gfx::Rect(13, 0, 2, 10), v2->bounds());
133
134 layout->set_main_axis_alignment(BoxLayout::MainAxisAlignment::kEnd);
135 host_->Layout();
136 EXPECT_EQ(gfx::Rect(0, 0, 5, 10), v1->bounds());
137 EXPECT_EQ(gfx::Rect(5, 0, 10, 10), v2->bounds());
138 }
139
TEST_F(BoxLayoutTest,NoSpace)140 TEST_F(BoxLayoutTest, NoSpace) {
141 host_->SetLayoutManager(std::make_unique<BoxLayout>(
142 BoxLayout::Orientation::kHorizontal, gfx::Insets(10), 10));
143 View* childView = new StaticSizedView(gfx::Size(20, 20));
144 host_->AddChildView(childView);
145 host_->SetBounds(0, 0, 10, 10);
146 host_->Layout();
147 EXPECT_EQ(gfx::Rect(0, 0, 0, 0), childView->bounds());
148 }
149
TEST_F(BoxLayoutTest,InvisibleChild)150 TEST_F(BoxLayoutTest, InvisibleChild) {
151 BoxLayout* layout = host_->SetLayoutManager(std::make_unique<BoxLayout>(
152 BoxLayout::Orientation::kHorizontal, gfx::Insets(10), 10));
153 View* v1 = new StaticSizedView(gfx::Size(20, 20));
154 v1->SetVisible(false);
155 host_->AddChildView(v1);
156 View* v2 = new StaticSizedView(gfx::Size(10, 10));
157 host_->AddChildView(v2);
158 EXPECT_EQ(gfx::Size(30, 30), layout->GetPreferredSize(host_.get()));
159 host_->SetBounds(0, 0, 30, 30);
160 host_->Layout();
161 EXPECT_EQ(gfx::Rect(10, 10, 10, 10), v2->bounds());
162 }
163
TEST_F(BoxLayoutTest,UseHeightForWidth)164 TEST_F(BoxLayoutTest, UseHeightForWidth) {
165 BoxLayout* layout = host_->SetLayoutManager(
166 std::make_unique<BoxLayout>(BoxLayout::Orientation::kVertical));
167 View* v1 = new StaticSizedView(gfx::Size(20, 10));
168 host_->AddChildView(v1);
169 ProportionallySizedView* v2 = new ProportionallySizedView(2);
170 v2->SetPreferredWidth(10);
171 host_->AddChildView(v2);
172 EXPECT_EQ(gfx::Size(20, 50), layout->GetPreferredSize(host_.get()));
173
174 host_->SetBounds(0, 0, 20, 50);
175 host_->Layout();
176 EXPECT_EQ(gfx::Rect(0, 0, 20, 10), v1->bounds());
177 EXPECT_EQ(gfx::Rect(0, 10, 20, 40), v2->bounds());
178
179 EXPECT_EQ(110, layout->GetPreferredHeightForWidth(host_.get(), 50));
180
181 // Test without horizontal stretching of the views.
182 layout->set_cross_axis_alignment(BoxLayout::CrossAxisAlignment::kEnd);
183 EXPECT_EQ(gfx::Size(20, 30).ToString(),
184 layout->GetPreferredSize(host_.get()).ToString());
185
186 host_->SetBounds(0, 0, 20, 30);
187 host_->Layout();
188 EXPECT_EQ(gfx::Rect(0, 0, 20, 10), v1->bounds());
189 EXPECT_EQ(gfx::Rect(10, 10, 10, 20), v2->bounds());
190
191 EXPECT_EQ(30, layout->GetPreferredHeightForWidth(host_.get(), 50));
192 }
193
TEST_F(BoxLayoutTest,EmptyPreferredSize)194 TEST_F(BoxLayoutTest, EmptyPreferredSize) {
195 for (size_t i = 0; i < 2; i++) {
196 BoxLayout::Orientation orientation =
197 i == 0 ? BoxLayout::Orientation::kHorizontal
198 : BoxLayout::Orientation::kVertical;
199 host_->RemoveAllChildViews(true);
200 host_->SetLayoutManager(
201 std::make_unique<BoxLayout>(orientation, gfx::Insets(), 5));
202 View* v1 = new StaticSizedView(gfx::Size());
203 host_->AddChildView(v1);
204 View* v2 = new StaticSizedView(gfx::Size(10, 10));
205 host_->AddChildView(v2);
206 host_->SizeToPreferredSize();
207 host_->Layout();
208
209 EXPECT_EQ(v2->GetPreferredSize().width(), host_->bounds().width()) << i;
210 EXPECT_EQ(v2->GetPreferredSize().height(), host_->bounds().height()) << i;
211 EXPECT_EQ(v1->GetPreferredSize().width(), v1->bounds().width()) << i;
212 EXPECT_EQ(v1->GetPreferredSize().height(), v1->bounds().height()) << i;
213 EXPECT_EQ(v2->GetPreferredSize().width(), v2->bounds().width()) << i;
214 EXPECT_EQ(v2->GetPreferredSize().height(), v2->bounds().height()) << i;
215 }
216 }
217
218 // Verifies that a BoxLayout correctly handles child spacing, flex layout, and
219 // empty preferred size, simultaneously.
TEST_F(BoxLayoutTest,EmptyPreferredSizeWithFlexLayoutAndChildSpacing)220 TEST_F(BoxLayoutTest, EmptyPreferredSizeWithFlexLayoutAndChildSpacing) {
221 host_->RemoveAllChildViews(true);
222 BoxLayout* layout = host_->SetLayoutManager(std::make_unique<BoxLayout>(
223 BoxLayout::Orientation::kHorizontal, gfx::Insets(), 5));
224 View* v1 = new StaticSizedView(gfx::Size());
225 host_->AddChildView(v1);
226 View* v2 = new StaticSizedView(gfx::Size(10, 10));
227 host_->AddChildView(v2);
228 View* v3 = new StaticSizedView(gfx::Size(1, 1));
229 host_->AddChildViewAt(v3, 0);
230 layout->SetFlexForView(v3, 1);
231 host_->SetSize(gfx::Size(1000, 15));
232 host_->Layout();
233
234 EXPECT_EQ(host_->bounds().right(), v2->bounds().right());
235 }
236
TEST_F(BoxLayoutTest,MainAxisAlignmentHorizontal)237 TEST_F(BoxLayoutTest, MainAxisAlignmentHorizontal) {
238 BoxLayout* layout = host_->SetLayoutManager(std::make_unique<BoxLayout>(
239 BoxLayout::Orientation::kHorizontal, gfx::Insets(10), 10));
240
241 View* v1 = new StaticSizedView(gfx::Size(20, 20));
242 host_->AddChildView(v1);
243 View* v2 = new StaticSizedView(gfx::Size(10, 10));
244 host_->AddChildView(v2);
245
246 host_->SetBounds(0, 0, 100, 40);
247
248 // Align children to the horizontal start by default.
249 host_->Layout();
250 EXPECT_EQ(gfx::Rect(10, 10, 20, 20).ToString(), v1->bounds().ToString());
251 EXPECT_EQ(gfx::Rect(40, 10, 10, 20).ToString(), v2->bounds().ToString());
252
253 // Ensure same results for MainAxisAlignment::kStart.
254 layout->set_main_axis_alignment(BoxLayout::MainAxisAlignment::kStart);
255 host_->Layout();
256 EXPECT_EQ(gfx::Rect(10, 10, 20, 20).ToString(), v1->bounds().ToString());
257 EXPECT_EQ(gfx::Rect(40, 10, 10, 20).ToString(), v2->bounds().ToString());
258
259 // Aligns children to the center horizontally.
260 layout->set_main_axis_alignment(BoxLayout::MainAxisAlignment::kCenter);
261 host_->Layout();
262 EXPECT_EQ(gfx::Rect(30, 10, 20, 20).ToString(), v1->bounds().ToString());
263 EXPECT_EQ(gfx::Rect(60, 10, 10, 20).ToString(), v2->bounds().ToString());
264
265 // Aligns children to the end of the host horizontally, accounting for the
266 // inside border spacing.
267 layout->set_main_axis_alignment(BoxLayout::MainAxisAlignment::kEnd);
268 host_->Layout();
269 EXPECT_EQ(gfx::Rect(50, 10, 20, 20).ToString(), v1->bounds().ToString());
270 EXPECT_EQ(gfx::Rect(80, 10, 10, 20).ToString(), v2->bounds().ToString());
271 }
272
TEST_F(BoxLayoutTest,MainAxisAlignmentVertical)273 TEST_F(BoxLayoutTest, MainAxisAlignmentVertical) {
274 BoxLayout* layout = host_->SetLayoutManager(std::make_unique<BoxLayout>(
275 BoxLayout::Orientation::kVertical, gfx::Insets(10), 10));
276
277 View* v1 = new StaticSizedView(gfx::Size(20, 20));
278 host_->AddChildView(v1);
279 View* v2 = new StaticSizedView(gfx::Size(10, 10));
280 host_->AddChildView(v2);
281
282 host_->SetBounds(0, 0, 40, 100);
283
284 // Align children to the vertical start by default.
285 host_->Layout();
286 EXPECT_EQ(gfx::Rect(10, 10, 20, 20).ToString(), v1->bounds().ToString());
287 EXPECT_EQ(gfx::Rect(10, 40, 20, 10).ToString(), v2->bounds().ToString());
288
289 // Ensure same results for MainAxisAlignment::kStart.
290 layout->set_main_axis_alignment(BoxLayout::MainAxisAlignment::kStart);
291 host_->Layout();
292 EXPECT_EQ(gfx::Rect(10, 10, 20, 20).ToString(), v1->bounds().ToString());
293 EXPECT_EQ(gfx::Rect(10, 40, 20, 10).ToString(), v2->bounds().ToString());
294
295 // Aligns children to the center vertically.
296 layout->set_main_axis_alignment(BoxLayout::MainAxisAlignment::kCenter);
297 host_->Layout();
298 EXPECT_EQ(gfx::Rect(10, 30, 20, 20).ToString(), v1->bounds().ToString());
299 EXPECT_EQ(gfx::Rect(10, 60, 20, 10).ToString(), v2->bounds().ToString());
300
301 // Aligns children to the end of the host vertically, accounting for the
302 // inside border spacing.
303 layout->set_main_axis_alignment(BoxLayout::MainAxisAlignment::kEnd);
304 host_->Layout();
305 EXPECT_EQ(gfx::Rect(10, 50, 20, 20).ToString(), v1->bounds().ToString());
306 EXPECT_EQ(gfx::Rect(10, 80, 20, 10).ToString(), v2->bounds().ToString());
307 }
308
TEST_F(BoxLayoutTest,CrossAxisAlignmentHorizontal)309 TEST_F(BoxLayoutTest, CrossAxisAlignmentHorizontal) {
310 BoxLayout* layout = host_->SetLayoutManager(std::make_unique<BoxLayout>(
311 BoxLayout::Orientation::kHorizontal, gfx::Insets(10), 10));
312
313 View* v1 = new StaticSizedView(gfx::Size(20, 20));
314 host_->AddChildView(v1);
315 View* v2 = new StaticSizedView(gfx::Size(10, 10));
316 host_->AddChildView(v2);
317
318 host_->SetBounds(0, 0, 100, 60);
319
320 // Stretch children to fill the available height by default.
321 host_->Layout();
322 EXPECT_EQ(gfx::Rect(10, 10, 20, 40).ToString(), v1->bounds().ToString());
323 EXPECT_EQ(gfx::Rect(40, 10, 10, 40).ToString(), v2->bounds().ToString());
324
325 // Ensure same results for kStretch.
326 layout->set_cross_axis_alignment(BoxLayout::CrossAxisAlignment::kStretch);
327 host_->Layout();
328 EXPECT_EQ(gfx::Rect(10, 10, 20, 40).ToString(), v1->bounds().ToString());
329 EXPECT_EQ(gfx::Rect(40, 10, 10, 40).ToString(), v2->bounds().ToString());
330
331 // Aligns children to the start vertically.
332 layout->set_cross_axis_alignment(BoxLayout::CrossAxisAlignment::kStart);
333 host_->Layout();
334 EXPECT_EQ(gfx::Rect(10, 10, 20, 20).ToString(), v1->bounds().ToString());
335 EXPECT_EQ(gfx::Rect(40, 10, 10, 10).ToString(), v2->bounds().ToString());
336
337 // Aligns children to the center vertically.
338 layout->set_cross_axis_alignment(BoxLayout::CrossAxisAlignment::kCenter);
339 host_->Layout();
340 EXPECT_EQ(gfx::Rect(10, 20, 20, 20).ToString(), v1->bounds().ToString());
341 EXPECT_EQ(gfx::Rect(40, 25, 10, 10).ToString(), v2->bounds().ToString());
342
343 // Aligns children to the end of the host vertically, accounting for the
344 // inside border spacing.
345 layout->set_cross_axis_alignment(BoxLayout::CrossAxisAlignment::kEnd);
346 host_->Layout();
347 EXPECT_EQ(gfx::Rect(10, 30, 20, 20).ToString(), v1->bounds().ToString());
348 EXPECT_EQ(gfx::Rect(40, 40, 10, 10).ToString(), v2->bounds().ToString());
349 }
350
TEST_F(BoxLayoutTest,CrossAxisAlignmentVertical)351 TEST_F(BoxLayoutTest, CrossAxisAlignmentVertical) {
352 BoxLayout* layout = host_->SetLayoutManager(std::make_unique<BoxLayout>(
353 BoxLayout::Orientation::kVertical, gfx::Insets(10), 10));
354
355 View* v1 = new StaticSizedView(gfx::Size(20, 20));
356 host_->AddChildView(v1);
357 View* v2 = new StaticSizedView(gfx::Size(10, 10));
358 host_->AddChildView(v2);
359
360 host_->SetBounds(0, 0, 60, 100);
361
362 // Stretch children to fill the available width by default.
363 host_->Layout();
364 EXPECT_EQ(gfx::Rect(10, 10, 40, 20).ToString(), v1->bounds().ToString());
365 EXPECT_EQ(gfx::Rect(10, 40, 40, 10).ToString(), v2->bounds().ToString());
366
367 // Ensure same results for kStretch.
368 layout->set_cross_axis_alignment(BoxLayout::CrossAxisAlignment::kStretch);
369 host_->Layout();
370 EXPECT_EQ(gfx::Rect(10, 10, 40, 20).ToString(), v1->bounds().ToString());
371 EXPECT_EQ(gfx::Rect(10, 40, 40, 10).ToString(), v2->bounds().ToString());
372
373 // Aligns children to the start horizontally.
374 layout->set_cross_axis_alignment(BoxLayout::CrossAxisAlignment::kStart);
375 host_->Layout();
376 EXPECT_EQ(gfx::Rect(10, 10, 20, 20).ToString(), v1->bounds().ToString());
377 EXPECT_EQ(gfx::Rect(10, 40, 10, 10).ToString(), v2->bounds().ToString());
378
379 // Aligns children to the center horizontally.
380 layout->set_cross_axis_alignment(BoxLayout::CrossAxisAlignment::kCenter);
381 host_->Layout();
382 EXPECT_EQ(gfx::Rect(20, 10, 20, 20).ToString(), v1->bounds().ToString());
383 EXPECT_EQ(gfx::Rect(25, 40, 10, 10).ToString(), v2->bounds().ToString());
384
385 // Aligns children to the end of the host horizontally, accounting for the
386 // inside border spacing.
387 layout->set_cross_axis_alignment(BoxLayout::CrossAxisAlignment::kEnd);
388 host_->Layout();
389 EXPECT_EQ(gfx::Rect(30, 10, 20, 20).ToString(), v1->bounds().ToString());
390 EXPECT_EQ(gfx::Rect(40, 40, 10, 10).ToString(), v2->bounds().ToString());
391 }
392
TEST_F(BoxLayoutTest,CrossAxisAlignmentVerticalChildPreferredWidth)393 TEST_F(BoxLayoutTest, CrossAxisAlignmentVerticalChildPreferredWidth) {
394 const int available_width = 40; // box-width - inset - margin
395 const int preferred_width = 30;
396
397 BoxLayout* layout = host_->SetLayoutManager(std::make_unique<BoxLayout>(
398 BoxLayout::Orientation::kVertical, gfx::Insets(10), 10));
399
400 auto* v1 = host_->AddChildView(std::make_unique<ProportionallySizedView>(1));
401 v1->SetPreferredWidth(preferred_width);
402
403 host_->SetBounds(0, 0, 60, 100);
404
405 // Default alignment should stretch child to full available width
406 host_->Layout();
407 EXPECT_EQ(gfx::Rect(10, 10, available_width, available_width), v1->bounds());
408
409 // Stretch alignment should stretch child to full available width
410 layout->set_cross_axis_alignment(BoxLayout::CrossAxisAlignment::kStretch);
411 host_->Layout();
412 EXPECT_EQ(gfx::Rect(10, 10, available_width, available_width), v1->bounds());
413
414 // Child aligned to start should use preferred area
415 layout->set_cross_axis_alignment(BoxLayout::CrossAxisAlignment::kStart);
416 host_->Layout();
417 EXPECT_EQ(gfx::Rect(10, 10, preferred_width, preferred_width), v1->bounds());
418
419 // Child aligned to center should use preferred area
420 layout->set_cross_axis_alignment(BoxLayout::CrossAxisAlignment::kCenter);
421 host_->Layout();
422 EXPECT_EQ(gfx::Rect(15, 10, preferred_width, preferred_width), v1->bounds());
423
424 // Child aligned to end should use preferred area
425 layout->set_cross_axis_alignment(BoxLayout::CrossAxisAlignment::kEnd);
426 host_->Layout();
427 EXPECT_EQ(gfx::Rect(20, 10, preferred_width, preferred_width), v1->bounds());
428 }
429
TEST_F(BoxLayoutTest,CrossAxisAlignmentVerticalChildHugePreferredWidth)430 TEST_F(BoxLayoutTest, CrossAxisAlignmentVerticalChildHugePreferredWidth) {
431 // Here we test the case where the child's preferred width is more than the
432 // actual available width.
433 // In this case the height should be calculated using the available width
434 // and not the preferred width.
435 const int available_width = 40;
436
437 BoxLayout* layout = host_->SetLayoutManager(std::make_unique<BoxLayout>(
438 BoxLayout::Orientation::kVertical, gfx::Insets(10), 10));
439
440 auto* v1 = host_->AddChildView(std::make_unique<ProportionallySizedView>(1));
441 v1->SetPreferredWidth(100);
442
443 host_->SetBounds(0, 0, 60, 100);
444
445 host_->Layout();
446 EXPECT_EQ(gfx::Rect(10, 10, available_width, available_width), v1->bounds());
447
448 layout->set_cross_axis_alignment(BoxLayout::CrossAxisAlignment::kStretch);
449 host_->Layout();
450 EXPECT_EQ(gfx::Rect(10, 10, available_width, available_width), v1->bounds());
451
452 layout->set_cross_axis_alignment(BoxLayout::CrossAxisAlignment::kStart);
453 host_->Layout();
454 EXPECT_EQ(gfx::Rect(10, 10, available_width, available_width), v1->bounds());
455
456 layout->set_cross_axis_alignment(BoxLayout::CrossAxisAlignment::kCenter);
457 host_->Layout();
458 EXPECT_EQ(gfx::Rect(10, 10, available_width, available_width), v1->bounds());
459
460 layout->set_cross_axis_alignment(BoxLayout::CrossAxisAlignment::kEnd);
461 host_->Layout();
462 EXPECT_EQ(gfx::Rect(10, 10, available_width, available_width), v1->bounds());
463 }
464
TEST_F(BoxLayoutTest,FlexAll)465 TEST_F(BoxLayoutTest, FlexAll) {
466 BoxLayout* layout = host_->SetLayoutManager(std::make_unique<BoxLayout>(
467 BoxLayout::Orientation::kHorizontal, gfx::Insets(10), 10));
468 layout->SetDefaultFlex(1);
469
470 View* v1 = new StaticSizedView(gfx::Size(20, 20));
471 host_->AddChildView(v1);
472 View* v2 = new StaticSizedView(gfx::Size(10, 10));
473 host_->AddChildView(v2);
474 View* v3 = new StaticSizedView(gfx::Size(30, 30));
475 host_->AddChildView(v3);
476 EXPECT_EQ(gfx::Size(100, 50), layout->GetPreferredSize(host_.get()));
477
478 host_->SetBounds(0, 0, 120, 50);
479 host_->Layout();
480 EXPECT_EQ(gfx::Rect(10, 10, 27, 30).ToString(), v1->bounds().ToString());
481 EXPECT_EQ(gfx::Rect(47, 10, 16, 30).ToString(), v2->bounds().ToString());
482 EXPECT_EQ(gfx::Rect(73, 10, 37, 30).ToString(), v3->bounds().ToString());
483 }
484
TEST_F(BoxLayoutTest,FlexGrowVertical)485 TEST_F(BoxLayoutTest, FlexGrowVertical) {
486 BoxLayout* layout = host_->SetLayoutManager(std::make_unique<BoxLayout>(
487 BoxLayout::Orientation::kVertical, gfx::Insets(10), 10));
488
489 View* v1 = new StaticSizedView(gfx::Size(20, 20));
490 host_->AddChildView(v1);
491 View* v2 = new StaticSizedView(gfx::Size(10, 10));
492 host_->AddChildView(v2);
493 View* v3 = new StaticSizedView(gfx::Size(30, 30));
494 host_->AddChildView(v3);
495
496 host_->SetBounds(0, 0, 50, 130);
497
498 // Views don't fill the available space by default.
499 host_->Layout();
500 EXPECT_EQ(gfx::Rect(10, 10, 30, 20).ToString(), v1->bounds().ToString());
501 EXPECT_EQ(gfx::Rect(10, 40, 30, 10).ToString(), v2->bounds().ToString());
502 EXPECT_EQ(gfx::Rect(10, 60, 30, 30).ToString(), v3->bounds().ToString());
503
504 for (auto main_alignment : kMainAlignments) {
505 layout->set_main_axis_alignment(main_alignment);
506
507 // Set the first view to consume all free space.
508 layout->SetFlexForView(v1, 1);
509 layout->ClearFlexForView(v2);
510 layout->ClearFlexForView(v3);
511 host_->Layout();
512 EXPECT_EQ(gfx::Rect(10, 10, 30, 50).ToString(), v1->bounds().ToString());
513 EXPECT_EQ(gfx::Rect(10, 70, 30, 10).ToString(), v2->bounds().ToString());
514 EXPECT_EQ(gfx::Rect(10, 90, 30, 30).ToString(), v3->bounds().ToString());
515
516 // Set the third view to take 2/3s of the free space and leave the first
517 // view
518 // with 1/3.
519 layout->SetFlexForView(v3, 2);
520 host_->Layout();
521 EXPECT_EQ(gfx::Rect(10, 10, 30, 30).ToString(), v1->bounds().ToString());
522 EXPECT_EQ(gfx::Rect(10, 50, 30, 10).ToString(), v2->bounds().ToString());
523 EXPECT_EQ(gfx::Rect(10, 70, 30, 50).ToString(), v3->bounds().ToString());
524
525 // Clear the previously set flex values and set the second view to take all
526 // the free space.
527 layout->ClearFlexForView(v1);
528 layout->SetFlexForView(v2, 1);
529 layout->ClearFlexForView(v3);
530 host_->Layout();
531 EXPECT_EQ(gfx::Rect(10, 10, 30, 20).ToString(), v1->bounds().ToString());
532 EXPECT_EQ(gfx::Rect(10, 40, 30, 40).ToString(), v2->bounds().ToString());
533 EXPECT_EQ(gfx::Rect(10, 90, 30, 30).ToString(), v3->bounds().ToString());
534 }
535 }
536
TEST_F(BoxLayoutTest,FlexGrowHorizontalWithRemainder)537 TEST_F(BoxLayoutTest, FlexGrowHorizontalWithRemainder) {
538 BoxLayout* layout = host_->SetLayoutManager(
539 std::make_unique<BoxLayout>(BoxLayout::Orientation::kHorizontal));
540 layout->SetDefaultFlex(1);
541 std::vector<View*> views;
542 for (int i = 0; i < 5; ++i) {
543 View* view = new StaticSizedView(gfx::Size(10, 10));
544 views.push_back(view);
545 host_->AddChildView(view);
546 }
547
548 EXPECT_EQ(gfx::Size(50, 10), layout->GetPreferredSize(host_.get()));
549
550 host_->SetBounds(0, 0, 52, 10);
551 host_->Layout();
552 // The 2nd and 4th views should have an extra pixel as they correspond to 20.8
553 // and 41.6 which round up.
554 EXPECT_EQ(gfx::Rect(0, 0, 10, 10).ToString(), views[0]->bounds().ToString());
555 EXPECT_EQ(gfx::Rect(10, 0, 11, 10).ToString(), views[1]->bounds().ToString());
556 EXPECT_EQ(gfx::Rect(21, 0, 10, 10).ToString(), views[2]->bounds().ToString());
557 EXPECT_EQ(gfx::Rect(31, 0, 11, 10).ToString(), views[3]->bounds().ToString());
558 EXPECT_EQ(gfx::Rect(42, 0, 10, 10).ToString(), views[4]->bounds().ToString());
559 }
560
TEST_F(BoxLayoutTest,FlexGrowHorizontalWithRemainder2)561 TEST_F(BoxLayoutTest, FlexGrowHorizontalWithRemainder2) {
562 BoxLayout* layout = host_->SetLayoutManager(
563 std::make_unique<BoxLayout>(BoxLayout::Orientation::kHorizontal));
564 layout->SetDefaultFlex(1);
565 std::vector<View*> views;
566 for (int i = 0; i < 4; ++i) {
567 View* view = new StaticSizedView(gfx::Size(1, 10));
568 views.push_back(view);
569 host_->AddChildView(view);
570 }
571
572 EXPECT_EQ(gfx::Size(4, 10), layout->GetPreferredSize(host_.get()));
573
574 host_->SetBounds(0, 0, 10, 10);
575 host_->Layout();
576 // The 1st and 3rd views should have an extra pixel as they correspond to 2.5
577 // and 7.5 which round up.
578 EXPECT_EQ(gfx::Rect(0, 0, 3, 10).ToString(), views[0]->bounds().ToString());
579 EXPECT_EQ(gfx::Rect(3, 0, 2, 10).ToString(), views[1]->bounds().ToString());
580 EXPECT_EQ(gfx::Rect(5, 0, 3, 10).ToString(), views[2]->bounds().ToString());
581 EXPECT_EQ(gfx::Rect(8, 0, 2, 10).ToString(), views[3]->bounds().ToString());
582 }
583
TEST_F(BoxLayoutTest,FlexShrinkHorizontal)584 TEST_F(BoxLayoutTest, FlexShrinkHorizontal) {
585 BoxLayout* layout = host_->SetLayoutManager(std::make_unique<BoxLayout>(
586 BoxLayout::Orientation::kHorizontal, gfx::Insets(10), 10));
587
588 View* v1 = new StaticSizedView(gfx::Size(20, 20));
589 host_->AddChildView(v1);
590 View* v2 = new StaticSizedView(gfx::Size(10, 10));
591 host_->AddChildView(v2);
592 View* v3 = new StaticSizedView(gfx::Size(30, 30));
593 host_->AddChildView(v3);
594
595 host_->SetBounds(0, 0, 85, 50);
596
597 // Truncate width by default.
598 host_->Layout();
599 EXPECT_EQ(gfx::Rect(10, 10, 20, 30).ToString(), v1->bounds().ToString());
600 EXPECT_EQ(gfx::Rect(40, 10, 10, 30).ToString(), v2->bounds().ToString());
601 EXPECT_EQ(gfx::Rect(60, 10, 15, 30).ToString(), v3->bounds().ToString());
602
603 for (auto main_alignment : kMainAlignments) {
604 layout->set_main_axis_alignment(main_alignment);
605
606 // Set the first view to shrink as much as necessary.
607 layout->SetFlexForView(v1, 1);
608 layout->ClearFlexForView(v2);
609 layout->ClearFlexForView(v3);
610 host_->Layout();
611 EXPECT_EQ(gfx::Rect(10, 10, 5, 30).ToString(), v1->bounds().ToString());
612 EXPECT_EQ(gfx::Rect(25, 10, 10, 30).ToString(), v2->bounds().ToString());
613 EXPECT_EQ(gfx::Rect(45, 10, 30, 30).ToString(), v3->bounds().ToString());
614
615 // Set the third view to shrink 2/3s of the free space and leave the first
616 // view with 1/3.
617 layout->SetFlexForView(v3, 2);
618 host_->Layout();
619 EXPECT_EQ(gfx::Rect(10, 10, 15, 30).ToString(), v1->bounds().ToString());
620 EXPECT_EQ(gfx::Rect(35, 10, 10, 30).ToString(), v2->bounds().ToString());
621 EXPECT_EQ(gfx::Rect(55, 10, 20, 30).ToString(), v3->bounds().ToString());
622
623 // Clear the previously set flex values and set the second view to take all
624 // the free space with MainAxisAlignment::kEnd set. This causes the second
625 // view to shrink to zero and the third view still doesn't fit so it
626 // overflows.
627 layout->ClearFlexForView(v1);
628 layout->SetFlexForView(v2, 2);
629 layout->ClearFlexForView(v3);
630 host_->Layout();
631 EXPECT_EQ(gfx::Rect(10, 10, 20, 30).ToString(), v1->bounds().ToString());
632 // Conceptually this view is at 10, 40, 0, 0.
633 EXPECT_EQ(gfx::Rect(0, 0, 0, 0).ToString(), v2->bounds().ToString());
634 EXPECT_EQ(gfx::Rect(50, 10, 25, 30).ToString(), v3->bounds().ToString());
635 }
636 }
637
TEST_F(BoxLayoutTest,FlexShrinkVerticalWithRemainder)638 TEST_F(BoxLayoutTest, FlexShrinkVerticalWithRemainder) {
639 BoxLayout* layout = host_->SetLayoutManager(
640 std::make_unique<BoxLayout>(BoxLayout::Orientation::kVertical));
641 View* v1 = new StaticSizedView(gfx::Size(20, 10));
642 host_->AddChildView(v1);
643 View* v2 = new StaticSizedView(gfx::Size(20, 20));
644 host_->AddChildView(v2);
645 View* v3 = new StaticSizedView(gfx::Size(20, 10));
646 host_->AddChildView(v3);
647 host_->SetBounds(0, 0, 20, 20);
648
649 for (auto main_alignment : kMainAlignments) {
650 layout->set_main_axis_alignment(main_alignment);
651
652 // The first view shrinks by 1/3 of the excess, the second view shrinks by
653 // 2/3 of the excess and the third view should maintain its preferred size.
654 layout->SetFlexForView(v1, 1);
655 layout->SetFlexForView(v2, 2);
656 layout->ClearFlexForView(v3);
657 host_->Layout();
658 EXPECT_EQ(gfx::Rect(0, 0, 20, 3).ToString(), v1->bounds().ToString());
659 EXPECT_EQ(gfx::Rect(0, 3, 20, 7).ToString(), v2->bounds().ToString());
660 EXPECT_EQ(gfx::Rect(0, 10, 20, 10).ToString(), v3->bounds().ToString());
661
662 // The second view shrinks to 2/3 of the excess, the third view shrinks to
663 // 1/3 of the excess and the first view should maintain its preferred size.
664 layout->ClearFlexForView(v1);
665 layout->SetFlexForView(v2, 2);
666 layout->SetFlexForView(v3, 1);
667 host_->Layout();
668 EXPECT_EQ(gfx::Rect(0, 0, 20, 10).ToString(), v1->bounds().ToString());
669 EXPECT_EQ(gfx::Rect(0, 10, 20, 7).ToString(), v2->bounds().ToString());
670 EXPECT_EQ(gfx::Rect(0, 17, 20, 3).ToString(), v3->bounds().ToString());
671
672 // Each view shrinks equally to fit within the available space.
673 layout->SetFlexForView(v1, 1);
674 layout->SetFlexForView(v2, 1);
675 layout->SetFlexForView(v3, 1);
676 host_->Layout();
677 EXPECT_EQ(gfx::Rect(0, 0, 20, 3).ToString(), v1->bounds().ToString());
678 EXPECT_EQ(gfx::Rect(0, 3, 20, 14).ToString(), v2->bounds().ToString());
679 EXPECT_EQ(gfx::Rect(0, 17, 20, 3).ToString(), v3->bounds().ToString());
680 }
681 }
682
TEST_F(BoxLayoutTest,MinimumCrossAxisVertical)683 TEST_F(BoxLayoutTest, MinimumCrossAxisVertical) {
684 BoxLayout* layout = host_->SetLayoutManager(
685 std::make_unique<BoxLayout>(BoxLayout::Orientation::kVertical));
686 View* v1 = new StaticSizedView(gfx::Size(20, 10));
687 host_->AddChildView(v1);
688 layout->set_minimum_cross_axis_size(30);
689
690 EXPECT_EQ(gfx::Size(30, 10), layout->GetPreferredSize(host_.get()));
691 }
692
TEST_F(BoxLayoutTest,MinimumCrossAxisHorizontal)693 TEST_F(BoxLayoutTest, MinimumCrossAxisHorizontal) {
694 BoxLayout* layout = host_->SetLayoutManager(
695 std::make_unique<BoxLayout>(BoxLayout::Orientation::kHorizontal));
696 View* v1 = new StaticSizedView(gfx::Size(20, 10));
697 host_->AddChildView(v1);
698 layout->set_minimum_cross_axis_size(30);
699
700 EXPECT_EQ(gfx::Size(20, 30), layout->GetPreferredSize(host_.get()));
701 }
702
TEST_F(BoxLayoutTest,MarginsUncollapsedHorizontal)703 TEST_F(BoxLayoutTest, MarginsUncollapsedHorizontal) {
704 BoxLayout* layout = host_->SetLayoutManager(
705 std::make_unique<BoxLayout>(BoxLayout::Orientation::kHorizontal));
706 View* v1 = new StaticSizedView(gfx::Size(20, 10));
707 v1->SetProperty(kMarginsKey, gfx::Insets(5, 5, 5, 5));
708 host_->AddChildView(v1);
709 View* v2 = new StaticSizedView(gfx::Size(20, 10));
710 v2->SetProperty(kMarginsKey, gfx::Insets(6, 4, 6, 4));
711 host_->AddChildView(v2);
712
713 EXPECT_EQ(gfx::Size(58, 22), layout->GetPreferredSize(host_.get()));
714 host_->SizeToPreferredSize();
715 layout->Layout(host_.get());
716 EXPECT_EQ(gfx::Rect(5, 5, 20, 12), v1->bounds());
717 EXPECT_EQ(gfx::Rect(34, 6, 20, 10), v2->bounds());
718 }
719
TEST_F(BoxLayoutTest,MarginsCollapsedHorizontal)720 TEST_F(BoxLayoutTest, MarginsCollapsedHorizontal) {
721 BoxLayout* layout = host_->SetLayoutManager(std::make_unique<BoxLayout>(
722 BoxLayout::Orientation::kHorizontal, gfx::Insets(0, 0), 0, true));
723 View* v1 = new StaticSizedView(gfx::Size(20, 10));
724 v1->SetProperty(kMarginsKey, gfx::Insets(5, 5, 5, 5));
725 host_->AddChildView(v1);
726 View* v2 = new StaticSizedView(gfx::Size(20, 10));
727 v2->SetProperty(kMarginsKey, gfx::Insets(6, 4, 6, 4));
728 host_->AddChildView(v2);
729
730 EXPECT_EQ(gfx::Size(54, 22), layout->GetPreferredSize(host_.get()));
731 host_->SizeToPreferredSize();
732 layout->Layout(host_.get());
733 EXPECT_EQ(gfx::Rect(5, 5, 20, 12), v1->bounds());
734 EXPECT_EQ(gfx::Rect(30, 6, 20, 10), v2->bounds());
735 }
736
TEST_F(BoxLayoutTest,MarginsUncollapsedVertical)737 TEST_F(BoxLayoutTest, MarginsUncollapsedVertical) {
738 BoxLayout* layout = host_->SetLayoutManager(
739 std::make_unique<BoxLayout>(BoxLayout::Orientation::kVertical));
740 View* v1 = new StaticSizedView(gfx::Size(20, 10));
741 v1->SetProperty(kMarginsKey, gfx::Insets(5, 5, 5, 5));
742 host_->AddChildView(v1);
743 View* v2 = new StaticSizedView(gfx::Size(20, 10));
744 v2->SetProperty(kMarginsKey, gfx::Insets(6, 4, 6, 4));
745 host_->AddChildView(v2);
746
747 EXPECT_EQ(gfx::Size(30, 42), layout->GetPreferredSize(host_.get()));
748 host_->SizeToPreferredSize();
749 layout->Layout(host_.get());
750 EXPECT_EQ(gfx::Rect(5, 5, 20, 10), v1->bounds());
751 EXPECT_EQ(gfx::Rect(4, 26, 22, 10), v2->bounds());
752 }
753
TEST_F(BoxLayoutTest,MarginsCollapsedVertical)754 TEST_F(BoxLayoutTest, MarginsCollapsedVertical) {
755 BoxLayout* layout = host_->SetLayoutManager(std::make_unique<BoxLayout>(
756 BoxLayout::Orientation::kVertical, gfx::Insets(0, 0), 0, true));
757 View* v1 = new StaticSizedView(gfx::Size(20, 10));
758 v1->SetProperty(kMarginsKey, gfx::Insets(5, 5, 5, 5));
759 host_->AddChildView(v1);
760 View* v2 = new StaticSizedView(gfx::Size(20, 10));
761 v2->SetProperty(kMarginsKey, gfx::Insets(6, 4, 6, 4));
762 host_->AddChildView(v2);
763
764 EXPECT_EQ(gfx::Size(30, 37), layout->GetPreferredSize(host_.get()));
765 host_->SizeToPreferredSize();
766 layout->Layout(host_.get());
767 EXPECT_EQ(gfx::Rect(5, 5, 20, 10), v1->bounds());
768 EXPECT_EQ(gfx::Rect(4, 21, 22, 10), v2->bounds());
769 }
770
TEST_F(BoxLayoutTest,UnbalancedMarginsUncollapsedHorizontal)771 TEST_F(BoxLayoutTest, UnbalancedMarginsUncollapsedHorizontal) {
772 auto layout_owner =
773 std::make_unique<BoxLayout>(BoxLayout::Orientation::kHorizontal);
774 layout_owner->set_cross_axis_alignment(
775 BoxLayout::CrossAxisAlignment::kCenter);
776 BoxLayout* layout = host_->SetLayoutManager(std::move(layout_owner));
777 View* v1 = new StaticSizedView(gfx::Size(20, 10));
778 v1->SetProperty(kMarginsKey, gfx::Insets(5, 5, 4, 4));
779 host_->AddChildView(v1);
780 View* v2 = new StaticSizedView(gfx::Size(20, 10));
781 v2->SetProperty(kMarginsKey, gfx::Insets(6, 4, 3, 6));
782 host_->AddChildView(v2);
783
784 EXPECT_EQ(gfx::Size(59, 20), layout->GetPreferredSize(host_.get()));
785 host_->SizeToPreferredSize();
786 layout->Layout(host_.get());
787 EXPECT_EQ(gfx::Rect(5, 5, 20, 10), v1->bounds());
788 EXPECT_EQ(gfx::Rect(33, 6, 20, 10), v2->bounds());
789 }
790
TEST_F(BoxLayoutTest,UnbalancedMarginsCollapsedHorizontal)791 TEST_F(BoxLayoutTest, UnbalancedMarginsCollapsedHorizontal) {
792 auto layout_owner = std::make_unique<BoxLayout>(
793 BoxLayout::Orientation::kHorizontal, gfx::Insets(0, 0), 0, true);
794 layout_owner->set_cross_axis_alignment(
795 BoxLayout::CrossAxisAlignment::kCenter);
796 BoxLayout* layout = host_->SetLayoutManager(std::move(layout_owner));
797 View* v1 = new StaticSizedView(gfx::Size(20, 10));
798 v1->SetProperty(kMarginsKey, gfx::Insets(5, 5, 4, 4));
799 host_->AddChildView(v1);
800 View* v2 = new StaticSizedView(gfx::Size(20, 10));
801 v2->SetProperty(kMarginsKey, gfx::Insets(6, 4, 3, 6));
802 host_->AddChildView(v2);
803
804 EXPECT_EQ(gfx::Size(55, 20), layout->GetPreferredSize(host_.get()));
805 host_->SizeToPreferredSize();
806 layout->Layout(host_.get());
807 EXPECT_EQ(gfx::Rect(5, 5, 20, 10), v1->bounds());
808 EXPECT_EQ(gfx::Rect(29, 6, 20, 10), v2->bounds());
809 }
810
TEST_F(BoxLayoutTest,UnbalancedMarginsUncollapsedVertical)811 TEST_F(BoxLayoutTest, UnbalancedMarginsUncollapsedVertical) {
812 auto layout_owner =
813 std::make_unique<BoxLayout>(BoxLayout::Orientation::kVertical);
814 layout_owner->set_cross_axis_alignment(
815 BoxLayout::CrossAxisAlignment::kCenter);
816 BoxLayout* layout = host_->SetLayoutManager(std::move(layout_owner));
817 View* v1 = new StaticSizedView(gfx::Size(20, 10));
818 v1->SetProperty(kMarginsKey, gfx::Insets(4, 5, 5, 3));
819 host_->AddChildView(v1);
820 View* v2 = new StaticSizedView(gfx::Size(20, 10));
821 v2->SetProperty(kMarginsKey, gfx::Insets(6, 4, 3, 5));
822 host_->AddChildView(v2);
823
824 EXPECT_EQ(gfx::Size(30, 38), layout->GetPreferredSize(host_.get()));
825 host_->SizeToPreferredSize();
826 layout->Layout(host_.get());
827 EXPECT_EQ(gfx::Rect(5, 4, 20, 10), v1->bounds());
828 EXPECT_EQ(gfx::Rect(5, 25, 20, 10), v2->bounds());
829 }
830
TEST_F(BoxLayoutTest,UnbalancedMarginsCollapsedVertical)831 TEST_F(BoxLayoutTest, UnbalancedMarginsCollapsedVertical) {
832 auto layout_owner = std::make_unique<BoxLayout>(
833 BoxLayout::Orientation::kVertical, gfx::Insets(0, 0), 0, true);
834 layout_owner->set_cross_axis_alignment(
835 BoxLayout::CrossAxisAlignment::kCenter);
836 BoxLayout* layout = host_->SetLayoutManager(std::move(layout_owner));
837 View* v1 = new StaticSizedView(gfx::Size(20, 10));
838 v1->SetProperty(kMarginsKey, gfx::Insets(4, 5, 5, 3));
839 host_->AddChildView(v1);
840 View* v2 = new StaticSizedView(gfx::Size(20, 10));
841 v2->SetProperty(kMarginsKey, gfx::Insets(6, 4, 3, 5));
842 host_->AddChildView(v2);
843
844 EXPECT_EQ(gfx::Size(30, 33), layout->GetPreferredSize(host_.get()));
845 host_->SizeToPreferredSize();
846 layout->Layout(host_.get());
847 EXPECT_EQ(gfx::Rect(5, 4, 20, 10), v1->bounds());
848 EXPECT_EQ(gfx::Rect(5, 20, 20, 10), v2->bounds());
849 }
850
TEST_F(BoxLayoutTest,OverlappingCrossMarginsAlignEnd)851 TEST_F(BoxLayoutTest, OverlappingCrossMarginsAlignEnd) {
852 {
853 BoxLayout* layout = host_->SetLayoutManager(
854 std::make_unique<BoxLayout>(BoxLayout::Orientation::kHorizontal));
855 layout->set_cross_axis_alignment(BoxLayout::CrossAxisAlignment::kEnd);
856 View* v1 = new StaticSizedView(gfx::Size(20, 4));
857 v1->SetProperty(kMarginsKey, gfx::Insets(3, 0, 0, 0));
858 host_->AddChildView(v1);
859 View* v2 = new StaticSizedView(gfx::Size(20, 5));
860 v2->SetProperty(kMarginsKey, gfx::Insets(0, 0, 2, 0));
861 host_->AddChildView(v2);
862
863 EXPECT_EQ(9, layout->GetPreferredSize(host_.get()).height());
864 }
865 host_->RemoveAllChildViews(true);
866 {
867 BoxLayout* layout = host_->SetLayoutManager(std::make_unique<BoxLayout>(
868 BoxLayout::Orientation::kHorizontal, gfx::Insets(0, 0), 0, true));
869 layout->set_cross_axis_alignment(BoxLayout::CrossAxisAlignment::kEnd);
870 View* v1 = new StaticSizedView(gfx::Size(20, 4));
871 v1->SetProperty(kMarginsKey, gfx::Insets(3, 0, 0, 0));
872 host_->AddChildView(v1);
873 View* v2 = new StaticSizedView(gfx::Size(20, 5));
874 v2->SetProperty(kMarginsKey, gfx::Insets(0, 0, 2, 0));
875 host_->AddChildView(v2);
876
877 EXPECT_EQ(9, layout->GetPreferredSize(host_.get()).height());
878 }
879 }
880
TEST_F(BoxLayoutTest,OverlappingCrossMarginsAlignStretch)881 TEST_F(BoxLayoutTest, OverlappingCrossMarginsAlignStretch) {
882 {
883 BoxLayout* layout = host_->SetLayoutManager(
884 std::make_unique<BoxLayout>(BoxLayout::Orientation::kHorizontal));
885 layout->set_cross_axis_alignment(BoxLayout::CrossAxisAlignment::kStretch);
886 View* v1 = new StaticSizedView(gfx::Size(20, 4));
887 v1->SetProperty(kMarginsKey, gfx::Insets(3, 0, 0, 0));
888 host_->AddChildView(v1);
889 View* v2 = new StaticSizedView(gfx::Size(20, 5));
890 v2->SetProperty(kMarginsKey, gfx::Insets(0, 0, 2, 0));
891 host_->AddChildView(v2);
892
893 EXPECT_EQ(10, layout->GetPreferredSize(host_.get()).height());
894 }
895 host_->RemoveAllChildViews(true);
896 {
897 BoxLayout* layout = host_->SetLayoutManager(std::make_unique<BoxLayout>(
898 BoxLayout::Orientation::kHorizontal, gfx::Insets(0, 0), 0, true));
899 layout->set_cross_axis_alignment(BoxLayout::CrossAxisAlignment::kStretch);
900 View* v1 = new StaticSizedView(gfx::Size(20, 4));
901 v1->SetProperty(kMarginsKey, gfx::Insets(3, 0, 0, 0));
902 host_->AddChildView(v1);
903 View* v2 = new StaticSizedView(gfx::Size(20, 5));
904 v2->SetProperty(kMarginsKey, gfx::Insets(0, 0, 2, 0));
905 host_->AddChildView(v2);
906
907 EXPECT_EQ(10, layout->GetPreferredSize(host_.get()).height());
908 }
909 }
910
TEST_F(BoxLayoutTest,OverlappingCrossMarginsAlignStart)911 TEST_F(BoxLayoutTest, OverlappingCrossMarginsAlignStart) {
912 {
913 BoxLayout* layout = host_->SetLayoutManager(
914 std::make_unique<BoxLayout>(BoxLayout::Orientation::kHorizontal));
915 layout->set_cross_axis_alignment(BoxLayout::CrossAxisAlignment::kStart);
916 View* v1 = new StaticSizedView(gfx::Size(20, 4));
917 v1->SetProperty(kMarginsKey, gfx::Insets(0, 0, 3, 0));
918 host_->AddChildView(v1);
919 View* v2 = new StaticSizedView(gfx::Size(20, 5));
920 v2->SetProperty(kMarginsKey, gfx::Insets(2, 0, 0, 0));
921 host_->AddChildView(v2);
922
923 EXPECT_EQ(9, layout->GetPreferredSize(host_.get()).height());
924 }
925 host_->RemoveAllChildViews(true);
926 {
927 BoxLayout* layout = host_->SetLayoutManager(std::make_unique<BoxLayout>(
928 BoxLayout::Orientation::kHorizontal, gfx::Insets(0, 0), 0, true));
929 layout->set_cross_axis_alignment(BoxLayout::CrossAxisAlignment::kStart);
930 View* v1 = new StaticSizedView(gfx::Size(20, 4));
931 v1->SetProperty(kMarginsKey, gfx::Insets(0, 0, 3, 0));
932 host_->AddChildView(v1);
933 View* v2 = new StaticSizedView(gfx::Size(20, 5));
934 v2->SetProperty(kMarginsKey, gfx::Insets(2, 0, 0, 0));
935 host_->AddChildView(v2);
936
937 EXPECT_EQ(9, layout->GetPreferredSize(host_.get()).height());
938 }
939 }
940
TEST_F(BoxLayoutTest,NegativeBetweenChildSpacing)941 TEST_F(BoxLayoutTest, NegativeBetweenChildSpacing) {
942 BoxLayout* layout = host_->SetLayoutManager(std::make_unique<BoxLayout>(
943 BoxLayout::Orientation::kVertical, gfx::Insets(), -10));
944 View* v1 = new StaticSizedView(gfx::Size(20, 20));
945 host_->AddChildView(v1);
946 View* v2 = new StaticSizedView(gfx::Size(20, 15));
947 host_->AddChildView(v2);
948
949 EXPECT_EQ(25, layout->GetPreferredSize(host_.get()).height());
950 EXPECT_EQ(20, layout->GetPreferredSize(host_.get()).width());
951 host_->SetBounds(0, 0, 20, 25);
952 host_->Layout();
953 EXPECT_EQ(gfx::Rect(0, 0, 20, 20), v1->bounds());
954 EXPECT_EQ(gfx::Rect(0, 10, 20, 15), v2->bounds());
955 }
956
TEST_F(BoxLayoutTest,MinimumChildSize)957 TEST_F(BoxLayoutTest, MinimumChildSize) {
958 BoxLayout* layout = host_->SetLayoutManager(std::make_unique<BoxLayout>(
959 BoxLayout::Orientation::kHorizontal, gfx::Insets()));
960 StaticSizedView* v1 = new StaticSizedView(gfx::Size(20, 20));
961 host_->AddChildView(v1);
962 StaticSizedView* v2 = new StaticSizedView(gfx::Size(20, 20));
963 host_->AddChildView(v2);
964
965 v1->set_minimum_size(gfx::Size(10, 20));
966 layout->SetFlexForView(v1, 1, true);
967
968 gfx::Size preferred_size = layout->GetPreferredSize(host_.get());
969 EXPECT_EQ(40, preferred_size.width());
970 EXPECT_EQ(20, preferred_size.height());
971
972 host_->SetBounds(0, 0, 15, 20);
973 host_->Layout();
974 EXPECT_EQ(gfx::Rect(0, 0, 10, 20), v1->bounds());
975 EXPECT_EQ(gfx::Rect(10, 0, 5, 20), v2->bounds());
976
977 v1->set_minimum_size(gfx::Size(5, 20));
978
979 host_->Layout();
980 EXPECT_EQ(gfx::Rect(0, 0, 5, 20), v1->bounds());
981 EXPECT_EQ(gfx::Rect(5, 0, 10, 20), v2->bounds());
982 }
983
984 } // namespace views
985