OpenTTD Source 20260311-master-g511d3794ce
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 /* Finish closing the dropdown, so it doesn't affect new window placement.
199 * Also mark it dirty in case the callback deals with the screen. (e.g. screenshots). */
200 this->Window::Close();
201
202 if (this->persistent_filter_text != nullptr) {
203 *this->persistent_filter_text = this->editbox.text.GetText();
204 }
205
206 Point pt = _cursor.pos;
207 pt.x -= this->parent->left;
208 pt.y -= this->parent->top;
209 this->parent->OnDropdownClose(pt, this->parent_button, this->selected_result, this->selected_click_result, this->options.Test(DropDownOption::InstantClose));
210
211 /* Set flag on parent widget to indicate that we have just closed. */
212 NWidgetCore *nwc = this->parent->GetWidget<NWidgetCore>(this->parent_button);
213 if (nwc != nullptr) nwc->disp_flags.Set(NWidgetDisplayFlag::DropdownClosed);
214 }
215
216 void OnFocusLost(bool closing) override
217 {
218 if (!closing) {
219 this->options.Reset(DropDownOption::InstantClose);
220 this->Close();
221 }
222 }
223
229 {
230 if (!this->options.Test(DropDownOption::Filterable)) return 0;
231
232 /* The edit panel widget does not exist yet so we don't know its real size. Calculate it instead. */
233 return GetCharacterHeight(FS_NORMAL) + WidgetDimensions::scaled.fullbevel.Vertical() * 3;
234 }
235
242 void FitAvailableHeight(Dimension &desired, const Dimension &list, uint available_height)
243 {
244 available_height -= this->GetFilterBoxHeight();
245
246 if (desired.height < available_height) return;
247
248 /* If the dropdown doesn't fully fit, we a need a dropdown. */
249 uint avg_height = list.height / (uint)this->list.size();
250 uint rows = std::max((available_height - WidgetDimensions::scaled.dropdownlist.Vertical()) / avg_height, 1U);
251
252 desired.width = std::max(list.width, desired.width - NWidgetScrollbar::GetVerticalDimension().width);
253 desired.height = rows * avg_height + WidgetDimensions::scaled.dropdownlist.Vertical();
254 }
255
260 uint GetVisibleHeight() const
261 {
262 uint height = 0;
263 for (const auto &item : this->list) {
264 if (!this->FilterByText(*item)) continue;
265 height += item->Height();
266 }
267 return height;
268 }
269
274 {
275 Rect button_rect = this->wi_rect.Translate(this->parent->left, this->parent->top);
276
277 /* Get the dimensions required for the list. */
278 Dimension list_dim = GetDropDownListDimension(this->list);
279
280 /* Set up dimensions for the items widget. */
281 Dimension widget_dim = list_dim;
282 widget_dim.width += WidgetDimensions::scaled.dropdownlist.Horizontal();
283 widget_dim.height += WidgetDimensions::scaled.dropdownlist.Vertical();
284
285 /* Width should match at least the width of the parent widget. */
286 widget_dim.width = std::max<uint>(widget_dim.width, button_rect.Width());
287
288 /* Available height below (or above, if the dropdown is placed above the widget). */
289 uint available_height_below = std::max(GetMainViewBottom() - button_rect.bottom - 1, 0);
290 uint available_height_above = std::max(button_rect.top - 1 - GetMainViewTop(), 0);
291
292 /* Is it better to place the dropdown above the widget? */
293 if (widget_dim.height > available_height_below && available_height_above > available_height_below) {
294 FitAvailableHeight(widget_dim, list_dim, available_height_above);
295 this->above = true;
296 this->position.y = button_rect.top - widget_dim.height - this->GetFilterBoxHeight();
297 this->GetWidget<NWidgetCore>(WID_DM_FILTER_PANEL)->GetParentWidget<NWidgetVertical>()->bottom_up = true;
298 } else {
299 FitAvailableHeight(widget_dim, list_dim, available_height_below);
300 this->above = false;
301 this->position.y = button_rect.bottom + 1;
302 this->GetWidget<NWidgetCore>(WID_DM_FILTER_PANEL)->GetParentWidget<NWidgetVertical>()->bottom_up = false;
303 }
304
305 if (_current_text_dir == TD_RTL) {
306 /* In case the list is wider than the parent button, the list should be right aligned to the button and overflow to the left. */
307 this->position.x = button_rect.right + 1 - (int)(widget_dim.width + (list_dim.height > widget_dim.height ? NWidgetScrollbar::GetVerticalDimension().width : 0));
308 } else {
309 this->position.x = button_rect.left;
310 }
311
312 this->initial_dim = widget_dim;
313 this->items_dim = widget_dim;
314 this->GetWidget<NWidgetStacked>(WID_DM_SHOW_SCROLL)->SetDisplayedPlane(list_dim.height > widget_dim.height ? 0 : SZSP_NONE);
315
316 /* Capacity is the average number of items visible */
317 this->vscroll->SetCapacity(widget_dim.height - WidgetDimensions::scaled.dropdownlist.Vertical());
318 this->vscroll->SetStepSize(list_dim.height / this->list.size());
319 this->vscroll->SetCount(this->GetVisibleHeight());
320
321 /* If the dropdown is positioned above the parent widget, start selection at the bottom. */
322 if (this->above) this->vscroll->SetPosition(INT_MAX);
323 }
324
325 void UpdateWidgetSize(WidgetID widget, Dimension &size, [[maybe_unused]] const Dimension &padding, [[maybe_unused]] Dimension &fill, [[maybe_unused]] Dimension &resize) override
326 {
327 if (widget == WID_DM_ITEMS) size = this->items_dim;
328 }
329
330 Point OnInitialPosition([[maybe_unused]] int16_t sm_width, [[maybe_unused]] int16_t sm_height, [[maybe_unused]] int window_number) override
331 {
332 return this->position;
333 }
334
341 bool GetDropDownItem(int &result, int &click_result)
342 {
343 if (GetWidgetFromPos(this, _cursor.pos.x - this->left, _cursor.pos.y - this->top) < 0) return false;
344
345 const Rect &r = this->GetWidget<NWidgetBase>(WID_DM_ITEMS)->GetCurrentRect().Shrink(WidgetDimensions::scaled.dropdownlist).Shrink(WidgetDimensions::scaled.dropdowntext, RectPadding::zero);
346 int click_y = _cursor.pos.y - this->top - r.top;
347 int y = -this->vscroll->GetPosition();
348 int y_end = r.Height();
349
350 for (const auto &item : this->list) {
351 if (!this->FilterByText(*item)) continue;
352 int item_height = item->Height();
353
354 /* Skip items that are scrolled up */
355 if (y > y_end) break;
356 if (click_y >= y && click_y < y + item_height) {
357 if (item->masked || !item->Selectable()) return false;
358 result = item->result;
359 click_result = item->OnClick(r.WithY(0, item_height - 1), {_cursor.pos.x - this->left, click_y - y});
360 return true;
361 }
362 y += item_height;
363 }
364
365 return false;
366 }
367
373 bool FilterByText(const DropDownListItem &item) const
374 {
375 /* Do not filter if the filter text box is empty */
376 if (this->string_filter.IsEmpty()) return true;
377
378 /* Filter table name */
379 this->string_filter.ResetState();
380 item.FilterText(this->string_filter);
381
382 return this->string_filter.GetState();
383 }
384
385 void DrawWidget(const Rect &r, WidgetID widget) const override
386 {
387 if (widget != WID_DM_ITEMS) return;
388
389 Colours colour = this->GetWidget<NWidgetCore>(widget)->colour;
390
391 Rect ir = r.Shrink(WidgetDimensions::scaled.dropdownlist);
392 if (ir.Height() == 0) return;
393
394 /* Setup a clipping rectangle... */
395 DrawPixelInfo tmp_dpi;
396 if (!FillDrawPixelInfo(&tmp_dpi, ir)) return;
397 /* ...but keep coordinates relative to the window. */
398 tmp_dpi.left += ir.left;
399 tmp_dpi.top += ir.top;
400 AutoRestoreBackup dpi_backup(_cur_dpi, &tmp_dpi);
401
402 int y = -this->vscroll->GetPosition();
403 int y_end = ir.Height();
404
405 for (const auto &item : this->list) {
406 if (!this->FilterByText(*item)) continue;
407 int item_height = item->Height();
408
409 /* Skip items that are scrolled up */
410 if (y > y_end) break;
411 if (y > -item_height) {
412 Rect full = ir.Translate(0, y).WithHeight(item_height);
413
414 bool selected = (this->selected_result == item->result) && item->Selectable() && this->selected_click_result < 0;
415 if (selected) GfxFillRect(full, PC_BLACK);
416
417 item->Draw(full, full.Shrink(WidgetDimensions::scaled.dropdowntext, RectPadding::zero), selected, selected ? this->selected_click_result : -1, colour);
418 }
419 y += item_height;
420 }
421 }
422
423 void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
424 {
425 if (widget != WID_DM_ITEMS) return;
426 int result, click_result;
427 if (this->GetDropDownItem(result, click_result)) {
428 this->click_delay = 4;
429 this->selected_result = result;
430 this->selected_click_result = click_result;
431 this->SetDirty();
432 }
433 }
434
436 const IntervalTimer<TimerWindow> scroll_interval = {std::chrono::milliseconds(30), [this](auto) {
437 if (this->scrolling == 0) return;
438
439 if (this->vscroll->UpdatePosition(this->scrolling)) this->SetDirty();
440
441 this->scrolling = 0;
442 }};
443
444 void OnMouseLoop() override
445 {
446 if (this->click_delay != 0 && --this->click_delay == 0) {
447 /* Close the dropdown, so it doesn't affect new window placement.
448 * Also mark it dirty in case the callback deals with the screen. (e.g. screenshots). */
449 if (!this->options.Test(DropDownOption::Persist)) this->Close();
450 this->parent->OnDropdownSelect(this->parent_button, this->selected_result, this->selected_click_result);
451 return;
452 }
453
454 if (this->drag_mode) {
455 int result, click_result;
456
458 this->drag_mode = false;
459 if (!this->GetDropDownItem(result, click_result)) {
460 if (this->options.Test(DropDownOption::InstantClose)) this->Close();
461 return;
462 }
463 this->click_delay = 2;
464 } else {
465 if (_cursor.pos.y <= this->top + WidgetDimensions::scaled.dropdownlist.top) {
466 /* Cursor is above the list, set scroll up */
467 this->scrolling = -1;
468 return;
469 } else if (_cursor.pos.y >= this->top + this->height - WidgetDimensions::scaled.dropdownlist.bottom) {
470 /* Cursor is below list, set scroll down */
471 this->scrolling = 1;
472 return;
473 }
474
475 if (!this->GetDropDownItem(result, click_result)) return;
476 }
477
478 if (this->selected_result != result || this->selected_click_result != click_result) {
479 this->selected_result = result;
480 this->selected_click_result = click_result;
481 this->SetDirty();
482 }
483 }
484 }
485
486 void ReplaceList(DropDownList &&list, std::optional<int> selected_result)
487 {
488 this->list = std::move(list);
489 if (selected_result.has_value()) this->selected_result = *selected_result;
490 this->UpdateSizeAndPosition();
491 this->ReInit();
492 this->InitializePositionSize(this->position.x, this->position.y, this->nested_root->smallest_x, this->nested_root->smallest_y);
493 this->FindWindowPlacementAndResize(this->window_desc.GetDefaultWidth(), this->window_desc.GetDefaultHeight(), true);
494 this->SetDirty();
495 }
496
497 void OnResize() override
498 {
499 this->vscroll->SetCapacity(this->items_dim.height - WidgetDimensions::scaled.dropdownlist.Vertical());
500 }
501
506 {
507 this->string_filter.SetFilterTerm(this->editbox.text.GetText());
508
509 uint height = this->GetVisibleHeight();
510 uint old_height = this->items_dim.height;
511 this->items_dim.height = std::min(this->initial_dim.height, height + WidgetDimensions::scaled.dropdownlist.Vertical());
512 this->vscroll->SetCount(height);
513
514 if (old_height != this->items_dim.height) {
515 this->ReInit();
516 if (this->above) {
517 /* Drop down list needs to be moved to near the parent drop down button. */
518 Rect button_rect = this->wi_rect.Translate(this->parent->left, this->parent->top);
519 this->top = button_rect.top - this->items_dim.height - this->GetFilterBoxHeight();
520 this->SetDirty();
521 }
522 } else {
523 this->SetDirty();
524 }
525 }
526
527 void OnEditboxChanged(WidgetID wid) override
528 {
529 if (wid != WID_DM_FILTER) return;
530 this->UpdateFilter();
531 }
532};
533
534void ReplaceDropDownList(Window *parent, DropDownList &&list, std::optional<int> selected_result)
535{
536 DropdownWindow *ddw = dynamic_cast<DropdownWindow *>(parent->FindChildWindow(WC_DROPDOWN_MENU));
537 if (ddw != nullptr) ddw->ReplaceList(std::move(list), selected_result);
538}
539
546{
547 Dimension dim{};
548 for (const auto &item : list) {
549 dim.height += item->Height();
550 dim.width = std::max(dim.width, item->Width());
551 }
552 dim.width += WidgetDimensions::scaled.dropdowntext.Horizontal();
553 return dim;
554}
555
568void ShowDropDownListAt(Window *w, DropDownList &&list, int selected, WidgetID button, Rect wi_rect, Colours wi_colour, DropDownOptions options, std::string * const persistent_filter_text)
569{
571 new DropdownWindow(w, std::move(list), selected, button, wi_rect, wi_colour, options, persistent_filter_text);
572}
573
585void ShowDropDownList(Window *w, DropDownList &&list, int selected, WidgetID button, uint width, DropDownOptions options, std::string * const persistent_filter_text)
586{
587 /* Handle the beep of the player's click. */
588 SndClickBeep();
589
590 /* Our parent's button widget is used to determine where to place the drop
591 * down list window. */
592 NWidgetCore *nwi = w->GetWidget<NWidgetCore>(button);
593 Rect wi_rect = nwi->GetCurrentRect();
594 Colours wi_colour = nwi->colour;
595
596 if ((nwi->type & WWT_MASK) == NWID_BUTTON_DROPDOWN) {
598 } else {
599 nwi->SetLowered(true);
600 }
601 nwi->SetDirty(w);
602
603 if (width != 0) {
604 if (_current_text_dir == TD_RTL) {
605 wi_rect.left = wi_rect.right + 1 - ScaleGUITrad(width);
606 } else {
607 wi_rect.right = wi_rect.left + ScaleGUITrad(width) - 1;
608 }
609 }
610
611 ShowDropDownListAt(w, std::move(list), selected, button, wi_rect, wi_colour, options, persistent_filter_text);
612}
613
627void 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)
628{
629 DropDownList list;
630
631 uint i = 0;
632 for (auto string : strings) {
633 if (!HasBit(hidden_mask, i)) {
634 list.push_back(MakeDropDownListStringItem(string, i, HasBit(disabled_mask, i)));
635 }
636 ++i;
637 }
638
639 if (!list.empty()) ShowDropDownList(w, std::move(list), selected, button, width, options, persistent_filter_text);
640}
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:568
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:627
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:545
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:585
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:330
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:444
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:260
void UpdateSizeAndPosition()
Update size and position of window to fit dropdown list into available space.
Definition dropdown.cpp:273
const IntervalTimer< TimerWindow > scroll_interval
Rate limit how fast scrolling happens.
Definition dropdown.cpp:436
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:423
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:325
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:385
DropDownOptions options
Options for this drop down menu.
Definition dropdown.cpp:134
void OnResize() override
Called after the window got resized.
Definition dropdown.cpp:497
bool FilterByText(const DropDownListItem &item) const
Filter individual dropdown item.
Definition dropdown.cpp:373
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:505
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:228
void OnEditboxChanged(WidgetID wid) override
The text in an editbox has been edited.
Definition dropdown.cpp:527
void FitAvailableHeight(Dimension &desired, const Dimension &list, uint available_height)
Fit dropdown list into available height, rounding to average item size.
Definition dropdown.cpp:242
bool GetDropDownItem(int &result, int &click_result)
Find the dropdown item under the cursor.
Definition dropdown.cpp:341
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:216
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 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.