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

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

Powered by Google App Engine
This is Rietveld 408576698