OLD | NEW |
1 // Copyright (c) 2014 The Chromium Authors. All rights reserved. | 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 | 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 "config.h" | 5 #include "config.h" |
6 #include "web/PopupMenuImpl.h" | 6 #include "web/PopupMenuImpl.h" |
7 | 7 |
8 #include "core/HTMLNames.h" | 8 #include "core/HTMLNames.h" |
9 #include "core/css/CSSFontSelector.h" | 9 #include "core/css/CSSFontSelector.h" |
10 #include "core/dom/ElementTraversal.h" | 10 #include "core/dom/ElementTraversal.h" |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
158 class PopupMenuImpl::ItemIterationContext { | 158 class PopupMenuImpl::ItemIterationContext { |
159 STACK_ALLOCATED(); | 159 STACK_ALLOCATED(); |
160 public: | 160 public: |
161 ItemIterationContext(const ComputedStyle& style, SharedBuffer* buffer) | 161 ItemIterationContext(const ComputedStyle& style, SharedBuffer* buffer) |
162 : m_direction(style.direction()) | 162 : m_direction(style.direction()) |
163 , m_foregroundColor(style.visitedDependentColor(CSSPropertyColor)) | 163 , m_foregroundColor(style.visitedDependentColor(CSSPropertyColor)) |
164 , m_backgroundColor(style.visitedDependentColor(CSSPropertyBackgroundCol
or)) | 164 , m_backgroundColor(style.visitedDependentColor(CSSPropertyBackgroundCol
or)) |
165 , m_textTransform(style.textTransform()) | 165 , m_textTransform(style.textTransform()) |
166 , m_fontDescription(style.fontDescription()) | 166 , m_fontDescription(style.fontDescription()) |
167 , m_listIndex(0) | 167 , m_listIndex(0) |
| 168 , m_isInGroup(false) |
168 , m_buffer(buffer) | 169 , m_buffer(buffer) |
169 { | 170 { |
170 ASSERT(m_buffer); | 171 ASSERT(m_buffer); |
171 #if OS(LINUX) | 172 #if OS(LINUX) |
172 // On other platforms, the <option> background color is the same as the | 173 // On other platforms, the <option> background color is the same as the |
173 // <select> background color. On Linux, that makes the <option> | 174 // <select> background color. On Linux, that makes the <option> |
174 // background color very dark, so by default, try to use a lighter | 175 // background color very dark, so by default, try to use a lighter |
175 // background color for <option>s. | 176 // background color for <option>s. |
176 if (LayoutTheme::theme().systemColor(CSSValueButtonface) == m_background
Color) | 177 if (LayoutTheme::theme().systemColor(CSSValueButtonface) == m_background
Color) |
177 m_backgroundColor = LayoutTheme::theme().systemColor(CSSValueMenu); | 178 m_backgroundColor = LayoutTheme::theme().systemColor(CSSValueMenu); |
(...skipping 13 matching lines...) Expand all Loading... |
191 PagePopupClient::addString("fontFamily: [", m_buffer); | 192 PagePopupClient::addString("fontFamily: [", m_buffer); |
192 for (const FontFamily* f = &fontFamily(); f; f = f->next()) { | 193 for (const FontFamily* f = &fontFamily(); f; f = f->next()) { |
193 addJavaScriptString(f->family().string(), m_buffer); | 194 addJavaScriptString(f->family().string(), m_buffer); |
194 if (f->next()) | 195 if (f->next()) |
195 PagePopupClient::addString(",", m_buffer); | 196 PagePopupClient::addString(",", m_buffer); |
196 } | 197 } |
197 PagePopupClient::addString("]", m_buffer); | 198 PagePopupClient::addString("]", m_buffer); |
198 PagePopupClient::addString("},\n", m_buffer); | 199 PagePopupClient::addString("},\n", m_buffer); |
199 } | 200 } |
200 | 201 |
| 202 void startGroupChildren() |
| 203 { |
| 204 ASSERT(!m_isInGroup); |
| 205 PagePopupClient::addString("children: [", m_buffer); |
| 206 m_isInGroup = true; |
| 207 } |
| 208 void finishGroupIfNecessary() |
| 209 { |
| 210 if (!m_isInGroup) |
| 211 return; |
| 212 PagePopupClient::addString("],},\n", m_buffer); |
| 213 m_isInGroup = false; |
| 214 } |
| 215 |
201 int fontSize() const { return m_fontDescription.computedPixelSize(); } | 216 int fontSize() const { return m_fontDescription.computedPixelSize(); } |
202 FontStyle fontStyle() const { return m_fontDescription.style(); } | 217 FontStyle fontStyle() const { return m_fontDescription.style(); } |
203 FontVariant fontVariant() const { return m_fontDescription.variant(); } | 218 FontVariant fontVariant() const { return m_fontDescription.variant(); } |
204 const FontFamily& fontFamily() const { return m_fontDescription.family(); } | 219 const FontFamily& fontFamily() const { return m_fontDescription.family(); } |
205 | 220 |
206 TextDirection m_direction; | 221 TextDirection m_direction; |
207 Color m_foregroundColor; | 222 Color m_foregroundColor; |
208 Color m_backgroundColor; | 223 Color m_backgroundColor; |
209 ETextTransform m_textTransform; | 224 ETextTransform m_textTransform; |
210 const FontDescription& m_fontDescription; | 225 const FontDescription& m_fontDescription; |
211 | 226 |
212 int m_listIndex; | 227 int m_listIndex; |
| 228 bool m_isInGroup; |
213 SharedBuffer* m_buffer; | 229 SharedBuffer* m_buffer; |
214 }; | 230 }; |
215 | 231 |
216 // ---------------------------------------------------------------- | 232 // ---------------------------------------------------------------- |
217 | 233 |
218 PassRefPtrWillBeRawPtr<PopupMenuImpl> PopupMenuImpl::create(ChromeClientImpl* ch
romeClient, PopupMenuClient* client) | 234 PassRefPtrWillBeRawPtr<PopupMenuImpl> PopupMenuImpl::create(ChromeClientImpl* ch
romeClient, PopupMenuClient* client) |
219 { | 235 { |
220 return adoptRefWillBeNoop(new PopupMenuImpl(chromeClient, client)); | 236 return adoptRefWillBeNoop(new PopupMenuImpl(chromeClient, client)); |
221 } | 237 } |
222 | 238 |
(...skipping 22 matching lines...) Expand all Loading... |
245 PagePopupClient::addString("<!DOCTYPE html><head><meta charset='UTF-8'><styl
e>\n", data); | 261 PagePopupClient::addString("<!DOCTYPE html><head><meta charset='UTF-8'><styl
e>\n", data); |
246 data->append(Platform::current()->loadResource("pickerCommon.css")); | 262 data->append(Platform::current()->loadResource("pickerCommon.css")); |
247 data->append(Platform::current()->loadResource("listPicker.css")); | 263 data->append(Platform::current()->loadResource("listPicker.css")); |
248 PagePopupClient::addString("</style></head><body><div id=main>Loading...</di
v><script>\n" | 264 PagePopupClient::addString("</style></head><body><div id=main>Loading...</di
v><script>\n" |
249 "window.dialogArguments = {\n", data); | 265 "window.dialogArguments = {\n", data); |
250 addProperty("selectedIndex", m_client->selectedIndex(), data); | 266 addProperty("selectedIndex", m_client->selectedIndex(), data); |
251 const ComputedStyle* ownerStyle = ownerElement().computedStyle(); | 267 const ComputedStyle* ownerStyle = ownerElement().computedStyle(); |
252 ItemIterationContext context(*ownerStyle, data); | 268 ItemIterationContext context(*ownerStyle, data); |
253 context.serializeBaseStyle(); | 269 context.serializeBaseStyle(); |
254 PagePopupClient::addString("children: [\n", data); | 270 PagePopupClient::addString("children: [\n", data); |
255 for (HTMLElement& child : Traversal<HTMLElement>::childrenOf(ownerElement())
) { | 271 for (; context.m_listIndex < m_client->listSize(); ++context.m_listIndex) { |
| 272 Element& child = m_client->itemElement(context.m_listIndex); |
| 273 if (!isHTMLOptGroupElement(child.parentNode())) |
| 274 context.finishGroupIfNecessary(); |
256 if (isHTMLOptionElement(child)) | 275 if (isHTMLOptionElement(child)) |
257 addOption(context, toHTMLOptionElement(child)); | 276 addOption(context, toHTMLOptionElement(child)); |
258 if (isHTMLOptGroupElement(child)) | 277 else if (isHTMLOptGroupElement(child)) |
259 addOptGroup(context, toHTMLOptGroupElement(child)); | 278 addOptGroup(context, toHTMLOptGroupElement(child)); |
260 if (isHTMLHRElement(child)) | 279 else if (isHTMLHRElement(child)) |
261 addSeparator(context, toHTMLHRElement(child)); | 280 addSeparator(context, toHTMLHRElement(child)); |
262 } | 281 } |
| 282 context.finishGroupIfNecessary(); |
263 PagePopupClient::addString("],\n", data); | 283 PagePopupClient::addString("],\n", data); |
264 | 284 |
265 addProperty("anchorRectInScreen", anchorRectInScreen, data); | 285 addProperty("anchorRectInScreen", anchorRectInScreen, data); |
266 bool isRTL = !ownerStyle->isLeftToRightDirection(); | 286 bool isRTL = !ownerStyle->isLeftToRightDirection(); |
267 addProperty("isRTL", isRTL, data); | 287 addProperty("isRTL", isRTL, data); |
268 addProperty("paddingStart", isRTL ? m_client->clientPaddingRight().toDouble(
) : m_client->clientPaddingLeft().toDouble(), data); | 288 addProperty("paddingStart", isRTL ? m_client->clientPaddingRight().toDouble(
) : m_client->clientPaddingLeft().toDouble(), data); |
269 PagePopupClient::addString("};\n", data); | 289 PagePopupClient::addString("};\n", data); |
270 data->append(Platform::current()->loadResource("pickerCommon.js")); | 290 data->append(Platform::current()->loadResource("pickerCommon.js")); |
271 data->append(Platform::current()->loadResource("listPicker.js")); | 291 data->append(Platform::current()->loadResource("listPicker.js")); |
272 PagePopupClient::addString("</script></body>\n", data); | 292 PagePopupClient::addString("</script></body>\n", data); |
273 } | 293 } |
274 | 294 |
275 void PopupMenuImpl::addElementStyle(ItemIterationContext& context, HTMLElement&
element) | 295 void PopupMenuImpl::addElementStyle(ItemIterationContext& context, HTMLElement&
element) |
276 { | 296 { |
277 const ComputedStyle* style = m_client->computedStyleForItem(element); | 297 const ComputedStyle* style = m_client->computedStyleForItem(context.m_listIn
dex); |
278 ASSERT(style); | 298 ASSERT(style); |
279 SharedBuffer* data = context.m_buffer; | 299 SharedBuffer* data = context.m_buffer; |
280 // TODO(tkent): We generate unnecessary "style: {\n},\n" even if no | 300 // TODO(tkent): We generate unnecessary "style: {\n},\n" even if no |
281 // additional style. | 301 // additional style. |
282 PagePopupClient::addString("style: {\n", data); | 302 PagePopupClient::addString("style: {\n", data); |
283 if (style->visibility() == HIDDEN) | 303 if (style->visibility() == HIDDEN) |
284 addProperty("visibility", String("hidden"), data); | 304 addProperty("visibility", String("hidden"), data); |
285 if (style->display() == NONE) | 305 if (style->display() == NONE) |
286 addProperty("display", String("none"), data); | 306 addProperty("display", String("none"), data); |
287 if (context.m_direction != style->direction()) | 307 if (context.m_direction != style->direction()) |
(...skipping 29 matching lines...) Expand all Loading... |
317 addProperty("textTransform", String(textTransformToString(style->textTra
nsform())), data); | 337 addProperty("textTransform", String(textTransformToString(style->textTra
nsform())), data); |
318 | 338 |
319 PagePopupClient::addString("},\n", data); | 339 PagePopupClient::addString("},\n", data); |
320 } | 340 } |
321 | 341 |
322 void PopupMenuImpl::addOption(ItemIterationContext& context, HTMLOptionElement&
element) | 342 void PopupMenuImpl::addOption(ItemIterationContext& context, HTMLOptionElement&
element) |
323 { | 343 { |
324 SharedBuffer* data = context.m_buffer; | 344 SharedBuffer* data = context.m_buffer; |
325 PagePopupClient::addString("{", data); | 345 PagePopupClient::addString("{", data); |
326 addProperty("label", element.text(), data); | 346 addProperty("label", element.text(), data); |
327 ASSERT(context.m_listIndex == element.listIndex()); | 347 addProperty("value", context.m_listIndex, data); |
328 addProperty("value", context.m_listIndex++, data); | |
329 if (!element.title().isEmpty()) | 348 if (!element.title().isEmpty()) |
330 addProperty("title", element.title(), data); | 349 addProperty("title", element.title(), data); |
331 const AtomicString& ariaLabel = element.fastGetAttribute(HTMLNames::aria_lab
elAttr); | 350 const AtomicString& ariaLabel = element.fastGetAttribute(HTMLNames::aria_lab
elAttr); |
332 if (!ariaLabel.isEmpty()) | 351 if (!ariaLabel.isEmpty()) |
333 addProperty("ariaLabel", ariaLabel, data); | 352 addProperty("ariaLabel", ariaLabel, data); |
334 if (element.isDisabledFormControl()) | 353 if (element.isDisabledFormControl()) |
335 addProperty("disabled", true, data); | 354 addProperty("disabled", true, data); |
336 addElementStyle(context, element); | 355 addElementStyle(context, element); |
337 PagePopupClient::addString("},", data); | 356 PagePopupClient::addString("},", data); |
338 } | 357 } |
339 | 358 |
340 void PopupMenuImpl::addOptGroup(ItemIterationContext& context, HTMLOptGroupEleme
nt& element) | 359 void PopupMenuImpl::addOptGroup(ItemIterationContext& context, HTMLOptGroupEleme
nt& element) |
341 { | 360 { |
342 SharedBuffer* data = context.m_buffer; | 361 SharedBuffer* data = context.m_buffer; |
343 ++context.m_listIndex; | |
344 PagePopupClient::addString("{\n", data); | 362 PagePopupClient::addString("{\n", data); |
345 PagePopupClient::addString("type: \"optgroup\",\n", data); | 363 PagePopupClient::addString("type: \"optgroup\",\n", data); |
346 addProperty("label", element.groupLabelText(), data); | 364 addProperty("label", element.groupLabelText(), data); |
347 addProperty("title", element.title(), data); | 365 addProperty("title", element.title(), data); |
348 addProperty("ariaLabel", element.fastGetAttribute(HTMLNames::aria_labelAttr)
, data); | 366 addProperty("ariaLabel", element.fastGetAttribute(HTMLNames::aria_labelAttr)
, data); |
349 addProperty("disabled", element.isDisabledFormControl(), data); | 367 addProperty("disabled", element.isDisabledFormControl(), data); |
350 addElementStyle(context, element); | 368 addElementStyle(context, element); |
351 PagePopupClient::addString("children: [", data); | 369 context.startGroupChildren(); |
352 for (HTMLElement& child : Traversal<HTMLElement>::childrenOf(element)) { | 370 // We should call ItemIterationContext::finishGroupIfNecessary() later. |
353 if (isHTMLOptionElement(child)) | |
354 addOption(context, toHTMLOptionElement(child)); | |
355 if (isHTMLHRElement(child)) | |
356 addSeparator(context, toHTMLHRElement(child)); | |
357 } | |
358 PagePopupClient::addString("],\n", data); | |
359 PagePopupClient::addString("},\n", data); | |
360 } | 371 } |
361 | 372 |
362 void PopupMenuImpl::addSeparator(ItemIterationContext& context, HTMLHRElement& e
lement) | 373 void PopupMenuImpl::addSeparator(ItemIterationContext& context, HTMLHRElement& e
lement) |
363 { | 374 { |
364 SharedBuffer* data = context.m_buffer; | 375 SharedBuffer* data = context.m_buffer; |
365 ++context.m_listIndex; | |
366 PagePopupClient::addString("{\n", data); | 376 PagePopupClient::addString("{\n", data); |
367 PagePopupClient::addString("type: \"separator\",\n", data); | 377 PagePopupClient::addString("type: \"separator\",\n", data); |
368 addProperty("title", element.title(), data); | 378 addProperty("title", element.title(), data); |
369 addProperty("ariaLabel", element.fastGetAttribute(HTMLNames::aria_labelAttr)
, data); | 379 addProperty("ariaLabel", element.fastGetAttribute(HTMLNames::aria_labelAttr)
, data); |
370 addProperty("disabled", element.isDisabledFormControl(), data); | 380 addProperty("disabled", element.isDisabledFormControl(), data); |
371 addElementStyle(context, element); | 381 addElementStyle(context, element); |
372 PagePopupClient::addString("},\n", data); | 382 PagePopupClient::addString("},\n", data); |
373 } | 383 } |
374 | 384 |
375 void PopupMenuImpl::selectFontsFromOwnerDocument(Document& document) | 385 void PopupMenuImpl::selectFontsFromOwnerDocument(Document& document) |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
469 ownerElement().document().updateLayoutTreeIfNeeded(); | 479 ownerElement().document().updateLayoutTreeIfNeeded(); |
470 if (!m_client) | 480 if (!m_client) |
471 return; | 481 return; |
472 m_needsUpdate = false; | 482 m_needsUpdate = false; |
473 RefPtr<SharedBuffer> data = SharedBuffer::create(); | 483 RefPtr<SharedBuffer> data = SharedBuffer::create(); |
474 PagePopupClient::addString("window.updateData = {\n", data.get()); | 484 PagePopupClient::addString("window.updateData = {\n", data.get()); |
475 PagePopupClient::addString("type: \"update\",\n", data.get()); | 485 PagePopupClient::addString("type: \"update\",\n", data.get()); |
476 ItemIterationContext context(*ownerElement().computedStyle(), data.get()); | 486 ItemIterationContext context(*ownerElement().computedStyle(), data.get()); |
477 context.serializeBaseStyle(); | 487 context.serializeBaseStyle(); |
478 PagePopupClient::addString("children: [", data.get()); | 488 PagePopupClient::addString("children: [", data.get()); |
479 for (HTMLElement& child : Traversal<HTMLElement>::childrenOf(ownerElement())
) { | 489 for (; context.m_listIndex < m_client->listSize(); ++context.m_listIndex) { |
| 490 Element& child = m_client->itemElement(context.m_listIndex); |
| 491 if (!isHTMLOptGroupElement(child.parentNode())) |
| 492 context.finishGroupIfNecessary(); |
480 if (isHTMLOptionElement(child)) | 493 if (isHTMLOptionElement(child)) |
481 addOption(context, toHTMLOptionElement(child)); | 494 addOption(context, toHTMLOptionElement(child)); |
482 if (isHTMLOptGroupElement(child)) | 495 else if (isHTMLOptGroupElement(child)) |
483 addOptGroup(context, toHTMLOptGroupElement(child)); | 496 addOptGroup(context, toHTMLOptGroupElement(child)); |
484 if (isHTMLHRElement(child)) | 497 else if (isHTMLHRElement(child)) |
485 addSeparator(context, toHTMLHRElement(child)); | 498 addSeparator(context, toHTMLHRElement(child)); |
486 } | 499 } |
| 500 context.finishGroupIfNecessary(); |
487 PagePopupClient::addString("],\n", data.get()); | 501 PagePopupClient::addString("],\n", data.get()); |
488 PagePopupClient::addString("}\n", data.get()); | 502 PagePopupClient::addString("}\n", data.get()); |
489 m_popup->postMessage(String::fromUTF8(data->data(), data->size())); | 503 m_popup->postMessage(String::fromUTF8(data->data(), data->size())); |
490 } | 504 } |
491 | 505 |
492 | 506 |
493 void PopupMenuImpl::disconnectClient() | 507 void PopupMenuImpl::disconnectClient() |
494 { | 508 { |
495 m_client = nullptr; | 509 m_client = nullptr; |
496 // Cannot be done during finalization, so instead done when the | 510 // Cannot be done during finalization, so instead done when the |
497 // layout object is destroyed and disconnected. | 511 // layout object is destroyed and disconnected. |
498 dispose(); | 512 dispose(); |
499 } | 513 } |
500 | 514 |
501 } // namespace blink | 515 } // namespace blink |
OLD | NEW |