Unreviewed, rolling out r241620.
[WebKit-https.git] / Source / WebCore / platform / gtk / RenderThemeWidget.cpp
1 /*
2  * Copyright (C) 2017 Igalia S.L.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "RenderThemeWidget.h"
28
29 #if GTK_CHECK_VERSION(3, 20, 0)
30
31 #include <wtf/HashMap.h>
32 #include <wtf/NeverDestroyed.h>
33
34 namespace WebCore {
35
36 static HashMap<unsigned, std::unique_ptr<RenderThemeWidget>>& widgetMap()
37 {
38     static NeverDestroyed<HashMap<unsigned, std::unique_ptr<RenderThemeWidget>>> map;
39     return map;
40 }
41
42 RenderThemeWidget& RenderThemeWidget::getOrCreate(Type widgetType)
43 {
44     auto addResult = widgetMap().ensure(static_cast<unsigned>(widgetType), [widgetType]() -> std::unique_ptr<RenderThemeWidget> {
45         switch (widgetType) {
46         case RenderThemeWidget::Type::VerticalScrollbarRight:
47             return std::make_unique<RenderThemeScrollbar>(GTK_ORIENTATION_VERTICAL, RenderThemeScrollbar::Mode::Full);
48         case RenderThemeWidget::Type::VerticalScrollbarLeft:
49             return std::make_unique<RenderThemeScrollbar>(GTK_ORIENTATION_VERTICAL, RenderThemeScrollbar::Mode::Full, RenderThemeScrollbar::VerticalPosition::Left);
50         case RenderThemeWidget::Type::HorizontalScrollbar:
51             return std::make_unique<RenderThemeScrollbar>(GTK_ORIENTATION_HORIZONTAL, RenderThemeScrollbar::Mode::Full);
52         case RenderThemeWidget::Type::VerticalScrollIndicatorRight:
53             return std::make_unique<RenderThemeScrollbar>(GTK_ORIENTATION_VERTICAL, RenderThemeScrollbar::Mode::Indicator);
54         case RenderThemeWidget::Type::VerticalScrollIndicatorLeft:
55             return std::make_unique<RenderThemeScrollbar>(GTK_ORIENTATION_VERTICAL, RenderThemeScrollbar::Mode::Indicator, RenderThemeScrollbar::VerticalPosition::Left);
56         case RenderThemeWidget::Type::HorizontalScrollIndicator:
57             return std::make_unique<RenderThemeScrollbar>(GTK_ORIENTATION_HORIZONTAL, RenderThemeScrollbar::Mode::Indicator);
58         case RenderThemeWidget::Type::CheckButton:
59             return std::make_unique<RenderThemeToggleButton>(RenderThemeToggleButton::Type::Check);
60         case RenderThemeWidget::Type::RadioButton:
61             return std::make_unique<RenderThemeToggleButton>(RenderThemeToggleButton::Type::Radio);
62         case RenderThemeWidget::Type::Button:
63             return std::make_unique<RenderThemeButton>(RenderThemeButton::Default::No);
64         case RenderThemeWidget::Type::ButtonDefault:
65             return std::make_unique<RenderThemeButton>(RenderThemeButton::Default::Yes);
66         case RenderThemeWidget::Type::ComboBox:
67             return std::make_unique<RenderThemeComboBox>();
68         case RenderThemeWidget::Type::Entry:
69             return std::make_unique<RenderThemeEntry>();
70         case RenderThemeWidget::Type::SelectedEntry:
71             return std::make_unique<RenderThemeEntry>(RenderThemeEntry::Selected::Yes);
72         case RenderThemeWidget::Type::SearchEntry:
73             return std::make_unique<RenderThemeSearchEntry>();
74         case RenderThemeWidget::Type::SpinButton:
75             return std::make_unique<RenderThemeSpinButton>();
76         case RenderThemeWidget::Type::VerticalSlider:
77             return std::make_unique<RenderThemeSlider>(GTK_ORIENTATION_VERTICAL);
78         case RenderThemeWidget::Type::HorizontalSlider:
79             return std::make_unique<RenderThemeSlider>(GTK_ORIENTATION_HORIZONTAL);
80         case RenderThemeWidget::Type::ProgressBar:
81             return std::make_unique<RenderThemeProgressBar>(RenderThemeProgressBar::Mode::Determinate);
82         case RenderThemeWidget::Type::IndeterminateProgressBar:
83             return std::make_unique<RenderThemeProgressBar>(RenderThemeProgressBar::Mode::Indeterminate);
84         case RenderThemeWidget::Type::ListView:
85             return std::make_unique<RenderThemeListView>();
86         case RenderThemeWidget::Type::Icon:
87             return std::make_unique<RenderThemeIcon>();
88         }
89         ASSERT_NOT_REACHED();
90         return nullptr;
91     });
92     return *addResult.iterator->value;
93 }
94
95 void RenderThemeWidget::clearCache()
96 {
97     widgetMap().clear();
98 }
99
100 RenderThemeWidget::~RenderThemeWidget() = default;
101
102 RenderThemeScrollbar::RenderThemeScrollbar(GtkOrientation orientation, Mode mode, VerticalPosition verticalPosition)
103 {
104     RenderThemeGadget::Info info = { RenderThemeGadget::Type::Scrollbar, "scrollbar", { } };
105     if (orientation == GTK_ORIENTATION_VERTICAL) {
106         info.classList.append("vertical");
107         info.classList.append(verticalPosition == VerticalPosition::Right ? "right" : "left");
108     } else {
109         info.classList.append("horizontal");
110         info.classList.append("bottom");
111     }
112     static bool usesOverlayScrollbars = g_strcmp0(g_getenv("GTK_OVERLAY_SCROLLING"), "0");
113     if (usesOverlayScrollbars)
114         info.classList.append("overlay-indicator");
115     if (mode == Mode::Full)
116         info.classList.append("hovering");
117     m_scrollbar = RenderThemeGadget::create(info);
118
119     Vector<RenderThemeGadget::Info> children;
120     auto steppers = static_cast<RenderThemeScrollbarGadget*>(m_scrollbar.get())->steppers();
121     if (steppers.contains(RenderThemeScrollbarGadget::Steppers::Backward)) {
122         m_steppersPosition[0] = children.size();
123         children.append({ RenderThemeGadget::Type::Generic, "button", { "up" } });
124     }
125     if (steppers.contains(RenderThemeScrollbarGadget::Steppers::SecondaryForward)) {
126         m_steppersPosition[1] = children.size();
127         children.append({ RenderThemeGadget::Type::Generic, "button", { "down" } });
128     }
129     m_troughPosition = children.size();
130     children.append({ RenderThemeGadget::Type::Generic, "trough", { } });
131     if (steppers.contains(RenderThemeScrollbarGadget::Steppers::SecondaryBackward)) {
132         m_steppersPosition[2] = children.size();
133         children.append({ RenderThemeGadget::Type::Generic, "button", { "up" } });
134     }
135     if (steppers.contains(RenderThemeScrollbarGadget::Steppers::Forward)) {
136         m_steppersPosition[3] = children.size();
137         children.append({ RenderThemeGadget::Type::Generic, "button", { "down" } });
138     }
139     info.type = RenderThemeGadget::Type::Generic;
140     info.name = "contents";
141     info.classList.clear();
142     m_contents = std::make_unique<RenderThemeBoxGadget>(info, GTK_ORIENTATION_VERTICAL, children, m_scrollbar.get());
143     info.name = "slider";
144     m_slider = RenderThemeGadget::create(info, m_contents->child(m_troughPosition));
145 }
146
147 RenderThemeGadget* RenderThemeScrollbar::stepper(RenderThemeScrollbarGadget::Steppers scrollbarStepper)
148 {
149     if (!static_cast<RenderThemeScrollbarGadget*>(m_scrollbar.get())->steppers().contains(scrollbarStepper))
150         return nullptr;
151
152     switch (scrollbarStepper) {
153     case RenderThemeScrollbarGadget::Steppers::Backward:
154         return m_contents->child(m_steppersPosition[0]);
155     case RenderThemeScrollbarGadget::Steppers::SecondaryForward:
156         return m_contents->child(m_steppersPosition[1]);
157     case RenderThemeScrollbarGadget::Steppers::SecondaryBackward:
158         return m_contents->child(m_steppersPosition[2]);
159     case RenderThemeScrollbarGadget::Steppers::Forward:
160         return m_contents->child(m_steppersPosition[3]);
161     default:
162         break;
163     }
164
165     return nullptr;
166 }
167
168 RenderThemeToggleButton::RenderThemeToggleButton(Type toggleType)
169 {
170     RenderThemeGadget::Info info = { RenderThemeGadget::Type::Generic, toggleType == Type::Check ? "checkbutton" : "radiobutton", { "text-button" } };
171     m_button = RenderThemeGadget::create(info);
172     if (toggleType == Type::Check) {
173         info.type = RenderThemeGadget::Type::Check;
174         info.name = "check";
175     } else {
176         info.type = RenderThemeGadget::Type::Radio;
177         info.name = "radio";
178     }
179     info.classList.clear();
180     m_toggle = RenderThemeGadget::create(info, m_button.get());
181 }
182
183 RenderThemeButton::RenderThemeButton(Default isDefault)
184 {
185     RenderThemeGadget::Info info = { RenderThemeGadget::Type::Button, "button", { "text-button" } };
186     if (isDefault == Default::Yes)
187         info.classList.append("default");
188     m_button = RenderThemeGadget::create(info);
189 }
190
191 RenderThemeComboBox::RenderThemeComboBox()
192 {
193     RenderThemeGadget::Info info = { RenderThemeGadget::Type::Generic, "combobox", { } };
194     m_comboBox = RenderThemeGadget::create(info);
195     Vector<RenderThemeGadget::Info> children = {
196         { RenderThemeGadget::Type::Generic, "button", { "combo" } }
197     };
198     info.name = "box";
199     info.classList = { "horizontal", "linked" };
200     m_box = std::make_unique<RenderThemeBoxGadget>(info, GTK_ORIENTATION_HORIZONTAL, children, m_comboBox.get());
201     RenderThemeGadget* button = m_box->child(0);
202     info.classList.removeLast();
203     m_buttonBox = RenderThemeGadget::create(info, button);
204     info.type = RenderThemeGadget::Type::Arrow;
205     info.name = "arrow";
206     info.classList = { };
207     m_arrow = RenderThemeGadget::create(info, m_buttonBox.get());
208 }
209
210 RenderThemeEntry::RenderThemeEntry(Selected isSelected)
211 {
212     RenderThemeGadget::Info info = { RenderThemeGadget::Type::TextField, "entry", { } };
213     m_entry = RenderThemeGadget::create(info);
214     if (isSelected == Selected::Yes) {
215         info.type = RenderThemeGadget::Type::Generic;
216         info.name = "selection";
217         m_selection = RenderThemeGadget::create(info, m_entry.get());
218     }
219 }
220
221 RenderThemeSearchEntry::RenderThemeSearchEntry()
222 {
223     RenderThemeGadget::Info info = { RenderThemeGadget::Type::Icon, "image", { "left" } };
224     m_leftIcon = RenderThemeGadget::create(info, m_entry.get());
225     static_cast<RenderThemeIconGadget*>(m_leftIcon.get())->setIconName("edit-find-symbolic");
226     info.classList.clear();
227     info.classList.append("right");
228     m_rightIcon = RenderThemeGadget::create(info, m_entry.get());
229     static_cast<RenderThemeIconGadget*>(m_rightIcon.get())->setIconName("edit-clear-symbolic");
230 }
231
232 RenderThemeSpinButton::RenderThemeSpinButton()
233 {
234     RenderThemeGadget::Info info = { RenderThemeGadget::Type::Generic, "spinbutton", { "horizontal" } };
235     m_spinButton = RenderThemeGadget::create(info);
236     info.type = RenderThemeGadget::Type::TextField;
237     info.name = "entry";
238     info.classList.clear();
239     m_entry = RenderThemeGadget::create(info, m_spinButton.get());
240     info.type = RenderThemeGadget::Type::Icon;
241     info.name = "button";
242     info.classList.append("up");
243     m_up = RenderThemeGadget::create(info, m_spinButton.get());
244     auto* upIcon = static_cast<RenderThemeIconGadget*>(m_up.get());
245     upIcon->setIconSize(RenderThemeIconGadget::IconSizeGtk::Menu);
246     upIcon->setIconName("list-add-symbolic");
247     info.classList[0] = "down";
248     m_down = RenderThemeGadget::create(info, m_spinButton.get());
249     auto* downIcon = static_cast<RenderThemeIconGadget*>(m_down.get());
250     downIcon->setIconSize(RenderThemeIconGadget::IconSizeGtk::Menu);
251     downIcon->setIconName("list-remove-symbolic");
252 }
253
254 RenderThemeSlider::RenderThemeSlider(GtkOrientation orientation)
255 {
256     RenderThemeGadget::Info info = { RenderThemeGadget::Type::Generic, "scale", { } };
257     if (orientation == GTK_ORIENTATION_VERTICAL)
258         info.classList.append("vertical");
259     else
260         info.classList.append("horizontal");
261     m_scale = RenderThemeGadget::create(info);
262     info.name = "contents";
263     info.classList.clear();
264     m_contents = RenderThemeGadget::create(info, m_scale.get());
265     info.name = "trough";
266     m_trough = RenderThemeGadget::create(info, m_contents.get());
267     info.name = "slider";
268     m_slider = RenderThemeGadget::create(info, m_trough.get());
269     info.name = "highlight";
270     m_highlight = RenderThemeGadget::create(info, m_trough.get());
271 }
272
273 RenderThemeProgressBar::RenderThemeProgressBar(Mode mode)
274 {
275     RenderThemeGadget::Info info = { RenderThemeGadget::Type::Generic, "progressbar", { "horizontal" } };
276     m_progressBar = RenderThemeGadget::create(info);
277     info.name = "trough";
278     info.classList.clear();
279     m_trough = RenderThemeGadget::create(info, m_progressBar.get());
280     info.name = "progress";
281     if (mode == Mode::Determinate)
282         info.classList.append("pulse");
283     m_progress = RenderThemeGadget::create(info, m_trough.get());
284 }
285
286 RenderThemeListView::RenderThemeListView()
287     : m_treeview(RenderThemeGadget::create({ RenderThemeGadget::Type::Generic, "treeview", { "view" } }))
288 {
289 }
290
291 RenderThemeIcon::RenderThemeIcon()
292     : m_icon(RenderThemeGadget::create({ RenderThemeGadget::Type::Icon, "image", { } }))
293 {
294 }
295
296 } // namepsace WebCore
297
298 #endif // GTK_CHECK_VERSION(3, 20, 0)