1/*
2 * This file is part of the select element renderer in WebCore.
3 *
4 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
5 * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2015 Apple Inc. All rights reserved.
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
16 *
17 * You should have received a copy of the GNU Library General Public License
18 * along with this library; see the file COPYING.LIB. If not, write to
19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
21 *
22 */
23
24#pragma once
25
26#include "LayoutRect.h"
27#include "PopupMenu.h"
28#include "PopupMenuClient.h"
29#include "RenderFlexibleBox.h"
30
31#if PLATFORM(COCOA)
32#define POPUP_MENU_PULLS_DOWN 0
33#else
34#define POPUP_MENU_PULLS_DOWN 1
35#endif
36
37namespace WebCore {
38
39class HTMLSelectElement;
40class RenderText;
41
42class RenderMenuList final : public RenderFlexibleBox, private PopupMenuClient {
43 WTF_MAKE_ISO_ALLOCATED(RenderMenuList);
44public:
45 RenderMenuList(HTMLSelectElement&, RenderStyle&&);
46 virtual ~RenderMenuList();
47
48 HTMLSelectElement& selectElement() const;
49
50#if !PLATFORM(IOS_FAMILY)
51 bool popupIsVisible() const { return m_popupIsVisible; }
52#endif
53 void showPopup();
54 void hidePopup();
55
56 void setOptionsChanged(bool changed) { m_needsOptionsWidthUpdate = changed; }
57
58 void didSetSelectedIndex(int listIndex);
59
60 String text() const;
61
62 RenderBlock* innerRenderer() const { return m_innerBlock.get(); }
63 void setInnerRenderer(RenderBlock&);
64
65 void didAttachChild(RenderObject& child, RenderObject* beforeChild);
66
67private:
68 void willBeDestroyed() override;
69
70 void element() const = delete;
71
72 bool isMenuList() const override { return true; }
73
74 bool createsAnonymousWrapper() const override { return true; }
75
76 void updateFromElement() override;
77
78 LayoutRect controlClipRect(const LayoutPoint&) const override;
79 bool hasControlClip() const override { return true; }
80 bool canHaveGeneratedChildren() const override { return false; }
81
82 const char* renderName() const override { return "RenderMenuList"; }
83
84 void computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const override;
85 void computePreferredLogicalWidths() override;
86
87 void styleDidChange(StyleDifference, const RenderStyle* oldStyle) override;
88
89 // PopupMenuClient methods
90 void valueChanged(unsigned listIndex, bool fireOnChange = true) override;
91 void selectionChanged(unsigned, bool) override { }
92 void selectionCleared() override { }
93 String itemText(unsigned listIndex) const override;
94 String itemLabel(unsigned listIndex) const override;
95 String itemIcon(unsigned listIndex) const override;
96 String itemToolTip(unsigned listIndex) const override;
97 String itemAccessibilityText(unsigned listIndex) const override;
98 bool itemIsEnabled(unsigned listIndex) const override;
99 PopupMenuStyle itemStyle(unsigned listIndex) const override;
100 PopupMenuStyle menuStyle() const override;
101 int clientInsetLeft() const override;
102 int clientInsetRight() const override;
103 LayoutUnit clientPaddingLeft() const override;
104 LayoutUnit clientPaddingRight() const override;
105 int listSize() const override;
106 int selectedIndex() const override;
107 void popupDidHide() override;
108 bool itemIsSeparator(unsigned listIndex) const override;
109 bool itemIsLabel(unsigned listIndex) const override;
110 bool itemIsSelected(unsigned listIndex) const override;
111 bool shouldPopOver() const override { return !POPUP_MENU_PULLS_DOWN; }
112 bool valueShouldChangeOnHotTrack() const override { return true; }
113 void setTextFromItem(unsigned listIndex) override;
114 void listBoxSelectItem(int listIndex, bool allowMultiplySelections, bool shift, bool fireOnChangeNow = true) override;
115 bool multiple() const override;
116 FontSelector* fontSelector() const override;
117 HostWindow* hostWindow() const override;
118 Ref<Scrollbar> createScrollbar(ScrollableArea&, ScrollbarOrientation, ScrollbarControlSize) override;
119
120 bool hasLineIfEmpty() const override { return true; }
121
122 // Flexbox defines baselines differently than regular blocks.
123 // For backwards compatibility, menulists need to do the regular block behavior.
124 int baselinePosition(FontBaseline baseline, bool firstLine, LineDirectionMode direction, LinePositionMode position) const override
125 {
126 return RenderBlock::baselinePosition(baseline, firstLine, direction, position);
127 }
128 Optional<int> firstLineBaseline() const override { return RenderBlock::firstLineBaseline(); }
129 Optional<int> inlineBlockBaseline(LineDirectionMode direction) const override { return RenderBlock::inlineBlockBaseline(direction); }
130
131 void getItemBackgroundColor(unsigned listIndex, Color&, bool& itemHasCustomBackgroundColor) const;
132
133 void adjustInnerStyle();
134 void setText(const String&);
135 void setTextFromOption(int optionIndex);
136 void updateOptionsWidth();
137
138 void didUpdateActiveOption(int optionIndex);
139
140 bool isFlexibleBoxImpl() const override { return true; }
141
142 WeakPtr<RenderText> m_buttonText;
143 WeakPtr<RenderBlock> m_innerBlock;
144
145 bool m_needsOptionsWidthUpdate;
146 int m_optionsWidth;
147
148 Optional<int> m_lastActiveIndex;
149
150 std::unique_ptr<RenderStyle> m_optionStyle;
151
152#if !PLATFORM(IOS_FAMILY)
153 RefPtr<PopupMenu> m_popup;
154 bool m_popupIsVisible;
155#endif
156};
157
158} // namespace WebCore
159
160SPECIALIZE_TYPE_TRAITS_RENDER_OBJECT(RenderMenuList, isMenuList())
161