diff options
author | Ben Murdoch <benm@google.com> | 2011-05-13 16:23:25 +0100 |
---|---|---|
committer | Ben Murdoch <benm@google.com> | 2011-05-16 11:35:02 +0100 |
commit | 65f03d4f644ce73618e5f4f50dd694b26f55ae12 (patch) | |
tree | f478babb801e720de7bfaee23443ffe029f58731 /Source/WebKit/chromium/src/AutoFillPopupMenuClient.cpp | |
parent | 47de4a2fb7262c7ebdb9cd133ad2c54c187454d0 (diff) | |
download | external_webkit-65f03d4f644ce73618e5f4f50dd694b26f55ae12.zip external_webkit-65f03d4f644ce73618e5f4f50dd694b26f55ae12.tar.gz external_webkit-65f03d4f644ce73618e5f4f50dd694b26f55ae12.tar.bz2 |
Merge WebKit at r75993: Initial merge by git.
Change-Id: I602bbdc3974787a3b0450456a30a7868286921c3
Diffstat (limited to 'Source/WebKit/chromium/src/AutoFillPopupMenuClient.cpp')
-rw-r--r-- | Source/WebKit/chromium/src/AutoFillPopupMenuClient.cpp | 376 |
1 files changed, 376 insertions, 0 deletions
diff --git a/Source/WebKit/chromium/src/AutoFillPopupMenuClient.cpp b/Source/WebKit/chromium/src/AutoFillPopupMenuClient.cpp new file mode 100644 index 0000000..4f57994 --- /dev/null +++ b/Source/WebKit/chromium/src/AutoFillPopupMenuClient.cpp @@ -0,0 +1,376 @@ +/* + * Copyright (C) 2010 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "AutoFillPopupMenuClient.h" + +#include "CSSStyleSelector.h" +#include "CSSValueKeywords.h" +#include "Chrome.h" +#include "FrameView.h" +#include "HTMLInputElement.h" +#include "RenderTheme.h" +#include "WebAutoFillClient.h" +#include "WebNode.h" +#include "WebString.h" +#include "WebVector.h" +#include "WebViewClient.h" +#include "WebViewImpl.h" + +using namespace WebCore; + +namespace WebKit { + +AutoFillPopupMenuClient::AutoFillPopupMenuClient() + : m_separatorIndex(-1) + , m_selectedIndex(-1) + , m_textField(0) +{ +} + +AutoFillPopupMenuClient::~AutoFillPopupMenuClient() +{ +} + +unsigned AutoFillPopupMenuClient::getSuggestionsCount() const +{ + return m_names.size() + ((m_separatorIndex == -1) ? 0 : 1); +} + +WebString AutoFillPopupMenuClient::getSuggestion(unsigned listIndex) const +{ + int index = convertListIndexToInternalIndex(listIndex); + if (index == -1) + return WebString(); + + ASSERT(index >= 0 && static_cast<size_t>(index) < m_names.size()); + return m_names[index]; +} + +WebString AutoFillPopupMenuClient::getLabel(unsigned listIndex) const +{ + int index = convertListIndexToInternalIndex(listIndex); + if (index == -1) + return WebString(); + + ASSERT(index >= 0 && static_cast<size_t>(index) < m_labels.size()); + return m_labels[index]; +} + +WebString AutoFillPopupMenuClient::getIcon(unsigned listIndex) const +{ + int index = convertListIndexToInternalIndex(listIndex); + if (index == -1) + return WebString(); + + ASSERT(index >= 0 && static_cast<size_t>(index) < m_icons.size()); + return m_icons[index]; +} + +void AutoFillPopupMenuClient::removeSuggestionAtIndex(unsigned listIndex) +{ + if (!canRemoveSuggestionAtIndex(listIndex)) + return; + + int index = convertListIndexToInternalIndex(listIndex); + + ASSERT(static_cast<unsigned>(index) < m_names.size()); + + m_names.remove(index); + m_labels.remove(index); + m_icons.remove(index); + m_uniqueIDs.remove(index); + + // Shift the separator index if necessary. + if (m_separatorIndex != -1) + m_separatorIndex--; +} + +bool AutoFillPopupMenuClient::canRemoveSuggestionAtIndex(unsigned listIndex) +{ + // Only allow deletion of items before the separator that have unique id 0 + // (i.e. are autocomplete rather than autofill items). + int index = convertListIndexToInternalIndex(listIndex); + return !m_uniqueIDs[index] && (m_separatorIndex == -1 || listIndex < static_cast<unsigned>(m_separatorIndex)); +} + +void AutoFillPopupMenuClient::valueChanged(unsigned listIndex, bool fireEvents) +{ + WebViewImpl* webView = getWebView(); + if (!webView) + return; + + if (m_separatorIndex != -1 && listIndex > static_cast<unsigned>(m_separatorIndex)) + --listIndex; + + ASSERT(listIndex < m_names.size()); + + webView->autoFillClient()->didAcceptAutoFillSuggestion(WebNode(getTextField()), + m_names[listIndex], + m_labels[listIndex], + m_uniqueIDs[listIndex], + listIndex); +} + +void AutoFillPopupMenuClient::selectionChanged(unsigned listIndex, bool fireEvents) +{ + WebViewImpl* webView = getWebView(); + if (!webView) + return; + + if (m_separatorIndex != -1 && listIndex > static_cast<unsigned>(m_separatorIndex)) + --listIndex; + + ASSERT(listIndex < m_names.size()); + + webView->autoFillClient()->didSelectAutoFillSuggestion(WebNode(getTextField()), + m_names[listIndex], + m_labels[listIndex], + m_uniqueIDs[listIndex]); +} + +void AutoFillPopupMenuClient::selectionCleared() +{ + WebViewImpl* webView = getWebView(); + if (webView) + webView->autoFillClient()->didClearAutoFillSelection(WebNode(getTextField())); +} + +String AutoFillPopupMenuClient::itemText(unsigned listIndex) const +{ + return getSuggestion(listIndex); +} + +String AutoFillPopupMenuClient::itemLabel(unsigned listIndex) const +{ + return getLabel(listIndex); +} + +String AutoFillPopupMenuClient::itemIcon(unsigned listIndex) const +{ + return getIcon(listIndex); +} + +bool AutoFillPopupMenuClient::itemIsEnabled(unsigned listIndex) const +{ + return !itemIsWarning(listIndex); +} + +PopupMenuStyle AutoFillPopupMenuClient::itemStyle(unsigned listIndex) const +{ + return itemIsWarning(listIndex) ? *m_warningStyle : *m_regularStyle; +} + +PopupMenuStyle AutoFillPopupMenuClient::menuStyle() const +{ + return *m_regularStyle; +} + +int AutoFillPopupMenuClient::clientPaddingLeft() const +{ + // Bug http://crbug.com/7708 seems to indicate the style can be 0. + RenderStyle* style = textFieldStyle(); + if (!style) + return 0; + + return RenderTheme::defaultTheme()->popupInternalPaddingLeft(style); +} + +int AutoFillPopupMenuClient::clientPaddingRight() const +{ + // Bug http://crbug.com/7708 seems to indicate the style can be 0. + RenderStyle* style = textFieldStyle(); + if (!style) + return 0; + + return RenderTheme::defaultTheme()->popupInternalPaddingRight(style); +} + +void AutoFillPopupMenuClient::popupDidHide() +{ + WebViewImpl* webView = getWebView(); + if (!webView) + return; + + webView->autoFillPopupDidHide(); + webView->autoFillClient()->didClearAutoFillSelection(WebNode(getTextField())); +} + +bool AutoFillPopupMenuClient::itemIsSeparator(unsigned listIndex) const +{ + return (m_separatorIndex != -1 && static_cast<unsigned>(m_separatorIndex) == listIndex); +} + +bool AutoFillPopupMenuClient::itemIsWarning(unsigned listIndex) const +{ + int index = convertListIndexToInternalIndex(listIndex); + if (index == -1) + return false; + + ASSERT(index >= 0 && static_cast<size_t>(index) < m_uniqueIDs.size()); + return m_uniqueIDs[index] < 0; +} + +void AutoFillPopupMenuClient::setTextFromItem(unsigned listIndex) +{ + m_textField->setValue(getSuggestion(listIndex)); +} + +FontSelector* AutoFillPopupMenuClient::fontSelector() const +{ + return m_textField->document()->styleSelector()->fontSelector(); +} + +HostWindow* AutoFillPopupMenuClient::hostWindow() const +{ + return m_textField->document()->view()->hostWindow(); +} + +PassRefPtr<Scrollbar> AutoFillPopupMenuClient::createScrollbar( + ScrollbarClient* client, + ScrollbarOrientation orientation, + ScrollbarControlSize size) +{ + return Scrollbar::createNativeScrollbar(client, orientation, size); +} + +void AutoFillPopupMenuClient::initialize( + HTMLInputElement* textField, + const WebVector<WebString>& names, + const WebVector<WebString>& labels, + const WebVector<WebString>& icons, + const WebVector<int>& uniqueIDs, + int separatorIndex) +{ + ASSERT(names.size() == labels.size()); + ASSERT(names.size() == icons.size()); + ASSERT(names.size() == uniqueIDs.size()); + ASSERT(separatorIndex < static_cast<int>(names.size())); + + m_selectedIndex = -1; + m_textField = textField; + + // The suggestions must be set before initializing the + // AutoFillPopupMenuClient. + setSuggestions(names, labels, icons, uniqueIDs, separatorIndex); + + FontDescription regularFontDescription; + RenderTheme::defaultTheme()->systemFont(CSSValueWebkitControl, + regularFontDescription); + RenderStyle* style = m_textField->computedStyle(); + regularFontDescription.setComputedSize(style->fontDescription().computedSize()); + + Font regularFont(regularFontDescription, 0, 0); + regularFont.update(textField->document()->styleSelector()->fontSelector()); + // The direction of text in popup menu is set the same as the direction of + // the input element: textField. + m_regularStyle.set(new PopupMenuStyle(Color::black, Color::white, regularFont, + true, false, Length(WebCore::Fixed), + textField->renderer()->style()->direction())); + + FontDescription warningFontDescription = regularFont.fontDescription(); + warningFontDescription.setItalic(true); + Font warningFont(warningFontDescription, regularFont.letterSpacing(), regularFont.wordSpacing()); + warningFont.update(regularFont.fontSelector()); + m_warningStyle.set(new PopupMenuStyle(Color::darkGray, + m_regularStyle->backgroundColor(), + warningFont, + m_regularStyle->isVisible(), + m_regularStyle->isDisplayNone(), + m_regularStyle->textIndent(), + m_regularStyle->textDirection())); +} + +void AutoFillPopupMenuClient::setSuggestions(const WebVector<WebString>& names, + const WebVector<WebString>& labels, + const WebVector<WebString>& icons, + const WebVector<int>& uniqueIDs, + int separatorIndex) +{ + ASSERT(names.size() == labels.size()); + ASSERT(names.size() == icons.size()); + ASSERT(names.size() == uniqueIDs.size()); + ASSERT(separatorIndex < static_cast<int>(names.size())); + + m_names.clear(); + m_labels.clear(); + m_icons.clear(); + m_uniqueIDs.clear(); + for (size_t i = 0; i < names.size(); ++i) { + m_names.append(names[i]); + m_labels.append(labels[i]); + m_icons.append(icons[i]); + m_uniqueIDs.append(uniqueIDs[i]); + } + + m_separatorIndex = separatorIndex; + + // Try to preserve selection if possible. + if (getSelectedIndex() >= static_cast<int>(names.size())) + setSelectedIndex(-1); +} + +int AutoFillPopupMenuClient::convertListIndexToInternalIndex(unsigned listIndex) const +{ + if (listIndex == static_cast<unsigned>(m_separatorIndex)) + return -1; + + if (m_separatorIndex == -1 || listIndex < static_cast<unsigned>(m_separatorIndex)) + return listIndex; + return listIndex - 1; +} + +WebViewImpl* AutoFillPopupMenuClient::getWebView() const +{ + Frame* frame = m_textField->document()->frame(); + if (!frame) + return 0; + + Page* page = frame->page(); + if (!page) + return 0; + + return static_cast<ChromeClientImpl*>(page->chrome()->client())->webView(); +} + +RenderStyle* AutoFillPopupMenuClient::textFieldStyle() const +{ + RenderStyle* style = m_textField->computedStyle(); + if (!style) { + // It seems we can only have a 0 style in a TextField if the + // node is detached, in which case we the popup should not be + // showing. Please report this in http://crbug.com/7708 and + // include the page you were visiting. + ASSERT_NOT_REACHED(); + } + return style; +} + +} // namespace WebKit |