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

Side by Side Diff: chrome/browser/ui/cocoa/simple_grid_layout.mm

Issue 14646021: [Autofill] Add basic version of GridLayout (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 7 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
OLDNEW
(Empty)
1 // Copyright (c) 2013 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.
4
5 #include "chrome/browser/ui/cocoa/simple_grid_layout.h"
6
7 #include <algorithm>
8
9 #include "base/logging.h"
10 #include "base/stl_util.h"
11
12 namespace {
13 const int kAutoColumnIdStart = 1000000; // Starting ID for autogeneration.
Robert Sesek 2013/05/02 20:16:46 nit: no indention
groby-ooo-7-16 2013/05/03 04:31:46 Done.
14 }
15
16 // Encapsulates state for a single NSView in the layout
17 class ViewState {
18 public:
19 ViewState(NSView* view, ColumnSet* column_set, int row, int column);
20
21 // Gets the current width of the column associated with this view.
22 float GetColumnWidth();
23
24 // Get the preferred height for specified width.
25 float GetHeightForWidth(float with);
26
27 Column* GetColumn() const { return column_set_->GetColumn(column_); }
28
29 int row_index() { return row_; }
30 NSView* view() { return view_; }
31 float preferred_height() { return pref_height_; }
32 void set_preferred_height(float height) { pref_height_ = height; }
33
34 private:
35 NSView* view_;
36 ColumnSet* column_set_;
37 int row_;
38 int column_;
39 float pref_height_;
40 };
41
42 class LayoutElement {
43 public:
44 LayoutElement(float resize_percent, int fixed_width);
45 virtual ~LayoutElement() {}
46
47 template <class T>
48 static void ResetSizes(ScopedVector<T>* elements) {
49 // Reset the layout width of each column.
50 for (typename std::vector<T*>::iterator i = elements->begin();
51 i != elements->end(); ++i) {
52 (*i)->ResetSize();
53 }
54 }
55
56 template <class T>
57 static void CalculateLocationsFromSize(ScopedVector<T>* elements) {
58 // Reset the layout width of each column.
59 int location = 0;
60 for (typename std::vector<T*>::iterator i = elements->begin();
61 i != elements->end(); ++i) {
62 (*i)->SetLocation(location);
63 location += (*i)->Size();
64 }
65 }
66
67 float Size() { return size_; }
68
69 void ResetSize() {
70 size_ = fixed_width_;
71 }
72
73 void SetSize(float size) {
74 size_ = size;
75 }
76
77 float Location() const {
78 return location_;
79 }
80
81 // Adjusts the size of this LayoutElement to be the max of the current size
82 // and the specified size.
83 virtual void AdjustSize(float size) {
84 size_ = std::max(size_, size);
85 }
86
87 void SetLocation(float location) {
88 location_ = location;
89 }
90
91 bool IsResizable() {
92 return resize_percent_ > 0.0f;
93 }
94
95 float ResizePercent() {
96 return resize_percent_;
97 }
98
99 private:
100 float resize_percent_;
101 int fixed_width_;
102 float size_;
103 float location_;
104 };
105
106 LayoutElement::LayoutElement(float resize_percent, int fixed_width)
107 : resize_percent_(resize_percent),
108 fixed_width_(fixed_width),
109 size_(0),
110 location_(0) {
111 }
112
113 class Column : public LayoutElement {
114 public:
115 Column(float resize_percent, int fixed_width, bool is_padding);
116
117 bool is_padding() { return is_padding_; }
Robert Sesek 2013/05/02 20:16:46 nit: blank line after
groby-ooo-7-16 2013/05/03 04:31:46 Done.
118 private:
119 const bool is_padding_;
120 };
121
122 Column::Column(float resize_percent, int fixed_width, bool is_padding)
123 : LayoutElement(resize_percent, fixed_width),
124 is_padding_(is_padding) {
125 }
126
127 class Row : public LayoutElement {
128 public:
129 Row(float resize_percent, int fixed_height, ColumnSet* column_set);
Robert Sesek 2013/05/02 20:16:46 nit: blank line after
groby-ooo-7-16 2013/05/03 04:31:46 Done.
130 ColumnSet* column_set() { return column_set_; }
131
132 private:
133 ColumnSet* column_set_;
134 };
135
136 Row::Row(float resize_percent, int fixed_height, ColumnSet* column_set)
Robert Sesek 2013/05/02 20:16:46 nit: extra space after ,
groby-ooo-7-16 2013/05/03 04:31:46 Done.
137 : LayoutElement(resize_percent, fixed_height),
138 column_set_(column_set) {
139 }
140
141 ViewState::ViewState(NSView* view, ColumnSet* column_set, int row, int column)
142 : view_(view),
143 column_set_(column_set),
144 row_(row),
145 column_(column) {}
146
147 float ViewState::GetColumnWidth() {
148 return column_set_->GetColumnWidth(column_);
149 }
150
151 float ViewState::GetHeightForWidth(float width) {
152 // NSView doesn't have any way to make height fit size, get frame height.
153 return NSHeight([view_ frame]);
154 }
155
156 ColumnSet::ColumnSet(int id) : id_(id) {
157 }
158
159 ColumnSet::~ColumnSet() {
160 }
161
162 void ColumnSet::AddPaddingColumn(int fixed_width) {
163 columns_.push_back(new Column(0.0f, fixed_width, true));
164 }
165
166 void ColumnSet::AddColumn(float resize_percent) {
167 columns_.push_back(new Column(resize_percent, 0, false));
168 }
169
170 void ColumnSet::CalculateSize(float width) {
171 // Reset column widths
172 LayoutElement::ResetSizes(&columns_);
173 width = CalculateRemainingWidth(width);
174 DistributeRemainingWidth(width);
175 }
176
177 void ColumnSet::ResetColumnXCoordinates() {
178 LayoutElement::CalculateLocationsFromSize(&columns_);
179 }
180
181 float ColumnSet::CalculateRemainingWidth(float width) {
182 for (size_t i = 0; i < columns_.size(); ++i)
183 width -= columns_[i]->Size();
184
185 return width;
186 }
187
188 void ColumnSet::DistributeRemainingWidth(float width) {
189 float total_resize = 0.0f;
190 int resizable_columns = 0.0;
191
192 for (size_t i = 0; i < columns_.size(); ++i) {
193 if (columns_[i]->IsResizable()) {
194 total_resize += columns_[i]->ResizePercent();
195 resizable_columns++;
196 }
197 }
198
199 float remaining_width = width;
200 for (size_t i = 0; i < columns_.size(); ++i) {
201 if (columns_[i]->IsResizable()) {
202 float delta = (resizable_columns == 0) ? remaining_width :
203 (width * columns_[i]->ResizePercent() / total_resize);
204 remaining_width -= delta;
205 columns_[i]->SetSize(columns_[i]->Size() + delta);
206 resizable_columns--;
207 }
208 }
209 }
210
211 float ColumnSet::GetColumnWidth(int column_index) {
212 if (column_index < 0 || column_index >= num_columns())
213 return 0.0;
214 return columns_[column_index]->Size();
215 }
216
217 float ColumnSet::ColumnLocation(int column_index) {
218 if (column_index < 0 || column_index >= num_columns())
219 return 0.0;
220 return columns_[column_index]->Location();
221 }
222
223 SimpleGridLayout::SimpleGridLayout(NSView* host)
224 : next_column_(0),
225 current_auto_id_(kAutoColumnIdStart),
226 host_(host) {
227 [host_ frame];
228 }
229
230 SimpleGridLayout::~SimpleGridLayout() {
231 }
232
233 ColumnSet* SimpleGridLayout::AddColumnSet(int id) {
234 DCHECK(GetColumnSet(id) == NULL);
235 ColumnSet* column_set = new ColumnSet(id);
236 column_sets_.push_back(column_set);
237 return column_set;
238 }
239
240 ColumnSet* SimpleGridLayout::GetColumnSet(int id) {
241 for (ScopedVector<ColumnSet>::const_iterator i = column_sets_.begin();
242 i != column_sets_.end(); ++i) {
243 if ((*i)->id() == id) {
244 return *i;
245 }
246 }
247 return NULL;
248 }
249
250 void SimpleGridLayout::AddPaddingRow(int fixed_height) {
251 AddRow(new Row(0.0f, fixed_height, NULL));
252 }
253
254 void SimpleGridLayout::StartRow(float vertical_resize, int column_set_id) {
255 ColumnSet* column_set = GetColumnSet(column_set_id);
256 DCHECK(column_set);
257 AddRow(new Row(vertical_resize, 0, column_set));
258 }
259
260 ColumnSet* SimpleGridLayout::AddRow() {
261 AddRow(new Row(0, 0, AddColumnSet(current_auto_id_++)));
262 return column_sets_.back();
263 }
264
265 void SimpleGridLayout::SkipColumns(int col_count) {
266 DCHECK(col_count > 0);
267 next_column_ += col_count;
268 ColumnSet* current_row_col_set_ = GetLastValidColumnSet();
269 DCHECK(current_row_col_set_ &&
270 next_column_ <= current_row_col_set_->num_columns());
271 SkipPaddingColumns();
272 }
273
274 void SimpleGridLayout::AddView(NSView* view) {
275 [host_ addSubview:view];
276 DCHECK(next_column_ < GetLastValidColumnSet()->num_columns());
277 view_states_.push_back(
278 new ViewState(view,
279 GetLastValidColumnSet(),
280 rows_.size() - 1,
281 next_column_++));
282 SkipPaddingColumns();
283 }
284
285 // Sizes elements to fit into the superViews bounds, according to constraints.
286 void SimpleGridLayout::Layout(NSView* superView) {
287 SizeRowsAndColumns(NSWidth([superView bounds]));
288 for (std::vector<ViewState*>::iterator i = view_states_.begin();
289 i != view_states_.end(); ++i) {
290 ViewState* view_state = *i;
291 NSView* view = view_state->view();
292 NSRect frame = NSMakeRect(view_state->GetColumn()->Location(),
293 rows_[view_state->row_index()]->Location(),
294 view_state->GetColumn()->Size(),
295 rows_[view_state->row_index()]->Size());
296 [view setFrame:frame];
297 }
298 }
299
300 void SimpleGridLayout::SizeRowsAndColumns(float width) {
301 // Size all columns first.
302 for (ScopedVector<ColumnSet>::iterator i = column_sets_.begin();
303 i != column_sets_.end(); ++i) {
304 (*i)->CalculateSize(width);
305 (*i)->ResetColumnXCoordinates();
306 }
307
308 // Reset the height of each row.
309 LayoutElement::ResetSizes(&rows_);
310
311 // For each ViewState, obtain the preferred height
312 for (std::vector<ViewState*>::iterator i= view_states_.begin();
313 i != view_states_.end() ; ++i) {
314 ViewState* view_state = *i;
315
316 // The view is resizable. As the pref height may vary with the width,
317 // ask for the pref again.
318 int actual_width = view_state->GetColumnWidth();
319
320 // The width this view will get differs from its preferred. Some Views
321 // pref height varies with its width; ask for the preferred again.
322 view_state->set_preferred_height(
323 view_state->GetHeightForWidth(actual_width));
324 }
325
326
327 // Make sure each row can accommodate all contained ViewStates.
328 std::vector<ViewState*>::iterator view_states_iterator = view_states_.begin();
329 for (; view_states_iterator != view_states_.end(); ++view_states_iterator) {
330 ViewState* view_state = *view_states_iterator;
331 Row* row = rows_[view_state->row_index()];
332 row->AdjustSize(view_state->preferred_height());
333 }
334
335 // Update the location of each of the rows.
336 LayoutElement::CalculateLocationsFromSize(&rows_);
337 }
338
339 void SimpleGridLayout::SkipPaddingColumns() {
340 ColumnSet* current_row_col_set_ = GetLastValidColumnSet();
341 while (next_column_ < current_row_col_set_->num_columns() &&
342 current_row_col_set_->GetColumn(next_column_)->is_padding()) {
343 next_column_++;
344 }
345 }
346
347 ColumnSet* SimpleGridLayout::GetLastValidColumnSet() {
348 for (int i = num_rows() - 1; i >= 0; --i) {
349 if (rows_[i]->column_set())
350 return rows_[i]->column_set();
351 }
352 return NULL;
353 }
354
355 float SimpleGridLayout::GetRowHeight(int row_index) {
356 if (row_index < 0 || row_index >= num_rows())
357 return 0.0;
358 return rows_[row_index]->Size();
359 }
360
361 float SimpleGridLayout::GetRowLocation(int row_index) const {
362 if (row_index < 0 || row_index >= num_rows())
363 return 0.0;
364 return rows_[row_index]->Location();
365 }
366
367 float SimpleGridLayout::GetPreferredHeightForWidth(float width) {
368 if (rows_.empty())
369 return 0.0f;
370
371 SizeRowsAndColumns(width);
372 return rows_.back()->Location() + rows_.back()->Size();
373 }
374
375 void SimpleGridLayout::AddRow(Row* row) {
376 next_column_ = 0;
377 rows_.push_back(row);
378 }
379
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698