LayoutTests:
[WebKit-https.git] / WebCore / html / HTMLGenericFormElement.cpp
1 /*
2  * This file is part of the DOM implementation for KDE.
3  *
4  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
5  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
6  *           (C) 2001 Dirk Mueller (mueller@kde.org)
7  * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc.
8  *           (C) 2006 Alexey Proskuryakov (ap@nypop.com)
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Library General Public
12  * License as published by the Free Software Foundation; either
13  * version 2 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Library General Public License for more details.
19  *
20  * You should have received a copy of the GNU Library General Public License
21  * along with this library; see the file COPYING.LIB.  If not, write to
22  * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23  * Boston, MA 02111-1307, USA.
24  *
25  */
26
27 #include "config.h"
28 #include "HTMLGenericFormElement.h"
29
30 #include "EventNames.h"
31 #include "Frame.h"
32 #include "HTMLFormElement.h"
33 #include "HTMLNames.h"
34 #include "RenderTheme.h"
35 #include "RenderWidget.h"
36 #include "Widget.h"
37
38 namespace WebCore {
39
40 using namespace EventNames;
41 using namespace HTMLNames;
42
43 HTMLGenericFormElement::HTMLGenericFormElement(const QualifiedName& tagName, Document* doc, HTMLFormElement* f)
44     : HTMLElement(tagName, doc), m_form(f), m_disabled(false), m_readOnly(false), m_valueMatchesRenderer(false)
45 {
46     if (!m_form)
47         m_form = getForm();
48     if (m_form)
49         m_form->registerFormElement(this);
50 }
51
52 HTMLGenericFormElement::~HTMLGenericFormElement()
53 {
54     if (m_form)
55         m_form->removeFormElement(this);
56 }
57
58 void HTMLGenericFormElement::parseMappedAttribute(MappedAttribute *attr)
59 {
60     if (attr->name() == nameAttr) {
61         // Do nothing.
62     } else if (attr->name() == disabledAttr) {
63         bool oldDisabled = m_disabled;
64         m_disabled = !attr->isNull();
65         if (oldDisabled != m_disabled) {
66             setChanged();
67             if (renderer() && renderer()->style()->hasAppearance())
68                 theme()->stateChanged(renderer(), EnabledState);
69         }
70     } else if (attr->name() == readonlyAttr) {
71         bool oldReadOnly = m_readOnly;
72         m_readOnly = !attr->isNull();
73         if (oldReadOnly != m_readOnly) {
74             setChanged();
75             if (renderer() && renderer()->style()->hasAppearance())
76                 theme()->stateChanged(renderer(), ReadOnlyState);
77         }
78     } else
79         HTMLElement::parseMappedAttribute(attr);
80 }
81
82 void HTMLGenericFormElement::attach()
83 {
84     assert(!attached());
85
86     HTMLElement::attach();
87
88     // The call to updateFromElement() needs to go after the call through
89     // to the base class's attach() because that can sometimes do a close
90     // on the renderer.
91     if (renderer()) {
92         renderer()->updateFromElement();
93     
94         // Delayed attachment in order to prevent FOUC can result in an object being
95         // programmatically focused before it has a render object.  If we have been focused
96         // (i.e., if we are the focusNode) then go ahead and focus our corresponding native widget.
97         // (Attach/detach can also happen as a result of display type changes, e.g., making a widget
98         // block instead of inline, and focus should be restored in that case as well.)
99         if (document()->focusNode() == this && renderer()->isWidget() && 
100             static_cast<RenderWidget*>(renderer())->widget())
101             static_cast<RenderWidget*>(renderer())->widget()->setFocus();
102     }
103 }
104
105 void HTMLGenericFormElement::insertedIntoTree(bool deep)
106 {
107     if (!m_form) {
108         // This handles the case of a new form element being created by
109         // JavaScript and inserted inside a form.  In the case of the parser
110         // setting a form, we will already have a non-null value for m_form, 
111         // and so we don't need to do anything.
112         m_form = getForm();
113         if (m_form)
114             m_form->registerFormElement(this);
115         else
116             if (isRadioButton() && !name().isEmpty() && isChecked())
117                 document()->radioButtonChecked((HTMLInputElement*)this, m_form);
118     }
119
120     HTMLElement::insertedIntoTree(deep);
121 }
122
123 static inline Node* findRoot(Node* n)
124 {
125     Node* root = n;
126     for (; n; n = n->parentNode())
127         root = n;
128     return root;
129 }
130
131 void HTMLGenericFormElement::removedFromTree(bool deep)
132 {
133     // If the form and element are both in the same tree, preserve the connection to the form.
134     // Otherwise, null out our form and remove ourselves from the form's list of elements.
135     if (m_form && !m_form->preserveAcrossRemove() && findRoot(this) != findRoot(m_form)) {
136         m_form->removeFormElement(this);
137         m_form = 0;
138     }
139     HTMLElement::removedFromTree(deep);
140 }
141
142 HTMLFormElement* HTMLGenericFormElement::getForm() const
143 {
144     for (Node* p = parentNode(); p; p = p->parentNode())
145         if (p->hasTagName(formTag))
146             return static_cast<HTMLFormElement*>(p);
147     return 0;
148 }
149
150 const AtomicString& HTMLGenericFormElement::name() const
151 {
152     const AtomicString& n = getAttribute(nameAttr);
153     return n.isNull() ? emptyAtom : n;
154 }
155
156 void HTMLGenericFormElement::setName(const AtomicString &value)
157 {
158     setAttribute(nameAttr, value);
159 }
160
161 void HTMLGenericFormElement::onSelect()
162 {
163     // ### make this work with new form events architecture
164     dispatchHTMLEvent(selectEvent,true,false);
165 }
166
167 void HTMLGenericFormElement::onChange()
168 {
169     // ### make this work with new form events architecture
170     dispatchHTMLEvent(changeEvent,true,false);
171 }
172
173 bool HTMLGenericFormElement::disabled() const
174 {
175     return m_disabled;
176 }
177
178 void HTMLGenericFormElement::setDisabled(bool b)
179 {
180     setAttribute(disabledAttr, b ? "" : 0);
181 }
182
183 void HTMLGenericFormElement::setReadOnly(bool b)
184 {
185     setAttribute(readonlyAttr, b ? "" : 0);
186 }
187
188 void HTMLGenericFormElement::recalcStyle( StyleChange ch )
189 {
190     //bool changed = changed();
191     HTMLElement::recalcStyle( ch );
192
193     if (renderer() /*&& changed*/)
194         renderer()->updateFromElement();
195 }
196
197 bool HTMLGenericFormElement::isFocusable() const
198 {
199     if (disabled() || !renderer() || 
200         (renderer()->style() && renderer()->style()->visibility() != VISIBLE) || 
201         renderer()->width() == 0 || renderer()->height() == 0)
202         return false;
203     return true;
204 }
205
206 bool HTMLGenericFormElement::isKeyboardFocusable(KeyboardEvent* event) const
207 {
208     if (isFocusable()) {
209         if (renderer()->isWidget()) {
210             return static_cast<RenderWidget*>(renderer())->widget() &&
211                 (static_cast<RenderWidget*>(renderer())->widget()->focusPolicy() & Widget::TabFocus);
212         }
213         if (document()->frame())
214             return document()->frame()->tabsToAllControls(event);
215     }
216     return false;
217 }
218
219 bool HTMLGenericFormElement::isMouseFocusable() const
220 {
221     if (isFocusable()) {
222         if (renderer()->isWidget()) {
223             return static_cast<RenderWidget*>(renderer())->widget() &&
224                 (static_cast<RenderWidget*>(renderer())->widget()->focusPolicy() & Widget::ClickFocus);
225         } 
226         // For <input type=image> and <button>, we will assume no mouse focusability.  This is
227         // consistent with OS X behavior for buttons.
228         return false;
229     }
230     return false;
231 }
232
233 String HTMLGenericFormElement::stateValue() const
234 {
235     // Should only reach here if object is inserted into the "form element with
236     // state" set. If so, the derived class is responsible for implementing this function.
237     ASSERT_NOT_REACHED();
238     return String();
239 }
240
241 void HTMLGenericFormElement::restoreState(const String&)
242 {
243     // Should only reach here if object of this type was once inserted into the
244     // "form element with state" set. If so, the derived class is responsible for
245     // implementing this function.
246     ASSERT_NOT_REACHED();
247 }
248
249 void HTMLGenericFormElement::closeRenderer()
250 {
251     Document* doc = document();
252     if (doc->hasStateForNewFormElements()) {
253         String state;
254         if (doc->takeStateForFormElement(name().impl(), type().impl(), state))
255             restoreState(state);
256     }
257 }
258
259 int HTMLGenericFormElement::tabIndex() const
260 {
261     return getAttribute(tabindexAttr).toInt();
262 }
263
264 void HTMLGenericFormElement::setTabIndex(int value)
265 {
266     setAttribute(tabindexAttr, String::number(value));
267 }
268     
269 } // namespace