Commit ae80ad9b authored by Kent Tamura's avatar Kent Tamura Committed by Commit Bot

Introduce blink::SelectType

This CL introduces blink::SelectType, blink::MenuListSelectType, and
blink::ListBoxSelectType.
Also, add SelectType::DidSelectOption() to simplify
HTMLSelectElement::SelectOption().

This CL has no behavior changes.

Bug: 1052232
Change-Id: I436cfdd70edf0668b03996b35008ae12f8b6c9c3
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2055950Reviewed-by: default avatarKoji Ishii <kojii@chromium.org>
Commit-Queue: Kent Tamura <tkent@chromium.org>
Cr-Commit-Position: refs/heads/master@{#741383}
parent fe91293e
...@@ -247,6 +247,8 @@ blink_core_sources("html") { ...@@ -247,6 +247,8 @@ blink_core_sources("html") {
"forms/reset_input_type.h", "forms/reset_input_type.h",
"forms/search_input_type.cc", "forms/search_input_type.cc",
"forms/search_input_type.h", "forms/search_input_type.h",
"forms/select_type.cc",
"forms/select_type.h",
"forms/slider_thumb_element.cc", "forms/slider_thumb_element.cc",
"forms/slider_thumb_element.h", "forms/slider_thumb_element.h",
"forms/spin_button_element.cc", "forms/spin_button_element.cc",
......
...@@ -60,6 +60,7 @@ ...@@ -60,6 +60,7 @@
#include "third_party/blink/renderer/core/html/forms/html_option_element.h" #include "third_party/blink/renderer/core/html/forms/html_option_element.h"
#include "third_party/blink/renderer/core/html/forms/menu_list_inner_element.h" #include "third_party/blink/renderer/core/html/forms/menu_list_inner_element.h"
#include "third_party/blink/renderer/core/html/forms/popup_menu.h" #include "third_party/blink/renderer/core/html/forms/popup_menu.h"
#include "third_party/blink/renderer/core/html/forms/select_type.h"
#include "third_party/blink/renderer/core/html/html_hr_element.h" #include "third_party/blink/renderer/core/html/html_hr_element.h"
#include "third_party/blink/renderer/core/html/html_slot_element.h" #include "third_party/blink/renderer/core/html/html_slot_element.h"
#include "third_party/blink/renderer/core/html/parser/html_parser_idioms.h" #include "third_party/blink/renderer/core/html/parser/html_parser_idioms.h"
...@@ -107,6 +108,8 @@ HTMLSelectElement::HTMLSelectElement(Document& document) ...@@ -107,6 +108,8 @@ HTMLSelectElement::HTMLSelectElement(Document& document)
is_autofilled_by_preview_(false), is_autofilled_by_preview_(false),
index_to_select_on_cancel_(-1), index_to_select_on_cancel_(-1),
popup_is_visible_(false) { popup_is_visible_(false) {
// Make sure SelectType is created after initializing |uses_menu_list_|.
select_type_ = SelectType::Create(*this);
SetHasCustomStyleCallbacks(); SetHasCustomStyleCallbacks();
EnsureUserAgentShadowRoot(); EnsureUserAgentShadowRoot();
} }
...@@ -1089,40 +1092,7 @@ void HTMLSelectElement::SelectOption(HTMLOptionElement* element, ...@@ -1089,40 +1092,7 @@ void HTMLSelectElement::SelectOption(HTMLOptionElement* element,
SetActiveSelectionEnd(element); SetActiveSelectionEnd(element);
} }
// Need to update last_on_change_option_ before select_type_->DidSelectOption(element, flags, should_update_popup);
// LayoutMenuList::UpdateFromElement.
bool should_dispatch_events = false;
if (UsesMenuList()) {
should_dispatch_events = (flags & kDispatchInputAndChangeEventFlag) &&
last_on_change_option_ != element;
last_on_change_option_ = element;
}
// For the menu list case, this is what makes the selected element appear.
UpdateMenuListLabel(UpdateFromElement());
// PopupMenu::UpdateFromElement() posts an O(N) task.
if (PopupIsVisible() && should_update_popup)
popup_->UpdateFromElement(PopupMenu::kBySelectionChange);
ScrollToSelection();
SetNeedsValidityCheck();
if (UsesMenuList()) {
if (should_dispatch_events) {
DispatchInputEvent();
DispatchChangeEvent();
}
if (LayoutObject* layout_object = GetLayoutObject()) {
// Need to check UsesMenuList() again because event handlers might
// change the status.
if (UsesMenuList()) {
// DidUpdateMenuListActiveOption() is O(N) because of
// HTMLOptionElement::index().
DidUpdateMenuListActiveOption(element);
}
}
}
NotifyFormStateChanged(); NotifyFormStateChanged();
if (LocalFrame::HasTransientUserActivation(GetDocument().GetFrame()) && if (LocalFrame::HasTransientUserActivation(GetDocument().GetFrame()) &&
...@@ -1983,6 +1953,7 @@ void HTMLSelectElement::Trace(Visitor* visitor) { ...@@ -1983,6 +1953,7 @@ void HTMLSelectElement::Trace(Visitor* visitor) {
visitor->Trace(active_selection_end_); visitor->Trace(active_selection_end_);
visitor->Trace(option_to_scroll_to_); visitor->Trace(option_to_scroll_to_);
visitor->Trace(suggested_option_); visitor->Trace(suggested_option_);
visitor->Trace(select_type_);
visitor->Trace(popup_); visitor->Trace(popup_);
visitor->Trace(popup_updater_); visitor->Trace(popup_updater_);
HTMLFormControlElementWithState::Trace(visitor); HTMLFormControlElementWithState::Trace(visitor);
...@@ -2290,6 +2261,7 @@ void HTMLSelectElement::CloneNonAttributePropertiesFrom( ...@@ -2290,6 +2261,7 @@ void HTMLSelectElement::CloneNonAttributePropertiesFrom(
void HTMLSelectElement::ChangeRendering() { void HTMLSelectElement::ChangeRendering() {
UpdateUsesMenuList(); UpdateUsesMenuList();
select_type_ = SelectType::Create(*this);
if (!InActiveDocument()) if (!InActiveDocument())
return; return;
// TODO(futhark): SetForceReattachLayoutTree() should be the correct way to // TODO(futhark): SetForceReattachLayoutTree() should be the correct way to
......
...@@ -47,6 +47,7 @@ class HTMLOptionElementOrHTMLOptGroupElement; ...@@ -47,6 +47,7 @@ class HTMLOptionElementOrHTMLOptGroupElement;
class HTMLElementOrLong; class HTMLElementOrLong;
class LayoutUnit; class LayoutUnit;
class PopupMenu; class PopupMenu;
class SelectType;
class CORE_EXPORT HTMLSelectElement final class CORE_EXPORT HTMLSelectElement final
: public HTMLFormControlElementWithState, : public HTMLFormControlElementWithState,
...@@ -333,12 +334,16 @@ class CORE_EXPORT HTMLSelectElement final ...@@ -333,12 +334,16 @@ class CORE_EXPORT HTMLSelectElement final
mutable bool should_recalc_list_items_; mutable bool should_recalc_list_items_;
bool is_autofilled_by_preview_; bool is_autofilled_by_preview_;
Member<SelectType> select_type_;
class PopupUpdater; class PopupUpdater;
Member<PopupUpdater> popup_updater_; Member<PopupUpdater> popup_updater_;
Member<PopupMenu> popup_; Member<PopupMenu> popup_;
int index_to_select_on_cancel_; int index_to_select_on_cancel_;
bool popup_is_visible_; bool popup_is_visible_;
friend class ListBoxSelectType;
friend class MenuListSelectType;
friend class SelectType;
FRIEND_TEST_ALL_PREFIXES(HTMLSelectElementTest, FirstSelectableOption); FRIEND_TEST_ALL_PREFIXES(HTMLSelectElementTest, FirstSelectableOption);
FRIEND_TEST_ALL_PREFIXES(HTMLSelectElementTest, LastSelectableOption); FRIEND_TEST_ALL_PREFIXES(HTMLSelectElementTest, LastSelectableOption);
FRIEND_TEST_ALL_PREFIXES(HTMLSelectElementTest, NextSelectableOption); FRIEND_TEST_ALL_PREFIXES(HTMLSelectElementTest, NextSelectableOption);
......
/*
* 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) 2001 Dirk Mueller (mueller@kde.org)
* Copyright (C) 2004, 2005, 2006, 2007, 2009, 2010, 2011 Apple Inc. All rights
* reserved.
* (C) 2006 Alexey Proskuryakov (ap@nypop.com)
* Copyright (C) 2010 Google Inc. All rights reserved.
* Copyright (C) 2009 Torch Mobile Inc. All rights reserved.
* (http://www.torchmobile.com/)
*
* 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.
*
*/
#include "third_party/blink/renderer/core/html/forms/select_type.h"
#include "third_party/blink/renderer/core/html/forms/html_select_element.h"
#include "third_party/blink/renderer/core/html/forms/popup_menu.h"
namespace blink {
class MenuListSelectType : public SelectType {
public:
explicit MenuListSelectType(HTMLSelectElement& select) : SelectType(select) {}
void DidSelectOption(HTMLOptionElement* element,
HTMLSelectElement::SelectOptionFlags flags,
bool should_update_popup) override;
};
void MenuListSelectType::DidSelectOption(
HTMLOptionElement* element,
HTMLSelectElement::SelectOptionFlags flags,
bool should_update_popup) {
// Need to update last_on_change_option_ before UpdateFromElement().
const bool should_dispatch_events =
(flags & HTMLSelectElement::kDispatchInputAndChangeEventFlag) &&
select_->last_on_change_option_ != element;
select_->last_on_change_option_ = element;
select_->UpdateMenuListLabel(select_->UpdateFromElement());
// PopupMenu::UpdateFromElement() posts an O(N) task.
if (select_->PopupIsVisible() && should_update_popup)
select_->popup_->UpdateFromElement(PopupMenu::kBySelectionChange);
SelectType::DidSelectOption(element, flags, should_update_popup);
if (should_dispatch_events) {
select_->DispatchInputEvent();
select_->DispatchChangeEvent();
}
if (select_->GetLayoutObject()) {
// Need to check UsesMenuList() again because event handlers might
// change the status.
if (select_->UsesMenuList()) {
// DidUpdateMenuListActiveOption() is O(N) because of
// HTMLOptionElement::index().
select_->DidUpdateMenuListActiveOption(element);
}
}
}
// ============================================================================
class ListBoxSelectType : public SelectType {
public:
explicit ListBoxSelectType(HTMLSelectElement& select) : SelectType(select) {}
};
// ============================================================================
SelectType::SelectType(HTMLSelectElement& select) : select_(select) {}
SelectType* SelectType::Create(HTMLSelectElement& select) {
if (select.UsesMenuList())
return MakeGarbageCollected<MenuListSelectType>(select);
else
return MakeGarbageCollected<ListBoxSelectType>(select);
}
void SelectType::Trace(Visitor* visitor) {
visitor->Trace(select_);
}
void SelectType::DidSelectOption(HTMLOptionElement*,
HTMLSelectElement::SelectOptionFlags,
bool) {
select_->ScrollToSelection();
select_->SetNeedsValidityCheck();
}
} // namespace blink
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HTML_FORMS_SELECT_TYPE_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_FORMS_SELECT_TYPE_H_
#include "third_party/blink/renderer/core/html/forms/html_select_element.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
namespace blink {
// SelectType class is an abstraction of the MenuList behavior and the ListBox
// behavior of HTMLSelectElement.
class SelectType : public GarbageCollected<SelectType> {
public:
// Creates an instance of a SelectType subclass depending on the current mode
// of |select|.
static SelectType* Create(HTMLSelectElement& select);
virtual void Trace(Visitor* visitor);
virtual void DidSelectOption(HTMLOptionElement* element,
HTMLSelectElement::SelectOptionFlags flags,
bool should_update_popup);
// TODO(crbug.com/1052232): Add more virtual functions.
protected:
explicit SelectType(HTMLSelectElement& select);
Member<HTMLSelectElement> select_;
private:
SelectType(const SelectType&) = delete;
SelectType& operator=(const SelectType&) = delete;
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_HTML_FORMS_SELECT_TYPE_H_
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment