OpenTTD
sortlist_type.h
Go to the documentation of this file.
1 /* $Id: sortlist_type.h 24900 2013-01-08 22:46:42Z planetmaker $ */
2 
3 /*
4  * This file is part of OpenTTD.
5  * 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.
6  * 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.
7  * 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  */
9 
12 #ifndef SORTLIST_TYPE_H
13 #define SORTLIST_TYPE_H
14 
15 #include "core/enum_type.hpp"
16 #include "core/bitmath_func.hpp"
17 #include "core/sort_func.hpp"
18 #include "core/smallvec_type.hpp"
19 #include "date_type.h"
20 
23  VL_NONE = 0,
24  VL_DESC = 1 << 0,
25  VL_RESORT = 1 << 1,
26  VL_REBUILD = 1 << 2,
27  VL_FIRST_SORT = 1 << 3,
28  VL_FILTER = 1 << 4,
29  VL_END = 1 << 5,
30 };
32 
33 
34 struct Listing {
35  bool order;
36  byte criteria;
37 };
39 struct Filtering {
40  bool state;
41  byte criteria;
42 };
43 
49 template <typename T, typename F = const char*>
50 class GUIList : public SmallVector<T, 32> {
51 public:
52  typedef int CDECL SortFunction(const T*, const T*);
53  typedef bool CDECL FilterFunction(const T*, F);
54 
55 protected:
59  uint8 sort_type;
60  uint8 filter_type;
61  uint16 resort_timer;
62 
68  bool IsSortable() const
69  {
70  return (this->data != NULL && this->items >= 2);
71  }
72 
77  {
78  /* Resort every 10 days */
79  this->resort_timer = DAY_TICKS * 10;
80  }
81 
82 public:
83  GUIList() :
84  sort_func_list(NULL),
85  filter_func_list(NULL),
87  sort_type(0),
88  filter_type(0),
89  resort_timer(1)
90  {};
91 
97  uint8 SortType() const
98  {
99  return this->sort_type;
100  }
101 
107  void SetSortType(uint8 n_type)
108  {
109  if (this->sort_type != n_type) {
111  this->sort_type = n_type;
112  }
113  }
114 
121  {
122  Listing l;
123  l.order = (this->flags & VL_DESC) != 0;
124  l.criteria = this->sort_type;
125 
126  return l;
127  }
128 
135  {
136  if (l.order) {
137  SETBITS(this->flags, VL_DESC);
138  } else {
139  CLRBITS(this->flags, VL_DESC);
140  }
141  this->sort_type = l.criteria;
142 
143  SETBITS(this->flags, VL_FIRST_SORT);
144  }
145 
151  uint8 FilterType() const
152  {
153  return this->filter_type;
154  }
155 
161  void SetFilterType(uint8 n_type)
162  {
163  if (this->filter_type != n_type) {
164  this->filter_type = n_type;
165  }
166  }
167 
174  {
175  Filtering f;
176  f.state = (this->flags & VL_FILTER) != 0;
177  f.criteria = this->filter_type;
178 
179  return f;
180  }
181 
188  {
189  if (f.state) {
190  SETBITS(this->flags, VL_FILTER);
191  } else {
192  CLRBITS(this->flags, VL_FILTER);
193  }
194  this->filter_type = f.criteria;
195  }
196 
205  bool NeedResort()
206  {
207  if (--this->resort_timer == 0) {
208  SETBITS(this->flags, VL_RESORT);
209  this->ResetResortTimer();
210  return true;
211  }
212  return false;
213  }
214 
219  void ForceResort()
220  {
221  SETBITS(this->flags, VL_RESORT);
222  }
223 
229  bool IsDescSortOrder() const
230  {
231  return (this->flags & VL_DESC) != 0;
232  }
233 
240  {
241  this->flags ^= VL_DESC;
242 
243  if (this->IsSortable()) MemReverseT(this->data, this->items);
244  }
245 
256  bool Sort(SortFunction *compare)
257  {
258  /* Do not sort if the resort bit is not set */
259  if (!(this->flags & VL_RESORT)) return false;
260 
261  CLRBITS(this->flags, VL_RESORT);
262 
263  this->ResetResortTimer();
264 
265  /* Do not sort when the list is not sortable */
266  if (!this->IsSortable()) return false;
267 
268  const bool desc = (this->flags & VL_DESC) != 0;
269 
270  if (this->flags & VL_FIRST_SORT) {
271  CLRBITS(this->flags, VL_FIRST_SORT);
272 
273  QSortT(this->data, this->items, compare, desc);
274  return true;
275  }
276 
277  GSortT(this->data, this->items, compare, desc);
278  return true;
279  }
280 
286  void SetSortFuncs(SortFunction * const *n_funcs)
287  {
288  this->sort_func_list = n_funcs;
289  }
290 
297  bool Sort()
298  {
299  assert(this->sort_func_list != NULL);
300  return this->Sort(this->sort_func_list[this->sort_type]);
301  }
302 
308  bool IsFilterEnabled() const
309  {
310  return (this->flags & VL_FILTER) != 0;
311  }
312 
318  void SetFilterState(bool state)
319  {
320  if (state) {
321  SETBITS(this->flags, VL_FILTER);
322  } else {
323  CLRBITS(this->flags, VL_FILTER);
324  }
325  }
326 
334  bool Filter(FilterFunction *decide, F filter_data)
335  {
336  /* Do not filter if the filter bit is not set */
337  if (!(this->flags & VL_FILTER)) return false;
338 
339  bool changed = false;
340  for (uint iter = 0; iter < this->items;) {
341  T *item = &this->data[iter];
342  if (!decide(item, filter_data)) {
343  this->Erase(item);
344  changed = true;
345  } else {
346  iter++;
347  }
348  }
349 
350  return changed;
351  }
352 
358  void SetFilterFuncs(FilterFunction * const *n_funcs)
359  {
360  this->filter_func_list = n_funcs;
361  }
362 
369  bool Filter(F filter_data)
370  {
371  if (this->filter_func_list == NULL) return false;
372  return this->Filter(this->filter_func_list[this->filter_type], filter_data);
373  }
374 
379  bool NeedRebuild() const
380  {
381  return (this->flags & VL_REBUILD) != 0;
382  }
383 
388  {
389  SETBITS(this->flags, VL_REBUILD);
390  }
391 
397  void RebuildDone()
398  {
399  CLRBITS(this->flags, VL_REBUILD);
401  }
402 };
403 
404 #endif /* SORTLIST_TYPE_H */