Follow up the recent HTMLSelectElement improvements with a little bit more
[WebKit-https.git] / Source / WebCore / html / HTMLSelectElement.h
1 /*
2  * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
3  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
4  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
5  *           (C) 2000 Dirk Mueller (mueller@kde.org)
6  * Copyright (C) 2004, 2005, 2006, 2007, 2009, 2010, 2011 Apple Inc. All rights reserved.
7  * Copyright (C) 2010 Google Inc. All rights reserved.
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Library General Public
11  * License as published by the Free Software Foundation; either
12  * version 2 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Library General Public License for more details.
18  *
19  * You should have received a copy of the GNU Library General Public License
20  * along with this library; see the file COPYING.LIB.  If not, write to
21  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22  * Boston, MA 02110-1301, USA.
23  *
24  */
25
26 #ifndef HTMLSelectElement_h
27 #define HTMLSelectElement_h
28
29 #include "CollectionCache.h"
30 #include "Event.h"
31 #include "HTMLFormControlElement.h"
32 #include <wtf/Vector.h>
33
34 namespace WebCore {
35
36 class HTMLOptionElement;
37 class HTMLOptionsCollection;
38
39 class HTMLSelectElement : public HTMLFormControlElementWithState {
40 public:
41     static PassRefPtr<HTMLSelectElement> create(const QualifiedName&, Document*, HTMLFormElement*);
42
43     int selectedIndex() const;
44     void setSelectedIndex(int index, bool deselect = true);
45     void setSelectedIndexByUser(int index, bool deselect = true, bool fireOnChangeNow = false, bool allowMultipleSelection = false);
46
47     // For ValidityState
48     bool valueMissing() const;
49
50     unsigned length() const;
51
52     int size() const { return m_size; }
53     bool multiple() const { return m_multiple; }
54
55     void add(HTMLElement*, HTMLElement* beforeElement, ExceptionCode&);
56     void remove(int index);
57     void remove(HTMLOptionElement*);
58
59     String value() const;
60     void setValue(const String&);
61
62     PassRefPtr<HTMLOptionsCollection> options();
63
64     void optionElementChildrenChanged();
65
66     void setRecalcListItems();
67     void updateListItemSelectedStates();
68
69     const Vector<HTMLElement*>& listItems() const;
70
71     virtual void accessKeyAction(bool sendToAnyElement);
72     void accessKeySetSelectedIndex(int);
73
74     void setMultiple(bool);
75
76     void setSize(int);
77
78     void setOption(unsigned index, HTMLOptionElement*, ExceptionCode&);
79     void setLength(unsigned, ExceptionCode&);
80
81     Node* namedItem(const AtomicString& name);
82     Node* item(unsigned index);
83
84     CollectionCache* collectionInfo() { m_collectionInfo.checkConsistency(); return &m_collectionInfo; }
85
86     void scrollToSelection();
87
88     bool canSelectAll() const;
89     void selectAll();
90     int listToOptionIndex(int listIndex) const;
91     void listBoxOnChange();
92     int optionToListIndex(int optionIndex) const;
93     int activeSelectionStartListIndex() const;
94     int activeSelectionEndListIndex() const;
95     void setActiveSelectionAnchorIndex(int);
96     void setActiveSelectionEndIndex(int);
97     void updateListBoxSelection(bool deselectOtherOptions);
98     
99 protected:
100     HTMLSelectElement(const QualifiedName&, Document*, HTMLFormElement*);
101
102 private:
103     virtual const AtomicString& formControlType() const;
104     
105     virtual bool isKeyboardFocusable(KeyboardEvent*) const;
106     virtual bool isMouseFocusable() const;
107
108     virtual void dispatchFocusEvent(PassRefPtr<Node> oldFocusedNode);
109     virtual void dispatchBlurEvent(PassRefPtr<Node> newFocusedNode);
110     
111     virtual bool canStartSelection() const { return false; }
112
113     virtual bool isEnumeratable() const { return true; }
114
115     virtual bool saveFormControlState(String& value) const;
116     virtual void restoreFormControlState(const String&);
117
118     virtual void parseMappedAttribute(Attribute*);
119
120     virtual RenderObject* createRenderer(RenderArena*, RenderStyle *);
121     virtual bool appendFormData(FormDataList&, bool);
122
123     virtual void reset();
124
125     virtual void defaultEventHandler(Event*);
126
127     void menuListOnChange();
128     
129     void recalcListItems(bool updateSelectedStates = true) const;
130
131     void deselectItems(HTMLOptionElement* excludeElement = 0);
132     void typeAheadFind(KeyboardEvent*);
133     void saveLastSelection();
134
135     virtual void insertedIntoTree(bool);
136
137     virtual bool isOptionalFormControl() const { return !isRequiredFormControl(); }
138     virtual bool isRequiredFormControl() const;
139
140     bool hasPlaceholderLabelOption() const;
141
142     void setSelectedIndex(int optionIndex, bool deselect, bool fireOnChangeNow, bool userDrivenChange = true);
143     void deselectItemsWithoutValidation(Element* excludeElement = 0);
144     void parseMultipleAttribute(const Attribute*);
145     int lastSelectedListIndex() const;
146     void updateSelectedState(int listIndex, bool multi, bool shift);
147     void menuListDefaultEventHandler(Event*);
148     bool platformHandleKeydownEvent(KeyboardEvent*);
149     void listBoxDefaultEventHandler(Event*);
150     void setOptionsChangedOnRenderer();
151     bool usesMenuList() const;
152
153     enum SkipDirection {
154         SkipBackwards = -1,
155         SkipForwards = 1
156     };
157     int nextValidIndex(int listIndex, SkipDirection, int skip) const;
158     int nextSelectableListIndex(int startIndex) const;
159     int previousSelectableListIndex(int startIndex) const;
160     int firstSelectableListIndex() const;
161     int lastSelectableListIndex() const;
162     int nextSelectableListIndexPageAway(int startIndex, SkipDirection) const;
163
164     virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0);
165
166     CollectionCache m_collectionInfo;
167     // m_listItems contains HTMLOptionElement, HTMLOptGroupElement, and HTMLHRElement objects.
168     mutable Vector<HTMLElement*> m_listItems;
169     Vector<bool> m_lastOnChangeSelection;
170     Vector<bool> m_cachedStateForActiveSelection;
171     DOMTimeStamp m_lastCharTime;
172     String m_typedString;
173     int m_size;
174     int m_lastOnChangeIndex;
175     int m_activeSelectionAnchorIndex;
176     int m_activeSelectionEndIndex;
177     UChar m_repeatingChar;
178     bool m_userDrivenChange;
179     bool m_multiple;
180     bool m_activeSelectionState;
181     mutable bool m_shouldRecalcListItems;
182 };
183
184 inline void HTMLSelectElement::setSelectedIndex(int index, bool deselect)
185 {
186     setSelectedIndex(index, deselect, false);
187 }
188
189 inline bool HTMLSelectElement::usesMenuList() const
190 {
191 #if ENABLE(NO_LISTBOX_RENDERING)
192     return true;
193 #else
194     return !m_multiple && m_size <= 1;
195 #endif
196 }
197
198 HTMLSelectElement* toHTMLSelectElement(Node*);
199 const HTMLSelectElement* toHTMLSelectElement(const Node*);
200 void toHTMLSelectElement(const HTMLSelectElement*); // This overload will catch anyone doing an unnecessary cast.
201
202 #ifdef NDEBUG
203
204 // The debug versions of these, with assertions, are not inlined.
205
206 inline HTMLSelectElement* toHTMLSelectElement(Node* node)
207 {
208     return static_cast<HTMLSelectElement*>(node);
209 }
210
211 inline const HTMLSelectElement* toHTMLSelectElement(const Node* node)
212 {
213     return static_cast<const HTMLSelectElement*>(node);
214 }
215
216 #endif
217
218 } // namespace
219
220 #endif