Index: Source/web/PopupMenuImpl.cpp |
diff --git a/Source/web/PopupMenuImpl.cpp b/Source/web/PopupMenuImpl.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..ce156448d93bedf10e06d278aae648e8dab8359e |
--- /dev/null |
+++ b/Source/web/PopupMenuImpl.cpp |
@@ -0,0 +1,310 @@ |
+/* |
+ * Copyright (C) 2012 Google Inc. All rights reserved. |
tkent
2014/12/15 09:26:04
I don't think this file is a copy of something. P
keishi
2014/12/16 03:53:24
Done.
|
+ * |
+ * Redistribution and use in source and binary forms, with or without |
+ * modification, are permitted provided that the following conditions |
+ * are met: |
+ * |
+ * 1. Redistributions of source code must retain the above copyright |
+ * notice, this list of conditions and the following disclaimer. |
+ * 2. 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. |
+ * |
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS 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 APPLE OR ITS 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 "web/PopupMenuImpl.h" |
+ |
+#include "core/HTMLNames.h" |
+#include "core/css/CSSFontSelector.h" |
+#include "core/dom/StyleEngine.h" |
+#include "core/frame/FrameView.h" |
+#include "core/html/HTMLHRElement.h" |
+#include "core/html/HTMLOptGroupElement.h" |
+#include "core/html/HTMLOptionElement.h" |
+#include "core/page/PagePopup.h" |
+#include "platform/geometry/IntRect.h" |
+#include "public/platform/Platform.h" |
+#include "public/web/WebColorChooser.h" |
+#include "web/ChromeClientImpl.h" |
+#include "web/WebViewImpl.h" |
+ |
+namespace blink { |
+ |
+class PopupMenuCSSFontSelector : public CSSFontSelector { |
+public: |
+ static PassRefPtr<PopupMenuCSSFontSelector> create(Document* document, CSSFontSelector* ownerFontSelector) |
tkent
2014/12/15 09:26:04
PassRefPtrWillBeRawPtr
keishi
2014/12/16 03:53:24
Done.
|
+ { |
+ return adoptRefWillBeNoop(new PopupMenuCSSFontSelector(document, ownerFontSelector)); |
+ } |
+ |
+ // We don't override willUseFontData() for now because the old PopupListBox |
+ // only worked with fonts loaded when opening the popup. |
+ virtual PassRefPtr<FontData> getFontData(const FontDescription&, const AtomicString&) override; |
+ |
+private: |
+ PopupMenuCSSFontSelector(Document* document, CSSFontSelector* ownerFontSelector) |
+ : CSSFontSelector(document) |
+ , m_ownerFontSelector(ownerFontSelector) { } |
+ RefPtrWillBeMember<CSSFontSelector> m_ownerFontSelector; |
+}; |
+ |
+PassRefPtr<FontData> PopupMenuCSSFontSelector::getFontData(const FontDescription& description, const AtomicString& name) |
+{ |
+ return m_ownerFontSelector->getFontData(description, name); |
+} |
+ |
+PassRefPtrWillBeRawPtr<PopupMenuImpl> PopupMenuImpl::create(ChromeClientImpl* chromeClient, PopupMenuClient* client) |
+{ |
+ return adoptRefWillBeNoop(new PopupMenuImpl(chromeClient, client)); |
+} |
+ |
+PopupMenuImpl::PopupMenuImpl(ChromeClientImpl* chromeClient, PopupMenuClient* client) |
+ : m_chromeClient(chromeClient) |
+ , m_client(client) |
+ , m_popup(0) |
tkent
2014/12/15 09:26:04
0 -> nullptr
keishi
2014/12/16 03:53:24
Done.
|
+{ |
+} |
+ |
+PopupMenuImpl::~PopupMenuImpl() |
+{ |
+ closePopup(); |
+} |
+ |
+IntSize PopupMenuImpl::contentSize() |
+{ |
+ return IntSize(0, 0); |
tkent
2014/12/15 09:26:04
IntSize(0, 0) -> IntSize()
keishi
2014/12/16 03:53:24
Done.
|
+} |
+ |
+void PopupMenuImpl::writeDocument(SharedBuffer* data) |
+{ |
+ IntRect anchorRectInScreen = m_chromeClient->rootViewToScreen(m_client->elementRectRelativeToRootView()); |
+ |
+ PagePopupClient::addString("<!DOCTYPE html><head><meta charset='UTF-8'><style>\n", data); |
+ data->append(Platform::current()->loadResource("pickerCommon.css")); |
+ data->append(Platform::current()->loadResource("listPicker.css")); |
+ PagePopupClient::addString("</style></head><body><div id=main>Loading...</div><script>\n" |
+ "window.dialogArguments = {\n", data); |
+ addProperty("selectedIndex", m_client->selectedIndex(), data); |
+ PagePopupClient::addString("children: [\n", data); |
+ for (HTMLElement& child : Traversal<HTMLElement>::childrenOf(ownerElement())) { |
+ if (isHTMLOptionElement(child)) |
+ addOption(toHTMLOptionElement(child), data); |
+ if (isHTMLOptGroupElement(child)) |
+ addOptGroup(toHTMLOptGroupElement(child), data); |
+ if (isHTMLHRElement(child)) |
+ addSeparator(toHTMLHRElement(child), data); |
+ } |
+ PagePopupClient::addString("],\n", data); |
+ addProperty("anchorRectInScreen", anchorRectInScreen, data); |
+ PagePopupClient::addString("};\n", data); |
+ data->append(Platform::current()->loadResource("pickerCommon.js")); |
+ data->append(Platform::current()->loadResource("listPicker.js")); |
+ PagePopupClient::addString("</script></body>\n", data); |
+} |
+ |
+const char* fontWeightToString(FontWeight weight) |
+{ |
+ switch (weight) { |
+ case FontWeight100: |
+ return "100"; |
+ case FontWeight200: |
+ return "200"; |
+ case FontWeight300: |
+ return "300"; |
+ case FontWeight400: |
+ return "400"; |
+ case FontWeight500: |
+ return "500"; |
+ case FontWeight600: |
+ return "600"; |
+ case FontWeight700: |
+ return "700"; |
+ case FontWeight800: |
+ return "800"; |
+ case FontWeight900: |
+ return "900"; |
+ } |
+} |
+ |
+void PopupMenuImpl::addElementStyle(HTMLElement& element, SharedBuffer* data) |
+{ |
+ RenderStyle* style = m_client->renderStyleForItem(element); |
+ ASSERT(style); |
+ PagePopupClient::addString("style: {\n", data); |
+ addProperty("color", style->visitedDependentColor(CSSPropertyColor).serialized(), data); |
+ addProperty("backgroundColor", style->visitedDependentColor(CSSPropertyBackgroundColor).serialized(), data); |
+ const FontDescription& fontDescription = style->font().fontDescription(); |
+ addProperty("fontSize", fontDescription.computedPixelSize(), data); |
+ addProperty("fontWeight", String(fontWeightToString(fontDescription.weight())), data); |
+ PagePopupClient::addString("fontFamily: [\n", data); |
+ for (const FontFamily* f = &fontDescription.family(); f; f = f->next()) { |
+ addJavaScriptString(f->family().string(), data); |
+ if (f->next()) |
+ PagePopupClient::addString(",\n", data); |
+ } |
+ PagePopupClient::addString("],\n", data); |
+ addProperty("visibility", String(style->visibility() == HIDDEN ? "hidden" : "visible"), data); |
+ addProperty("display", String(style->display() == NONE ? "none" : "block"), data); |
+ addProperty("direction", String(style->direction() == RTL ? "rtl" : "ltr"), data); |
+ addProperty("unicodeBidi", String(isOverride(style->unicodeBidi()) ? "bidi-override" : "normal"), data); |
+ PagePopupClient::addString("},\n", data); |
+} |
+ |
+void PopupMenuImpl::addOption(HTMLOptionElement& element, SharedBuffer* data) |
+{ |
+ PagePopupClient::addString("{\n", data); |
+ PagePopupClient::addString("type: \"option\",\n", data); |
+ addProperty("label", element.text(), data); |
+ addProperty("title", element.title(), data); |
+ addProperty("value", element.listIndex(), data); |
+ addProperty("ariaLabel", element.fastGetAttribute(HTMLNames::aria_labelAttr), data); |
+ addProperty("disabled", element.isDisabledFormControl(), data); |
+ addElementStyle(element, data); |
+ PagePopupClient::addString("},\n", data); |
+} |
+ |
+void PopupMenuImpl::addOptGroup(HTMLOptGroupElement& element, SharedBuffer* data) |
+{ |
+ PagePopupClient::addString("{\n", data); |
+ PagePopupClient::addString("type: \"optgroup\",\n", data); |
+ addProperty("label", element.groupLabelText(), data); |
+ addProperty("title", element.title(), data); |
+ addProperty("ariaLabel", element.fastGetAttribute(HTMLNames::aria_labelAttr), data); |
+ addProperty("disabled", element.isDisabledFormControl(), data); |
+ addElementStyle(element, data); |
+ PagePopupClient::addString("children: [", data); |
+ for (HTMLElement& child : Traversal<HTMLElement>::childrenOf(element)) { |
+ if (isHTMLOptionElement(child)) |
+ addOption(toHTMLOptionElement(child), data); |
+ if (isHTMLOptGroupElement(child)) |
+ addOptGroup(toHTMLOptGroupElement(child), data); |
+ if (isHTMLHRElement(child)) |
+ addSeparator(toHTMLHRElement(child), data); |
+ } |
+ PagePopupClient::addString("],\n", data); |
+ PagePopupClient::addString("},\n", data); |
+} |
+ |
+void PopupMenuImpl::addSeparator(HTMLHRElement& element, SharedBuffer* data) |
+{ |
+ PagePopupClient::addString("{\n", data); |
+ PagePopupClient::addString("type: \"separator\",\n", data); |
+ addProperty("title", element.title(), data); |
+ addProperty("ariaLabel", element.fastGetAttribute(HTMLNames::aria_labelAttr), data); |
+ addProperty("disabled", element.isDisabledFormControl(), data); |
+ addElementStyle(element, data); |
+ PagePopupClient::addString("},\n", data); |
+} |
+ |
+void PopupMenuImpl::didWriteDocument(Document* document) |
+{ |
+ Document& ownerDocument = ownerElement().document(); |
+ document->styleEngine()->setFontSelector(PopupMenuCSSFontSelector::create(document, ownerDocument.styleEngine()->fontSelector())); |
+} |
+ |
+void PopupMenuImpl::setValueAndClosePopup(int numValue, const String& stringValue) |
+{ |
+ ASSERT(m_popup); |
+ ASSERT(m_client); |
+ bool success; |
+ int listIndex = stringValue.toInt(&success); |
+ ASSERT(success); |
+ m_client->selectionChanged(listIndex); |
+ m_client->valueChanged(listIndex); |
+ closePopup(); |
+} |
+ |
+void PopupMenuImpl::setValue(const String& value) |
+{ |
+ ASSERT(m_client); |
+ bool success; |
+ int listIndex = value.toInt(&success); |
+ ASSERT(success); |
+ m_client->setTextFromItem(listIndex); |
+ // FIXME: Wrong menu list text when switching from keyboard to mouse. We need something like PopupListBox::m_originalIndex. |
+} |
+ |
+void PopupMenuImpl::didClosePopup() |
+{ |
+ m_popup = 0; |
tkent
2014/12/15 09:26:04
0 -> nullptr
keishi
2014/12/16 03:53:24
Done.
|
+ m_client->popupDidHide(); |
+} |
+ |
+Element& PopupMenuImpl::ownerElement() |
+{ |
+ return m_client->ownerElement(); |
+} |
+ |
+void PopupMenuImpl::closePopup() |
+{ |
+ if (m_popup) |
+ m_chromeClient->closePagePopup(m_popup); |
+} |
+ |
+void PopupMenuImpl::trace(Visitor* visitor) |
tkent
2014/12/15 09:26:04
This function looks unnecessary.
keishi
2014/12/16 03:53:24
Done.
|
+{ |
+ PopupMenu::trace(visitor); |
+} |
+ |
+void PopupMenuImpl::dispose() |
+{ |
+ closePopup(); |
+} |
+ |
+void PopupMenuImpl::show(const FloatQuad& /*controlPosition*/, const IntSize& /*controlSize*/, int /*index*/) |
+{ |
+ ASSERT(!m_popup); |
+ m_popup = m_chromeClient->openPagePopup(this, m_client->elementRectRelativeToRootView()); |
+} |
+ |
+void PopupMenuImpl::hide() |
+{ |
+ if (m_popup) |
+ m_chromeClient->closePagePopup(m_popup); |
+} |
+ |
+void PopupMenuImpl::updateFromElement() |
+{ |
+ RefPtr<SharedBuffer> data = SharedBuffer::create(); |
+ PagePopupClient::addString("window.updateData = {\n", data.get()); |
+ PagePopupClient::addString("type: \"update\",\n", data.get()); |
+ PagePopupClient::addString("children: [", data.get()); |
+ for (HTMLElement& child : Traversal<HTMLElement>::childrenOf(ownerElement())) { |
+ if (isHTMLOptionElement(child)) |
+ addOption(toHTMLOptionElement(child), data.get()); |
+ if (isHTMLOptGroupElement(child)) |
+ addOptGroup(toHTMLOptGroupElement(child), data.get()); |
+ if (isHTMLHRElement(child)) |
+ addSeparator(toHTMLHRElement(child), data.get()); |
+ } |
+ PagePopupClient::addString("],\n", data.get()); |
+ PagePopupClient::addString("}\n", data.get()); |
+ m_popup->postMessage(String(data->data(), data->size())); |
+} |
+ |
+ |
+void PopupMenuImpl::disconnectClient() |
+{ |
+ m_client = 0; |
tkent
2014/12/15 09:26:04
0 -> nullptr
keishi
2014/12/16 03:53:24
Done.
|
+#if ENABLE(OILPAN) |
+ // Cannot be done during finalization, so instead done when the |
+ // render object is destroyed and disconnected. |
+ // |
+ // FIXME: do this always, regardless of ENABLE(OILPAN). |
+ dispose(); |
+#endif |
+} |
+ |
+} // namespace blink |