OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |