summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/core/html/forms/html_select_element.h
blob: 314840a3f45e8a049d4b6bc9b4a32f441cb01773 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
/*
 * 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/public/mojom/input/focus_type.mojom-blink-forward.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 LayoutUnit;
class PopupMenu;
class SelectType;

class CORE_EXPORT HTMLSelectElement final
    : public HTMLFormControlElementWithState,
      private TypeAheadDataSource {
  DEFINE_WRAPPERTYPEINFO();

 public:
  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_; }
  // The number of items to be shown in the LisBox mode.
  // Do not call this in the MenuList mode.
  unsigned ListBoxSize() const;
  bool IsMultiple() const { return is_multiple_; }

  bool UsesMenuList() const { return uses_menu_list_; }

  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();
  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&);
  IndexedPropertySetterResult AnonymousIndexedSetter(unsigned,
                                                     HTMLOptionElement*,
                                                     ExceptionState&);

  void OptGroupInsertedOrRemoved(HTMLOptGroupElement&);
  void HrInsertedOrRemoved(HTMLHRElement&);

  HTMLOptionElement* SpatialNavigationFocusedOption();

  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;
  HTMLOptionElement* OptionToBeShownForTesting() const;
  // Style of the selected OPTION. This is nullable, and only for
  // the menulist mode.
  const ComputedStyle* OptionStyle() const;
  void ShowPopup();
  void HidePopup();
  PopupMenu* PopupForTesting() const;

  void ResetTypeAheadSessionForTesting();

  // Used for slot assignment.
  static bool CanAssignToSelectSlot(const Node&);

  bool HasNonInBodyInsertionMode() const override { return true; }

  void Trace(Visitor*) override;
  void CloneNonAttributePropertiesFrom(const Element&,
                                       CloneChildrenFlag) override;

  // This should be called only if UsesMenuList().
  Element& InnerElement() const;

 private:
  const AtomicString& FormControlType() const override;

  bool MayTriggerVirtualKeyboard() const override;

  bool ShouldHaveFocusAppearance() const final;

  void DispatchFocusEvent(
      Element* old_focused_element,
      mojom::blink::FocusType,
      InputDeviceCapabilities* source_capabilities) override;
  void DispatchBlurEvent(Element* new_focused_element,
                         mojom::blink::FocusType,
                         InputDeviceCapabilities* source_capabilities) override;

  bool CanStartSelection() const override { return false; }

  bool IsEnumeratable() const override { return true; }
  bool IsInteractiveContent() const override;
  bool IsLabelable() const override { return true; }

  FormControlState SaveFormControlState() const override;
  void RestoreFormControlState(const FormControlState&) override;

  void ChildrenChanged(const ChildrenChange& change) override;
  bool ChildrenChangedAllChildrenRemovedNeedsList() const override;
  void ParseAttribute(const AttributeModificationParams&) override;
  bool IsPresentationAttribute(const QualifiedName&) const override;

  bool TypeShouldForceLegacyLayout() const override;
  LayoutObject* CreateLayoutObject(const ComputedStyle&, LegacyLayout) override;
  void DidRecalcStyle(const StyleRecalcChange) override;
  void AttachLayoutTree(AttachContext&) override;
  void DetachLayoutTree(bool performing_reattach = false) override;
  void AppendToFormData(FormData&) override;
  void DidAddUserAgentShadowRoot(ShadowRoot&) override;

  void DefaultEventHandler(Event&) override;

  void SetRecalcListItems();
  void RecalcListItems() const;
  enum ResetReason { kResetReasonSelectedOptionRemoved, kResetReasonOthers };
  void ResetToDefaultSelection(ResetReason = kResetReasonOthers);
  void TypeAheadFind(const KeyboardEvent&);
  // 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;
  wtf_size_t SearchOptionsForValue(const String&,
                                   wtf_size_t list_index_start,
                                   wtf_size_t list_index_end) const;
  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;

  AutoscrollController* GetAutoscrollController() const;
  LayoutBox* AutoscrollBox() override;
  void StopAutoscroll() override;
  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 UpdateUsesMenuList();
  // Apply changes to rendering as a result of attribute changes (multiple,
  // size).
  void ChangeRendering();
  void UpdateUserAgentShadowTree(ShadowRoot& root);

  // list_items_ contains HTMLOptionElement, HTMLOptGroupElement, and
  // HTMLHRElement objects.
  mutable ListItems list_items_;
  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 uses_menu_list_ = true;
  bool is_multiple_;
  mutable bool should_recalc_list_items_;
  bool is_autofilled_by_preview_;

  Member<SelectType> select_type_;
  int index_to_select_on_cancel_;

  friend class ListBoxSelectType;
  friend class MenuListSelectType;
  friend class SelectType;
  friend class HTMLSelectElementTest;
};

}  // namespace blink

#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_HTML_FORMS_HTML_SELECT_ELEMENT_H_