OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 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 | 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 "chrome/browser/ui/cocoa/autofill/simple_grid_layout.h" | 5 #include "chrome/browser/ui/cocoa/autofill/simple_grid_layout.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 | 8 |
9 #include <algorithm> | 9 #include <algorithm> |
10 | 10 |
11 #include "base/logging.h" | 11 #include "base/memory/ptr_util.h" |
12 #include "base/stl_util.h" | |
13 | 12 |
14 namespace { | 13 namespace { |
15 const int kAutoColumnIdStart = 1000000; // Starting ID for autogeneration. | 14 const int kAutoColumnIdStart = 1000000; // Starting ID for autogeneration. |
16 } | 15 } |
17 | 16 |
18 // Encapsulates state for a single NSView in the layout | 17 // Encapsulates state for a single NSView in the layout |
19 class ViewState { | 18 class ViewState { |
20 public: | 19 public: |
21 ViewState(NSView* view, ColumnSet* column_set, int row, int column); | 20 ViewState(NSView* view, ColumnSet* column_set, int row, int column); |
22 | 21 |
(...skipping 17 matching lines...) Expand all Loading... |
40 int column_; | 39 int column_; |
41 float pref_height_; | 40 float pref_height_; |
42 }; | 41 }; |
43 | 42 |
44 class LayoutElement { | 43 class LayoutElement { |
45 public: | 44 public: |
46 LayoutElement(float resize_percent, int fixed_width); | 45 LayoutElement(float resize_percent, int fixed_width); |
47 virtual ~LayoutElement() {} | 46 virtual ~LayoutElement() {} |
48 | 47 |
49 template <class T> | 48 template <class T> |
50 static void ResetSizes(ScopedVector<T>* elements) { | 49 static void ResetSizes(std::vector<std::unique_ptr<T>>* elements) { |
51 // Reset the layout width of each column. | 50 // Reset the layout width of each column. |
52 for (typename std::vector<T*>::iterator i = elements->begin(); | 51 for (const auto& element : *elements) |
53 i != elements->end(); ++i) { | 52 element->ResetSize(); |
54 (*i)->ResetSize(); | 53 } |
| 54 |
| 55 template <class T> |
| 56 static void CalculateLocationsFromSize( |
| 57 std::vector<std::unique_ptr<T>>* elements) { |
| 58 // Reset the layout width of each column. |
| 59 int location = 0; |
| 60 for (const auto& element : *elements) { |
| 61 element->SetLocation(location); |
| 62 location += element->Size(); |
55 } | 63 } |
56 } | 64 } |
57 | 65 |
58 template <class T> | |
59 static void CalculateLocationsFromSize(ScopedVector<T>* elements) { | |
60 // Reset the layout width of each column. | |
61 int location = 0; | |
62 for (typename std::vector<T*>::iterator i = elements->begin(); | |
63 i != elements->end(); ++i) { | |
64 (*i)->SetLocation(location); | |
65 location += (*i)->Size(); | |
66 } | |
67 } | |
68 | |
69 float Size() { return size_; } | 66 float Size() { return size_; } |
70 | 67 |
71 void ResetSize() { | 68 void ResetSize() { |
72 size_ = fixed_width_; | 69 size_ = fixed_width_; |
73 } | 70 } |
74 | 71 |
75 void SetSize(float size) { | 72 void SetSize(float size) { |
76 size_ = size; | 73 size_ = size; |
77 } | 74 } |
78 | 75 |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
157 return NSHeight([view_ frame]); | 154 return NSHeight([view_ frame]); |
158 } | 155 } |
159 | 156 |
160 ColumnSet::ColumnSet(int id) : id_(id) { | 157 ColumnSet::ColumnSet(int id) : id_(id) { |
161 } | 158 } |
162 | 159 |
163 ColumnSet::~ColumnSet() { | 160 ColumnSet::~ColumnSet() { |
164 } | 161 } |
165 | 162 |
166 void ColumnSet::AddPaddingColumn(int fixed_width) { | 163 void ColumnSet::AddPaddingColumn(int fixed_width) { |
167 columns_.push_back(new Column(0.0f, fixed_width, true)); | 164 columns_.push_back(base::MakeUnique<Column>(0.0f, fixed_width, true)); |
168 } | 165 } |
169 | 166 |
170 void ColumnSet::AddColumn(float resize_percent) { | 167 void ColumnSet::AddColumn(float resize_percent) { |
171 columns_.push_back(new Column(resize_percent, 0, false)); | 168 columns_.push_back(base::MakeUnique<Column>(resize_percent, 0, false)); |
172 } | 169 } |
173 | 170 |
174 void ColumnSet::CalculateSize(float width) { | 171 void ColumnSet::CalculateSize(float width) { |
175 // Reset column widths | 172 // Reset column widths. |
176 LayoutElement::ResetSizes(&columns_); | 173 LayoutElement::ResetSizes(&columns_); |
177 width = CalculateRemainingWidth(width); | 174 width = CalculateRemainingWidth(width); |
178 DistributeRemainingWidth(width); | 175 DistributeRemainingWidth(width); |
179 } | 176 } |
180 | 177 |
181 void ColumnSet::ResetColumnXCoordinates() { | 178 void ColumnSet::ResetColumnXCoordinates() { |
182 LayoutElement::CalculateLocationsFromSize(&columns_); | 179 LayoutElement::CalculateLocationsFromSize(&columns_); |
183 } | 180 } |
184 | 181 |
185 float ColumnSet::CalculateRemainingWidth(float width) { | 182 float ColumnSet::CalculateRemainingWidth(float width) { |
186 for (size_t i = 0; i < columns_.size(); ++i) | 183 for (const auto& column : columns_) |
187 width -= columns_[i]->Size(); | 184 width -= column->Size(); |
188 | 185 |
189 return width; | 186 return width; |
190 } | 187 } |
191 | 188 |
192 void ColumnSet::DistributeRemainingWidth(float width) { | 189 void ColumnSet::DistributeRemainingWidth(float width) { |
193 float total_resize = 0.0f; | 190 float total_resize = 0.0f; |
194 int resizable_columns = 0.0; | 191 int resizable_columns = 0.0; |
195 | 192 |
196 for (size_t i = 0; i < columns_.size(); ++i) { | 193 for (const auto& column : columns_) { |
197 if (columns_[i]->IsResizable()) { | 194 if (column->IsResizable()) { |
198 total_resize += columns_[i]->ResizePercent(); | 195 total_resize += column->ResizePercent(); |
199 resizable_columns++; | 196 resizable_columns++; |
200 } | 197 } |
201 } | 198 } |
202 | 199 |
203 float remaining_width = width; | 200 float remaining_width = width; |
204 for (size_t i = 0; i < columns_.size(); ++i) { | 201 for (const auto& column : columns_) { |
205 if (columns_[i]->IsResizable()) { | 202 if (column->IsResizable()) { |
206 float delta = (resizable_columns == 0) ? remaining_width : | 203 float delta = (resizable_columns == 0) |
207 (width * columns_[i]->ResizePercent() / total_resize); | 204 ? remaining_width |
| 205 : (width * column->ResizePercent() / total_resize); |
208 remaining_width -= delta; | 206 remaining_width -= delta; |
209 columns_[i]->SetSize(columns_[i]->Size() + delta); | 207 column->SetSize(column->Size() + delta); |
210 resizable_columns--; | 208 resizable_columns--; |
211 } | 209 } |
212 } | 210 } |
213 } | 211 } |
214 | 212 |
215 float ColumnSet::GetColumnWidth(int column_index) { | 213 float ColumnSet::GetColumnWidth(int column_index) { |
216 if (column_index < 0 || column_index >= num_columns()) | 214 if (column_index < 0 || column_index >= num_columns()) |
217 return 0.0; | 215 return 0.0; |
218 return columns_[column_index]->Size(); | 216 return columns_[column_index]->Size(); |
219 } | 217 } |
220 | 218 |
221 float ColumnSet::ColumnLocation(int column_index) { | 219 float ColumnSet::ColumnLocation(int column_index) { |
222 if (column_index < 0 || column_index >= num_columns()) | 220 if (column_index < 0 || column_index >= num_columns()) |
223 return 0.0; | 221 return 0.0; |
224 return columns_[column_index]->Location(); | 222 return columns_[column_index]->Location(); |
225 } | 223 } |
226 | 224 |
227 SimpleGridLayout::SimpleGridLayout(NSView* host) | 225 SimpleGridLayout::SimpleGridLayout(NSView* host) |
228 : next_column_(0), | 226 : next_column_(0), |
229 current_auto_id_(kAutoColumnIdStart), | 227 current_auto_id_(kAutoColumnIdStart), |
230 host_(host) { | 228 host_(host) { |
231 [host_ frame]; | 229 [host_ frame]; |
232 } | 230 } |
233 | 231 |
234 SimpleGridLayout::~SimpleGridLayout() { | 232 SimpleGridLayout::~SimpleGridLayout() { |
235 } | 233 } |
236 | 234 |
237 ColumnSet* SimpleGridLayout::AddColumnSet(int id) { | 235 ColumnSet* SimpleGridLayout::AddColumnSet(int id) { |
238 DCHECK(GetColumnSet(id) == NULL); | 236 DCHECK(GetColumnSet(id) == nullptr); |
239 ColumnSet* column_set = new ColumnSet(id); | 237 column_sets_.push_back(base::MakeUnique<ColumnSet>(id)); |
240 column_sets_.push_back(column_set); | 238 return column_sets_.back().get(); |
241 return column_set; | |
242 } | 239 } |
243 | 240 |
244 ColumnSet* SimpleGridLayout::GetColumnSet(int id) { | 241 ColumnSet* SimpleGridLayout::GetColumnSet(int id) { |
245 for (ScopedVector<ColumnSet>::const_iterator i = column_sets_.begin(); | 242 for (const auto& column_set : column_sets_) { |
246 i != column_sets_.end(); ++i) { | 243 if (column_set->id() == id) { |
247 if ((*i)->id() == id) { | 244 return column_set.get(); |
248 return *i; | |
249 } | 245 } |
250 } | 246 } |
251 return NULL; | 247 return nullptr; |
252 } | 248 } |
253 | 249 |
254 void SimpleGridLayout::AddPaddingRow(int fixed_height) { | 250 void SimpleGridLayout::AddPaddingRow(int fixed_height) { |
255 AddRow(new Row(0.0f, fixed_height, NULL)); | 251 AddRow(base::MakeUnique<Row>(0.0f, fixed_height, nullptr)); |
256 } | 252 } |
257 | 253 |
258 void SimpleGridLayout::StartRow(float vertical_resize, int column_set_id) { | 254 void SimpleGridLayout::StartRow(float vertical_resize, int column_set_id) { |
259 ColumnSet* column_set = GetColumnSet(column_set_id); | 255 ColumnSet* column_set = GetColumnSet(column_set_id); |
260 DCHECK(column_set); | 256 DCHECK(column_set); |
261 AddRow(new Row(vertical_resize, 0, column_set)); | 257 AddRow(base::MakeUnique<Row>(vertical_resize, 0, column_set)); |
262 } | 258 } |
263 | 259 |
264 ColumnSet* SimpleGridLayout::AddRow() { | 260 ColumnSet* SimpleGridLayout::AddRow() { |
265 AddRow(new Row(0, 0, AddColumnSet(current_auto_id_++))); | 261 AddRow(base::MakeUnique<Row>(0, 0, AddColumnSet(current_auto_id_++))); |
266 return column_sets_.back(); | 262 return column_sets_.back().get(); |
267 } | 263 } |
268 | 264 |
269 void SimpleGridLayout::SkipColumns(int col_count) { | 265 void SimpleGridLayout::SkipColumns(int col_count) { |
270 DCHECK(col_count > 0); | 266 DCHECK(col_count > 0); |
271 next_column_ += col_count; | 267 next_column_ += col_count; |
272 ColumnSet* current_row_col_set_ = GetLastValidColumnSet(); | 268 ColumnSet* current_row_col_set_ = GetLastValidColumnSet(); |
273 DCHECK(current_row_col_set_ && | 269 DCHECK(current_row_col_set_ && |
274 next_column_ <= current_row_col_set_->num_columns()); | 270 next_column_ <= current_row_col_set_->num_columns()); |
275 SkipPaddingColumns(); | 271 SkipPaddingColumns(); |
276 } | 272 } |
277 | 273 |
278 void SimpleGridLayout::AddView(NSView* view) { | 274 void SimpleGridLayout::AddView(NSView* view) { |
279 [host_ addSubview:view]; | 275 [host_ addSubview:view]; |
280 DCHECK(next_column_ < GetLastValidColumnSet()->num_columns()); | 276 DCHECK(next_column_ < GetLastValidColumnSet()->num_columns()); |
281 view_states_.push_back( | 277 view_states_.push_back(base::MakeUnique<ViewState>( |
282 new ViewState(view, | 278 view, GetLastValidColumnSet(), rows_.size() - 1, next_column_++)); |
283 GetLastValidColumnSet(), | |
284 rows_.size() - 1, | |
285 next_column_++)); | |
286 SkipPaddingColumns(); | 279 SkipPaddingColumns(); |
287 } | 280 } |
288 | 281 |
289 // Sizes elements to fit into the superViews bounds, according to constraints. | 282 // Sizes elements to fit into the superViews bounds, according to constraints. |
290 void SimpleGridLayout::Layout(NSView* superView) { | 283 void SimpleGridLayout::Layout(NSView* superView) { |
291 SizeRowsAndColumns(NSWidth([superView bounds])); | 284 SizeRowsAndColumns(NSWidth([superView bounds])); |
292 for (std::vector<ViewState*>::iterator i = view_states_.begin(); | 285 for (const auto& view_state : view_states_) { |
293 i != view_states_.end(); ++i) { | |
294 ViewState* view_state = *i; | |
295 NSView* view = view_state->view(); | 286 NSView* view = view_state->view(); |
296 NSRect frame = NSMakeRect(view_state->GetColumn()->Location(), | 287 NSRect frame = NSMakeRect(view_state->GetColumn()->Location(), |
297 rows_[view_state->row_index()]->Location(), | 288 rows_[view_state->row_index()]->Location(), |
298 view_state->GetColumn()->Size(), | 289 view_state->GetColumn()->Size(), |
299 rows_[view_state->row_index()]->Size()); | 290 rows_[view_state->row_index()]->Size()); |
300 [view setFrame:NSIntegralRect(frame)]; | 291 [view setFrame:NSIntegralRect(frame)]; |
301 } | 292 } |
302 } | 293 } |
303 | 294 |
304 void SimpleGridLayout::SizeRowsAndColumns(float width) { | 295 void SimpleGridLayout::SizeRowsAndColumns(float width) { |
305 // Size all columns first. | 296 // Size all columns first. |
306 for (ScopedVector<ColumnSet>::iterator i = column_sets_.begin(); | 297 for (const auto& column_set : column_sets_) { |
307 i != column_sets_.end(); ++i) { | 298 column_set->CalculateSize(width); |
308 (*i)->CalculateSize(width); | 299 column_set->ResetColumnXCoordinates(); |
309 (*i)->ResetColumnXCoordinates(); | |
310 } | 300 } |
311 | 301 |
312 // Reset the height of each row. | 302 // Reset the height of each row. |
313 LayoutElement::ResetSizes(&rows_); | 303 LayoutElement::ResetSizes(&rows_); |
314 | 304 |
315 // For each ViewState, obtain the preferred height | 305 // For each ViewState, obtain the preferred height |
316 for (std::vector<ViewState*>::iterator i= view_states_.begin(); | 306 for (const auto& view_state : view_states_) { |
317 i != view_states_.end() ; ++i) { | |
318 ViewState* view_state = *i; | |
319 | |
320 // The view is resizable. As the pref height may vary with the width, | 307 // The view is resizable. As the pref height may vary with the width, |
321 // ask for the pref again. | 308 // ask for the pref again. |
322 int actual_width = view_state->GetColumnWidth(); | 309 int actual_width = view_state->GetColumnWidth(); |
323 | 310 |
324 // The width this view will get differs from its preferred. Some Views | 311 // The width this view will get differs from its preferred. Some Views |
325 // pref height varies with its width; ask for the preferred again. | 312 // pref height varies with its width; ask for the preferred again. |
326 view_state->set_preferred_height( | 313 view_state->set_preferred_height( |
327 view_state->GetHeightForWidth(actual_width)); | 314 view_state->GetHeightForWidth(actual_width)); |
328 } | 315 } |
329 | 316 |
330 | 317 |
331 // Make sure each row can accommodate all contained ViewStates. | 318 // Make sure each row can accommodate all contained ViewStates. |
332 std::vector<ViewState*>::iterator view_states_iterator = view_states_.begin(); | 319 for (const auto& view_state : view_states_) { |
333 for (; view_states_iterator != view_states_.end(); ++view_states_iterator) { | 320 Row* row = rows_[view_state->row_index()].get(); |
334 ViewState* view_state = *view_states_iterator; | |
335 Row* row = rows_[view_state->row_index()]; | |
336 row->AdjustSize(view_state->preferred_height()); | 321 row->AdjustSize(view_state->preferred_height()); |
337 } | 322 } |
338 | 323 |
339 // Update the location of each of the rows. | 324 // Update the location of each of the rows. |
340 LayoutElement::CalculateLocationsFromSize(&rows_); | 325 LayoutElement::CalculateLocationsFromSize(&rows_); |
341 } | 326 } |
342 | 327 |
343 void SimpleGridLayout::SkipPaddingColumns() { | 328 void SimpleGridLayout::SkipPaddingColumns() { |
344 ColumnSet* current_row_col_set_ = GetLastValidColumnSet(); | 329 ColumnSet* current_row_col_set_ = GetLastValidColumnSet(); |
345 while (next_column_ < current_row_col_set_->num_columns() && | 330 while (next_column_ < current_row_col_set_->num_columns() && |
346 current_row_col_set_->GetColumn(next_column_)->is_padding()) { | 331 current_row_col_set_->GetColumn(next_column_)->is_padding()) { |
347 next_column_++; | 332 next_column_++; |
348 } | 333 } |
349 } | 334 } |
350 | 335 |
351 ColumnSet* SimpleGridLayout::GetLastValidColumnSet() { | 336 ColumnSet* SimpleGridLayout::GetLastValidColumnSet() { |
352 for (int i = num_rows() - 1; i >= 0; --i) { | 337 for (int i = num_rows() - 1; i >= 0; --i) { |
353 if (rows_[i]->column_set()) | 338 if (rows_[i]->column_set()) |
354 return rows_[i]->column_set(); | 339 return rows_[i]->column_set(); |
355 } | 340 } |
356 return NULL; | 341 return nullptr; |
357 } | 342 } |
358 | 343 |
359 float SimpleGridLayout::GetRowHeight(int row_index) { | 344 float SimpleGridLayout::GetRowHeight(int row_index) { |
360 if (row_index < 0 || row_index >= num_rows()) | 345 if (row_index < 0 || row_index >= num_rows()) |
361 return 0.0; | 346 return 0.0; |
362 return rows_[row_index]->Size(); | 347 return rows_[row_index]->Size(); |
363 } | 348 } |
364 | 349 |
365 float SimpleGridLayout::GetRowLocation(int row_index) const { | 350 float SimpleGridLayout::GetRowLocation(int row_index) const { |
366 if (row_index < 0 || row_index >= num_rows()) | 351 if (row_index < 0 || row_index >= num_rows()) |
367 return 0.0; | 352 return 0.0; |
368 return rows_[row_index]->Location(); | 353 return rows_[row_index]->Location(); |
369 } | 354 } |
370 | 355 |
371 float SimpleGridLayout::GetPreferredHeightForWidth(float width) { | 356 float SimpleGridLayout::GetPreferredHeightForWidth(float width) { |
372 if (rows_.empty()) | 357 if (rows_.empty()) |
373 return 0.0f; | 358 return 0.0f; |
374 | 359 |
375 SizeRowsAndColumns(width); | 360 SizeRowsAndColumns(width); |
376 return rows_.back()->Location() + rows_.back()->Size(); | 361 return rows_.back()->Location() + rows_.back()->Size(); |
377 } | 362 } |
378 | 363 |
379 void SimpleGridLayout::AddRow(Row* row) { | 364 void SimpleGridLayout::AddRow(std::unique_ptr<Row> row) { |
380 next_column_ = 0; | 365 next_column_ = 0; |
381 rows_.push_back(row); | 366 rows_.push_back(std::move(row)); |
382 } | 367 } |
383 | 368 |
OLD | NEW |