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

Unified Diff: ui/views/layout/box_layout.cc

Issue 360213002: Add Flex to views::BoxLayout. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: address comments Created 6 years, 6 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « ui/views/layout/box_layout.h ('k') | ui/views/layout/box_layout_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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..943386d74f75f5b8a8efa0658891769067768224 100644
--- a/ui/views/layout/box_layout.cc
+++ b/ui/views/layout/box_layout.cc
@@ -20,85 +20,120 @@ 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) {
+ DCHECK(index >= 0);
+ DCHECK(flex_weight >= 0);
+ flex_map_[index] = flex_weight;
+}
+
+void BoxLayout::ClearFlexForViewAt(int index) {
+ DCHECK(index >= 0);
+ flex_map_.erase(index);
+}
+
+void BoxLayout::SetDefaultFlex(int default_flex) {
+ DCHECK(default_flex >= 0);
+ default_flex_ = default_flex;
+}
+
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 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);
+ }
+ total_main_axis_size -= between_child_spacing_;
benwells 2014/07/04 07:27:56 Nit: this line can move after the if (!num_visible
calamity 2014/07/07 05:11:17 Done.
+
+ if (!num_visible)
+ return;
- 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);
+ // Free space can be negative indicating that the views want to overflow.
+ int main_free_space = MainAxisSize(child_area) - total_main_axis_size;
+ {
+ int position = MainAxisPosition(child_area);
+ int size = MainAxisSize(child_area);
+ if (!flex_sum) {
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;
+ position += main_free_space / 2;
size = total_main_axis_size;
break;
case MAIN_AXIS_ALIGNMENT_END:
- position += free_space;
+ position += main_free_space;
size = total_main_axis_size;
break;
default:
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()) {
- gfx::Rect bounds(child_area);
- SetMainAxisPosition(main_position, &bounds);
- if (cross_axis_alignment_ != CROSS_AXIS_ALIGNMENT_STRETCH) {
- int free_space = CrossAxisSize(bounds) - CrossAxisSizeForView(child);
- int position = CrossAxisPosition(bounds);
- if (cross_axis_alignment_ == CROSS_AXIS_ALIGNMENT_CENTER) {
- position += free_space / 2;
- } else if (cross_axis_alignment_ == CROSS_AXIS_ALIGNMENT_END) {
- position += free_space;
- }
- SetCrossAxisPosition(position, &bounds);
- SetCrossAxisSize(CrossAxisSizeForView(child), &bounds);
+ if (!child->visible())
+ continue;
+
+ gfx::Rect bounds(child_area);
+ SetMainAxisPosition(main_position, &bounds);
+ if (cross_axis_alignment_ != CROSS_AXIS_ALIGNMENT_STRETCH) {
+ int free_space = CrossAxisSize(bounds) - CrossAxisSizeForView(child);
+ int position = CrossAxisPosition(bounds);
+ if (cross_axis_alignment_ == CROSS_AXIS_ALIGNMENT_CENTER) {
+ position += free_space / 2;
+ } else if (cross_axis_alignment_ == CROSS_AXIS_ALIGNMENT_END) {
+ position += free_space;
}
- int child_main_axis_size = MainAxisSizeForView(child, child_area.width());
- SetMainAxisSize(child_main_axis_size + padding, &bounds);
- if (MainAxisSize(bounds) > 0)
- main_position += MainAxisSize(bounds) + between_child_spacing_;
-
- // Clamp child view bounds to |child_area|.
- bounds.Intersect(child_area);
- child->SetBoundsRect(bounds);
+ SetCrossAxisPosition(position, &bounds);
+ SetCrossAxisSize(CrossAxisSizeForView(child), &bounds);
+ }
+
+ int current_padding = 0;
+ if (GetFlexForViewAt(i) > 0) {
+ current_padding = main_free_space * GetFlexForViewAt(i) / flex_sum;
+ current_remainder += main_free_space * GetFlexForViewAt(i);
+ current_remainder %= flex_sum;
benwells 2014/07/04 07:27:56 As discussed today I'm worried this will leak pixe
calamity 2014/07/07 05:11:17 Indeed it does. Reworked algorithm.
+ // Use the current remainder to round to the nearest pixel.
+ if (std::abs(current_remainder) * 2 >= flex_sum)
+ current_padding += main_free_space > 0 ? 1 : -1;
}
+
+ int child_main_axis_size = MainAxisSizeForView(child, child_area.width());
+ 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|.
+ bounds.Intersect(child_area);
+ child->SetBoundsRect(bounds);
}
+ DCHECK_EQ(0, current_remainder);
}
gfx::Size BoxLayout::GetPreferredSize(const View* host) const {
@@ -122,6 +157,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();
}
« no previous file with comments | « ui/views/layout/box_layout.h ('k') | ui/views/layout/box_layout_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698