| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2014 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "config.h" | |
| 6 #include "web/PopupMenuImpl.h" | |
| 7 | |
| 8 #include "core/HTMLNames.h" | |
| 9 #include "core/css/CSSFontSelector.h" | |
| 10 #include "core/dom/StyleEngine.h" | |
| 11 #include "core/frame/FrameView.h" | |
| 12 #include "core/html/HTMLHRElement.h" | |
| 13 #include "core/html/HTMLOptGroupElement.h" | |
| 14 #include "core/html/HTMLOptionElement.h" | |
| 15 #include "core/page/PagePopup.h" | |
| 16 #include "platform/geometry/IntRect.h" | |
| 17 #include "platform/text/PlatformLocale.h" | |
| 18 #include "public/platform/Platform.h" | |
| 19 #include "public/web/WebColorChooser.h" | |
| 20 #include "web/ChromeClientImpl.h" | |
| 21 #include "web/WebViewImpl.h" | |
| 22 | |
| 23 namespace blink { | |
| 24 | |
| 25 class PopupMenuCSSFontSelector : public CSSFontSelector { | |
| 26 public: | |
| 27 static PassRefPtrWillBeRawPtr<PopupMenuCSSFontSelector> create(Document* doc
ument, CSSFontSelector* ownerFontSelector) | |
| 28 { | |
| 29 return adoptRefWillBeNoop(new PopupMenuCSSFontSelector(document, ownerFo
ntSelector)); | |
| 30 } | |
| 31 | |
| 32 // We don't override willUseFontData() for now because the old PopupListBox | |
| 33 // only worked with fonts loaded when opening the popup. | |
| 34 virtual PassRefPtr<FontData> getFontData(const FontDescription&, const Atomi
cString&) override; | |
| 35 | |
| 36 virtual void trace(Visitor*) override; | |
| 37 | |
| 38 private: | |
| 39 PopupMenuCSSFontSelector(Document* document, CSSFontSelector* ownerFontSelec
tor) | |
| 40 : CSSFontSelector(document) | |
| 41 , m_ownerFontSelector(ownerFontSelector) | |
| 42 { | |
| 43 } | |
| 44 | |
| 45 RefPtrWillBeMember<CSSFontSelector> m_ownerFontSelector; | |
| 46 }; | |
| 47 | |
| 48 PassRefPtr<FontData> PopupMenuCSSFontSelector::getFontData(const FontDescription
& description, const AtomicString& name) | |
| 49 { | |
| 50 return m_ownerFontSelector->getFontData(description, name); | |
| 51 } | |
| 52 | |
| 53 void PopupMenuCSSFontSelector::trace(Visitor* visitor) | |
| 54 { | |
| 55 visitor->trace(m_ownerFontSelector); | |
| 56 CSSFontSelector::trace(visitor); | |
| 57 } | |
| 58 | |
| 59 PassRefPtrWillBeRawPtr<PopupMenuImpl> PopupMenuImpl::create(ChromeClientImpl* ch
romeClient, PopupMenuClient* client) | |
| 60 { | |
| 61 return adoptRefWillBeNoop(new PopupMenuImpl(chromeClient, client)); | |
| 62 } | |
| 63 | |
| 64 PopupMenuImpl::PopupMenuImpl(ChromeClientImpl* chromeClient, PopupMenuClient* cl
ient) | |
| 65 : m_chromeClient(chromeClient) | |
| 66 , m_client(client) | |
| 67 , m_popup(nullptr) | |
| 68 , m_indexToSetOnClose(-1) | |
| 69 { | |
| 70 } | |
| 71 | |
| 72 PopupMenuImpl::~PopupMenuImpl() | |
| 73 { | |
| 74 closePopup(); | |
| 75 } | |
| 76 | |
| 77 IntSize PopupMenuImpl::contentSize() | |
| 78 { | |
| 79 return IntSize(); | |
| 80 } | |
| 81 | |
| 82 void PopupMenuImpl::writeDocument(SharedBuffer* data) | |
| 83 { | |
| 84 IntRect anchorRectInScreen = m_chromeClient->rootViewToScreen(m_client->elem
entRectRelativeToRootView()); | |
| 85 | |
| 86 PagePopupClient::addString("<!DOCTYPE html><head><meta charset='UTF-8'><styl
e>\n", data); | |
| 87 data->append(Platform::current()->loadResource("pickerCommon.css")); | |
| 88 data->append(Platform::current()->loadResource("listPicker.css")); | |
| 89 PagePopupClient::addString("</style></head><body><div id=main>Loading...</di
v><script>\n" | |
| 90 "window.dialogArguments = {\n", data); | |
| 91 addProperty("selectedIndex", m_client->selectedIndex(), data); | |
| 92 PagePopupClient::addString("children: [\n", data); | |
| 93 for (HTMLElement& child : Traversal<HTMLElement>::childrenOf(ownerElement())
) { | |
| 94 if (isHTMLOptionElement(child)) | |
| 95 addOption(toHTMLOptionElement(child), data); | |
| 96 if (isHTMLOptGroupElement(child)) | |
| 97 addOptGroup(toHTMLOptGroupElement(child), data); | |
| 98 if (isHTMLHRElement(child)) | |
| 99 addSeparator(toHTMLHRElement(child), data); | |
| 100 } | |
| 101 PagePopupClient::addString("],\n", data); | |
| 102 addProperty("anchorRectInScreen", anchorRectInScreen, data); | |
| 103 PagePopupClient::addString("};\n", data); | |
| 104 data->append(Platform::current()->loadResource("pickerCommon.js")); | |
| 105 data->append(Platform::current()->loadResource("listPicker.js")); | |
| 106 PagePopupClient::addString("</script></body>\n", data); | |
| 107 } | |
| 108 | |
| 109 const char* fontWeightToString(FontWeight weight) | |
| 110 { | |
| 111 switch (weight) { | |
| 112 case FontWeight100: | |
| 113 return "100"; | |
| 114 case FontWeight200: | |
| 115 return "200"; | |
| 116 case FontWeight300: | |
| 117 return "300"; | |
| 118 case FontWeight400: | |
| 119 return "400"; | |
| 120 case FontWeight500: | |
| 121 return "500"; | |
| 122 case FontWeight600: | |
| 123 return "600"; | |
| 124 case FontWeight700: | |
| 125 return "700"; | |
| 126 case FontWeight800: | |
| 127 return "800"; | |
| 128 case FontWeight900: | |
| 129 return "900"; | |
| 130 default: | |
| 131 ASSERT_NOT_REACHED(); | |
| 132 break; | |
| 133 } | |
| 134 return 0; | |
| 135 } | |
| 136 | |
| 137 void PopupMenuImpl::addElementStyle(HTMLElement& element, SharedBuffer* data) | |
| 138 { | |
| 139 RenderStyle* style = m_client->renderStyleForItem(element); | |
| 140 ASSERT(style); | |
| 141 PagePopupClient::addString("style: {\n", data); | |
| 142 addProperty("color", style->visitedDependentColor(CSSPropertyColor).serializ
ed(), data); | |
| 143 addProperty("backgroundColor", style->visitedDependentColor(CSSPropertyBackg
roundColor).serialized(), data); | |
| 144 const FontDescription& fontDescription = style->font().fontDescription(); | |
| 145 addProperty("fontSize", fontDescription.computedPixelSize(), data); | |
| 146 addProperty("fontWeight", String(fontWeightToString(fontDescription.weight()
)), data); | |
| 147 PagePopupClient::addString("fontFamily: [\n", data); | |
| 148 for (const FontFamily* f = &fontDescription.family(); f; f = f->next()) { | |
| 149 addJavaScriptString(f->family().string(), data); | |
| 150 if (f->next()) | |
| 151 PagePopupClient::addString(",\n", data); | |
| 152 } | |
| 153 PagePopupClient::addString("],\n", data); | |
| 154 addProperty("visibility", String(style->visibility() == HIDDEN ? "hidden" :
"visible"), data); | |
| 155 addProperty("display", String(style->display() == NONE ? "none" : "block"),
data); | |
| 156 addProperty("direction", String(style->direction() == RTL ? "rtl" : "ltr"),
data); | |
| 157 addProperty("unicodeBidi", String(isOverride(style->unicodeBidi()) ? "bidi-o
verride" : "normal"), data); | |
| 158 PagePopupClient::addString("},\n", data); | |
| 159 } | |
| 160 | |
| 161 void PopupMenuImpl::addOption(HTMLOptionElement& element, SharedBuffer* data) | |
| 162 { | |
| 163 PagePopupClient::addString("{\n", data); | |
| 164 PagePopupClient::addString("type: \"option\",\n", data); | |
| 165 addProperty("label", element.text(), data); | |
| 166 addProperty("title", element.title(), data); | |
| 167 addProperty("value", element.listIndex(), data); | |
| 168 addProperty("ariaLabel", element.fastGetAttribute(HTMLNames::aria_labelAttr)
, data); | |
| 169 addProperty("disabled", element.isDisabledFormControl(), data); | |
| 170 addElementStyle(element, data); | |
| 171 PagePopupClient::addString("},\n", data); | |
| 172 } | |
| 173 | |
| 174 void PopupMenuImpl::addOptGroup(HTMLOptGroupElement& element, SharedBuffer* data
) | |
| 175 { | |
| 176 PagePopupClient::addString("{\n", data); | |
| 177 PagePopupClient::addString("type: \"optgroup\",\n", data); | |
| 178 addProperty("label", element.groupLabelText(), data); | |
| 179 addProperty("title", element.title(), data); | |
| 180 addProperty("ariaLabel", element.fastGetAttribute(HTMLNames::aria_labelAttr)
, data); | |
| 181 addProperty("disabled", element.isDisabledFormControl(), data); | |
| 182 addElementStyle(element, data); | |
| 183 PagePopupClient::addString("children: [", data); | |
| 184 for (HTMLElement& child : Traversal<HTMLElement>::childrenOf(element)) { | |
| 185 if (isHTMLOptionElement(child)) | |
| 186 addOption(toHTMLOptionElement(child), data); | |
| 187 if (isHTMLOptGroupElement(child)) | |
| 188 addOptGroup(toHTMLOptGroupElement(child), data); | |
| 189 if (isHTMLHRElement(child)) | |
| 190 addSeparator(toHTMLHRElement(child), data); | |
| 191 } | |
| 192 PagePopupClient::addString("],\n", data); | |
| 193 PagePopupClient::addString("},\n", data); | |
| 194 } | |
| 195 | |
| 196 void PopupMenuImpl::addSeparator(HTMLHRElement& element, SharedBuffer* data) | |
| 197 { | |
| 198 PagePopupClient::addString("{\n", data); | |
| 199 PagePopupClient::addString("type: \"separator\",\n", data); | |
| 200 addProperty("title", element.title(), data); | |
| 201 addProperty("ariaLabel", element.fastGetAttribute(HTMLNames::aria_labelAttr)
, data); | |
| 202 addProperty("disabled", element.isDisabledFormControl(), data); | |
| 203 addElementStyle(element, data); | |
| 204 PagePopupClient::addString("},\n", data); | |
| 205 } | |
| 206 | |
| 207 void PopupMenuImpl::didWriteDocument(Document& document) | |
| 208 { | |
| 209 Document& ownerDocument = ownerElement().document(); | |
| 210 document.styleEngine()->setFontSelector(PopupMenuCSSFontSelector::create(&do
cument, ownerDocument.styleEngine()->fontSelector())); | |
| 211 } | |
| 212 | |
| 213 void PopupMenuImpl::setValueAndClosePopup(int numValue, const String& stringValu
e) | |
| 214 { | |
| 215 ASSERT(m_popup); | |
| 216 ASSERT(m_client); | |
| 217 bool success; | |
| 218 int listIndex = stringValue.toInt(&success); | |
| 219 ASSERT(success); | |
| 220 m_client->selectionChanged(listIndex); | |
| 221 m_client->valueChanged(listIndex); | |
| 222 m_indexToSetOnClose = -1; | |
| 223 closePopup(); | |
| 224 } | |
| 225 | |
| 226 void PopupMenuImpl::setValue(const String& value) | |
| 227 { | |
| 228 ASSERT(m_client); | |
| 229 bool success; | |
| 230 int listIndex = value.toInt(&success); | |
| 231 ASSERT(success); | |
| 232 m_client->setTextFromItem(listIndex); | |
| 233 m_indexToSetOnClose = listIndex; | |
| 234 } | |
| 235 | |
| 236 void PopupMenuImpl::didClosePopup() | |
| 237 { | |
| 238 if (m_indexToSetOnClose >= 0) | |
| 239 m_client->valueChanged(m_indexToSetOnClose); | |
| 240 m_indexToSetOnClose = -1; | |
| 241 m_popup = nullptr; | |
| 242 m_client->popupDidHide(); | |
| 243 } | |
| 244 | |
| 245 Element& PopupMenuImpl::ownerElement() | |
| 246 { | |
| 247 return m_client->ownerElement(); | |
| 248 } | |
| 249 | |
| 250 Locale& PopupMenuImpl::locale() | |
| 251 { | |
| 252 return Locale::defaultLocale(); | |
| 253 } | |
| 254 | |
| 255 void PopupMenuImpl::closePopup() | |
| 256 { | |
| 257 if (m_popup) | |
| 258 m_chromeClient->closePagePopup(m_popup); | |
| 259 } | |
| 260 | |
| 261 void PopupMenuImpl::dispose() | |
| 262 { | |
| 263 closePopup(); | |
| 264 } | |
| 265 | |
| 266 void PopupMenuImpl::show(const FloatQuad& /*controlPosition*/, const IntSize& /*
controlSize*/, int /*index*/) | |
| 267 { | |
| 268 ASSERT(!m_popup); | |
| 269 m_popup = m_chromeClient->openPagePopup(this, m_client->elementRectRelativeT
oRootView()); | |
| 270 } | |
| 271 | |
| 272 void PopupMenuImpl::hide() | |
| 273 { | |
| 274 if (m_popup) | |
| 275 m_chromeClient->closePagePopup(m_popup); | |
| 276 } | |
| 277 | |
| 278 void PopupMenuImpl::updateFromElement() | |
| 279 { | |
| 280 RefPtr<SharedBuffer> data = SharedBuffer::create(); | |
| 281 PagePopupClient::addString("window.updateData = {\n", data.get()); | |
| 282 PagePopupClient::addString("type: \"update\",\n", data.get()); | |
| 283 PagePopupClient::addString("children: [", data.get()); | |
| 284 for (HTMLElement& child : Traversal<HTMLElement>::childrenOf(ownerElement())
) { | |
| 285 if (isHTMLOptionElement(child)) | |
| 286 addOption(toHTMLOptionElement(child), data.get()); | |
| 287 if (isHTMLOptGroupElement(child)) | |
| 288 addOptGroup(toHTMLOptGroupElement(child), data.get()); | |
| 289 if (isHTMLHRElement(child)) | |
| 290 addSeparator(toHTMLHRElement(child), data.get()); | |
| 291 } | |
| 292 PagePopupClient::addString("],\n", data.get()); | |
| 293 PagePopupClient::addString("}\n", data.get()); | |
| 294 m_popup->postMessage(String(data->data(), data->size())); | |
| 295 } | |
| 296 | |
| 297 | |
| 298 void PopupMenuImpl::disconnectClient() | |
| 299 { | |
| 300 m_client = nullptr; | |
| 301 #if ENABLE(OILPAN) | |
| 302 // Cannot be done during finalization, so instead done when the | |
| 303 // render object is destroyed and disconnected. | |
| 304 // | |
| 305 // FIXME: do this always, regardless of ENABLE(OILPAN). | |
| 306 dispose(); | |
| 307 #endif | |
| 308 } | |
| 309 | |
| 310 } // namespace blink | |
| OLD | NEW |