OpenTTD Source: src/picker_gui.cpp Source File

OpenTTD Source 15.3

picker_gui.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
10#include "stdafx.h"
11#include "core/backup_type.hpp"
12#include "company_func.h"
13#include "gui.h"
14#include "hotkeys.h"
15#include "ini_type.h"
16#include "newgrf_badge.h"
17#include "newgrf_badge_config.h"
18#include "newgrf_badge_gui.h"
19#include "picker_gui.h"
20#include "querystring_gui.h"
21#include "settings_type.h"
22#include "sortlist_type.h"
23#include "sound_func.h"
24#include "sound_type.h"
25#include "string_func.h"
26#include "stringfilter_type.h"
27#include "strings_func.h"
28#include "widget_type.h"
29#include "window_func.h"
30#include "window_gui.h"
31#include "window_type.h"
32#include "zoom_func.h"
33
34#include "widgets/picker_widget.h"
35
36#include "table/sprites.h"
37#include "table/strings.h"
38
39#include <charconv>
40
41#include "safeguards.h"
42
43static std::vector<PickerCallbacks *> &GetPickerCallbacks()
44{
45 static std::vector<PickerCallbacks *> callbacks;
46 return callbacks;
47}
48
49PickerCallbacks::PickerCallbacks(const std::string &ini_group) : ini_group(ini_group)
50{
51 GetPickerCallbacks().push_back(this);
52}
53
54PickerCallbacks::~PickerCallbacks()
55{
56 auto &callbacks = GetPickerCallbacks();
57 callbacks.erase(std::ranges::find(callbacks, this));
58}
59
65 static void PickerLoadConfig(const IniFile &ini, PickerCallbacks &callbacks)
66{
67 const IniGroup *group = ini.GetGroup(callbacks.ini_group);
68 if (group == nullptr) return;
69
70 callbacks.saved.clear();
71 for (const IniItem &item : group->items) {
72 std::array<uint8_t, 4> grfid_buf;
73
74 std::string_view str = item.name;
75
76 /* Try reading "<grfid>|<localid>" */
77 auto grfid_pos = str.find('|');
78 if (grfid_pos == std::string_view::npos) continue;
79
80 std::string_view grfid_str = str.substr(0, grfid_pos);
81 if (!ConvertHexToBytes(grfid_str, grfid_buf)) continue;
82
83 str = str.substr(grfid_pos + 1);
84 uint32_t grfid = grfid_buf[0] | (grfid_buf[1] << 8) | (grfid_buf[2] << 16) | (grfid_buf[3] << 24);
85 uint16_t localid;
86 auto [ptr, err] = std::from_chars(str.data(), str.data() + str.size(), localid);
87
88 if (err == std::errc{} && ptr == str.data() + str.size()) {
89 callbacks.saved.insert({grfid, localid, 0, 0});
90 }
91 }
92}
93
99 static void PickerSaveConfig(IniFile &ini, const PickerCallbacks &callbacks)
100{
101 IniGroup &group = ini.GetOrCreateGroup(callbacks.ini_group);
102 group.Clear();
103
104 for (const PickerItem &item : callbacks.saved) {
105 std::string key = fmt::format("{:08X}|{}", std::byteswap(item.grfid), item.local_id);
106 group.CreateItem(key);
107 }
108}
109
114 void PickerLoadConfig(const IniFile &ini)
115{
116 for (auto *cb : GetPickerCallbacks()) PickerLoadConfig(ini, *cb);
117}
118
123 void PickerSaveConfig(IniFile &ini)
124{
125 for (const auto *cb : GetPickerCallbacks()) PickerSaveConfig(ini, *cb);
126}
127
129 static bool ClassIDSorter(int const &a, int const &b)
130{
131 return a < b;
132}
133
135 static bool ClassTagNameFilter(int const *item, PickerFilterData &filter)
136{
137 filter.ResetState();
138 filter.AddLine(GetString(filter.callbacks->GetClassName(*item)));
139 return filter.GetState();
140}
141
143 static bool TypeIDSorter(PickerItem const &a, PickerItem const &b)
144{
145 int r = a.class_index - b.class_index;
146 if (r == 0) r = a.index - b.index;
147 return r < 0;
148}
149
151 static bool TypeTagNameFilter(PickerItem const *item, PickerFilterData &filter)
152{
153 auto badges = filter.callbacks->GetTypeBadges(item->class_index, item->index);
154 if (filter.bdf.has_value() && !filter.bdf->Filter(badges)) return false;
155 if (filter.btf.has_value() && filter.btf->Filter(badges)) return true;
156
157 filter.ResetState();
158 filter.AddLine(GetString(filter.callbacks->GetTypeName(item->class_index, item->index)));
159 return filter.GetState();
160}
161
162 static const std::initializer_list<PickerClassList::SortFunction * const> _class_sorter_funcs = { &ClassIDSorter };
163 static const std::initializer_list<PickerClassList::FilterFunction * const> _class_filter_funcs = { &ClassTagNameFilter };
164 static const std::initializer_list<PickerTypeList::SortFunction * const> _type_sorter_funcs = { TypeIDSorter };
165 static const std::initializer_list<PickerTypeList::FilterFunction * const> _type_filter_funcs = { TypeTagNameFilter };
166
167PickerWindow::PickerWindow(WindowDesc &desc, Window *parent, int window_number, PickerCallbacks &callbacks) : PickerWindowBase(desc, parent), callbacks(callbacks),
168 class_editbox(EDITBOX_MAX_SIZE * MAX_CHAR_LENGTH, EDITBOX_MAX_SIZE),
169 type_editbox(EDITBOX_MAX_SIZE * MAX_CHAR_LENGTH, EDITBOX_MAX_SIZE)
170{
171 this->window_number = window_number;
172
173 /* Init of nested tree is deferred.
174 * PickerWindow::ConstructWindow must be called by the inheriting window. */
175}
176
177void PickerWindow::ConstructWindow()
178{
179 this->CreateNestedTree();
180
181 /* Test if pickers should be active.*/
182 bool is_active = this->callbacks.IsActive();
183
184 this->preview_height = std::max(this->callbacks.preview_height, PREVIEW_HEIGHT);
185
186 /* Functionality depends on widgets being present, not window class. */
187 this->has_class_picker = is_active && this->GetWidget<NWidgetBase>(WID_PW_CLASS_LIST) != nullptr && this->callbacks.HasClassChoice();
188 this->has_type_picker = is_active && this->GetWidget<NWidgetBase>(WID_PW_TYPE_MATRIX) != nullptr;
189
190 if (this->has_class_picker) {
191 this->GetWidget<NWidgetCore>(WID_PW_CLASS_LIST)->SetToolTip(this->callbacks.GetClassTooltip());
192
193 this->querystrings[WID_PW_CLASS_FILTER] = &this->class_editbox;
194 } else {
195 if (auto *nwid = this->GetWidget<NWidgetStacked>(WID_PW_CLASS_SEL); nwid != nullptr) {
196 /* Check the container orientation. MakeNWidgets adds an additional NWID_VERTICAL container so we check the grand-parent. */
197 bool is_vertical = (nwid->parent->parent->type == NWID_VERTICAL);
198 nwid->SetDisplayedPlane(is_vertical ? SZSP_HORIZONTAL : SZSP_VERTICAL);
199 }
200 }
201
202 this->class_editbox.cancel_button = QueryString::ACTION_CLEAR;
203 this->class_string_filter.SetFilterTerm(this->class_editbox.text.GetText());
204 this->class_string_filter.callbacks = &this->callbacks;
205
206 this->classes.SetListing(this->callbacks.class_last_sorting);
207 this->classes.SetFiltering(this->callbacks.class_last_filtering);
208 this->classes.SetSortFuncs(_class_sorter_funcs);
209 this->classes.SetFilterFuncs(_class_filter_funcs);
210
211 /* Update saved type information. */
212 this->callbacks.saved = this->callbacks.UpdateSavedItems(this->callbacks.saved);
213
214 /* Clear used type information. */
215 this->callbacks.used.clear();
216
217 if (this->has_type_picker) {
218 /* Populate used type information. */
219 this->callbacks.FillUsedItems(this->callbacks.used);
220
221 SetWidgetDisabledState(WID_PW_MODE_ALL, !this->callbacks.HasClassChoice());
222
223 this->GetWidget<NWidgetCore>(WID_PW_TYPE_ITEM)->SetToolTip(this->callbacks.GetTypeTooltip());
224
225 auto *matrix = this->GetWidget<NWidgetMatrix>(WID_PW_TYPE_MATRIX);
226 matrix->SetScrollbar(this->GetScrollbar(WID_PW_TYPE_SCROLL));
227
228 this->querystrings[WID_PW_TYPE_FILTER] = &this->type_editbox;
229 } else {
230 if (auto *nwid = this->GetWidget<NWidgetStacked>(WID_PW_TYPE_SEL); nwid != nullptr) {
231 /* Check the container orientation. MakeNWidgets adds an additional NWID_VERTICAL container so we check the grand-parent. */
232 bool is_vertical = (nwid->parent->parent->type == NWID_VERTICAL);
233 nwid->SetDisplayedPlane(is_vertical ? SZSP_HORIZONTAL : SZSP_VERTICAL);
234 }
235 }
236
237 this->type_editbox.cancel_button = QueryString::ACTION_CLEAR;
238 this->type_string_filter.SetFilterTerm(this->type_editbox.text.GetText());
239 this->type_string_filter.callbacks = &this->callbacks;
240
241 this->types.SetListing(this->callbacks.type_last_sorting);
242 this->types.SetFiltering(this->callbacks.type_last_filtering);
243 this->types.SetSortFuncs(_type_sorter_funcs);
244 this->types.SetFilterFuncs(_type_filter_funcs);
245
246 this->FinishInitNested(this->window_number);
247
248 this->InvalidateData(PICKER_INVALIDATION_ALL);
249}
250
251 void PickerWindow::OnInit()
252{
253 this->badge_classes = GUIBadgeClasses(this->callbacks.GetFeature());
254 this->badge_filters = AddBadgeDropdownFilters(this, WID_PW_BADGE_FILTER, WID_PW_BADGE_FILTER, COLOUR_DARK_GREEN, this->callbacks.GetFeature());
255
256 this->widget_lookup.clear();
257 this->nested_root->FillWidgetLookup(this->widget_lookup);
258}
259
260 void PickerWindow::Close(int data)
261{
262 this->callbacks.Close(data);
263 this->PickerWindowBase::Close(data);
264}
265
266 void PickerWindow::UpdateWidgetSize(WidgetID widget, Dimension &size, const Dimension &padding, Dimension &fill, Dimension &resize)
267{
268 switch (widget) {
269 /* Class picker */
270 case WID_PW_CLASS_LIST:
271 fill.height = resize.height = GetCharacterHeight(FS_NORMAL) + padding.height;
272 size.height = 5 * resize.height;
273 break;
274
275 /* Type picker */
276 case WID_PW_TYPE_MATRIX:
277 /* At least two items wide. */
278 size.width += resize.width;
279 fill.width = resize.width;
280 fill.height = 1;
281
282 /* Resizing in X direction only at blob size, but at pixel level in Y. */
283 resize.height = 1;
284 break;
285
286 /* Type picker */
287 case WID_PW_TYPE_ITEM:
288 size.width = ScaleGUITrad(PREVIEW_WIDTH) + WidgetDimensions::scaled.fullbevel.Horizontal();
289 size.height = ScaleGUITrad(this->preview_height) + WidgetDimensions::scaled.fullbevel.Vertical();
290 break;
291
292 case WID_PW_CONFIGURE_BADGES:
293 /* Hide the configuration button if no configurable badges are present. */
294 if (this->badge_classes.GetClasses().empty()) size = {0, 0};
295 break;
296 }
297}
298
299std::string PickerWindow::GetWidgetString(WidgetID widget, StringID stringid) const
300{
301 if (IsInsideMM(widget, this->badge_filters.first, this->badge_filters.second)) {
302 return this->GetWidget<NWidgetBadgeFilter>(widget)->GetStringParameter(this->badge_filter_choices);
303 }
304
305 return this->Window::GetWidgetString(widget, stringid);
306}
307
308 void PickerWindow::DrawWidget(const Rect &r, WidgetID widget) const
309{
310 switch (widget) {
311 /* Class picker */
312 case WID_PW_CLASS_LIST: {
313 Rect ir = r.Shrink(WidgetDimensions::scaled.matrix);
314 const int selected = this->callbacks.GetSelectedClass();
315 const auto vscroll = this->GetScrollbar(WID_PW_CLASS_SCROLL);
316 const int y_step = this->GetWidget<NWidgetResizeBase>(widget)->resize_y;
317 auto [first, last] = vscroll->GetVisibleRangeIterators(this->classes);
318 for (auto it = first; it != last; ++it) {
319 DrawString(ir, this->callbacks.GetClassName(*it), *it == selected ? TC_WHITE : TC_BLACK);
320 ir.top += y_step;
321 }
322 break;
323 }
324
325 /* Type picker */
326 case WID_PW_TYPE_ITEM: {
327 assert(this->GetWidget<NWidgetBase>(widget)->GetParentWidget<NWidgetMatrix>()->GetCurrentElement() < static_cast<int>(this->types.size()));
328 const auto &item = this->types[this->GetWidget<NWidgetBase>(widget)->GetParentWidget<NWidgetMatrix>()->GetCurrentElement()];
329
330 DrawPixelInfo tmp_dpi;
331 Rect ir = r.Shrink(WidgetDimensions::scaled.bevel);
332 if (FillDrawPixelInfo(&tmp_dpi, ir)) {
333 AutoRestoreBackup dpi_backup(_cur_dpi, &tmp_dpi);
334 int x = (ir.Width() - ScaleSpriteTrad(PREVIEW_WIDTH)) / 2 + ScaleSpriteTrad(PREVIEW_LEFT);
335 int y = (ir.Height() + ScaleSpriteTrad(this->preview_height)) / 2 - ScaleSpriteTrad(PREVIEW_BOTTOM);
336
337 this->callbacks.DrawType(x, y, item.class_index, item.index);
338
339 int by = ir.Height() - ScaleGUITrad(12);
340
341 GrfSpecFeature feature = this->callbacks.GetFeature();
342 /* Houses have recolours but not related to the company colour and other items depend on gamemode. */
343 PaletteID palette = _game_mode != GM_NORMAL || feature == GSF_HOUSES ? PAL_NONE : GetCompanyPalette(_local_company);
344 DrawBadgeColumn({0, by, ir.Width() - 1, ir.Height() - 1}, 0, this->badge_classes, this->callbacks.GetTypeBadges(item.class_index, item.index), feature, std::nullopt, palette);
345
346 if (this->callbacks.saved.contains(item)) {
347 DrawSprite(SPR_BLOT, PALETTE_TO_YELLOW, 0, 0);
348 }
349 if (this->callbacks.used.contains(item)) {
350 DrawSprite(SPR_BLOT, PALETTE_TO_GREEN, ir.Width() - GetSpriteSize(SPR_BLOT).width, 0);
351 }
352 }
353
354 if (!this->callbacks.IsTypeAvailable(item.class_index, item.index)) {
355 GfxFillRect(ir, GetColourGradient(COLOUR_GREY, SHADE_DARKER), FILLRECT_CHECKER);
356 }
357 break;
358 }
359
360 case WID_PW_TYPE_NAME: {
361 StringID str = this->callbacks.GetTypeName(this->callbacks.GetSelectedClass(), this->callbacks.GetSelectedType());
362 if (str != INVALID_STRING_ID) DrawString(r, str, TC_GOLD, SA_CENTER);
363 break;
364 }
365 }
366}
367
368 void PickerWindow::OnResize()
369{
370 if (this->has_class_picker) {
371 this->GetScrollbar(WID_PW_CLASS_SCROLL)->SetCapacityFromWidget(this, WID_PW_CLASS_LIST);
372 }
373}
374
375 void PickerWindow::OnClick(Point pt, WidgetID widget, int)
376{
377 switch (widget) {
378 /* Class Picker */
379 case WID_PW_CLASS_LIST: {
380 const auto vscroll = this->GetWidget<NWidgetScrollbar>(WID_PW_CLASS_SCROLL);
381 auto it = vscroll->GetScrolledItemFromWidget(this->classes, pt.y, this, WID_PW_CLASS_LIST);
382 if (it == this->classes.end()) return;
383
384 if (this->callbacks.GetSelectedClass() != *it || HasBit(this->callbacks.mode, PFM_ALL)) {
385 ClrBit(this->callbacks.mode, PFM_ALL); // Disable showing all.
386 this->callbacks.SetSelectedClass(*it);
387 this->InvalidateData({PickerInvalidation::Type, PickerInvalidation::Position, PickerInvalidation::Validate});
388 }
389 SndClickBeep();
390 CloseWindowById(WC_SELECT_STATION, 0);
391 break;
392 }
393
394 case WID_PW_MODE_ALL:
395 case WID_PW_MODE_USED:
396 case WID_PW_MODE_SAVED:
397 ToggleBit(this->callbacks.mode, widget - WID_PW_MODE_ALL);
398 if (!this->IsWidgetDisabled(WID_PW_MODE_ALL) && HasBit(this->callbacks.mode, widget - WID_PW_MODE_ALL)) {
399 /* Enabling used or saved filters automatically enables all. */
400 SetBit(this->callbacks.mode, PFM_ALL);
401 }
402 this->InvalidateData({PickerInvalidation::Class, PickerInvalidation::Type, PickerInvalidation::Position});
403 SndClickBeep();
404 break;
405
406 case WID_PW_SHRINK:
407 this->callbacks.preview_height = this->preview_height = _ctrl_pressed ? PREVIEW_HEIGHT : std::max(PREVIEW_HEIGHT, this->preview_height - STEP_PREVIEW_HEIGHT);
408 this->InvalidateData({});
409 this->ReInit();
410 break;
411
412 case WID_PW_EXPAND:
413 this->callbacks.preview_height = this->preview_height = _ctrl_pressed ? MAX_PREVIEW_HEIGHT : std::min(MAX_PREVIEW_HEIGHT, this->preview_height + STEP_PREVIEW_HEIGHT);
414 this->InvalidateData({});
415 this->ReInit();
416 break;
417
418 /* Type Picker */
419 case WID_PW_TYPE_ITEM: {
420 int sel = this->GetWidget<NWidgetBase>(widget)->GetParentWidget<NWidgetMatrix>()->GetCurrentElement();
421 assert(sel < (int)this->types.size());
422 const auto &item = this->types[sel];
423
424 if (_ctrl_pressed) {
425 auto it = this->callbacks.saved.find(item);
426 if (it == std::end(this->callbacks.saved)) {
427 this->callbacks.saved.insert(item);
428 } else {
429 this->callbacks.saved.erase(it);
430 }
431 this->InvalidateData(PickerInvalidation::Type);
432 break;
433 }
434
435 if (this->callbacks.IsTypeAvailable(item.class_index, item.index)) {
436 this->callbacks.SetSelectedClass(item.class_index);
437 this->callbacks.SetSelectedType(item.index);
438 this->InvalidateData(PickerInvalidation::Position);
439 }
440 SndClickBeep();
441 CloseWindowById(WC_SELECT_STATION, 0);
442 break;
443 }
444
445 case WID_PW_CONFIGURE_BADGES:
446 if (this->badge_classes.GetClasses().empty()) break;
447 ShowDropDownList(this, BuildBadgeClassConfigurationList(this->badge_classes, 1, {}, COLOUR_DARK_GREEN), -1, widget, 0, DropDownOption::Persist);
448 break;
449
450 default:
451 if (IsInsideMM(widget, this->badge_filters.first, this->badge_filters.second)) {
452 /* Houses have recolours but not related to the company colour and other items depend on gamemode. */
453 PaletteID palette = _game_mode != GM_NORMAL || this->callbacks.GetFeature() == GSF_HOUSES ? PAL_NONE : GetCompanyPalette(_local_company);
454 ShowDropDownList(this, this->GetWidget<NWidgetBadgeFilter>(widget)->GetDropDownList(palette), -1, widget, 0);
455 }
456 break;
457 }
458}
459
460 void PickerWindow::OnDropdownSelect(WidgetID widget, int index, int click_result)
461{
462 switch (widget) {
463 case WID_PW_CONFIGURE_BADGES: {
464 bool reopen = HandleBadgeConfigurationDropDownClick(this->callbacks.GetFeature(), 1, index, click_result, this->badge_filter_choices);
465
466 this->ReInit();
467
468 if (reopen) {
469 ReplaceDropDownList(this, BuildBadgeClassConfigurationList(this->badge_classes, 1, {}, COLOUR_DARK_GREEN), -1);
470 } else {
471 this->CloseChildWindows(WC_DROPDOWN_MENU);
472 }
473
474 /* We need to refresh if a filter is removed. */
475 this->InvalidateData({PickerInvalidation::Type, PickerInvalidation::Filter, PickerInvalidation::Position});
476 break;
477 }
478
479 default:
480 if (IsInsideMM(widget, this->badge_filters.first, this->badge_filters.second)) {
481 if (index < 0) {
482 ResetBadgeFilter(this->badge_filter_choices, this->GetWidget<NWidgetBadgeFilter>(widget)->GetBadgeClassID());
483 } else {
484 SetBadgeFilter(this->badge_filter_choices, BadgeID(index));
485 }
486 this->InvalidateData({PickerInvalidation::Type, PickerInvalidation::Filter, PickerInvalidation::Position});
487 }
488 break;
489 }
490}
491
492 void PickerWindow::OnInvalidateData(int data, bool gui_scope)
493{
494 if (!gui_scope) return;
495
496 PickerInvalidations pi(data);
497
498 if (pi.Test(PickerInvalidation::Filter)) {
499 if (this->badge_filter_choices.empty()) {
500 this->type_string_filter.bdf.reset();
501 } else {
502 this->type_string_filter.bdf.emplace(this->badge_filter_choices);
503 }
504 this->types.SetFilterState(!type_string_filter.IsEmpty() || type_string_filter.bdf.has_value());
505 }
506
507 if (pi.Test(PickerInvalidation::Class)) this->classes.ForceRebuild();
508 if (pi.Test(PickerInvalidation::Type)) this->types.ForceRebuild();
509
510 this->BuildPickerClassList();
511 if (pi.Test(PickerInvalidation::Validate)) this->EnsureSelectedClassIsValid();
512 if (pi.Test(PickerInvalidation::Position)) this->EnsureSelectedClassIsVisible();
513
514 this->BuildPickerTypeList();
515 if (pi.Test(PickerInvalidation::Validate)) this->EnsureSelectedTypeIsValid();
516 if (pi.Test(PickerInvalidation::Position)) this->EnsureSelectedTypeIsVisible();
517
518 if (this->has_type_picker) {
519 SetWidgetLoweredState(WID_PW_MODE_ALL, HasBit(this->callbacks.mode, PFM_ALL));
520 SetWidgetLoweredState(WID_PW_MODE_USED, HasBit(this->callbacks.mode, PFM_USED));
521 SetWidgetLoweredState(WID_PW_MODE_SAVED, HasBit(this->callbacks.mode, PFM_SAVED));
522 }
523
524 SetWidgetDisabledState(WID_PW_SHRINK, this->preview_height == PREVIEW_HEIGHT);
525 SetWidgetDisabledState(WID_PW_EXPAND, this->preview_height == MAX_PREVIEW_HEIGHT);
526}
527
528 EventState PickerWindow::OnHotkey(int hotkey)
529{
530 switch (hotkey) {
531 case PCWHK_FOCUS_FILTER_BOX:
532 /* Cycle between the two edit boxes. */
533 if (this->has_type_picker && (this->nested_focus == nullptr || this->nested_focus->GetIndex() != WID_PW_TYPE_FILTER)) {
534 this->SetFocusedWidget(WID_PW_TYPE_FILTER);
535 } else if (this->has_class_picker && (this->nested_focus == nullptr || this->nested_focus->GetIndex() != WID_PW_CLASS_FILTER)) {
536 this->SetFocusedWidget(WID_PW_CLASS_FILTER);
537 }
538 SetFocusedWindow(this);
539 return ES_HANDLED;
540
541 default:
542 return ES_NOT_HANDLED;
543 }
544}
545
546 void PickerWindow::OnEditboxChanged(WidgetID wid)
547{
548 switch (wid) {
549 case WID_PW_CLASS_FILTER:
550 this->class_string_filter.SetFilterTerm(this->class_editbox.text.GetText());
551 this->classes.SetFilterState(!class_string_filter.IsEmpty());
552 this->InvalidateData(PickerInvalidation::Class);
553 break;
554
555 case WID_PW_TYPE_FILTER:
556 this->type_string_filter.SetFilterTerm(this->type_editbox.text.GetText());
557 if (!type_string_filter.IsEmpty()) {
558 this->type_string_filter.btf.emplace(this->type_string_filter, this->callbacks.GetFeature());
559 } else {
560 this->type_string_filter.btf.reset();
561 }
562 this->InvalidateData({PickerInvalidation::Type, PickerInvalidation::Filter, PickerInvalidation::Position});
563 break;
564
565 default:
566 break;
567 }
568}
569
571 void PickerWindow::BuildPickerClassList()
572{
573 if (!this->classes.NeedRebuild()) return;
574
575 int count = this->callbacks.GetClassCount();
576
577 this->classes.clear();
578 this->classes.reserve(count);
579
580 bool filter_used = HasBit(this->callbacks.mode, PFM_USED);
581 bool filter_saved = HasBit(this->callbacks.mode, PFM_SAVED);
582 for (int i = 0; i < count; i++) {
583 if (this->callbacks.GetClassName(i) == INVALID_STRING_ID) continue;
584 if (filter_used && std::none_of(std::begin(this->callbacks.used), std::end(this->callbacks.used), [i](const PickerItem &item) { return item.class_index == i; })) continue;
585 if (filter_saved && std::none_of(std::begin(this->callbacks.saved), std::end(this->callbacks.saved), [i](const PickerItem &item) { return item.class_index == i; })) continue;
586 this->classes.emplace_back(i);
587 }
588
589 this->classes.Filter(this->class_string_filter);
590 this->classes.RebuildDone();
591 this->classes.Sort();
592
593 if (!this->has_class_picker) return;
594 this->GetScrollbar(WID_PW_CLASS_SCROLL)->SetCount(this->classes.size());
595}
596
597void PickerWindow::EnsureSelectedClassIsValid()
598{
599 int class_index = this->callbacks.GetSelectedClass();
600 if (std::binary_search(std::begin(this->classes), std::end(this->classes), class_index)) return;
601
602 if (!this->classes.empty()) {
603 class_index = this->classes.front();
604 } else {
605 /* Classes can be empty if filters are enabled, find the first usable class. */
606 int count = this->callbacks.GetClassCount();
607 for (int i = 0; i < count; i++) {
608 if (this->callbacks.GetClassName(i) == INVALID_STRING_ID) continue;
609 class_index = i;
610 break;
611 }
612 }
613
614 this->callbacks.SetSelectedClass(class_index);
615 this->types.ForceRebuild();
616}
617
618void PickerWindow::EnsureSelectedClassIsVisible()
619{
620 if (!this->has_class_picker) return;
621 if (this->classes.empty()) return;
622
623 auto it = std::ranges::find(this->classes, this->callbacks.GetSelectedClass());
624 if (it == std::end(this->classes)) return;
625
626 int pos = static_cast<int>(std::distance(std::begin(this->classes), it));
627 this->GetScrollbar(WID_PW_CLASS_SCROLL)->ScrollTowards(pos);
628}
629
630void PickerWindow::RefreshUsedTypeList()
631{
632 if (!this->has_type_picker) return;
633
634 this->callbacks.used.clear();
635 this->callbacks.FillUsedItems(this->callbacks.used);
636 this->InvalidateData(PickerInvalidation::Type);
637}
638
640 void PickerWindow::BuildPickerTypeList()
641{
642 if (!this->types.NeedRebuild()) return;
643
644 this->types.clear();
645
646 bool show_all = HasBit(this->callbacks.mode, PFM_ALL);
647 bool filter_used = HasBit(this->callbacks.mode, PFM_USED);
648 bool filter_saved = HasBit(this->callbacks.mode, PFM_SAVED);
649 int cls_id = this->callbacks.GetSelectedClass();
650
651 if (filter_used) {
652 /* Showing used items. May also be filtered by saved items. */
653 this->types.reserve(this->callbacks.used.size());
654 for (const PickerItem &item : this->callbacks.used) {
655 if (!show_all && item.class_index != cls_id) continue;
656 if (this->callbacks.GetTypeName(item.class_index, item.index) == INVALID_STRING_ID) continue;
657 this->types.emplace_back(item);
658 }
659 } else if (filter_saved) {
660 /* Showing only saved items. */
661 this->types.reserve(this->callbacks.saved.size());
662 for (const PickerItem &item : this->callbacks.saved) {
663 /* The used list may contain items that aren't currently loaded, skip these. */
664 if (item.class_index == -1) continue;
665 if (!show_all && item.class_index != cls_id) continue;
666 if (this->callbacks.GetTypeName(item.class_index, item.index) == INVALID_STRING_ID) continue;
667 this->types.emplace_back(item);
668 }
669 } else if (show_all) {
670 /* Reserve enough space for everything. */
671 int total = 0;
672 for (int class_index : this->classes) total += this->callbacks.GetTypeCount(class_index);
673 this->types.reserve(total);
674 /* Add types in all classes. */
675 for (int class_index : this->classes) {
676 int count = this->callbacks.GetTypeCount(class_index);
677 for (int i = 0; i < count; i++) {
678 if (this->callbacks.GetTypeName(class_index, i) == INVALID_STRING_ID) continue;
679 this->types.emplace_back(this->callbacks.GetPickerItem(class_index, i));
680 }
681 }
682 } else {
683 /* Add types in only the selected class. */
684 if (cls_id >= 0 && cls_id < this->callbacks.GetClassCount()) {
685 int count = this->callbacks.GetTypeCount(cls_id);
686 this->types.reserve(count);
687 for (int i = 0; i < count; i++) {
688 if (this->callbacks.GetTypeName(cls_id, i) == INVALID_STRING_ID) continue;
689 this->types.emplace_back(this->callbacks.GetPickerItem(cls_id, i));
690 }
691 }
692 }
693
694 this->types.Filter(this->type_string_filter);
695 this->types.RebuildDone();
696 this->types.Sort();
697
698 if (!this->has_type_picker) return;
699 this->GetWidget<NWidgetMatrix>(WID_PW_TYPE_MATRIX)->SetCount(static_cast<int>(this->types.size()));
700}
701
702void PickerWindow::EnsureSelectedTypeIsValid()
703{
704 int class_index = this->callbacks.GetSelectedClass();
705 int index = this->callbacks.GetSelectedType();
706 if (std::any_of(std::begin(this->types), std::end(this->types), [class_index, index](const auto &item) { return item.class_index == class_index && item.index == index; })) return;
707
708 if (!this->types.empty()) {
709 class_index = this->types.front().class_index;
710 index = this->types.front().index;
711 } else {
712 /* Types can be empty if filters are enabled, find the first usable type. */
713 int count = this->callbacks.GetTypeCount(class_index);
714 for (int i = 0; i < count; i++) {
715 if (this->callbacks.GetTypeName(class_index, i) == INVALID_STRING_ID) continue;
716 index = i;
717 break;
718 }
719 }
720 this->callbacks.SetSelectedClass(class_index);
721 this->callbacks.SetSelectedType(index);
722}
723
724void PickerWindow::EnsureSelectedTypeIsVisible()
725{
726 if (!this->has_type_picker) return;
727 if (this->types.empty()) {
728 this->GetWidget<NWidgetMatrix>(WID_PW_TYPE_MATRIX)->SetClicked(-1);
729 return;
730 }
731
732 int class_index = this->callbacks.GetSelectedClass();
733 int index = this->callbacks.GetSelectedType();
734
735 auto it = std::ranges::find_if(this->types, [class_index, index](const auto &item) { return item.class_index == class_index && item.index == index; });
736 int pos = -1;
737 if (it != std::end(this->types)) {
738 pos = static_cast<int>(std::distance(std::begin(this->types), it));
739 }
740
741 this->GetWidget<NWidgetMatrix>(WID_PW_TYPE_MATRIX)->SetClicked(pos);
742}
743
745std::unique_ptr<NWidgetBase> MakePickerClassWidgets()
746{
747 static constexpr std::initializer_list<NWidgetPart> picker_class_widgets = {
748 NWidget(NWID_SELECTION, INVALID_COLOUR, WID_PW_CLASS_SEL),
749 NWidget(NWID_VERTICAL),
750 NWidget(WWT_PANEL, COLOUR_DARK_GREEN),
751 NWidget(WWT_EDITBOX, COLOUR_DARK_GREEN, WID_PW_CLASS_FILTER), SetMinimalSize(144, 0), SetPadding(2), SetFill(1, 0), SetStringTip(STR_LIST_FILTER_OSKTITLE, STR_LIST_FILTER_TOOLTIP),
752 EndContainer(),
753 NWidget(NWID_HORIZONTAL),
754 NWidget(WWT_PANEL, COLOUR_DARK_GREEN),
755 NWidget(WWT_MATRIX, COLOUR_GREY, WID_PW_CLASS_LIST), SetFill(1, 1), SetResize(1, 1), SetPadding(WidgetDimensions::unscaled.picker),
756 SetMatrixDataTip(1, 0), SetScrollbar(WID_PW_CLASS_SCROLL),
757 EndContainer(),
758 NWidget(NWID_VSCROLLBAR, COLOUR_DARK_GREEN, WID_PW_CLASS_SCROLL),
759 EndContainer(),
760 EndContainer(),
761 EndContainer(),
762 };
763
764 return MakeNWidgets(picker_class_widgets, nullptr);
765}
766
768std::unique_ptr<NWidgetBase> MakePickerTypeWidgets()
769{
770 static constexpr std::initializer_list<NWidgetPart> picker_type_widgets = {
771 NWidget(NWID_SELECTION, INVALID_COLOUR, WID_PW_TYPE_SEL),
772 NWidget(NWID_VERTICAL),
773 NWidget(NWID_HORIZONTAL),
774 NWidget(WWT_PANEL, COLOUR_DARK_GREEN),
775 NWidget(WWT_EDITBOX, COLOUR_DARK_GREEN, WID_PW_TYPE_FILTER), SetPadding(2), SetResize(1, 0), SetFill(1, 0), SetStringTip(STR_LIST_FILTER_OSKTITLE, STR_LIST_FILTER_TOOLTIP),
776 EndContainer(),
777 NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_PW_CONFIGURE_BADGES), SetAspect(WidgetDimensions::ASPECT_UP_DOWN_BUTTON), SetResize(0, 0), SetFill(0, 1), SetSpriteTip(SPR_EXTRA_MENU, STR_BADGE_CONFIG_MENU_TOOLTIP),
778 EndContainer(),
779 NWidget(NWID_VERTICAL, NWidContainerFlag{}, WID_PW_BADGE_FILTER),
780 EndContainer(),
781 NWidget(NWID_HORIZONTAL, NWidContainerFlag::EqualSize),
782 NWidget(WWT_TEXTBTN, COLOUR_DARK_GREEN, WID_PW_MODE_ALL), SetFill(1, 0), SetResize(1, 0), SetStringTip(STR_PICKER_MODE_ALL, STR_PICKER_MODE_ALL_TOOLTIP),
783 NWidget(WWT_TEXTBTN, COLOUR_DARK_GREEN, WID_PW_MODE_USED), SetFill(1, 0), SetResize(1, 0), SetStringTip(STR_PICKER_MODE_USED, STR_PICKER_MODE_USED_TOOLTIP),
784 NWidget(WWT_TEXTBTN, COLOUR_DARK_GREEN, WID_PW_MODE_SAVED), SetFill(1, 0), SetResize(1, 0), SetStringTip(STR_PICKER_MODE_SAVED, STR_PICKER_MODE_SAVED_TOOLTIP),
785 NWidget(WWT_PUSHTXTBTN, COLOUR_DARK_GREEN, WID_PW_SHRINK), SetAspect(WidgetDimensions::ASPECT_UP_DOWN_BUTTON), SetStringTip(STR_PICKER_PREVIEW_SHRINK, STR_PICKER_PREVIEW_SHRINK_TOOLTIP),
786 NWidget(WWT_PUSHTXTBTN, COLOUR_DARK_GREEN, WID_PW_EXPAND), SetAspect(WidgetDimensions::ASPECT_UP_DOWN_BUTTON), SetStringTip(STR_PICKER_PREVIEW_EXPAND, STR_PICKER_PREVIEW_EXPAND_TOOLTIP),
787 EndContainer(),
788 NWidget(NWID_HORIZONTAL),
789 NWidget(WWT_PANEL, COLOUR_DARK_GREEN), SetScrollbar(WID_PW_TYPE_SCROLL),
790 NWidget(NWID_MATRIX, COLOUR_DARK_GREEN, WID_PW_TYPE_MATRIX), SetPIP(0, 2, 0), SetPadding(WidgetDimensions::unscaled.picker),
791 NWidget(WWT_PANEL, COLOUR_GREY, WID_PW_TYPE_ITEM), SetScrollbar(WID_PW_TYPE_SCROLL),
792 EndContainer(),
793 EndContainer(),
794 EndContainer(),
795 NWidget(NWID_VSCROLLBAR, COLOUR_DARK_GREEN, WID_PW_TYPE_SCROLL),
796 EndContainer(),
797 NWidget(NWID_HORIZONTAL),
798 NWidget(WWT_PANEL, COLOUR_DARK_GREEN),
799 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_PW_TYPE_NAME), SetPadding(WidgetDimensions::unscaled.framerect), SetResize(1, 0), SetFill(1, 0), SetMinimalTextLines(1, 0),
800 EndContainer(),
801 NWidget(WWT_RESIZEBOX, COLOUR_DARK_GREEN, WID_PW_TYPE_RESIZE),
802 EndContainer(),
803 EndContainer(),
804 EndContainer(),
805 };
806
807 return MakeNWidgets(picker_type_widgets, nullptr);
808}
809
810void InvalidateAllPickerWindows()
811{
812 InvalidateWindowClassesData(WC_BUS_STATION, PickerWindow::PICKER_INVALIDATION_ALL);
813 InvalidateWindowClassesData(WC_TRUCK_STATION, PickerWindow::PICKER_INVALIDATION_ALL);
814 InvalidateWindowClassesData(WC_SELECT_STATION, PickerWindow::PICKER_INVALIDATION_ALL);
815 InvalidateWindowClassesData(WC_BUILD_WAYPOINT, PickerWindow::PICKER_INVALIDATION_ALL);
816 InvalidateWindowClassesData(WC_BUILD_OBJECT, PickerWindow::PICKER_INVALIDATION_ALL);
817 InvalidateWindowClassesData(WC_BUILD_HOUSE, PickerWindow::PICKER_INVALIDATION_ALL);
818}
backup_type.hpp
Class for backupping variables and making sure they are restored later.
SetBit
constexpr T SetBit(T &x, const uint8_t y)
Set a bit in a variable.
Definition bitmath_func.hpp:121
HasBit
constexpr bool HasBit(const T x, const uint8_t y)
Checks if a bit in a value is set.
Definition bitmath_func.hpp:103
ToggleBit
constexpr T ToggleBit(T &x, const uint8_t y)
Toggles a bit in a variable.
Definition bitmath_func.hpp:157
ClrBit
constexpr T ClrBit(T &x, const uint8_t y)
Clears a bit in a variable.
Definition bitmath_func.hpp:139
BaseBitSet::Test
constexpr bool Test(Tvalue_type value) const
Test if the value-th bit is set.
Definition base_bitset_type.hpp:141
EnumBitSet
Enum-as-bit-set wrapper.
Definition enum_type.hpp:177
GUIBadgeClasses
Definition newgrf_badge_gui.h:19
GUIList::Filter
bool Filter(FilterFunction *decide, F filter_data)
Filter the list.
Definition sortlist_type.h:342
GUIList::RebuildDone
void RebuildDone()
Notify the sortlist that the rebuild is done.
Definition sortlist_type.h:405
GUIList::SetFiltering
void SetFiltering(Filtering f)
Import filter conditions.
Definition sortlist_type.h:200
GUIList::SetListing
void SetListing(Listing l)
Import sort conditions.
Definition sortlist_type.h:148
GUIList::SetFilterState
void SetFilterState(bool state)
Enable or disable the filter.
Definition sortlist_type.h:326
GUIList::SetFilterFuncs
void SetFilterFuncs(std::span< FilterFunction *const > n_funcs)
Hand the filter function pointers to the GUIList.
Definition sortlist_type.h:365
GUIList::NeedRebuild
bool NeedRebuild() const
Check if a rebuild is needed.
Definition sortlist_type.h:387
GUIList::ForceRebuild
void ForceRebuild()
Force that a rebuild is needed.
Definition sortlist_type.h:395
GUIList::Sort
bool Sort(Comp compare)
Sort the list.
Definition sortlist_type.h:266
GUIList::SetSortFuncs
void SetSortFuncs(std::span< SortFunction *const > n_funcs)
Hand the sort function pointers to the GUIList.
Definition sortlist_type.h:293
NWidgetMatrix
Matrix container with implicitly equal sized (virtual) sub-widgets.
Definition widget_type.h:617
PickerCallbacks
Class for PickerClassWindow to collect information and retain state.
Definition picker_gui.h:39
PickerCallbacks::GetSelectedClass
virtual int GetSelectedClass() const =0
Get the index of the selected class.
PickerCallbacks::type_last_filtering
Filtering type_last_filtering
Default filtering of PickerTypeList.
Definition picker_gui.h:94
PickerCallbacks::GetPickerItem
virtual PickerItem GetPickerItem(int cls_id, int id) const =0
Get data about an item.
PickerCallbacks::ini_group
const std::string ini_group
Ini Group for saving favourites.
Definition picker_gui.h:96
PickerCallbacks::SetSelectedClass
virtual void SetSelectedClass(int id) const =0
Set the selected class.
PickerCallbacks::IsActive
virtual bool IsActive() const =0
Should picker class/type selection be enabled?
PickerCallbacks::GetTypeName
virtual StringID GetTypeName(int cls_id, int id) const =0
Get the item of a type.
PickerCallbacks::IsTypeAvailable
virtual bool IsTypeAvailable(int cls_id, int id) const =0
Test if an item is currently buildable.
PickerCallbacks::FillUsedItems
virtual void FillUsedItems(std::set< PickerItem > &items)=0
Fill a set with all items that are used by the current player.
PickerCallbacks::GetTypeTooltip
virtual StringID GetTypeTooltip() const =0
Get the tooltip string for the type grid.
PickerCallbacks::HasClassChoice
virtual bool HasClassChoice() const =0
Are there multiple classes to chose from?
PickerCallbacks::type_last_sorting
Listing type_last_sorting
Default sorting of PickerTypeList.
Definition picker_gui.h:93
PickerCallbacks::used
std::set< PickerItem > used
Set of items used in the current game by the current company.
Definition picker_gui.h:101
PickerCallbacks::GetClassTooltip
virtual StringID GetClassTooltip() const =0
Get the tooltip string for the class list.
PickerCallbacks::GetTypeCount
virtual int GetTypeCount(int cls_id) const =0
Get the number of types in a class.
PickerCallbacks::GetClassCount
virtual int GetClassCount() const =0
Get the number of classes.
PickerCallbacks::SetSelectedType
virtual void SetSelectedType(int id) const =0
Set the selected type.
PickerCallbacks::GetClassName
virtual StringID GetClassName(int id) const =0
Get the name of a class.
PickerCallbacks::preview_height
int preview_height
Previously adjusted height.
Definition picker_gui.h:99
PickerCallbacks::UpdateSavedItems
virtual std::set< PickerItem > UpdateSavedItems(const std::set< PickerItem > &src)=0
Update link between grfid/localidx and class_index/index in saved items.
PickerCallbacks::DrawType
virtual void DrawType(int x, int y, int cls_id, int id) const =0
Draw preview image of an item.
PickerCallbacks::GetTypeBadges
virtual std::span< const BadgeID > GetTypeBadges(int cls_id, int id) const =0
Get the item of a type.
PickerCallbacks::class_last_filtering
Filtering class_last_filtering
Default filtering of PickerClassList.
Definition picker_gui.h:91
PickerCallbacks::GetSelectedType
virtual int GetSelectedType() const =0
Get the selected type.
PickerCallbacks::mode
uint8_t mode
Bitmask of PickerFilterModes.
Definition picker_gui.h:97
PickerCallbacks::saved
std::set< PickerItem > saved
Set of saved favourite items.
Definition picker_gui.h:102
PickerCallbacks::class_last_sorting
Listing class_last_sorting
Default sorting of PickerClassList.
Definition picker_gui.h:90
PickerWindowBase
Base class for windows opened from a toolbar.
Definition window_gui.h:992
PickerWindowBase::Close
void Close(int data=0) override
Hide the window and all its child windows, and mark them for a later deletion.
Definition window.cpp:3602
PickerWindow::MAX_PREVIEW_HEIGHT
static constexpr int MAX_PREVIEW_HEIGHT
Maximum height of each preview button.
Definition picker_gui.h:182
PickerWindow::PREVIEW_WIDTH
static constexpr int PREVIEW_WIDTH
Width of each preview button.
Definition picker_gui.h:176
PickerWindow::Close
void Close(int data=0) override
Hide the window and all its child windows, and mark them for a later deletion.
Definition picker_gui.cpp:260
PickerWindow::preview_height
int preview_height
Height of preview images.
Definition picker_gui.h:188
PickerWindow::has_class_picker
bool has_class_picker
Set if this window has a class picker 'component'.
Definition picker_gui.h:186
PickerWindow::PREVIEW_HEIGHT
static constexpr int PREVIEW_HEIGHT
Height of each preview button.
Definition picker_gui.h:177
PickerWindow::DrawWidget
void DrawWidget(const Rect &r, WidgetID widget) const override
Draw the contents of a nested widget.
Definition picker_gui.cpp:308
PickerWindow::PickerInvalidation::Position
@ Position
Update scroll positions.
PickerWindow::PickerInvalidation::Class
@ Class
Refresh the class list.
PickerWindow::PickerInvalidation::Type
@ Type
Refresh the type list.
PickerWindow::PickerInvalidation::Validate
@ Validate
Validate selected item.
PickerWindow::PickerInvalidation::Filter
@ Filter
Update filter state.
PickerWindow::PREVIEW_LEFT
static constexpr int PREVIEW_LEFT
Offset from left edge to draw preview.
Definition picker_gui.h:178
PickerWindow::types
PickerTypeList types
List of types.
Definition picker_gui.h:224
PickerWindow::class_editbox
QueryString class_editbox
Filter editbox.
Definition picker_gui.h:218
PickerWindow::has_type_picker
bool has_type_picker
Set if this window has a type picker 'component'.
Definition picker_gui.h:187
PickerWindow::BuildPickerClassList
void BuildPickerClassList()
Builds the filter list of classes.
Definition picker_gui.cpp:571
PickerWindow::PFM_USED
@ PFM_USED
Show used types.
Definition picker_gui.h:161
PickerWindow::PFM_ALL
@ PFM_ALL
Show all classes.
Definition picker_gui.h:160
PickerWindow::PFM_SAVED
@ PFM_SAVED
Show saved types.
Definition picker_gui.h:162
PickerWindow::OnEditboxChanged
void OnEditboxChanged(WidgetID wid) override
The text in an editbox has been edited.
Definition picker_gui.cpp:546
PickerWindow::BuildPickerTypeList
void BuildPickerTypeList()
Builds the filter list of types.
Definition picker_gui.cpp:640
PickerWindow::OnDropdownSelect
void OnDropdownSelect(WidgetID widget, int index, int click_result) override
A dropdown option associated to this window has been selected.
Definition picker_gui.cpp:460
PickerWindow::OnResize
void OnResize() override
Called after the window got resized.
Definition picker_gui.cpp:368
PickerWindow::PREVIEW_BOTTOM
static constexpr int PREVIEW_BOTTOM
Offset from bottom edge to draw preview.
Definition picker_gui.h:179
PickerWindow::PCWHK_FOCUS_FILTER_BOX
@ PCWHK_FOCUS_FILTER_BOX
Focus the edit box for editing the filter string.
Definition picker_gui.h:205
PickerWindow::GetWidgetString
std::string GetWidgetString(WidgetID widget, StringID stringid) const override
Get the raw string for a widget.
Definition picker_gui.cpp:299
PickerWindow::OnClick
void OnClick(Point pt, WidgetID widget, int click_count) override
A click with the left mouse button has been made on the window.
Definition picker_gui.cpp:375
PickerWindow::OnInvalidateData
void OnInvalidateData(int data=0, bool gui_scope=true) override
Some data on this window has become invalid.
Definition picker_gui.cpp:492
PickerWindow::type_editbox
QueryString type_editbox
Filter editbox.
Definition picker_gui.h:226
PickerWindow::OnHotkey
EventState OnHotkey(int hotkey) override
A hotkey has been pressed.
Definition picker_gui.cpp:528
PickerWindow::OnInit
void OnInit() override
Notification that the nested widget tree gets initialized.
Definition picker_gui.cpp:251
PickerWindow::UpdateWidgetSize
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 picker_gui.cpp:266
PickerWindow::classes
PickerClassList classes
List of classes.
Definition picker_gui.h:216
PickerWindow::STEP_PREVIEW_HEIGHT
static constexpr int STEP_PREVIEW_HEIGHT
Step for decreasing or increase preview button height.
Definition picker_gui.h:181
Scrollbar::SetCount
void SetCount(size_t num)
Sets the number of elements in the list.
Definition widget_type.h:795
Scrollbar::SetCapacityFromWidget
void SetCapacityFromWidget(Window *w, WidgetID widget, int padding=0)
Set capacity of visible elements from the size and resize properties of a widget.
Definition widget.cpp:2527
Scrollbar::ScrollTowards
void ScrollTowards(size_type position)
Scroll towards the given position; if the item is visible nothing happens, otherwise it will be shown...
Definition widget_type.h:856
WidgetDimensions::scaled
static WidgetDimensions scaled
Widget dimensions scaled for current zoom level.
Definition window_gui.h:30
WidgetDimensions::fullbevel
RectPadding fullbevel
Always-scaled bevel thickness.
Definition window_gui.h:39
WidgetDimensions::unscaled
static const WidgetDimensions unscaled
Unscaled widget dimensions.
Definition window_gui.h:93
GetCompanyPalette
PaletteID GetCompanyPalette(CompanyID company)
Get the palette for recolouring with a company colour.
Definition company_cmd.cpp:164
_local_company
CompanyID _local_company
Company controlled by the human player at this client. Can also be COMPANY_SPECTATOR.
Definition company_cmd.cpp:55
company_func.h
Functions related to companies.
ShowDropDownList
void ShowDropDownList(Window *w, DropDownList &&list, int selected, WidgetID button, uint width, DropDownOptions options)
Show a drop down list.
Definition dropdown.cpp:418
DropDownOption::Persist
@ Persist
Set if this dropdown should stay open after an option is selected.
GetCharacterHeight
int GetCharacterHeight(FontSize size)
Get height of a character for a given font size.
Definition fontcache.cpp:87
GetSpriteSize
Dimension GetSpriteSize(SpriteID sprid, Point *offset, ZoomLevel zoom)
Get the size of a sprite.
Definition gfx.cpp:968
DrawString
int DrawString(int left, int right, int top, std::string_view str, TextColour colour, StringAlignment align, bool underline, FontSize fontsize)
Draw string, possibly truncated to make it fit in its allocated space.
Definition gfx.cpp:668
_ctrl_pressed
bool _ctrl_pressed
Is Ctrl pressed?
Definition gfx.cpp:38
DrawSprite
void DrawSprite(SpriteID img, PaletteID pal, int x, int y, const SubSprite *sub, ZoomLevel zoom)
Draw a sprite, not in a viewport.
Definition gfx.cpp:1034
GfxFillRect
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:115
FillDrawPixelInfo
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:1568
FS_NORMAL
@ FS_NORMAL
Index of the normal font in the font tables.
Definition gfx_type.h:249
SA_CENTER
@ SA_CENTER
Center both horizontally and vertically.
Definition gfx_type.h:398
PaletteID
uint32_t PaletteID
The number of the palette.
Definition gfx_type.h:18
FILLRECT_CHECKER
@ FILLRECT_CHECKER
Draw only every second pixel, used for greying-out.
Definition gfx_type.h:346
SetMatrixDataTip
constexpr NWidgetPart SetMatrixDataTip(uint32_t cols, uint32_t rows, StringID tip={})
Widget part function for setting the data and tooltip of WWT_MATRIX widgets.
Definition widget_type.h:1311
SetFill
constexpr NWidgetPart SetFill(uint16_t fill_x, uint16_t fill_y)
Widget part function for setting filling.
Definition widget_type.h:1222
SetSpriteTip
constexpr NWidgetPart SetSpriteTip(SpriteID sprite, StringID tip={})
Widget part function for setting the sprite and tooltip.
Definition widget_type.h:1254
SetPIP
constexpr NWidgetPart SetPIP(uint8_t pre, uint8_t inter, uint8_t post)
Widget part function for setting a pre/inter/post spaces.
Definition widget_type.h:1378
SetScrollbar
constexpr NWidgetPart SetScrollbar(WidgetID index)
Attach a scrollbar to a widget.
Definition widget_type.h:1402
SetPadding
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.
Definition widget_type.h:1335
SetStringTip
constexpr NWidgetPart SetStringTip(StringID string, StringID tip={})
Widget part function for setting the string and tooltip.
Definition widget_type.h:1243
SetAspect
constexpr NWidgetPart SetAspect(float ratio, AspectFlags flags=AspectFlag::ResizeX)
Widget part function for setting the aspect ratio.
Definition widget_type.h:1413
SetMinimalSize
constexpr NWidgetPart SetMinimalSize(int16_t x, int16_t y)
Widget part function for setting the minimal size.
Definition widget_type.h:1159
MakeNWidgets
std::unique_ptr< NWidgetBase > MakeNWidgets(std::span< const NWidgetPart > nwid_parts, std::unique_ptr< NWidgetBase > &&container)
Construct a nested widget tree from an array of parts.
Definition widget.cpp:3410
EndContainer
constexpr NWidgetPart EndContainer()
Widget part function for denoting the end of a container (horizontal, vertical, WWT_FRAME,...
Definition widget_type.h:1232
NWidget
constexpr NWidgetPart NWidget(WidgetType tp, Colours col, WidgetID idx=INVALID_WIDGET)
Widget part function for starting a new 'real' widget.
Definition widget_type.h:1427
SetMinimalTextLines
constexpr NWidgetPart SetMinimalTextLines(uint8_t lines, uint8_t spacing, FontSize size=FS_NORMAL)
Widget part function for setting the minimal text lines.
Definition widget_type.h:1190
SetResize
constexpr NWidgetPart SetResize(int16_t dx, int16_t dy)
Widget part function for setting the resize step.
Definition widget_type.h:1148
gui.h
GUI functions that shouldn't be here.
hotkeys.h
Hotkey related functions.
ini_type.h
Types related to reading/writing '*.ini' files.
IsInsideMM
constexpr bool IsInsideMM(const size_t x, const size_t min, const size_t max) noexcept
Checks if a value is in an interval.
Definition math_func.hpp:267
GrfSpecFeature
GrfSpecFeature
Definition newgrf.h:68
newgrf_badge.h
Functions related to NewGRF badges.
newgrf_badge_config.h
Functions related to NewGRF badge configuration.
newgrf_badge_gui.h
GUI functions related to NewGRF badges.
GetColourGradient
PixelColour GetColourGradient(Colours colour, ColourShade shade)
Get colour gradient palette index.
Definition palette.cpp:388
_class_filter_funcs
static const std::initializer_list< PickerClassList::FilterFunction *const > _class_filter_funcs
Filter functions of the PickerClassList.
Definition picker_gui.cpp:163
TypeIDSorter
static bool TypeIDSorter(PickerItem const &a, PickerItem const &b)
Sort types by id.
Definition picker_gui.cpp:143
PickerLoadConfig
static void PickerLoadConfig(const IniFile &ini, PickerCallbacks &callbacks)
Load favourites of a picker from config.
Definition picker_gui.cpp:65
_type_sorter_funcs
static const std::initializer_list< PickerTypeList::SortFunction *const > _type_sorter_funcs
Sort functions of the PickerTypeList.
Definition picker_gui.cpp:164
ClassIDSorter
static bool ClassIDSorter(int const &a, int const &b)
Sort classes by id.
Definition picker_gui.cpp:129
_class_sorter_funcs
static const std::initializer_list< PickerClassList::SortFunction *const > _class_sorter_funcs
Sort functions of the PickerClassList.
Definition picker_gui.cpp:162
MakePickerClassWidgets
std::unique_ptr< NWidgetBase > MakePickerClassWidgets()
Create nested widgets for the class picker widgets.
Definition picker_gui.cpp:745
TypeTagNameFilter
static bool TypeTagNameFilter(PickerItem const *item, PickerFilterData &filter)
Filter types by class name.
Definition picker_gui.cpp:151
_type_filter_funcs
static const std::initializer_list< PickerTypeList::FilterFunction *const > _type_filter_funcs
Filter functions of the PickerTypeList.
Definition picker_gui.cpp:165
PickerSaveConfig
static void PickerSaveConfig(IniFile &ini, const PickerCallbacks &callbacks)
Save favourites of a picker to config.
Definition picker_gui.cpp:99
MakePickerTypeWidgets
std::unique_ptr< NWidgetBase > MakePickerTypeWidgets()
Create nested widgets for the type picker widgets.
Definition picker_gui.cpp:768
ClassTagNameFilter
static bool ClassTagNameFilter(int const *item, PickerFilterData &filter)
Filter classes by class name.
Definition picker_gui.cpp:135
picker_gui.h
Functions/types etc.
picker_widget.h
Types related to the picker widgets.
WID_PW_MODE_SAVED
@ WID_PW_MODE_SAVED
Toggle showing only saved types.
Definition picker_widget.h:26
WID_PW_CLASS_FILTER
@ WID_PW_CLASS_FILTER
Editbox filter.
Definition picker_widget.h:18
WID_PW_TYPE_SCROLL
@ WID_PW_TYPE_SCROLL
Scrollbar for the matrix.
Definition picker_widget.h:31
WID_PW_EXPAND
@ WID_PW_EXPAND
Button to increase preview image height.
Definition picker_widget.h:28
WID_PW_CONFIGURE_BADGES
@ WID_PW_CONFIGURE_BADGES
Button to configure badges.
Definition picker_widget.h:34
WID_PW_TYPE_ITEM
@ WID_PW_TYPE_ITEM
A single item.
Definition picker_widget.h:30
WID_PW_CLASS_LIST
@ WID_PW_CLASS_LIST
List of classes.
Definition picker_widget.h:19
WID_PW_TYPE_FILTER
@ WID_PW_TYPE_FILTER
Text filter.
Definition picker_widget.h:23
WID_PW_MODE_USED
@ WID_PW_MODE_USED
Toggle showing only used types.
Definition picker_widget.h:25
WID_PW_BADGE_FILTER
@ WID_PW_BADGE_FILTER
Container for dropdown badge filters.
Definition picker_widget.h:35
WID_PW_TYPE_MATRIX
@ WID_PW_TYPE_MATRIX
Matrix with items.
Definition picker_widget.h:29
WID_PW_CLASS_SEL
@ WID_PW_CLASS_SEL
Stack to hide the class picker.
Definition picker_widget.h:17
WID_PW_MODE_ALL
@ WID_PW_MODE_ALL
Toggle "Show all" filter mode.
Definition picker_widget.h:24
WID_PW_CLASS_SCROLL
@ WID_PW_CLASS_SCROLL
Scrollbar for list of classes.
Definition picker_widget.h:20
WID_PW_SHRINK
@ WID_PW_SHRINK
Button to reduce preview image height.
Definition picker_widget.h:27
WID_PW_TYPE_SEL
@ WID_PW_TYPE_SEL
Stack to hide the type picker.
Definition picker_widget.h:22
WID_PW_TYPE_NAME
@ WID_PW_TYPE_NAME
Name of selected item.
Definition picker_widget.h:32
WID_PW_TYPE_RESIZE
@ WID_PW_TYPE_RESIZE
Type resize handle.
Definition picker_widget.h:33
querystring_gui.h
Base for the GUIs that have an edit box in them.
safeguards.h
A number of safeguards to prevent using unsafe methods.
settings_type.h
Types related to global configuration settings.
sortlist_type.h
Base types for having sorted lists in GUIs.
SndClickBeep
void SndClickBeep()
Play a beep sound for a click event if enabled in settings.
Definition sound.cpp:253
sound_func.h
Functions related to sound.
sound_type.h
Types related to sounds.
sprites.h
This file contains all sprite-related enums and defines.
stdafx.h
Definition of base types and functions in a cross-platform compatible way.
ConvertHexToBytes
bool ConvertHexToBytes(std::string_view hex, std::span< uint8_t > bytes)
Convert a hex-string to a byte-array, while validating it was actually hex.
Definition string.cpp:570
string_func.h
Functions related to low-level strings.
stringfilter_type.h
Searching and filtering using a stringterm.
GetString
std::string GetString(StringID string)
Resolve the given StringID into a std::string with formatting but no parameters.
Definition strings.cpp:424
strings_func.h
Functions related to OTTD's strings.
StringID
uint32_t StringID
Numeric value that represents a string, independent of the selected language.
Definition strings_type.h:19
INVALID_STRING_ID
static const StringID INVALID_STRING_ID
Constant representing an invalid string (16bit in case it is used in savegames)
Definition strings_type.h:20
MAX_CHAR_LENGTH
static const int MAX_CHAR_LENGTH
Max. length of UTF-8 encoded unicode character.
Definition strings_type.h:21
AutoRestoreBackup
Class to backup a specific variable and restore it upon destruction of this object to prevent stack v...
Definition backup_type.hpp:150
Coord2D< int >
Coord2D::y
T y
Y coordinate.
Definition geometry_type.hpp:35
Dimension
Dimensions (a width and height) of a rectangle in 2D.
Definition geometry_type.hpp:56
DrawPixelInfo
Data about how and where to blit pixels.
Definition gfx_type.h:157
IniFile
Ini file that supports both loading and saving.
Definition ini_type.h:86
IniGroup
A group within an ini file.
Definition ini_type.h:34
IniGroup::Clear
void Clear()
Clear all items in the group.
Definition ini_load.cpp:97
IniGroup::CreateItem
IniItem & CreateItem(std::string_view name)
Create an item with the given name.
Definition ini_load.cpp:80
IniGroup::items
std::list< IniItem > items
all items in the group
Definition ini_type.h:35
IniItem
A single "line" in an ini file.
Definition ini_type.h:23
IniLoadFile::GetGroup
const IniGroup * GetGroup(std::string_view name) const
Get the group with the given name.
Definition ini_load.cpp:118
IniLoadFile::GetOrCreateGroup
IniGroup & GetOrCreateGroup(std::string_view name)
Get the group with the given name, and if it doesn't exist create a new group.
Definition ini_load.cpp:146
PickerFilterData
Definition picker_gui.h:148
PickerFilterData::callbacks
const PickerCallbacks * callbacks
Callbacks for filter functions to access to callbacks.
Definition picker_gui.h:149
PickerItem
Definition picker_gui.h:25
QueryString::cancel_button
int cancel_button
Widget button of parent window to simulate when pressing CANCEL in OSK.
Definition querystring_gui.h:28
QueryString::ACTION_CLEAR
static const int ACTION_CLEAR
Clear editbox.
Definition querystring_gui.h:24
RectPadding::Horizontal
constexpr uint Horizontal() const
Get total horizontal padding of RectPadding.
Definition geometry_type.hpp:89
RectPadding::Vertical
constexpr uint Vertical() const
Get total vertical padding of RectPadding.
Definition geometry_type.hpp:95
Rect
Specification of a rectangle with absolute coordinates of all edges.
Definition geometry_type.hpp:101
Rect::Width
int Width() const
Get width of Rect.
Definition geometry_type.hpp:111
Rect::Shrink
Rect Shrink(int s) const
Copy and shrink Rect by s pixels.
Definition geometry_type.hpp:124
Rect::Height
int Height() const
Get height of Rect.
Definition geometry_type.hpp:117
StringFilter::IsEmpty
bool IsEmpty() const
Check whether any filter words were entered.
Definition stringfilter_type.h:57
StringFilter::SetFilterTerm
void SetFilterTerm(std::string_view str)
Set the term to filter on.
Definition stringfilter.cpp:29
StringFilter::ResetState
void ResetState()
Reset the matching state to process a new item.
Definition stringfilter.cpp:80
StringFilter::GetState
bool GetState() const
Get the matching state of the current item.
Definition stringfilter_type.h:67
StrongType::Typedef< uint32_t, struct BadgeIDTag, StrongType::Compare >
Textbuf::GetText
std::string_view GetText() const
Get the current text.
Definition textbuf.cpp:284
WindowDesc
High level window description.
Definition window_gui.h:168
Window
Data structure for an opened window.
Definition window_gui.h:274
Window::ReInit
void ReInit(int rx=0, int ry=0, bool reposition=false)
Re-initialize a window, and optionally change its size.
Definition window.cpp:980
Window::FinishInitNested
void FinishInitNested(WindowNumber window_number=0)
Perform the second part of the initialization of a nested widget tree.
Definition window.cpp:1809
Window::querystrings
std::map< WidgetID, QueryString * > querystrings
QueryString associated to WWT_EDITBOX widgets.
Definition window_gui.h:321
Window::GetWidgetString
virtual std::string GetWidgetString(WidgetID widget, StringID stringid) const
Get the raw string for a widget.
Definition window.cpp:506
Window::CloseChildWindows
void CloseChildWindows(WindowClass wc=WC_INVALID) const
Close all children a window might have in a head-recursive manner.
Definition window.cpp:1077
Window::resize
ResizeInfo resize
Resize information.
Definition window_gui.h:315
Window::CreateNestedTree
void CreateNestedTree()
Perform the first part of the initialization of a nested widget tree.
Definition window.cpp:1799
Window::SetFocusedWidget
bool SetFocusedWidget(WidgetID widget_index)
Set focus within this window to the given widget.
Definition window.cpp:487
Window::IsWidgetDisabled
bool IsWidgetDisabled(WidgetID widget_index) const
Gets the enabled/disabled status of a widget.
Definition window_gui.h:411
Window::SetWidgetLoweredState
void SetWidgetLoweredState(WidgetID widget_index, bool lowered_stat)
Sets the lowered/raised status of a widget.
Definition window_gui.h:442
Window::nested_focus
const NWidgetCore * nested_focus
Currently focused nested widget, or nullptr if no nested widget has focus.
Definition window_gui.h:320
Window::widget_lookup
WidgetLookup widget_lookup
Indexed access to the nested widget tree. Do not access directly, use Window::GetWidget() instead.
Definition window_gui.h:323
Window::GetScrollbar
const Scrollbar * GetScrollbar(WidgetID widnum) const
Return the Scrollbar to a widget index.
Definition window.cpp:315
Window::SetWidgetDisabledState
void SetWidgetDisabledState(WidgetID widget_index, bool disab_stat)
Sets the enabled/disabled status of a widget.
Definition window_gui.h:382
Window::nested_root
std::unique_ptr< NWidgetBase > nested_root
Root of the nested tree.
Definition window_gui.h:322
Window::width
int width
width of the window (number of pixels to the right in x direction)
Definition window_gui.h:312
Window::window_number
WindowNumber window_number
Window number within the window class.
Definition window_gui.h:303
ScaleGUITrad
static RectPadding ScaleGUITrad(const RectPadding &r)
Scale a RectPadding to GUI zoom level.
Definition widget.cpp:49
widget_type.h
Definitions about widgets.
WWT_PUSHTXTBTN
@ WWT_PUSHTXTBTN
Normal push-button (no toggle button) with text caption.
Definition widget_type.h:105
WWT_IMGBTN
@ WWT_IMGBTN
(Toggle) Button with image
Definition widget_type.h:41
WWT_EDITBOX
@ WWT_EDITBOX
a textbox for typing
Definition widget_type.h:62
NWID_HORIZONTAL
@ NWID_HORIZONTAL
Horizontal container.
Definition widget_type.h:66
WWT_TEXTBTN
@ WWT_TEXTBTN
(Toggle) Button with text
Definition widget_type.h:44
WWT_PANEL
@ WWT_PANEL
Simple depressed panel.
Definition widget_type.h:39
WWT_MATRIX
@ WWT_MATRIX
Grid of rows and columns.
Definition widget_type.h:50
NWID_VSCROLLBAR
@ NWID_VSCROLLBAR
Vertical scrollbar.
Definition widget_type.h:76
NWID_VERTICAL
@ NWID_VERTICAL
Vertical container.
Definition widget_type.h:68
WWT_EMPTY
@ WWT_EMPTY
Empty widget, place holder to reserve space in widget tree.
Definition widget_type.h:37
WWT_RESIZEBOX
@ WWT_RESIZEBOX
Resize box (normally at bottom-right of a window)
Definition widget_type.h:59
NWID_MATRIX
@ NWID_MATRIX
Matrix container.
Definition widget_type.h:69
NWID_SELECTION
@ NWID_SELECTION
Stacked widgets, only one visible at a time (eg in a panel with tabs).
Definition widget_type.h:71
SZSP_HORIZONTAL
@ SZSP_HORIZONTAL
Display plane with zero size vertically, and filling and resizing horizontally.
Definition widget_type.h:508
SZSP_VERTICAL
@ SZSP_VERTICAL
Display plane with zero size horizontally, and filling and resizing vertically.
Definition widget_type.h:507
NWidContainerFlag
NWidContainerFlag
Nested widget container flags,.
Definition widget_type.h:543
EqualSize
@ EqualSize
Containers should keep all their (resizing) children equally large.
Definition widget_type.h:544
CloseWindowById
void CloseWindowById(WindowClass cls, WindowNumber number, bool force, int data)
Close a window by its class and window number (if it is open).
Definition window.cpp:1195
SetFocusedWindow
void SetFocusedWindow(Window *w)
Set the window that has the focus.
Definition window.cpp:423
InvalidateWindowClassesData
void InvalidateWindowClassesData(WindowClass cls, int data, bool gui_scope)
Mark window data of all windows of a given class as invalid (in need of re-computing) Note that by de...
Definition window.cpp:3314
window_func.h
Window functions not directly related to making/drawing windows.
window_gui.h
Functions, definitions and such used only by the GUI.
window_type.h
Types related to windows.
WidgetID
int WidgetID
Widget ID.
Definition window_type.h:20
EventState
EventState
State of handling an event.
Definition window_type.h:780
ES_HANDLED
@ ES_HANDLED
The passed event is handled.
Definition window_type.h:781
ES_NOT_HANDLED
@ ES_NOT_HANDLED
The passed event is not handled.
Definition window_type.h:782
WC_BUILD_OBJECT
@ WC_BUILD_OBJECT
Build object; Window numbers:
Definition window_type.h:381
WC_BUILD_HOUSE
@ WC_BUILD_HOUSE
Build house; Window numbers:
Definition window_type.h:387
WC_SELECT_STATION
@ WC_SELECT_STATION
Select station (when joining stations); Window numbers:
Definition window_type.h:247
WC_TRUCK_STATION
@ WC_TRUCK_STATION
Build truck station; Window numbers:
Definition window_type.h:420
WC_DROPDOWN_MENU
@ WC_DROPDOWN_MENU
Drop down menu; Window numbers:
Definition window_type.h:161
WC_BUS_STATION
@ WC_BUS_STATION
Build bus station; Window numbers:
Definition window_type.h:414
WC_BUILD_WAYPOINT
@ WC_BUILD_WAYPOINT
Build waypoint; Window numbers:
Definition window_type.h:434
zoom_func.h
Functions related to zooming.
ScaleSpriteTrad
int ScaleSpriteTrad(int value)
Scale traditional pixel dimensions to GUI zoom level, for drawing sprites.
Definition zoom_func.h:107