OpenTTD Source 15.0-beta1
sortlist_type.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 <http://www.gnu.org/licenses/>.
6 */
7
10#ifndef SORTLIST_TYPE_H
11#define SORTLIST_TYPE_H
12
13#include "core/enum_type.hpp"
14#include "core/bitmath_func.hpp"
15#include "core/mem_func.hpp"
17
20 VL_NONE = 0,
21 VL_DESC = 1 << 0,
22 VL_RESORT = 1 << 1,
23 VL_REBUILD = 1 << 2,
24 VL_FILTER = 1 << 3,
25 VL_END = 1 << 4,
26};
28
29
30struct Listing {
31 bool order;
32 uint8_t criteria;
33};
35struct Filtering {
36 bool state;
37 uint8_t criteria;
38};
39
46template <typename T, typename P = std::nullptr_t, typename F = const char*>
47class GUIList : public std::vector<T> {
48public:
49 using SortFunction = std::conditional_t<std::is_same_v<P, std::nullptr_t>, bool (const T&, const T&), bool (const T&, const T&, const P)>;
50 using FilterFunction = bool(const T*, F);
51
52protected:
53 std::span<SortFunction * const> sort_func_list;
54 std::span<FilterFunction * const> filter_func_list;
56 uint8_t sort_type;
57 uint8_t filter_type;
58 uint16_t resort_timer;
59
60 /* If sort parameters are used then params must be a reference, however if not then params cannot be a reference as
61 * it will not be able to reference anything. */
62 using SortParameterReference = std::conditional_t<std::is_same_v<P, std::nullptr_t>, P, P&>;
63 const SortParameterReference params;
64
70 bool IsSortable() const
71 {
72 return std::vector<T>::size() >= 2;
73 }
74
79 {
80 /* Resort every 10 days */
81 this->resort_timer = Ticks::DAY_TICKS * 10;
82 }
83
84public:
85 /* If sort parameters are not used then we don't require a reference to the params. */
86 template <typename T_ = T, typename P_ = P, typename _F = F, std::enable_if_t<std::is_same_v<P_, std::nullptr_t>>* = nullptr>
87 GUIList() :
91 sort_type(0),
92 filter_type(0),
93 resort_timer(1),
94 params(nullptr)
95 {};
96
97 /* If sort parameters are used then we require a reference to the params. */
98 template <typename T_ = T, typename P_ = P, typename _F = F, std::enable_if_t<!std::is_same_v<P_, std::nullptr_t>>* = nullptr>
99 GUIList(const P &params) :
100 sort_func_list({}),
102 flags(VL_NONE),
103 sort_type(0),
104 filter_type(0),
105 resort_timer(1),
106 params(params)
107 {};
108
114 uint8_t SortType() const
115 {
116 return this->sort_type;
117 }
118
124 void SetSortType(uint8_t n_type)
125 {
126 assert(n_type < std::size(this->sort_func_list));
127 if (this->sort_type != n_type) {
128 SETBITS(this->flags, VL_RESORT);
129 this->sort_type = n_type;
130 }
131 }
132
139 {
140 Listing l;
141 l.order = (this->flags & VL_DESC) != 0;
142 l.criteria = this->sort_type;
143
144 return l;
145 }
146
153 {
154 if (l.order) {
155 SETBITS(this->flags, VL_DESC);
156 } else {
157 CLRBITS(this->flags, VL_DESC);
158 }
159 this->sort_type = l.criteria;
160 }
161
167 uint8_t FilterType() const
168 {
169 return this->filter_type;
170 }
171
177 void SetFilterType(uint8_t n_type)
178 {
179 assert(n_type < std::size(this->filter_func_list));
180 if (this->filter_type != n_type) {
181 this->filter_type = n_type;
182 }
183 }
184
191 {
192 Filtering f;
193 f.state = (this->flags & VL_FILTER) != 0;
194 f.criteria = this->filter_type;
195
196 return f;
197 }
198
205 {
206 if (f.state) {
207 SETBITS(this->flags, VL_FILTER);
208 } else {
209 CLRBITS(this->flags, VL_FILTER);
210 }
211 this->filter_type = f.criteria;
212 }
213
223 {
224 if (--this->resort_timer == 0) {
225 SETBITS(this->flags, VL_RESORT);
226 this->ResetResortTimer();
227 return true;
228 }
229 return false;
230 }
231
237 {
238 SETBITS(this->flags, VL_RESORT);
239 }
240
246 bool IsDescSortOrder() const
247 {
248 return (this->flags & VL_DESC) != 0;
249 }
250
257 {
258 this->flags ^= VL_DESC;
259
260 if (this->IsSortable()) std::reverse(std::vector<T>::begin(), std::vector<T>::end());
261 }
262
269 template <typename Comp>
270 bool Sort(Comp compare)
271 {
272 /* Do not sort if the resort bit is not set */
273 if (!(this->flags & VL_RESORT)) return false;
274
275 CLRBITS(this->flags, VL_RESORT);
276
277 this->ResetResortTimer();
278
279 /* Do not sort when the list is not sortable */
280 if (!this->IsSortable()) return false;
281
282 const bool desc = (this->flags & VL_DESC) != 0;
283
284 if constexpr (std::is_same_v<P, std::nullptr_t>) {
285 std::sort(std::vector<T>::begin(), std::vector<T>::end(), [&](const T &a, const T &b) { return desc ? compare(b, a) : compare(a, b); });
286 } else {
287 std::sort(std::vector<T>::begin(), std::vector<T>::end(), [&](const T &a, const T &b) { return desc ? compare(b, a, params) : compare(a, b, params); });
288 }
289 return true;
290 }
291
297 void SetSortFuncs(std::span<SortFunction * const> n_funcs)
298 {
299 this->sort_func_list = n_funcs;
300 }
301
308 bool Sort()
309 {
310 if (this->sort_func_list.empty()) return false;
311 assert(this->sort_type < this->sort_func_list.size());
312 return this->Sort(this->sort_func_list[this->sort_type]);
313 }
314
320 bool IsFilterEnabled() const
321 {
322 return (this->flags & VL_FILTER) != 0;
323 }
324
330 void SetFilterState(bool state)
331 {
332 if (state) {
333 SETBITS(this->flags, VL_FILTER);
334 } else {
335 CLRBITS(this->flags, VL_FILTER);
336 }
337 }
338
346 bool Filter(FilterFunction *decide, F filter_data)
347 {
348 /* Do not filter if the filter bit is not set */
349 if (!(this->flags & VL_FILTER)) return false;
350
351 bool changed = false;
352 for (auto it = std::vector<T>::begin(); it != std::vector<T>::end(); /* Nothing */) {
353 if (!decide(&*it, filter_data)) {
354 it = std::vector<T>::erase(it);
355 changed = true;
356 } else {
357 it++;
358 }
359 }
360
361 return changed;
362 }
363
369 void SetFilterFuncs(std::span<FilterFunction * const> n_funcs)
370 {
371 this->filter_func_list = n_funcs;
372 }
373
380 bool Filter(F filter_data)
381 {
382 if (this->filter_func_list.empty()) return false;
383 assert(this->filter_type < this->filter_func_list.size());
384 return this->Filter(this->filter_func_list[this->filter_type], filter_data);
385 }
386
391 bool NeedRebuild() const
392 {
393 return (this->flags & VL_REBUILD) != 0;
394 }
395
400 {
401 SETBITS(this->flags, VL_REBUILD);
402 }
403
410 {
411 CLRBITS(this->flags, VL_REBUILD);
412 SETBITS(this->flags, VL_RESORT);
413 }
414};
415
416#endif /* SORTLIST_TYPE_H */
Functions related to bit mathematics.
#define CLRBITS(x, y)
Clears several bits in a variable.
#define SETBITS(x, y)
Sets several bits in a variable.
List template of 'things' T to sort in a GUI.
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.
bool IsSortable() const
Check if the list is sortable.
uint16_t resort_timer
resort list after a given amount of ticks if set
void SetFilterState(bool state)
Enable or disable the filter.
bool IsDescSortOrder() const
Check if the sort order is descending.
void ToggleSortOrder()
Toggle the sort order Since that is the worst condition for the sort function reverse the list here.
bool(const T *, F) FilterFunction
Signature of filter function.
void SetFilterFuncs(std::span< FilterFunction *const > n_funcs)
Hand the filter function pointers to the GUIList.
Filtering GetFiltering() const
Export current filter conditions.
bool NeedRebuild() const
Check if a rebuild is needed.
void SetFilterType(uint8_t n_type)
Set the filtertype of the list.
std::span< FilterFunction *const > filter_func_list
the filter criteria functions
void ResetResortTimer()
Reset the resort timer.
void ForceRebuild()
Force that a rebuild is needed.
bool IsFilterEnabled() const
Check if the filter is enabled.
std::conditional_t< std::is_same_v< P, std::nullptr_t >, bool(const T &, const T &), bool(const T &, const T &, const P)> SortFunction
Signature of sort function.
std::span< SortFunction *const > sort_func_list
the sort criteria functions
bool Sort(Comp compare)
Sort the list.
void ForceResort()
Force a resort next Sort call Reset the resort timer if used too.
uint8_t SortType() const
Get the sorttype of the list.
bool Filter(F filter_data)
Filter the data with the currently selected filter.
bool Sort()
Overload of #Sort(SortFunction *compare) Overloaded to reduce external code.
Listing GetListing() const
Export current sort conditions.
uint8_t sort_type
what criteria to sort on
void SetSortFuncs(std::span< SortFunction *const > n_funcs)
Hand the sort function pointers to the GUIList.
bool NeedResort()
Check if a resort is needed next loop If used the resort timer will decrease every call till 0.
void SetSortType(uint8_t n_type)
Set the sorttype of the list.
uint8_t filter_type
what criteria to filter on
SortListFlags flags
used to control sorting/resorting/etc.
uint8_t FilterType() const
Get the filtertype of the list.
static constexpr TimerGameTick::Ticks DAY_TICKS
1 day is 74 ticks; TimerGameCalendar::date_fract used to be uint16_t and incremented by 885.
Type (helpers) for enums.
#define DECLARE_ENUM_AS_BIT_SET(enum_type)
Operators to allow to work with enum as with type safe bit set in C++.
Definition enum_type.hpp:35
Functions related to memory operations.
SortListFlags
Flags of the sort list.
@ VL_DESC
sort descending or ascending
@ VL_RESORT
instruct the code to resort the list in the next loop
@ VL_NONE
no sort
@ VL_FILTER
filter disabled/enabled
@ VL_REBUILD
rebuild the sort list
Data structure describing what to show in the list (filter criteria).
uint8_t criteria
Filtering criteria.
bool state
Filter on/off.
Data structure describing how to show the list (what sort direction and criteria).
uint8_t criteria
Sorting criteria.
bool order
Ascending/descending.
Definition of the tick-based game-timer.