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 "core/html/HTMLContentElement.h"
30#include "core/html/HTMLFormControlElementWithState.h"
31#include "core/html/HTMLOptionsCollection.h"
32#include "core/html/forms/TypeAhead.h"
33#include "wtf/Vector.h"
34
35namespace blink {
36
37class AutoscrollController;
38class ExceptionState;
39class HTMLOptionElement;
40class MouseEvent;
41
42class HTMLSelectElement FINAL : public HTMLFormControlElementWithState, public TypeAheadDataSource {
43    DEFINE_WRAPPERTYPEINFO();
44public:
45    static PassRefPtrWillBeRawPtr<HTMLSelectElement> create(Document&);
46    static PassRefPtrWillBeRawPtr<HTMLSelectElement> create(Document&, HTMLFormElement*);
47
48    int selectedIndex() const;
49    void setSelectedIndex(int);
50    int suggestedIndex() const;
51    void setSuggestedIndex(int);
52
53    void optionSelectedByUser(int index, bool dispatchChangeEvent, bool allowMultipleSelection = false);
54
55    // For ValidityState
56    virtual String validationMessage() const OVERRIDE;
57    virtual bool valueMissing() const OVERRIDE;
58
59    virtual void resetImpl() OVERRIDE;
60
61    unsigned length() const;
62
63    int size() const { return m_size; }
64    bool multiple() const { return m_multiple; }
65
66    bool usesMenuList() const;
67
68    void add(HTMLElement*, HTMLElement* beforeElement, ExceptionState&);
69    void addBeforeOptionAtIndex(HTMLElement*, int beforeIndex, ExceptionState&);
70
71    using Node::remove;
72    void remove(int index);
73
74    String value() const;
75    void setValue(const String&, bool sendEvents = false);
76    String suggestedValue() const;
77    void setSuggestedValue(const String&);
78
79    PassRefPtrWillBeRawPtr<HTMLOptionsCollection> options();
80    PassRefPtrWillBeRawPtr<HTMLCollection> selectedOptions();
81
82    void optionElementChildrenChanged();
83
84    void setRecalcListItems();
85    void invalidateSelectedItems();
86    void updateListItemSelectedStates();
87
88    const WillBeHeapVector<RawPtrWillBeMember<HTMLElement> >& listItems() const;
89
90    virtual void accessKeyAction(bool sendMouseEvents) OVERRIDE;
91    void accessKeySetSelectedIndex(int);
92
93    void setMultiple(bool);
94
95    void setSize(int);
96
97    void setOption(unsigned index, HTMLOptionElement*, ExceptionState&);
98    void setLength(unsigned, ExceptionState&);
99
100    Element* namedItem(const AtomicString& name);
101    HTMLOptionElement* item(unsigned index);
102
103    void scrollToSelection();
104    void scrollTo(int listIndex);
105
106    void listBoxSelectItem(int listIndex, bool allowMultiplySelections, bool shift, bool fireOnChangeNow = true);
107
108    bool canSelectAll() const;
109    void selectAll();
110    int listToOptionIndex(int listIndex) const;
111    void listBoxOnChange();
112    int optionToListIndex(int optionIndex) const;
113    int activeSelectionStartListIndex() const;
114    int activeSelectionEndListIndex() const;
115    void setActiveSelectionAnchorIndex(int);
116    void setActiveSelectionEndIndex(int);
117
118    // For use in the implementation of HTMLOptionElement.
119    void optionSelectionStateChanged(HTMLOptionElement*, bool optionIsSelected);
120    void optionRemoved(const HTMLOptionElement&);
121    bool anonymousIndexedSetter(unsigned, PassRefPtrWillBeRawPtr<HTMLOptionElement>, ExceptionState&);
122
123    void updateListOnRenderer();
124
125    HTMLOptionElement* spatialNavigationFocusedOption();
126    void handleMouseRelease();
127
128    virtual void trace(Visitor*) OVERRIDE;
129
130protected:
131    HTMLSelectElement(Document&, HTMLFormElement*);
132
133private:
134    virtual const AtomicString& formControlType() const OVERRIDE;
135
136    virtual bool shouldShowFocusRingOnMouseFocus() const OVERRIDE;
137
138    virtual void dispatchFocusEvent(Element* oldFocusedElement, FocusType) OVERRIDE;
139    virtual void dispatchBlurEvent(Element* newFocusedElemnet) OVERRIDE;
140
141    virtual bool canStartSelection() const OVERRIDE { return false; }
142
143    virtual bool isEnumeratable() const OVERRIDE { return true; }
144    virtual bool isInteractiveContent() const OVERRIDE;
145    virtual bool supportsAutofocus() const OVERRIDE;
146    virtual bool supportLabels() const OVERRIDE { return true; }
147
148    virtual FormControlState saveFormControlState() const OVERRIDE;
149    virtual void restoreFormControlState(const FormControlState&) OVERRIDE;
150
151    virtual void parseAttribute(const QualifiedName&, const AtomicString&) OVERRIDE;
152    virtual bool isPresentationAttribute(const QualifiedName&) const OVERRIDE;
153
154    virtual RenderObject* createRenderer(RenderStyle*) OVERRIDE;
155    virtual bool appendFormData(FormDataList&, bool) OVERRIDE;
156    virtual void didAddUserAgentShadowRoot(ShadowRoot&) OVERRIDE;
157
158    virtual void defaultEventHandler(Event*) OVERRIDE;
159
160    void dispatchInputAndChangeEventForMenuList(bool requiresUserGesture = true);
161
162    void recalcListItems(bool updateSelectedStates = true) const;
163
164    void typeAheadFind(KeyboardEvent*);
165    void saveLastSelection();
166
167    virtual InsertionNotificationRequest insertedInto(ContainerNode*) OVERRIDE;
168
169    virtual bool isOptionalFormControl() const OVERRIDE { return !isRequiredFormControl(); }
170    virtual bool isRequiredFormControl() const OVERRIDE;
171
172    bool hasPlaceholderLabelOption() const;
173
174    enum SelectOptionFlag {
175        DeselectOtherOptions = 1 << 0,
176        DispatchInputAndChangeEvent = 1 << 1,
177        UserDriven = 1 << 2,
178    };
179    typedef unsigned SelectOptionFlags;
180    void selectOption(int optionIndex, SelectOptionFlags = 0);
181    void deselectItemsWithoutValidation(HTMLElement* elementToExclude = 0);
182    void parseMultipleAttribute(const AtomicString&);
183    int lastSelectedListIndex() const;
184    void updateSelectedState(int listIndex, bool multi, bool shift);
185    void menuListDefaultEventHandler(Event*);
186    void handlePopupOpenKeyboardEvent(Event*);
187    bool shouldOpenPopupForKeyDownEvent(KeyboardEvent*);
188    bool shouldOpenPopupForKeyPressEvent(KeyboardEvent*);
189    void listBoxDefaultEventHandler(Event*);
190    void setOptionsChangedOnRenderer();
191    size_t searchOptionsForValue(const String&, size_t listIndexStart, size_t listIndexEnd) const;
192    void updateListBoxSelection(bool deselectOtherOptions, bool scroll = true);
193
194    enum SkipDirection {
195        SkipBackwards = -1,
196        SkipForwards = 1
197    };
198    int nextValidIndex(int listIndex, SkipDirection, int skip) const;
199    int nextSelectableListIndex(int startIndex) const;
200    int previousSelectableListIndex(int startIndex) const;
201    int firstSelectableListIndex() const;
202    int lastSelectableListIndex() const;
203    int nextSelectableListIndexPageAway(int startIndex, SkipDirection) const;
204    int listIndexForEventTargetOption(const Event&);
205    int listIndexForOption(const HTMLOptionElement&);
206    AutoscrollController* autoscrollController() const;
207
208    virtual void childrenChanged(const ChildrenChange&) OVERRIDE;
209    virtual bool areAuthorShadowsAllowed() const OVERRIDE { return false; }
210    virtual void finishParsingChildren() OVERRIDE;
211
212    // TypeAheadDataSource functions.
213    virtual int indexOfSelectedOption() const OVERRIDE;
214    virtual int optionCount() const OVERRIDE;
215    virtual String optionAtIndex(int index) const OVERRIDE;
216
217    // m_listItems contains HTMLOptionElement, HTMLOptGroupElement, and HTMLHRElement objects.
218    mutable WillBeHeapVector<RawPtrWillBeMember<HTMLElement> > m_listItems;
219    Vector<bool> m_lastOnChangeSelection;
220    Vector<bool> m_cachedStateForActiveSelection;
221    TypeAhead m_typeAhead;
222    int m_size;
223    int m_lastOnChangeIndex;
224    int m_activeSelectionAnchorIndex;
225    int m_activeSelectionEndIndex;
226    bool m_isProcessingUserDrivenChange;
227    bool m_multiple;
228    bool m_activeSelectionState;
229    mutable bool m_shouldRecalcListItems;
230    int m_suggestedIndex;
231};
232
233} // namespace blink
234
235#endif // HTMLSelectElement_h
236