Chromium Code Reviews| Index: Source/core/html/HTMLMenuElement.cpp |
| diff --git a/Source/core/html/HTMLMenuElement.cpp b/Source/core/html/HTMLMenuElement.cpp |
| index 2783c047b6a4883d7ac6a990de7ca945c070696c..dc483c9c6304008fdbc17a89f3bfd41ba9715c1f 100644 |
| --- a/Source/core/html/HTMLMenuElement.cpp |
| +++ b/Source/core/html/HTMLMenuElement.cpp |
| @@ -21,18 +21,73 @@ |
| */ |
| #include "config.h" |
| + |
| #include "core/html/HTMLMenuElement.h" |
| -#include "HTMLNames.h" |
| +#include "core/dom/ElementTraversal.h" |
| +#include "core/events/EventListener.h" |
| +#include "core/events/RelatedEvent.h" |
| +#include "core/html/HTMLMenuitemElement.h" |
| +#include "core/page/ContextMenuController.h" |
| +#include "core/page/Page.h" |
| namespace WebCore { |
| using namespace HTMLNames; |
| +class HTMLMenuElementEventListener : public EventListener { |
|
esprehn
2014/05/20 05:51:34
FINAL
This class should also have it's own .h and
pals
2014/05/21 07:55:12
Done.
|
| +public: |
| + static PassRefPtr<HTMLMenuElementEventListener> create(HTMLMenuElement* menu) { return adoptRef(new HTMLMenuElementEventListener(menu)); } |
| + static const HTMLMenuElementEventListener* cast(const EventListener* listener) |
|
esprehn
2014/05/20 05:51:34
This should be an instance method, toHTMLMenuEleme
pals
2014/05/21 07:55:12
Done.
|
| + { |
| + return listener->type() == NativeEventListenerType |
| + ? static_cast<const HTMLMenuElementEventListener*>(listener) |
| + : 0; |
| + } |
| + |
| + virtual bool operator==(const EventListener& other); |
| + |
| +private: |
| + HTMLMenuElementEventListener(HTMLMenuElement* menu) |
|
esprehn
2014/05/20 05:51:34
missing explicit
pals
2014/05/21 07:55:12
Done.
|
| + : EventListener(NativeEventListenerType) |
| + , m_menu(menu) |
| + { |
| + } |
| + |
| + virtual void handleEvent(ExecutionContext*, Event*); |
| + |
| + HTMLMenuElement* m_menu; |
| +}; |
| + |
| +void HTMLMenuElementEventListener::handleEvent(ExecutionContext*, Event* event) |
| +{ |
| + if (event->type() == EventTypeNames::show && toRelatedEvent(event)->isRelatedEvent()) { |
| + Node* node = toRelatedEvent(event)->relatedTarget()->toNode(); |
| + if (node && node->isElementNode()) { |
| + const HTMLElement& element = toHTMLElement(*node); |
| + HTMLMenuElement* menuElement = element.menuElement(); |
| + if (menuElement) { |
| + menuElement->buildCustomProvider(); |
| + event->setDefaultHandled(); |
| + } |
| + } |
| + } |
| +} |
| + |
| +bool HTMLMenuElementEventListener::operator==(const EventListener& listener) |
| +{ |
| + if (const HTMLMenuElementEventListener* menuEventListener = HTMLMenuElementEventListener::cast(&listener)) |
| + return m_menu == menuEventListener->m_menu; |
| + return false; |
| +} |
| + |
| inline HTMLMenuElement::HTMLMenuElement(Document& document) |
| : HTMLElement(menuTag, document) |
| { |
| ScriptWrappable::init(this); |
| + // Add event listeners |
|
esprehn
2014/05/20 05:51:34
remove comment, it doesn't add value.
pals
2014/05/21 07:55:12
Done.
|
| + RefPtr<EventListener> listener = HTMLMenuElementEventListener::create(this); |
| + this->addEventListener("show", listener.release(), false); |
|
esprehn
2014/05/20 05:51:34
Remove this->, you don't need it.
pals
2014/05/21 07:55:12
Done.
|
| } |
| PassRefPtr<HTMLMenuElement> HTMLMenuElement::create(Document& document) |
| @@ -40,4 +95,31 @@ PassRefPtr<HTMLMenuElement> HTMLMenuElement::create(Document& document) |
| return adoptRef(new HTMLMenuElement(document)); |
| } |
| +void HTMLMenuElement::buildCustomProvider() |
| +{ |
| + m_menuItems.clear(); |
| + ContextMenu menu; |
| + populateContextMenuItems(this, menu); |
| + m_menuProvider = CustomContextMenuProvider::create(this, menu.items()); |
| +} |
| + |
| +void HTMLMenuElement::populateContextMenuItems(HTMLMenuElement* menu, ContextMenu& contextMenu) |
| +{ |
| + for (Element* nextElement = ElementTraversal::firstWithin(*menu); nextElement; nextElement = ElementTraversal::next(*nextElement)) { |
|
esprehn
2014/05/20 05:51:34
Missing scoping node, this will traverse all the w
pals
2014/05/21 07:55:12
Done.
|
| + if (nextElement->hasTagName(HTMLNames::menuTag)) { |
| + ContextMenu subMenu; |
| + populateContextMenuItems(toHTMLMenuElement(nextElement), subMenu); |
| + contextMenu.appendItem(ContextMenuItem(SubmenuType, ContextMenuItemCustomTagNoAction, nextElement->fastGetAttribute(HTMLNames::labelAttr), &subMenu)); |
| + } else { |
| + m_menuItems.append(toHTMLElement(nextElement)); |
|
esprehn
2014/05/20 05:51:34
Does the spec really say that anything is a menu i
pals
2014/05/21 07:55:12
Done.
|
| + contextMenu.appendItem(ContextMenuItem(ActionType, static_cast<ContextMenuAction>(ContextMenuItemBaseCustomTag + m_menuItems.size() - 1), nextElement->fastGetAttribute(HTMLNames::labelAttr))); |
|
esprehn
2014/05/20 05:51:34
This enum stuff doesn't look right.
pals
2014/05/21 07:55:12
I mostly followed the custom contextmenu implement
|
| + } |
| + } |
| +} |
| + |
| +HTMLElement* HTMLMenuElement::getSelectedMenuItem(unsigned menuId) |
| +{ |
| + return m_menuItems[menuId - ContextMenuItemBaseCustomTag]; |
| +} |
| + |
| } |