2 * This file is part of the DOM implementation for KDE.
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)
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.
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.
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.
28 #include "HTMLGenericFormElement.h"
30 #include "EventNames.h"
32 #include "HTMLFormElement.h"
33 #include "HTMLNames.h"
34 #include "RenderTheme.h"
35 #include "RenderWidget.h"
40 using namespace EventNames;
41 using namespace HTMLNames;
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)
49 m_form->registerFormElement(this);
52 HTMLGenericFormElement::~HTMLGenericFormElement()
55 m_form->removeFormElement(this);
58 void HTMLGenericFormElement::parseMappedAttribute(MappedAttribute *attr)
60 if (attr->name() == nameAttr) {
62 } else if (attr->name() == disabledAttr) {
63 bool oldDisabled = m_disabled;
64 m_disabled = !attr->isNull();
65 if (oldDisabled != m_disabled) {
67 if (renderer() && renderer()->style()->hasAppearance())
68 theme()->stateChanged(renderer(), EnabledState);
70 } else if (attr->name() == readonlyAttr) {
71 bool oldReadOnly = m_readOnly;
72 m_readOnly = !attr->isNull();
73 if (oldReadOnly != m_readOnly) {
75 if (renderer() && renderer()->style()->hasAppearance())
76 theme()->stateChanged(renderer(), ReadOnlyState);
79 HTMLElement::parseMappedAttribute(attr);
82 void HTMLGenericFormElement::attach()
86 HTMLElement::attach();
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
92 renderer()->updateFromElement();
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();
105 void HTMLGenericFormElement::insertedIntoTree(bool deep)
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.
114 m_form->registerFormElement(this);
116 if (isRadioButton() && !name().isEmpty() && isChecked())
117 document()->radioButtonChecked((HTMLInputElement*)this, m_form);
120 HTMLElement::insertedIntoTree(deep);
123 static inline Node* findRoot(Node* n)
126 for (; n; n = n->parentNode())
131 void HTMLGenericFormElement::removedFromTree(bool deep)
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);
139 HTMLElement::removedFromTree(deep);
142 HTMLFormElement* HTMLGenericFormElement::getForm() const
144 for (Node* p = parentNode(); p; p = p->parentNode())
145 if (p->hasTagName(formTag))
146 return static_cast<HTMLFormElement*>(p);
150 const AtomicString& HTMLGenericFormElement::name() const
152 const AtomicString& n = getAttribute(nameAttr);
153 return n.isNull() ? emptyAtom : n;
156 void HTMLGenericFormElement::setName(const AtomicString &value)
158 setAttribute(nameAttr, value);
161 void HTMLGenericFormElement::onSelect()
163 // ### make this work with new form events architecture
164 dispatchHTMLEvent(selectEvent,true,false);
167 void HTMLGenericFormElement::onChange()
169 // ### make this work with new form events architecture
170 dispatchHTMLEvent(changeEvent,true,false);
173 bool HTMLGenericFormElement::disabled() const
178 void HTMLGenericFormElement::setDisabled(bool b)
180 setAttribute(disabledAttr, b ? "" : 0);
183 void HTMLGenericFormElement::setReadOnly(bool b)
185 setAttribute(readonlyAttr, b ? "" : 0);
188 void HTMLGenericFormElement::recalcStyle( StyleChange ch )
190 //bool changed = changed();
191 HTMLElement::recalcStyle( ch );
193 if (renderer() /*&& changed*/)
194 renderer()->updateFromElement();
197 bool HTMLGenericFormElement::isFocusable() const
199 if (disabled() || !renderer() ||
200 (renderer()->style() && renderer()->style()->visibility() != VISIBLE) ||
201 renderer()->width() == 0 || renderer()->height() == 0)
206 bool HTMLGenericFormElement::isKeyboardFocusable(KeyboardEvent* event) const
209 if (renderer()->isWidget()) {
210 return static_cast<RenderWidget*>(renderer())->widget() &&
211 (static_cast<RenderWidget*>(renderer())->widget()->focusPolicy() & Widget::TabFocus);
213 if (document()->frame())
214 return document()->frame()->tabsToAllControls(event);
219 bool HTMLGenericFormElement::isMouseFocusable() const
222 if (renderer()->isWidget()) {
223 return static_cast<RenderWidget*>(renderer())->widget() &&
224 (static_cast<RenderWidget*>(renderer())->widget()->focusPolicy() & Widget::ClickFocus);
226 // For <input type=image> and <button>, we will assume no mouse focusability. This is
227 // consistent with OS X behavior for buttons.
233 String HTMLGenericFormElement::stateValue() const
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();
241 void HTMLGenericFormElement::restoreState(const String&)
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();
249 void HTMLGenericFormElement::closeRenderer()
251 Document* doc = document();
252 if (doc->hasStateForNewFormElements()) {
254 if (doc->takeStateForFormElement(name().impl(), type().impl(), state))
259 int HTMLGenericFormElement::tabIndex() const
261 return getAttribute(tabindexAttr).toInt();
264 void HTMLGenericFormElement::setTabIndex(int value)
266 setAttribute(tabindexAttr, String::number(value));