OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved. | 2 * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved. |
3 * | 3 * |
4 * This library is free software; you can redistribute it and/or | 4 * This library is free software; you can redistribute it and/or |
5 * modify it under the terms of the GNU Library General Public | 5 * modify it under the terms of the GNU Library General Public |
6 * License as published by the Free Software Foundation; either | 6 * License as published by the Free Software Foundation; either |
7 * version 2 of the License, or (at your option) any later version. | 7 * version 2 of the License, or (at your option) any later version. |
8 * | 8 * |
9 * This library is distributed in the hope that it will be useful, | 9 * This library is distributed in the hope that it will be useful, |
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
12 * Library General Public License for more details. | 12 * Library General Public License for more details. |
13 * | 13 * |
14 * You should have received a copy of the GNU Library General Public License | 14 * You should have received a copy of the GNU Library General Public License |
15 * along with this library; see the file COPYING.LIB. If not, write to | 15 * along with this library; see the file COPYING.LIB. If not, write to |
16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | 16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
17 * Boston, MA 02110-1301, USA. | 17 * Boston, MA 02110-1301, USA. |
18 * | 18 * |
19 */ | 19 */ |
20 | 20 |
21 #include "config.h" | 21 #include "config.h" |
22 #include "core/html/forms/RadioButtonGroupScope.h" | 22 #include "core/html/forms/RadioButtonGroupScope.h" |
23 | 23 |
| 24 #include "core/InputTypeNames.h" |
24 #include "core/html/HTMLInputElement.h" | 25 #include "core/html/HTMLInputElement.h" |
25 #include "wtf/HashSet.h" | 26 #include "wtf/HashSet.h" |
26 | 27 |
27 namespace blink { | 28 namespace blink { |
28 | 29 |
29 class RadioButtonGroup : public NoBaseWillBeGarbageCollected<RadioButtonGroup> { | 30 class RadioButtonGroup : public NoBaseWillBeGarbageCollected<RadioButtonGroup> { |
30 WTF_MAKE_FAST_ALLOCATED_WILL_BE_REMOVED; | 31 WTF_MAKE_FAST_ALLOCATED_WILL_BE_REMOVED; |
31 public: | 32 public: |
32 static PassOwnPtrWillBeRawPtr<RadioButtonGroup> create(); | 33 static PassOwnPtrWillBeRawPtr<RadioButtonGroup> create(); |
33 bool isEmpty() const { return m_members.isEmpty(); } | 34 bool isEmpty() const { return m_members.isEmpty(); } |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
73 HTMLInputElement* oldCheckedButton = m_checkedButton; | 74 HTMLInputElement* oldCheckedButton = m_checkedButton; |
74 if (oldCheckedButton == button) | 75 if (oldCheckedButton == button) |
75 return; | 76 return; |
76 m_checkedButton = button; | 77 m_checkedButton = button; |
77 if (oldCheckedButton) | 78 if (oldCheckedButton) |
78 oldCheckedButton->setChecked(false); | 79 oldCheckedButton->setChecked(false); |
79 } | 80 } |
80 | 81 |
81 void RadioButtonGroup::add(HTMLInputElement* button) | 82 void RadioButtonGroup::add(HTMLInputElement* button) |
82 { | 83 { |
83 ASSERT(button->isRadioButton()); | 84 ASSERT(button->type() == InputTypeNames::radio); |
84 if (!m_members.add(button).isNewEntry) | 85 if (!m_members.add(button).isNewEntry) |
85 return; | 86 return; |
86 bool groupWasValid = isValid(); | 87 bool groupWasValid = isValid(); |
87 if (button->isRequired()) | 88 if (button->isRequired()) |
88 ++m_requiredCount; | 89 ++m_requiredCount; |
89 if (button->checked()) | 90 if (button->checked()) |
90 setCheckedButton(button); | 91 setCheckedButton(button); |
91 | 92 |
92 bool groupIsValid = isValid(); | 93 bool groupIsValid = isValid(); |
93 if (groupWasValid != groupIsValid) { | 94 if (groupWasValid != groupIsValid) { |
94 setNeedsValidityCheckForAllButtons(); | 95 setNeedsValidityCheckForAllButtons(); |
95 } else if (!groupIsValid) { | 96 } else if (!groupIsValid) { |
96 // A radio button not in a group is always valid. We need to make it | 97 // A radio button not in a group is always valid. We need to make it |
97 // invalid only if the group is invalid. | 98 // invalid only if the group is invalid. |
98 button->setNeedsValidityCheck(); | 99 button->setNeedsValidityCheck(); |
99 } | 100 } |
100 } | 101 } |
101 | 102 |
102 void RadioButtonGroup::updateCheckedState(HTMLInputElement* button) | 103 void RadioButtonGroup::updateCheckedState(HTMLInputElement* button) |
103 { | 104 { |
104 ASSERT(button->isRadioButton()); | 105 ASSERT(button->type() == InputTypeNames::radio); |
105 ASSERT(m_members.contains(button)); | 106 ASSERT(m_members.contains(button)); |
106 bool wasValid = isValid(); | 107 bool wasValid = isValid(); |
107 if (button->checked()) { | 108 if (button->checked()) { |
108 setCheckedButton(button); | 109 setCheckedButton(button); |
109 } else { | 110 } else { |
110 if (m_checkedButton == button) | 111 if (m_checkedButton == button) |
111 m_checkedButton = nullptr; | 112 m_checkedButton = nullptr; |
112 } | 113 } |
113 if (wasValid != isValid()) | 114 if (wasValid != isValid()) |
114 setNeedsValidityCheckForAllButtons(); | 115 setNeedsValidityCheckForAllButtons(); |
115 typedef WillBeHeapHashSet<RawPtrWillBeMember<HTMLInputElement> >::const_iter
ator Iterator; | 116 typedef WillBeHeapHashSet<RawPtrWillBeMember<HTMLInputElement> >::const_iter
ator Iterator; |
116 Iterator end = m_members.end(); | 117 Iterator end = m_members.end(); |
117 for (Iterator it = m_members.begin(); it != end; ++it) { | 118 for (Iterator it = m_members.begin(); it != end; ++it) { |
118 (*it)->didAffectSelector(AffectedSelectorIndeterminate); | 119 (*it)->didAffectSelector(AffectedSelectorIndeterminate); |
119 } | 120 } |
120 } | 121 } |
121 | 122 |
122 void RadioButtonGroup::requiredAttributeChanged(HTMLInputElement* button) | 123 void RadioButtonGroup::requiredAttributeChanged(HTMLInputElement* button) |
123 { | 124 { |
124 ASSERT(button->isRadioButton()); | 125 ASSERT(button->type() == InputTypeNames::radio); |
125 ASSERT(m_members.contains(button)); | 126 ASSERT(m_members.contains(button)); |
126 bool wasValid = isValid(); | 127 bool wasValid = isValid(); |
127 if (button->isRequired()) { | 128 if (button->isRequired()) { |
128 ++m_requiredCount; | 129 ++m_requiredCount; |
129 } else { | 130 } else { |
130 ASSERT(m_requiredCount); | 131 ASSERT(m_requiredCount); |
131 --m_requiredCount; | 132 --m_requiredCount; |
132 } | 133 } |
133 if (wasValid != isValid()) | 134 if (wasValid != isValid()) |
134 setNeedsValidityCheckForAllButtons(); | 135 setNeedsValidityCheckForAllButtons(); |
135 } | 136 } |
136 | 137 |
137 void RadioButtonGroup::remove(HTMLInputElement* button) | 138 void RadioButtonGroup::remove(HTMLInputElement* button) |
138 { | 139 { |
139 ASSERT(button->isRadioButton()); | 140 ASSERT(button->type() == InputTypeNames::radio); |
140 WillBeHeapHashSet<RawPtrWillBeMember<HTMLInputElement> >::iterator it = m_me
mbers.find(button); | 141 WillBeHeapHashSet<RawPtrWillBeMember<HTMLInputElement> >::iterator it = m_me
mbers.find(button); |
141 if (it == m_members.end()) | 142 if (it == m_members.end()) |
142 return; | 143 return; |
143 bool wasValid = isValid(); | 144 bool wasValid = isValid(); |
144 m_members.remove(it); | 145 m_members.remove(it); |
145 if (button->isRequired()) { | 146 if (button->isRequired()) { |
146 ASSERT(m_requiredCount); | 147 ASSERT(m_requiredCount); |
147 --m_requiredCount; | 148 --m_requiredCount; |
148 } | 149 } |
149 if (m_checkedButton == button) | 150 if (m_checkedButton == button) |
(...skipping 11 matching lines...) Expand all Loading... |
161 button->setNeedsValidityCheck(); | 162 button->setNeedsValidityCheck(); |
162 } | 163 } |
163 } | 164 } |
164 | 165 |
165 void RadioButtonGroup::setNeedsValidityCheckForAllButtons() | 166 void RadioButtonGroup::setNeedsValidityCheckForAllButtons() |
166 { | 167 { |
167 typedef WillBeHeapHashSet<RawPtrWillBeMember<HTMLInputElement> >::const_iter
ator Iterator; | 168 typedef WillBeHeapHashSet<RawPtrWillBeMember<HTMLInputElement> >::const_iter
ator Iterator; |
168 Iterator end = m_members.end(); | 169 Iterator end = m_members.end(); |
169 for (Iterator it = m_members.begin(); it != end; ++it) { | 170 for (Iterator it = m_members.begin(); it != end; ++it) { |
170 HTMLInputElement* button = *it; | 171 HTMLInputElement* button = *it; |
171 ASSERT(button->isRadioButton()); | 172 ASSERT(button->type() == InputTypeNames::radio); |
172 button->setNeedsValidityCheck(); | 173 button->setNeedsValidityCheck(); |
173 } | 174 } |
174 } | 175 } |
175 | 176 |
176 bool RadioButtonGroup::contains(HTMLInputElement* button) const | 177 bool RadioButtonGroup::contains(HTMLInputElement* button) const |
177 { | 178 { |
178 return m_members.contains(button); | 179 return m_members.contains(button); |
179 } | 180 } |
180 | 181 |
181 void RadioButtonGroup::trace(Visitor* visitor) | 182 void RadioButtonGroup::trace(Visitor* visitor) |
(...skipping 12 matching lines...) Expand all Loading... |
194 RadioButtonGroupScope::RadioButtonGroupScope() | 195 RadioButtonGroupScope::RadioButtonGroupScope() |
195 { | 196 { |
196 } | 197 } |
197 | 198 |
198 RadioButtonGroupScope::~RadioButtonGroupScope() | 199 RadioButtonGroupScope::~RadioButtonGroupScope() |
199 { | 200 { |
200 } | 201 } |
201 | 202 |
202 void RadioButtonGroupScope::addButton(HTMLInputElement* element) | 203 void RadioButtonGroupScope::addButton(HTMLInputElement* element) |
203 { | 204 { |
204 ASSERT(element->isRadioButton()); | 205 ASSERT(element->type() == InputTypeNames::radio); |
205 if (element->name().isEmpty()) | 206 if (element->name().isEmpty()) |
206 return; | 207 return; |
207 | 208 |
208 if (!m_nameToGroupMap) | 209 if (!m_nameToGroupMap) |
209 m_nameToGroupMap = adoptPtrWillBeNoop(new NameToGroupMap); | 210 m_nameToGroupMap = adoptPtrWillBeNoop(new NameToGroupMap); |
210 | 211 |
211 OwnPtrWillBeMember<RadioButtonGroup>& group = m_nameToGroupMap->add(element-
>name(), nullptr).storedValue->value; | 212 OwnPtrWillBeMember<RadioButtonGroup>& group = m_nameToGroupMap->add(element-
>name(), nullptr).storedValue->value; |
212 if (!group) | 213 if (!group) |
213 group = RadioButtonGroup::create(); | 214 group = RadioButtonGroup::create(); |
214 group->add(element); | 215 group->add(element); |
215 } | 216 } |
216 | 217 |
217 void RadioButtonGroupScope::updateCheckedState(HTMLInputElement* element) | 218 void RadioButtonGroupScope::updateCheckedState(HTMLInputElement* element) |
218 { | 219 { |
219 ASSERT(element->isRadioButton()); | 220 ASSERT(element->type() == InputTypeNames::radio); |
220 if (element->name().isEmpty()) | 221 if (element->name().isEmpty()) |
221 return; | 222 return; |
222 ASSERT(m_nameToGroupMap); | 223 ASSERT(m_nameToGroupMap); |
223 if (!m_nameToGroupMap) | 224 if (!m_nameToGroupMap) |
224 return; | 225 return; |
225 RadioButtonGroup* group = m_nameToGroupMap->get(element->name()); | 226 RadioButtonGroup* group = m_nameToGroupMap->get(element->name()); |
226 ASSERT(group); | 227 ASSERT(group); |
227 group->updateCheckedState(element); | 228 group->updateCheckedState(element); |
228 } | 229 } |
229 | 230 |
230 void RadioButtonGroupScope::requiredAttributeChanged(HTMLInputElement* element) | 231 void RadioButtonGroupScope::requiredAttributeChanged(HTMLInputElement* element) |
231 { | 232 { |
232 ASSERT(element->isRadioButton()); | 233 ASSERT(element->type() == InputTypeNames::radio); |
233 if (element->name().isEmpty()) | 234 if (element->name().isEmpty()) |
234 return; | 235 return; |
235 ASSERT(m_nameToGroupMap); | 236 ASSERT(m_nameToGroupMap); |
236 if (!m_nameToGroupMap) | 237 if (!m_nameToGroupMap) |
237 return; | 238 return; |
238 RadioButtonGroup* group = m_nameToGroupMap->get(element->name()); | 239 RadioButtonGroup* group = m_nameToGroupMap->get(element->name()); |
239 ASSERT(group); | 240 ASSERT(group); |
240 group->requiredAttributeChanged(element); | 241 group->requiredAttributeChanged(element); |
241 } | 242 } |
242 | 243 |
243 HTMLInputElement* RadioButtonGroupScope::checkedButtonForGroup(const AtomicStrin
g& name) const | 244 HTMLInputElement* RadioButtonGroupScope::checkedButtonForGroup(const AtomicStrin
g& name) const |
244 { | 245 { |
245 if (!m_nameToGroupMap) | 246 if (!m_nameToGroupMap) |
246 return 0; | 247 return 0; |
247 RadioButtonGroup* group = m_nameToGroupMap->get(name); | 248 RadioButtonGroup* group = m_nameToGroupMap->get(name); |
248 return group ? group->checkedButton() : 0; | 249 return group ? group->checkedButton() : 0; |
249 } | 250 } |
250 | 251 |
251 bool RadioButtonGroupScope::isInRequiredGroup(HTMLInputElement* element) const | 252 bool RadioButtonGroupScope::isInRequiredGroup(HTMLInputElement* element) const |
252 { | 253 { |
253 ASSERT(element->isRadioButton()); | 254 ASSERT(element->type() == InputTypeNames::radio); |
254 if (element->name().isEmpty()) | 255 if (element->name().isEmpty()) |
255 return false; | 256 return false; |
256 if (!m_nameToGroupMap) | 257 if (!m_nameToGroupMap) |
257 return false; | 258 return false; |
258 RadioButtonGroup* group = m_nameToGroupMap->get(element->name()); | 259 RadioButtonGroup* group = m_nameToGroupMap->get(element->name()); |
259 return group && group->isRequired() && group->contains(element); | 260 return group && group->isRequired() && group->contains(element); |
260 } | 261 } |
261 | 262 |
262 void RadioButtonGroupScope::removeButton(HTMLInputElement* element) | 263 void RadioButtonGroupScope::removeButton(HTMLInputElement* element) |
263 { | 264 { |
264 ASSERT(element->isRadioButton()); | 265 ASSERT(element->type() == InputTypeNames::radio); |
265 if (element->name().isEmpty()) | 266 if (element->name().isEmpty()) |
266 return; | 267 return; |
267 if (!m_nameToGroupMap) | 268 if (!m_nameToGroupMap) |
268 return; | 269 return; |
269 | 270 |
270 RadioButtonGroup* group = m_nameToGroupMap->get(element->name()); | 271 RadioButtonGroup* group = m_nameToGroupMap->get(element->name()); |
271 if (!group) | 272 if (!group) |
272 return; | 273 return; |
273 group->remove(element); | 274 group->remove(element); |
274 if (group->isEmpty()) { | 275 if (group->isEmpty()) { |
275 // We don't remove an empty RadioButtonGroup from m_nameToGroupMap for | 276 // We don't remove an empty RadioButtonGroup from m_nameToGroupMap for |
276 // better performance. | 277 // better performance. |
277 ASSERT(!group->isRequired()); | 278 ASSERT(!group->isRequired()); |
278 ASSERT_WITH_SECURITY_IMPLICATION(!group->checkedButton()); | 279 ASSERT_WITH_SECURITY_IMPLICATION(!group->checkedButton()); |
279 } | 280 } |
280 } | 281 } |
281 | 282 |
282 void RadioButtonGroupScope::trace(Visitor* visitor) | 283 void RadioButtonGroupScope::trace(Visitor* visitor) |
283 { | 284 { |
284 #if ENABLE(OILPAN) | 285 #if ENABLE(OILPAN) |
285 visitor->trace(m_nameToGroupMap); | 286 visitor->trace(m_nameToGroupMap); |
286 #endif | 287 #endif |
287 } | 288 } |
288 | 289 |
289 } // namespace | 290 } // namespace |
OLD | NEW |