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

Side by Side Diff: chrome/browser/ui/autofill/autofill_popup_controller_impl.cc

Issue 772253003: Create an autofill Suggestion class (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: self review 2 Created 6 years 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
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 "chrome/browser/ui/autofill/autofill_popup_controller_impl.h" 5 #include "chrome/browser/ui/autofill/autofill_popup_controller_impl.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <utility> 8 #include <utility>
9 9
10 #include "base/logging.h" 10 #include "base/logging.h"
11 #include "base/strings/utf_string_conversions.h" 11 #include "base/strings/utf_string_conversions.h"
12 #include "chrome/browser/ui/autofill/autofill_popup_view.h" 12 #include "chrome/browser/ui/autofill/autofill_popup_view.h"
13 #include "chrome/browser/ui/autofill/popup_constants.h" 13 #include "chrome/browser/ui/autofill/popup_constants.h"
14 #include "components/autofill/core/browser/autofill_popup_delegate.h" 14 #include "components/autofill/core/browser/autofill_popup_delegate.h"
15 #include "components/autofill/core/browser/popup_item_ids.h" 15 #include "components/autofill/core/browser/popup_item_ids.h"
16 #include "components/autofill/core/browser/suggestion.h"
16 #include "content/public/browser/native_web_keyboard_event.h" 17 #include "content/public/browser/native_web_keyboard_event.h"
17 #include "grit/components_scaled_resources.h" 18 #include "grit/components_scaled_resources.h"
18 #include "ui/base/resource/resource_bundle.h" 19 #include "ui/base/resource/resource_bundle.h"
19 #include "ui/events/event.h" 20 #include "ui/events/event.h"
20 #include "ui/gfx/rect_conversions.h" 21 #include "ui/gfx/rect_conversions.h"
21 #include "ui/gfx/screen.h" 22 #include "ui/gfx/screen.h"
22 #include "ui/gfx/text_elider.h" 23 #include "ui/gfx/text_elider.h"
23 #include "ui/gfx/text_utils.h" 24 #include "ui/gfx/text_utils.h"
24 #include "ui/gfx/vector2d.h" 25 #include "ui/gfx/vector2d.h"
25 26
26 using base::WeakPtr; 27 using base::WeakPtr;
27 28
28 namespace autofill { 29 namespace autofill {
29 namespace { 30 namespace {
30 31
31 // Used to indicate that no line is currently selected by the user. 32 // Used to indicate that no line is currently selected by the user.
32 const int kNoSelection = -1; 33 const int kNoSelection = -1;
33 34
34 // The vertical height of each row in pixels. 35 // The vertical height of each row in pixels.
35 const size_t kRowHeight = 24; 36 const size_t kRowHeight = 24;
36 37
37 // The vertical height of a separator in pixels. 38 // The vertical height of a separator in pixels.
38 const size_t kSeparatorHeight = 1; 39 const size_t kSeparatorHeight = 1;
39 40
40 #if !defined(OS_ANDROID) 41 #if !defined(OS_ANDROID)
41 // Size difference between name and subtext in pixels. 42 // Size difference between name and label in pixels.
42 const int kLabelFontSizeDelta = -2; 43 const int kLabelFontSizeDelta = -2;
43 44
44 const size_t kNamePadding = AutofillPopupView::kNamePadding; 45 const size_t kNamePadding = AutofillPopupView::kNamePadding;
45 const size_t kIconPadding = AutofillPopupView::kIconPadding; 46 const size_t kIconPadding = AutofillPopupView::kIconPadding;
46 const size_t kEndPadding = AutofillPopupView::kEndPadding; 47 const size_t kEndPadding = AutofillPopupView::kEndPadding;
47 #endif 48 #endif
48 49
49 struct DataResource { 50 struct DataResource {
50 const char* name; 51 const char* name;
51 int id; 52 int id;
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
103 web_contents)), 104 web_contents)),
104 view_(NULL), 105 view_(NULL),
105 delegate_(delegate), 106 delegate_(delegate),
106 text_direction_(text_direction), 107 text_direction_(text_direction),
107 weak_ptr_factory_(this) { 108 weak_ptr_factory_(this) {
108 ClearState(); 109 ClearState();
109 controller_common_->SetKeyPressCallback( 110 controller_common_->SetKeyPressCallback(
110 base::Bind(&AutofillPopupControllerImpl::HandleKeyPressEvent, 111 base::Bind(&AutofillPopupControllerImpl::HandleKeyPressEvent,
111 base::Unretained(this))); 112 base::Unretained(this)));
112 #if !defined(OS_ANDROID) 113 #if !defined(OS_ANDROID)
113 subtext_font_list_ = name_font_list_.DeriveWithSizeDelta(kLabelFontSizeDelta); 114 label_font_list_ = value_font_list_.DeriveWithSizeDelta(kLabelFontSizeDelta);
114 title_font_list_ = name_font_list_.DeriveWithStyle(gfx::Font::BOLD); 115 title_font_list_ = value_font_list_.DeriveWithStyle(gfx::Font::BOLD);
115 #if defined(OS_MACOSX) 116 #if defined(OS_MACOSX)
116 // There is no italic version of the system font. 117 // There is no italic version of the system font.
117 warning_font_list_ = name_font_list_; 118 warning_font_list_ = value_font_list_;
118 #else 119 #else
119 warning_font_list_ = name_font_list_.DeriveWithStyle(gfx::Font::ITALIC); 120 warning_font_list_ = value_font_list_.DeriveWithStyle(gfx::Font::ITALIC);
120 #endif 121 #endif
121 #endif 122 #endif
122 } 123 }
123 124
124 AutofillPopupControllerImpl::~AutofillPopupControllerImpl() {} 125 AutofillPopupControllerImpl::~AutofillPopupControllerImpl() {}
125 126
126 void AutofillPopupControllerImpl::Show( 127 void AutofillPopupControllerImpl::Show(
127 const std::vector<base::string16>& names, 128 const std::vector<autofill::Suggestion>& suggestions) {
128 const std::vector<base::string16>& subtexts, 129 SetValues(suggestions);
129 const std::vector<base::string16>& icons, 130 DCHECK_EQ(suggestions_.size(), elided_values_.size());
130 const std::vector<int>& identifiers) { 131 DCHECK_EQ(suggestions_.size(), elided_labels_.size());
131 SetValues(names, subtexts, icons, identifiers);
132 132
133 #if !defined(OS_ANDROID) 133 #if !defined(OS_ANDROID)
134 // Android displays the long text with ellipsis using the view attributes. 134 // Android displays the long text with ellipsis using the view attributes.
135 135
136 UpdatePopupBounds(); 136 UpdatePopupBounds();
137 int popup_width = popup_bounds().width(); 137 int popup_width = popup_bounds().width();
138 138
139 // Elide the name and subtext strings so that the popup fits in the available 139 // Elide the name and label strings so that the popup fits in the available
140 // space. 140 // space.
141 for (size_t i = 0; i < names_.size(); ++i) { 141 for (size_t i = 0; i < suggestions_.size(); ++i) {
142 int name_width = gfx::GetStringWidth(names_[i], GetNameFontListForRow(i)); 142 int value_width =
143 int subtext_width = gfx::GetStringWidth(subtexts_[i], subtext_font_list()); 143 gfx::GetStringWidth(suggestions_[i].value, GetValueFontListForRow(i));
144 int total_text_length = name_width + subtext_width; 144 int label_width =
145 gfx::GetStringWidth(suggestions_[i].label, GetLabelFontList());
146 int total_text_length = value_width + label_width;
145 147
146 // The line can have no strings if it represents a UI element, such as 148 // The line can have no strings if it represents a UI element, such as
147 // a separator line. 149 // a separator line.
148 if (total_text_length == 0) 150 if (total_text_length == 0)
149 continue; 151 continue;
150 152
151 int available_width = popup_width - RowWidthWithoutText(i); 153 int available_width = popup_width - RowWidthWithoutText(i);
152 154
153 // Each field receives space in proportion to its length. 155 // Each field receives space in proportion to its length.
154 int name_size = available_width * name_width / total_text_length; 156 int value_size = available_width * value_width / total_text_length;
155 names_[i] = gfx::ElideText(names_[i], GetNameFontListForRow(i), 157 elided_values_[i] = gfx::ElideText(suggestions_[i].value,
156 name_size, gfx::ELIDE_TAIL); 158 GetValueFontListForRow(i),
159 value_size, gfx::ELIDE_TAIL);
157 160
158 int subtext_size = available_width * subtext_width / total_text_length; 161 int label_size = available_width * label_width / total_text_length;
159 subtexts_[i] = gfx::ElideText(subtexts_[i], subtext_font_list(), 162 elided_labels_[i] = gfx::ElideText(suggestions_[i].label,
160 subtext_size, gfx::ELIDE_TAIL); 163 GetLabelFontList(),
164 label_size, gfx::ELIDE_TAIL);
161 } 165 }
162 #endif 166 #endif
163 167
164 if (!view_) { 168 if (!view_) {
165 view_ = AutofillPopupView::Create(this); 169 view_ = AutofillPopupView::Create(this);
166 170
167 // It is possible to fail to create the popup, in this case 171 // It is possible to fail to create the popup, in this case
168 // treat the popup as hiding right away. 172 // treat the popup as hiding right away.
169 if (!view_) { 173 if (!view_) {
170 Hide(); 174 Hide();
171 return; 175 return;
172 } 176 }
173 177
174 ShowView(); 178 ShowView();
175 } else { 179 } else {
176 UpdateBoundsAndRedrawPopup(); 180 UpdateBoundsAndRedrawPopup();
177 } 181 }
178 182
179 controller_common_->RegisterKeyPressCallback(); 183 controller_common_->RegisterKeyPressCallback();
180 delegate_->OnPopupShown(); 184 delegate_->OnPopupShown();
181 } 185 }
182 186
183 void AutofillPopupControllerImpl::UpdateDataListValues( 187 void AutofillPopupControllerImpl::UpdateDataListValues(
184 const std::vector<base::string16>& values, 188 const std::vector<base::string16>& values,
185 const std::vector<base::string16>& labels) { 189 const std::vector<base::string16>& labels) {
186 // Remove all the old data list values, which should always be at the top of 190 // Remove all the old data list values, which should always be at the top of
187 // the list if they are present. 191 // the list if they are present.
188 while (!identifiers_.empty() && 192 while (!suggestions_.empty() &&
189 identifiers_[0] == POPUP_ITEM_ID_DATALIST_ENTRY) { 193 suggestions_[0].frontend_id == POPUP_ITEM_ID_DATALIST_ENTRY) {
190 names_.erase(names_.begin()); 194 suggestions_.erase(suggestions_.begin());
191 subtexts_.erase(subtexts_.begin()); 195 elided_values_.erase(elided_values_.begin());
192 icons_.erase(icons_.begin()); 196 elided_labels_.erase(elided_labels_.begin());
193 identifiers_.erase(identifiers_.begin());
194 } 197 }
195 198
196 // If there are no new data list values, exit (clearing the separator if there 199 // If there are no new data list values, exit (clearing the separator if there
197 // is one). 200 // is one).
198 if (values.empty()) { 201 if (values.empty()) {
199 if (!identifiers_.empty() && identifiers_[0] == POPUP_ITEM_ID_SEPARATOR) { 202 if (!suggestions_.empty() &&
200 names_.erase(names_.begin()); 203 suggestions_[0].frontend_id == POPUP_ITEM_ID_SEPARATOR) {
201 subtexts_.erase(subtexts_.begin()); 204 suggestions_.erase(suggestions_.begin());
202 icons_.erase(icons_.begin()); 205 elided_values_.erase(elided_values_.begin());
203 identifiers_.erase(identifiers_.begin()); 206 elided_labels_.erase(elided_labels_.begin());
204 } 207 }
205 208
206 // The popup contents have changed, so either update the bounds or hide it. 209 // The popup contents have changed, so either update the bounds or hide it.
207 if (HasSuggestions()) 210 if (HasSuggestions())
208 UpdateBoundsAndRedrawPopup(); 211 UpdateBoundsAndRedrawPopup();
209 else 212 else
210 Hide(); 213 Hide();
211 214
212 return; 215 return;
213 } 216 }
214 217
215 // Add a separator if there are any other values. 218 // Add a separator if there are any other values.
216 if (!identifiers_.empty() && identifiers_[0] != POPUP_ITEM_ID_SEPARATOR) { 219 if (!suggestions_.empty() &&
217 names_.insert(names_.begin(), base::string16()); 220 suggestions_[0].frontend_id != POPUP_ITEM_ID_SEPARATOR) {
218 subtexts_.insert(subtexts_.begin(), base::string16()); 221 suggestions_.insert(suggestions_.begin(), autofill::Suggestion());
219 icons_.insert(icons_.begin(), base::string16()); 222 suggestions_[0].frontend_id = POPUP_ITEM_ID_SEPARATOR;
220 identifiers_.insert(identifiers_.begin(), POPUP_ITEM_ID_SEPARATOR); 223 elided_values_.insert(elided_values_.begin(), base::string16());
224 elided_labels_.insert(elided_labels_.begin(), base::string16());
221 } 225 }
222 226
223 227 // Prepend the parameters to the suggestions we already have.
224 names_.insert(names_.begin(), values.begin(), values.end()); 228 suggestions_.insert(suggestions_.begin(), values.size(), Suggestion());
225 subtexts_.insert(subtexts_.begin(), labels.begin(), labels.end()); 229 for (size_t i = 0; i < values.size(); i++) {
226 230 suggestions_[i].value = values[i];
227 // Add the values that are the same for all data list elements. 231 suggestions_[i].label = labels[i];
228 icons_.insert(icons_.begin(), values.size(), base::string16()); 232 suggestions_[i].frontend_id = POPUP_ITEM_ID_DATALIST_ENTRY;
229 identifiers_.insert( 233 }
230 identifiers_.begin(), values.size(), POPUP_ITEM_ID_DATALIST_ENTRY);
231 234
232 UpdateBoundsAndRedrawPopup(); 235 UpdateBoundsAndRedrawPopup();
233 } 236 }
234 237
235 void AutofillPopupControllerImpl::Hide() { 238 void AutofillPopupControllerImpl::Hide() {
236 controller_common_->RemoveKeyPressCallback(); 239 controller_common_->RemoveKeyPressCallback();
237 if (delegate_) 240 if (delegate_)
238 delegate_->OnPopupHidden(); 241 delegate_->OnPopupHidden();
239 242
240 if (view_) 243 if (view_)
(...skipping 18 matching lines...) Expand all
259 case ui::VKEY_DOWN: 262 case ui::VKEY_DOWN:
260 SelectNextLine(); 263 SelectNextLine();
261 return true; 264 return true;
262 case ui::VKEY_PRIOR: // Page up. 265 case ui::VKEY_PRIOR: // Page up.
263 // Set no line and then select the next line in case the first line is not 266 // Set no line and then select the next line in case the first line is not
264 // selectable. 267 // selectable.
265 SetSelectedLine(kNoSelection); 268 SetSelectedLine(kNoSelection);
266 SelectNextLine(); 269 SelectNextLine();
267 return true; 270 return true;
268 case ui::VKEY_NEXT: // Page down. 271 case ui::VKEY_NEXT: // Page down.
269 SetSelectedLine(names().size() - 1); 272 SetSelectedLine(GetLineCount() - 1);
270 return true; 273 return true;
271 case ui::VKEY_ESCAPE: 274 case ui::VKEY_ESCAPE:
272 Hide(); 275 Hide();
273 return true; 276 return true;
274 case ui::VKEY_DELETE: 277 case ui::VKEY_DELETE:
275 return (event.modifiers & content::NativeWebKeyboardEvent::ShiftKey) && 278 return (event.modifiers & content::NativeWebKeyboardEvent::ShiftKey) &&
276 RemoveSelectedLine(); 279 RemoveSelectedLine();
277 case ui::VKEY_TAB: 280 case ui::VKEY_TAB:
278 // A tab press should cause the selected line to be accepted, but still 281 // A tab press should cause the selected line to be accepted, but still
279 // return false so the tab key press propagates and changes the cursor 282 // return false so the tab key press propagates and changes the cursor
(...skipping 21 matching lines...) Expand all
301 304
302 void AutofillPopupControllerImpl::SetSelectionAtPoint(const gfx::Point& point) { 305 void AutofillPopupControllerImpl::SetSelectionAtPoint(const gfx::Point& point) {
303 SetSelectedLine(LineFromY(point.y())); 306 SetSelectedLine(LineFromY(point.y()));
304 } 307 }
305 308
306 bool AutofillPopupControllerImpl::AcceptSelectedLine() { 309 bool AutofillPopupControllerImpl::AcceptSelectedLine() {
307 if (selected_line_ == kNoSelection) 310 if (selected_line_ == kNoSelection)
308 return false; 311 return false;
309 312
310 DCHECK_GE(selected_line_, 0); 313 DCHECK_GE(selected_line_, 0);
311 DCHECK_LT(selected_line_, static_cast<int>(names_.size())); 314 DCHECK_LT(selected_line_, static_cast<int>(GetLineCount()));
312 315
313 if (!CanAccept(identifiers_[selected_line_])) 316 if (!CanAccept(suggestions_[selected_line_].frontend_id))
314 return false; 317 return false;
315 318
316 AcceptSuggestion(selected_line_); 319 AcceptSuggestion(selected_line_);
317 return true; 320 return true;
318 } 321 }
319 322
320 void AutofillPopupControllerImpl::SelectionCleared() { 323 void AutofillPopupControllerImpl::SelectionCleared() {
321 SetSelectedLine(kNoSelection); 324 SetSelectedLine(kNoSelection);
322 } 325 }
323 326
324 void AutofillPopupControllerImpl::AcceptSuggestion(size_t index) { 327 void AutofillPopupControllerImpl::AcceptSuggestion(size_t index) {
325 delegate_->DidAcceptSuggestion(full_names_[index], identifiers_[index]); 328 const autofill::Suggestion& suggestion = suggestions_[index];
329 delegate_->DidAcceptSuggestion(suggestion.value, suggestion.frontend_id);
326 } 330 }
327 331
328 int AutofillPopupControllerImpl::GetIconResourceID( 332 int AutofillPopupControllerImpl::GetIconResourceID(
329 const base::string16& resource_name) const { 333 const base::string16& resource_name) const {
330 for (size_t i = 0; i < arraysize(kDataResources); ++i) { 334 for (size_t i = 0; i < arraysize(kDataResources); ++i) {
331 if (resource_name == base::ASCIIToUTF16(kDataResources[i].name)) 335 if (resource_name == base::ASCIIToUTF16(kDataResources[i].name))
332 return kDataResources[i].id; 336 return kDataResources[i].id;
333 } 337 }
334 338
335 return -1; 339 return -1;
336 } 340 }
337 341
338 bool AutofillPopupControllerImpl::CanDelete(size_t index) const { 342 bool AutofillPopupControllerImpl::CanDelete(size_t index) const {
339 // TODO(isherman): Native AddressBook suggestions on Mac and Android should 343 // TODO(isherman): Native AddressBook suggestions on Mac and Android should
340 // not be considered to be deleteable. 344 // not be considered to be deleteable.
341 int id = identifiers_[index]; 345 int id = suggestions_[index].frontend_id;
342 return id > 0 || id == POPUP_ITEM_ID_AUTOCOMPLETE_ENTRY || 346 return id > 0 || id == POPUP_ITEM_ID_AUTOCOMPLETE_ENTRY ||
343 id == POPUP_ITEM_ID_PASSWORD_ENTRY; 347 id == POPUP_ITEM_ID_PASSWORD_ENTRY;
344 } 348 }
345 349
346 bool AutofillPopupControllerImpl::IsWarning(size_t index) const { 350 bool AutofillPopupControllerImpl::IsWarning(size_t index) const {
347 return identifiers_[index] == POPUP_ITEM_ID_WARNING_MESSAGE; 351 return suggestions_[index].frontend_id == POPUP_ITEM_ID_WARNING_MESSAGE;
348 } 352 }
349 353
350 gfx::Rect AutofillPopupControllerImpl::GetRowBounds(size_t index) { 354 gfx::Rect AutofillPopupControllerImpl::GetRowBounds(size_t index) {
351 int top = kPopupBorderThickness; 355 int top = kPopupBorderThickness;
352 for (size_t i = 0; i < index; ++i) { 356 for (size_t i = 0; i < index; ++i) {
353 top += GetRowHeightFromId(identifiers()[i]); 357 top += GetRowHeightFromId(suggestions_[i].frontend_id);
354 } 358 }
355 359
356 return gfx::Rect( 360 return gfx::Rect(
357 kPopupBorderThickness, 361 kPopupBorderThickness,
358 top, 362 top,
359 popup_bounds_.width() - 2 * kPopupBorderThickness, 363 popup_bounds_.width() - 2 * kPopupBorderThickness,
360 GetRowHeightFromId(identifiers()[index])); 364 GetRowHeightFromId(suggestions_[index].frontend_id));
361 } 365 }
362 366
363 void AutofillPopupControllerImpl::SetPopupBounds(const gfx::Rect& bounds) { 367 void AutofillPopupControllerImpl::SetPopupBounds(const gfx::Rect& bounds) {
364 popup_bounds_ = bounds; 368 popup_bounds_ = bounds;
365 UpdateBoundsAndRedrawPopup(); 369 UpdateBoundsAndRedrawPopup();
366 } 370 }
367 371
368 const gfx::Rect& AutofillPopupControllerImpl::popup_bounds() const { 372 const gfx::Rect& AutofillPopupControllerImpl::popup_bounds() const {
369 return popup_bounds_; 373 return popup_bounds_;
370 } 374 }
371 375
372 content::WebContents* AutofillPopupControllerImpl::web_contents() { 376 content::WebContents* AutofillPopupControllerImpl::web_contents() {
373 return controller_common_->web_contents(); 377 return controller_common_->web_contents();
374 } 378 }
375 379
376 gfx::NativeView AutofillPopupControllerImpl::container_view() { 380 gfx::NativeView AutofillPopupControllerImpl::container_view() {
377 return controller_common_->container_view(); 381 return controller_common_->container_view();
378 } 382 }
379 383
380 const gfx::RectF& AutofillPopupControllerImpl::element_bounds() const { 384 const gfx::RectF& AutofillPopupControllerImpl::element_bounds() const {
381 return controller_common_->element_bounds(); 385 return controller_common_->element_bounds();
382 } 386 }
383 387
384 bool AutofillPopupControllerImpl::IsRTL() const { 388 bool AutofillPopupControllerImpl::IsRTL() const {
385 return text_direction_ == base::i18n::RIGHT_TO_LEFT; 389 return text_direction_ == base::i18n::RIGHT_TO_LEFT;
386 } 390 }
387 391
388 const std::vector<base::string16>& AutofillPopupControllerImpl::names() const { 392 size_t AutofillPopupControllerImpl::GetLineCount() const {
389 return names_; 393 return suggestions_.size();
390 } 394 }
391 395
392 const std::vector<base::string16>& AutofillPopupControllerImpl::subtexts() 396 const autofill::Suggestion& AutofillPopupControllerImpl::GetSuggestionAt(
393 const { 397 size_t row) const {
394 return subtexts_; 398 return suggestions_[row];
395 } 399 }
396 400
397 const std::vector<base::string16>& AutofillPopupControllerImpl::icons() const { 401 const base::string16& AutofillPopupControllerImpl::GetElidedValueAt(
398 return icons_; 402 size_t row) const {
403 return elided_values_[row];
399 } 404 }
400 405
401 const std::vector<int>& AutofillPopupControllerImpl::identifiers() const { 406 const base::string16& AutofillPopupControllerImpl::GetElidedLabelAt(
402 return identifiers_; 407 size_t row) const {
408 return elided_labels_[row];
403 } 409 }
404 410
405 #if !defined(OS_ANDROID) 411 #if !defined(OS_ANDROID)
406 const gfx::FontList& AutofillPopupControllerImpl::GetNameFontListForRow( 412 const gfx::FontList& AutofillPopupControllerImpl::GetValueFontListForRow(
407 size_t index) const { 413 size_t index) const {
408 if (identifiers_[index] == POPUP_ITEM_ID_WARNING_MESSAGE) 414 if (suggestions_[index].frontend_id == POPUP_ITEM_ID_WARNING_MESSAGE)
409 return warning_font_list_; 415 return warning_font_list_;
410 416
411 if (identifiers_[index] == POPUP_ITEM_ID_TITLE) 417 if (suggestions_[index].frontend_id == POPUP_ITEM_ID_TITLE)
412 return title_font_list_; 418 return title_font_list_;
413 419
414 return name_font_list_; 420 return value_font_list_;
415 } 421 }
416 422
417 const gfx::FontList& AutofillPopupControllerImpl::subtext_font_list() const { 423 const gfx::FontList& AutofillPopupControllerImpl::GetLabelFontList() const {
418 return subtext_font_list_; 424 return label_font_list_;
419 } 425 }
420 #endif 426 #endif
421 427
422 int AutofillPopupControllerImpl::selected_line() const { 428 int AutofillPopupControllerImpl::selected_line() const {
423 return selected_line_; 429 return selected_line_;
424 } 430 }
425 431
426 void AutofillPopupControllerImpl::SetSelectedLine(int selected_line) { 432 void AutofillPopupControllerImpl::SetSelectedLine(int selected_line) {
427 if (selected_line_ == selected_line) 433 if (selected_line_ == selected_line)
428 return; 434 return;
429 435
430 if (selected_line_ != kNoSelection && 436 if (selected_line_ != kNoSelection &&
431 static_cast<size_t>(selected_line_) < identifiers_.size()) 437 static_cast<size_t>(selected_line_) < suggestions_.size())
432 InvalidateRow(selected_line_); 438 InvalidateRow(selected_line_);
433 439
434 if (selected_line != kNoSelection) { 440 if (selected_line != kNoSelection) {
435 InvalidateRow(selected_line); 441 InvalidateRow(selected_line);
436 442
437 if (!CanAccept(identifiers_[selected_line])) 443 if (!CanAccept(suggestions_[selected_line].frontend_id))
438 selected_line = kNoSelection; 444 selected_line = kNoSelection;
439 } 445 }
440 446
441 selected_line_ = selected_line; 447 selected_line_ = selected_line;
442 448
443 if (selected_line_ != kNoSelection) { 449 if (selected_line_ != kNoSelection) {
444 delegate_->DidSelectSuggestion(names_[selected_line_], 450 delegate_->DidSelectSuggestion(elided_values_[selected_line_],
445 identifiers_[selected_line_]); 451 suggestions_[selected_line_].frontend_id);
446 } else { 452 } else {
447 delegate_->ClearPreviewedForm(); 453 delegate_->ClearPreviewedForm();
448 } 454 }
449 } 455 }
450 456
451 void AutofillPopupControllerImpl::SelectNextLine() { 457 void AutofillPopupControllerImpl::SelectNextLine() {
452 int new_selected_line = selected_line_ + 1; 458 int new_selected_line = selected_line_ + 1;
453 459
454 // Skip over any lines that can't be selected. 460 // Skip over any lines that can't be selected.
455 while (static_cast<size_t>(new_selected_line) < names_.size() && 461 while (static_cast<size_t>(new_selected_line) < GetLineCount() &&
456 !CanAccept(identifiers()[new_selected_line])) { 462 !CanAccept(suggestions_[new_selected_line].frontend_id)) {
457 ++new_selected_line; 463 ++new_selected_line;
458 } 464 }
459 465
460 if (new_selected_line >= static_cast<int>(names_.size())) 466 if (new_selected_line >= static_cast<int>(GetLineCount()))
461 new_selected_line = 0; 467 new_selected_line = 0;
462 468
463 SetSelectedLine(new_selected_line); 469 SetSelectedLine(new_selected_line);
464 } 470 }
465 471
466 void AutofillPopupControllerImpl::SelectPreviousLine() { 472 void AutofillPopupControllerImpl::SelectPreviousLine() {
467 int new_selected_line = selected_line_ - 1; 473 int new_selected_line = selected_line_ - 1;
468 474
469 // Skip over any lines that can't be selected. 475 // Skip over any lines that can't be selected.
470 while (new_selected_line > kNoSelection && 476 while (new_selected_line > kNoSelection &&
471 !CanAccept(identifiers()[new_selected_line])) { 477 !CanAccept(GetSuggestionAt(new_selected_line).frontend_id)) {
472 --new_selected_line; 478 --new_selected_line;
473 } 479 }
474 480
475 if (new_selected_line <= kNoSelection) 481 if (new_selected_line <= kNoSelection)
476 new_selected_line = names_.size() - 1; 482 new_selected_line = GetLineCount() - 1;
477 483
478 SetSelectedLine(new_selected_line); 484 SetSelectedLine(new_selected_line);
479 } 485 }
480 486
481 bool AutofillPopupControllerImpl::RemoveSelectedLine() { 487 bool AutofillPopupControllerImpl::RemoveSelectedLine() {
482 if (selected_line_ == kNoSelection) 488 if (selected_line_ == kNoSelection)
483 return false; 489 return false;
484 490
485 DCHECK_GE(selected_line_, 0); 491 DCHECK_GE(selected_line_, 0);
486 DCHECK_LT(selected_line_, static_cast<int>(names_.size())); 492 DCHECK_LT(selected_line_, static_cast<int>(GetLineCount()));
487 493
488 if (!CanDelete(selected_line_)) 494 if (!CanDelete(selected_line_))
489 return false; 495 return false;
490 496
491 delegate_->RemoveSuggestion(full_names_[selected_line_], 497 delegate_->RemoveSuggestion(suggestions_[selected_line_].value,
492 identifiers_[selected_line_]); 498 suggestions_[selected_line_].frontend_id);
493 499
494 // Remove the deleted element. 500 // Remove the deleted element.
495 names_.erase(names_.begin() + selected_line_); 501 suggestions_.erase(suggestions_.begin() + selected_line_);
496 full_names_.erase(full_names_.begin() + selected_line_); 502 elided_values_.erase(elided_values_.begin() + selected_line_);
497 subtexts_.erase(subtexts_.begin() + selected_line_); 503 elided_labels_.erase(elided_labels_.begin() + selected_line_);
498 icons_.erase(icons_.begin() + selected_line_);
499 identifiers_.erase(identifiers_.begin() + selected_line_);
500 504
501 SetSelectedLine(kNoSelection); 505 SetSelectedLine(kNoSelection);
502 506
503 if (HasSuggestions()) { 507 if (HasSuggestions()) {
504 delegate_->ClearPreviewedForm(); 508 delegate_->ClearPreviewedForm();
505 UpdateBoundsAndRedrawPopup(); 509 UpdateBoundsAndRedrawPopup();
506 } else { 510 } else {
507 Hide(); 511 Hide();
508 } 512 }
509 513
510 return true; 514 return true;
511 } 515 }
512 516
513 int AutofillPopupControllerImpl::LineFromY(int y) { 517 int AutofillPopupControllerImpl::LineFromY(int y) {
514 int current_height = kPopupBorderThickness; 518 int current_height = kPopupBorderThickness;
515 519
516 for (size_t i = 0; i < identifiers().size(); ++i) { 520 for (size_t i = 0; i < suggestions_.size(); ++i) {
517 current_height += GetRowHeightFromId(identifiers()[i]); 521 current_height += GetRowHeightFromId(suggestions_[i].frontend_id);
518 522
519 if (y <= current_height) 523 if (y <= current_height)
520 return i; 524 return i;
521 } 525 }
522 526
523 // The y value goes beyond the popup so stop the selection at the last line. 527 // The y value goes beyond the popup so stop the selection at the last line.
524 return identifiers().size() - 1; 528 return GetLineCount() - 1;
525 } 529 }
526 530
527 int AutofillPopupControllerImpl::GetRowHeightFromId(int identifier) const { 531 int AutofillPopupControllerImpl::GetRowHeightFromId(int identifier) const {
528 if (identifier == POPUP_ITEM_ID_SEPARATOR) 532 if (identifier == POPUP_ITEM_ID_SEPARATOR)
529 return kSeparatorHeight; 533 return kSeparatorHeight;
530 534
531 return kRowHeight; 535 return kRowHeight;
532 } 536 }
533 537
534 bool AutofillPopupControllerImpl::CanAccept(int id) { 538 bool AutofillPopupControllerImpl::CanAccept(int id) {
535 return id != POPUP_ITEM_ID_SEPARATOR && id != POPUP_ITEM_ID_WARNING_MESSAGE && 539 return id != POPUP_ITEM_ID_SEPARATOR && id != POPUP_ITEM_ID_WARNING_MESSAGE &&
536 id != POPUP_ITEM_ID_TITLE; 540 id != POPUP_ITEM_ID_TITLE;
537 } 541 }
538 542
539 bool AutofillPopupControllerImpl::HasSuggestions() { 543 bool AutofillPopupControllerImpl::HasSuggestions() {
540 return identifiers_.size() != 0 && 544 if (suggestions_.empty())
541 (identifiers_[0] > 0 || 545 return false;
542 identifiers_[0] == POPUP_ITEM_ID_AUTOCOMPLETE_ENTRY || 546 int id = suggestions_[0].frontend_id;
543 identifiers_[0] == POPUP_ITEM_ID_PASSWORD_ENTRY || 547 return id > 0 ||
544 identifiers_[0] == POPUP_ITEM_ID_DATALIST_ENTRY || 548 id == POPUP_ITEM_ID_AUTOCOMPLETE_ENTRY ||
545 identifiers_[0] == POPUP_ITEM_ID_MAC_ACCESS_CONTACTS); 549 id == POPUP_ITEM_ID_PASSWORD_ENTRY ||
550 id == POPUP_ITEM_ID_DATALIST_ENTRY ||
551 id == POPUP_ITEM_ID_MAC_ACCESS_CONTACTS;
546 } 552 }
547 553
548 void AutofillPopupControllerImpl::SetValues( 554 void AutofillPopupControllerImpl::SetValues(
549 const std::vector<base::string16>& names, 555 const std::vector<autofill::Suggestion>& suggestions) {
550 const std::vector<base::string16>& subtexts, 556 suggestions_ = suggestions;
551 const std::vector<base::string16>& icons, 557 elided_values_.resize(suggestions.size());
552 const std::vector<int>& identifiers) { 558 elided_labels_.resize(suggestions.size());
553 names_ = names; 559 for (size_t i = 0; i < suggestions.size(); i++) {
554 full_names_ = names; 560 elided_values_[i] = suggestions[i].value;
555 subtexts_ = subtexts; 561 elided_labels_[i] = suggestions[i].label;
556 icons_ = icons; 562 }
557 identifiers_ = identifiers;
558 } 563 }
559 564
560 void AutofillPopupControllerImpl::ShowView() { 565 void AutofillPopupControllerImpl::ShowView() {
561 view_->Show(); 566 view_->Show();
562 } 567 }
563 568
564 void AutofillPopupControllerImpl::InvalidateRow(size_t row) { 569 void AutofillPopupControllerImpl::InvalidateRow(size_t row) {
565 DCHECK(0 <= row); 570 DCHECK(0 <= row);
566 DCHECK(row < identifiers_.size()); 571 DCHECK(row < suggestions_.size());
567 view_->InvalidateRow(row); 572 view_->InvalidateRow(row);
568 } 573 }
569 574
570 #if !defined(OS_ANDROID) 575 #if !defined(OS_ANDROID)
571 int AutofillPopupControllerImpl::GetDesiredPopupWidth() const { 576 int AutofillPopupControllerImpl::GetDesiredPopupWidth() const {
572 int popup_width = controller_common_->RoundedElementBounds().width(); 577 int popup_width = controller_common_->RoundedElementBounds().width();
573 DCHECK_EQ(names().size(), subtexts().size()); 578 for (size_t i = 0; i < GetLineCount(); ++i) {
574 for (size_t i = 0; i < names().size(); ++i) {
575 int row_size = 579 int row_size =
576 gfx::GetStringWidth(names()[i], name_font_list_) + 580 gfx::GetStringWidth(GetElidedValueAt(i), value_font_list_) +
577 gfx::GetStringWidth(subtexts()[i], subtext_font_list_) + 581 gfx::GetStringWidth(GetElidedLabelAt(i), label_font_list_) +
578 RowWidthWithoutText(i); 582 RowWidthWithoutText(i);
579 583
580 popup_width = std::max(popup_width, row_size); 584 popup_width = std::max(popup_width, row_size);
581 } 585 }
582 586
583 return popup_width; 587 return popup_width;
584 } 588 }
585 589
586 int AutofillPopupControllerImpl::GetDesiredPopupHeight() const { 590 int AutofillPopupControllerImpl::GetDesiredPopupHeight() const {
587 int popup_height = 2 * kPopupBorderThickness; 591 int popup_height = 2 * kPopupBorderThickness;
588 592
589 for (size_t i = 0; i < identifiers().size(); ++i) { 593 for (size_t i = 0; i < suggestions_.size(); ++i) {
590 popup_height += GetRowHeightFromId(identifiers()[i]); 594 popup_height += GetRowHeightFromId(suggestions_[i].frontend_id);
591 } 595 }
592 596
593 return popup_height; 597 return popup_height;
594 } 598 }
595 599
596 int AutofillPopupControllerImpl::RowWidthWithoutText(int row) const { 600 int AutofillPopupControllerImpl::RowWidthWithoutText(int row) const {
597 int row_size = kEndPadding; 601 int row_size = kEndPadding;
598 602
599 if (!subtexts_[row].empty()) 603 if (!elided_labels_[row].empty())
600 row_size += kNamePadding; 604 row_size += kNamePadding;
601 605
602 // Add the Autofill icon size, if required. 606 // Add the Autofill icon size, if required.
603 if (!icons_[row].empty()) { 607 const base::string16& icon = suggestions_[row].icon;
608 if (!icon.empty()) {
604 int icon_width = ui::ResourceBundle::GetSharedInstance().GetImageNamed( 609 int icon_width = ui::ResourceBundle::GetSharedInstance().GetImageNamed(
605 GetIconResourceID(icons_[row])).Width(); 610 GetIconResourceID(icon)).Width();
606 row_size += icon_width + kIconPadding; 611 row_size += icon_width + kIconPadding;
607 } 612 }
608 613
609 // Add the padding at the end. 614 // Add the padding at the end.
610 row_size += kEndPadding; 615 row_size += kEndPadding;
611 616
612 // Add room for the popup border. 617 // Add room for the popup border.
613 row_size += 2 * kPopupBorderThickness; 618 row_size += 2 * kPopupBorderThickness;
614 619
615 return row_size; 620 return row_size;
616 } 621 }
617 622
618 void AutofillPopupControllerImpl::UpdatePopupBounds() { 623 void AutofillPopupControllerImpl::UpdatePopupBounds() {
619 int popup_width = GetDesiredPopupWidth(); 624 int popup_width = GetDesiredPopupWidth();
620 int popup_height = GetDesiredPopupHeight(); 625 int popup_height = GetDesiredPopupHeight();
621 626
622 popup_bounds_ = controller_common_->GetPopupBounds(popup_width, 627 popup_bounds_ = controller_common_->GetPopupBounds(popup_width, popup_height);
623 popup_height);
624 } 628 }
625 #endif // !defined(OS_ANDROID) 629 #endif // !defined(OS_ANDROID)
626 630
627 WeakPtr<AutofillPopupControllerImpl> AutofillPopupControllerImpl::GetWeakPtr() { 631 WeakPtr<AutofillPopupControllerImpl> AutofillPopupControllerImpl::GetWeakPtr() {
628 return weak_ptr_factory_.GetWeakPtr(); 632 return weak_ptr_factory_.GetWeakPtr();
629 } 633 }
630 634
631 void AutofillPopupControllerImpl::ClearState() { 635 void AutofillPopupControllerImpl::ClearState() {
632 // Don't clear view_, because otherwise the popup will have to get regenerated 636 // Don't clear view_, because otherwise the popup will have to get regenerated
633 // and this will cause flickering. 637 // and this will cause flickering.
634 638
635 popup_bounds_ = gfx::Rect(); 639 popup_bounds_ = gfx::Rect();
636 640
637 names_.clear(); 641 suggestions_.clear();
638 subtexts_.clear(); 642 elided_values_.clear();
639 icons_.clear(); 643 elided_labels_.clear();
640 identifiers_.clear();
641 full_names_.clear();
642 644
643 selected_line_ = kNoSelection; 645 selected_line_ = kNoSelection;
644 } 646 }
645 647
646 } // namespace autofill 648 } // namespace autofill
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698