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