WebCore:
authoradele <adele@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 6 Jul 2006 05:47:30 +0000 (05:47 +0000)
committeradele <adele@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 6 Jul 2006 05:47:30 +0000 (05:47 +0000)
        Reviewed by Maciej and Hyatt.

        Initial implementation of popup menu control.  This can be turned on by setting -webkit-appearance: menulist on a select element.

        * WebCore.xcodeproj/project.pbxproj: Added RenderMenuList.h, RenderMenuList.cpp, RenderPopupMenu.h, RenderPopupMenu.cpp,
        RenderPopupMenuWin.h, RenderPopupMenuMac.h, RenderPopupMenuMac.mm,

        * dom/Node.cpp:
        (WebCore::Node::renderStyle): Added. Returns the renderer's style.  If there's no renderer, returns's a RenderStyle that's kept by the node.
        This is important for HTMLOptGroupElement and HTMLOptionElement, which don't have renderers.
        (WebCore::Node::setRenderStyle): Added.
        * dom/Node.h:
        * dom/Element.cpp: (WebCore::Element::recalcStyle): Updated to use renderStyle so recalcStyle will work for HTMLOptionElements and HTMLOptGroupElements.

        * css/cssstyleselector.cpp: Updated to call renderStyle method on the node, so resolving style works on elements w/o renderers that cache style.
        (WebCore::CSSStyleSelector::initForStyleResolve):
        (WebCore::CSSStyleSelector::locateCousinList):
        (WebCore::CSSStyleSelector::canShareStyleWithElement):
        (WebCore::CSSStyleSelector::locateSharedStyle):
        (WebCore::CSSStyleSelector::checkOneSelector):

        * css/html4.css: Removed display:none from options and optgroups, since we're now caching style for these elements.
        Added font-weight styles for option and optgroup.

        * html/HTMLOptGroupElement.h: Added m_style to keep track of a RenderStyle for the element, even though we aren't creating a renderer.
        This will allow us to honor style for optgroups and options for popup menus (and eventually list boxes too).
        (WebCore::HTMLOptGroupElement::rendererIsNeeded): Added.
        (WebCore::HTMLOptGroupElement::renderStyle): Added.
        * html/HTMLOptionElement.h: ditto.
        (WebCore::HTMLOptionElement::rendererIsNeeded): Added.
        (WebCore::HTMLOptionElement::renderStyle): Added.

        * html/HTMLOptGroupElement.cpp:
        (WebCore::HTMLOptGroupElement::HTMLOptGroupElement): Initialize m_style.
        (WebCore::HTMLOptGroupElement::attach): Set the renderStyle.
        (WebCore::HTMLOptGroupElement::detach): Clear m_style.
        (WebCore::HTMLOptGroupElement::setRenderStyle): Added.
        (WebCore::HTMLOptGroupElement::groupLabelText): Added.
        * html/HTMLOptionElement.cpp: ditto.
        (WebCore::HTMLOptionElement::HTMLOptionElement):
        (WebCore::HTMLOptionElement::attach):
        (WebCore::HTMLOptionElement::detach):
        (WebCore::HTMLOptionElement::setRenderStyle):
        (WebCore::HTMLOptionElement::optionText):

        * html/HTMLSelectElement.cpp: Added code to use the new RenderMenuList if the appearance is set to MenuListAppearance,
        and if we're not creating a list box renderer.
        (WebCore::HTMLSelectElement::recalcStyle):
        (WebCore::HTMLSelectElement::createRenderer):
        (WebCore::HTMLSelectElement::setRecalcListItems):
        (WebCore::HTMLSelectElement::reset):
        (WebCore::HTMLSelectElement::notifyOptionSelected):
        (WebCore::HTMLSelectElement::defaultEventHandler):
        * html/HTMLSelectElement.h:

        * WebCore.exp: Added _wkPopupMenu.
        * platform/mac/WebCoreSystemInterface.h: Added wkPopupMenu to get the NSMenu to pop up.
        * platform/mac/WebCoreSystemInterface.mm:

        * platform/win/TemporaryLinkStubs.cpp: Added stubs for RenderPopupMenuWin.
        (RenderPopupMenuWin::RenderPopupMenuWin):
        (RenderPopupMenuWin::~RenderPopupMenuWin):
        (RenderPopupMenuWin::clear):
        (RenderPopupMenuWin::populate):
        (RenderPopupMenuWin::showPopup):
        (RenderPopupMenuWin::addSeparator):
        (RenderPopupMenuWin::addGroupLabel):
        (RenderPopupMenuWin::addOption):
        * rendering/RenderPopupMenuWin.h: Added.

        * rendering/RenderPopupMenu.cpp: Added.
        (WebCore::RenderPopupMenu::RenderPopupMenu):
        (WebCore::RenderPopupMenu::~RenderPopupMenu):
        (WebCore::RenderPopupMenu::clear):
        (WebCore::RenderPopupMenu::populate): Walks the DOM tree, and adds separators, options, and group labels to the RenderPopupMenu.
        (WebCore::RenderPopupMenu::showPopup):
        (WebCore::RenderPopupMenu::addSeparator):
        (WebCore::RenderPopupMenu::addGroupLabel):
        (WebCore::RenderPopupMenu::addOption):
        * rendering/RenderPopupMenu.h: Added.
        (WebCore::RenderPopupMenu::renderName):
        (WebCore::RenderPopupMenu::getRenderMenuList):
        * rendering/RenderPopupMenuMac.h: Added.
        * rendering/RenderPopupMenuMac.mm: Added.
        (WebCore::RenderPopupMenuMac::RenderPopupMenuMac):
        (WebCore::RenderPopupMenuMac::~RenderPopupMenuMac):
        (WebCore::RenderPopupMenuMac::clear): Removes all items from the menu.
        (WebCore::RenderPopupMenuMac::populate): Disables menuChangedMessages before populating the menu.
        (WebCore::RenderPopupMenuMac::showPopup): Calculates the right position, and calls wkPopupMenu.
        (WebCore::RenderPopupMenuMac::addSeparator):
        (WebCore::RenderPopupMenuMac::addGroupLabel):
        (WebCore::RenderPopupMenuMac::addOption):

        * rendering/RenderMenuList.cpp: Added.
        (WebCore::RenderMenuList::RenderMenuList):
        (WebCore::RenderMenuList::addChild):
        (WebCore::RenderMenuList::removeChild):
        (WebCore::RenderMenuList::setStyle):
        (WebCore::RenderMenuList::updateFromElement): If the options have changed, iterate through the children to find the menu item with the widest text.
        Set the button text to the selected item's text.
        (WebCore::RenderMenuList::setText):
        (WebCore::RenderMenuList::paintObject):
        (WebCore::RenderMenuList::baselinePosition):
        (WebCore::RenderMenuList::calcMinMaxWidth):
        (WebCore::RenderMenuList::showPopup):
        (WebCore::RenderMenuList::layout):
        (WebCore::RenderMenuList::updateSelection):
        (WebCore::RenderMenuList::valueChanged):
        * rendering/RenderMenuList.h: Added.
        (WebCore::RenderMenuList::removeLeftoverAnonymousBoxes):
        (WebCore::RenderMenuList::allowsReusingAnonymousChild):
        (WebCore::RenderMenuList::canHaveChildren):
        (WebCore::RenderMenuList::renderName):
        (WebCore::RenderMenuList::setOptionsChanged):
        (WebCore::RenderMenuList::selectionChanged):
        (WebCore::RenderMenuList::setSelectionChanged):
        (WebCore::RenderMenuList::hasPopupMenu):

        * rendering/RenderTheme.cpp: Added cases for MenuListAppearance.
        (WebCore::RenderTheme::adjustStyle):
        (WebCore::RenderTheme::paint):
        (WebCore::RenderTheme::paintBorderOnly):
        (WebCore::RenderTheme::isControlStyled):
        (WebCore::RenderTheme::adjustMenuListStyle):
        (WebCore::RenderTheme::createPopupMenu): creates platform-specific RenderPopupMenu.
        * rendering/RenderTheme.h:
        (WebCore::RenderTheme::sizeOfArrowControl): Added.
        (WebCore::RenderTheme::paintMenuList): Added.
        * rendering/RenderThemeMac.h:
        * rendering/RenderThemeMac.mm:
        (WebCore::RenderThemeMac::adjustRepaintRect):
        (WebCore::RenderThemeMac::paintMenuList):
        (WebCore::RenderThemeMac::adjustMenuListStyle):
        (WebCore::RenderThemeMac::setPopupButtonCellState):
        (WebCore::RenderThemeMac::createPopupMenu):
        (WebCore::RenderThemeMac::sizeOfArrowControl):
        * rendering/RenderThemeWin.cpp: (WebCore::RenderThemeWin::createPopupMenu):
        * rendering/RenderThemeWin.h:

WebKit:

        Reviewed by Maciej and Hyatt.

        WebKit part of initial popup menu implementation.

        * WebCoreSupport/WebSystemInterface.m: (InitWebCoreSystemInterface):
        Initialize WKPopupMenu.

WebKitLibraries:

        Reviewed by Maciej and Hyatt.

        * WebKitSystemInterface.h: Updated.
        * libWebKitSystemInterface.a: Updated.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@15177 268f45cc-cd09-0410-ab3c-d52691b4dbfc

35 files changed:
WebCore/ChangeLog
WebCore/WebCore.exp
WebCore/WebCore.xcodeproj/project.pbxproj
WebCore/css/cssstyleselector.cpp
WebCore/css/html4.css
WebCore/dom/Element.cpp
WebCore/dom/Node.cpp
WebCore/dom/Node.h
WebCore/html/HTMLOptGroupElement.cpp
WebCore/html/HTMLOptGroupElement.h
WebCore/html/HTMLOptionElement.cpp
WebCore/html/HTMLOptionElement.h
WebCore/html/HTMLSelectElement.cpp
WebCore/html/HTMLSelectElement.h
WebCore/platform/mac/WebCoreSystemInterface.h
WebCore/platform/mac/WebCoreSystemInterface.mm
WebCore/platform/win/TemporaryLinkStubs.cpp
WebCore/rendering/RenderMenuList.cpp [new file with mode: 0644]
WebCore/rendering/RenderMenuList.h [new file with mode: 0644]
WebCore/rendering/RenderPopupMenu.cpp [new file with mode: 0644]
WebCore/rendering/RenderPopupMenu.h [new file with mode: 0644]
WebCore/rendering/RenderPopupMenuMac.h [new file with mode: 0644]
WebCore/rendering/RenderPopupMenuMac.mm [new file with mode: 0644]
WebCore/rendering/RenderPopupMenuWin.h [new file with mode: 0644]
WebCore/rendering/RenderTheme.cpp
WebCore/rendering/RenderTheme.h
WebCore/rendering/RenderThemeMac.h
WebCore/rendering/RenderThemeMac.mm
WebCore/rendering/RenderThemeWin.cpp
WebCore/rendering/RenderThemeWin.h
WebKit/ChangeLog
WebKit/WebCoreSupport/WebSystemInterface.m
WebKitLibraries/ChangeLog
WebKitLibraries/WebKitSystemInterface.h
WebKitLibraries/libWebKitSystemInterface.a

