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

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

Issue 24246011: Move form-related 78 files to core/html/forms/. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 7 years, 3 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
« no previous file with comments | « Source/core/dom/CheckedRadioButtons.h ('k') | Source/core/dom/Document.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved.
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
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
16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 *
19 */
20
21 #include "config.h"
22 #include "core/dom/CheckedRadioButtons.h"
23
24 #include "core/html/HTMLInputElement.h"
25 #include "wtf/HashSet.h"
26
27 namespace WebCore {
28
29 class RadioButtonGroup {
30 WTF_MAKE_FAST_ALLOCATED;
31 public:
32 static PassOwnPtr<RadioButtonGroup> create();
33 bool isEmpty() const { return m_members.isEmpty(); }
34 bool isRequired() const { return m_requiredCount; }
35 HTMLInputElement* checkedButton() const { return m_checkedButton; }
36 void add(HTMLInputElement*);
37 void updateCheckedState(HTMLInputElement*);
38 void requiredAttributeChanged(HTMLInputElement*);
39 void remove(HTMLInputElement*);
40 bool contains(HTMLInputElement*) const;
41
42 private:
43 RadioButtonGroup();
44 void setNeedsValidityCheckForAllButtons();
45 bool isValid() const;
46 void setCheckedButton(HTMLInputElement*);
47
48 HashSet<HTMLInputElement*> m_members;
49 HTMLInputElement* m_checkedButton;
50 size_t m_requiredCount;
51 };
52
53 RadioButtonGroup::RadioButtonGroup()
54 : m_checkedButton(0)
55 , m_requiredCount(0)
56 {
57 }
58
59 PassOwnPtr<RadioButtonGroup> RadioButtonGroup::create()
60 {
61 return adoptPtr(new RadioButtonGroup);
62 }
63
64 inline bool RadioButtonGroup::isValid() const
65 {
66 return !isRequired() || m_checkedButton;
67 }
68
69 void RadioButtonGroup::setCheckedButton(HTMLInputElement* button)
70 {
71 HTMLInputElement* oldCheckedButton = m_checkedButton;
72 if (oldCheckedButton == button)
73 return;
74 m_checkedButton = button;
75 if (oldCheckedButton)
76 oldCheckedButton->setChecked(false);
77 }
78
79 void RadioButtonGroup::add(HTMLInputElement* button)
80 {
81 ASSERT(button->isRadioButton());
82 if (!m_members.add(button).isNewEntry)
83 return;
84 bool groupWasValid = isValid();
85 if (button->isRequired())
86 ++m_requiredCount;
87 if (button->checked())
88 setCheckedButton(button);
89
90 bool groupIsValid = isValid();
91 if (groupWasValid != groupIsValid)
92 setNeedsValidityCheckForAllButtons();
93 else if (!groupIsValid) {
94 // A radio button not in a group is always valid. We need to make it
95 // invalid only if the group is invalid.
96 button->setNeedsValidityCheck();
97 }
98 }
99
100 void RadioButtonGroup::updateCheckedState(HTMLInputElement* button)
101 {
102 ASSERT(button->isRadioButton());
103 ASSERT(m_members.contains(button));
104 bool wasValid = isValid();
105 if (button->checked())
106 setCheckedButton(button);
107 else {
108 if (m_checkedButton == button)
109 m_checkedButton = 0;
110 }
111 if (wasValid != isValid())
112 setNeedsValidityCheckForAllButtons();
113 }
114
115 void RadioButtonGroup::requiredAttributeChanged(HTMLInputElement* button)
116 {
117 ASSERT(button->isRadioButton());
118 ASSERT(m_members.contains(button));
119 bool wasValid = isValid();
120 if (button->isRequired())
121 ++m_requiredCount;
122 else {
123 ASSERT(m_requiredCount);
124 --m_requiredCount;
125 }
126 if (wasValid != isValid())
127 setNeedsValidityCheckForAllButtons();
128 }
129
130 void RadioButtonGroup::remove(HTMLInputElement* button)
131 {
132 ASSERT(button->isRadioButton());
133 HashSet<HTMLInputElement*>::iterator it = m_members.find(button);
134 if (it == m_members.end())
135 return;
136 bool wasValid = isValid();
137 m_members.remove(it);
138 if (button->isRequired()) {
139 ASSERT(m_requiredCount);
140 --m_requiredCount;
141 }
142 if (m_checkedButton == button)
143 m_checkedButton = 0;
144
145 if (m_members.isEmpty()) {
146 ASSERT(!m_requiredCount);
147 ASSERT(!m_checkedButton);
148 } else if (wasValid != isValid())
149 setNeedsValidityCheckForAllButtons();
150 if (!wasValid) {
151 // A radio button not in a group is always valid. We need to make it
152 // valid only if the group was invalid.
153 button->setNeedsValidityCheck();
154 }
155 }
156
157 void RadioButtonGroup::setNeedsValidityCheckForAllButtons()
158 {
159 typedef HashSet<HTMLInputElement*>::const_iterator Iterator;
160 Iterator end = m_members.end();
161 for (Iterator it = m_members.begin(); it != end; ++it) {
162 HTMLInputElement* button = *it;
163 ASSERT(button->isRadioButton());
164 button->setNeedsValidityCheck();
165 }
166 }
167
168 bool RadioButtonGroup::contains(HTMLInputElement* button) const
169 {
170 return m_members.contains(button);
171 }
172
173 // ----------------------------------------------------------------
174
175 // Explicity define empty constructor and destructor in order to prevent the
176 // compiler from generating them as inlines. So we don't need to to define
177 // RadioButtonGroup in the header.
178 CheckedRadioButtons::CheckedRadioButtons()
179 {
180 }
181
182 CheckedRadioButtons::~CheckedRadioButtons()
183 {
184 }
185
186 void CheckedRadioButtons::addButton(HTMLInputElement* element)
187 {
188 ASSERT(element->isRadioButton());
189 if (element->name().isEmpty())
190 return;
191
192 if (!m_nameToGroupMap)
193 m_nameToGroupMap = adoptPtr(new NameToGroupMap);
194
195 OwnPtr<RadioButtonGroup>& group = m_nameToGroupMap->add(element->name().impl (), PassOwnPtr<RadioButtonGroup>()).iterator->value;
196 if (!group)
197 group = RadioButtonGroup::create();
198 group->add(element);
199 }
200
201 void CheckedRadioButtons::updateCheckedState(HTMLInputElement* element)
202 {
203 ASSERT(element->isRadioButton());
204 if (element->name().isEmpty())
205 return;
206 ASSERT(m_nameToGroupMap);
207 if (!m_nameToGroupMap)
208 return;
209 RadioButtonGroup* group = m_nameToGroupMap->get(element->name().impl());
210 ASSERT(group);
211 group->updateCheckedState(element);
212 }
213
214 void CheckedRadioButtons::requiredAttributeChanged(HTMLInputElement* element)
215 {
216 ASSERT(element->isRadioButton());
217 if (element->name().isEmpty())
218 return;
219 ASSERT(m_nameToGroupMap);
220 if (!m_nameToGroupMap)
221 return;
222 RadioButtonGroup* group = m_nameToGroupMap->get(element->name().impl());
223 ASSERT(group);
224 group->requiredAttributeChanged(element);
225 }
226
227 HTMLInputElement* CheckedRadioButtons::checkedButtonForGroup(const AtomicString& name) const
228 {
229 if (!m_nameToGroupMap)
230 return 0;
231 RadioButtonGroup* group = m_nameToGroupMap->get(name.impl());
232 return group ? group->checkedButton() : 0;
233 }
234
235 bool CheckedRadioButtons::isInRequiredGroup(HTMLInputElement* element) const
236 {
237 ASSERT(element->isRadioButton());
238 if (element->name().isEmpty())
239 return false;
240 if (!m_nameToGroupMap)
241 return false;
242 RadioButtonGroup* group = m_nameToGroupMap->get(element->name().impl());
243 return group && group->isRequired() && group->contains(element);
244 }
245
246 void CheckedRadioButtons::removeButton(HTMLInputElement* element)
247 {
248 ASSERT(element->isRadioButton());
249 if (element->name().isEmpty())
250 return;
251 if (!m_nameToGroupMap)
252 return;
253
254 NameToGroupMap::iterator it = m_nameToGroupMap->find(element->name().impl()) ;
255 if (it == m_nameToGroupMap->end())
256 return;
257 it->value->remove(element);
258 if (it->value->isEmpty()) {
259 // FIXME: We may skip deallocating the empty RadioButtonGroup for
260 // performance improvement. If we do so, we need to change the key type
261 // of m_nameToGroupMap from StringImpl* to AtomicString.
262 m_nameToGroupMap->remove(it);
263 if (m_nameToGroupMap->isEmpty())
264 m_nameToGroupMap.clear();
265 }
266 }
267
268 } // namespace
OLDNEW
« no previous file with comments | « Source/core/dom/CheckedRadioButtons.h ('k') | Source/core/dom/Document.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698