Chromium Code Reviews| 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 |