OpenTTD Source 20260311-master-g511d3794ce
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
25struct PickerItem {
26 uint32_t grfid;
27 uint16_t local_id;
28 int class_index;
29 int index;
30
31 inline auto operator<=>(const PickerItem &other) const
32 {
33 if (auto cmp = this->grfid <=> other.grfid; cmp != 0) return cmp;
34 return this->local_id <=> other.local_id;
35 }
36};
37
39class PickerCallbacks {
40public:
41 explicit PickerCallbacks(const std::string &ini_group);
43 virtual ~PickerCallbacks();
44
46 virtual void Close([[maybe_unused]] int data) { }
47
52 virtual GrfSpecFeature GetFeature() const = 0;
57 virtual bool IsActive() const = 0;
62 virtual bool HasClassChoice() const = 0;
63
64 /* Class callbacks */
69 virtual StringID GetClassTooltip() const = 0;
75 virtual int GetClassCount() const = 0;
80 virtual int GetSelectedClass() const = 0;
85 virtual void SetSelectedClass(int id) const = 0;
91 virtual StringID GetClassName(int id) const = 0;
92
93 /* Type callbacks */
98 virtual StringID GetTypeTooltip() const = 0;
105 virtual int GetTypeCount(int cls_id) const = 0;
110 virtual int GetSelectedType() const = 0;
115 virtual void SetSelectedType(int id) const = 0;
122 virtual PickerItem GetPickerItem(int cls_id, int id) const = 0;
129 virtual StringID GetTypeName(int cls_id, int id) const = 0;
136 virtual std::span<const BadgeID> GetTypeBadges(int cls_id, int id) const = 0;
143 virtual bool IsTypeAvailable(int cls_id, int id) const = 0;
151 virtual void DrawType(int x, int y, int cls_id, int id) const = 0;
152
153 /* Collection Callbacks */
158 virtual StringID GetCollectionTooltip() const = 0;
159
164 virtual void FillUsedItems(std::set<PickerItem> &items) = 0;
170 virtual std::map<std::string, std::set<PickerItem>> UpdateSavedItems(const std::map<std::string, std::set<PickerItem>> &src) = 0;
176 inline std::set<std::string> InitializeInactiveCollections(const std::map<std::string, std::set<PickerItem>> collections)
177 {
178 std::set<std::string> inactive;
179
180 for (const auto &collection : collections) {
181 if ((collection.second.size() == 1 && collection.second.contains({})) || collection.first == "") continue;
182 for (const PickerItem &item : collection.second) {
183 if (item.class_index == -1 || item.index == -1) {
184 inactive.emplace(collection.first);
185 break;
186 }
187 if (GetTypeName(item.class_index, item.index) == INVALID_STRING_ID) {
188 inactive.emplace(collection.first);
189 break;
190 }
191 }
192 }
193 return inactive;
194 }
195
198
199 Listing type_last_sorting = { false, 0 };
201
203
204 const std::string ini_group;
205 uint8_t mode = 0;
206 bool rename_collection = false;
207 std::string sel_collection;
208 std::string edit_collection;
209 std::set<std::string> rm_collections;
210
212
213 std::set<PickerItem> used;
214 std::map<std::string, std::set<PickerItem>> saved;
215};
216
218template <typename T>
219class PickerCallbacksNewGRFClass : public PickerCallbacks {
220public:
221 explicit PickerCallbacksNewGRFClass(const std::string &ini_group) : PickerCallbacks(ini_group) {}
222
223 inline typename T::index_type GetClassIndex(int cls_id) const { return static_cast<typename T::index_type>(cls_id); }
224 inline const T *GetClass(int cls_id) const { return T::Get(this->GetClassIndex(cls_id)); }
225 inline const typename T::spec_type *GetSpec(int cls_id, int id) const { return this->GetClass(cls_id)->GetSpec(id); }
226
227 bool HasClassChoice() const override { return T::GetUIClassCount() > 1; }
228
229 int GetClassCount() const override { return T::GetClassCount(); }
230 int GetTypeCount(int cls_id) const override { return this->GetClass(cls_id)->GetSpecCount(); }
231
232 PickerItem GetPickerItem(const typename T::spec_type *spec, int cls_id = -1, int id = -1) const
233 {
234 if (spec == nullptr) return {0, 0, cls_id, id};
235 return {spec->grf_prop.grfid, spec->grf_prop.local_id, spec->class_index.base(), spec->index};
236 }
237
238 PickerItem GetPickerItem(int cls_id, int id) const override
239 {
240 return GetPickerItem(GetClass(cls_id)->GetSpec(id), cls_id, id);
241 }
242
243 std::map<std::string, std::set<PickerItem>> UpdateSavedItems(const std::map<std::string, std::set<PickerItem>> &src) override
244 {
245 if (src.empty()) return {};
246
247 std::map<std::string, std::set<PickerItem>> dst;
248 for (auto it = src.begin(); it != src.end(); it++) {
249 if (it->second.empty() || (it->second.size() == 1 && it->second.contains({}))) {
250 dst[it->first];
251 continue;
252 }
253
254 for (const auto &item : it->second) {
255 const auto *spec = T::GetByGrf(item.grfid, item.local_id);
256 if (spec == nullptr) {
257 dst[it->first].emplace(item.grfid, item.local_id, -1, -1);
258 } else {
259 dst[it->first].emplace(GetPickerItem(spec));
260 }
261 }
262 }
263 return dst;
264 }
265};
266
269 std::optional<BadgeTextFilter> btf;
270 std::optional<BadgeDropdownFilter> bdf;
271};
272
276
277class PickerWindow : public PickerWindowBase {
278public:
279 enum PickerFilterModes : uint8_t {
283 };
284
294 using PickerInvalidations = EnumBitSet<PickerInvalidation, uint8_t>;
295
296 static constexpr PickerInvalidations PICKER_INVALIDATION_ALL{PickerInvalidation::Class, PickerInvalidation::Type, PickerInvalidation::Position, PickerInvalidation::Validate};
297
298 static constexpr int PREVIEW_WIDTH = 64;
299 static constexpr int PREVIEW_HEIGHT = 48;
300 static constexpr int PREVIEW_LEFT = 31;
301 static constexpr int PREVIEW_BOTTOM = 31;
302
303 static constexpr int STEP_PREVIEW_HEIGHT = 16;
304 static constexpr int MAX_PREVIEW_HEIGHT = PREVIEW_HEIGHT * 3;
305
306 static constexpr uint EDITBOX_MAX_SIZE = 16;
307
308 bool has_class_picker = false;
309 bool has_type_picker = false;
312 std::set<std::string> inactive;
313
314 PickerWindow(WindowDesc &desc, Window *parent, int window_number, PickerCallbacks &callbacks);
315 void OnInit() override;
316 void Close(int data = 0) override;
317 void UpdateWidgetSize(WidgetID widget, Dimension &size, const Dimension &padding, Dimension &fill, Dimension &resize) override;
318 std::string GetWidgetString(WidgetID widget, StringID stringid) const override;
319 DropDownList BuildCollectionDropDownList();
320 void DrawWidget(const Rect &r, WidgetID widget) const override;
321 void OnDropdownSelect(WidgetID widget, int index, int click_result) override;
322 void OnResize() override;
323 void static DeletePickerCollectionCallback(Window *win, bool confirmed);
324 void OnClick(Point pt, WidgetID widget, int click_count) override;
325 void OnQueryTextFinished(std::optional<std::string> str) override;
326 void OnInvalidateData(int data = 0, bool gui_scope = true) override;
327 EventState OnHotkey(int hotkey) override;
328 void OnEditboxChanged(WidgetID wid) override;
329
334
335 void InvalidateData(PickerInvalidations data) { this->Window::InvalidateData(data.base()); }
336
337protected:
338 void ConstructWindow();
339
340 PickerCallbacks &callbacks;
341
342private:
344 PickerFilterData class_string_filter;
346
348 void EnsureSelectedClassIsValid();
349 void EnsureSelectedClassIsVisible();
350
352 PickerFilterData type_string_filter;
354
355 void RefreshUsedTypeList();
356 void BuildPickerTypeList();
357 void EnsureSelectedTypeIsValid();
358 void EnsureSelectedTypeIsVisible();
359
361
363
364 GUIBadgeClasses badge_classes;
365 std::pair<WidgetID, WidgetID> badge_filters{};
366 BadgeFilterChoices badge_filter_choices{};
367
368 const IntervalTimer<TimerGameCalendar> yearly_interval = {{TimerGameCalendar::Trigger::Year, TimerGameCalendar::Priority::None}, [this](auto) {
369 this->SetDirty();
370 }};
371
372 const IntervalTimer<TimerWindow> refresh_interval = {std::chrono::seconds(3), [this](auto) {
373 RefreshUsedTypeList();
374 }};
375};
376
377class NWidgetBase;
378std::unique_ptr<NWidgetBase> MakePickerClassWidgets();
379std::unique_ptr<NWidgetBase> MakePickerTypeWidgets();
380
381#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:243
PickerItem GetPickerItem(int cls_id, int id) const override
Get data about an item.
Definition picker_gui.h:238
int GetClassCount() const override
Get the number of classes.
Definition picker_gui.h:229
int GetTypeCount(int cls_id) const override
Get the number of types in a class.
Definition picker_gui.h:230
bool HasClassChoice() const override
Are there multiple classes to chose from?
Definition picker_gui.h:227
Class for PickerClassWindow to collect information and retain state.
Definition picker_gui.h:39
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:176
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:208
Filtering type_last_filtering
Default filtering of PickerTypeList.
Definition picker_gui.h:200
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:204
bool rename_collection
Are we renaming a collection?
Definition picker_gui.h:206
Listing collection_last_sorting
Default sorting of PickerCollectionList.
Definition picker_gui.h:202
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:207
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:199
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:213
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:211
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:197
virtual void Close(int data)
Hide the window and all its child windows, and mark them for a later deletion.
Definition picker_gui.h:46
std::set< std::string > rm_collections
Set of removed or renamed collections for updating ini file.
Definition picker_gui.h:209
std::map< std::string, std::set< PickerItem > > saved
Set of saved collections of items.
Definition picker_gui.h:214
virtual int GetSelectedType() const =0
Get the selected type.
uint8_t mode
Bitmask of PickerFilterModes.
Definition picker_gui.h:205
Listing class_last_sorting
Default sorting of PickerClassList.
Definition picker_gui.h:196
static constexpr int MAX_PREVIEW_HEIGHT
Maximum height of each preview button.
Definition picker_gui.h:304
static constexpr int PREVIEW_WIDTH
Width of each preview button.
Definition picker_gui.h:298
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:311
bool has_class_picker
Set if this window has a class picker 'component'.
Definition picker_gui.h:308
static constexpr int PREVIEW_HEIGHT
Height of each preview button.
Definition picker_gui.h:299
static constexpr uint EDITBOX_MAX_SIZE
The maximum number of characters for the filter edit box.
Definition picker_gui.h:306
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:286
@ Position
Update scroll positions.
Definition picker_gui.h:290
@ Class
Refresh the class list.
Definition picker_gui.h:287
@ Type
Refresh the type list.
Definition picker_gui.h:288
@ Validate
Validate selected item.
Definition picker_gui.h:291
@ Collection
Refresh the collection list.
Definition picker_gui.h:289
@ Filter
Update filter state.
Definition picker_gui.h:292
bool has_collection_picker
Set if this window has a collection picker 'component'.
Definition picker_gui.h:310
static constexpr int PREVIEW_LEFT
Offset from left edge to draw preview.
Definition picker_gui.h:300
PickerTypeList types
List of types.
Definition picker_gui.h:351
std::set< std::string > inactive
Set of collections with inactive items.
Definition picker_gui.h:312
QueryString class_editbox
Filter editbox.
Definition picker_gui.h:345
bool has_type_picker
Set if this window has a type picker 'component'.
Definition picker_gui.h:309
void BuildPickerClassList()
Builds the filter list of classes.
@ PFM_USED
Show used types.
Definition picker_gui.h:281
@ PFM_ALL
Show all classes.
Definition picker_gui.h:280
@ PFM_SAVED
Show saved types.
Definition picker_gui.h:282
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:301
PickerClassWindowHotkeys
Enum referring to the Hotkeys in the picker window.
Definition picker_gui.h:331
@ PCWHK_FOCUS_FILTER_BOX
Focus the edit box for editing the filter string.
Definition picker_gui.h:332
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:360
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:353
EventState OnHotkey(int hotkey) override
A hotkey has been pressed.
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:343
static constexpr int STEP_PREVIEW_HEIGHT
Step for decreasing or increase preview button height.
Definition picker_gui.h:303
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:980
#define Rect
Macro that prevents name conflicts between included headers.
#define Point
Macro that prevents name conflicts between included headers.
GrfSpecFeature
Definition newgrf.h:71
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:274
GUIList< int, std::nullptr_t, PickerFilterData & > PickerClassList
GUIList holding classes to display.
Definition picker_gui.h:273
std::unique_ptr< NWidgetBase > MakePickerClassWidgets()
Create nested widgets for the class picker widgets.
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:275
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:268
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:168
void InvalidateData(int data=0, bool gui_scope=true)
Mark this window's data as invalid (in need of re-computing).
Definition window.cpp:3261
Window * parent
Parent window.
Definition window_gui.h:329
ResizeInfo resize
Resize information.
Definition window_gui.h:315
Window(WindowDesc &desc)
Empty constructor, initialization has been moved to InitNested() called from the constructor of the d...
Definition window.cpp:1845
WindowNumber window_number
Window number within the window class.
Definition window_gui.h:303
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:20
EventState
State of handling an event.