OpenTTD Source 20260621-master-g720d10536d
picker_gui.h
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#ifndef PICKER_GUI_H
11#define PICKER_GUI_H
12
13#include "newgrf_badge.h"
14#include "newgrf_badge_gui.h"
15#include "querystring_gui.h"
16#include "sortlist_type.h"
17#include "stringfilter_type.h"
18#include "strings_type.h"
19#include "timer/timer.h"
21#include "timer/timer_window.h"
22#include "window_gui.h"
23#include "window_type.h"
24
26enum class PickerFilterMode : uint8_t {
30};
31
34
35struct PickerItem {
36 uint32_t grfid;
37 uint16_t local_id;
38 int class_index;
39 int index;
40
41 inline auto operator<=>(const PickerItem &other) const
42 {
43 if (auto cmp = this->grfid <=> other.grfid; cmp != 0) return cmp;
44 return this->local_id <=> other.local_id;
45 }
46};
47
49class PickerCallbacks {
50public:
51 explicit PickerCallbacks(const std::string &ini_group);
53 virtual ~PickerCallbacks();
54
56 virtual void Close([[maybe_unused]] int data) { }
57
62 virtual GrfSpecFeature GetFeature() const = 0;
67 virtual bool IsActive() const = 0;
72 virtual bool HasClassChoice() const = 0;
73
74 /* Class callbacks */
79 virtual StringID GetClassTooltip() const = 0;
85 virtual int GetClassCount() const = 0;
90 virtual int GetSelectedClass() const = 0;
95 virtual void SetSelectedClass(int id) const = 0;
101 virtual StringID GetClassName(int id) const = 0;
102
103 /* Type callbacks */
108 virtual StringID GetTypeTooltip() const = 0;
115 virtual int GetTypeCount(int cls_id) const = 0;
120 virtual int GetSelectedType() const = 0;
125 virtual void SetSelectedType(int id) const = 0;
132 virtual PickerItem GetPickerItem(int cls_id, int id) const = 0;
139 virtual StringID GetTypeName(int cls_id, int id) const = 0;
146 virtual std::span<const BadgeID> GetTypeBadges(int cls_id, int id) const = 0;
153 virtual bool IsTypeAvailable(int cls_id, int id) const = 0;
161 virtual void DrawType(int x, int y, int cls_id, int id) const = 0;
162
163 /* Collection Callbacks */
168 virtual StringID GetCollectionTooltip() const = 0;
169
174 virtual void FillUsedItems(std::set<PickerItem> &items) = 0;
180 virtual std::map<std::string, std::set<PickerItem>> UpdateSavedItems(const std::map<std::string, std::set<PickerItem>> &src) = 0;
186 inline std::set<std::string> InitializeInactiveCollections(const std::map<std::string, std::set<PickerItem>> collections)
187 {
188 std::set<std::string> inactive;
189
190 for (const auto &collection : collections) {
191 if ((collection.second.size() == 1 && collection.second.contains({})) || collection.first == "") continue;
192 for (const PickerItem &item : collection.second) {
193 if (item.class_index == -1 || item.index == -1) {
194 inactive.emplace(collection.first);
195 break;
196 }
197 if (GetTypeName(item.class_index, item.index) == INVALID_STRING_ID) {
198 inactive.emplace(collection.first);
199 break;
200 }
201 }
202 }
203 return inactive;
204 }
205
208
209 Listing type_last_sorting = { false, 0 };
211
213
214 const std::string ini_group;
216 bool rename_collection = false;
217 std::string sel_collection;
218 std::string edit_collection;
219 std::set<std::string> rm_collections;
220
222
223 std::set<PickerItem> used;
224 std::map<std::string, std::set<PickerItem>> saved;
225};
226
228template <typename T>
229class PickerCallbacksNewGRFClass : public PickerCallbacks {
230public:
235 explicit PickerCallbacksNewGRFClass(const std::string &ini_group) : PickerCallbacks(ini_group) {}
236
242 inline typename T::index_type GetClassIndex(int cls_id) const { return static_cast<typename T::index_type>(cls_id); }
243
249 inline const T *GetClass(int cls_id) const { return T::Get(this->GetClassIndex(cls_id)); }
250
257 inline const typename T::spec_type *GetSpec(int cls_id, int id) const { return this->GetClass(cls_id)->GetSpec(id); }
258
259 bool HasClassChoice() const override { return T::GetUIClassCount() > 1; }
260
261 int GetClassCount() const override { return T::GetClassCount(); }
262 int GetTypeCount(int cls_id) const override { return this->GetClass(cls_id)->GetSpecCount(); }
263
271 PickerItem GetPickerItem(const typename T::spec_type *spec, int cls_id = -1, int id = -1) const
272 {
273 if (spec == nullptr) return {0, 0, cls_id, id};
274 return {spec->grf_prop.grfid, spec->grf_prop.local_id, spec->class_index.base(), spec->index};
275 }
276
283 PickerItem GetPickerItem(int cls_id, int id) const override
284 {
285 return GetPickerItem(GetClass(cls_id)->GetSpec(id), cls_id, id);
286 }
287
288 std::map<std::string, std::set<PickerItem>> UpdateSavedItems(const std::map<std::string, std::set<PickerItem>> &src) override
289 {
290 if (src.empty()) return {};
291
292 std::map<std::string, std::set<PickerItem>> dst;
293 for (auto it = src.begin(); it != src.end(); it++) {
294 if (it->second.empty() || (it->second.size() == 1 && it->second.contains({}))) {
295 dst[it->first];
296 continue;
297 }
298
299 for (const auto &item : it->second) {
300 const auto *spec = T::GetByGrf(item.grfid, item.local_id);
301 if (spec == nullptr) {
302 dst[it->first].emplace(item.grfid, item.local_id, -1, -1);
303 } else {
304 dst[it->first].emplace(GetPickerItem(spec));
305 }
306 }
307 }
308 return dst;
309 }
310};
311
314 std::optional<BadgeTextFilter> btf;
315 std::optional<BadgeDropdownFilter> bdf;
316};
317
321
322class PickerWindow : public PickerWindowBase {
323public:
333
336
338
339 static constexpr int PREVIEW_WIDTH = 64;
340 static constexpr int PREVIEW_HEIGHT = 48;
341 static constexpr int PREVIEW_LEFT = 31;
342 static constexpr int PREVIEW_BOTTOM = 31;
343
344 static constexpr int STEP_PREVIEW_HEIGHT = 16;
345 static constexpr int MAX_PREVIEW_HEIGHT = PREVIEW_HEIGHT * 3;
346
347 static constexpr uint EDITBOX_MAX_SIZE = 16;
348
349 bool has_class_picker = false;
350 bool has_type_picker = false;
353 std::set<std::string> inactive;
354
355 PickerWindow(WindowDesc &desc, Window *parent, int window_number, PickerCallbacks &callbacks);
356 void OnInit() override;
357 void Close(int data = 0) override;
358 void UpdateWidgetSize(WidgetID widget, Dimension &size, const Dimension &padding, Dimension &fill, Dimension &resize) override;
359 std::string GetWidgetString(WidgetID widget, StringID stringid) const override;
360 DropDownList BuildCollectionDropDownList();
361 void DrawWidget(const Rect &r, WidgetID widget) const override;
362 void OnDropdownSelect(WidgetID widget, int index, int click_result) override;
363 void OnResize() override;
364 void static DeletePickerCollectionCallback(Window *win, bool confirmed);
365 void OnClick(Point pt, WidgetID widget, int click_count) override;
366 void OnQueryTextFinished(std::optional<std::string> str) override;
367 void OnInvalidateData(int data = 0, bool gui_scope = true) override;
368 EventState OnHotkey(int hotkey) override;
369 void OnEditboxChanged(WidgetID wid) override;
370
375
376 void InvalidateData(PickerInvalidations data) { this->Window::InvalidateData(data.base()); }
377
378protected:
379 void ConstructWindow();
380
381 PickerCallbacks &callbacks;
382
383private:
385 PickerFilterData class_string_filter;
387
389 void EnsureSelectedClassIsValid();
390 void EnsureSelectedClassIsVisible();
391
393 PickerFilterData type_string_filter;
395
396 void RefreshUsedTypeList();
397 void BuildPickerTypeList();
398 void EnsureSelectedTypeIsValid();
399 void EnsureSelectedTypeIsVisible();
400
402
404
405 GUIBadgeClasses badge_classes;
406 std::pair<WidgetID, WidgetID> badge_filters{};
407 BadgeFilterChoices badge_filter_choices{};
408
409 const IntervalTimer<TimerGameCalendar> yearly_interval = {{TimerGameCalendar::Trigger::Year, TimerGameCalendar::Priority::None}, [this](auto) {
410 this->SetDirty();
411 }};
412
413 const IntervalTimer<TimerWindow> refresh_interval = {std::chrono::seconds(3), [this](auto) {
414 RefreshUsedTypeList();
415 }};
416};
417
418class NWidgetBase;
419std::unique_ptr<NWidgetBase> MakePickerClassWidgets();
420std::unique_ptr<NWidgetBase> MakePickerTypeWidgets();
421
422#endif /* PICKER_GUI_H */
Enum-as-bit-set wrapper.
List template of 'things' T to sort in a GUI.
Baseclass for nested widgets.
std::map< std::string, std::set< PickerItem > > UpdateSavedItems(const std::map< std::string, std::set< PickerItem > > &src) override
Update link between grfid/localidx and class_index/index in saved items.
Definition picker_gui.h:288
PickerItem GetPickerItem(int cls_id, int id) const override
Get the PickerItem for the given index with the class.
Definition picker_gui.h:283
int GetClassCount() const override
Get the number of classes.
Definition picker_gui.h:261
T::index_type GetClassIndex(int cls_id) const
Casts the given index to the right type.
Definition picker_gui.h:242
const T * GetClass(int cls_id) const
Get the class with the given index.
Definition picker_gui.h:249
int GetTypeCount(int cls_id) const override
Get the number of types in a class.
Definition picker_gui.h:262
bool HasClassChoice() const override
Are there multiple classes to chose from?
Definition picker_gui.h:259
PickerItem GetPickerItem(const typename T::spec_type *spec, int cls_id=-1, int id=-1) const
Get the PickerItem for the given spec.
Definition picker_gui.h:271
PickerCallbacksNewGRFClass(const std::string &ini_group)
Create the callback instance.
Definition picker_gui.h:235
const T::spec_type * GetSpec(int cls_id, int id) const
Get the spec of an object within a class.
Definition picker_gui.h:257
Class for PickerClassWindow to collect information and retain state.
Definition picker_gui.h:49
std::set< std::string > InitializeInactiveCollections(const std::map< std::string, std::set< PickerItem > > collections)
Initialize the list of active collections for sorting purposes.
Definition picker_gui.h:186
virtual ~PickerCallbacks()
Ensure the destructor of the sub classes are called as well.
virtual int GetSelectedClass() const =0
Get the index of the selected class.
std::string edit_collection
Collection to rename or delete.
Definition picker_gui.h:218
Filtering type_last_filtering
Default filtering of PickerTypeList.
Definition picker_gui.h:210
virtual PickerItem GetPickerItem(int cls_id, int id) const =0
Get data about an item.
const std::string ini_group
Ini Group for saving favourites.
Definition picker_gui.h:214
bool rename_collection
Are we renaming a collection?
Definition picker_gui.h:216
Listing collection_last_sorting
Default sorting of PickerCollectionList.
Definition picker_gui.h:212
virtual void SetSelectedClass(int id) const =0
Set the selected class.
std::string sel_collection
Currently selected collection of saved items.
Definition picker_gui.h:217
virtual bool IsActive() const =0
Should picker class/type selection be enabled?
virtual StringID GetTypeName(int cls_id, int id) const =0
Get the item name of a type.
virtual bool IsTypeAvailable(int cls_id, int id) const =0
Test if an item is currently buildable.
virtual void FillUsedItems(std::set< PickerItem > &items)=0
Fill a set with all items that are used by the current player.
virtual StringID GetTypeTooltip() const =0
Get the tooltip string for the type grid.
virtual bool HasClassChoice() const =0
Are there multiple classes to chose from?
Listing type_last_sorting
Default sorting of PickerTypeList.
Definition picker_gui.h:209
virtual StringID GetCollectionTooltip() const =0
Get the tooltip string for the collection list.
std::set< PickerItem > used
Set of items used in the current game by the current company.
Definition picker_gui.h:223
virtual StringID GetClassTooltip() const =0
Get the tooltip string for the class list.
virtual int GetTypeCount(int cls_id) const =0
Get the number of types in a class.
virtual int GetClassCount() const =0
Get the number of classes.
virtual GrfSpecFeature GetFeature() const =0
NewGRF feature this picker is for.
virtual void SetSelectedType(int id) const =0
Set the selected type.
virtual StringID GetClassName(int id) const =0
Get the name of a class.
int preview_height
Previously adjusted height.
Definition picker_gui.h:221
PickerFilterModes mode
Bitmask of PickerFilterModes.
Definition picker_gui.h:215
virtual void DrawType(int x, int y, int cls_id, int id) const =0
Draw preview image of an item.
virtual std::span< const BadgeID > GetTypeBadges(int cls_id, int id) const =0
Get the item's badges of a type.
virtual std::map< std::string, std::set< PickerItem > > UpdateSavedItems(const std::map< std::string, std::set< PickerItem > > &src)=0
Update link between grfid/localidx and class_index/index in saved items.
Filtering class_last_filtering
Default filtering of PickerClassList.
Definition picker_gui.h:207
virtual void Close(int data)
Hide the window and all its child windows, and mark them for a later deletion.
Definition picker_gui.h:56
std::set< std::string > rm_collections
Set of removed or renamed collections for updating ini file.
Definition picker_gui.h:219
std::map< std::string, std::set< PickerItem > > saved
Set of saved collections of items.
Definition picker_gui.h:224
virtual int GetSelectedType() const =0
Get the selected type.
Listing class_last_sorting
Default sorting of PickerClassList.
Definition picker_gui.h:206
static constexpr int MAX_PREVIEW_HEIGHT
Maximum height of each preview button.
Definition picker_gui.h:345
static constexpr int PREVIEW_WIDTH
Width of each preview button.
Definition picker_gui.h:339
void Close(int data=0) override
Hide the window and all its child windows, and mark them for a later deletion.
int preview_height
Height of preview images.
Definition picker_gui.h:352
bool has_class_picker
Set if this window has a class picker 'component'.
Definition picker_gui.h:349
static constexpr int PREVIEW_HEIGHT
Height of each preview button.
Definition picker_gui.h:340
static constexpr uint EDITBOX_MAX_SIZE
The maximum number of characters for the filter edit box.
Definition picker_gui.h:347
void DrawWidget(const Rect &r, WidgetID widget) const override
Draw the contents of a nested widget.
PickerInvalidation
The things of a picker that can be invalidated.
Definition picker_gui.h:325
@ Position
Update scroll positions.
Definition picker_gui.h:329
@ Class
Refresh the class list.
Definition picker_gui.h:326
@ Type
Refresh the type list.
Definition picker_gui.h:327
@ Validate
Validate selected item.
Definition picker_gui.h:330
@ Collection
Refresh the collection list.
Definition picker_gui.h:328
@ Filter
Update filter state.
Definition picker_gui.h:331
bool has_collection_picker
Set if this window has a collection picker 'component'.
Definition picker_gui.h:351
static constexpr int PREVIEW_LEFT
Offset from left edge to draw preview.
Definition picker_gui.h:341
PickerTypeList types
List of types.
Definition picker_gui.h:392
std::set< std::string > inactive
Set of collections with inactive items.
Definition picker_gui.h:353
QueryString class_editbox
Filter editbox.
Definition picker_gui.h:386
bool has_type_picker
Set if this window has a type picker 'component'.
Definition picker_gui.h:350
void BuildPickerClassList()
Builds the filter list of classes.
void BuildPickerCollectionList()
Builds the filter list of collections.
void OnEditboxChanged(WidgetID wid) override
The text in an editbox has been edited.
void OnQueryTextFinished(std::optional< std::string > str) override
The query window opened from this window has closed.
void BuildPickerTypeList()
Builds the filter list of types.
void OnDropdownSelect(WidgetID widget, int index, int click_result) override
A dropdown option associated to this window has been selected.
void OnResize() override
Called after the window got resized.
static constexpr int PREVIEW_BOTTOM
Offset from bottom edge to draw preview.
Definition picker_gui.h:342
PickerClassWindowHotkeys
Enum referring to the Hotkeys in the picker window.
Definition picker_gui.h:372
@ PCWHK_FOCUS_FILTER_BOX
Focus the edit box for editing the filter string.
Definition picker_gui.h:373
std::string GetWidgetString(WidgetID widget, StringID stringid) const override
Get the raw string for a widget.
PickerCollectionList collections
List of collections.
Definition picker_gui.h:401
void OnClick(Point pt, WidgetID widget, int click_count) override
A click with the left mouse button has been made on the window.
void OnInvalidateData(int data=0, bool gui_scope=true) override
Some data on this window has become invalid.
QueryString type_editbox
Filter editbox.
Definition picker_gui.h:394
EventState OnHotkey(int hotkey) override
A hotkey has been pressed.
EnumBitSet< PickerInvalidation, uint8_t > PickerInvalidations
Bitset of Pickerinvalidation elements.
Definition picker_gui.h:335
void OnInit() override
Notification that the nested widget tree gets initialized.
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.
PickerClassList classes
List of classes.
Definition picker_gui.h:384
static constexpr int STEP_PREVIEW_HEIGHT
Step for decreasing or increase preview button height.
Definition picker_gui.h:344
std::vector< std::unique_ptr< const DropDownListItem > > DropDownList
A drop down list is a collection of drop down list items.
#define T
Climate temperate.
Definition engines.h:91
void SetDirty() const
Mark entire window as dirty (in need of re-paint).
Definition window.cpp:972
#define Rect
Macro that prevents name conflicts between included headers.
#define Point
Macro that prevents name conflicts between included headers.
GrfSpecFeature
Definition newgrf.h:80
Functions related to NewGRF badges.
GUI functions related to NewGRF badges.
GUIList< PickerItem, std::nullptr_t, PickerFilterData & > PickerTypeList
GUIList holding classes/types to display.
Definition picker_gui.h:319
GUIList< int, std::nullptr_t, PickerFilterData & > PickerClassList
GUIList holding classes to display.
Definition picker_gui.h:318
PickerFilterMode
Picker filter mode.
Definition picker_gui.h:26
@ Used
Show used types.
Definition picker_gui.h:28
@ Saved
Show saved types.
Definition picker_gui.h:29
@ All
Show all classes.
Definition picker_gui.h:27
std::unique_ptr< NWidgetBase > MakePickerClassWidgets()
Create nested widgets for the class picker widgets.
EnumBitSet< PickerFilterMode, uint8_t > PickerFilterModes
Bitset of PickerFilterMode elements.
Definition picker_gui.h:33
std::unique_ptr< NWidgetBase > MakePickerTypeWidgets()
Create nested widgets for the type picker widgets.
GUIList< std::string, std::nullptr_t, PickerFilterData & > PickerCollectionList
GUIList holding collections to display.
Definition picker_gui.h:320
Base for the GUIs that have an edit box in them.
Base types for having sorted lists in GUIs.
Searching and filtering using a stringterm.
Types related to strings.
uint32_t StringID
Numeric value that represents a string, independent of the selected language.
static const StringID INVALID_STRING_ID
Constant representing an invalid string (16bit in case it is used in savegames).
Dimensions (a width and height) of a rectangle in 2D.
Data structure describing what to show in the list (filter criteria).
Data structure describing how to show the list (what sort direction and criteria).
const PickerCallbacks * callbacks
Callbacks for filter functions to access to callbacks.
Definition picker_gui.h:313
Data stored about a string that can be modified in the GUI.
StringFilter(const bool *case_sensitive=nullptr, bool locale_aware=true)
Constructor for filter.
High level window description.
Definition window_gui.h:172
void InvalidateData(int data=0, bool gui_scope=true)
Mark this window's data as invalid (in need of re-computing).
Definition window.cpp:3255
Window * parent
Parent window.
Definition window_gui.h:328
ResizeInfo resize
Resize information.
Definition window_gui.h:314
Window(WindowDesc &desc)
Empty constructor, initialization has been moved to InitNested() called from the constructor of the d...
Definition window.cpp:1838
WindowNumber window_number
Window number within the window class.
Definition window_gui.h:302
Definition of Interval and OneShot timers.
Definition of the game-calendar-timer.
Definition of the Window system.
Functions, definitions and such used only by the GUI.
Types related to windows.
int WidgetID
Widget ID.
Definition window_type.h:21
EventState
State of handling an event.