Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(816)

Unified Diff: Source/core/html/HTMLOptGroupElement.cpp

Issue 347773002: Implement select listbox using shadow DOM (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: gixed slow select-max-length.html Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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

Powered by Google App Engine
This is Rietveld 408576698