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

Side by Side 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, 5 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 | Annotate | Revision Log
« 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 »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 "ui/gfx/rect.h" 7 #include "ui/gfx/rect.h"
8 #include "ui/views/view.h" 8 #include "ui/views/view.h"
9 9
10 namespace views { 10 namespace views {
11 11
12 BoxLayout::BoxLayout(BoxLayout::Orientation orientation, 12 BoxLayout::BoxLayout(BoxLayout::Orientation orientation,
13 int inside_border_horizontal_spacing, 13 int inside_border_horizontal_spacing,
14 int inside_border_vertical_spacing, 14 int inside_border_vertical_spacing,
15 int between_child_spacing) 15 int between_child_spacing)
16 : orientation_(orientation), 16 : orientation_(orientation),
17 inside_border_insets_(inside_border_vertical_spacing, 17 inside_border_insets_(inside_border_vertical_spacing,
18 inside_border_horizontal_spacing, 18 inside_border_horizontal_spacing,
19 inside_border_vertical_spacing, 19 inside_border_vertical_spacing,
20 inside_border_horizontal_spacing), 20 inside_border_horizontal_spacing),
21 between_child_spacing_(between_child_spacing), 21 between_child_spacing_(between_child_spacing),
22 main_axis_alignment_(MAIN_AXIS_ALIGNMENT_START), 22 main_axis_alignment_(MAIN_AXIS_ALIGNMENT_START),
23 cross_axis_alignment_(CROSS_AXIS_ALIGNMENT_STRETCH) { 23 cross_axis_alignment_(CROSS_AXIS_ALIGNMENT_STRETCH),
24 default_flex_(0) {
24 } 25 }
25 26
26 BoxLayout::~BoxLayout() { 27 BoxLayout::~BoxLayout() {
27 } 28 }
28 29
30 void BoxLayout::SetFlexForViewAt(int index, int flex_weight) {
31 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.
32 }
33
34 void BoxLayout::ClearFlexForViewAt(int index) {
35 flex_map_.erase(index);
36 }
37
29 void BoxLayout::Layout(View* host) { 38 void BoxLayout::Layout(View* host) {
30 gfx::Rect child_area(host->GetLocalBounds()); 39 gfx::Rect child_area(host->GetLocalBounds());
31 child_area.Inset(host->GetInsets()); 40 child_area.Inset(host->GetInsets());
32 child_area.Inset(inside_border_insets_); 41 child_area.Inset(inside_border_insets_);
33 42
34 int padding = 0; 43 int padding_unit = 0;
35 if (main_axis_alignment_ != MAIN_AXIS_ALIGNMENT_START) { 44 int padding_remainder = 0;
36 int total_main_axis_size = 0; 45 int padding_sign = 0;
37 int num_visible = 0; 46 int total_main_axis_size = 0;
38 for (int i = 0; i < host->child_count(); ++i) { 47 int num_visible = 0;
39 View* child = host->child_at(i); 48 int flex_sum = 0;
40 if (!child->visible()) 49 for (int i = 0; i < host->child_count(); ++i) {
41 continue; 50 View* child = host->child_at(i);
42 total_main_axis_size += MainAxisSizeForView(child, child_area.width()) + 51 if (!child->visible())
43 between_child_spacing_; 52 continue;
44 ++num_visible; 53 total_main_axis_size +=
45 } 54 MainAxisSizeForView(child, child_area.width()) + between_child_spacing_;
55 ++num_visible;
56 flex_sum += GetFlexForViewAt(i);
57 }
46 58
47 if (num_visible) { 59 if (num_visible) {
48 total_main_axis_size -= between_child_spacing_; 60 total_main_axis_size -= between_child_spacing_;
49 int free_space = MainAxisSize(child_area) - total_main_axis_size; 61 // Free space can be negative indicating that the views want to overflow.
50 int position = MainAxisPosition(child_area); 62 int free_space = MainAxisSize(child_area) - total_main_axis_size;
51 int size = MainAxisSize(child_area); 63 int position = MainAxisPosition(child_area);
64 int size = MainAxisSize(child_area);
65 if (flex_sum) {
66 padding_sign = free_space > 0 ? 1 : -1;
67 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.
68 // If free space is negative, this will be negative.
69 padding_remainder = free_space % flex_sum;
70 } else {
52 switch (main_axis_alignment_) { 71 switch (main_axis_alignment_) {
53 case MAIN_AXIS_ALIGNMENT_FILL: 72 case MAIN_AXIS_ALIGNMENT_START:
54 padding = std::max(free_space / num_visible, 0);
55 break; 73 break;
56 case MAIN_AXIS_ALIGNMENT_CENTER: 74 case MAIN_AXIS_ALIGNMENT_CENTER:
57 position += free_space / 2; 75 position += free_space / 2;
58 size = total_main_axis_size; 76 size = total_main_axis_size;
59 break; 77 break;
60 case MAIN_AXIS_ALIGNMENT_END: 78 case MAIN_AXIS_ALIGNMENT_END:
61 position += free_space; 79 position += free_space;
62 size = total_main_axis_size; 80 size = total_main_axis_size;
63 break; 81 break;
64 default: 82 default:
65 NOTREACHED(); 83 NOTREACHED();
66 break; 84 break;
67 } 85 }
68 gfx::Rect new_child_area(child_area);
69 SetMainAxisPosition(position, &new_child_area);
70 SetMainAxisSize(size, &new_child_area);
71 child_area.Intersect(new_child_area);
72 } 86 }
87 gfx::Rect new_child_area(child_area);
88 SetMainAxisPosition(position, &new_child_area);
89 SetMainAxisSize(size, &new_child_area);
90 child_area.Intersect(new_child_area);
73 } 91 }
74 92
75 int main_position = MainAxisPosition(child_area); 93 int main_position = MainAxisPosition(child_area);
94 int current_remainder = 0;
76 for (int i = 0; i < host->child_count(); ++i) { 95 for (int i = 0; i < host->child_count(); ++i) {
77 View* child = host->child_at(i); 96 View* child = host->child_at(i);
78 if (child->visible()) { 97 if (child->visible()) {
79 gfx::Rect bounds(child_area); 98 gfx::Rect bounds(child_area);
80 SetMainAxisPosition(main_position, &bounds); 99 SetMainAxisPosition(main_position, &bounds);
81 if (cross_axis_alignment_ != CROSS_AXIS_ALIGNMENT_STRETCH) { 100 if (cross_axis_alignment_ != CROSS_AXIS_ALIGNMENT_STRETCH) {
82 int free_space = CrossAxisSize(bounds) - CrossAxisSizeForView(child); 101 int free_space = CrossAxisSize(bounds) - CrossAxisSizeForView(child);
83 int position = CrossAxisPosition(bounds); 102 int position = CrossAxisPosition(bounds);
84 if (cross_axis_alignment_ == CROSS_AXIS_ALIGNMENT_CENTER) { 103 if (cross_axis_alignment_ == CROSS_AXIS_ALIGNMENT_CENTER) {
85 position += free_space / 2; 104 position += free_space / 2;
86 } else if (cross_axis_alignment_ == CROSS_AXIS_ALIGNMENT_END) { 105 } else if (cross_axis_alignment_ == CROSS_AXIS_ALIGNMENT_END) {
87 position += free_space; 106 position += free_space;
88 } 107 }
89 SetCrossAxisPosition(position, &bounds); 108 SetCrossAxisPosition(position, &bounds);
90 SetCrossAxisSize(CrossAxisSizeForView(child), &bounds); 109 SetCrossAxisSize(CrossAxisSizeForView(child), &bounds);
91 } 110 }
92 int child_main_axis_size = MainAxisSizeForView(child, child_area.width()); 111 int child_main_axis_size = MainAxisSizeForView(child, child_area.width());
93 SetMainAxisSize(child_main_axis_size + padding, &bounds); 112 // The padding for the current view.
94 if (MainAxisSize(bounds) > 0) 113 int current_padding = 0;
114 if (GetFlexForViewAt(i) > 0) {
115 current_padding = padding_unit * GetFlexForViewAt(i);
116 // Add any extra space due to multiple padding units being consumed.
117 int remainder_change = padding_remainder * GetFlexForViewAt(i);
118 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
119 // Use the current remainder to round to the nearest pixel.
120 current_remainder = (current_remainder + remainder_change) % flex_sum;
121 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
122 current_padding += padding_sign;
123 }
124
125 SetMainAxisSize(child_main_axis_size + current_padding, &bounds);
126 if (MainAxisSize(bounds) > 0 || GetFlexForViewAt(i) > 0)
95 main_position += MainAxisSize(bounds) + between_child_spacing_; 127 main_position += MainAxisSize(bounds) + between_child_spacing_;
96 128
97 // Clamp child view bounds to |child_area|. 129 // Clamp child view bounds to |child_area|.
98 bounds.Intersect(child_area); 130 bounds.Intersect(child_area);
99 child->SetBoundsRect(bounds); 131 child->SetBoundsRect(bounds);
100 } 132 }
101 } 133 }
102 } 134 }
103 135
104 gfx::Size BoxLayout::GetPreferredSize(const View* host) const { 136 gfx::Size BoxLayout::GetPreferredSize(const View* host) const {
(...skipping 10 matching lines...) Expand all
115 } 147 }
116 148
117 return GetPreferredSizeForChildWidth(host, width); 149 return GetPreferredSizeForChildWidth(host, width);
118 } 150 }
119 151
120 int BoxLayout::GetPreferredHeightForWidth(const View* host, int width) const { 152 int BoxLayout::GetPreferredHeightForWidth(const View* host, int width) const {
121 int child_width = width - NonChildSize(host).width(); 153 int child_width = width - NonChildSize(host).width();
122 return GetPreferredSizeForChildWidth(host, child_width).height(); 154 return GetPreferredSizeForChildWidth(host, child_width).height();
123 } 155 }
124 156
157 int BoxLayout::GetFlexForViewAt(int index) {
158 std::map<int, int>::const_iterator it = flex_map_.find(index);
159 if (it == flex_map_.end())
160 return default_flex_;
161
162 return it->second;
163 }
164
125 int BoxLayout::MainAxisSize(const gfx::Rect& rect) const { 165 int BoxLayout::MainAxisSize(const gfx::Rect& rect) const {
126 return orientation_ == kHorizontal ? rect.width() : rect.height(); 166 return orientation_ == kHorizontal ? rect.width() : rect.height();
127 } 167 }
128 168
129 int BoxLayout::MainAxisPosition(const gfx::Rect& rect) const { 169 int BoxLayout::MainAxisPosition(const gfx::Rect& rect) const {
130 return orientation_ == kHorizontal ? rect.x() : rect.y(); 170 return orientation_ == kHorizontal ? rect.x() : rect.y();
131 } 171 }
132 172
133 void BoxLayout::SetMainAxisSize(int size, gfx::Rect* rect) const { 173 void BoxLayout::SetMainAxisSize(int size, gfx::Rect* rect) const {
134 if (orientation_ == kHorizontal) 174 if (orientation_ == kHorizontal)
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
229 child_area_bounds.height() + non_child_size.height()); 269 child_area_bounds.height() + non_child_size.height());
230 } 270 }
231 271
232 gfx::Size BoxLayout::NonChildSize(const View* host) const { 272 gfx::Size BoxLayout::NonChildSize(const View* host) const {
233 gfx::Insets insets(host->GetInsets()); 273 gfx::Insets insets(host->GetInsets());
234 return gfx::Size(insets.width() + inside_border_insets_.width(), 274 return gfx::Size(insets.width() + inside_border_insets_.width(),
235 insets.height() + inside_border_insets_.height()); 275 insets.height() + inside_border_insets_.height());
236 } 276 }
237 277
238 } // namespace views 278 } // namespace views
OLDNEW
« 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