 Chromium Code Reviews
 Chromium Code Reviews Issue 10037002:
  Datalist UI (WebKit part)  (Closed) 
  Base URL: http://svn.webkit.org/repository/webkit/trunk
    
  
    Issue 10037002:
  Datalist UI (WebKit part)  (Closed) 
  Base URL: http://svn.webkit.org/repository/webkit/trunk| OLD | NEW | 
|---|---|
| 1 /* | 1 /* | 
| 2 * Copyright (C) 2011 Google Inc. All rights reserved. | 2 * Copyright (C) 2011 Google Inc. All rights reserved. | 
| 3 * | 3 * | 
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without | 
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are | 
| 6 * met: | 6 * met: | 
| 7 * | 7 * | 
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright | 
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. | 
| 10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above | 
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 45 #include "WebViewClient.h" | 45 #include "WebViewClient.h" | 
| 46 #include "WebViewImpl.h" | 46 #include "WebViewImpl.h" | 
| 47 #include "platform/WebString.h" | 47 #include "platform/WebString.h" | 
| 48 #include "platform/WebVector.h" | 48 #include "platform/WebVector.h" | 
| 49 | 49 | 
| 50 using namespace WebCore; | 50 using namespace WebCore; | 
| 51 | 51 | 
| 52 namespace WebKit { | 52 namespace WebKit { | 
| 53 | 53 | 
| 54 AutofillPopupMenuClient::AutofillPopupMenuClient() | 54 AutofillPopupMenuClient::AutofillPopupMenuClient() | 
| 55 : m_separatorIndex(-1) | 55 : m_textField(0) | 
| 56 , m_selectedIndex(-1) | |
| 
Ilya Sherman
2012/04/11 00:27:52
nit: We should still initialize m_selectedIndex.
 
keishi
2012/04/11 12:13:12
Done.
 | |
| 57 , m_textField(0) | |
| 58 { | 56 { | 
| 59 } | 57 } | 
| 60 | 58 | 
| 61 AutofillPopupMenuClient::~AutofillPopupMenuClient() | 59 AutofillPopupMenuClient::~AutofillPopupMenuClient() | 
| 62 { | 60 { | 
| 63 } | 61 } | 
| 64 | 62 | 
| 65 unsigned AutofillPopupMenuClient::getSuggestionsCount() const | 63 unsigned AutofillPopupMenuClient::getSuggestionsCount() const | 
| 66 { | 64 { | 
| 67 return m_names.size() + ((m_separatorIndex == -1) ? 0 : 1); | 65 return m_names.size(); | 
| 68 } | 66 } | 
| 69 | 67 | 
| 70 WebString AutofillPopupMenuClient::getSuggestion(unsigned listIndex) const | 68 WebString AutofillPopupMenuClient::getSuggestion(unsigned listIndex) const | 
| 71 { | 69 { | 
| 72 int index = convertListIndexToInternalIndex(listIndex); | 70 ASSERT(listIndex >= 0 && static_cast<size_t>(listIndex) < m_names.size()); | 
| 
Ilya Sherman
2012/04/11 00:27:52
nit: No need to check nonnegativity nor to cast --
 
keishi
2012/04/11 12:13:12
Done.
 | |
| 73 if (index == -1) | 71 return m_names[listIndex]; | 
| 74 return WebString(); | |
| 75 | |
| 76 ASSERT(index >= 0 && static_cast<size_t>(index) < m_names.size()); | |
| 77 return m_names[index]; | |
| 78 } | 72 } | 
| 79 | 73 | 
| 80 WebString AutofillPopupMenuClient::getLabel(unsigned listIndex) const | 74 WebString AutofillPopupMenuClient::getLabel(unsigned listIndex) const | 
| 81 { | 75 { | 
| 82 int index = convertListIndexToInternalIndex(listIndex); | 76 ASSERT(listIndex >= 0 && static_cast<size_t>(listIndex) < m_labels.size()); | 
| 
Ilya Sherman
2012/04/11 00:27:52
nit: Ditto
 
keishi
2012/04/11 12:13:12
Done.
 | |
| 83 if (index == -1) | 77 return m_labels[listIndex]; | 
| 84 return WebString(); | |
| 85 | |
| 86 ASSERT(index >= 0 && static_cast<size_t>(index) < m_labels.size()); | |
| 87 return m_labels[index]; | |
| 88 } | 78 } | 
| 89 | 79 | 
| 90 WebString AutofillPopupMenuClient::getIcon(unsigned listIndex) const | 80 WebString AutofillPopupMenuClient::getIcon(unsigned listIndex) const | 
| 91 { | 81 { | 
| 92 int index = convertListIndexToInternalIndex(listIndex); | 82 ASSERT(listIndex >= 0 && static_cast<size_t>(listIndex) < m_icons.size()); | 
| 
Ilya Sherman
2012/04/11 00:27:52
nit: Ditto
 
keishi
2012/04/11 12:13:12
Done.
 | |
| 93 if (index == -1) | 83 return m_icons[listIndex]; | 
| 94 return WebString(); | |
| 95 | |
| 96 ASSERT(index >= 0 && static_cast<size_t>(index) < m_icons.size()); | |
| 97 return m_icons[index]; | |
| 98 } | 84 } | 
| 99 | 85 | 
| 100 void AutofillPopupMenuClient::removeSuggestionAtIndex(unsigned listIndex) | 86 void AutofillPopupMenuClient::removeSuggestionAtIndex(unsigned listIndex) | 
| 101 { | 87 { | 
| 102 if (!canRemoveSuggestionAtIndex(listIndex)) | 88 if (!canRemoveSuggestionAtIndex(listIndex)) | 
| 103 return; | 89 return; | 
| 104 | 90 | 
| 105 int index = convertListIndexToInternalIndex(listIndex); | 91 ASSERT(static_cast<unsigned>(listIndex) < m_names.size()); | 
| 
Ilya Sherman
2012/04/11 00:27:52
nit: No need to cast, the listIndex is already uns
 
keishi
2012/04/11 12:13:12
Done.
 | |
| 106 | 92 | 
| 107 ASSERT(static_cast<unsigned>(index) < m_names.size()); | 93 m_names.remove(listIndex); | 
| 108 | 94 m_labels.remove(listIndex); | 
| 109 m_names.remove(index); | 95 m_icons.remove(listIndex); | 
| 110 m_labels.remove(index); | 96 m_itemIDs.remove(listIndex); | 
| 111 m_icons.remove(index); | |
| 112 m_uniqueIDs.remove(index); | |
| 113 | |
| 114 // Shift the separator index if necessary. | |
| 115 if (m_separatorIndex != -1) | |
| 116 m_separatorIndex--; | |
| 117 } | 97 } | 
| 118 | 98 | 
| 119 bool AutofillPopupMenuClient::canRemoveSuggestionAtIndex(unsigned listIndex) | 99 bool AutofillPopupMenuClient::canRemoveSuggestionAtIndex(unsigned listIndex) | 
| 120 { | 100 { | 
| 121 // Only allow deletion of items before the separator that have unique id 0 | 101 return m_itemIDs[listIndex] > 0 || // Is autofill entry? | 
| 
Ilya Sherman
2012/04/11 00:27:52
It's not currently possible to remove Autofill ent
 
keishi
2012/04/11 12:13:12
Done. I'll match the current behavior.
 | |
| 122 // (i.e. are autocomplete rather than autofill items). | 102 m_itemIDs[listIndex] == AutocompleteEntryMenuItemID || | 
| 123 int index = convertListIndexToInternalIndex(listIndex); | 103 m_itemIDs[listIndex] == PasswordEntryMenuItemID; | 
| 124 return !m_uniqueIDs[index] && (m_separatorIndex == -1 || listIndex < static_ cast<unsigned>(m_separatorIndex)); | |
| 125 } | 104 } | 
| 126 | 105 | 
| 127 void AutofillPopupMenuClient::valueChanged(unsigned listIndex, bool fireEvents) | 106 void AutofillPopupMenuClient::valueChanged(unsigned listIndex, bool fireEvents) | 
| 128 { | 107 { | 
| 129 WebViewImpl* webView = getWebView(); | 108 WebViewImpl* webView = getWebView(); | 
| 130 if (!webView) | 109 if (!webView) | 
| 131 return; | 110 return; | 
| 132 | 111 | 
| 133 if (m_separatorIndex != -1 && listIndex > static_cast<unsigned>(m_separatorI ndex)) | |
| 134 --listIndex; | |
| 135 | |
| 136 ASSERT(listIndex < m_names.size()); | 112 ASSERT(listIndex < m_names.size()); | 
| 137 | 113 | 
| 138 webView->autofillClient()->didAcceptAutofillSuggestion(WebNode(getTextField( )), | 114 webView->autofillClient()->didAcceptAutofillSuggestion(WebNode(getTextField( )), | 
| 139 m_names[listIndex], | 115 m_names[listIndex], | 
| 140 m_labels[listIndex], | 116 m_labels[listIndex], | 
| 141 m_uniqueIDs[listIndex ], | 117 m_itemIDs[listIndex], | 
| 142 listIndex); | 118 listIndex); | 
| 143 } | 119 } | 
| 144 | 120 | 
| 145 void AutofillPopupMenuClient::selectionChanged(unsigned listIndex, bool fireEven ts) | 121 void AutofillPopupMenuClient::selectionChanged(unsigned listIndex, bool fireEven ts) | 
| 146 { | 122 { | 
| 147 WebViewImpl* webView = getWebView(); | 123 WebViewImpl* webView = getWebView(); | 
| 148 if (!webView) | 124 if (!webView) | 
| 149 return; | 125 return; | 
| 150 | 126 | 
| 151 if (m_separatorIndex != -1 && listIndex > static_cast<unsigned>(m_separatorI ndex)) | |
| 152 --listIndex; | |
| 153 | |
| 154 ASSERT(listIndex < m_names.size()); | 127 ASSERT(listIndex < m_names.size()); | 
| 155 | 128 | 
| 156 webView->autofillClient()->didSelectAutofillSuggestion(WebNode(getTextField( )), | 129 webView->autofillClient()->didSelectAutofillSuggestion(WebNode(getTextField( )), | 
| 157 m_names[listIndex], | 130 m_names[listIndex], | 
| 158 m_labels[listIndex], | 131 m_labels[listIndex], | 
| 159 m_uniqueIDs[listIndex ]); | 132 m_itemIDs[listIndex]) ; | 
| 160 } | 133 } | 
| 161 | 134 | 
| 162 void AutofillPopupMenuClient::selectionCleared() | 135 void AutofillPopupMenuClient::selectionCleared() | 
| 163 { | 136 { | 
| 164 WebViewImpl* webView = getWebView(); | 137 WebViewImpl* webView = getWebView(); | 
| 165 if (webView) | 138 if (webView) | 
| 166 webView->autofillClient()->didClearAutofillSelection(WebNode(getTextFiel d())); | 139 webView->autofillClient()->didClearAutofillSelection(WebNode(getTextFiel d())); | 
| 167 } | 140 } | 
| 168 | 141 | 
| 169 String AutofillPopupMenuClient::itemText(unsigned listIndex) const | 142 String AutofillPopupMenuClient::itemText(unsigned listIndex) const | 
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 221 WebViewImpl* webView = getWebView(); | 194 WebViewImpl* webView = getWebView(); | 
| 222 if (!webView) | 195 if (!webView) | 
| 223 return; | 196 return; | 
| 224 | 197 | 
| 225 webView->autofillPopupDidHide(); | 198 webView->autofillPopupDidHide(); | 
| 226 webView->autofillClient()->didClearAutofillSelection(WebNode(getTextField()) ); | 199 webView->autofillClient()->didClearAutofillSelection(WebNode(getTextField()) ); | 
| 227 } | 200 } | 
| 228 | 201 | 
| 229 bool AutofillPopupMenuClient::itemIsSeparator(unsigned listIndex) const | 202 bool AutofillPopupMenuClient::itemIsSeparator(unsigned listIndex) const | 
| 230 { | 203 { | 
| 231 return (m_separatorIndex != -1 && static_cast<unsigned>(m_separatorIndex) == listIndex); | 204 return m_itemIDs[listIndex] == SeparatorMenuItemID; | 
| 232 } | 205 } | 
| 233 | 206 | 
| 234 bool AutofillPopupMenuClient::itemIsWarning(unsigned listIndex) const | 207 bool AutofillPopupMenuClient::itemIsWarning(unsigned listIndex) const | 
| 235 { | 208 { | 
| 236 int index = convertListIndexToInternalIndex(listIndex); | 209 return m_itemIDs[listIndex] == WarningMessageMenuItemID; | 
| 237 if (index == -1) | |
| 238 return false; | |
| 239 | |
| 240 ASSERT(index >= 0 && static_cast<size_t>(index) < m_uniqueIDs.size()); | |
| 241 return m_uniqueIDs[index] < 0; | |
| 242 } | 210 } | 
| 243 | 211 | 
| 244 void AutofillPopupMenuClient::setTextFromItem(unsigned listIndex) | 212 void AutofillPopupMenuClient::setTextFromItem(unsigned listIndex) | 
| 245 { | 213 { | 
| 246 m_textField->setValue(getSuggestion(listIndex)); | 214 m_textField->setValue(getSuggestion(listIndex)); | 
| 247 } | 215 } | 
| 248 | 216 | 
| 249 FontSelector* AutofillPopupMenuClient::fontSelector() const | 217 FontSelector* AutofillPopupMenuClient::fontSelector() const | 
| 250 { | 218 { | 
| 251 return m_textField->document()->styleSelector()->fontSelector(); | 219 return m_textField->document()->styleSelector()->fontSelector(); | 
| (...skipping 10 matching lines...) Expand all Loading... | |
| 262 ScrollbarControlSize size) | 230 ScrollbarControlSize size) | 
| 263 { | 231 { | 
| 264 return Scrollbar::createNativeScrollbar(scrollableArea, orientation, size); | 232 return Scrollbar::createNativeScrollbar(scrollableArea, orientation, size); | 
| 265 } | 233 } | 
| 266 | 234 | 
| 267 void AutofillPopupMenuClient::initialize( | 235 void AutofillPopupMenuClient::initialize( | 
| 268 HTMLInputElement* textField, | 236 HTMLInputElement* textField, | 
| 269 const WebVector<WebString>& names, | 237 const WebVector<WebString>& names, | 
| 270 const WebVector<WebString>& labels, | 238 const WebVector<WebString>& labels, | 
| 271 const WebVector<WebString>& icons, | 239 const WebVector<WebString>& icons, | 
| 272 const WebVector<int>& uniqueIDs, | 240 const WebVector<int>& itemIDs) | 
| 273 int separatorIndex) | |
| 274 { | 241 { | 
| 275 ASSERT(names.size() == labels.size()); | 242 ASSERT(names.size() == labels.size()); | 
| 276 ASSERT(names.size() == icons.size()); | 243 ASSERT(names.size() == icons.size()); | 
| 277 ASSERT(names.size() == uniqueIDs.size()); | 244 ASSERT(names.size() == itemIDs.size()); | 
| 278 ASSERT(separatorIndex < static_cast<int>(names.size())); | |
| 279 | 245 | 
| 280 m_selectedIndex = -1; | 246 m_selectedIndex = -1; | 
| 281 m_textField = textField; | 247 m_textField = textField; | 
| 282 | 248 | 
| 283 // The suggestions must be set before initializing the | 249 // The suggestions must be set before initializing the | 
| 284 // AutofillPopupMenuClient. | 250 // AutofillPopupMenuClient. | 
| 285 setSuggestions(names, labels, icons, uniqueIDs, separatorIndex); | 251 setSuggestions(names, labels, icons, itemIDs); | 
| 286 | 252 | 
| 287 FontDescription regularFontDescription; | 253 FontDescription regularFontDescription; | 
| 288 RenderTheme::defaultTheme()->systemFont(CSSValueWebkitControl, | 254 RenderTheme::defaultTheme()->systemFont(CSSValueWebkitControl, | 
| 289 regularFontDescription); | 255 regularFontDescription); | 
| 290 RenderStyle* style = m_textField->computedStyle(); | 256 RenderStyle* style = m_textField->computedStyle(); | 
| 291 regularFontDescription.setComputedSize(style->fontDescription().computedSize ()); | 257 regularFontDescription.setComputedSize(style->fontDescription().computedSize ()); | 
| 292 | 258 | 
| 293 Font regularFont(regularFontDescription, 0, 0); | 259 Font regularFont(regularFontDescription, 0, 0); | 
| 294 regularFont.update(textField->document()->styleSelector()->fontSelector()); | 260 regularFont.update(textField->document()->styleSelector()->fontSelector()); | 
| 295 // The direction of text in popup menu is set the same as the direction of | 261 // The direction of text in popup menu is set the same as the direction of | 
| (...skipping 10 matching lines...) Expand all Loading... | |
| 306 m_warningStyle = adoptPtr(new PopupMenuStyle(Color::darkGray, m_regularStyle ->backgroundColor(), warningFont, | 272 m_warningStyle = adoptPtr(new PopupMenuStyle(Color::darkGray, m_regularStyle ->backgroundColor(), warningFont, | 
| 307 m_regularStyle->isVisible(), m_ regularStyle->isDisplayNone(), | 273 m_regularStyle->isVisible(), m_ regularStyle->isDisplayNone(), | 
| 308 m_regularStyle->textIndent(), m _regularStyle->textDirection(), | 274 m_regularStyle->textIndent(), m _regularStyle->textDirection(), | 
| 309 m_regularStyle->hasTextDirectio nOverride(), | 275 m_regularStyle->hasTextDirectio nOverride(), | 
| 310 PopupMenuStyle::AutofillPopup)) ; | 276 PopupMenuStyle::AutofillPopup)) ; | 
| 311 } | 277 } | 
| 312 | 278 | 
| 313 void AutofillPopupMenuClient::setSuggestions(const WebVector<WebString>& names, | 279 void AutofillPopupMenuClient::setSuggestions(const WebVector<WebString>& names, | 
| 314 const WebVector<WebString>& labels, | 280 const WebVector<WebString>& labels, | 
| 315 const WebVector<WebString>& icons, | 281 const WebVector<WebString>& icons, | 
| 316 const WebVector<int>& uniqueIDs, | 282 const WebVector<int>& itemIDs) | 
| 317 int separatorIndex) | |
| 318 { | 283 { | 
| 319 ASSERT(names.size() == labels.size()); | 284 ASSERT(names.size() == labels.size()); | 
| 320 ASSERT(names.size() == icons.size()); | 285 ASSERT(names.size() == icons.size()); | 
| 321 ASSERT(names.size() == uniqueIDs.size()); | 286 ASSERT(names.size() == itemIDs.size()); | 
| 322 ASSERT(separatorIndex < static_cast<int>(names.size())); | |
| 323 | 287 | 
| 324 m_names.clear(); | 288 m_names.clear(); | 
| 325 m_labels.clear(); | 289 m_labels.clear(); | 
| 326 m_icons.clear(); | 290 m_icons.clear(); | 
| 327 m_uniqueIDs.clear(); | 291 m_itemIDs.clear(); | 
| 328 for (size_t i = 0; i < names.size(); ++i) { | 292 for (size_t i = 0; i < names.size(); ++i) { | 
| 329 m_names.append(names[i]); | 293 m_names.append(names[i]); | 
| 330 m_labels.append(labels[i]); | 294 m_labels.append(labels[i]); | 
| 331 m_icons.append(icons[i]); | 295 m_icons.append(icons[i]); | 
| 332 m_uniqueIDs.append(uniqueIDs[i]); | 296 m_itemIDs.append(itemIDs[i]); | 
| 333 } | 297 } | 
| 334 | 298 | 
| 335 m_separatorIndex = separatorIndex; | |
| 336 | |
| 337 // Try to preserve selection if possible. | 299 // Try to preserve selection if possible. | 
| 338 if (getSelectedIndex() >= static_cast<int>(names.size())) | 300 if (getSelectedIndex() >= static_cast<int>(names.size())) | 
| 339 setSelectedIndex(-1); | 301 setSelectedIndex(-1); | 
| 340 } | 302 } | 
| 341 | 303 | 
| 342 int AutofillPopupMenuClient::convertListIndexToInternalIndex(unsigned listIndex) const | |
| 343 { | |
| 344 if (listIndex == static_cast<unsigned>(m_separatorIndex)) | |
| 345 return -1; | |
| 346 | |
| 347 if (m_separatorIndex == -1 || listIndex < static_cast<unsigned>(m_separatorI ndex)) | |
| 348 return listIndex; | |
| 349 return listIndex - 1; | |
| 350 } | |
| 351 | |
| 352 WebViewImpl* AutofillPopupMenuClient::getWebView() const | 304 WebViewImpl* AutofillPopupMenuClient::getWebView() const | 
| 353 { | 305 { | 
| 354 Frame* frame = m_textField->document()->frame(); | 306 Frame* frame = m_textField->document()->frame(); | 
| 355 if (!frame) | 307 if (!frame) | 
| 356 return 0; | 308 return 0; | 
| 357 | 309 | 
| 358 Page* page = frame->page(); | 310 Page* page = frame->page(); | 
| 359 if (!page) | 311 if (!page) | 
| 360 return 0; | 312 return 0; | 
| 361 | 313 | 
| 362 return static_cast<WebViewImpl*>(page->chrome()->client()->webView()); | 314 return static_cast<WebViewImpl*>(page->chrome()->client()->webView()); | 
| 363 } | 315 } | 
| 364 | 316 | 
| 365 RenderStyle* AutofillPopupMenuClient::textFieldStyle() const | 317 RenderStyle* AutofillPopupMenuClient::textFieldStyle() const | 
| 366 { | 318 { | 
| 367 RenderStyle* style = m_textField->computedStyle(); | 319 RenderStyle* style = m_textField->computedStyle(); | 
| 368 if (!style) { | 320 if (!style) { | 
| 369 // It seems we can only have a 0 style in a TextField if the | 321 // It seems we can only have a 0 style in a TextField if the | 
| 370 // node is detached, in which case we the popup should not be | 322 // node is detached, in which case we the popup should not be | 
| 371 // showing. Please report this in http://crbug.com/7708 and | 323 // showing. Please report this in http://crbug.com/7708 and | 
| 372 // include the page you were visiting. | 324 // include the page you were visiting. | 
| 373 ASSERT_NOT_REACHED(); | 325 ASSERT_NOT_REACHED(); | 
| 374 } | 326 } | 
| 375 return style; | 327 return style; | 
| 376 } | 328 } | 
| 377 | 329 | 
| 378 } // namespace WebKit | 330 } // namespace WebKit | 
| OLD | NEW |