OpenTTD Source  20240917-master-g9ab0a47812
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"
16 #include "timer/timer_game_tick.h"
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 
30 struct Listing {
31  bool order;
32  uint8_t criteria;
33 };
35 struct Filtering {
36  bool state;
37  uint8_t criteria;
38 };
39 
46 template <typename T, typename P = std::nullptr_t, typename F = const char*>
47 class GUIList : public std::vector<T> {
48 public:
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 
52 protected:
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 
84 public:
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() :
88  sort_func_list({}),
89  filter_func_list({}),
90  flags(VL_NONE),
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({}),
101  filter_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 
222  bool NeedResort()
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 
236  void ForceResort()
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 
409  void RebuildDone()
410  {
411  CLRBITS(this->flags, VL_REBUILD);
412  SETBITS(this->flags, VL_RESORT);
413  }
414 };
415 
416 #endif /* SORTLIST_TYPE_H */
Filtering::criteria
uint8_t criteria
Filtering criteria.
Definition: sortlist_type.h:37
GUIList::Filter
bool Filter(F filter_data)
Filter the data with the currently selected filter.
Definition: sortlist_type.h:380
GUIList::IsSortable
bool IsSortable() const
Check if the list is sortable.
Definition: sortlist_type.h:70
GUIList::ResetResortTimer
void ResetResortTimer()
Reset the resort timer.
Definition: sortlist_type.h:78
mem_func.hpp
GUIList::SetFilterState
void SetFilterState(bool state)
Enable or disable the filter.
Definition: sortlist_type.h:330
GUIList::sort_func_list
std::span< SortFunction *const > sort_func_list
the sort criteria functions
Definition: sortlist_type.h:53
Filtering::state
bool state
Filter on/off.
Definition: sortlist_type.h:36
GUIList
List template of 'things' T to sort in a GUI.
Definition: sortlist_type.h:47
VL_RESORT
@ VL_RESORT
instruct the code to resort the list in the next loop
Definition: sortlist_type.h:22
SortListFlags
SortListFlags
Flags of the sort list.
Definition: sortlist_type.h:19
GUIList::filter_type
uint8_t filter_type
what criteria to filter on
Definition: sortlist_type.h:57
GUIList::SetSortType
void SetSortType(uint8_t n_type)
Set the sorttype of the list.
Definition: sortlist_type.h:124
GUIList::SetFilterFuncs
void SetFilterFuncs(std::span< FilterFunction *const > n_funcs)
Hand the filter function pointers to the GUIList.
Definition: sortlist_type.h:369
GUIList::resort_timer
uint16_t resort_timer
resort list after a given amount of ticks if set
Definition: sortlist_type.h:58
GUIList::NeedRebuild
bool NeedRebuild() const
Check if a rebuild is needed.
Definition: sortlist_type.h:391
SETBITS
#define SETBITS(x, y)
Sets several bits in a variable.
Definition: bitmath_func.hpp:136
GUIList::Sort
bool Sort()
Overload of #Sort(SortFunction *compare) Overloaded to reduce external code.
Definition: sortlist_type.h:308
bitmath_func.hpp
GUIList::GetFiltering
Filtering GetFiltering() const
Export current filter conditions.
Definition: sortlist_type.h:190
VL_FILTER
@ VL_FILTER
filter disabled/enabled
Definition: sortlist_type.h:24
GUIList::NeedResort
bool NeedResort()
Check if a resort is needed next loop If used the resort timer will decrease every call till 0.
Definition: sortlist_type.h:222
Listing
Data structure describing how to show the list (what sort direction and criteria).
Definition: sortlist_type.h:30
GUIList::flags
SortListFlags flags
used to control sorting/resorting/etc.
Definition: sortlist_type.h:55
GUIList::Filter
bool Filter(FilterFunction *decide, F filter_data)
Filter the list.
Definition: sortlist_type.h:346
GUIList< BuildBridgeData >::SortFunction
std::conditional_t< std::is_same_v< std::nullptr_t, std::nullptr_t >, bool(const BuildBridgeData &, const BuildBridgeData &), bool(const BuildBridgeData &, const BuildBridgeData &, const std::nullptr_t)> SortFunction
Signature of sort function.
Definition: sortlist_type.h:49
GUIList::ForceResort
void ForceResort()
Force a resort next Sort call Reset the resort timer if used too.
Definition: sortlist_type.h:236
Listing::order
bool order
Ascending/descending.
Definition: sortlist_type.h:31
GUIList::ToggleSortOrder
void ToggleSortOrder()
Toggle the sort order Since that is the worst condition for the sort function reverse the list here.
Definition: sortlist_type.h:256
GUIList::FilterType
uint8_t FilterType() const
Get the filtertype of the list.
Definition: sortlist_type.h:167
Filtering
Data structure describing what to show in the list (filter criteria).
Definition: sortlist_type.h:35
timer_game_tick.h
GUIList::IsDescSortOrder
bool IsDescSortOrder() const
Check if the sort order is descending.
Definition: sortlist_type.h:246
GUIList< BuildBridgeData >::FilterFunction
bool(const BuildBridgeData *, const char *) FilterFunction
Signature of filter function.
Definition: sortlist_type.h:50
Listing::criteria
uint8_t criteria
Sorting criteria.
Definition: sortlist_type.h:32
GUIList::ForceRebuild
void ForceRebuild()
Force that a rebuild is needed.
Definition: sortlist_type.h:399
VL_DESC
@ VL_DESC
sort descending or ascending
Definition: sortlist_type.h:21
GUIList::GetListing
Listing GetListing() const
Export current sort conditions.
Definition: sortlist_type.h:138
GUIList::filter_func_list
std::span< FilterFunction *const > filter_func_list
the filter criteria functions
Definition: sortlist_type.h:54
enum_type.hpp
DECLARE_ENUM_AS_BIT_SET
DECLARE_ENUM_AS_BIT_SET(GenderEthnicity) enum CompanyManagerFaceVariable
Bitgroups of the CompanyManagerFace variable.
Definition: company_manager_face.h:29
GUIList::SortType
uint8_t SortType() const
Get the sorttype of the list.
Definition: sortlist_type.h:114
GUIList::RebuildDone
void RebuildDone()
Notify the sortlist that the rebuild is done.
Definition: sortlist_type.h:409
GUIList::IsFilterEnabled
bool IsFilterEnabled() const
Check if the filter is enabled.
Definition: sortlist_type.h:320
Ticks::DAY_TICKS
static constexpr TimerGameTick::Ticks DAY_TICKS
1 day is 74 ticks; TimerGameCalendar::date_fract used to be uint16_t and incremented by 885.
Definition: timer_game_tick.h:75
VL_NONE
@ VL_NONE
no sort
Definition: sortlist_type.h:20
VL_REBUILD
@ VL_REBUILD
rebuild the sort list
Definition: sortlist_type.h:23
GUIList::Sort
bool Sort(Comp compare)
Sort the list.
Definition: sortlist_type.h:270
GUIList::sort_type
uint8_t sort_type
what criteria to sort on
Definition: sortlist_type.h:56
CLRBITS
#define CLRBITS(x, y)
Clears several bits in a variable.
Definition: bitmath_func.hpp:166
GUIList::SetFiltering
void SetFiltering(Filtering f)
Import filter conditions.
Definition: sortlist_type.h:204
GUIList::SetFilterType
void SetFilterType(uint8_t n_type)
Set the filtertype of the list.
Definition: sortlist_type.h:177
GUIList::SetSortFuncs
void SetSortFuncs(std::span< SortFunction *const > n_funcs)
Hand the sort function pointers to the GUIList.
Definition: sortlist_type.h:297
GUIList::SetListing
void SetListing(Listing l)
Import sort conditions.
Definition: sortlist_type.h:152