| /* |
| * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). |
| * Copyright (C) 1999 Lars Knoll (knoll@kde.org) |
| * (C) 1999 Antti Koivisto (koivisto@kde.org) |
| * (C) 2000 Dirk Mueller (mueller@kde.org) |
| * Copyright (C) 2004, 2005, 2006, 2007, 2009, 2010, 2011 Apple Inc. All rights |
| * reserved. |
| * Copyright (C) 2010 Google Inc. All rights reserved. |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Library General Public |
| * License as published by the Free Software Foundation; either |
| * version 2 of the License, or (at your option) any later version. |
| * |
| * This library is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Library General Public License for more details. |
| * |
| * You should have received a copy of the GNU Library General Public License |
| * along with this library; see the file COPYING.LIB. If not, write to |
| * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
| * Boston, MA 02110-1301, USA. |
| * |
| */ |
| |
| #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HTML_FORMS_HTML_SELECT_ELEMENT_H_ |
| #define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_FORMS_HTML_SELECT_ELEMENT_H_ |
| |
| #include "base/gtest_prod_util.h" |
| #include "third_party/blink/renderer/core/core_export.h" |
| #include "third_party/blink/renderer/core/html/forms/html_form_control_element_with_state.h" |
| #include "third_party/blink/renderer/core/html/forms/html_options_collection.h" |
| #include "third_party/blink/renderer/core/html/forms/option_list.h" |
| #include "third_party/blink/renderer/core/html/forms/type_ahead.h" |
| #include "third_party/blink/renderer/platform/wtf/vector.h" |
| |
| namespace blink { |
| |
| class AutoscrollController; |
| class ExceptionState; |
| class HTMLHRElement; |
| class HTMLOptGroupElement; |
| class HTMLOptionElement; |
| class HTMLOptionElementOrHTMLOptGroupElement; |
| class HTMLElementOrLong; |
| class PopupMenu; |
| |
| class CORE_EXPORT HTMLSelectElement final |
| : public HTMLFormControlElementWithState, |
| private TypeAheadDataSource { |
| DEFINE_WRAPPERTYPEINFO(); |
| |
| public: |
| static HTMLSelectElement* Create(Document&); |
| |
| explicit HTMLSelectElement(Document&); |
| ~HTMLSelectElement() override; |
| |
| int selectedIndex() const; |
| void setSelectedIndex(int); |
| // `listIndex' version of |selectedIndex|. |
| int SelectedListIndex() const; |
| |
| // For ValidityState |
| String validationMessage() const override; |
| bool ValueMissing() const override; |
| |
| String DefaultToolTip() const override; |
| void ResetImpl() override; |
| |
| unsigned length() const; |
| void setLength(unsigned, ExceptionState&); |
| |
| // TODO(tkent): Rename |size| to |Size|. This is not an implementation of |
| // |size| IDL attribute. |
| unsigned size() const { return size_; } |
| bool IsMultiple() const { return is_multiple_; } |
| |
| bool UsesMenuList() const; |
| |
| void add(const HTMLOptionElementOrHTMLOptGroupElement&, |
| const HTMLElementOrLong&, |
| ExceptionState&); |
| |
| using Node::remove; |
| void remove(int index); |
| |
| String value() const; |
| void setValue(const String&, bool send_events = false); |
| String SuggestedValue() const; |
| void SetSuggestedValue(const String&); |
| |
| // |options| and |selectedOptions| are not safe to be used in in |
| // HTMLOptionElement::removedFrom() and insertedInto() because their cache |
| // is inconsistent in these functions. |
| HTMLOptionsCollection* options(); |
| HTMLCollection* selectedOptions(); |
| |
| // This is similar to |options| HTMLCollection. But this is safe in |
| // HTMLOptionElement::removedFrom() and insertedInto(). |
| // OptionList supports only forward iteration. |
| OptionList GetOptionList() const { return OptionList(*this); } |
| |
| void OptionElementChildrenChanged(const HTMLOptionElement&); |
| |
| void InvalidateSelectedItems(); |
| |
| using ListItems = HeapVector<Member<HTMLElement>>; |
| // We prefer |optionList()| to |listItems()|. |
| const ListItems& GetListItems() const; |
| |
| void AccessKeyAction(bool send_mouse_events) override; |
| void SelectOptionByAccessKey(HTMLOptionElement*); |
| |
| void SetOption(unsigned index, HTMLOptionElement*, ExceptionState&); |
| |
| Element* namedItem(const AtomicString& name); |
| HTMLOptionElement* item(unsigned index); |
| |
| void ScrollToSelection(); |
| void ScrollToOption(HTMLOptionElement*); |
| |
| bool CanSelectAll() const; |
| void SelectAll(); |
| void ListBoxOnChange(); |
| int ActiveSelectionEndListIndex() const; |
| HTMLOptionElement* ActiveSelectionEnd() const; |
| void SetActiveSelectionAnchor(HTMLOptionElement*); |
| void SetActiveSelectionEnd(HTMLOptionElement*); |
| |
| // For use in the implementation of HTMLOptionElement. |
| void OptionSelectionStateChanged(HTMLOptionElement*, bool option_is_selected); |
| void OptionInserted(HTMLOptionElement&, bool option_is_selected); |
| void OptionRemoved(HTMLOptionElement&); |
| bool AnonymousIndexedSetter(unsigned, HTMLOptionElement*, ExceptionState&); |
| |
| void OptGroupInsertedOrRemoved(HTMLOptGroupElement&); |
| void HrInsertedOrRemoved(HTMLHRElement&); |
| |
| HTMLOptionElement* SpatialNavigationFocusedOption(); |
| void HandleMouseRelease(); |
| |
| int ListIndexForOption(const HTMLOptionElement&); |
| |
| // Helper functions for popup menu implementations. |
| String ItemText(const Element&) const; |
| bool ItemIsDisplayNone(Element&) const; |
| // itemComputedStyle() returns nullptr only if the owner Document is not |
| // active. So, It returns a valid object when we open a popup. |
| const ComputedStyle* ItemComputedStyle(Element&) const; |
| // Text starting offset in LTR. |
| LayoutUnit ClientPaddingLeft() const; |
| // Text starting offset in RTL. |
| LayoutUnit ClientPaddingRight() const; |
| void SelectOptionByPopup(int list_index); |
| void SelectMultipleOptionsByPopup(const Vector<int>& list_indices); |
| // A popup is canceled when the popup was hidden without selecting an item. |
| void PopupDidCancel(); |
| // Provisional selection is a selection made using arrow keys or type ahead. |
| void ProvisionalSelectionChanged(unsigned); |
| void PopupDidHide(); |
| bool PopupIsVisible() const { return popup_is_visible_; } |
| HTMLOptionElement* OptionToBeShown() const; |
| void ShowPopup(); |
| void HidePopup(); |
| PopupMenu* Popup() const { return popup_.Get(); } |
| void DidMutateSubtree(); |
| |
| void ResetTypeAheadSessionForTesting(); |
| |
| // Used for slot assignment. |
| static bool CanAssignToSelectSlot(const Node&); |
| |
| bool HasNonInBodyInsertionMode() const override { return true; } |
| |
| void Trace(blink::Visitor*) override; |
| void CloneNonAttributePropertiesFrom(const Element&, |
| CloneChildrenFlag) override; |
| |
| private: |
| const AtomicString& FormControlType() const override; |
| |
| bool MayTriggerVirtualKeyboard() const override; |
| |
| void DispatchFocusEvent( |
| Element* old_focused_element, |
| WebFocusType, |
| InputDeviceCapabilities* source_capabilities) override; |
| void DispatchBlurEvent(Element* new_focused_element, |
| WebFocusType, |
| InputDeviceCapabilities* source_capabilities) override; |
| |
| bool CanStartSelection() const override { return false; } |
| |
| bool IsEnumeratable() const override { return true; } |
| bool IsInteractiveContent() const override; |
| bool SupportsAutofocus() const override; |
| bool IsLabelable() const override { return true; } |
| |
| FormControlState SaveFormControlState() const override; |
| void RestoreFormControlState(const FormControlState&) override; |
| |
| void ParseAttribute(const AttributeModificationParams&) override; |
| bool IsPresentationAttribute(const QualifiedName&) const override; |
| |
| LayoutObject* CreateLayoutObject(const ComputedStyle&) override; |
| void DidRecalcStyle(StyleRecalcChange) override; |
| void DetachLayoutTree(const AttachContext& = AttachContext()) override; |
| void AppendToFormData(FormData&) override; |
| void DidAddUserAgentShadowRoot(ShadowRoot&) override; |
| |
| void DefaultEventHandler(Event&) override; |
| |
| void DispatchInputAndChangeEventForMenuList(); |
| |
| void SetRecalcListItems(); |
| void RecalcListItems() const; |
| enum ResetReason { kResetReasonSelectedOptionRemoved, kResetReasonOthers }; |
| void ResetToDefaultSelection(ResetReason = kResetReasonOthers); |
| void TypeAheadFind(const KeyboardEvent&); |
| void SaveLastSelection(); |
| void SaveListboxActiveSelection(); |
| // Returns the first selected OPTION, or nullptr. |
| HTMLOptionElement* SelectedOption() const; |
| |
| bool IsOptionalFormControl() const override { |
| return !IsRequiredFormControl(); |
| } |
| bool IsRequiredFormControl() const override; |
| |
| bool HasPlaceholderLabelOption() const; |
| |
| enum SelectOptionFlag { |
| kDeselectOtherOptionsFlag = 1 << 0, |
| kDispatchInputAndChangeEventFlag = 1 << 1, |
| kMakeOptionDirtyFlag = 1 << 2, |
| }; |
| typedef unsigned SelectOptionFlags; |
| void SelectOption(HTMLOptionElement*, SelectOptionFlags); |
| bool DeselectItemsWithoutValidation( |
| HTMLOptionElement* element_to_exclude = nullptr); |
| void ParseMultipleAttribute(const AtomicString&); |
| HTMLOptionElement* LastSelectedOption() const; |
| void UpdateSelectedState(HTMLOptionElement*, bool multi, bool shift); |
| void MenuListDefaultEventHandler(Event&); |
| void HandlePopupOpenKeyboardEvent(Event&); |
| bool ShouldOpenPopupForKeyDownEvent(const KeyboardEvent&); |
| bool ShouldOpenPopupForKeyPressEvent(const KeyboardEvent&); |
| void ListBoxDefaultEventHandler(Event&); |
| void SetOptionsChangedOnLayoutObject(); |
| wtf_size_t SearchOptionsForValue(const String&, |
| wtf_size_t list_index_start, |
| wtf_size_t list_index_end) const; |
| void UpdateListBoxSelection(bool deselect_other_options, bool scroll = true); |
| void SetIndexToSelectOnCancel(int list_index); |
| void SetSuggestedOption(HTMLOptionElement*); |
| |
| // Returns nullptr if listIndex is out of bounds, or it doesn't point an |
| // HTMLOptionElement. |
| HTMLOptionElement* OptionAtListIndex(int list_index) const; |
| enum SkipDirection { kSkipBackwards = -1, kSkipForwards = 1 }; |
| HTMLOptionElement* NextValidOption(int list_index, |
| SkipDirection, |
| int skip) const; |
| HTMLOptionElement* NextSelectableOption(HTMLOptionElement*) const; |
| HTMLOptionElement* PreviousSelectableOption(HTMLOptionElement*) const; |
| HTMLOptionElement* FirstSelectableOption() const; |
| HTMLOptionElement* LastSelectableOption() const; |
| HTMLOptionElement* NextSelectableOptionPageAway(HTMLOptionElement*, |
| SkipDirection) const; |
| HTMLOptionElement* EventTargetOption(const Event&); |
| AutoscrollController* GetAutoscrollController() const; |
| void ScrollToOptionTask(); |
| |
| bool AreAuthorShadowsAllowed() const override { return false; } |
| void FinishParsingChildren() override; |
| |
| // TypeAheadDataSource functions. |
| int IndexOfSelectedOption() const override; |
| int OptionCount() const override; |
| String OptionAtIndex(int index) const override; |
| |
| void ObserveTreeMutation(); |
| void UnobserveTreeMutation(); |
| |
| // list_items_ contains HTMLOptionElement, HTMLOptGroupElement, and |
| // HTMLHRElement objects. |
| mutable ListItems list_items_; |
| Vector<bool> last_on_change_selection_; |
| Vector<bool> cached_state_for_active_selection_; |
| TypeAhead type_ahead_; |
| unsigned size_; |
| Member<HTMLOptionElement> last_on_change_option_; |
| Member<HTMLOptionElement> active_selection_anchor_; |
| Member<HTMLOptionElement> active_selection_end_; |
| Member<HTMLOptionElement> option_to_scroll_to_; |
| Member<HTMLOptionElement> suggested_option_; |
| bool is_multiple_; |
| bool active_selection_state_; |
| mutable bool should_recalc_list_items_; |
| bool is_autofilled_by_preview_; |
| |
| class PopupUpdater; |
| Member<PopupUpdater> popup_updater_; |
| Member<PopupMenu> popup_; |
| int index_to_select_on_cancel_; |
| bool popup_is_visible_; |
| |
| FRIEND_TEST_ALL_PREFIXES(HTMLSelectElementTest, FirstSelectableOption); |
| FRIEND_TEST_ALL_PREFIXES(HTMLSelectElementTest, LastSelectableOption); |
| FRIEND_TEST_ALL_PREFIXES(HTMLSelectElementTest, NextSelectableOption); |
| FRIEND_TEST_ALL_PREFIXES(HTMLSelectElementTest, PreviousSelectableOption); |
| }; |
| |
| } // namespace blink |
| |
| #endif // THIRD_PARTY_BLINK_RENDERER_CORE_HTML_FORMS_HTML_SELECT_ELEMENT_H_ |