index 9fd8cb642a6bf6f7bd7d7d5ec51f65f3ce6b173e..61318944842cf2fcd870c8fc1f3e7b742be4ffb8 100644 (file)
@@ -1,3 +1,144 @@
+2006-07-05  Adele Peterson  <adele@apple.com>
+
+        Reviewed by Maciej and Hyatt.
+
+        Initial implementation of popup menu control.  This can be turned on by setting -webkit-appearance: menulist on a select element.
+
+        * WebCore.xcodeproj/project.pbxproj: Added RenderMenuList.h, RenderMenuList.cpp, RenderPopupMenu.h, RenderPopupMenu.cpp, 
+        RenderPopupMenuWin.h, RenderPopupMenuMac.h, RenderPopupMenuMac.mm, 
+    
+        * dom/Node.cpp:
+        (WebCore::Node::renderStyle): Added. Returns the renderer's style.  If there's no renderer, returns's a RenderStyle that's kept by the node.
+        This is important for HTMLOptGroupElement and HTMLOptionElement, which don't have renderers.
+        (WebCore::Node::setRenderStyle): Added.
+        * dom/Node.h:
+        * dom/Element.cpp: (WebCore::Element::recalcStyle): Updated to use renderStyle so recalcStyle will work for HTMLOptionElements and HTMLOptGroupElements.
+           
+        * css/cssstyleselector.cpp: Updated to call renderStyle method on the node, so resolving style works on elements w/o renderers that cache style. 
+        (WebCore::CSSStyleSelector::initForStyleResolve):
+        (WebCore::CSSStyleSelector::locateCousinList):
+        (WebCore::CSSStyleSelector::canShareStyleWithElement):
+        (WebCore::CSSStyleSelector::locateSharedStyle):
+        (WebCore::CSSStyleSelector::checkOneSelector):
+
+        * css/html4.css: Removed display:none from options and optgroups, since we're now caching style for these elements.
+        Added font-weight styles for option and optgroup.
+        
+        * html/HTMLOptGroupElement.h: Added m_style to keep track of a RenderStyle for the element, even though we aren't creating a renderer.
+        This will allow us to honor style for optgroups and options for popup menus (and eventually list boxes too).
+        (WebCore::HTMLOptGroupElement::rendererIsNeeded): Added.
+        (WebCore::HTMLOptGroupElement::renderStyle): Added.
+        * html/HTMLOptionElement.h: ditto.
+        (WebCore::HTMLOptionElement::rendererIsNeeded): Added.
+        (WebCore::HTMLOptionElement::renderStyle): Added.
+        
+        * html/HTMLOptGroupElement.cpp:
+        (WebCore::HTMLOptGroupElement::HTMLOptGroupElement): Initialize m_style.
+        (WebCore::HTMLOptGroupElement::attach): Set the renderStyle.
+        (WebCore::HTMLOptGroupElement::detach): Clear m_style.
+        (WebCore::HTMLOptGroupElement::setRenderStyle): Added.
+        (WebCore::HTMLOptGroupElement::groupLabelText): Added.
+        * html/HTMLOptionElement.cpp: ditto.
+        (WebCore::HTMLOptionElement::HTMLOptionElement):
+        (WebCore::HTMLOptionElement::attach):
+        (WebCore::HTMLOptionElement::detach):
+        (WebCore::HTMLOptionElement::setRenderStyle):
+        (WebCore::HTMLOptionElement::optionText):
+
+        * html/HTMLSelectElement.cpp: Added code to use the new RenderMenuList if the appearance is set to MenuListAppearance, 
+        and if we're not creating a list box renderer.
+        (WebCore::HTMLSelectElement::recalcStyle):
+        (WebCore::HTMLSelectElement::createRenderer):
+        (WebCore::HTMLSelectElement::setRecalcListItems):
+        (WebCore::HTMLSelectElement::reset):
+        (WebCore::HTMLSelectElement::notifyOptionSelected):
+        (WebCore::HTMLSelectElement::defaultEventHandler):
+        * html/HTMLSelectElement.h:
+
+        * WebCore.exp: Added _wkPopupMenu.
+        * platform/mac/WebCoreSystemInterface.h: Added wkPopupMenu to get the NSMenu to pop up.
+        * platform/mac/WebCoreSystemInterface.mm:
+
+        * platform/win/TemporaryLinkStubs.cpp: Added stubs for RenderPopupMenuWin.
+        (RenderPopupMenuWin::RenderPopupMenuWin):
+        (RenderPopupMenuWin::~RenderPopupMenuWin):
+        (RenderPopupMenuWin::clear):
+        (RenderPopupMenuWin::populate):
+        (RenderPopupMenuWin::showPopup):
+        (RenderPopupMenuWin::addSeparator):
+        (RenderPopupMenuWin::addGroupLabel):
+        (RenderPopupMenuWin::addOption):
+        * rendering/RenderPopupMenuWin.h: Added.
+
+        * rendering/RenderPopupMenu.cpp: Added.
+        (WebCore::RenderPopupMenu::RenderPopupMenu):
+        (WebCore::RenderPopupMenu::~RenderPopupMenu):
+        (WebCore::RenderPopupMenu::clear):
+        (WebCore::RenderPopupMenu::populate): Walks the DOM tree, and adds separators, options, and group labels to the RenderPopupMenu.
+        (WebCore::RenderPopupMenu::showPopup):
+        (WebCore::RenderPopupMenu::addSeparator):
+        (WebCore::RenderPopupMenu::addGroupLabel):
+        (WebCore::RenderPopupMenu::addOption):
+        * rendering/RenderPopupMenu.h: Added.
+        (WebCore::RenderPopupMenu::renderName):
+        (WebCore::RenderPopupMenu::getRenderMenuList):
+        * rendering/RenderPopupMenuMac.h: Added.
+        * rendering/RenderPopupMenuMac.mm: Added.
+        (WebCore::RenderPopupMenuMac::RenderPopupMenuMac):
+        (WebCore::RenderPopupMenuMac::~RenderPopupMenuMac):
+        (WebCore::RenderPopupMenuMac::clear): Removes all items from the menu.
+        (WebCore::RenderPopupMenuMac::populate): Disables menuChangedMessages before populating the menu.
+        (WebCore::RenderPopupMenuMac::showPopup): Calculates the right position, and calls wkPopupMenu.
+        (WebCore::RenderPopupMenuMac::addSeparator):
+        (WebCore::RenderPopupMenuMac::addGroupLabel):
+        (WebCore::RenderPopupMenuMac::addOption):
+        
+        * rendering/RenderMenuList.cpp: Added.
+        (WebCore::RenderMenuList::RenderMenuList):
+        (WebCore::RenderMenuList::addChild):
+        (WebCore::RenderMenuList::removeChild):
+        (WebCore::RenderMenuList::setStyle):
+        (WebCore::RenderMenuList::updateFromElement): If the options have changed, iterate through the children to find the menu item with the widest text.
+        Set the button text to the selected item's text.
+        (WebCore::RenderMenuList::setText):
+        (WebCore::RenderMenuList::paintObject):
+        (WebCore::RenderMenuList::baselinePosition):
+        (WebCore::RenderMenuList::calcMinMaxWidth):
+        (WebCore::RenderMenuList::showPopup):
+        (WebCore::RenderMenuList::layout):
+        (WebCore::RenderMenuList::updateSelection):
+        (WebCore::RenderMenuList::valueChanged):
+        * rendering/RenderMenuList.h: Added.
+        (WebCore::RenderMenuList::removeLeftoverAnonymousBoxes):
+        (WebCore::RenderMenuList::allowsReusingAnonymousChild):
+        (WebCore::RenderMenuList::canHaveChildren):
+        (WebCore::RenderMenuList::renderName):
+        (WebCore::RenderMenuList::setOptionsChanged):
+        (WebCore::RenderMenuList::selectionChanged):
+        (WebCore::RenderMenuList::setSelectionChanged):
+        (WebCore::RenderMenuList::hasPopupMenu):
+
+        * rendering/RenderTheme.cpp: Added cases for MenuListAppearance.
+        (WebCore::RenderTheme::adjustStyle):
+        (WebCore::RenderTheme::paint):
+        (WebCore::RenderTheme::paintBorderOnly):
+        (WebCore::RenderTheme::isControlStyled):
+        (WebCore::RenderTheme::adjustMenuListStyle):
+        (WebCore::RenderTheme::createPopupMenu): creates platform-specific RenderPopupMenu.
+        * rendering/RenderTheme.h:
+        (WebCore::RenderTheme::sizeOfArrowControl): Added. 
+        (WebCore::RenderTheme::paintMenuList): Added.
+        * rendering/RenderThemeMac.h:
+        * rendering/RenderThemeMac.mm:
+        (WebCore::RenderThemeMac::adjustRepaintRect):
+        (WebCore::RenderThemeMac::paintMenuList):
+        (WebCore::RenderThemeMac::adjustMenuListStyle):
+        (WebCore::RenderThemeMac::setPopupButtonCellState):
+        (WebCore::RenderThemeMac::createPopupMenu):
+        (WebCore::RenderThemeMac::sizeOfArrowControl):
+        * rendering/RenderThemeWin.cpp: (WebCore::RenderThemeWin::createPopupMenu):
+        * rendering/RenderThemeWin.h:
+
 2006-07-05  Brady Eidson  <beidson@apple.com>
 
         Reviewed by Tim Omernick.
index 49ad23f174a35e20788f5a6cbc1b3bde357e7f8f..132159dee845af68505c2a3c805e07c6f6f349b6 100644 (file)
@@ -147,6 +147,7 @@ _wkGetGlyphVectorRecordSize
 _wkGetMIMETypeForExtension
 _wkGetNSFontATSUFontId
 _wkInitializeGlyphVector
+_wkPopupMenu
 _wkReleaseStyleGroup
 _wkSetCGFontRenderingMode
 _wkSetDragImage
index 738984b574d08ab64f96ddb077f5a0eeeb832222..f6841fe1e923803505694c08435bb17dfbb909e3 100644 (file)
                AB4261D80A2F6C9700BDD17D /* missingImage.tiff in Resources */ = {isa = PBXBuildFile; fileRef = AB4261D70A2F6C9700BDD17D /* missingImage.tiff */; };
                AB67D1A8097F3AE300F9392E /* RenderTextField.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AB67D1A6097F3AE300F9392E /* RenderTextField.cpp */; };
                AB67D1A9097F3AE300F9392E /* RenderTextField.h in Headers */ = {isa = PBXBuildFile; fileRef = AB67D1A7097F3AE300F9392E /* RenderTextField.h */; };
