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 |