Chromium Code Reviews| Index: Source/core/html/HTMLOptGroupElement.cpp |
| diff --git a/Source/core/html/HTMLOptGroupElement.cpp b/Source/core/html/HTMLOptGroupElement.cpp |
| index 01c307a46d66dcaa577f3d43c47493147b70485d..30a28118db7f5ebc35db590433144fb8a4d38f56 100644 |
| --- a/Source/core/html/HTMLOptGroupElement.cpp |
| +++ b/Source/core/html/HTMLOptGroupElement.cpp |
| @@ -28,13 +28,78 @@ |
| #include "core/HTMLNames.h" |
| #include "core/dom/Document.h" |
| #include "core/dom/NodeRenderStyle.h" |
| +#include "core/dom/Text.h" |
| +#include "core/html/HTMLContentElement.h" |
| +#include "core/html/HTMLDivElement.h" |
| #include "core/html/HTMLSelectElement.h" |
| #include "wtf/StdLibExtras.h" |
| +#include "wtf/unicode/CharacterNames.h" |
| namespace WebCore { |
| using namespace HTMLNames; |
| +class GroupLabelElement : public HTMLDivElement { |
|
esprehn
2014/06/23 21:59:56
Put this in it's own file.
keishi
2014/07/01 04:53:32
Removed this class.
|
| +public: |
| + static PassRefPtrWillBeRawPtr<GroupLabelElement> create(Document&); |
| + |
| + void setText(const String& text) |
|
esprehn
2014/06/23 21:59:55
Not inline.
|
| + { |
| + DEFINE_STATIC_LOCAL(String, nonBreakingSpaceString, (&noBreakSpace, 1)); |
| + const String& labelText = text.isEmpty() ? nonBreakingSpaceString : text; |
| + if (!m_textNode) { |
| + m_textNode = Text::create(document(), labelText); |
|
esprehn
2014/06/23 21:59:55
You should just setTextContent, don't rewrite it y
|
| + appendChild(m_textNode); |
| + } else { |
| + m_textNode->replaceWholeText(labelText); |
|
esprehn
2014/06/23 21:59:56
Use setTextContent.
|
| + } |
| + } |
| + |
| +private: |
| + explicit GroupLabelElement(Document& document) |
| + : HTMLDivElement(document) |
| + , m_textNode(nullptr) |
| + { |
| + setHasCustomStyleCallbacks(); |
| + } |
| + virtual PassRefPtr<RenderStyle> customStyleForRenderer() OVERRIDE; |
| + |
| + RefPtrWillBeMember<Text> m_textNode; |
| +}; |
| + |
| +PassRefPtrWillBeRawPtr<GroupLabelElement> GroupLabelElement::create(Document& document) |
| +{ |
| + return adoptRefWillBeNoop(new GroupLabelElement(document)); |
| +} |
| + |
| +PassRefPtr<RenderStyle> GroupLabelElement::customStyleForRenderer() |
| +{ |
| + RefPtr<RenderStyle> originalStyle = document().styleResolver()->styleForElement(this); |
|
esprehn
2014/06/23 21:59:56
originalStyleForRenderer()
|
| + RefPtr<RenderStyle> style = RenderStyle::clone(originalStyle.get()); |
| + |
| + style->setPaddingRight(Length(2, Fixed)); |
| + style->setPaddingLeft(Length(2, Fixed)); |
| + |
| + int paddingBottom = 1; |
| + HTMLSelectElement* selectElement = toHTMLOptGroupElement(shadowHost())->ownerSelectElement(); |
| + if (selectElement) { |
| + const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = selectElement->listItems(); |
| + ASSERT(items.size() > 0); |
| + if (items.last() == this) |
| + paddingBottom = 0; |
| + } |
|
esprehn
2014/06/23 21:59:56
Why do you need this custom styling hook, I'm not
keishi
2014/07/01 04:53:32
Removed. The current implementation has a 1 pixel
|
| + style->setPaddingBottom(Length(paddingBottom, Fixed)); |
| + |
| + return style.release(); |
| +} |
| + |
| +PassRefPtrWillBeRawPtr<HTMLOptGroupElement> HTMLOptGroupElement::create(Document& document) |
| +{ |
| + RefPtrWillBeRawPtr<HTMLOptGroupElement> optGroupElement = adoptRefWillBeNoop(new HTMLOptGroupElement(document)); |
| + optGroupElement->ensureUserAgentShadowRoot(); |
| + return optGroupElement.release(); |
| +} |
| + |
| inline HTMLOptGroupElement::HTMLOptGroupElement(Document& document) |
| : HTMLElement(optgroupTag, document) |
| { |
| @@ -42,7 +107,11 @@ inline HTMLOptGroupElement::HTMLOptGroupElement(Document& document) |
| ScriptWrappable::init(this); |
| } |
| -DEFINE_NODE_FACTORY(HTMLOptGroupElement) |
| +void HTMLOptGroupElement::trace(Visitor* visitor) |
| +{ |
| + visitor->trace(m_groupLabelElement); |
| + HTMLElement::trace(visitor); |
| +} |
| bool HTMLOptGroupElement::isDisabledFormControl() const |
| { |
| @@ -51,8 +120,11 @@ bool HTMLOptGroupElement::isDisabledFormControl() const |
| bool HTMLOptGroupElement::rendererIsFocusable() const |
| { |
| - // Optgroup elements do not have a renderer so we check the renderStyle instead. |
| - return renderStyle() && renderStyle()->display() != NONE; |
| + HTMLSelectElement* selectElement = ownerSelectElement(); |
| + if (!selectElement || selectElement->usesMenuList()) { |
| + return !isDisplayNone(); |
| + } |
| + return HTMLElement::rendererIsFocusable(); |
| } |
| void HTMLOptGroupElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta) |
| @@ -61,6 +133,12 @@ void HTMLOptGroupElement::childrenChanged(bool changedByParser, Node* beforeChan |
| HTMLElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta); |
| } |
| +bool HTMLOptGroupElement::rendererIsNeeded(const RenderStyle&) |
| +{ |
| + HTMLSelectElement* select = ownerSelectElement(); |
| + return select && !select->usesMenuList() && !isDisplayNone(); |
|
esprehn
2014/06/23 21:59:55
This is not correct, you should be calling the sup
keishi
2014/07/01 04:53:32
Done.
|
| +} |
| + |
| void HTMLOptGroupElement::parseAttribute(const QualifiedName& name, const AtomicString& value) |
| { |
| HTMLElement::parseAttribute(name, value); |
| @@ -68,6 +146,8 @@ void HTMLOptGroupElement::parseAttribute(const QualifiedName& name, const Atomic |
| if (name == disabledAttr) |
| didAffectSelector(AffectedSelectorDisabled | AffectedSelectorEnabled); |
| + else if (name == labelAttr) |
| + updateGroupLabel(); |
| } |
| void HTMLOptGroupElement::recalcSelectOptions() |
| @@ -112,6 +192,7 @@ PassRefPtr<RenderStyle> HTMLOptGroupElement::customStyleForRenderer() |
| return m_style; |
| } |
| + |
| String HTMLOptGroupElement::groupLabelText() const |
| { |
| String itemText = getAttribute(labelAttr); |
| @@ -124,6 +205,16 @@ String HTMLOptGroupElement::groupLabelText() const |
| return itemText; |
| } |
| +LayoutUnit HTMLOptGroupElement::groupLabelHeight() const |
| +{ |
| + if (!m_groupLabelElement) |
| + return 0; |
| + RenderObject* labelRenderer = m_groupLabelElement->renderer(); |
| + if (!labelRenderer) |
| + return 0; |
| + return labelRenderer->absoluteBoundingBoxRect().height(); |
|
esprehn
2014/06/23 21:59:55
This is wrong, you can't call int this when layout
|
| +} |
| + |
| HTMLSelectElement* HTMLOptGroupElement::ownerSelectElement() const |
| { |
| return Traversal<HTMLSelectElement>::firstAncestor(*this); |
| @@ -137,10 +228,47 @@ void HTMLOptGroupElement::accessKeyAction(bool) |
| select->accessKeyAction(false); |
| } |
| +void HTMLOptGroupElement::didAddUserAgentShadowRoot(ShadowRoot& root) |
| +{ |
| + RefPtr<GroupLabelElement> groupLabelElement = GroupLabelElement::create(document()); |
| + groupLabelElement->setText(String()); |
|
esprehn
2014/06/23 21:59:55
I don't think yo need a custom GroupLabelElement a
keishi
2014/07/01 04:53:32
Done.
|
| + root.appendChild(groupLabelElement); |
| + m_groupLabelElement = groupLabelElement.get(); |
|
esprehn
2014/06/23 21:59:55
Remove.
keishi
2014/07/01 04:53:32
Done.
|
| + |
| + RefPtr<HTMLContentElement> content = HTMLContentElement::create(document()); |
| + content->setAttribute(selectAttr, "option"); |
| + root.appendChild(content); |
| +} |
| + |
| +void HTMLOptGroupElement::updateGroupLabel() |
| +{ |
| + static_cast<GroupLabelElement*>(ensureUserAgentShadowRoot().firstChild())->setText(groupLabelText()); |
| +} |
| + |
| bool HTMLOptGroupElement::isDisplayNone() const |
| { |
| - RenderStyle* style = nonRendererStyle(); |
| - return style && style->display() == NONE; |
| + RenderStyle* style = renderStyle(); |
| + return !style || style->display() == NONE; |
|
esprehn
2014/06/23 21:59:56
We should just remove this method....
keishi
2014/07/01 04:53:32
Done.
|
| +} |
| + |
| +Node::InsertionNotificationRequest HTMLOptGroupElement::insertedInto(ContainerNode* insertionPoint) |
| +{ |
| + HTMLElement::insertedInto(insertionPoint); |
| + return insertionPoint->inDocument() ? InsertionShouldCallDidNotifySubtreeInsertions : InsertionDone; |
|
esprehn
2014/06/23 21:59:55
You shouldn't be using InsertionShouldCallDidNotif
keishi
2014/07/01 04:53:32
Done.
|
| +} |
| + |
| +void HTMLOptGroupElement::didNotifySubtreeInsertionsToDocument() |
| +{ |
| + updateView(); |
| +} |
| + |
| +void HTMLOptGroupElement::updateView() |
| +{ |
| + HTMLSelectElement* select = ownerSelectElement(); |
| + if (select && !select->usesMenuList()) |
| + ensureUserAgentShadowRoot(); |
|
esprehn
2014/06/23 21:59:55
You always have a UA ShadowRoot, you call it in ::
keishi
2014/07/01 04:53:32
Done.
|
| + else if (userAgentShadowRoot() && document().lifecycle().stateAllowsDetach()) |
|
esprehn
2014/06/23 21:59:55
Using stateAllowsDetach() is wrong, don't do that.
|
| + userAgentShadowRoot()->detach(); |
|
esprehn
2014/06/23 21:59:55
You should not be calling detach like this.
|
| } |
| } // namespace |