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 <http://www.gnu.org/licenses/>.
8 /** @file picker_gui.h Functions/types etc. related to the picker GUI. */
13 #include "querystring_gui.h"
14 #include "sortlist_type.h"
15 #include "stringfilter_type.h"
16 #include "strings_type.h"
17 #include "timer/timer.h"
18 #include "timer/timer_game_calendar.h"
19 #include "timer/timer_window.h"
20 #include "window_gui.h"
21 #include "window_type.h"
29 inline auto operator<=>(const PickerItem
&other
) const
31 if (auto cmp
= this->grfid
<=> other
.grfid
; cmp
!= 0) return cmp
;
32 return this->local_id
<=> other
.local_id
;
36 /** Class for PickerClassWindow to collect information and retain state. */
37 class PickerCallbacks
{
39 explicit PickerCallbacks(const std::string
&ini_group
);
40 virtual ~PickerCallbacks();
42 virtual void Close(int) { }
44 /** Should picker class/type selection be enabled? */
45 virtual bool IsActive() const = 0;
46 /** Are there multiple classes to chose from? */
47 virtual bool HasClassChoice() const = 0;
50 /** Get the tooltip string for the class list. */
51 virtual StringID
GetClassTooltip() const = 0;
52 /** Get the number of classes. @note Used only to estimate space requirements. */
53 virtual int GetClassCount() const = 0;
54 /** Get the index of the selected class. */
55 virtual int GetSelectedClass() const = 0;
56 /** Set the selected class. */
57 virtual void SetSelectedClass(int id
) const = 0;
58 /** Get the name of a class. */
59 virtual StringID
GetClassName(int id
) const = 0;
62 /** Get the tooltip string for the type grid. */
63 virtual StringID
GetTypeTooltip() const = 0;
64 /** Get the number of types in a class. @note Used only to estimate space requirements. */
65 virtual int GetTypeCount(int cls_id
) const = 0;
67 /** Get the selected type. */
68 virtual int GetSelectedType() const = 0;
69 /** Set the selected type. */
70 virtual void SetSelectedType(int id
) const = 0;
71 /** Get data about an item. */
72 virtual PickerItem
GetPickerItem(int cls_id
, int id
) const = 0;
73 /** Get the item of a type. */
74 virtual StringID
GetTypeName(int cls_id
, int id
) const = 0;
75 /** Test if an item is currently buildable. */
76 virtual bool IsTypeAvailable(int cls_id
, int id
) const = 0;
77 /** Draw preview image of an item. */
78 virtual void DrawType(int x
, int y
, int cls_id
, int id
) const = 0;
80 /** Fill a set with all items that are used by the current player. */
81 virtual void FillUsedItems(std::set
<PickerItem
> &items
) = 0;
82 /** Update link between grfid/localidx and class_index/index in saved items. */
83 virtual std::set
<PickerItem
> UpdateSavedItems(const std::set
<PickerItem
> &src
) = 0;
85 Listing class_last_sorting
= { false, 0 }; ///< Default sorting of #PickerClassList.
86 Filtering class_last_filtering
= { false, 0 }; ///< Default filtering of #PickerClassList.
88 Listing type_last_sorting
= { false, 0 }; ///< Default sorting of #PickerTypeList.
89 Filtering type_last_filtering
= { false, 0 }; ///< Default filtering of #PickerTypeList.
91 const std::string ini_group
; ///< Ini Group for saving favourites.
92 uint8_t mode
= 0; ///< Bitmask of \c PickerFilterModes.
94 std::set
<PickerItem
> used
; ///< Set of items used in the current game by the current company.
95 std::set
<PickerItem
> saved
; ///< Set of saved favourite items.
98 /** Helper for PickerCallbacks when the class system is based on NewGRFClass. */
100 class PickerCallbacksNewGRFClass
: public PickerCallbacks
{
102 explicit PickerCallbacksNewGRFClass(const std::string
&ini_group
) : PickerCallbacks(ini_group
) {}
104 inline typename
T::index_type
GetClassIndex(int cls_id
) const { return static_cast<typename
T::index_type
>(cls_id
); }
105 inline const T
*GetClass(int cls_id
) const { return T::Get(this->GetClassIndex(cls_id
)); }
106 inline const typename
T::spec_type
*GetSpec(int cls_id
, int id
) const { return this->GetClass(cls_id
)->GetSpec(id
); }
108 bool HasClassChoice() const override
{ return T::GetUIClassCount() > 1; }
110 int GetClassCount() const override
{ return T::GetClassCount(); }
111 int GetTypeCount(int cls_id
) const override
{ return this->GetClass(cls_id
)->GetSpecCount(); }
113 PickerItem
GetPickerItem(const typename
T::spec_type
*spec
, int cls_id
= -1, int id
= -1) const
115 if (spec
== nullptr) return {0, 0, cls_id
, id
};
116 return {spec
->grf_prop
.grffile
== nullptr ? 0 : spec
->grf_prop
.grffile
->grfid
, spec
->grf_prop
.local_id
, spec
->class_index
, spec
->index
};
119 PickerItem
GetPickerItem(int cls_id
, int id
) const override
121 return GetPickerItem(GetClass(cls_id
)->GetSpec(id
), cls_id
, id
);
124 std::set
<PickerItem
> UpdateSavedItems(const std::set
<PickerItem
> &src
) override
126 if (src
.empty()) return {};
128 std::set
<PickerItem
> dst
;
129 for (const auto &item
: src
) {
130 const auto *spec
= T::GetByGrf(item
.grfid
, item
.local_id
);
131 if (spec
== nullptr) {
132 dst
.insert({item
.grfid
, item
.local_id
, -1, -1});
134 dst
.insert(GetPickerItem(spec
));
141 struct PickerFilterData
: StringFilter
{
142 const PickerCallbacks
*callbacks
; ///< Callbacks for filter functions to access to callbacks.
145 using PickerClassList
= GUIList
<int, std::nullptr_t
, PickerFilterData
&>; ///< GUIList holding classes to display.
146 using PickerTypeList
= GUIList
<PickerItem
, std::nullptr_t
, PickerFilterData
&>; ///< GUIList holding classes/types to display.
148 class PickerWindow
: public PickerWindowBase
{
150 enum PickerFilterModes
{
151 PFM_ALL
= 0, ///< Show all classes.
152 PFM_USED
= 1, ///< Show used types.
153 PFM_SAVED
= 2, ///< Show saved types.
156 enum PickerFilterInvalidation
{
157 PFI_CLASS
= 1U << 0, ///< Refresh the class list.
158 PFI_TYPE
= 1U << 1, ///< Refresh the type list.
159 PFI_POSITION
= 1U << 2, ///< Update scroll positions.
160 PFI_VALIDATE
= 1U << 3, ///< Validate selected item.
163 static const int PREVIEW_WIDTH
= 64; ///< Width of each preview button.
164 static const int PREVIEW_HEIGHT
= 48; ///< Height of each preview button.
165 static const int PREVIEW_LEFT
= 31; ///< Offset from left edge to draw preview.
166 static const int PREVIEW_BOTTOM
= 31; ///< Offset from bottom edge to draw preview.
168 static const uint EDITBOX_MAX_SIZE
= 16; ///< The maximum number of characters for the filter edit box.
170 bool has_class_picker
= false; ///< Set if this window has a class picker 'component'.
171 bool has_type_picker
= false; ///< Set if this window has a type picker 'component'.
173 PickerWindow(WindowDesc
&desc
, Window
*parent
, int window_number
, PickerCallbacks
&callbacks
);
174 void Close(int data
= 0) override
;
175 void UpdateWidgetSize(WidgetID widget
, Dimension
&size
, const Dimension
&padding
, Dimension
&fill
, Dimension
&resize
) override
;
176 void DrawWidget(const Rect
&r
, WidgetID widget
) const override
;
177 void OnResize() override
;
178 void OnClick(Point pt
, WidgetID widget
, int click_count
) override
;
179 void OnInvalidateData(int data
= 0, bool gui_scope
= true) override
;
180 EventState
OnHotkey(int hotkey
) override
;
181 void OnEditboxChanged(WidgetID wid
) override
;
183 /** Enum referring to the Hotkeys in the picker window */
184 enum PickerClassWindowHotkeys
{
185 PCWHK_FOCUS_FILTER_BOX
, ///< Focus the edit box for editing the filter string
189 void ConstructWindow();
191 PickerCallbacks
&callbacks
;
194 PickerClassList classes
; ///< List of classes.
195 PickerFilterData class_string_filter
;
196 QueryString class_editbox
; ///< Filter editbox.
198 void BuildPickerClassList();
199 void EnsureSelectedClassIsValid();
200 void EnsureSelectedClassIsVisible();
202 PickerTypeList types
; ///< List of types.
203 PickerFilterData type_string_filter
;
204 QueryString type_editbox
; ///< Filter editbox
206 void RefreshUsedTypeList();
207 void BuildPickerTypeList();
208 void EnsureSelectedTypeIsValid();
209 void EnsureSelectedTypeIsVisible();
211 IntervalTimer
<TimerGameCalendar
> yearly_interval
= {{TimerGameCalendar::YEAR
, TimerGameCalendar::Priority::NONE
}, [this](auto) {
215 IntervalTimer
<TimerWindow
> refresh_interval
= {std::chrono::seconds(3), [this](auto) {
216 RefreshUsedTypeList();
221 std::unique_ptr
<NWidgetBase
> MakePickerClassWidgets();
222 std::unique_ptr
<NWidgetBase
> MakePickerTypeWidgets();
224 #endif /* PICKER_GUI_H */