[SyncFS] Build indexes from FileTracker entries on disk.
[chromium-blink-merge.git] / ui / views / layout / box_layout.cc
blob91504ad3c3879050b0f0d400260ef2f5bf85f955
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
3 // found in the LICENSE file.
5 #include "ui/views/layout/box_layout.h"
7 #include "ui/gfx/rect.h"
8 #include "ui/views/view.h"
10 namespace views {
12 BoxLayout::BoxLayout(BoxLayout::Orientation orientation,
13 int inside_border_horizontal_spacing,
14 int inside_border_vertical_spacing,
15 int between_child_spacing)
16 : orientation_(orientation),
17 inside_border_insets_(inside_border_vertical_spacing,
18 inside_border_horizontal_spacing,
19 inside_border_vertical_spacing,
20 inside_border_horizontal_spacing),
21 between_child_spacing_(between_child_spacing),
22 main_axis_alignment_(MAIN_AXIS_ALIGNMENT_START),
23 cross_axis_alignment_(CROSS_AXIS_ALIGNMENT_STRETCH) {
26 BoxLayout::~BoxLayout() {
29 void BoxLayout::Layout(View* host) {
30 gfx::Rect child_area(host->GetLocalBounds());
31 child_area.Inset(host->GetInsets());
32 child_area.Inset(inside_border_insets_);
34 int padding = 0;
35 if (main_axis_alignment_ != MAIN_AXIS_ALIGNMENT_START) {
36 int total_main_axis_size = 0;
37 int num_visible = 0;
38 for (int i = 0; i < host->child_count(); ++i) {
39 View* child = host->child_at(i);
40 if (!child->visible())
41 continue;
42 total_main_axis_size += MainAxisSizeForView(child, child_area.width()) +
43 between_child_spacing_;
44 ++num_visible;
47 if (num_visible) {
48 total_main_axis_size -= between_child_spacing_;
49 int free_space = MainAxisSize(child_area) - total_main_axis_size;
50 int position = MainAxisPosition(child_area);
51 int size = MainAxisSize(child_area);
52 switch (main_axis_alignment_) {
53 case MAIN_AXIS_ALIGNMENT_FILL:
54 padding = std::max(free_space / num_visible, 0);
55 break;
56 case MAIN_AXIS_ALIGNMENT_CENTER:
57 position += free_space / 2;
58 size = total_main_axis_size;
59 break;
60 case MAIN_AXIS_ALIGNMENT_END:
61 position += free_space;
62 size = total_main_axis_size;
63 break;
64 default:
65 NOTREACHED();
66 break;
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);
75 int main_position = MainAxisPosition(child_area);
76 for (int i = 0; i < host->child_count(); ++i) {
77 View* child = host->child_at(i);
78 if (child->visible()) {
79 gfx::Rect bounds(child_area);
80 SetMainAxisPosition(main_position, &bounds);
81 if (cross_axis_alignment_ != CROSS_AXIS_ALIGNMENT_STRETCH) {
82 int free_space = CrossAxisSize(bounds) - CrossAxisSizeForView(child);
83 int position = CrossAxisPosition(bounds);
84 if (cross_axis_alignment_ == CROSS_AXIS_ALIGNMENT_CENTER) {
85 position += free_space / 2;
86 } else if (cross_axis_alignment_ == CROSS_AXIS_ALIGNMENT_END) {
87 position += free_space;
89 SetCrossAxisPosition(position, &bounds);
90 SetCrossAxisSize(CrossAxisSizeForView(child), &bounds);
92 int child_main_axis_size = MainAxisSizeForView(child, child_area.width());
93 SetMainAxisSize(child_main_axis_size + padding, &bounds);
94 if (MainAxisSize(bounds) > 0)
95 main_position += MainAxisSize(bounds) + between_child_spacing_;
97 // Clamp child view bounds to |child_area|.
98 bounds.Intersect(child_area);
99 child->SetBoundsRect(bounds);
104 gfx::Size BoxLayout::GetPreferredSize(const View* host) const {
105 // Calculate the child views' preferred width.
106 int width = 0;
107 if (orientation_ == kVertical) {
108 for (int i = 0; i < host->child_count(); ++i) {
109 const View* child = host->child_at(i);
110 if (!child->visible())
111 continue;
113 width = std::max(width, child->GetPreferredSize().width());
117 return GetPreferredSizeForChildWidth(host, width);
120 int BoxLayout::GetPreferredHeightForWidth(const View* host, int width) const {
121 int child_width = width - NonChildSize(host).width();
122 return GetPreferredSizeForChildWidth(host, child_width).height();
125 int BoxLayout::MainAxisSize(const gfx::Rect& rect) const {
126 return orientation_ == kHorizontal ? rect.width() : rect.height();
129 int BoxLayout::MainAxisPosition(const gfx::Rect& rect) const {
130 return orientation_ == kHorizontal ? rect.x() : rect.y();
133 void BoxLayout::SetMainAxisSize(int size, gfx::Rect* rect) const {
134 if (orientation_ == kHorizontal)
135 rect->set_width(size);
136 else
137 rect->set_height(size);
140 void BoxLayout::SetMainAxisPosition(int position, gfx::Rect* rect) const {
141 if (orientation_ == kHorizontal)
142 rect->set_x(position);
143 else
144 rect->set_y(position);
147 int BoxLayout::CrossAxisSize(const gfx::Rect& rect) const {
148 return orientation_ == kVertical ? rect.width() : rect.height();
151 int BoxLayout::CrossAxisPosition(const gfx::Rect& rect) const {
152 return orientation_ == kVertical ? rect.x() : rect.y();
155 void BoxLayout::SetCrossAxisSize(int size, gfx::Rect* rect) const {
156 if (orientation_ == kVertical)
157 rect->set_width(size);
158 else
159 rect->set_height(size);
162 void BoxLayout::SetCrossAxisPosition(int position, gfx::Rect* rect) const {
163 if (orientation_ == kVertical)
164 rect->set_x(position);
165 else
166 rect->set_y(position);
169 int BoxLayout::MainAxisSizeForView(const View* view,
170 int child_area_width) const {
171 return orientation_ == kHorizontal
172 ? view->GetPreferredSize().width()
173 : view->GetHeightForWidth(cross_axis_alignment_ ==
174 CROSS_AXIS_ALIGNMENT_STRETCH
175 ? child_area_width
176 : view->GetPreferredSize().width());
179 int BoxLayout::CrossAxisSizeForView(const View* view) const {
180 return orientation_ == kVertical
181 ? view->GetPreferredSize().width()
182 : view->GetHeightForWidth(view->GetPreferredSize().width());
185 gfx::Size BoxLayout::GetPreferredSizeForChildWidth(const View* host,
186 int child_area_width) const {
187 gfx::Rect child_area_bounds;
189 if (orientation_ == kHorizontal) {
190 // Horizontal layouts ignore |child_area_width|, meaning they mimic the
191 // default behavior of GridLayout::GetPreferredHeightForWidth().
192 // TODO(estade): fix this if it ever becomes a problem.
193 int position = 0;
194 for (int i = 0; i < host->child_count(); ++i) {
195 const View* child = host->child_at(i);
196 if (!child->visible())
197 continue;
199 gfx::Size size(child->GetPreferredSize());
200 if (size.IsEmpty())
201 continue;
203 gfx::Rect child_bounds(position, 0, size.width(), size.height());
204 child_area_bounds.Union(child_bounds);
205 position += size.width() + between_child_spacing_;
207 } else {
208 int height = 0;
209 for (int i = 0; i < host->child_count(); ++i) {
210 const View* child = host->child_at(i);
211 if (!child->visible())
212 continue;
214 // Use the child area width for getting the height if the child is
215 // supposed to stretch. Use its preferred size otherwise.
216 int extra_height = MainAxisSizeForView(child, child_area_width);
217 // Only add |between_child_spacing_| if this is not the only child.
218 if (height != 0 && extra_height > 0)
219 height += between_child_spacing_;
220 height += extra_height;
223 child_area_bounds.set_width(child_area_width);
224 child_area_bounds.set_height(height);
227 gfx::Size non_child_size = NonChildSize(host);
228 return gfx::Size(child_area_bounds.width() + non_child_size.width(),
229 child_area_bounds.height() + non_child_size.height());
232 gfx::Size BoxLayout::NonChildSize(const View* host) const {
233 gfx::Insets insets(host->GetInsets());
234 return gfx::Size(insets.width() + inside_border_insets_.width(),
235 insets.height() + inside_border_insets_.height());
238 } // namespace views