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