| 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;
|
| +}
|
| +
|
| +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;
|
| + // 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;
|
| + // 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)
|
| + 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();
|
| }
|
|
|