Chromium Code Reviews| Index: ui/views/layout/box_layout.cc |
| diff --git a/ui/views/layout/box_layout.cc b/ui/views/layout/box_layout.cc |
| index 91504ad3c3879050b0f0d400260ef2f5bf85f955..8a9cfa263ddde9338a31dd0b42f2da08c2465ca6 100644 |
| --- a/ui/views/layout/box_layout.cc |
| +++ b/ui/views/layout/box_layout.cc |
| @@ -20,38 +20,56 @@ BoxLayout::BoxLayout(BoxLayout::Orientation orientation, |
| inside_border_horizontal_spacing), |
| between_child_spacing_(between_child_spacing), |
| main_axis_alignment_(MAIN_AXIS_ALIGNMENT_START), |
| - cross_axis_alignment_(CROSS_AXIS_ALIGNMENT_STRETCH) { |
| + cross_axis_alignment_(CROSS_AXIS_ALIGNMENT_STRETCH), |
| + default_flex_(0) { |
| } |
| BoxLayout::~BoxLayout() { |
| } |
| +void BoxLayout::SetFlexForViewAt(int index, int flex_weight) { |
| + flex_map_[index] = flex_weight; |
|
benwells
2014/07/02 08:02:26
Nit: check flex_weight >= 0
calamity
2014/07/03 01:54:27
Done.
|
| +} |
| + |
| +void BoxLayout::ClearFlexForViewAt(int index) { |
| + flex_map_.erase(index); |
| +} |
| + |
| void BoxLayout::Layout(View* host) { |
| gfx::Rect child_area(host->GetLocalBounds()); |
| child_area.Inset(host->GetInsets()); |
| child_area.Inset(inside_border_insets_); |
| - int padding = 0; |
| - if (main_axis_alignment_ != MAIN_AXIS_ALIGNMENT_START) { |
| - int total_main_axis_size = 0; |
| - int num_visible = 0; |
| - for (int i = 0; i < host->child_count(); ++i) { |
| - View* child = host->child_at(i); |
| - if (!child->visible()) |
| - continue; |
| - total_main_axis_size += MainAxisSizeForView(child, child_area.width()) + |
| - between_child_spacing_; |
| - ++num_visible; |
| - } |
| + int padding_unit = 0; |
| + int padding_remainder = 0; |
| + int padding_sign = 0; |
| + int total_main_axis_size = 0; |
| + int num_visible = 0; |
| + int flex_sum = 0; |
| + for (int i = 0; i < host->child_count(); ++i) { |
| + View* child = host->child_at(i); |
| + if (!child->visible()) |
| + continue; |
| + total_main_axis_size += |
| + MainAxisSizeForView(child, child_area.width()) + between_child_spacing_; |
| + ++num_visible; |
| + flex_sum += GetFlexForViewAt(i); |
| + } |
| - if (num_visible) { |
| - total_main_axis_size -= between_child_spacing_; |
| - int free_space = MainAxisSize(child_area) - total_main_axis_size; |
| - int position = MainAxisPosition(child_area); |
| - int size = MainAxisSize(child_area); |
| + if (num_visible) { |
| + total_main_axis_size -= between_child_spacing_; |
| + // Free space can be negative indicating that the views want to overflow. |
| + int free_space = MainAxisSize(child_area) - total_main_axis_size; |
| + int position = MainAxisPosition(child_area); |
| + int size = MainAxisSize(child_area); |
| + if (flex_sum) { |
| + padding_sign = free_space > 0 ? 1 : -1; |
| + padding_unit = free_space / flex_sum; |
|
benwells
2014/07/02 08:02:26
As discussed maybe there is a simpler way to do th
calamity
2014/07/03 01:54:27
Done.
|
| + // If free space is negative, this will be negative. |
| + padding_remainder = free_space % flex_sum; |
| + } else { |
| switch (main_axis_alignment_) { |
| - case MAIN_AXIS_ALIGNMENT_FILL: |
| - padding = std::max(free_space / num_visible, 0); |
| + case MAIN_AXIS_ALIGNMENT_START: |
| break; |
| case MAIN_AXIS_ALIGNMENT_CENTER: |
| position += free_space / 2; |
| @@ -65,14 +83,15 @@ void BoxLayout::Layout(View* host) { |
| NOTREACHED(); |
| break; |
| } |
| - gfx::Rect new_child_area(child_area); |
| - SetMainAxisPosition(position, &new_child_area); |
| - SetMainAxisSize(size, &new_child_area); |
| - child_area.Intersect(new_child_area); |
| } |
| + gfx::Rect new_child_area(child_area); |
| + SetMainAxisPosition(position, &new_child_area); |
| + SetMainAxisSize(size, &new_child_area); |
| + child_area.Intersect(new_child_area); |
| } |
| int main_position = MainAxisPosition(child_area); |
| + int current_remainder = 0; |
| for (int i = 0; i < host->child_count(); ++i) { |
| View* child = host->child_at(i); |
| if (child->visible()) { |
| @@ -90,8 +109,21 @@ void BoxLayout::Layout(View* host) { |
| SetCrossAxisSize(CrossAxisSizeForView(child), &bounds); |
| } |
| int child_main_axis_size = MainAxisSizeForView(child, child_area.width()); |
| - SetMainAxisSize(child_main_axis_size + padding, &bounds); |
| - if (MainAxisSize(bounds) > 0) |
| + // The padding for the current view. |
| + int current_padding = 0; |
| + if (GetFlexForViewAt(i) > 0) { |
| + current_padding = padding_unit * GetFlexForViewAt(i); |
| + // Add any extra space due to multiple padding units being consumed. |
| + int remainder_change = padding_remainder * GetFlexForViewAt(i); |
| + current_padding += remainder_change / flex_sum; |
|
benwells
2014/07/02 08:02:26
shouldn't this be += (current_remainder + remainde
calamity
2014/07/03 01:54:27
I don't believe so. The current remainder is facto
|
| + // Use the current remainder to round to the nearest pixel. |
| + current_remainder = (current_remainder + remainder_change) % flex_sum; |
| + if (std::abs(current_remainder) > flex_sum / 2) |
|
benwells
2014/07/02 08:02:26
reminder: you said this should be >= when we were
calamity
2014/07/03 01:54:27
Done. Also had to move the / 2 to the other side t
|
| + current_padding += padding_sign; |
| + } |
| + |
| + SetMainAxisSize(child_main_axis_size + current_padding, &bounds); |
| + if (MainAxisSize(bounds) > 0 || GetFlexForViewAt(i) > 0) |
| main_position += MainAxisSize(bounds) + between_child_spacing_; |
| // Clamp child view bounds to |child_area|. |
| @@ -122,6 +154,14 @@ int BoxLayout::GetPreferredHeightForWidth(const View* host, int width) const { |
| return GetPreferredSizeForChildWidth(host, child_width).height(); |
| } |
| +int BoxLayout::GetFlexForViewAt(int index) { |
| + std::map<int, int>::const_iterator it = flex_map_.find(index); |
| + if (it == flex_map_.end()) |
| + return default_flex_; |
| + |
| + return it->second; |
| +} |
| + |
| int BoxLayout::MainAxisSize(const gfx::Rect& rect) const { |
| return orientation_ == kHorizontal ? rect.width() : rect.height(); |
| } |