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

Side by Side 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 /* 1 /*
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 1999 Antti Koivisto (koivisto@kde.org) 3 * (C) 1999 Antti Koivisto (koivisto@kde.org)
4 * (C) 2001 Dirk Mueller (mueller@kde.org) 4 * (C) 2001 Dirk Mueller (mueller@kde.org)
5 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2010 Apple Inc. All rights reserv ed. 5 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2010 Apple Inc. All rights reserv ed.
6 * (C) 2006 Alexey Proskuryakov (ap@nypop.com) 6 * (C) 2006 Alexey Proskuryakov (ap@nypop.com)
7 * 7 *
8 * This library is free software; you can redistribute it and/or 8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public 9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either 10 * License as published by the Free Software Foundation; either
(...skipping 10 matching lines...) Expand all
21 * Boston, MA 02110-1301, USA. 21 * Boston, MA 02110-1301, USA.
22 * 22 *
23 */ 23 */
24 24
25 #include "config.h" 25 #include "config.h"
26 #include "core/html/HTMLOptGroupElement.h" 26 #include "core/html/HTMLOptGroupElement.h"
27 27
28 #include "core/HTMLNames.h" 28 #include "core/HTMLNames.h"
29 #include "core/dom/Document.h" 29 #include "core/dom/Document.h"
30 #include "core/dom/NodeRenderStyle.h" 30 #include "core/dom/NodeRenderStyle.h"
31 #include "core/dom/Text.h"
32 #include "core/html/HTMLContentElement.h"
33 #include "core/html/HTMLDivElement.h"
31 #include "core/html/HTMLSelectElement.h" 34 #include "core/html/HTMLSelectElement.h"
32 #include "wtf/StdLibExtras.h" 35 #include "wtf/StdLibExtras.h"
36 #include "wtf/unicode/CharacterNames.h"
33 37
34 namespace WebCore { 38 namespace WebCore {
35 39
36 using namespace HTMLNames; 40 using namespace HTMLNames;
37 41
42 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.
43 public:
44 static PassRefPtrWillBeRawPtr<GroupLabelElement> create(Document&);
45
46 void setText(const String& text)
esprehn 2014/06/23 21:59:55 Not inline.
47 {
48 DEFINE_STATIC_LOCAL(String, nonBreakingSpaceString, (&noBreakSpace, 1));
49 const String& labelText = text.isEmpty() ? nonBreakingSpaceString : text ;
50 if (!m_textNode) {
51 m_textNode = Text::create(document(), labelText);
esprehn 2014/06/23 21:59:55 You should just setTextContent, don't rewrite it y
52 appendChild(m_textNode);
53 } else {
54 m_textNode->replaceWholeText(labelText);
esprehn 2014/06/23 21:59:56 Use setTextContent.
55 }
56 }
57
58 private:
59 explicit GroupLabelElement(Document& document)
60 : HTMLDivElement(document)
61 , m_textNode(nullptr)
62 {
63 setHasCustomStyleCallbacks();
64 }
65 virtual PassRefPtr<RenderStyle> customStyleForRenderer() OVERRIDE;
66
67 RefPtrWillBeMember<Text> m_textNode;
68 };
69
70 PassRefPtrWillBeRawPtr<GroupLabelElement> GroupLabelElement::create(Document& do cument)
71 {
72 return adoptRefWillBeNoop(new GroupLabelElement(document));
73 }
74
75 PassRefPtr<RenderStyle> GroupLabelElement::customStyleForRenderer()
76 {
77 RefPtr<RenderStyle> originalStyle = document().styleResolver()->styleForElem ent(this);
esprehn 2014/06/23 21:59:56 originalStyleForRenderer()
78 RefPtr<RenderStyle> style = RenderStyle::clone(originalStyle.get());
79
80 style->setPaddingRight(Length(2, Fixed));
81 style->setPaddingLeft(Length(2, Fixed));
82
83 int paddingBottom = 1;
84 HTMLSelectElement* selectElement = toHTMLOptGroupElement(shadowHost())->owne rSelectElement();
85 if (selectElement) {
86 const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& items = select Element->listItems();
87 ASSERT(items.size() > 0);
88 if (items.last() == this)
89 paddingBottom = 0;
90 }
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
91 style->setPaddingBottom(Length(paddingBottom, Fixed));
92
93 return style.release();
94 }
95
96 PassRefPtrWillBeRawPtr<HTMLOptGroupElement> HTMLOptGroupElement::create(Document & document)
97 {
98 RefPtrWillBeRawPtr<HTMLOptGroupElement> optGroupElement = adoptRefWillBeNoop (new HTMLOptGroupElement(document));
99 optGroupElement->ensureUserAgentShadowRoot();
100 return optGroupElement.release();
101 }
102
38 inline HTMLOptGroupElement::HTMLOptGroupElement(Document& document) 103 inline HTMLOptGroupElement::HTMLOptGroupElement(Document& document)
39 : HTMLElement(optgroupTag, document) 104 : HTMLElement(optgroupTag, document)
40 { 105 {
41 setHasCustomStyleCallbacks(); 106 setHasCustomStyleCallbacks();
42 ScriptWrappable::init(this); 107 ScriptWrappable::init(this);
43 } 108 }
44 109
45 DEFINE_NODE_FACTORY(HTMLOptGroupElement) 110 void HTMLOptGroupElement::trace(Visitor* visitor)
111 {
112 visitor->trace(m_groupLabelElement);
113 HTMLElement::trace(visitor);
114 }
46 115
47 bool HTMLOptGroupElement::isDisabledFormControl() const 116 bool HTMLOptGroupElement::isDisabledFormControl() const
48 { 117 {
49 return fastHasAttribute(disabledAttr); 118 return fastHasAttribute(disabledAttr);
50 } 119 }
51 120
52 bool HTMLOptGroupElement::rendererIsFocusable() const 121 bool HTMLOptGroupElement::rendererIsFocusable() const
53 { 122 {
54 // Optgroup elements do not have a renderer so we check the renderStyle inst ead. 123 HTMLSelectElement* selectElement = ownerSelectElement();
55 return renderStyle() && renderStyle()->display() != NONE; 124 if (!selectElement || selectElement->usesMenuList()) {
125 return !isDisplayNone();
126 }
127 return HTMLElement::rendererIsFocusable();
56 } 128 }
57 129
58 void HTMLOptGroupElement::childrenChanged(bool changedByParser, Node* beforeChan ge, Node* afterChange, int childCountDelta) 130 void HTMLOptGroupElement::childrenChanged(bool changedByParser, Node* beforeChan ge, Node* afterChange, int childCountDelta)
59 { 131 {
60 recalcSelectOptions(); 132 recalcSelectOptions();
61 HTMLElement::childrenChanged(changedByParser, beforeChange, afterChange, chi ldCountDelta); 133 HTMLElement::childrenChanged(changedByParser, beforeChange, afterChange, chi ldCountDelta);
62 } 134 }
63 135
136 bool HTMLOptGroupElement::rendererIsNeeded(const RenderStyle&)
137 {
138 HTMLSelectElement* select = ownerSelectElement();
139 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.
140 }
141
64 void HTMLOptGroupElement::parseAttribute(const QualifiedName& name, const Atomic String& value) 142 void HTMLOptGroupElement::parseAttribute(const QualifiedName& name, const Atomic String& value)
65 { 143 {
66 HTMLElement::parseAttribute(name, value); 144 HTMLElement::parseAttribute(name, value);
67 recalcSelectOptions(); 145 recalcSelectOptions();
68 146
69 if (name == disabledAttr) 147 if (name == disabledAttr)
70 didAffectSelector(AffectedSelectorDisabled | AffectedSelectorEnabled); 148 didAffectSelector(AffectedSelectorDisabled | AffectedSelectorEnabled);
149 else if (name == labelAttr)
150 updateGroupLabel();
71 } 151 }
72 152
73 void HTMLOptGroupElement::recalcSelectOptions() 153 void HTMLOptGroupElement::recalcSelectOptions()
74 { 154 {
75 if (HTMLSelectElement* select = Traversal<HTMLSelectElement>::firstAncestor( *this)) 155 if (HTMLSelectElement* select = Traversal<HTMLSelectElement>::firstAncestor( *this))
76 select->setRecalcListItems(); 156 select->setRecalcListItems();
77 } 157 }
78 158
79 void HTMLOptGroupElement::attach(const AttachContext& context) 159 void HTMLOptGroupElement::attach(const AttachContext& context)
80 { 160 {
(...skipping 24 matching lines...) Expand all
105 { 185 {
106 return m_style.get(); 186 return m_style.get();
107 } 187 }
108 188
109 PassRefPtr<RenderStyle> HTMLOptGroupElement::customStyleForRenderer() 189 PassRefPtr<RenderStyle> HTMLOptGroupElement::customStyleForRenderer()
110 { 190 {
111 updateNonRenderStyle(); 191 updateNonRenderStyle();
112 return m_style; 192 return m_style;
113 } 193 }
114 194
195
115 String HTMLOptGroupElement::groupLabelText() const 196 String HTMLOptGroupElement::groupLabelText() const
116 { 197 {
117 String itemText = getAttribute(labelAttr); 198 String itemText = getAttribute(labelAttr);
118 199
119 // In WinIE, leading and trailing whitespace is ignored in options and optgr oups. We match this behavior. 200 // In WinIE, leading and trailing whitespace is ignored in options and optgr oups. We match this behavior.
120 itemText = itemText.stripWhiteSpace(); 201 itemText = itemText.stripWhiteSpace();
121 // We want to collapse our whitespace too. This will match other browsers. 202 // We want to collapse our whitespace too. This will match other browsers.
122 itemText = itemText.simplifyWhiteSpace(); 203 itemText = itemText.simplifyWhiteSpace();
123 204
124 return itemText; 205 return itemText;
125 } 206 }
126 207
208 LayoutUnit HTMLOptGroupElement::groupLabelHeight() const
209 {
210 if (!m_groupLabelElement)
211 return 0;
212 RenderObject* labelRenderer = m_groupLabelElement->renderer();
213 if (!labelRenderer)
214 return 0;
215 return labelRenderer->absoluteBoundingBoxRect().height();
esprehn 2014/06/23 21:59:55 This is wrong, you can't call int this when layout
216 }
217
127 HTMLSelectElement* HTMLOptGroupElement::ownerSelectElement() const 218 HTMLSelectElement* HTMLOptGroupElement::ownerSelectElement() const
128 { 219 {
129 return Traversal<HTMLSelectElement>::firstAncestor(*this); 220 return Traversal<HTMLSelectElement>::firstAncestor(*this);
130 } 221 }
131 222
132 void HTMLOptGroupElement::accessKeyAction(bool) 223 void HTMLOptGroupElement::accessKeyAction(bool)
133 { 224 {
134 HTMLSelectElement* select = ownerSelectElement(); 225 HTMLSelectElement* select = ownerSelectElement();
135 // send to the parent to bring focus to the list box 226 // send to the parent to bring focus to the list box
136 if (select && !select->focused()) 227 if (select && !select->focused())
137 select->accessKeyAction(false); 228 select->accessKeyAction(false);
138 } 229 }
139 230
231 void HTMLOptGroupElement::didAddUserAgentShadowRoot(ShadowRoot& root)
232 {
233 RefPtr<GroupLabelElement> groupLabelElement = GroupLabelElement::create(docu ment());
234 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.
235 root.appendChild(groupLabelElement);
236 m_groupLabelElement = groupLabelElement.get();
esprehn 2014/06/23 21:59:55 Remove.
keishi 2014/07/01 04:53:32 Done.
237
238 RefPtr<HTMLContentElement> content = HTMLContentElement::create(document());
239 content->setAttribute(selectAttr, "option");
240 root.appendChild(content);
241 }
242
243 void HTMLOptGroupElement::updateGroupLabel()
244 {
245 static_cast<GroupLabelElement*>(ensureUserAgentShadowRoot().firstChild())->s etText(groupLabelText());
246 }
247
140 bool HTMLOptGroupElement::isDisplayNone() const 248 bool HTMLOptGroupElement::isDisplayNone() const
141 { 249 {
142 RenderStyle* style = nonRendererStyle(); 250 RenderStyle* style = renderStyle();
143 return style && style->display() == NONE; 251 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.
252 }
253
254 Node::InsertionNotificationRequest HTMLOptGroupElement::insertedInto(ContainerNo de* insertionPoint)
255 {
256 HTMLElement::insertedInto(insertionPoint);
257 return insertionPoint->inDocument() ? InsertionShouldCallDidNotifySubtreeIns ertions : InsertionDone;
esprehn 2014/06/23 21:59:55 You shouldn't be using InsertionShouldCallDidNotif
keishi 2014/07/01 04:53:32 Done.
258 }
259
260 void HTMLOptGroupElement::didNotifySubtreeInsertionsToDocument()
261 {
262 updateView();
263 }
264
265 void HTMLOptGroupElement::updateView()
266 {
267 HTMLSelectElement* select = ownerSelectElement();
268 if (select && !select->usesMenuList())
269 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.
270 else if (userAgentShadowRoot() && document().lifecycle().stateAllowsDetach() )
esprehn 2014/06/23 21:59:55 Using stateAllowsDetach() is wrong, don't do that.
271 userAgentShadowRoot()->detach();
esprehn 2014/06/23 21:59:55 You should not be calling detach like this.
144 } 272 }
145 273
146 } // namespace 274 } // namespace
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698