38 static std::vector<PickerCallbacks *> &GetPickerCallbacks()
40 static std::vector<PickerCallbacks *> callbacks;
44 PickerCallbacks::PickerCallbacks(
const std::string &ini_group) : ini_group(ini_group)
46 GetPickerCallbacks().push_back(
this);
49 PickerCallbacks::~PickerCallbacks()
51 auto &callbacks = GetPickerCallbacks();
52 callbacks.erase(std::find(callbacks.begin(), callbacks.end(),
this));
63 if (group ==
nullptr)
return;
65 callbacks.
saved.clear();
67 std::array<uint8_t, 4> grfid_buf;
69 std::string_view str = item.
name;
72 auto grfid_pos = str.find(
'|');
73 if (grfid_pos == std::string_view::npos)
continue;
75 std::string_view grfid_str = str.substr(0, grfid_pos);
78 str = str.substr(grfid_pos + 1);
79 uint32_t grfid = grfid_buf[0] | (grfid_buf[1] << 8) | (grfid_buf[2] << 16) | (grfid_buf[3] << 24);
81 auto [ptr, err] = std::from_chars(str.data(), str.data() + str.size(), localid);
83 if (err == std::errc{} && ptr == str.data() + str.size()) {
84 callbacks.
saved.insert({grfid, localid, 0, 0});
100 std::string key = fmt::format(
"{:08X}|{}",
BSWAP32(item.grfid), item.local_id);
140 int r = a.class_index - b.class_index;
141 if (r == 0) r = a.index - b.index;
162 this->window_number = window_number;
168 void PickerWindow::ConstructWindow()
173 bool isActive = this->callbacks.
IsActive();
184 if (
auto *nwid = this->GetWidget<NWidgetStacked>(
WID_PW_CLASS_SEL); nwid !=
nullptr) {
186 bool is_vertical = (nwid->parent->parent->type ==
NWID_VERTICAL);
193 this->class_string_filter.
callbacks = &this->callbacks;
204 this->callbacks.
used.clear();
219 if (
auto *nwid = this->GetWidget<NWidgetStacked>(
WID_PW_TYPE_SEL); nwid !=
nullptr) {
221 bool is_vertical = (nwid->parent->parent->type ==
NWID_VERTICAL);
228 this->type_string_filter.
callbacks = &this->callbacks;
242 this->callbacks.Close(data);
252 size.height = 5 *
resize.height;
258 size.width +=
resize.width;
259 fill.width =
resize.width;
274 void PickerWindow::DrawWidget(
const Rect &r,
WidgetID widget)
const
282 const int y_step = this->GetWidget<NWidgetResizeBase>(widget)->resize_y;
283 auto [first, last] = vscroll->GetVisibleRangeIterators(this->
classes);
284 for (
auto it = first; it != last; ++it) {
293 assert(this->GetWidget<NWidgetBase>(widget)->GetParentWidget<NWidgetMatrix>()->GetCurrentElement() <
static_cast<int>(this->
types.size()));
294 const auto &item = this->
types[this->GetWidget<NWidgetBase>(widget)->GetParentWidget<
NWidgetMatrix>()->GetCurrentElement()];
303 this->callbacks.
DrawType(x, y, item.class_index, item.index);
304 if (this->callbacks.
saved.contains(item)) {
305 DrawSprite(SPR_BLOT, PALETTE_TO_YELLOW, 0, 0);
307 if (this->callbacks.
used.contains(item)) {
338 if (it == this->
classes.end())
return;
363 int sel = this->GetWidget<NWidgetBase>(widget)->GetParentWidget<
NWidgetMatrix>()->GetCurrentElement();
364 assert(sel < (
int)this->
types.size());
365 const auto &item = this->
types[sel];
368 auto it = this->callbacks.
saved.find(item);
369 if (it == std::end(this->callbacks.
saved)) {
370 this->callbacks.
saved.insert(item);
372 this->callbacks.
saved.erase(it);
390 void PickerWindow::OnInvalidateData(
int data,
bool gui_scope)
392 if (!gui_scope)
return;
398 if ((data &
PFI_VALIDATE) != 0) this->EnsureSelectedClassIsValid();
399 if ((data &
PFI_POSITION) != 0) this->EnsureSelectedClassIsVisible();
402 if ((data &
PFI_VALIDATE) != 0) this->EnsureSelectedTypeIsValid();
403 if ((data &
PFI_POSITION) != 0) this->EnsureSelectedTypeIsVisible();
430 void PickerWindow::OnEditboxChanged(
WidgetID wid)
462 for (
int i = 0; i < count; i++) {
464 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;
465 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;
477 void PickerWindow::EnsureSelectedClassIsValid()
480 if (std::binary_search(std::begin(this->
classes), std::end(this->
classes), class_index))
return;
483 class_index = this->
classes.front();
487 for (
int i = 0; i < count; i++) {
498 void PickerWindow::EnsureSelectedClassIsVisible()
501 if (this->
classes.empty())
return;
504 if (it == std::end(this->
classes))
return;
506 int pos =
static_cast<int>(std::distance(std::begin(this->
classes), it));
510 void PickerWindow::RefreshUsedTypeList()
514 this->callbacks.
used.clear();
533 this->
types.reserve(this->callbacks.
used.size());
535 if (!show_all && item.class_index != cls_id)
continue;
537 this->
types.emplace_back(item);
539 }
else if (filter_saved) {
541 this->
types.reserve(this->callbacks.
saved.size());
544 if (item.class_index == -1)
continue;
545 if (!show_all && item.class_index != cls_id)
continue;
547 this->
types.emplace_back(item);
549 }
else if (show_all) {
553 this->
types.reserve(total);
555 for (
int class_index : this->classes) {
557 for (
int i = 0; i < count; i++) {
564 if (cls_id >= 0 && cls_id < this->callbacks.
GetClassCount()) {
566 this->
types.reserve(count);
567 for (
int i = 0; i < count; i++) {
582 void PickerWindow::EnsureSelectedTypeIsValid()
586 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;
588 if (!this->
types.empty()) {
589 class_index = this->
types.front().class_index;
590 index = this->
types.front().index;
594 for (
int i = 0; i < count; i++) {
604 void PickerWindow::EnsureSelectedTypeIsVisible()
607 if (this->
types.empty()) {
615 auto it = std::find_if(std::begin(this->
types), std::end(this->
types), [class_index, index](
const auto &item) {
return item.class_index == class_index && item.index == index; });
616 if (it == std::end(this->
types))
return;
618 int pos =
static_cast<int>(std::distance(std::begin(this->
types), it));
625 static constexpr
NWidgetPart picker_class_widgets[] = {
629 NWidget(
WWT_EDITBOX, COLOUR_DARK_GREEN,
WID_PW_CLASS_FILTER),
SetMinimalSize(144, 0),
SetPadding(2),
SetFill(1, 0),
SetDataTip(STR_LIST_FILTER_OSKTITLE, STR_LIST_FILTER_TOOLTIP),
648 static constexpr
NWidgetPart picker_type_widgets[] = {
652 NWidget(
WWT_EDITBOX, COLOUR_DARK_GREEN,
WID_PW_TYPE_FILTER),
SetPadding(2),
SetResize(1, 0),
SetFill(1, 0),
SetDataTip(STR_LIST_FILTER_OSKTITLE, STR_LIST_FILTER_TOOLTIP),
670 NWidget(
WWT_EMPTY, INVALID_COLOUR,
WID_PW_TYPE_NAME),
SetPadding(
WidgetDimensions::unscaled.framerect),
SetResize(1, 0),
SetFill(1, 0),
SetMinimalTextLines(1, 0),
Class for backupping variables and making sure they are restored later.
constexpr debug_inline bool HasBit(const T x, const uint8_t y)
Checks if a bit in a value is set.
constexpr T SetBit(T &x, const uint8_t y)
Set a bit in a variable.
static uint32_t BSWAP32(uint32_t x)
Perform a 32 bits endianness bitswap on x.
constexpr T ToggleBit(T &x, const uint8_t y)
Toggles a bit in a variable.
constexpr T ClrBit(T &x, const uint8_t y)
Clears a bit in a variable.
bool Filter(FilterFunction *decide, F filter_data)
Filter the list.
void RebuildDone()
Notify the sortlist that the rebuild is done.
void SetFiltering(Filtering f)
Import filter conditions.
void SetListing(Listing l)
Import sort conditions.
void SetFilterState(bool state)
Enable or disable the filter.
void SetFilterFuncs(std::span< FilterFunction *const > n_funcs)
Hand the filter function pointers to the GUIList.
bool NeedRebuild() const
Check if a rebuild is needed.
void ForceRebuild()
Force that a rebuild is needed.
bool Sort(Comp compare)
Sort the list.
void SetSortFuncs(std::span< SortFunction *const > n_funcs)
Hand the sort function pointers to the GUIList.
Class for PickerClassWindow to collect information and retain state.
virtual int GetSelectedClass() const =0
Get the index of the selected class.
Filtering type_last_filtering
Default filtering of PickerTypeList.
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.
virtual void SetSelectedClass(int id) const =0
Set the selected class.
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 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 std::set< PickerItem > UpdateSavedItems(const std::set< PickerItem > &src)=0
Update link between grfid/localidx and class_index/index in saved items.
virtual bool HasClassChoice() const =0
Are there multiple classes to chose from?
Listing type_last_sorting
Default sorting of PickerTypeList.
std::set< PickerItem > used
Set of items used in the current game by the current company.
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 void SetSelectedType(int id) const =0
Set the selected type.
virtual StringID GetClassName(int id) const =0
Get the name of a class.
virtual void DrawType(int x, int y, int cls_id, int id) const =0
Draw preview image of an item.
Filtering class_last_filtering
Default filtering of PickerClassList.
virtual int GetSelectedType() const =0
Get the selected type.
uint8_t mode
Bitmask of PickerFilterModes.
std::set< PickerItem > saved
Set of saved favourite items.
Listing class_last_sorting
Default sorting of PickerClassList.
Base class for windows opened from a toolbar.
void Close([[maybe_unused]] int data=0) override
Hide the window and all its child windows, and mark them for a later deletion.
void Close(int data=0) override
Hide the window and all its child windows, and mark them for a later deletion.
bool has_class_picker
Set if this window has a class picker 'component'.
static const int PREVIEW_LEFT
Offset from left edge to draw preview.
@ PFM_USED
Show used types.
@ PFM_ALL
Show all classes.
@ PFM_SAVED
Show saved types.
PickerTypeList types
List of types.
QueryString class_editbox
Filter editbox.
bool has_type_picker
Set if this window has a type picker 'component'.
void BuildPickerClassList()
Builds the filter list of classes.
@ PCWHK_FOCUS_FILTER_BOX
Focus the edit box for editing the filter string.
void BuildPickerTypeList()
Builds the filter list of types.
void OnResize() override
Called after the window got resized.
@ PFI_POSITION
Update scroll positions.
@ PFI_VALIDATE
Validate selected item.
@ PFI_CLASS
Refresh the class list.
@ PFI_TYPE
Refresh the type list.
static const int PREVIEW_WIDTH
Width of each preview button.
QueryString type_editbox
Filter editbox.
static const int PREVIEW_BOTTOM
Offset from bottom edge to draw preview.
EventState OnHotkey(int hotkey) override
A hotkey has been pressed.
PickerClassList classes
List of classes.
static const int PREVIEW_HEIGHT
Height of each preview button.
int GetCharacterHeight(FontSize size)
Get height of a character for a given font size.
Dimension GetSpriteSize(SpriteID sprid, Point *offset, ZoomLevel zoom)
Get the size of a sprite.
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.
bool _ctrl_pressed
Is Ctrl pressed?
void GfxFillRect(int left, int top, int right, int bottom, int colour, FillRectMode mode)
Applies a certain FillRectMode-operation to a rectangle [left, right] x [top, bottom] on the screen.
void DrawSprite(SpriteID img, PaletteID pal, int x, int y, const SubSprite *sub, ZoomLevel zoom)
Draw a sprite, not in a viewport.
bool FillDrawPixelInfo(DrawPixelInfo *n, int left, int top, int width, int height)
Set up a clipping area for only drawing into a certain area.
@ SA_CENTER
Center both horizontally and vertically.
@ FS_NORMAL
Index of the normal font in the font tables.
@ FILLRECT_CHECKER
Draw only every second pixel, used for greying-out.
GUI functions that shouldn't be here.
Hotkey related functions.
Types related to reading/writing '*.ini' files.
uint8_t GetColourGradient(Colours colour, ColourShade shade)
Get colour gradient palette index.
static const std::initializer_list< PickerClassList::FilterFunction *const > _class_filter_funcs
Filter functions of the PickerClassList.
std::unique_ptr< NWidgetBase > MakePickerTypeWidgets()
Create nested widgets for the type picker widgets.
std::unique_ptr< NWidgetBase > MakePickerClassWidgets()
Create nested widgets for the class picker widgets.
static bool TypeIDSorter(PickerItem const &a, PickerItem const &b)
Sort types by id.
static void PickerLoadConfig(const IniFile &ini, PickerCallbacks &callbacks)
Load favourites of a picker from config.
static const std::initializer_list< PickerTypeList::SortFunction *const > _type_sorter_funcs
Sort functions of the PickerTypeList.
static bool ClassIDSorter(int const &a, int const &b)
Sort classes by id.
static const std::initializer_list< PickerClassList::SortFunction *const > _class_sorter_funcs
Sort functions of the PickerClassList.
static bool TypeTagNameFilter(PickerItem const *item, PickerFilterData &filter)
Filter types by class name.
static const std::initializer_list< PickerTypeList::FilterFunction *const > _type_filter_funcs
Filter functions of the PickerTypeList.
static void PickerSaveConfig(IniFile &ini, const PickerCallbacks &callbacks)
Save favourites of a picker to config.
static bool ClassTagNameFilter(int const *item, PickerFilterData &filter)
Filter classes by class name.
Base for the GUIs that have an edit box in them.
A number of safeguards to prevent using unsafe methods.
ClientSettings _settings_client
The current settings for this game.
Types related to global configuration settings.
Base types for having sorted lists in GUIs.
Functions related to sound.
@ SND_15_BEEP
19 == 0x13 GUI button click
This file contains all sprite-related enums and defines.
Definition of base types and functions in a cross-platform compatible way.
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.
Functions related to low-level strings.
Searching and filtering using a stringterm.
std::string GetString(StringID string)
Resolve the given StringID into a std::string with all the associated DParam lookups and formatting.
Functions related to OTTD's strings.
static const StringID INVALID_STRING_ID
Constant representing an invalid string (16bit in case it is used in savegames)
static const int MAX_CHAR_LENGTH
Max. length of UTF-8 encoded unicode character.
Class to backup a specific variable and restore it upon destruction of this object to prevent stack v...
SoundSettings sound
sound effect settings
Dimensions (a width and height) of a rectangle in 2D.
Data about how and where to blit pixels.
Ini file that supports both loading and saving.
A group within an ini file.
void Clear()
Clear all items in the group.
IniItem & CreateItem(std::string_view name)
Create an item with the given name.
std::list< IniItem > items
all items in the group
A single "line" in an ini file.
std::string name
The name of this item.
const IniGroup * GetGroup(std::string_view name) const
Get the group with the given name.
IniGroup & GetOrCreateGroup(std::string_view name)
Get the group with the given name, and if it doesn't exist create a new group.
const PickerCallbacks * callbacks
Callbacks for filter functions to access to callbacks.
Coordinates of a point in 2D.
int cancel_button
Widget button of parent window to simulate when pressing CANCEL in OSK.
static const int ACTION_CLEAR
Clear editbox.
constexpr uint Horizontal() const
Get total horizontal padding of RectPadding.
constexpr uint Vertical() const
Get total vertical padding of RectPadding.
Specification of a rectangle with absolute coordinates of all edges.
int Width() const
Get width of Rect.
Rect Shrink(int s) const
Copy and shrink Rect by s pixels.
int Height() const
Get height of Rect.
bool click_beep
Beep on a random selection of buttons.
bool IsEmpty() const
Check whether any filter words were entered.
void SetFilterTerm(const char *str)
Set the term to filter on.
void ResetState()
Reset the matching state to process a new item.
void AddLine(const char *str)
Pass another text line from the current item to the filter.
bool GetState() const
Get the matching state of the current item.
char *const buf
buffer in which text is saved
High level window description.
Data structure for an opened window.
void FinishInitNested(WindowNumber window_number=0)
Perform the second part of the initialization of a nested widget tree.
std::map< WidgetID, QueryString * > querystrings
QueryString associated to WWT_EDITBOX widgets.
void InvalidateData(int data=0, bool gui_scope=true)
Mark this window's data as invalid (in need of re-computing)
ResizeInfo resize
Resize information.
void CreateNestedTree()
Perform the first part of the initialization of a nested widget tree.
bool SetFocusedWidget(WidgetID widget_index)
Set focus within this window to the given widget.
bool IsWidgetDisabled(WidgetID widget_index) const
Gets the enabled/disabled status of a widget.
void SetWidgetLoweredState(WidgetID widget_index, bool lowered_stat)
Sets the lowered/raised status of a widget.
const NWidgetCore * nested_focus
Currently focused nested widget, or nullptr if no nested widget has focus.
const Scrollbar * GetScrollbar(WidgetID widnum) const
Return the Scrollbar to a widget index.
void SetWidgetDisabledState(WidgetID widget_index, bool disab_stat)
Sets the enabled/disabled status of a widget.
int width
width of the window (number of pixels to the right in x direction)
WindowNumber window_number
Window number within the window class.
void CloseWindowById(WindowClass cls, WindowNumber number, bool force, int data)
Close a window by its class and window number (if it is open).
void SetFocusedWindow(Window *w)
Set the window that has the focus.
Window functions not directly related to making/drawing windows.
Functions, definitions and such used only by the GUI.
Types related to windows.
EventState
State of handling an event.
@ ES_HANDLED
The passed event is handled.
@ ES_NOT_HANDLED
The passed event is not handled.
@ WC_SELECT_STATION
Select station (when joining stations); Window numbers:
Functions related to zooming.
int ScaleSpriteTrad(int value)
Scale traditional pixel dimensions to GUI zoom level, for drawing sprites.
int ScaleGUITrad(int value)
Scale traditional pixel dimensions to GUI zoom level.