+               ABDDFE790A5C6E7000A3E11D /* RenderMenuList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABDDFE730A5C6E6F00A3E11D /* RenderMenuList.cpp */; };
+               ABDDFE7A0A5C6E7000A3E11D /* RenderMenuList.h in Headers */ = {isa = PBXBuildFile; fileRef = ABDDFE740A5C6E7000A3E11D /* RenderMenuList.h */; };
+               ABDDFE7B0A5C6E7000A3E11D /* RenderPopupMenu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABDDFE750A5C6E7000A3E11D /* RenderPopupMenu.cpp */; };
+               ABDDFE7C0A5C6E7000A3E11D /* RenderPopupMenu.h in Headers */ = {isa = PBXBuildFile; fileRef = ABDDFE760A5C6E7000A3E11D /* RenderPopupMenu.h */; };
+               ABDDFE7D0A5C6E7000A3E11D /* RenderPopupMenuMac.h in Headers */ = {isa = PBXBuildFile; fileRef = ABDDFE770A5C6E7000A3E11D /* RenderPopupMenuMac.h */; };
+               ABDDFE7E0A5C6E7000A3E11D /* RenderPopupMenuMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = ABDDFE780A5C6E7000A3E11D /* RenderPopupMenuMac.mm */; };
                ABE7B5230A489F830031881C /* DeprecatedRenderSelect.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ABE7B5210A489F830031881C /* DeprecatedRenderSelect.cpp */; };
                ABE7B5240A489F830031881C /* DeprecatedRenderSelect.h in Headers */ = {isa = PBXBuildFile; fileRef = ABE7B5220A489F830031881C /* DeprecatedRenderSelect.h */; };
                BC066F6F09FEB2FA00C589A7 /* WebCoreTextRenderer.h in Headers */ = {isa = PBXBuildFile; fileRef = BC066F6C09FEB2FA00C589A7 /* WebCoreTextRenderer.h */; settings = {ATTRIBUTES = (Private, ); }; };
                AB4261D70A2F6C9700BDD17D /* missingImage.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = missingImage.tiff; sourceTree = "<group>"; };
                AB67D1A6097F3AE300F9392E /* RenderTextField.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = RenderTextField.cpp; sourceTree = "<group>"; };
                AB67D1A7097F3AE300F9392E /* RenderTextField.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = RenderTextField.h; sourceTree = "<group>"; };
+               ABDDFE730A5C6E6F00A3E11D /* RenderMenuList.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = RenderMenuList.cpp; sourceTree = "<group>"; };
+               ABDDFE740A5C6E7000A3E11D /* RenderMenuList.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = RenderMenuList.h; sourceTree = "<group>"; };
+               ABDDFE750A5C6E7000A3E11D /* RenderPopupMenu.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = RenderPopupMenu.cpp; sourceTree = "<group>"; };
+               ABDDFE760A5C6E7000A3E11D /* RenderPopupMenu.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = RenderPopupMenu.h; sourceTree = "<group>"; };
+               ABDDFE770A5C6E7000A3E11D /* RenderPopupMenuMac.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = RenderPopupMenuMac.h; sourceTree = "<group>"; };
+               ABDDFE780A5C6E7000A3E11D /* RenderPopupMenuMac.mm */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.objcpp; path = RenderPopupMenuMac.mm; sourceTree = "<group>"; };
                ABE7B5210A489F830031881C /* DeprecatedRenderSelect.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = DeprecatedRenderSelect.cpp; sourceTree = "<group>"; };
                ABE7B5220A489F830031881C /* DeprecatedRenderSelect.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DeprecatedRenderSelect.h; sourceTree = "<group>"; };
                BC066F6C09FEB2FA00C589A7 /* WebCoreTextRenderer.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = WebCoreTextRenderer.h; sourceTree = "<group>"; };
                F523D2F302DE443B018635CA /* rendering */ = {
                        isa = PBXGroup;
                        children = (
+                               ABDDFE730A5C6E6F00A3E11D /* RenderMenuList.cpp */,
+                               ABDDFE740A5C6E7000A3E11D /* RenderMenuList.h */,
+                               ABDDFE750A5C6E7000A3E11D /* RenderPopupMenu.cpp */,
+                               ABDDFE760A5C6E7000A3E11D /* RenderPopupMenu.h */,
+                               ABDDFE770A5C6E7000A3E11D /* RenderPopupMenuMac.h */,
+                               ABDDFE780A5C6E7000A3E11D /* RenderPopupMenuMac.mm */,
                                ABE7B5210A489F830031881C /* DeprecatedRenderSelect.cpp */,
                                ABE7B5220A489F830031881C /* DeprecatedRenderSelect.h */,
                                A8CFF04B0A154F09000A4234 /* AutoTableLayout.cpp */,
                                1A1D13800A5325520064BF5F /* DOMXPath.h in Headers */,
                                1A1D13CA0A5329090064BF5F /* DOMXPathInternal.h in Headers */,
                                93A1EAA80A563508006960A0 /* ImageDocumentMac.h in Headers */,
+                               ABDDFE7A0A5C6E7000A3E11D /* RenderMenuList.h in Headers */,
+                               ABDDFE7C0A5C6E7000A3E11D /* RenderPopupMenu.h in Headers */,
+                               ABDDFE7D0A5C6E7000A3E11D /* RenderPopupMenuMac.h in Headers */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                516149ED0A525E3A003DFC7A /* SiteIcon.cpp in Sources */,
                                1A1D13810A5325520064BF5F /* DOMXPath.mm in Sources */,
                                93A1EAA00A5634C9006960A0 /* ImageDocumentMac.mm in Sources */,
+                               ABDDFE790A5C6E7000A3E11D /* RenderMenuList.cpp in Sources */,
+                               ABDDFE7B0A5C6E7000A3E11D /* RenderPopupMenu.cpp in Sources */,
+                               ABDDFE7E0A5C6E7000A3E11D /* RenderPopupMenuMac.mm in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
index 7204c600ae861d6e27687f254fe67febc86e07c7..0df1a6719bf662f743ee9f90b9310be9797f70cf 100644 (file)
@@ -545,7 +545,7 @@ void CSSStyleSelector::initForStyleResolve(Element* e, RenderStyle* defaultParen
     if (defaultParent)
         parentStyle = defaultParent;
     else
-        parentStyle = (parentNode && parentNode->renderer()) ? parentNode->renderer()->style() : 0;
+        parentStyle = parentNode ? parentNode->renderStyle() : 0;
     view = element->document()->view();
     isXMLDoc = !element->document()->isHTMLDocument();
     frame = element->document()->frame();
@@ -641,12 +641,12 @@ Node* CSSStyleSelector::locateCousinList(Element* parent)
 {
     if (parent && parent->isStyledElement()) {
         StyledElement* p = static_cast<StyledElement*>(parent);
-        if (p->renderer() && !p->inlineStyleDecl() && !p->hasID()) {
+        if (!p->inlineStyleDecl() && !p->hasID()) {
             Node* r = p->previousSibling();
             int subcount = 0;
-            RenderStyle* st = p->renderer()->style();
+            RenderStyle* st = p->renderStyle();
             while (r) {
-                if (r->renderer() && r->renderer()->style() == st)
+                if (r->renderStyle() == st)
                     return r->lastChild();
                 if (subcount++ == siblingThreshold)
                     return 0;
@@ -655,7 +655,7 @@ Node* CSSStyleSelector::locateCousinList(Element* parent)
             if (!r)
                 r = locateCousinList(static_cast<Element*>(parent->parentNode()));
             while (r) {
-                if (r->renderer() && r->renderer()->style() == st)
+                if (r->renderStyle() == st)
                     return r->lastChild();
                 if (subcount++ == siblingThreshold)
                     return 0;
@@ -670,12 +670,13 @@ bool CSSStyleSelector::canShareStyleWithElement(Node* n)
 {
     if (n->isStyledElement()) {
         StyledElement* s = static_cast<StyledElement*>(n);
-        if (s->renderer() && !s->renderer()->style()->unique() &&
+        RenderStyle* style = s->renderStyle();
+        if (style && !style->unique() &&
             (s->tagQName() == element->tagQName()) && !s->hasID() &&
             (s->hasClass() == element->hasClass()) && !s->inlineStyleDecl() &&
             (s->hasMappedAttributes() == styledElement->hasMappedAttributes()) &&
             (s->isLink() == element->isLink()) && 
-            !s->renderer()->style()->affectedByAttributeSelectors() &&
+            !style->affectedByAttributeSelectors() &&
             (s->hovered() == element->hovered()) &&
             (s->active() == element->active()) &&
             (s->focused() == element->focused()) &&
@@ -702,9 +703,9 @@ bool CSSStyleSelector::canShareStyleWithElement(Node* n)
                         Color linkColor = element->document()->linkColor();
                         Color visitedColor = element->document()->visitedLinkColor();
                         if (pseudoState == PseudoUnknown)
-                            checkPseudoState(element, s->renderer()->style()->pseudoState() != PseudoAnyLink ||
+                            checkPseudoState(element, style->pseudoState() != PseudoAnyLink ||
                                              linkColor != visitedColor);
-                        linksMatch = (pseudoState == s->renderer()->style()->pseudoState());
+                        linksMatch = (pseudoState == style->pseudoState());
                     }
                     
                     if (linksMatch)
@@ -726,7 +727,7 @@ RenderStyle* CSSStyleSelector::locateSharedStyle()
         for (n = element->previousSibling(); n && !n->isElementNode(); n = n->previousSibling());
         while (n) {
             if (canShareStyleWithElement(n))
-                return n->renderer()->style();
+                return n->renderStyle();
             if (count++ == siblingThreshold)
                 return 0;
             for (n = n->previousSibling(); n && !n->isElementNode(); n = n->previousSibling());
@@ -735,7 +736,7 @@ RenderStyle* CSSStyleSelector::locateSharedStyle()
             n = locateCousinList(static_cast<Element*>(element->parentNode()));
         while (n) {
             if (canShareStyleWithElement(n))
-                return n->renderer()->style();
+                return n->renderStyle();
             if (count++ == siblingThreshold)
                 return 0;
             for (n = n->previousSibling(); n && !n->isElementNode(); n = n->previousSibling());
@@ -1482,24 +1483,20 @@ bool CSSStyleSelector::checkOneSelector(CSSSelector* sel, Element* e, bool isSub
                 if (strictParsing || isSubSelector || sel->relation() == CSSSelector::SubSelector || (sel->hasTag() && !e->hasTagName(aTag)) || e->isLink()) {
                     if (element == e && style)
                         style->setAffectedByHoverRules(true);
-                    if (e->renderer()) {
-                        if (element != e)
-                            e->renderer()->style()->setAffectedByHoverRules(true);
+                        if (element != e && e->renderStyle())
+                            e->renderStyle()->setAffectedByHoverRules(true);
                         if (e->hovered())
                             return true;
-                    }
                 }
                 break;
             }
             case CSSSelector::PseudoDrag: {
                 if (element == e && style)
                     style->setAffectedByDragRules(true);
-                if (e->renderer()) {
-                    if (element != e)
-                        e->renderer()->style()->setAffectedByDragRules(true);
-                    if (e->renderer()->isDragging())
+                    if (element != e && e->renderStyle())
+                        e->renderStyle()->setAffectedByDragRules(true);
+                    if (e->renderer() && e->renderer()->isDragging())
                         return true;
-                }
                 break;
             }
             case CSSSelector::PseudoFocus:
@@ -1512,8 +1509,8 @@ bool CSSStyleSelector::checkOneSelector(CSSSelector* sel, Element* e, bool isSub
                 if (strictParsing || isSubSelector || sel->relation() == CSSSelector::SubSelector || (sel->hasTag() && !e->hasTagName(aTag)) || e->isLink()) {
                     if (element == e && style)
                         style->setAffectedByActiveRules(true);
-                    else if (e->renderer())
-                        e->renderer()->style()->setAffectedByActiveRules(true);
+                    else if (e->renderStyle())
+                        e->renderStyle()->setAffectedByActiveRules(true);
                     if (e->active())
                         return true;
                 }
index c5da69ee3f1341d8785ba2d0eee7ecdb1e896d97..cfea1eeb33b232812d2bfc6fa95c84d53b0c2fad 100644 (file)
@@ -384,7 +384,7 @@ select, button, input[type="button"], input[type="image"], input[type="submit"],
     -webkit-user-select: ignore
 }
 
-option, optgroup, area, param {
+area, param {
     display: none
 }
 
@@ -399,9 +399,19 @@ input[type="radio"] {
 }
 
 select {
+    // FIXME: Uncomment this when flipping the switch to use the new popup menu implementation
+    // -webkit-appearance: menulist;
     box-sizing: border-box;
 }
 
+optgroup {
+    font-weight: bolder;
+}
+
+option {
+    font-weight: normal;
+}
+
 /* inline elements */
 
 u, ins {
index 19df05e7e70ee6e86d31233c5df42f191ddf2684..2c0faa8c15cb31a23a8ba9209c24b570c7d1f0da 100644 (file)
@@ -543,41 +543,44 @@ void Element::attach()
     ContainerNode::attach();
 }
 
-void Element::recalcStyle( StyleChange change )
+void Element::recalcStyle(StyleChange change)
 {
     // ### should go away and be done in renderobject
-    RenderStyle* _style = renderer() ? renderer()->style() : 0;
-    bool hasParentRenderer = parent() ? parent()->renderer() : false;
+    RenderStyle* _style = renderStyle();
+    bool hasParentStyle = parentNode() ? parentNode()->renderStyle() : false;
     
-    if ( hasParentRenderer && (change >= Inherit || changed()) ) {
+    if (hasParentStyle && (change >= Inherit || changed())) {
         RenderStyle *newStyle = document()->styleSelector()->styleForElement(this);
-        StyleChange ch = diff( _style, newStyle );
+        StyleChange ch = diff(_style, newStyle);
         if (ch == Detach) {
             if (attached())
                 detach();
             // ### Suboptimal. Style gets calculated again.
             attach();
             // attach recalulates the style for all children. No need to do it twice.
-            setChanged( false );
-            setHasChangedChild( false );
+            setChanged(false);
+            setHasChangedChild(false);
             newStyle->deref(document()->renderArena());
             return;
         }
         else if (ch != NoChange) {
-            if (renderer() && newStyle)
-                renderer()->setStyle(newStyle);
+            if (newStyle)
+                setRenderStyle(newStyle);
         }
-        else if (changed() && renderer() && newStyle && (document()->usesSiblingRules() || document()->usesDescendantRules())) {
+        else if (changed() && newStyle && (document()->usesSiblingRules() || document()->usesDescendantRules())) {
             // Although no change occurred, we use the new style so that the cousin style sharing code won't get
             // fooled into believing this style is the same.  This is only necessary if the document actually uses
             // sibling/descendant rules, since otherwise it isn't possible for ancestor styles to affect sharing of
             // descendants.
-            renderer()->setStyleInternal(newStyle);
+            if (renderer())
+                renderer()->setStyleInternal(newStyle);
+            else
+                setRenderStyle(newStyle);
         }
 
         newStyle->deref(document()->renderArena());
 
-        if ( change != Force) {
+        if (change != Force) {
             if (document()->usesDescendantRules())
                 change = Force;
             else
@@ -590,8 +593,8 @@ void Element::recalcStyle( StyleChange change )
             n->recalcStyle(change);
     }
 
-    setChanged( false );
-    setHasChangedChild( false );
+    setChanged(false);
+    setHasChangedChild(false);
 }
 
 bool Element::childTypeAllowed(NodeType type)
index 1ad95b8d0aebaf5708056ae56c3970004d1ebb68..b6cb4d58e48493c27a9890585abdc7c2a8ef66f2 100644 (file)
@@ -940,6 +940,16 @@ RenderObject *Node::createRenderer(RenderArena *arena, RenderStyle *style)
     return 0;
 }
 
+RenderStyle* Node::renderStyle()
+{ 
+    return m_renderer ? m_renderer->style() : 0; 
+}
+
+void Node::setRenderStyle(RenderStyle* s) {
+    if (m_renderer)
+        m_renderer->setStyle(s); 
+}
+
 int Node::maxOffset() const
 {
     return 1;
index 6a4d99f66881fbd0a82eda5e467490ee8424c1d3..a17c9a94c89fcc196071dac558458912ac0d3892 100644 (file)
@@ -365,6 +365,10 @@ public:
     virtual bool childShouldCreateRenderer(Node*) const { return true; }
 #endif
     virtual RenderObject* createRenderer(RenderArena*, RenderStyle*);
+    
+    // Wrapper for nodes that don't have a renderer, but still cache the style (like HTMLOptionElement).
+    virtual RenderStyle* renderStyle();
+    virtual void setRenderStyle(RenderStyle* s);
 
     // -----------------------------------------------------------------------------
     // Notification of document structure changes
index 077f5a025cef937d0aa523f0b0009ba77915ae18..d9077ef62c3cb9bf6ff7f578b29e39bd57cda7ac 100644 (file)
 #include "config.h"
 #include "HTMLOptGroupElement.h"
 
+#include "Document.h"
+#include "cssstyleselector.h"
 #include "HTMLSelectElement.h"
 #include "HTMLNames.h"
+#include "RenderMenuList.h"
 
 namespace WebCore {
 
@@ -36,10 +39,7 @@ using namespace HTMLNames;
 
 HTMLOptGroupElement::HTMLOptGroupElement(Document* doc, HTMLFormElement* f)
     : HTMLGenericFormElement(optgroupTag, doc, f)
-{
-}
-
-HTMLOptGroupElement::~HTMLOptGroupElement()
+    , m_style(0)
 {
 }
 
@@ -123,5 +123,44 @@ bool HTMLOptGroupElement::checkDTD(const Node* newChild)
 {
     return newChild->hasTagName(HTMLNames::optionTag) || newChild->hasTagName(HTMLNames::hrTag);
 }
+
+void HTMLOptGroupElement::attach()
+{
+    setRenderStyle(styleForRenderer(0));
+    HTMLGenericFormElement::attach();
+}
+
+void HTMLOptGroupElement::detach()
+{
+    if (m_style) {
+        m_style->deref(document()->renderArena());
+        m_style = 0;
+    }
+    HTMLGenericFormElement::detach();
+}
+
+void HTMLOptGroupElement::setRenderStyle( RenderStyle* newStyle )
+{
+    RenderStyle* oldStyle = m_style;
+    m_style = newStyle;
+     if (m_style)
+        m_style->ref();
+    
+    if (oldStyle)
+        oldStyle->deref(document()->renderArena());
+}
+
+String HTMLOptGroupElement::groupLabelText()
+{
+    DeprecatedString itemText = getAttribute(labelAttr).deprecatedString();
+    
+    itemText.replace('\\', document()->backslashAsCurrencySymbol());
+    // In WinIE, leading and trailing whitespace is ignored in options and optgroups. We match this behavior.
+    itemText = itemText.stripWhiteSpace();
+    // We want to collapse our whitespace too.  This will match other browsers.
+    itemText = itemText.simplifyWhiteSpace();
+        
+    return itemText;
+}
  
 } // namespace
index ef554220349e788d5241dd1116eaea5ac0976223..16303501f8e164dbde915abf2f411daee0c9328b 100644 (file)
@@ -33,7 +33,6 @@ namespace WebCore {
 class HTMLOptGroupElement : public HTMLGenericFormElement {
 public:
     HTMLOptGroupElement(Document*, HTMLFormElement* = 0);
-    virtual ~HTMLOptGroupElement();
 
     virtual bool checkDTD(const Node*);
     virtual const AtomicString& type() const;
@@ -44,11 +43,21 @@ public:
     virtual bool appendChild(PassRefPtr<Node> newChild, ExceptionCode&);
     virtual ContainerNode* addChild(PassRefPtr<Node>);
     virtual void parseMappedAttribute(MappedAttribute*);
+    virtual bool rendererIsNeeded(RenderStyle*) { return false; }
+    virtual void attach();
+    virtual void detach();
+    virtual RenderStyle* renderStyle() const { return m_style; }
+    virtual void setRenderStyle(RenderStyle* s);
 
     void recalcSelectOptions();
 
     String label() const;
     void setLabel(const String&);
+    
+    String groupLabelText();
+    
+private:
+    RenderStyle* m_style;
 };
 
 } //namespace
index 102d39a57d456cfaa4eac52f8c0821df11375590..adc6a3b2b8b295853444b00ab3b4588359a1f97b 100644 (file)
 #include "HTMLOptionElement.h"
 
 #include "Document.h"
+#include "cssstyleselector.h"
 #include "ExceptionCode.h"
 #include "HTMLNames.h"
 #include "HTMLSelectElement.h"
+#include "RenderMenuList.h"
 #include "Text.h"
 #include <wtf/Vector.h>
 
@@ -41,6 +43,7 @@ using namespace HTMLNames;
 HTMLOptionElement::HTMLOptionElement(Document* doc, HTMLFormElement* f)
     : HTMLGenericFormElement(optionTag, doc, f)
     , m_selected(false)
+    , m_style(0)
 {
 }
 
@@ -49,6 +52,21 @@ bool HTMLOptionElement::checkDTD(const Node* newChild)
     return newChild->isTextNode() || newChild->hasTagName(scriptTag);
 }
 
+void HTMLOptionElement::attach()
+{
+    setRenderStyle(styleForRenderer(0));
+    HTMLGenericFormElement::attach();
+}
+
+void HTMLOptionElement::detach()
+{
+    if (m_style) {
+        m_style->deref(document()->renderArena());
+        m_style = 0;
+    }
+    HTMLGenericFormElement::detach();
+}
+
 bool HTMLOptionElement::isFocusable() const
 {
     return false;
@@ -192,4 +210,32 @@ void HTMLOptionElement::setLabel(const String& value)
     setAttribute(labelAttr, value);
 }
 
+void HTMLOptionElement::setRenderStyle( RenderStyle* newStyle )
+{
+    RenderStyle* oldStyle = m_style;
+    m_style = newStyle;
+     if (m_style)
+        m_style->ref();
+    
+    if (oldStyle)
+        oldStyle->deref(document()->renderArena());
+}
+
+String HTMLOptionElement::optionText()
+{
+    DeprecatedString itemText = text().deprecatedString();
+    if (itemText.isEmpty())
+        itemText = getAttribute(labelAttr).deprecatedString();
+    
+    itemText.replace('\\', document()->backslashAsCurrencySymbol());
+    // In WinIE, leading and trailing whitespace is ignored in options and optgroups. We match this behavior.
+    itemText = itemText.stripWhiteSpace();
+    // We want to collapse our whitespace too.  This will match other browsers.
+    itemText = itemText.simplifyWhiteSpace();
+    if (parentNode() && parentNode()->hasTagName(optgroupTag))
+        itemText.prepend("    ");
+        
+    return itemText;
+}
+
 } // namespace
index 1659f72f8dc7a53769f2a1ea85c1b31377fd8581..50657522eb3c33c6280f317c29ed7a9b2ba2d06d 100644 (file)
@@ -38,6 +38,7 @@ class HTMLOptionElement : public HTMLGenericFormElement
 {
     friend class DeprecatedRenderSelect;
     friend class HTMLSelectElement;
+    friend class RenderMenuList;
 
 public:
     HTMLOptionElement(Document*, HTMLFormElement* = 0);
@@ -46,7 +47,12 @@ public:
     virtual int tagPriority() const { return 2; }
     virtual bool checkDTD(const Node* newChild);
     virtual bool isFocusable() const;
-
+    virtual bool rendererIsNeeded(RenderStyle*) { return false; }
+    virtual void attach();
+    virtual void detach();
+    virtual RenderStyle* renderStyle() const { return m_style; }
+    virtual void setRenderStyle(RenderStyle*);
+    
     virtual const AtomicString& type() const;
 
     String text() const;
@@ -71,10 +77,13 @@ public:
 
     String label() const;
     void setLabel(const String&);
+    
+    String optionText();
 
 private:
     String m_value;
     bool m_selected;
+    RenderStyle* m_style;
 };
 
 } //namespace
index ca5c736d20102f001c492231ab9184b5ac50fe77..2c7a15f7fe2d062a74e9ee0789d8676db100113a 100644 (file)
@@ -29,6 +29,7 @@
 
 #include "CSSPropertyNames.h"
 #include "Document.h"
+#include "DeprecatedRenderSelect.h"
 #include "Event.h"
 #include "EventNames.h"
 #include "FormDataList.h"
@@ -37,7 +38,7 @@
 #include "HTMLOptionElement.h"
 #include "HTMLOptionsCollection.h"
 #include "KeyboardEvent.h"
-#include "DeprecatedRenderSelect.h"
+#include "RenderMenuList.h"
 #include "cssstyleselector.h"
 #include <wtf/Vector.h>
 
@@ -75,8 +76,12 @@ bool HTMLSelectElement::checkDTD(const Node* newChild)
 
 void HTMLSelectElement::recalcStyle( StyleChange ch )
 {
-    if (hasChangedChild() && renderer())
-        static_cast<DeprecatedRenderSelect*>(renderer())->setOptionsChanged(true);
+    if (hasChangedChild() && renderer()) {
+        if (shouldUseMenuList(renderer()->style()))
+            static_cast<RenderMenuList*>(renderer())->setOptionsChanged(true);
+        else
+            static_cast<DeprecatedRenderSelect*>(renderer())->setOptionsChanged(true);
+    }
 
     HTMLGenericFormElement::recalcStyle( ch );
 }
@@ -272,6 +277,8 @@ void HTMLSelectElement::parseMappedAttribute(MappedAttribute *attr)
 
 RenderObject *HTMLSelectElement::createRenderer(RenderArena *arena, RenderStyle *style)
 {
+    if (shouldUseMenuList(style))
+        return new (arena) RenderMenuList(this);
     return new (arena) DeprecatedRenderSelect(this);
 }
 
@@ -389,8 +396,12 @@ void HTMLSelectElement::childrenChanged()
 void HTMLSelectElement::setRecalcListItems()
 {
     m_recalcListItems = true;
-    if (renderer())
-        static_cast<DeprecatedRenderSelect*>(renderer())->setOptionsChanged(true);
+    if (renderer()) {
+        if (shouldUseMenuList(renderer()->style()))
+            static_cast<RenderMenuList*>(renderer())->setOptionsChanged(true);
+        else
+            static_cast<DeprecatedRenderSelect*>(renderer())->setOptionsChanged(true);
+    }
     setChanged();
 }
 
@@ -414,8 +425,12 @@ void HTMLSelectElement::reset()
     }
     if (!optionSelected && firstOption)
         firstOption->setSelected(true);
-    if (renderer())
-        static_cast<DeprecatedRenderSelect*>(renderer())->setSelectionChanged(true);
+    if (renderer()) {
+        if (shouldUseMenuList(renderer()->style()))
+            static_cast<RenderMenuList*>(renderer())->setSelectionChanged(true);
+        else
+            static_cast<DeprecatedRenderSelect*>(renderer())->setSelectionChanged(true);
+    }
     setChanged(true);
 }
 
@@ -430,8 +445,12 @@ void HTMLSelectElement::notifyOptionSelected(HTMLOptionElement *selectedOption,
                 static_cast<HTMLOptionElement*>(items[i])->m_selected = (items[i] == selectedOption);
         }
     }
