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

Side by Side Diff: Source/WebCore/dom/CheckedRadioButtons.cpp

Issue 9805002: Revert 105710 - Introduce RadioButtonGroup class to keep track of the group members and required st… (Closed) Base URL: http://svn.webkit.org/repository/webkit/branches/chromium/1025/
Patch Set: Created 8 years, 9 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
« no previous file with comments | « Source/WebCore/dom/CheckedRadioButtons.h ('k') | Source/WebCore/html/CheckboxInputType.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 "CheckedRadioButtons.h" 22 #include "CheckedRadioButtons.h"
23 23
24 #include "HTMLInputElement.h" 24 #include "HTMLInputElement.h"
25 #include <wtf/HashSet.h>
26 25
27 namespace WebCore { 26 namespace WebCore {
28 27
29 class RadioButtonGroup {
30 public:
31 static PassOwnPtr<RadioButtonGroup> create();
32 bool isEmpty() const { return m_members.isEmpty(); }
33 bool isRequired() const { return m_requiredCount; }
34 HTMLInputElement* checkedButton() const { return m_checkedButton; }
35 void add(HTMLInputElement*);
36 void updateCheckedState(HTMLInputElement*);
37 void requiredAttributeChanged(HTMLInputElement*);
38 void remove(HTMLInputElement*);
39
40 private:
41 RadioButtonGroup();
42 void setNeedsValidityCheckForAllButtons();
43 bool isValid() const;
44 void setCheckedButton(HTMLInputElement*);
45
46 HashSet<HTMLInputElement*> m_members;
47 HTMLInputElement* m_checkedButton;
48 size_t m_requiredCount;
49 };
50
51 RadioButtonGroup::RadioButtonGroup()
52 : m_checkedButton(0)
53 , m_requiredCount(0)
54 {
55 }
56
57 PassOwnPtr<RadioButtonGroup> RadioButtonGroup::create()
58 {
59 return adoptPtr(new RadioButtonGroup);
60 }
61
62 inline bool RadioButtonGroup::isValid() const
63 {
64 return !isRequired() || m_checkedButton;
65 }
66
67 void RadioButtonGroup::setCheckedButton(HTMLInputElement* button)
68 {
69 HTMLInputElement* oldCheckedButton = m_checkedButton;
70 if (oldCheckedButton == button)
71 return;
72 m_checkedButton = button;
73 if (oldCheckedButton)
74 oldCheckedButton->setChecked(false);
75 }
76
77 void RadioButtonGroup::add(HTMLInputElement* button)
78 {
79 ASSERT(button->isRadioButton());
80 if (!m_members.add(button).second)
81 return;
82 bool groupWasValid = isValid();
83 if (button->required())
84 ++m_requiredCount;
85 if (button->checked())
86 setCheckedButton(button);
87
88 bool groupIsValid = isValid();
89 if (groupWasValid != groupIsValid)
90 setNeedsValidityCheckForAllButtons();
91 else if (!groupIsValid) {
92 // A radio button not in a group is always valid. We need to make it
93 // invalid only if the group is invalid.
94 button->setNeedsValidityCheck();
95 }
96 }
97
98 void RadioButtonGroup::updateCheckedState(HTMLInputElement* button)
99 {
100 ASSERT(button->isRadioButton());
101 ASSERT(m_members.contains(button));
102 bool wasValid = isValid();
103 if (button->checked())
104 setCheckedButton(button);
105 else {
106 if (m_checkedButton == button)
107 m_checkedButton = 0;
108 }
109 if (wasValid != isValid())
110 setNeedsValidityCheckForAllButtons();
111 }
112
113 void RadioButtonGroup::requiredAttributeChanged(HTMLInputElement* button)
114 {
115 ASSERT(button->isRadioButton());
116 ASSERT(m_members.contains(button));
117 bool wasValid = isValid();
118 if (button->required())
119 ++m_requiredCount;
120 else {
121 ASSERT(m_requiredCount);
122 --m_requiredCount;
123 }
124 if (wasValid != isValid())
125 setNeedsValidityCheckForAllButtons();
126 }
127
128 void RadioButtonGroup::remove(HTMLInputElement* button)
129 {
130 ASSERT(button->isRadioButton());
131 HashSet<HTMLInputElement*>::iterator it = m_members.find(button);
132 if (it == m_members.end())
133 return;
134 bool wasValid = isValid();
135 m_members.remove(it);
136 if (button->required()) {
137 ASSERT(m_requiredCount);
138 --m_requiredCount;
139 }
140 if (m_checkedButton == button)
141 m_checkedButton = 0;
142
143 if (m_members.isEmpty()) {
144 ASSERT(!m_requiredCount);
145 ASSERT(!m_checkedButton);
146 } else if (wasValid != isValid())
147 setNeedsValidityCheckForAllButtons();
148 if (!wasValid) {
149 // A radio button not in a group is always valid. We need to make it
150 // valid only if the group was invalid.
151 button->setNeedsValidityCheck();
152 }
153 }
154
155 void RadioButtonGroup::setNeedsValidityCheckForAllButtons()
156 {
157 typedef HashSet<HTMLInputElement*>::const_iterator Iterator;
158 Iterator end = m_members.end();
159 for (Iterator it = m_members.begin(); it != end; ++it) {
160 HTMLInputElement* button = *it;
161 ASSERT(button->isRadioButton());
162 button->setNeedsValidityCheck();
163 }
164 }
165
166 // ----------------------------------------------------------------
167
168 static inline bool shouldMakeRadioGroup(HTMLInputElement* element) 28 static inline bool shouldMakeRadioGroup(HTMLInputElement* element)
169 { 29 {
170 return element->isRadioButton() && !element->name().isEmpty() && element->in Document(); 30 return element->isRadioButton() && !element->name().isEmpty() && element->in Document();
171 } 31 }
172 32
173 // Explicity define empty constructor and destructor in order to prevent the
174 // compiler from generating them as inlines. So we don't need to to define
175 // RadioButtonGroup in the header.
176 CheckedRadioButtons::CheckedRadioButtons()
177 {
178 }
179
180 CheckedRadioButtons::~CheckedRadioButtons()
181 {
182 }
183
184 void CheckedRadioButtons::addButton(HTMLInputElement* element) 33 void CheckedRadioButtons::addButton(HTMLInputElement* element)
185 { 34 {
186 if (!shouldMakeRadioGroup(element)) 35 if (!shouldMakeRadioGroup(element))
187 return; 36 return;
188 37
189 if (!m_nameToGroupMap) 38 // We only track checked buttons.
190 m_nameToGroupMap = adoptPtr(new NameToGroupMap); 39 if (!element->checked())
40 return;
191 41
192 OwnPtr<RadioButtonGroup>& group = m_nameToGroupMap->add(element->name().impl (), PassOwnPtr<RadioButtonGroup>()).first->second; 42 if (!m_nameToCheckedRadioButtonMap)
193 if (!group) 43 m_nameToCheckedRadioButtonMap = adoptPtr(new NameToInputMap);
194 group = RadioButtonGroup::create();
195 group->add(element);
196 }
197 44
198 void CheckedRadioButtons::updateCheckedState(HTMLInputElement* element) 45 pair<NameToInputMap::iterator, bool> result = m_nameToCheckedRadioButtonMap- >add(element->name().impl(), element);
199 { 46 if (result.second)
200 if (!shouldMakeRadioGroup(element))
201 return; 47 return;
202 ASSERT(m_nameToGroupMap); 48
203 if (!m_nameToGroupMap) 49 HTMLInputElement* oldCheckedButton = result.first->second;
50 if (oldCheckedButton == element)
204 return; 51 return;
205 RadioButtonGroup* group = m_nameToGroupMap->get(element->name().impl());
206 ASSERT(group);
207 group->updateCheckedState(element);
208 }
209 52
210 void CheckedRadioButtons::requiredAttributeChanged(HTMLInputElement* element) 53 result.first->second = element;
211 { 54 oldCheckedButton->setChecked(false);
212 if (!shouldMakeRadioGroup(element))
213 return;
214 ASSERT(m_nameToGroupMap);
215 if (!m_nameToGroupMap)
216 return;
217 RadioButtonGroup* group = m_nameToGroupMap->get(element->name().impl());
218 ASSERT(group);
219 group->requiredAttributeChanged(element);
220 } 55 }
221 56
222 HTMLInputElement* CheckedRadioButtons::checkedButtonForGroup(const AtomicString& name) const 57 HTMLInputElement* CheckedRadioButtons::checkedButtonForGroup(const AtomicString& name) const
223 { 58 {
224 if (!m_nameToGroupMap) 59 if (!m_nameToCheckedRadioButtonMap)
225 return 0; 60 return 0;
226 m_nameToGroupMap->checkConsistency();
227 RadioButtonGroup* group = m_nameToGroupMap->get(name.impl());
228 return group ? group->checkedButton() : 0;
229 }
230 61
231 bool CheckedRadioButtons::isInRequiredGroup(HTMLInputElement* element) const 62 m_nameToCheckedRadioButtonMap->checkConsistency();
232 { 63
233 ASSERT(element->isRadioButton()); 64 return m_nameToCheckedRadioButtonMap->get(name.impl());
234 if (!element->inDocument())
235 return false;
236 if (!m_nameToGroupMap)
237 return false;
238
239 RadioButtonGroup* group = m_nameToGroupMap->get(element->name().impl());
240 return group && group->isRequired();
241 } 65 }
242 66
243 void CheckedRadioButtons::removeButton(HTMLInputElement* element) 67 void CheckedRadioButtons::removeButton(HTMLInputElement* element)
244 { 68 {
245 if (!shouldMakeRadioGroup(element)) 69 if (element->name().isEmpty() || !m_nameToCheckedRadioButtonMap)
246 return; 70 return;
247 if (!m_nameToGroupMap) 71
72 m_nameToCheckedRadioButtonMap->checkConsistency();
73
74 NameToInputMap::iterator it = m_nameToCheckedRadioButtonMap->find(element->n ame().impl());
75 if (it == m_nameToCheckedRadioButtonMap->end() || it->second != element)
248 return; 76 return;
77
78 ASSERT(element->shouldAppearChecked());
79 ASSERT(element->isRadioButton());
249 80
250 m_nameToGroupMap->checkConsistency(); 81 m_nameToCheckedRadioButtonMap->remove(it);
251 NameToGroupMap::iterator it = m_nameToGroupMap->find(element->name().impl()) ; 82 if (m_nameToCheckedRadioButtonMap->isEmpty())
252 if (it == m_nameToGroupMap->end()) 83 m_nameToCheckedRadioButtonMap.clear();
253 return;
254 it->second->remove(element);
255 if (it->second->isEmpty()) {
256 // FIXME: We may skip deallocating the empty RadioButtonGroup for
257 // performance improvement. If we do so, we need to change the key type
258 // of m_nameToGroupMap from AtomicStringImpl* to RefPtr<AtomicStringImpl >.
259 m_nameToGroupMap->remove(it);
260 if (m_nameToGroupMap->isEmpty())
261 m_nameToGroupMap.clear();
262 }
263 } 84 }
264 85
265 } // namespace 86 } // namespace
OLDNEW
« no previous file with comments | « Source/WebCore/dom/CheckedRadioButtons.h ('k') | Source/WebCore/html/CheckboxInputType.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698