Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(293)

Side by Side Diff: ui/views/layout/box_layout.cc

Issue 2836313002: BoxLayout now suports per-view margins. (Closed)
Patch Set: Added unit tests. Fixed GetPreferredSize() calculations. Refactored some code. Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ui/views/layout/box_layout.h" 5 #include "ui/views/layout/box_layout.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "ui/gfx/geometry/rect.h" 9 #include "ui/gfx/geometry/rect.h"
10 #include "ui/views/view.h" 10 #include "ui/views/view.h"
11 11
12 namespace views { 12 namespace views {
13 13
14 BoxLayout::ViewWrapper::ViewWrapper() : view_(nullptr), layout_(nullptr) {}
15
16 BoxLayout::ViewWrapper::ViewWrapper(const BoxLayout* layout, View* view)
17 : view_(view), layout_(layout) {
18 gfx::Insets* margins = view_ ? view_->GetProperty(kMarginsKey) : nullptr;
19 if (margins)
20 margins_ = *margins;
21 }
22
23 BoxLayout::ViewWrapper::~ViewWrapper() {}
24
25 int BoxLayout::ViewWrapper::GetHeightForWidth(int width) const {
26 return layout_->collapse_margins_spacing_
27 ? view_->GetHeightForWidth(width)
28 : view_->GetHeightForWidth(std::max(0, width - margins_.width())) +
29 margins_.height();
30 }
31
32 gfx::Size BoxLayout::ViewWrapper::GetPreferredSize() const {
33 gfx::Size preferred_size = view_->GetPreferredSize();
34 if (!layout_->collapse_margins_spacing_)
35 preferred_size.Enlarge(margins_.width(), margins_.height());
36 return preferred_size;
37 }
38
39 void BoxLayout::ViewWrapper::SetBoundsRect(const gfx::Rect& bounds) {
40 if (layout_->collapse_margins_spacing_) {
41 view_->SetBounds(bounds.x(), bounds.y(), bounds.width(), bounds.height());
sky 2017/05/15 20:29:09 view_->SetBoundsRect(bounds)
kylix_rd 2017/05/16 18:45:47 Done.
42 } else {
43 view_->SetBounds(bounds.x() + margins_.left(), bounds.y() + margins_.top(),
44 std::max(0, bounds.width() - margins_.width()),
45 std::max(0, bounds.height() - margins_.height()));
46 }
47 }
48
49 bool BoxLayout::ViewWrapper::visible() const {
50 return view_->visible();
51 }
52
14 BoxLayout::BoxLayout(BoxLayout::Orientation orientation, 53 BoxLayout::BoxLayout(BoxLayout::Orientation orientation,
15 int inside_border_horizontal_spacing, 54 int inside_border_horizontal_spacing,
16 int inside_border_vertical_spacing, 55 int inside_border_vertical_spacing,
17 int between_child_spacing) 56 int between_child_spacing,
57 bool collapse_margins_spacing)
18 : orientation_(orientation), 58 : orientation_(orientation),
19 inside_border_insets_(inside_border_vertical_spacing, 59 inside_border_insets_(inside_border_vertical_spacing,
20 inside_border_horizontal_spacing), 60 inside_border_horizontal_spacing),
21 between_child_spacing_(between_child_spacing), 61 between_child_spacing_(between_child_spacing),
22 main_axis_alignment_(MAIN_AXIS_ALIGNMENT_START), 62 main_axis_alignment_(MAIN_AXIS_ALIGNMENT_START),
23 cross_axis_alignment_(CROSS_AXIS_ALIGNMENT_STRETCH), 63 cross_axis_alignment_(CROSS_AXIS_ALIGNMENT_STRETCH),
24 default_flex_(0), 64 default_flex_(0),
25 minimum_cross_axis_size_(0), 65 minimum_cross_axis_size_(0),
26 host_(NULL) { 66 collapse_margins_spacing_(collapse_margins_spacing),
27 } 67 host_(NULL) {}
28 68
29 BoxLayout::~BoxLayout() { 69 BoxLayout::~BoxLayout() {
30 } 70 }
31 71
32 void BoxLayout::SetFlexForView(const View* view, int flex_weight) { 72 void BoxLayout::SetFlexForView(const View* view, int flex_weight) {
33 DCHECK(host_); 73 DCHECK(host_);
34 DCHECK(view); 74 DCHECK(view);
35 DCHECK_EQ(host_, view->parent()); 75 DCHECK_EQ(host_, view->parent());
36 DCHECK_GE(flex_weight, 0); 76 DCHECK_GE(flex_weight, 0);
37 flex_map_[view] = flex_weight; 77 flex_map_[view] = flex_weight;
38 } 78 }
39 79
40 void BoxLayout::ClearFlexForView(const View* view) { 80 void BoxLayout::ClearFlexForView(const View* view) {
41 DCHECK(view); 81 DCHECK(view);
42 flex_map_.erase(view); 82 flex_map_.erase(view);
43 } 83 }
44 84
45 void BoxLayout::SetDefaultFlex(int default_flex) { 85 void BoxLayout::SetDefaultFlex(int default_flex) {
46 DCHECK_GE(default_flex, 0); 86 DCHECK_GE(default_flex, 0);
47 default_flex_ = default_flex; 87 default_flex_ = default_flex;
48 } 88 }
49 89
50 void BoxLayout::Layout(View* host) { 90 void BoxLayout::Layout(View* host) {
51 DCHECK_EQ(host_, host); 91 DCHECK_EQ(host_, host);
52 gfx::Rect child_area(host->GetLocalBounds()); 92 gfx::Rect child_area(host->GetContentsBounds());
53 child_area.Inset(host->GetInsets()); 93 if (collapse_margins_spacing_) {
54 child_area.Inset(inside_border_insets_); 94 AdjustMainAxisForMargin(&child_area);
95 AdjustCrossAxisForMargin(&child_area);
96 } else {
97 child_area.Inset(inside_border_insets_);
98 }
55 99
56 int total_main_axis_size = 0; 100 int total_main_axis_size = 0;
57 int num_visible = 0; 101 int num_visible = 0;
58 int flex_sum = 0; 102 int flex_sum = 0;
59 // Calculate the total size of children in the main axis. 103 // Calculate the total size of children in the main axis.
60 for (int i = 0; i < host->child_count(); ++i) { 104 for (int i = 0; i < host->child_count(); ++i) {
61 View* child = host->child_at(i); 105 ViewWrapper child(this, host->child_at(i));
62 if (!child->visible()) 106 ViewWrapper next(this, NextVisibleView(i));
107 if (!child.visible())
63 continue; 108 continue;
64 int flex = GetFlexForView(child); 109 int flex = GetFlexForView(child.view());
65 int child_main_axis_size = MainAxisSizeForView(child, child_area.width()); 110 int child_main_axis_size = MainAxisSizeForView(child, child_area.width());
66 if (child_main_axis_size == 0 && flex == 0) 111 if (child_main_axis_size == 0 && flex == 0)
67 continue; 112 continue;
68 total_main_axis_size += child_main_axis_size + between_child_spacing_; 113 total_main_axis_size +=
114 child_main_axis_size + MainAxisMarginBetweenViews(child, next);
69 ++num_visible; 115 ++num_visible;
70 flex_sum += flex; 116 flex_sum += flex;
71 } 117 }
72 118
73 if (!num_visible) 119 if (!num_visible)
74 return; 120 return;
75 121
76 total_main_axis_size -= between_child_spacing_; 122 total_main_axis_size -= between_child_spacing_;
77 // Free space can be negative indicating that the views want to overflow. 123 // Free space can be negative indicating that the views want to overflow.
78 int main_free_space = MainAxisSize(child_area) - total_main_axis_size; 124 int main_free_space = MainAxisSize(child_area) - total_main_axis_size;
(...skipping 20 matching lines...) Expand all
99 gfx::Rect new_child_area(child_area); 145 gfx::Rect new_child_area(child_area);
100 SetMainAxisPosition(position, &new_child_area); 146 SetMainAxisPosition(position, &new_child_area);
101 SetMainAxisSize(size, &new_child_area); 147 SetMainAxisSize(size, &new_child_area);
102 child_area.Intersect(new_child_area); 148 child_area.Intersect(new_child_area);
103 } 149 }
104 150
105 int main_position = MainAxisPosition(child_area); 151 int main_position = MainAxisPosition(child_area);
106 int total_padding = 0; 152 int total_padding = 0;
107 int current_flex = 0; 153 int current_flex = 0;
108 for (int i = 0; i < host->child_count(); ++i) { 154 for (int i = 0; i < host->child_count(); ++i) {
109 View* child = host->child_at(i); 155 ViewWrapper child(this, host->child_at(i));
110 if (!child->visible()) 156 ViewWrapper next(this, NextVisibleView(i));
157 if (!child.visible())
111 continue; 158 continue;
112 159
113 // TODO(bruthig): Fix this. The main axis should be calculated before 160 // TODO(bruthig): Fix this. The main axis should be calculated before
114 // the cross axis size because child Views may calculate their cross axis 161 // the cross axis size because child Views may calculate their cross axis
115 // size based on their main axis size. See https://crbug.com/682266. 162 // size based on their main axis size. See https://crbug.com/682266.
116 163
117 // Calculate cross axis size. 164 // Calculate cross axis size.
118 gfx::Rect bounds(child_area); 165 gfx::Rect bounds(child_area);
119 SetMainAxisPosition(main_position, &bounds); 166 SetMainAxisPosition(main_position, &bounds);
120 if (cross_axis_alignment_ != CROSS_AXIS_ALIGNMENT_STRETCH) { 167 if (cross_axis_alignment_ != CROSS_AXIS_ALIGNMENT_STRETCH) {
121 int free_space = CrossAxisSize(bounds) - CrossAxisSizeForView(child); 168 int free_space = CrossAxisSize(bounds) - CrossAxisSizeForView(child);
122 int position = CrossAxisPosition(bounds); 169 int position = CrossAxisPosition(bounds);
123 if (cross_axis_alignment_ == CROSS_AXIS_ALIGNMENT_CENTER) { 170 if (cross_axis_alignment_ == CROSS_AXIS_ALIGNMENT_CENTER) {
124 position += free_space / 2; 171 position += free_space / 2;
125 } else if (cross_axis_alignment_ == CROSS_AXIS_ALIGNMENT_END) { 172 } else if (cross_axis_alignment_ == CROSS_AXIS_ALIGNMENT_END) {
126 position += free_space; 173 position += free_space;
127 } 174 }
128 SetCrossAxisPosition(position, &bounds); 175 SetCrossAxisPosition(position, &bounds);
129 SetCrossAxisSize(CrossAxisSizeForView(child), &bounds); 176 SetCrossAxisSize(CrossAxisSizeForView(child), &bounds);
130 } 177 }
131 178
132 // Calculate flex padding. 179 // Calculate flex padding.
133 int current_padding = 0; 180 int current_padding = 0;
134 if (GetFlexForView(child) > 0) { 181 if (GetFlexForView(child.view()) > 0) {
135 current_flex += GetFlexForView(child); 182 current_flex += GetFlexForView(child.view());
136 int quot = (main_free_space * current_flex) / flex_sum; 183 int quot = (main_free_space * current_flex) / flex_sum;
137 int rem = (main_free_space * current_flex) % flex_sum; 184 int rem = (main_free_space * current_flex) % flex_sum;
138 current_padding = quot - total_padding; 185 current_padding = quot - total_padding;
139 // Use the current remainder to round to the nearest pixel. 186 // Use the current remainder to round to the nearest pixel.
140 if (std::abs(rem) * 2 >= flex_sum) 187 if (std::abs(rem) * 2 >= flex_sum)
141 current_padding += main_free_space > 0 ? 1 : -1; 188 current_padding += main_free_space > 0 ? 1 : -1;
142 total_padding += current_padding; 189 total_padding += current_padding;
143 } 190 }
144 191
145 // Set main axis size. 192 // Set main axis size.
146 // TODO(bruthig): Use the allocated width to determine the cross axis size. 193 // TODO(bruthig): Use the allocated width to determine the cross axis size.
147 // See https://crbug.com/682266. 194 // See https://crbug.com/682266.
148 int child_main_axis_size = MainAxisSizeForView(child, child_area.width()); 195 int child_main_axis_size = MainAxisSizeForView(child, child_area.width());
149 SetMainAxisSize(child_main_axis_size + current_padding, &bounds); 196 SetMainAxisSize(child_main_axis_size + current_padding, &bounds);
150 if (MainAxisSize(bounds) > 0 || GetFlexForView(child) > 0) 197 if (MainAxisSize(bounds) > 0 || GetFlexForView(child.view()) > 0)
151 main_position += MainAxisSize(bounds) + between_child_spacing_; 198 main_position +=
199 MainAxisSize(bounds) + MainAxisMarginBetweenViews(child, next);
152 200
153 // Clamp child view bounds to |child_area|. 201 // Clamp child view bounds to |child_area|.
154 bounds.Intersect(child_area); 202 bounds.Intersect(child_area);
155 child->SetBoundsRect(bounds); 203 child.SetBoundsRect(bounds);
156 } 204 }
157 205
158 // Flex views should have grown/shrunk to consume all free space. 206 // Flex views should have grown/shrunk to consume all free space.
159 if (flex_sum) 207 if (flex_sum)
160 DCHECK_EQ(total_padding, main_free_space); 208 DCHECK_EQ(total_padding, main_free_space);
161 } 209 }
162 210
163 gfx::Size BoxLayout::GetPreferredSize(const View* host) const { 211 gfx::Size BoxLayout::GetPreferredSize(const View* host) const {
164 DCHECK_EQ(host_, host); 212 DCHECK_EQ(host_, host);
165 // Calculate the child views' preferred width. 213 // Calculate the child views' preferred width.
166 int width = 0; 214 int width = 0;
167 if (orientation_ == kVertical) { 215 if (orientation_ == kVertical) {
168 for (int i = 0; i < host->child_count(); ++i) { 216 for (int i = 0; i < host_->child_count(); ++i) {
169 const View* child = host->child_at(i); 217 const ViewWrapper child(this, host_->child_at(i));
170 if (!child->visible()) 218 if (!child.visible())
171 continue; 219 continue;
172 220
173 width = std::max(width, child->GetPreferredSize().width()); 221 width = std::max(width, child.GetPreferredSize().width());
174 } 222 }
175 width = std::max(width, minimum_cross_axis_size_); 223 width = std::max(width, minimum_cross_axis_size_);
176 } 224 }
177 225
178 return GetPreferredSizeForChildWidth(host, width); 226 return GetPreferredSizeForChildWidth(host, width);
179 } 227 }
180 228
181 int BoxLayout::GetPreferredHeightForWidth(const View* host, int width) const { 229 int BoxLayout::GetPreferredHeightForWidth(const View* host, int width) const {
182 DCHECK_EQ(host_, host); 230 DCHECK_EQ(host_, host);
183 int child_width = width - NonChildSize(host).width(); 231 int child_width = width - NonChildSize(host).width();
184 return GetPreferredSizeForChildWidth(host, child_width).height(); 232 return GetPreferredSizeForChildWidth(host, child_width).height();
185 } 233 }
186 234
187 void BoxLayout::Installed(View* host) { 235 void BoxLayout::Installed(View* host) {
188 DCHECK(!host_); 236 DCHECK(!host_);
189 host_ = host; 237 host_ = host;
190 } 238 }
191 239
192 void BoxLayout::ViewRemoved(View* host, View* view) { 240 void BoxLayout::ViewRemoved(View* host, View* view) {
193 ClearFlexForView(view); 241 ClearFlexForView(view);
194 } 242 }
195 243
196 int BoxLayout::GetFlexForView(const View* view) const { 244 int BoxLayout::GetFlexForView(const View* view) const {
197 std::map<const View*, int>::const_iterator it = flex_map_.find(view); 245 FlexMap::const_iterator it = flex_map_.find(view);
198 if (it == flex_map_.end()) 246 if (it == flex_map_.end())
199 return default_flex_; 247 return default_flex_;
200 248
201 return it->second; 249 return it->second;
202 } 250 }
203 251
204 int BoxLayout::MainAxisSize(const gfx::Rect& rect) const { 252 int BoxLayout::MainAxisSize(const gfx::Rect& rect) const {
205 return orientation_ == kHorizontal ? rect.width() : rect.height(); 253 return orientation_ == kHorizontal ? rect.width() : rect.height();
206 } 254 }
207 255
(...skipping 30 matching lines...) Expand all
238 rect->set_height(size); 286 rect->set_height(size);
239 } 287 }
240 288
241 void BoxLayout::SetCrossAxisPosition(int position, gfx::Rect* rect) const { 289 void BoxLayout::SetCrossAxisPosition(int position, gfx::Rect* rect) const {
242 if (orientation_ == kVertical) 290 if (orientation_ == kVertical)
243 rect->set_x(position); 291 rect->set_x(position);
244 else 292 else
245 rect->set_y(position); 293 rect->set_y(position);
246 } 294 }
247 295
248 int BoxLayout::MainAxisSizeForView(const View* view, 296 int BoxLayout::MainAxisSizeForView(const ViewWrapper& view,
249 int child_area_width) const { 297 int child_area_width) const {
250 return orientation_ == kHorizontal 298 return orientation_ == kHorizontal
251 ? view->GetPreferredSize().width() 299 ? view.GetPreferredSize().width()
252 : view->GetHeightForWidth(cross_axis_alignment_ == 300 : view.GetHeightForWidth(cross_axis_alignment_ ==
253 CROSS_AXIS_ALIGNMENT_STRETCH 301 CROSS_AXIS_ALIGNMENT_STRETCH
254 ? child_area_width 302 ? child_area_width
255 : view->GetPreferredSize().width()); 303 : view.GetPreferredSize().width());
256 } 304 }
257 305
258 int BoxLayout::CrossAxisSizeForView(const View* view) const { 306 int BoxLayout::MainAxisMarginBetweenViews(const ViewWrapper& left,
307 const ViewWrapper& right) const {
308 return orientation_ == Orientation::kHorizontal
309 ? (collapse_margins_spacing_ && left.view() && right.view()
310 ? std::max(between_child_spacing_,
sky 2017/05/15 20:29:09 optional: this code is nigh unreadable because of
kylix_rd 2017/05/16 18:45:47 What? You don't appreciate my "mad ternary operato
311 std::max(left.margins().right(),
312 right.margins().left()))
313 : between_child_spacing_)
314 : (collapse_margins_spacing_ && left.view() && right.view()
315 ? std::max(between_child_spacing_,
316 std::max(left.margins().bottom(),
317 right.margins().top()))
318 : between_child_spacing_);
319 }
320
321 gfx::Insets BoxLayout::MainAxisOuterMargin() const {
322 const ViewWrapper first(this, FirstVisibleView());
323 const ViewWrapper last(this, LastVisibleView());
324 if (orientation_ == Orientation::kHorizontal) {
325 return gfx::Insets(
326 0, std::max(inside_border_insets_.left(), first.margins().left()), 0,
327 std::max(inside_border_insets_.right(), last.margins().right()));
328 } else {
329 return gfx::Insets(
330 std::max(inside_border_insets_.top(), first.margins().top()), 0,
331 std::max(inside_border_insets_.bottom(), last.margins().bottom()), 0);
332 }
333 }
334
335 gfx::Insets BoxLayout::CrossAxisOuterMargin() const {
336 int top_or_left;
337 int bottom_or_right;
338 bool is_vertical = orientation_ == Orientation::kVertical;
339 top_or_left =
340 is_vertical ? inside_border_insets_.left() : inside_border_insets_.top();
341 bottom_or_right = is_vertical ? inside_border_insets_.right()
342 : inside_border_insets_.bottom();
343 for (int i = 0; i < host_->child_count(); ++i) {
344 const ViewWrapper child(this, host_->child_at(i));
345 if (!child.visible())
346 continue;
347 top_or_left = std::max(top_or_left, is_vertical ? child.margins().left()
348 : child.margins().top());
349 bottom_or_right =
350 std::max(bottom_or_right, is_vertical ? child.margins().right()
351 : child.margins().bottom());
352 }
353 if (is_vertical)
354 return gfx::Insets(0, top_or_left, 0, bottom_or_right);
355 else
356 return gfx::Insets(top_or_left, 0, bottom_or_right, 0);
357 }
358
359 void BoxLayout::AdjustMainAxisForMargin(gfx::Rect* rect) const {
360 rect->Inset(MainAxisOuterMargin());
361 }
362
363 void BoxLayout::AdjustCrossAxisForMargin(gfx::Rect* rect) const {
364 rect->Inset(CrossAxisOuterMargin());
365 }
366
367 int BoxLayout::CrossAxisSizeForView(const ViewWrapper& view) const {
259 // TODO(bruthig): For horizontal case use the available width and not the 368 // TODO(bruthig): For horizontal case use the available width and not the
260 // preferred width. See https://crbug.com/682266. 369 // preferred width. See https://crbug.com/682266.
261 return orientation_ == kVertical 370 return orientation_ == kVertical
262 ? view->GetPreferredSize().width() 371 ? view.GetPreferredSize().width()
263 : view->GetHeightForWidth(view->GetPreferredSize().width()); 372 : view.GetHeightForWidth(view.GetPreferredSize().width());
264 } 373 }
265 374
266 gfx::Size BoxLayout::GetPreferredSizeForChildWidth(const View* host, 375 gfx::Size BoxLayout::GetPreferredSizeForChildWidth(const View* host,
267 int child_area_width) const { 376 int child_area_width) const {
377 DCHECK_EQ(host, host_);
268 gfx::Rect child_area_bounds; 378 gfx::Rect child_area_bounds;
269 379
270 if (orientation_ == kHorizontal) { 380 if (orientation_ == kHorizontal) {
271 // Horizontal layouts ignore |child_area_width|, meaning they mimic the 381 // Horizontal layouts ignore |child_area_width|, meaning they mimic the
272 // default behavior of GridLayout::GetPreferredHeightForWidth(). 382 // default behavior of GridLayout::GetPreferredHeightForWidth().
273 // TODO(estade|bruthig): Fix this See // https://crbug.com/682266. 383 // TODO(estade|bruthig): Fix this See // https://crbug.com/682266.
274 int position = 0; 384 int position = 0;
275 for (int i = 0; i < host->child_count(); ++i) { 385 for (int i = 0; i < host_->child_count(); ++i) {
276 const View* child = host->child_at(i); 386 const ViewWrapper child(this, host_->child_at(i));
277 if (!child->visible()) 387 const ViewWrapper next(this, NextVisibleView(i));
388 if (!child.visible())
278 continue; 389 continue;
279 390
280 gfx::Size size(child->GetPreferredSize()); 391 gfx::Size size(child.GetPreferredSize());
281 if (size.IsEmpty()) 392 if (size.IsEmpty())
282 continue; 393 continue;
283 394
284 gfx::Rect child_bounds(position, 0, size.width(), size.height()); 395 gfx::Rect child_bounds(position, 0, size.width(), size.height());
285 child_area_bounds.Union(child_bounds); 396 child_area_bounds.Union(child_bounds);
286 position += size.width() + between_child_spacing_; 397 position += size.width() + MainAxisMarginBetweenViews(child, next);
287 } 398 }
288 child_area_bounds.set_height( 399 child_area_bounds.set_height(
289 std::max(child_area_bounds.height(), minimum_cross_axis_size_)); 400 std::max(child_area_bounds.height(), minimum_cross_axis_size_));
290 } else { 401 } else {
291 int height = 0; 402 int height = 0;
292 for (int i = 0; i < host->child_count(); ++i) { 403 for (int i = 0; i < host_->child_count(); ++i) {
293 const View* child = host->child_at(i); 404 const ViewWrapper child(this, host_->child_at(i));
294 if (!child->visible()) 405 const ViewWrapper next(this, NextVisibleView(i));
406 if (!child.visible())
295 continue; 407 continue;
296 408
297 // Use the child area width for getting the height if the child is 409 // Use the child area width for getting the height if the child is
298 // supposed to stretch. Use its preferred size otherwise. 410 // supposed to stretch. Use its preferred size otherwise.
299 int extra_height = MainAxisSizeForView(child, child_area_width); 411 int extra_height = MainAxisSizeForView(child, child_area_width);
300 // Only add |between_child_spacing_| if this is not the only child. 412 // Only add |between_child_spacing_| if this is not the only child.
301 if (height != 0 && extra_height > 0) 413 if (next.view() && extra_height > 0)
302 height += between_child_spacing_; 414 height += MainAxisMarginBetweenViews(child, next);
303 height += extra_height; 415 height += extra_height;
304 } 416 }
305 417
306 child_area_bounds.set_width(child_area_width); 418 child_area_bounds.set_width(child_area_width);
307 child_area_bounds.set_height(height); 419 child_area_bounds.set_height(height);
308 } 420 }
309 421
310 gfx::Size non_child_size = NonChildSize(host); 422 gfx::Size non_child_size = NonChildSize(host_);
311 return gfx::Size(child_area_bounds.width() + non_child_size.width(), 423 return gfx::Size(child_area_bounds.width() + non_child_size.width(),
312 child_area_bounds.height() + non_child_size.height()); 424 child_area_bounds.height() + non_child_size.height());
313 } 425 }
314 426
315 gfx::Size BoxLayout::NonChildSize(const View* host) const { 427 gfx::Size BoxLayout::NonChildSize(const View* host) const {
316 gfx::Insets insets(host->GetInsets()); 428 gfx::Insets insets(host->GetInsets());
317 return gfx::Size(insets.width() + inside_border_insets_.width(), 429 if (!collapse_margins_spacing_) {
318 insets.height() + inside_border_insets_.height()); 430 return gfx::Size(insets.width() + inside_border_insets_.width(),
431 insets.height() + inside_border_insets_.height());
432 } else {
433 gfx::Insets main_axis = MainAxisOuterMargin();
434 gfx::Insets cross_axis = CrossAxisOuterMargin();
435 return gfx::Size(
436 insets.width() + main_axis.width() + cross_axis.width(),
437 insets.height() + main_axis.height() + cross_axis.height());
438 }
439 }
440
441 View* BoxLayout::NextVisibleView(int index) const {
442 for (int i = index + 1; i < host_->child_count(); ++i) {
443 View* result = host_->child_at(i);
444 if (result->visible())
445 return result;
446 }
447 return nullptr;
448 }
449
450 View* BoxLayout::FirstVisibleView() const {
451 return NextVisibleView(-1);
452 }
453
454 View* BoxLayout::LastVisibleView() const {
455 for (int i = host_->child_count() - 1; i >= 0; --i) {
456 View* result = host_->child_at(i);
457 if (result->visible())
458 return result;
459 }
460 return nullptr;
319 } 461 }
320 462
321 } // namespace views 463 } // namespace views
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698