-    if (renderer())
-        static_cast<DeprecatedRenderSelect*>(renderer())->setSelectionChanged(true);
+    if (renderer()) {
+        if (shouldUseMenuList(renderer()->style()))
+            static_cast<RenderMenuList*>(renderer())->setSelectionChanged(true);
+        else
+            static_cast<DeprecatedRenderSelect*>(renderer())->setSelectionChanged(true);
+    }
 
     setChanged(true);
 }
@@ -448,6 +467,9 @@ void HTMLSelectElement::defaultEventHandler(Event *evt)
             evt->setDefaultHandled();
         }
     }
+    if (evt->type() == mousedownEvent && renderer() && shouldUseMenuList(renderer()->style()))
+        static_cast<RenderMenuList*>(renderer())->showPopup();
+
     HTMLGenericFormElement::defaultEventHandler(evt);
 }
 
index 1c327398f799c871c3adb0eb34f3b2c4b589677c..910d24952f8738b79b7e7436569bcbeaec3dfd84 100644 (file)
@@ -28,6 +28,7 @@
 
 #include "HTMLGenericFormElement.h"
 #include "HTMLCollection.h"
+#include "render_style.h"
 #include <wtf/Vector.h>
 
 namespace WebCore {
@@ -38,6 +39,7 @@ class DeprecatedRenderSelect;
 
 class HTMLSelectElement : public HTMLGenericFormElement {
     friend class DeprecatedRenderSelect;
+    friend class RenderMenuList;
 
 public:
     HTMLSelectElement(Document*, HTMLFormElement* = 0);
@@ -120,6 +122,7 @@ public:
 
 private:
     void recalcListItems();
+    bool shouldUseMenuList(RenderStyle* style) { return !m_multiple && m_size <= 1 && style->appearance() == MenulistAppearance; }
 
     mutable Vector<HTMLElement*> m_listItems;
     int m_minwidth;
index 002586cd2d1c923fb82ad0d016c6f4aacbb723aa..2077247ec357d0c32073519c7c255d44a7f8bee7 100644 (file)
@@ -52,7 +52,9 @@ typedef struct _NSRange NSRange;
 
 #ifndef __OBJC__
 class NSImage;
+class NSMenu;
 class NSString;
+class NSView;
 #endif
 
 #ifdef __cplusplus
@@ -83,6 +85,7 @@ extern size_t (*wkGetGlyphVectorRecordSize)(void* glyphVector);
 extern NSString* (*wkGetMIMETypeForExtension)(NSString*);
 extern ATSUFontID (*wkGetNSFontATSUFontId)(NSFont*);
 extern OSStatus (*wkInitializeGlyphVector)(int count, void* glyphs);
+extern void (*wkPopupMenu)(NSMenu*, NSPoint location, float width, NSView*, int selectedItem, NSFont*);
 extern void (*wkReleaseStyleGroup)(void* group);
 extern void (*wkSetCGFontRenderingMode)(CGContextRef, NSFont*);
 extern void (*wkSetDragImage)(NSImage*, NSPoint offset);
index 5a52451498d32e433892985ec3f371c6934edfdc..6076b9bcb25af20fb739d4e1c6891833aafe3c0e 100644 (file)
@@ -46,6 +46,7 @@ size_t (*wkGetGlyphVectorRecordSize)(void* glyphVector);
 NSString* (*wkGetMIMETypeForExtension)(NSString*);
 ATSUFontID (*wkGetNSFontATSUFontId)(NSFont*);
 OSStatus (*wkInitializeGlyphVector)(int count, void* glyphs);
+void (*wkPopupMenu)(NSMenu*, NSPoint location, float width, NSView*, int selectedItem, NSFont*);
 void (*wkReleaseStyleGroup)(void* group);
 void (*wkSetCGFontRenderingMode)(CGContextRef, NSFont*);
 void (*wkSetDragImage)(NSImage*, NSPoint offset);
index 1008e223c86e965a88aaaefde54165ac3ab4dc59..b31d509d1308b3835bed8f5235327a3a2068ccb4 100644 (file)
@@ -61,6 +61,7 @@
 #include "RenderThemeWin.h"
 #include "TextBoundaries.h"
 #include "AccessibilityObjectCache.h"
+#include "RenderPopupMenuWin.h"
 
 using namespace WebCore;
 
@@ -358,3 +359,15 @@ void WebCore::setFocusRingColorChangeFunction(void (*)()) { }
 void Frame::setNeedsReapplyStyles() { }
 
 void Image::drawTiled(GraphicsContext*, const FloatRect&, const FloatRect&, TileRule, TileRule, CompositeOperator) { }
+
+RenderPopupMenuWin::RenderPopupMenuWin(Node*) { notImplemented();}
+RenderPopupMenuWin::~RenderPopupMenuWin() { notImplemented(); }
+void RenderPopupMenuWin::clear() { notImplemented(); }
+void RenderPopupMenuWin::populate() { notImplemented(); }
+void RenderPopupMenuWin::showPopup(const IntRect&, FrameView*, int index) { notImplemented(); }
+void RenderPopupMenuWin::addSeparator() { notImplemented(); }
+void RenderPopupMenuWin::addGroupLabel(HTMLOptGroupElement*) { notImplemented(); }
+void RenderPopupMenuWin::addOption(HTMLOptionElement*) { notImplemented(); }
+
+bool RenderThemeWin::paintMenuList(RenderObject*, const RenderObject::PaintInfo&, const IntRect&) { notImplemented(); return false; }
+void RenderThemeWin::adjustMenuListStyle(CSSStyleSelector*, RenderStyle*, Element*) const { notImplemented(); }
diff --git a/WebCore/rendering/RenderMenuList.cpp b/WebCore/rendering/RenderMenuList.cpp
new file mode 100644 (file)
index 0000000..eba5c09
--- /dev/null
@@ -0,0 +1,244 @@
+/**
+ * This file is part of the select element renderer in WebCore.
+ *
+ * Copyright (C) 2006 Apple Computer, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "config.h"
+#include "RenderMenuList.h"
+
+#include "Document.h"
+#include "HTMLNames.h"
+#include "HTMLOptionElement.h"
+#include "FrameView.h"
+#include "GraphicsContext.h"
+#include "RenderPopupMenu.h"
+#include "RenderText.h"
+#include "RenderTheme.h"
+#include <math.h>
+
+namespace WebCore {
+
+using namespace HTMLNames;
+using namespace std;
+
+RenderMenuList::RenderMenuList(HTMLSelectElement* element)
+    : RenderFlexibleBox(element)
+    , m_buttonText(0)
+    , m_inner(0)
+    , m_popupMenu(0)
+    , m_size(element->size())
+    , m_selectionChanged(true)
+    , m_optionsChanged(true)
+    , m_longestWidth(0)
+    , m_selectedIndex(0)
+{
+}
+
+void RenderMenuList::addChild(RenderObject* newChild, RenderObject* beforeChild)
+{
+    if (!m_inner) {
+        // Create an anonymous block.
+        assert(!m_first);
+        m_inner = createAnonymousBlock();
+        m_inner->style()->setBoxFlex(1.0f);
+        RenderFlexibleBox::addChild(m_inner);
+    }
+    m_inner->addChild(newChild, beforeChild);
+}
+
+void RenderMenuList::removeChild(RenderObject* oldChild)
+{
+    if (oldChild == m_inner || !m_inner) {
+        RenderFlexibleBox::removeChild(oldChild);
+        m_inner = 0;
+    }
+    else
+        m_inner->removeChild(oldChild);
+}
+
+void RenderMenuList::setStyle(RenderStyle* style)
+{
+    style->setPaddingLeft(Length(10, Fixed));
+    style->setPaddingRight(Length(8, Fixed));
+    RenderBlock::setStyle(style);
+    if (m_buttonText)
+        m_buttonText->setStyle(style);
+    if (m_inner)
+        m_inner->style()->setBoxFlex(1.0f);
+    if (m_popupMenu) {
+        RenderStyle *newStyle = new (renderArena()) RenderStyle();
+        newStyle->inheritFrom(style);
+        m_popupMenu->setStyle(newStyle);
+    }
+    setReplaced(isInline());
+}
+
+void RenderMenuList::updateFromElement()
+{
+    if (m_optionsChanged) {
+        HTMLSelectElement* select = static_cast<HTMLSelectElement*>(node());
+        if (select->m_recalcListItems)
+            select->recalcListItems();
+        
+        Vector<HTMLElement*> listItems = select->listItems();
+        bool found = false;
+        unsigned firstOption = listItems.size();
+        int i = listItems.size();
+        m_longestWidth = 0;
+        while (i--)
+            if (listItems[i]->hasTagName(optionTag)) {
+                HTMLOptionElement* element = static_cast<HTMLOptionElement*>(listItems[i]);
+                String text = element->optionText();
+                float stringWidth = (text.isNull() || text.isEmpty()) ? 0 : style()->font().floatWidth(TextRun(text.impl()), TextStyle(0, 0, 0, false, false, false, false));
+                if (stringWidth > m_longestWidth)
+                    m_longestWidth = stringWidth;
+                if (found)
+                    element->m_selected = false;
+                else if (element->selected()) {
+                    setText(text);
+                    m_selectedIndex = i;
+                    found = true;
+                }
+                firstOption = i;
+            }
+        m_optionsChanged = false;
+    }
+}
+
+void RenderMenuList::setText(String s)
+{
+    if (s.isEmpty()) {
+        if (m_buttonText) {
+            m_buttonText->destroy();
+            m_buttonText = 0;
+        }
+    } else {
+        if (m_buttonText)
+            m_buttonText->setText(s.impl());
+        else {
+            m_buttonText = new (renderArena()) RenderText(document(), s.impl());
+            m_buttonText->setStyle(style());
+            addChild(m_buttonText);
+        }
+    }
+}
+
+void RenderMenuList::paintObject(PaintInfo& i, int _tx, int _ty)
+{
+    // Push a clip.
+    if (m_inner && i.phase == PaintPhaseForeground) {
+        IntRect clipRect(_tx + borderLeft(), _ty + borderTop(),
+            width() - borderLeft() - borderRight(), height() - borderBottom() - borderTop());
+        if (clipRect.width() == 0 || clipRect.height() == 0)
+            return;
+        i.p->save();
+        i.p->addClip(clipRect);
+    }
+    
+    // Paint the children.
+    RenderBlock::paintObject(i, _tx, _ty);
+    
+    // Pop the clip.
+    if (m_inner && i.phase == PaintPhaseForeground)
+        i.p->restore();
+}
+
+
+short RenderMenuList::baselinePosition(bool f, bool b) const
+{
+    return RenderFlexibleBox::baselinePosition(f, b);
+}
+
+void RenderMenuList::calcMinMaxWidth()
+{
+    if (m_optionsChanged)
+        updateFromElement();
+
+    m_minWidth = 0;
+    m_maxWidth = 0;
+
+    if (style()->width().isFixed() && style()->width().value() > 0)
+        m_minWidth = m_maxWidth = calcContentBoxWidth(style()->width().value());
+    else
+        m_maxWidth = m_longestWidth;
+    
+    if (style()->minWidth().isFixed() && style()->minWidth().value() > 0) {
+        m_maxWidth = max(m_maxWidth, calcContentBoxWidth(style()->minWidth().value()));
+        m_minWidth = max(m_minWidth, calcContentBoxWidth(style()->minWidth().value()));
+    } else if (style()->width().isPercent() || (style()->width().isAuto() && style()->height().isPercent()))
+        m_minWidth = 0;
+    else
+        m_minWidth = m_maxWidth;
+    
+    if (style()->maxWidth().isFixed() && style()->maxWidth().value() != undefinedLength) {
+        m_maxWidth = min(m_maxWidth, calcContentBoxWidth(style()->maxWidth().value()));
+        m_minWidth = min(m_minWidth, calcContentBoxWidth(style()->maxWidth().value()));
+    }
+
+    int toAdd = paddingLeft() + paddingRight() + borderLeft() + borderRight() + theme()->sizeOfArrowControl(style());
+    m_minWidth += toAdd;
+    m_maxWidth += toAdd;
+
+    setMinMaxKnown();
+}
+
+void RenderMenuList::showPopup()
+{
+    if (!m_popupMenu) {
+        RenderStyle *newStyle = new (renderArena()) RenderStyle();
+        newStyle->inheritFrom(style());
+        m_popupMenu = theme()->createPopupMenu(renderArena(), document());
+        m_popupMenu->setStyle(newStyle);
+        RenderFlexibleBox::addChild(m_popupMenu);
+    }
+    m_popupMenu->showPopup(absoluteBoundingBoxRect(), document()->view(), m_selectedIndex);
+    m_popupMenu->destroy();
+    m_popupMenu = 0;
+}
+
+void RenderMenuList::layout()
+{
+    RenderFlexibleBox::layout();
+}
+
+
+void RenderMenuList::updateSelection()
+{
+
+}
+
+void RenderMenuList::valueChanged(unsigned index)
+{
+    m_selectedIndex = index;
+    Vector<HTMLElement*> listItems = static_cast<HTMLSelectElement*>(node())->listItems();
+
+    for (unsigned i = 0; i < listItems.size(); ++i)
+        if (listItems[i]->hasTagName(optionTag) && i != index)
+            static_cast<HTMLOptionElement*>(listItems[i])->m_selected = false;
+
+    HTMLOptionElement* element = static_cast<HTMLOptionElement*>(listItems[index]);
+    element->m_selected = true;
+    
+    setText(element->optionText());
+    
+    static_cast<HTMLSelectElement*>(node())->onChange();
+}
+
+}
diff --git a/WebCore/rendering/RenderMenuList.h b/WebCore/rendering/RenderMenuList.h
new file mode 100644 (file)
index 0000000..baa397e
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * This file is part of the select element renderer in WebCore.
+ *
+ * Copyright (C) 2006 Apple Computer
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef RenderMenuList_H
+#define RenderMenuList_H
+
+#include "RenderButton.h"
+#include "HTMLSelectElement.h"
+
+namespace WebCore {
+
+class RenderPopupMenu;
+
+class RenderMenuList : public RenderFlexibleBox
+{
+public:
+    RenderMenuList(HTMLSelectElement*);
+
+    virtual void addChild(RenderObject* newChild, RenderObject *beforeChild = 0);
+    virtual void removeChild(RenderObject* oldChild);
+    virtual void removeLeftoverAnonymousBoxes() {}
+    virtual bool allowsReusingAnonymousChild() const { return false; }
+    virtual bool canHaveChildren() const { return false; }
+
+    virtual void setStyle(RenderStyle*);
+    virtual void updateFromElement();
+
+    virtual void paintObject(PaintInfo&, int tx, int ty);
+
+    virtual const char* renderName() const { return "RenderMenuList"; }
+    
+    short baselinePosition(bool f, bool b) const;
+    virtual void calcMinMaxWidth();
+    virtual void layout();
+
+    void setOptionsChanged(bool o) { m_optionsChanged = o; }
+
+    bool selectionChanged() { return m_selectionChanged; }
+    void setSelectionChanged(bool selectionChanged) { m_selectionChanged = selectionChanged; }
+    void updateSelection();
+    
+    void showPopup();
+    void valueChanged(unsigned index);
+    bool hasPopupMenu() { return m_popupMenu; }
+
+protected:
+    void setText(String);
+
+    RenderText* m_buttonText;
+    RenderBlock* m_inner;
+    RenderPopupMenu* m_popupMenu;
+
+    unsigned m_size;
+    bool m_selectionChanged;
+    bool m_optionsChanged;
+    float m_longestWidth;
+    int m_selectedIndex;
+};
+
+}
+
+#endif
diff --git a/WebCore/rendering/RenderPopupMenu.cpp b/WebCore/rendering/RenderPopupMenu.cpp
new file mode 100644 (file)
index 0000000..dd6af06
--- /dev/null
@@ -0,0 +1,54 @@
+/**
+ * This file is part of the popup menu implementation for <select> elements in WebCore.
+ *
+ * Copyright (C) 2006 Apple Computer, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+#include "RenderPopupMenu.h"
+
+#include "HTMLNames.h"
+#include "HTMLOptionElement.h"
+#include "HTMLOptGroupElement.h"
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+RenderPopupMenu::RenderPopupMenu(Node* element)
+    : RenderBlock(element)
+{
+}
+
+void RenderPopupMenu::populate()
+{
+    RenderMenuList* select = getRenderMenuList();
+    ASSERT(select);
+    if (!select->node())
+        return;
+    for (Node* n = select->node()->firstChild(); n; n = n->traverseNextNode(select->node())) {
+        if (n->hasTagName(optionTag))
+            addOption(static_cast<HTMLOptionElement*>(n));
+        else if (n->hasTagName(optgroupTag))
+            addGroupLabel(static_cast<HTMLOptGroupElement*>(n));
+        else if (n->hasTagName(hrTag))
+            addSeparator();
+    }
+}
+
+}
diff --git a/WebCore/rendering/RenderPopupMenu.h b/WebCore/rendering/RenderPopupMenu.h
new file mode 100644 (file)
index 0000000..d2d9a85
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * This file is part of the popup menu implementation for <select> elements in WebCore.
+ *
+ * Copyright (C) 2006 Apple Computer, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef RENDER_POPUPMENU_H
+#define RENDER_POPUPMENU_H
+
+#include "RenderBlock.h"
+#include "RenderMenuList.h"
+
+namespace WebCore {
+
+class HTMLOptionElement;
+class HTMLOptGroupElement;
+
+class RenderPopupMenu : public RenderBlock {
+public:
+    RenderPopupMenu(Node*);
+    virtual ~RenderPopupMenu() {}
+    
+    virtual const char* renderName() const { return "RenderPopupMenu"; }
+
+    virtual void clear() = 0;
+    virtual void populate();
+    virtual void showPopup(const IntRect&, FrameView*, int index) = 0;
+    
+    RenderMenuList* getRenderMenuList() { return static_cast<RenderMenuList*>(parent() ? parent()->parent() : 0); }
+
+protected:
+    virtual void addSeparator() = 0;
+    virtual void addGroupLabel(HTMLOptGroupElement*) = 0;
+    virtual void addOption(HTMLOptionElement*) = 0;
+
+};
+
+}
+
+#endif
diff --git a/WebCore/rendering/RenderPopupMenuMac.h b/WebCore/rendering/RenderPopupMenuMac.h
new file mode 100644 (file)
index 0000000..ed4387c
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * This file is part of the popup menu implementation for <select> elements in WebCore.
+ *
+ * Copyright (C) 2006 Apple Computer, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef RENDER_POPUPMENU_MAC_H
+#define RENDER_POPUPMENU_MAC_H
+
+#import "RenderPopupMenu.h"
+#import <AppKit/NSPopUpButtonCell.h>
+
+namespace WebCore {
+
+class RenderPopupMenuMac : public RenderPopupMenu {
+public:
+    RenderPopupMenuMac(Node*);
+    ~RenderPopupMenuMac();
+    
+    virtual void clear();
+    virtual void showPopup(const IntRect&, FrameView*, int index);
+    virtual void populate();
+    
+protected:
+    virtual void addSeparator();
+    virtual void addGroupLabel(HTMLOptGroupElement*);
+    virtual void addOption(HTMLOptionElement*);
+
+    NSPopUpButtonCell* popup;
+
+};
+
+}
+
+#endif
\ No newline at end of file
diff --git a/WebCore/rendering/RenderPopupMenuMac.mm b/WebCore/rendering/RenderPopupMenuMac.mm
new file mode 100644 (file)
index 0000000..61ab803
--- /dev/null
@@ -0,0 +1,181 @@
+/*
+ * This file is part of the popup menu implementation for <select> elements in WebCore.
+ *
+ * Copyright (C) 2006 Apple Computer, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#import "config.h"
+#import "RenderPopupMenuMac.h"
+
+#import "FrameView.h"
+#import "HTMLNames.h"
+#import "HTMLOptionElement.h"
+#import "HTMLOptGroupElement.h"
+#import "RenderMenuList.h"
+#import "WebCoreSystemInterface.h"
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+RenderPopupMenuMac::RenderPopupMenuMac(Node* element)
+    : RenderPopupMenu(element)
+    , popup(nil)
+{
+}
+
+RenderPopupMenuMac::~RenderPopupMenuMac()
+{
+    if (popup) {
+        [popup setControlView: nil];
+        [popup release];
+    }
+}
+
+void RenderPopupMenuMac::clear()
+{
+    if (popup)
+        [popup removeAllItems];
+}
+
+void RenderPopupMenuMac::populate()
+{
+    BOOL messagesEnabled = [[popup menu] menuChangedMessagesEnabled];
+    [[popup menu] setMenuChangedMessagesEnabled:NO];
+    RenderPopupMenu::populate();
+    [[popup menu] setMenuChangedMessagesEnabled:messagesEnabled];
+
+}
+
+void RenderPopupMenuMac::showPopup(const IntRect& r, FrameView* v, int index)
+{
+    if (!popup) {
+        popup = [[[NSPopUpButtonCell alloc] initTextCell:@"" pullsDown:NO] retain];
+        [popup setUsesItemFromMenu:NO];
+        [popup setAutoenablesItems:NO];
+    }
+    // If we decide to cache the NSMenuItems, we shouldn't clear and populate every time we show the popup menu
+    clear();
+    populate();
+    
+    if ([popup numberOfItems] <= 0)
+        return;
+    
+    ASSERT([popup numberOfItems] > index);
+    
+    NSView* view = v->getDocumentView();
+    [popup attachPopUpWithFrame:r inView:view];
+    
+    [popup selectItemAtIndex:index];
+    
+    NSPoint location = NSMakePoint(NSMinX(r), NSMaxY(r));
+    float vertOffset;
+    
+    //center it in our title frame
+    NSRect titleFrame = [popup titleRectForBounds:r];
+    if (titleFrame.size.width <= 0 || titleFrame.size.height <= 0)
+        titleFrame = r;
+    NSFont* font = style()->font().getNSFont();
+    NSSize sizeOfSelectedItem = titleFrame.size;
+
+    vertOffset = round((NSMaxY(r) - NSMaxY(titleFrame)) + (NSHeight(titleFrame) + sizeOfSelectedItem.height)/2.f);
+
+    //Align us for different fonts
+    NSFont* defaultFont = [NSFont systemFontOfSize:[font pointSize]];
+    vertOffset += [font descender] - [defaultFont descender];
+
+    vertOffset = fmin(NSHeight(r), vertOffset);
+
+    location.x -= 10;
+    location.y -= vertOffset;
+
+//  NSColor* backgroundColor = nsColor(style()->backgroundColor());
+    NSMenu* menu = [popup menu];
+    
+    wkPopupMenu(menu, location, floor(NSWidth(r) + 0.5), view, index, font);
+    
+    // update text on button
+    int newIndex = [popup indexOfSelectedItem];
+    if (index != newIndex && newIndex >= 0)
+        getRenderMenuList()->valueChanged(newIndex);
+
+    [popup dismissPopUp];
+}
+
+void RenderPopupMenuMac::addSeparator()
+{
+    NSMenuItem *separator = [NSMenuItem separatorItem];
+    [[popup menu] addItem:separator];
+}
+
+void RenderPopupMenuMac::addGroupLabel(HTMLOptGroupElement* element)
+{
+    if (!element)
+        return;
+    String text = element->groupLabelText();
+    
+    [popup addItemWithTitle:@""];
+    NSMenuItem *menuItem = [popup lastItem];
+
+    RenderStyle* s = element->renderStyle();
+    if (!s)
+        s = style();
+
+    NSMutableDictionary* attributes = [[NSMutableDictionary alloc] init];
+    if (s->font() != Font())
+        [attributes setObject:s->font().getNSFont() forKey:NSFontAttributeName];
+    [attributes setObject:nsColor(s->color()) forKey:NSForegroundColorAttributeName];
+    NSAttributedString *string = [[NSAttributedString alloc] initWithString:text attributes:attributes];
+
+    [menuItem setAttributedTitle:string];
+    [string release];
+    [attributes release];
+    [menuItem setEnabled:NO];
+}
+
+void RenderPopupMenuMac::addOption(HTMLOptionElement* element)
+{
+    if (!element)
+        return;
+    String text = element->optionText();
+    
+    bool groupEnabled = true;
+    if (element->parentNode() && element->parentNode()->hasTagName(optgroupTag))
+        groupEnabled = element->parentNode()->isEnabled();
+
+    [popup addItemWithTitle:@""];
+    NSMenuItem *menuItem = [popup lastItem];
+    
+    RenderStyle* s = element->renderStyle();
+    if (!s)
+        s = style();
+        
+    NSMutableDictionary* attributes = [[NSMutableDictionary alloc] init];
+    if (s->font() != Font())
+        [attributes setObject:s->font().getNSFont() forKey:NSFontAttributeName];
+    [attributes setObject:nsColor(s->color()) forKey:NSForegroundColorAttributeName];
+    NSAttributedString *string = [[NSAttributedString alloc] initWithString:text attributes:attributes];
+
+    [menuItem setAttributedTitle:string];
+    [string release];
+    [attributes release];
+    [menuItem setEnabled:groupEnabled && element->isEnabled()];
+
+}
+
+}
diff --git a/WebCore/rendering/RenderPopupMenuWin.h b/WebCore/rendering/RenderPopupMenuWin.h
new file mode 100644 (file)
index 0000000..9d8384f
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * This file is part of the popup menu implementation for <select> elements in WebCore.
+ *
+ * Copyright (C) 2006 Apple Computer, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef RENDER_POPUPMENU_WIN_H
+#define RENDER_POPUPMENU_WIN_H
+
+#include "RenderPopupMenu.h"
+
+namespace WebCore {
+
+class HTMLOptionElement;
+class HTMLOptGroupElement;
+
+class RenderPopupMenuWin : public RenderPopupMenu {
+public:
+    RenderPopupMenuWin(Node*);
+    ~RenderPopupMenuWin();
+
+    virtual void clear();
+    virtual void populate();
+    virtual void showPopup(const IntRect&, FrameView*, int index);
+    
+protected:
+    virtual void addSeparator();
+    virtual void addGroupLabel(HTMLOptGroupElement*);
+    virtual void addOption(HTMLOptionElement*);
+
+};
+
+}
+
+#endif
index 2972712adb02efa2f666a555dee1606ff2030476..dd9b2b5455b495af862f1b27f985d5905aba4f52 100644 (file)
@@ -27,6 +27,7 @@
 #include "HTMLInputElement.h"
 #include "HTMLNames.h"
 #include "render_style.h"
+#include "RenderPopupMenu.h"
 
 // The methods in this file are shared by all themes on every platform.
 
@@ -59,6 +60,8 @@ void RenderTheme::adjustStyle(CSSStyleSelector* selector, RenderStyle* style, El
             return adjustTextFieldStyle(selector, style, e);
         case TextAreaAppearance:
             return adjustTextAreaStyle(selector, style, e);
+        case MenulistAppearance:
+            return adjustMenuListStyle(selector, style, e);
         default:
             break;
     }
@@ -87,6 +90,8 @@ bool RenderTheme::paint(RenderObject* o, const RenderObject::PaintInfo& i, const
         case SquareButtonAppearance:
         case ButtonAppearance:
             return paintButton(o, i, r);
+        case MenulistAppearance:
+            return paintMenuList(o, i, r);
         case TextFieldAppearance:
         case TextAreaAppearance:
             return true;
@@ -113,6 +118,7 @@ bool RenderTheme::paintBorderOnly(RenderObject* o, const RenderObject::PaintInfo
         case PushButtonAppearance:
         case SquareButtonAppearance:
         case ButtonAppearance:
+        case MenulistAppearance:
         default:
             break;
     }
@@ -177,6 +183,7 @@ bool RenderTheme::isControlStyled(const RenderStyle* style, const BorderData& bo
         case PushButtonAppearance:
         case SquareButtonAppearance:
         case ButtonAppearance:
+        case MenulistAppearance:
         case TextFieldAppearance:
         case TextAreaAppearance: {
             // Test the style to see if the UA border and background match.
@@ -305,4 +312,8 @@ void RenderTheme::adjustTextAreaStyle(CSSStyleSelector* selector, RenderStyle* s
 {
 }
 
+void RenderTheme::adjustMenuListStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+{
+}
+
 }
index 9d283be9d5daaa948015e1b2f0e20c0c518e10a7..c892e2a9fe78ac8681defea1e62b69ef65dc535f 100644 (file)
@@ -28,6 +28,8 @@
 namespace WebCore {
 
 class Element;
+class RenderPopupMenu;
+
 enum ControlState { HoverState, PressedState, FocusState, EnabledState, CheckedState, ReadOnlyState };
 
 class RenderTheme {
@@ -98,6 +100,9 @@ public:
     virtual Color platformActiveSelectionForegroundColor() const;
     virtual Color platformInactiveSelectionForegroundColor() const;
 
+    virtual int sizeOfArrowControl(RenderStyle*) const { return 0; }
+    virtual RenderPopupMenu* createPopupMenu(RenderArena*, Document*) = 0;
+
 protected:
     // Methods for state querying
     bool isChecked(const RenderObject* o) const;
@@ -126,6 +131,10 @@ protected:
 
     virtual void adjustTextAreaStyle(CSSStyleSelector* selector, RenderStyle* style, WebCore::Element* e) const;
     virtual bool paintTextArea(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r) { return true; }
+
+    virtual void adjustMenuListStyle(CSSStyleSelector* selector, RenderStyle* style, WebCore::Element* e) const;
+    virtual bool paintMenuList(RenderObject* o, const RenderObject::PaintInfo& i, const IntRect& r) { return true; }
+
 };
 
 // Function to obtain the theme.  This is implemented in your platform-specific theme implementation to hand
index 875f61d83467aac3ab08d74dc5a91772c8e55d95..93e83cf57f03dd0b00629e8e630d53159f7346fa 100644 (file)
@@ -28,6 +28,7 @@
 namespace WebCore {
 
 class RenderStyle;
+class RenderPopupMenu;
 
 class RenderThemeMac : public RenderTheme {
 public:
@@ -54,6 +55,9 @@ public:
 
     virtual Color platformActiveSelectionBackgroundColor() const;
     virtual Color platformInactiveSelectionBackgroundColor() const;
+    
+    virtual int sizeOfArrowControl(RenderStyle*) const;
+    virtual RenderPopupMenu* createPopupMenu(RenderArena*, Document*);
 
 protected:
     // Methods for each appearance value.
@@ -73,6 +77,9 @@ protected:
     virtual bool paintTextArea(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
     virtual void adjustTextAreaStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
 
+    virtual bool paintMenuList(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+    virtual void adjustMenuListStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+
 private:
     IntRect inflateRect(const IntRect&, const IntSize&, const int* margins) const;
 
@@ -103,11 +110,14 @@ private:
     const IntSize* buttonSizes() const;
     const int* buttonMargins() const;
     void setButtonCellState(const RenderObject*, const IntRect&);
+    
+    void setPopupButtonCellState(const RenderObject*, const IntRect&);
 
 private:
     NSButtonCell* checkbox;
     NSButtonCell* radio;
     NSButtonCell* button;
+    NSPopUpButtonCell* popupButton;
     Image* resizeCornerImage;
 };
 
index aeff2133b0b65cf3650332c8538ab9e380b1af8a..7c1ae909edda668437223944991b2c44ccd79c2f 100644 (file)
@@ -30,6 +30,7 @@
 #import "RenderView.h"
 #import "WebCoreSystemInterface.h"
 #import "cssstyleselector.h"
+#import "RenderPopupMenuMac.h"
 
 // The methods in this file are specific to the Mac OS X platform.
 
@@ -117,6 +118,10 @@ void RenderThemeMac::adjustRepaintRect(const RenderObject* o, IntRect& r)
                 r = inflateRect(r, buttonSizes()[[button controlSize]], buttonMargins());
             break;
         }
+        case MenulistAppearance: {
+            setPopupButtonCellState(o, r); 
+            break;
+        }
         default:
             break;
     }
@@ -576,4 +581,74 @@ void RenderThemeMac::adjustTextAreaStyle(CSSStyleSelector* selector, RenderStyle
         addIntrinsicMargins(style, NSRegularControlSize);
 }
 
+bool RenderThemeMac::paintMenuList(RenderObject* o, const RenderObject::PaintInfo&, const IntRect& r)
+{
+    setPopupButtonCellState(o, r);
+    
+    [popupButton drawWithFrame:r inView:o->view()->frameView()->getDocumentView()];
+    [popupButton setControlView:nil];
+    return false;
+}
+
+void RenderThemeMac::adjustMenuListStyle(CSSStyleSelector* selector, RenderStyle* style, Element* e) const
+{
+    NSControlSize controlSize = controlSizeForFont(style);
+    
+    // Add in intrinsic margins
+    addIntrinsicMargins(style, controlSize);
+
+    // Height is locked to auto.
+    style->setHeight(Length(Auto));
+    
+    // White-space is locked to pre
+    style->setWhiteSpace(PRE);
+
+    if (controlSize != NSMiniControlSize) {
+        style->setPaddingTop(Length(2, Fixed));
+        style->setPaddingBottom(Length(5, Fixed));
+    }
+
+    // Our font is locked to the appropriate system font size for the control.  To clarify, we first use the CSS-specified font to figure out
+    // a reasonable control size, but once that control size is determined, we throw that font away and use the appropriate
+    // system font for the control size instead.
+    setFontFromControlSize(selector, style, controlSize);
+}
+
+void RenderThemeMac::setPopupButtonCellState(const RenderObject* o, const IntRect& r)
+{
+    if (!popupButton) {
+        popupButton = KWQRetainNSRelease([[NSPopUpButtonCell alloc] initTextCell:@"" pullsDown:NO]);
+        [popupButton setUsesItemFromMenu:NO];
+    }
+
+    // Set the control size based off the rectangle we're painting into.
+    RenderThemeMac::setControlSize(popupButton, buttonSizes(), IntSize(r.width(), r.height()));
+
+    // Update the various states we respond to.
+    updateCheckedState(popupButton, o);
+    updateEnabledState(popupButton, o);
+    updatePressedState(popupButton, o);
+    updateFocusedState(popupButton, o);
+}
+
+RenderPopupMenu* RenderThemeMac::createPopupMenu(RenderArena* arena, Document* doc)
+{
+    return new (arena) RenderPopupMenuMac(doc);
+}
+
+int RenderThemeMac::sizeOfArrowControl(RenderStyle* style) const
+{
+    NSControlSize controlSize = controlSizeForFont(style);
+    
+    switch (controlSize) {
+    case NSRegularControlSize:
+        return 26;
+    case NSSmallControlSize:
+        return 20;
+    case NSMiniControlSize:
+        return 16;
+    }
+    return 0;
+}
+
 }
index 14a789137161c8f1e18e23c5903ea7585bc3212f..947171f85ce4ad475f68b20025b4dcd3b614713d 100644 (file)
@@ -357,4 +357,9 @@ bool RenderThemeWin::paintTextArea(RenderObject* o, const RenderObject::PaintInf
     return paintTextField(o, i, r);
 }
 
+RenderPopupMenu* RenderThemeWin::createPopupMenu(RenderArena* arena, Document* doc)
+{
+    return new (arena) RenderPopupMenuWin(doc);
+}
+
 }
index 0c50b418b9e60bda6f93d930a72c8f5233f0be56..a30f13c8c21a28804cb197ef577baff6bb671c39 100644 (file)
@@ -70,6 +70,10 @@ public:
     virtual void adjustTextAreaStyle(CSSStyleSelector*, RenderStyle*, WebCore::Element*) const;
     virtual bool paintTextArea(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
 
+    virtual bool paintMenuList(RenderObject*, const RenderObject::PaintInfo&, const IntRect&);
+    virtual void adjustMenuListStyle(CSSStyleSelector*, RenderStyle*, Element*) const;
+    virtual RenderPopupMenu* createPopupMenu(RenderArena*, Document*);
+
 private:
     void addIntrinsicMargins(RenderStyle*) const;
     void close();
index 834df654eb150a683bffbf70550732f6c9cfeefb..cdfd96e6778877577cb609b3f222827b69386034 100644 (file)
@@ -1,3 +1,12 @@
+2006-07-05  Adele Peterson  <adele@apple.com>
+
+        Reviewed by Maciej and Hyatt.
+
+        WebKit part of initial popup menu implementation.
+
+        * WebCoreSupport/WebSystemInterface.m: (InitWebCoreSystemInterface):
+        Initialize WKPopupMenu.
+
 2006-07-05  Anders Carlsson  <acarlsson@apple.com>
 
         Reviewed by Maciej.
@@ -24,7 +33,6 @@
         * WebKit.LP64.exp: Added.
         * WebKit.xcodeproj/project.pbxproj:
 
->>>>>>> .r15169
 2006-07-04  Timothy Hatcher  <timothy@apple.com>
 
         Reviewed by Maciej.
index 0df3c8a1995661793b43f2f10e963d53b5867105..b35ea7dd42e96205d54b7c97f024a0936bc8d9eb 100644 (file)
@@ -59,6 +59,7 @@ void InitWebCoreSystemInterface(void)
     INIT(GetMIMETypeForExtension);
     INIT(GetNSFontATSUFontId);
     INIT(InitializeGlyphVector);
+    INIT(PopupMenu);
     INIT(ReleaseStyleGroup);
     INIT(SetCGFontRenderingMode);
     INIT(SetDragImage);
index 0a45417f6c4d275fd33ae0fbf674bc74690eab2f..6d39d32b096d550c9bef9d70b3d19da36ebe8da4 100644 (file)
@@ -1,3 +1,10 @@
+2006-07-05  Adele Peterson  <adele@apple.com>
+
+        Reviewed by Maciej and Hyatt.
+
+        * WebKitSystemInterface.h: Updated.
+        * libWebKitSystemInterface.a: Updated.
+
 2006-06-16  Adele Peterson  <adele@apple.com>
 
         Reviewed by Alice.
index 64120c822c22d24451896b4ad6820c6522dc56b7..73cff9d2d77055c78d54787f5a06bbaacb38f3d9 100644 (file)
@@ -100,6 +100,7 @@ void WKSetDragImage(NSImage *image, NSPoint offset);
 
 void WKDrawBezeledTextFieldCell(NSRect, BOOL enabled);
 void WKDrawBezeledTextArea(NSRect, BOOL enabled);
+void WKPopupMenu(NSMenu*, NSPoint location, float width, NSView*, int selectedItem, NSFont*);
 
 void WKSendUserChangeNotifications(void);
 BOOL WKConvertNSEventToCarbonEvent(EventRecord *carbonEvent, NSEvent *cocoaEvent);
index 9511793fdab8d3fe3241510e8d4d2e6bf25e078a..d24add8f0df60b5ae19fde03dde34c4db07c23db 100644 (file)
Binary files a/WebKitLibraries/libWebKitSystemInterface.a and b/WebKitLibraries/libWebKitSystemInterface.a differ