OpenTTD Source 20260331-master-g915bc00ea0
dropdown.cpp
Go to the documentation of this file.
1/*
2 * This file is part of OpenTTD.
3 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4 * OpenTTD 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.
5 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <https://www.gnu.org/licenses/old-licenses/gpl-2.0>.
6 */
7
9
10#include "stdafx.h"
11#include "core/backup_type.hpp"
12#include "dropdown_type.h"
13#include "dropdown_func.h"
14#include "stringfilter_type.h"
15#include "querystring_gui.h"
16#include "strings_func.h"
17#include "sound_func.h"
18#include "timer/timer.h"
19#include "timer/timer_window.h"
20#include "window_gui.h"
21#include "window_func.h"
22#include "zoom_func.h"
23
25
26#include "table/strings.h"
27
29
30#include "safeguards.h"
31
36std::unique_ptr<DropDownListItem> MakeDropDownListDividerItem()
37{
38 return std::make_unique<DropDownListDividerItem>(-1);
39}
40
49std::unique_ptr<DropDownListItem> MakeDropDownListStringItem(StringID str, int value, bool masked, bool shaded)
50{
51 return MakeDropDownListStringItem(GetString(str), value, masked, shaded);
52}
53
55std::unique_ptr<DropDownListItem> MakeDropDownListStringItem(std::string &&str, int value, bool masked, bool shaded)
56{
57 return std::make_unique<DropDownListStringItem>(std::move(str), value, masked, shaded);
58}
59
70std::unique_ptr<DropDownListItem> MakeDropDownListIconItem(SpriteID sprite, PaletteID palette, StringID str, int value, bool masked, bool shaded)
71{
72 return std::make_unique<DropDownListIconItem>(sprite, palette, GetString(str), value, masked, shaded);
73}
74
79std::unique_ptr<DropDownListItem> MakeDropDownListIconItem(const Dimension &dim, SpriteID sprite, PaletteID palette, StringID str, int value, bool masked, bool shaded)
80{
81 return std::make_unique<DropDownListIconItem>(dim, sprite, palette, GetString(str), value, masked, shaded);
82}
83
94std::unique_ptr<DropDownListItem> MakeDropDownListCheckedItem(bool checked, StringID str, int value, bool masked, bool shaded, uint indent)
95{
96 return std::make_unique<DropDownListCheckedItem>(indent, checked, GetString(str), value, masked, shaded);
97}
98
99static constexpr std::initializer_list<NWidgetPart> _nested_dropdown_menu_widgets = {
101 NWidget(NWID_SELECTION, INVALID_COLOUR, WID_DM_FILTER_SEL),
103 NWidget(WWT_EDITBOX, COLOUR_END, WID_DM_FILTER), SetResize(1, 0), SetFill(1, 0), SetPadding(2), SetStringTip(STR_LIST_FILTER_OSKTITLE, STR_LIST_FILTER_TOOLTIP),
104 EndContainer(),
105 EndContainer(),
108 EndContainer(),
109 NWidget(NWID_SELECTION, INVALID_COLOUR, WID_DM_SHOW_SCROLL),
111 EndContainer(),
112 EndContainer(),
113 EndContainer(),
114};
115
118 WDP_MANUAL, {}, 0, 0,
120 {},
121 _nested_dropdown_menu_widgets
122);
123
131 uint8_t click_delay = 0;
132 bool drag_mode = true;
133 bool above = false;
134 DropDownOptions options;
135 int scrolling = 0;
137 Scrollbar *vscroll = nullptr;
138 std::string * const persistent_filter_text = nullptr;
139
142
145
157 DropdownWindow(Window *parent, DropDownList &&list, int selected, WidgetID button, const Rect wi_rect, Colours wi_colour, DropDownOptions options, std::string * const persistent_filter_text)
159 , parent_button(button)
161 , list(std::move(list))
162 , selected_result(selected)
165 , editbox(60 * MAX_CHAR_LENGTH, 60)
166 {
167 assert(!this->list.empty());
168
169 this->parent = parent;
170
171 this->CreateNestedTree();
172
173 this->GetWidget<NWidgetStacked>(WID_DM_FILTER_SEL)->SetDisplayedPlane(this->options.Test(DropDownOption::Filterable) ? 0 : SZSP_HORIZONTAL);
174 this->GetWidget<NWidgetCore>(WID_DM_FILTER_PANEL)->colour = wi_colour;
175 this->GetWidget<NWidgetCore>(WID_DM_FILTER)->colour = wi_colour;
176 this->GetWidget<NWidgetCore>(WID_DM_ITEMS)->colour = wi_colour;
177 this->GetWidget<NWidgetCore>(WID_DM_SCROLL)->colour = wi_colour;
178 this->vscroll = this->GetScrollbar(WID_DM_SCROLL);
179 this->UpdateSizeAndPosition();
180
181 this->querystrings[WID_DM_FILTER] = &this->editbox;
182
183 this->FinishInitNested(0);
184
185 if (this->options.Test(DropDownOption::Filterable)) {
187 if (this->persistent_filter_text != nullptr && !this->persistent_filter_text->empty()) {
188 this->editbox.text.Assign(*this->persistent_filter_text);
189 this->UpdateFilter();
190 }
191 }
192
193 this->flags.Reset(WindowFlag::WhiteBorder);
194 }
195
196 void Close([[maybe_unused]] int data = 0) override
197 {
198 this->UnfocusFocusedWidget();
199
200 /* Finish closing the dropdown, so it doesn't affect new window placement.
201 * Also mark it dirty in case the callback deals with the screen. (e.g. screenshots). */
202 this->Window::Close();
203
204 if (this->persistent_filter_text != nullptr) {
205 *this->persistent_filter_text = this->editbox.text.GetText();
206 }
207
208 Point pt = _cursor.pos;
209 pt.x -= this->parent->left;
210 pt.y -= this->parent->top;
211 this->parent->OnDropdownClose(pt, this->parent_button, this->selected_result, this->selected_click_result, this->options.Test(DropDownOption::InstantClose));
212
213 /* Set flag on parent widget to indicate that we have just closed. */
214 NWidgetCore *nwc = this->parent->GetWidget<NWidgetCore>(this->parent_button);
215 if (nwc != nullptr) nwc->disp_flags.Set(NWidgetDisplayFlag::DropdownClosed);
216 }
217
218 void OnFocusLost(bool closing) override
219 {
220 if (!closing) {
221 this->options.Reset(DropDownOption::InstantClose);
222 this->Close();
223 }
224 }
225
231 {
232 if (!this->options.Test(DropDownOption::Filterable)) return 0;
233
234 /* The edit panel widget does not exist yet so we don't know its real size. Calculate it instead. */
235 return GetCharacterHeight(FS_NORMAL) + WidgetDimensions::scaled.fullbevel.Vertical() * 3;
236 }
237
244 void FitAvailableHeight(Dimension &desired, const Dimension &list, uint available_height)
245 {
246 available_height -= this->GetFilterBoxHeight();
247
248 if (desired.height < available_height) return;
249
250 /* If the dropdown doesn't fully fit, we a need a dropdown. */
251 uint avg_height = list.height / (uint)this->list.size();
252 uint rows = std::max((available_height - WidgetDimensions::scaled.dropdownlist.Vertical()) / avg_height, 1U);
253
254 desired.width = std::max(list.width, desired.width - NWidgetScrollbar::GetVerticalDimension().width);
255 desired.height = rows * avg_height + WidgetDimensions::scaled.dropdownlist.Vertical();
256 }
257
262 uint GetVisibleHeight() const
263 {
264 uint height = 0;
265 for (const auto &item : this->list) {
266 if (!this->FilterByText(*item)) continue;
267 height += item->Height();
268 }
269 return height;
270 }
271
276 {
277 Rect button_rect = this->wi_rect.Translate(this->parent->left, this->parent->top);
278
279 /* Get the dimensions required for the list. */
280 Dimension list_dim = GetDropDownListDimension(this->list);
281
282 /* Set up dimensions for the items widget. */
283 Dimension widget_dim = list_dim;
284 widget_dim.width += WidgetDimensions::scaled.dropdownlist.Horizontal();
285 widget_dim.height += WidgetDimensions::scaled.dropdownlist.Vertical();
286
287 /* Width should match at least the width of the parent widget. */
288 widget_dim.width = std::max<uint>(widget_dim.width, button_rect.Width());
289
290 /* Available height below (or above, if the dropdown is placed above the widget). */
291 uint available_height_below = std::max(GetMainViewBottom() - button_rect.bottom - 1, 0);
292 uint available_height_above = std::max(button_rect.top - 1 - GetMainViewTop(), 0);
293
294 /* Is it better to place the dropdown above the widget? */
295 if (widget_dim.height > available_height_below && available_height_above > available_height_below) {
296 FitAvailableHeight(widget_dim, list_dim, available_height_above);
297 this->above = true;
298 this->position.y = button_rect.top - widget_dim.height - this->GetFilterBoxHeight();
299 this->GetWidget<NWidgetCore>(WID_DM_FILTER_PANEL)->GetParentWidget<NWidgetVertical>()->bottom_up = true;
300 } else {
301 FitAvailableHeight(widget_dim, list_dim, available_height_below);
302 this->above = false;
303 this->position.y = button_rect.bottom + 1;
304 this->GetWidget<NWidgetCore>(WID_DM_FILTER_PANEL)->GetParentWidget<NWidgetVertical>()->bottom_up = false;
305 }
306
307 if (_current_text_dir == TD_RTL) {
308 /* In case the list is wider than the parent button, the list should be right aligned to the button and overflow to the left. */
309 this->position.x = button_rect.right + 1 - (int)(widget_dim.width + (list_dim.height > widget_dim.height ? NWidgetScrollbar::GetVerticalDimension().width : 0));
310 } else {
311 this->position.x = button_rect.left;
312 }
313
314 this->initial_dim = widget_dim;
315 this->items_dim = widget_dim;
316 this->GetWidget<NWidgetStacked>(WID_DM_SHOW_SCROLL)->SetDisplayedPlane(list_dim.height > widget_dim.height ? 0 : SZSP_NONE);
317
318 /* Capacity is the average number of items visible */
319 this->vscroll->SetCapacity(widget_dim.height - WidgetDimensions::scaled.dropdownlist.Vertical());
320 this->vscroll->SetStepSize(list_dim.height / this->list.size());
321 this->vscroll->SetCount(this->GetVisibleHeight());
322
323 /* If the dropdown is positioned above the parent widget, start selection at the bottom. */
324 if (this->above) this->vscroll->SetPosition(INT_MAX);
325 }
326
327 void UpdateWidgetSize(WidgetID widget, Dimension &size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension &fill, [[maybe_unused]] Dimension &resize) override
328 {
329 if (widget == WID_DM_ITEMS) size = this->items_dim;
330 }
331
332 Point OnInitialPosition([[maybe_unused]] int16_t sm_width, [[maybe_unused]] int16_t sm_height, [[maybe_unused]] int window_number) override
333 {
334 return this->position;
335 }
336
343 bool GetDropDownItem(int &result, int &click_result)
344 {
345 if (GetWidgetFromPos(this, _cursor.pos.x - this->left, _cursor.pos.y - this->top) < 0) return false;
346
347 const Rect &r = this->GetWidget<NWidgetBase>(WID_DM_ITEMS)->GetCurrentRect().Shrink(WidgetDimensions::scaled.dropdownlist).Shrink(WidgetDimensions::scaled.dropdowntext, RectPadding::zero);
348 int click_y = _cursor.pos.y - this->top - r.top;
349 int y = -this->vscroll->GetPosition();
350 int y_end = r.Height();
351
352 for (const auto &item : this->list) {
353 if (!this->FilterByText(*item)) continue;
354 int item_height = item->Height();
355
356 /* Skip items that are scrolled up */
357 if (y > y_end) break;
358 if (click_y >= y && click_y < y + item_height) {
359 if (item->masked || !item->Selectable()) return false;
360 result = item->result;
361 click_result = item->OnClick(r.WithY(0, item_height - 1), {_cursor.pos.x - this->left, click_y - y});
362 return true;
363 }
364 y += item_height;
365 }
366
367 return false;
368 }
369
375 bool FilterByText(const DropDownListItem &item) const
376 {
377 /* Do not filter if the filter text box is empty */
378 if (this->string_filter.IsEmpty()) return true;
379
380 /* Filter table name */
381 this->string_filter.ResetState();
382 item.FilterText(this->string_filter);
383
384 return this->string_filter.GetState();
385 }
386
387 void DrawWidget(const Rect &r, WidgetID widget) const override
388 {
389 if (widget != WID_DM_ITEMS) return;
390
391 Colours colour = this->GetWidget<NWidgetCore>(widget)->colour;
392
393 Rect ir = r.Shrink(WidgetDimensions::scaled.dropdownlist);
394 if (ir.Height() == 0) return;
395
396 /* Setup a clipping rectangle... */
397 DrawPixelInfo tmp_dpi;
398 if (!FillDrawPixelInfo(&tmp_dpi, ir)) return;
399 /* ...but keep coordinates relative to the window. */
400 tmp_dpi.left += ir.left;
401 tmp_dpi.top += ir.top;
402 AutoRestoreBackup dpi_backup(_cur_dpi, &tmp_dpi);
403
404 int y = -this->vscroll->GetPosition();
405 int y_end = ir.Height();
406
407 for (const auto &item : this->list) {
408 if (!this->FilterByText(*item)) continue;
409 int item_height = item->Height();
410
411 /* Skip items that are scrolled up */
412 if (y > y_end) break;
413 if (y > -item_height) {
414 Rect full = ir.Translate(0, y).WithHeight(item_height);
415
416 bool selected = (this->selected_result == item->result) && item->Selectable() && this->selected_click_result < 0;
417 if (selected) GfxFillRect(full, PC_BLACK);
418
419 item->Draw(full, full.Shrink(WidgetDimensions::scaled.dropdowntext, RectPadding::zero), selected, selected ? this->selected_click_result : -1, colour);
420 }
421 y += item_height;
422 }
423 }
424
425 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
426 {
427 if (widget != WID_DM_ITEMS) return;
428 int result, click_result;
429 if (this->GetDropDownItem(result, click_result)) {
430 this->click_delay = 4;
431 this->selected_result = result;
432 this->selected_click_result = click_result;
433 this->SetDirty();
434 }
435 }
436
438 const IntervalTimer<TimerWindow> scroll_interval = {std::chrono::milliseconds(30), [this](auto) {
439 if (this->scrolling == 0) return;
440
441 if (this->vscroll->UpdatePosition(this->scrolling)) this->SetDirty();
442
443 this->scrolling = 0;
444 }};
445
446 void OnMouseLoop() override
447 {
448 if (this->click_delay != 0 && --this->click_delay == 0) {
449 /* Close the dropdown, so it doesn't affect new window placement.
450 * Also mark it dirty in case the callback deals with the screen. (e.g. screenshots). */
451 if (!this->options.Test(DropDownOption::Persist)) this->Close();
452 this->parent->OnDropdownSelect(this->parent_button, this->selected_result, this->selected_click_result);
453 return;
454 }
455
456 if (this->drag_mode) {
457 int result, click_result;
458
460 this->drag_mode = false;
461 if (!this->GetDropDownItem(result, click_result)) {
462 if (this->options.Test(DropDownOption::InstantClose)) this->Close();
463 return;
464 }
465 this->click_delay = 2;
466 } else {
467 if (_cursor.pos.y <= this->top + WidgetDimensions::scaled.dropdownlist.top) {
468 /* Cursor is above the list, set scroll up */
469 this->scrolling = -1;
470 return;
471 } else if (_cursor.pos.y >= this->top + this->height - WidgetDimensions::scaled.dropdownlist.bottom) {
472 /* Cursor is below list, set scroll down */
473 this->scrolling = 1;
474 return;
475 }
476
477 if (!this->GetDropDownItem(result, click_result)) return;
478 }
479
480 if (this->selected_result != result || this->selected_click_result != click_result) {
481 this->selected_result = result;
482 this->selected_click_result = click_result;
483 this->SetDirty();
484 }
485 }
486 }
487
488 void ReplaceList(DropDownList &&list, std::optional<int> selected_result)
489 {
490 this->list = std::move(list);
491 if (selected_result.has_value()) this->selected_result = *selected_result;
492 this->UpdateSizeAndPosition();
493 this->ReInit();
494 this->InitializePositionSize(this->position.x, this->position.y, this->nested_root->smallest_x, this->nested_root->smallest_y);
495 this->FindWindowPlacementAndResize(this->window_desc.GetDefaultWidth(), this->window_desc.GetDefaultHeight(), true);
496 this->SetDirty();
497 }
498
499 void OnResize() override
500 {
501 this->vscroll->SetCapacity(this->items_dim.height - WidgetDimensions::scaled.dropdownlist.Vertical());
502 }
503
508 {
509 this->string_filter.SetFilterTerm(this->editbox.text.GetText());
510
511 uint height = this->GetVisibleHeight();
512 uint old_height = this->items_dim.height;
513 this->items_dim.height = std::min(this->initial_dim.height, height + WidgetDimensions::scaled.dropdownlist.Vertical());
514 this->vscroll->SetCount(height);
515
516 if (old_height != this->items_dim.height) {
517 this->ReInit();
518 if (this->above) {
519 /* Drop down list needs to be moved to near the parent drop down button. */
520 Rect button_rect = this->wi_rect.Translate(this->parent->left, this->parent->top);
521 this->top = button_rect.top - this->items_dim.height - this->GetFilterBoxHeight();
522 this->SetDirty();
523 }
524 } else {
525 this->SetDirty();
526 }
527 }
528
529 void OnEditboxChanged(WidgetID wid) override
530 {
531 if (wid != WID_DM_FILTER) return;
532 this->UpdateFilter();
533 }
534};
535
536void ReplaceDropDownList(Window *parent, DropDownList &&list, std::optional<int> selected_result)
537{
538 DropdownWindow *ddw = dynamic_cast<DropdownWindow *>(parent->FindChildWindow(WC_DROPDOWN_MENU));
539 if (ddw != nullptr) ddw->ReplaceList(std::move(list), selected_result);
540}
541
548{
549 Dimension dim{};
550 for (const auto &item : list) {
551 dim.height += item->Height();
552 dim.width = std::max(dim.width, item->Width());
553 }
554 dim.width += WidgetDimensions::scaled.dropdowntext.Horizontal();
555 return dim;
556}
557
570void ShowDropDownListAt(Window *w, DropDownList &&list, int selected, WidgetID button, Rect wi_rect, Colours wi_colour, DropDownOptions options, std::string * const persistent_filter_text)
571{
573 new DropdownWindow(w, std::move(list), selected, button, wi_rect, wi_colour, options, persistent_filter_text);
574}
575
587void ShowDropDownList(Window *w, DropDownList &&list, int selected, WidgetID button, uint width, DropDownOptions options, std::string * const persistent_filter_text)
588{
589 /* Handle the beep of the player's click. */
590 SndClickBeep();
591
592 /* Our parent's button widget is used to determine where to place the drop
593 * down list window. */
594 NWidgetCore *nwi = w->GetWidget<NWidgetCore>(button);
595 Rect wi_rect = nwi->GetCurrentRect();
596 Colours wi_colour = nwi->colour;
597
598 if ((nwi->type & WWT_MASK) == NWID_BUTTON_DROPDOWN) {
600 } else {
601 nwi->SetLowered(true);
602 }
603 nwi->SetDirty(w);
604
605 if (width != 0) {
606 if (_current_text_dir == TD_RTL) {
607 wi_rect.left = wi_rect.right + 1 - ScaleGUITrad(width);
608 } else {
609 wi_rect.right = wi_rect.left + ScaleGUITrad(width) - 1;
610 }
611 }
612
613 ShowDropDownListAt(w, std::move(list), selected, button, wi_rect, wi_colour, options, persistent_filter_text);
614}
615
629void ShowDropDownMenu(Window *w, std::span<const StringID> strings, int selected, WidgetID button, uint32_t disabled_mask, uint32_t hidden_mask, uint width, DropDownOptions options, std::string * const persistent_filter_text)
630{
631 DropDownList list;
632
633 uint i = 0;
634 for (auto string : strings) {
635 if (!HasBit(hidden_mask, i)) {
636 list.push_back(MakeDropDownListStringItem(string, i, HasBit(disabled_mask, i)));
637 }
638 ++i;
639 }
640
641 if (!list.empty()) ShowDropDownList(w, std::move(list), selected, button, width, options, persistent_filter_text);
642}
Class for backupping variables and making sure they are restored later.
constexpr bool HasBit(const T x, const uint8_t y)
Checks if a bit in a value is set.
constexpr bool Test(Tvalue_type value) const
Test if the value-th bit is set.
constexpr Timpl & Reset()
Reset all bits.
constexpr Timpl & Set()
Set all bits.
Base list item class from which others are derived.
virtual void FilterText(StringFilter &string_filter) const
Add text from this dropdown item to a string filter.
An interval timer will fire every interval, and will continue to fire until it is deleted.
Definition timer.h:76
virtual void SetDirty(const Window *w) const
Mark the widget as 'dirty' (in need of repaint).
Definition widget.cpp:933
WidgetType type
Type of the widget / nested widget.
Base class for a 'real' widget.
NWidgetDisplayFlags disp_flags
Flags that affect display and interaction with the widget.
Colours colour
Colour of this widget.
void SetLowered(bool lowered)
Lower or raise the widget.
Vertical container.
Scrollbar data structure.
void SetCount(size_t num)
Sets the number of elements in the list.
bool UpdatePosition(int difference, ScrollbarStepping unit=SS_SMALL)
Updates the position of the first visible element by the given amount.
void SetCapacity(size_t capacity)
Set the capacity of visible elements.
bool SetPosition(size_type position)
Sets the position of the first visible element.
void SetStepSize(size_t stepsize)
Set the distance to scroll when using the buttons or the wheel.
size_type GetPosition() const
Gets the position of the first visible element in the list.
static WidgetDimensions scaled
Widget dimensions scaled for current zoom level.
Definition window_gui.h:30
void ShowDropDownListAt(Window *w, DropDownList &&list, int selected, WidgetID button, Rect wi_rect, Colours wi_colour, DropDownOptions options, std::string *const persistent_filter_text)
Show a drop down list.
Definition dropdown.cpp:570
void ShowDropDownMenu(Window *w, std::span< const StringID > strings, int selected, WidgetID button, uint32_t disabled_mask, uint32_t hidden_mask, uint width, DropDownOptions options, std::string *const persistent_filter_text)
Show a dropdown menu window near a widget of the parent window.
Definition dropdown.cpp:629
std::unique_ptr< DropDownListItem > MakeDropDownListDividerItem()
Creates new DropDownListDividerItem.
Definition dropdown.cpp:36
static WindowDesc _dropdown_desc(WDP_MANUAL, {}, 0, 0, WC_DROPDOWN_MENU, WC_NONE, {}, _nested_dropdown_menu_widgets)
Window description for dropdown menus.
std::unique_ptr< DropDownListItem > MakeDropDownListIconItem(SpriteID sprite, PaletteID palette, StringID str, int value, bool masked, bool shaded)
Creates new DropDownListIconItem.
Definition dropdown.cpp:70
std::unique_ptr< DropDownListItem > MakeDropDownListStringItem(StringID str, int value, bool masked, bool shaded)
Creates new DropDownListStringItem.
Definition dropdown.cpp:49
std::unique_ptr< DropDownListItem > MakeDropDownListCheckedItem(bool checked, StringID str, int value, bool masked, bool shaded, uint indent)
Creates new DropDownListCheckedItem.
Definition dropdown.cpp:94
Dimension GetDropDownListDimension(const DropDownList &list)
Determine width and height required to fully display a DropDownList.
Definition dropdown.cpp:547
void ShowDropDownList(Window *w, DropDownList &&list, int selected, WidgetID button, uint width, DropDownOptions options, std::string *const persistent_filter_text)
Show a drop down list.
Definition dropdown.cpp:587
Common drop down list components.
Functions related to the drop down widget.
Types related to the drop down widget.
std::vector< std::unique_ptr< const DropDownListItem > > DropDownList
A drop down list is a collection of drop down list items.
@ InstantClose
Set if releasing mouse button should close the list regardless of where the cursor is.
@ Persist
Set if this dropdown should stay open after an option is selected.
@ Filterable
Set if the dropdown is filterable.
Types related to the dropdown widgets.
@ WID_DM_FILTER_SEL
Selection for item filter.
@ WID_DM_FILTER
Item filter.
@ WID_DM_FILTER_PANEL
Panel for item filter.
@ WID_DM_ITEMS
Panel showing the dropdown items.
@ WID_DM_SCROLL
Scrollbar.
@ WID_DM_SHOW_SCROLL
Hide scrollbar if too few items.
int GetCharacterHeight(FontSize size)
Get height of a character for a given font size.
Definition fontcache.cpp:87
bool _left_button_clicked
Is left mouse button clicked?
Definition gfx.cpp:43
void GfxFillRect(int left, int top, int right, int bottom, const std::variant< PixelColour, PaletteID > &colour, FillRectMode mode)
Applies a certain FillRectMode-operation to a rectangle [left, right] x [top, bottom] on the screen.
Definition gfx.cpp:116
bool FillDrawPixelInfo(DrawPixelInfo *n, int left, int top, int width, int height)
Set up a clipping area for only drawing into a certain area.
Definition gfx.cpp:1573
uint32_t SpriteID
The number of a sprite, without mapping bits and colourtables.
Definition gfx_type.h:17
@ FS_NORMAL
Index of the normal font in the font tables.
Definition gfx_type.h:249
uint32_t PaletteID
The number of the palette.
Definition gfx_type.h:18
constexpr NWidgetPart SetFill(uint16_t fill_x, uint16_t fill_y)
Widget part function for setting filling.
constexpr NWidgetPart SetScrollbar(WidgetID index)
Attach a scrollbar to a widget.
constexpr NWidgetPart SetPadding(uint8_t top, uint8_t right, uint8_t bottom, uint8_t left)
Widget part function for setting additional space around a widget.
constexpr NWidgetPart SetStringTip(StringID string, StringID tip={})
Widget part function for setting the string and tooltip.
constexpr NWidgetPart EndContainer()
Widget part function for denoting the end of a container (horizontal, vertical, WWT_FRAME,...
constexpr NWidgetPart NWidget(WidgetType tp, Colours col, WidgetID idx=INVALID_WIDGET)
Widget part function for starting a new 'real' widget.
constexpr NWidgetPart SetResize(int16_t dx, int16_t dy)
Widget part function for setting the resize step.
void SetDirty() const
Mark entire window as dirty (in need of re-paint).
Definition window.cpp:980
#define Rect
Macro that prevents name conflicts between included headers.
#define Point
Macro that prevents name conflicts between included headers.
static constexpr PixelColour PC_BLACK
Black palette colour.
Base for the GUIs that have an edit box in them.
A number of safeguards to prevent using unsafe methods.
void SndClickBeep()
Play a beep sound for a click event if enabled in settings.
Definition sound.cpp:253
Functions related to sound.
Definition of base types and functions in a cross-platform compatible way.
Searching and filtering using a stringterm.
std::string GetString(StringID string)
Resolve the given StringID into a std::string with formatting but no parameters.
Definition strings.cpp:424
TextDirection _current_text_dir
Text direction of the currently selected language.
Definition strings.cpp:56
Functions related to OTTD's strings.
uint32_t StringID
Numeric value that represents a string, independent of the selected language.
@ TD_RTL
Text is written right-to-left by default.
static const int MAX_CHAR_LENGTH
Max. length of UTF-8 encoded unicode character.
Class to backup a specific variable and restore it upon destruction of this object to prevent stack v...
T y
Y coordinate.
T x
X coordinate.
Dimensions (a width and height) of a rectangle in 2D.
Data about how and where to blit pixels.
Definition gfx_type.h:157
Drop-down menu window.
Definition dropdown.cpp:125
Point OnInitialPosition(int16_t sm_width, int16_t sm_height, int window_number) override
Compute the initial position of the window.
Definition dropdown.cpp:332
WidgetID parent_button
Parent widget number where the window is dropped from.
Definition dropdown.cpp:126
DropdownWindow(Window *parent, DropDownList &&list, int selected, WidgetID button, const Rect wi_rect, Colours wi_colour, DropDownOptions options, std::string *const persistent_filter_text)
Create a dropdown menu.
Definition dropdown.cpp:157
void OnMouseLoop() override
Called for every mouse loop run, which is at least once per (game) tick.
Definition dropdown.cpp:446
Dimension initial_dim
Initial dimension of dropdown menu before filtering.
Definition dropdown.cpp:140
StringFilter string_filter
String filter for filter text.
Definition dropdown.cpp:143
uint GetVisibleHeight() const
Get the height of the dropdown list, excluding filtered items.
Definition dropdown.cpp:262
void UpdateSizeAndPosition()
Update size and position of window to fit dropdown list into available space.
Definition dropdown.cpp:275
const IntervalTimer< TimerWindow > scroll_interval
Rate limit how fast scrolling happens.
Definition dropdown.cpp:438
Rect wi_rect
Rect of the button that opened the dropdown.
Definition dropdown.cpp:127
void OnClick(Point pt, WidgetID widget, int click_count) override
A click with the left mouse button has been made on the window.
Definition dropdown.cpp:425
Dimension items_dim
Calculated cropped and padded dimension for the items widget.
Definition dropdown.cpp:141
void UpdateWidgetSize(WidgetID widget, Dimension &size, const Dimension &padding, Dimension &fill, Dimension &resize) override
Update size and resize step of a widget in the window.
Definition dropdown.cpp:327
std::string *const persistent_filter_text
Unmanaged pointer to string for retaining filter text.
Definition dropdown.cpp:138
uint8_t click_delay
Timer to delay selection.
Definition dropdown.cpp:131
int selected_result
Result value of the selected item in the list.
Definition dropdown.cpp:129
QueryString editbox
Editbox for filter text.
Definition dropdown.cpp:144
bool above
Set if the drop down list is above the drop down widget instead of below.
Definition dropdown.cpp:133
void Close(int data=0) override
Hide the window and all its child windows, and mark them for a later deletion.
Definition dropdown.cpp:196
void DrawWidget(const Rect &r, WidgetID widget) const override
Draw the contents of a nested widget.
Definition dropdown.cpp:387
DropDownOptions options
Options for this drop down menu.
Definition dropdown.cpp:134
void OnResize() override
Called after the window got resized.
Definition dropdown.cpp:499
bool FilterByText(const DropDownListItem &item) const
Filter individual dropdown item.
Definition dropdown.cpp:375
DropDownList list
List with dropdown menu items.
Definition dropdown.cpp:128
void UpdateFilter()
Apply text filter to the items in the dropdown list, resizing the window as necessary.
Definition dropdown.cpp:507
int selected_click_result
Click result value, from the OnClick handler of the selected item.
Definition dropdown.cpp:130
uint GetFilterBoxHeight() const
Get height of filter edit panel.
Definition dropdown.cpp:230
void OnEditboxChanged(WidgetID wid) override
The text in an editbox has been edited.
Definition dropdown.cpp:529
void FitAvailableHeight(Dimension &desired, const Dimension &list, uint available_height)
Fit dropdown list into available height, rounding to average item size.
Definition dropdown.cpp:244
bool GetDropDownItem(int &result, int &click_result)
Find the dropdown item under the cursor.
Definition dropdown.cpp:343
Point position
Position of the topleft corner of the window.
Definition dropdown.cpp:136
int scrolling
If non-zero, auto-scroll the item list (one time).
Definition dropdown.cpp:135
void OnFocusLost(bool closing) override
The window has lost focus.
Definition dropdown.cpp:218
Data stored about a string that can be modified in the GUI.
Specification of a rectangle with absolute coordinates of all edges.
int Width() const
Get width of Rect.
Rect Shrink(int s) const
Copy and shrink Rect by s pixels.
Rect WithHeight(int height, bool end=false) const
Copy Rect and set its height.
int Height() const
Get height of Rect.
Rect WithY(int new_top, int new_bottom) const
Create a new Rect, replacing the top and bottom coordiates.
Rect Translate(int x, int y) const
Copy and translate Rect by x,y pixels.
String filter and state.
bool IsEmpty() const
Check whether any filter words were entered.
void SetFilterTerm(std::string_view str)
Set the term to filter on.
void ResetState()
Reset the matching state to process a new item.
bool GetState() const
Get the matching state of the current item.
std::string_view GetText() const
Get the current text.
Definition textbuf.cpp:284
void Assign(std::string_view text)
Copy a string into the textbuffer.
Definition textbuf.cpp:420
High level window description.
Definition window_gui.h:168
int16_t GetDefaultWidth() const
Determine default width of window.
Definition window.cpp:150
Data structure for an opened window.
Definition window_gui.h:274
void ReInit(int rx=0, int ry=0, bool reposition=false)
Re-initialize a window, and optionally change its size.
Definition window.cpp:992
virtual void Close(int data=0)
Hide the window and all its child windows, and mark them for a later deletion.
Definition window.cpp:1117
void FinishInitNested(WindowNumber window_number=0)
Perform the second part of the initialization of a nested widget tree.
Definition window.cpp:1822
std::map< WidgetID, QueryString * > querystrings
QueryString associated to WWT_EDITBOX widgets.
Definition window_gui.h:321
void InitializePositionSize(int x, int y, int min_width, int min_height)
Set the position and smallest size of the window.
Definition window.cpp:1471
Window * parent
Parent window.
Definition window_gui.h:329
ResizeInfo resize
Resize information.
Definition window_gui.h:315
void UnfocusFocusedWidget()
Makes no widget on this window have focus.
Definition window.cpp:483
void CreateNestedTree()
Perform the first part of the initialization of a nested widget tree.
Definition window.cpp:1812
WindowDesc & window_desc
Window description.
Definition window_gui.h:300
bool SetFocusedWidget(WidgetID widget_index)
Set focus within this window to the given widget.
Definition window.cpp:499
virtual void FindWindowPlacementAndResize(int def_width, int def_height, bool allow_resize)
Resize window towards the default size.
Definition window.cpp:1490
Window * FindChildWindow(WindowClass wc=WC_INVALID) const
Find the Window whose parent pointer points to this window.
Definition window.cpp:1061
int top
y position of top edge of the window
Definition window_gui.h:311
Window(WindowDesc &desc)
Empty constructor, initialization has been moved to InitNested() called from the constructor of the d...
Definition window.cpp:1845
const NWID * GetWidget(WidgetID widnum) const
Get the nested widget with number widnum from the nested widget tree.
Definition window_gui.h:990
WindowFlags flags
Window flags.
Definition window_gui.h:301
const Scrollbar * GetScrollbar(WidgetID widnum) const
Return the Scrollbar to a widget index.
Definition window.cpp:327
int height
Height of the window (number of pixels down in y direction).
Definition window_gui.h:313
WindowNumber window_number
Window number within the window class.
Definition window_gui.h:303
Definition of Interval and OneShot timers.
Definition of the Window system.
WidgetID GetWidgetFromPos(const Window *w, int x, int y)
Returns the index for the widget located at the given position relative to the window.
Definition widget.cpp:276
static RectPadding ScaleGUITrad(const RectPadding &r)
Scale a RectPadding to GUI zoom level.
Definition widget.cpp:49
@ NWID_BUTTON_DROPDOWN
Button with a drop-down.
Definition widget_type.h:74
@ WWT_EDITBOX
a textbox for typing
Definition widget_type.h:62
@ NWID_HORIZONTAL
Horizontal container.
Definition widget_type.h:66
@ WWT_PANEL
Simple depressed panel.
Definition widget_type.h:39
@ NWID_VSCROLLBAR
Vertical scrollbar.
Definition widget_type.h:76
@ NWID_VERTICAL
Vertical container.
Definition widget_type.h:68
@ NWID_SELECTION
Stacked widgets, only one visible at a time (eg in a panel with tabs).
Definition widget_type.h:71
@ DropdownClosed
Dropdown menu of the dropdown widget has closed.
@ DropdownActive
Dropdown menu of the button dropdown widget is active.
@ SZSP_HORIZONTAL
Display plane with zero size vertically, and filling and resizing horizontally.
@ SZSP_NONE
Display plane with zero size in both directions (none filling and resizing).
int GetMainViewTop()
Return the top of the main view available for general use.
Definition window.cpp:2152
void CloseWindowByClass(WindowClass cls, int data)
Close all windows of a given class.
Definition window.cpp:1222
int GetMainViewBottom()
Return the bottom of the main view available for general use.
Definition window.cpp:2163
Window functions not directly related to making/drawing windows.
Functions, definitions and such used only by the GUI.
@ WhiteBorder
Window white border counter bit mask.
Definition window_gui.h:235
@ WDP_MANUAL
Manually align the window (so no automatic location finding).
Definition window_gui.h:143
int WidgetID
Widget ID.
Definition window_type.h:20
@ WC_NONE
No window, redirects to WC_MAIN_WINDOW.
Definition window_type.h:50
@ WC_DROPDOWN_MENU
Drop down menu; Window numbers:
Functions related to zooming.