Rearrange storage of reserved tracks for railway tiles
[openttd/fttd.git] / src / sortlist_type.h
blob1a30c3b1a8640265018dba219b849a78765424e2
1 /* $Id$ */
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 */
10 /** @file sortlist_type.h Base types for having sorted lists in GUIs. */
12 #ifndef SORTLIST_TYPE_H
13 #define SORTLIST_TYPE_H
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"
21 /** Flags of the sort list. */
22 enum SortListFlags {
23 VL_NONE = 0, ///< no sort
24 VL_DESC = 1 << 0, ///< sort descending or ascending
25 VL_RESORT = 1 << 1, ///< instruct the code to resort the list in the next loop
26 VL_REBUILD = 1 << 2, ///< rebuild the sort list
27 VL_FIRST_SORT = 1 << 3, ///< sort with quick sort first
28 VL_FILTER = 1 << 4, ///< filter disabled/enabled
29 VL_END = 1 << 5,
31 DECLARE_ENUM_AS_BIT_SET(SortListFlags)
33 /** Data structure describing how to show the list (what sort direction and criteria). */
34 struct Listing {
35 bool order; ///< Ascending/descending
36 byte criteria; ///< Sorting criteria
38 /** Data structure describing what to show in the list (filter criteria). */
39 struct Filtering {
40 bool state; ///< Filter on/off
41 byte criteria; ///< Filtering criteria
44 /**
45 * List template of 'things' \p T to sort in a GUI.
46 * @tparam T Type of data stored in the list to represent each item.
47 * @tparam F Type of data fed as additional value to the filter function. @see FilterFunction
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*); ///< Signature of sort function.
53 typedef bool CDECL FilterFunction(const T*, F); ///< Signature of filter function.
55 protected:
56 SortFunction * const *sort_func_list; ///< the sort criteria functions
57 FilterFunction * const *filter_func_list; ///< the filter criteria functions
58 SortListFlags flags; ///< used to control sorting/resorting/etc.
59 uint8 sort_type; ///< what criteria to sort on
60 uint8 filter_type; ///< what criteria to filter on
61 uint16 resort_timer; ///< resort list after a given amount of ticks if set
63 /**
64 * Check if the list is sortable
66 * @return true if we can sort the list
68 bool IsSortable() const
70 return (this->data != NULL && this->items >= 2);
73 /**
74 * Reset the resort timer
76 void ResetResortTimer()
78 /* Resort every 10 days */
79 this->resort_timer = DAY_TICKS * 10;
82 public:
83 GUIList() :
84 sort_func_list(NULL),
85 filter_func_list(NULL),
86 flags(VL_FIRST_SORT),
87 sort_type(0),
88 filter_type(0),
89 resort_timer(1)
90 {};
92 /**
93 * Get the sorttype of the list
95 * @return The current sorttype
97 uint8 SortType() const
99 return this->sort_type;
103 * Set the sorttype of the list
105 * @param n_type the new sort type
107 void SetSortType(uint8 n_type)
109 if (this->sort_type != n_type) {
110 SETBITS(this->flags, VL_RESORT | VL_FIRST_SORT);
111 this->sort_type = n_type;
116 * Export current sort conditions
118 * @return the current sort conditions
120 Listing GetListing() const
122 Listing l;
123 l.order = (this->flags & VL_DESC) != 0;
124 l.criteria = this->sort_type;
126 return l;
130 * Import sort conditions
132 * @param l The sort conditions we want to use
134 void SetListing(Listing l)
136 if (l.order) {
137 SETBITS(this->flags, VL_DESC);
138 } else {
139 CLRBITS(this->flags, VL_DESC);
141 this->sort_type = l.criteria;
143 SETBITS(this->flags, VL_FIRST_SORT);
147 * Get the filtertype of the list
149 * @return The current filtertype
151 uint8 FilterType() const
153 return this->filter_type;
157 * Set the filtertype of the list
159 * @param n_type the new filter type
161 void SetFilterType(uint8 n_type)
163 if (this->filter_type != n_type) {
164 this->filter_type = n_type;
169 * Export current filter conditions
171 * @return the current filter conditions
173 Filtering GetFiltering() const
175 Filtering f;
176 f.state = (this->flags & VL_FILTER) != 0;
177 f.criteria = this->filter_type;
179 return f;
183 * Import filter conditions
185 * @param f The filter conditions we want to use
187 void SetFiltering(Filtering f)
189 if (f.state) {
190 SETBITS(this->flags, VL_FILTER);
191 } else {
192 CLRBITS(this->flags, VL_FILTER);
194 this->filter_type = f.criteria;
198 * Check if a resort is needed next loop
199 * If used the resort timer will decrease every call
200 * till 0. If 0 reached the resort bit will be set and
201 * the timer will be reset.
203 * @return true if resort bit is set for next loop
205 bool NeedResort()
207 if (--this->resort_timer == 0) {
208 SETBITS(this->flags, VL_RESORT);
209 this->ResetResortTimer();
210 return true;
212 return false;
216 * Force a resort next Sort call
217 * Reset the resort timer if used too.
219 void ForceResort()
221 SETBITS(this->flags, VL_RESORT);
225 * Check if the sort order is descending
227 * @return true if the sort order is descending
229 bool IsDescSortOrder() const
231 return (this->flags & VL_DESC) != 0;
235 * Toggle the sort order
236 * Since that is the worst condition for the sort function
237 * reverse the list here.
239 void ToggleSortOrder()
241 this->flags ^= VL_DESC;
243 if (this->IsSortable()) MemReverseT(this->data, this->items);
247 * Sort the list.
248 * For the first sorting we use quick sort since it is
249 * faster for irregular sorted data. After that we
250 * use gsort.
252 * @param compare The function to compare two list items
253 * @return true if the list sequence has been altered
256 bool Sort(SortFunction *compare)
258 /* Do not sort if the resort bit is not set */
259 if (!(this->flags & VL_RESORT)) return false;
261 CLRBITS(this->flags, VL_RESORT);
263 this->ResetResortTimer();
265 /* Do not sort when the list is not sortable */
266 if (!this->IsSortable()) return false;
268 const bool desc = (this->flags & VL_DESC) != 0;
270 if (this->flags & VL_FIRST_SORT) {
271 CLRBITS(this->flags, VL_FIRST_SORT);
273 QSortT(this->data, this->items, compare, desc);
274 return true;
277 GSortT(this->data, this->items, compare, desc);
278 return true;
282 * Hand the array of sort function pointers to the sort list
284 * @param n_funcs The pointer to the first sort func
286 void SetSortFuncs(SortFunction * const *n_funcs)
288 this->sort_func_list = n_funcs;
292 * Overload of #Sort(SortFunction *compare)
293 * Overloaded to reduce external code
295 * @return true if the list sequence has been altered
297 bool Sort()
299 assert(this->sort_func_list != NULL);
300 return this->Sort(this->sort_func_list[this->sort_type]);
304 * Check if the filter is enabled
306 * @return true if the filter is enabled
308 bool IsFilterEnabled() const
310 return (this->flags & VL_FILTER) != 0;
314 * Enable or disable the filter
316 * @param state If filtering should be enabled or disabled
318 void SetFilterState(bool state)
320 if (state) {
321 SETBITS(this->flags, VL_FILTER);
322 } else {
323 CLRBITS(this->flags, VL_FILTER);
328 * Filter the list.
330 * @param decide The function to decide about an item
331 * @param filter_data Additional data passed to the filter function
332 * @return true if the list has been altered by filtering
334 bool Filter(FilterFunction *decide, F filter_data)
336 /* Do not filter if the filter bit is not set */
337 if (!(this->flags & VL_FILTER)) return false;
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++;
350 return changed;
354 * Hand the array of filter function pointers to the sort list
356 * @param n_funcs The pointer to the first filter func
358 void SetFilterFuncs(FilterFunction * const *n_funcs)
360 this->filter_func_list = n_funcs;
364 * Filter the data with the currently selected filter.
366 * @param filter_data Additional data passed to the filter function.
367 * @return true if the list has been altered by filtering
369 bool Filter(F filter_data)
371 if (this->filter_func_list == NULL) return false;
372 return this->Filter(this->filter_func_list[this->filter_type], filter_data);
376 * Check if a rebuild is needed
377 * @return true if a rebuild is needed
379 bool NeedRebuild() const
381 return (this->flags & VL_REBUILD) != 0;
385 * Force that a rebuild is needed
387 void ForceRebuild()
389 SETBITS(this->flags, VL_REBUILD);
393 * Notify the sortlist that the rebuild is done
395 * @note This forces a resort
397 void RebuildDone()
399 CLRBITS(this->flags, VL_REBUILD);
400 SETBITS(this->flags, VL_RESORT | VL_FIRST_SORT);
404 #endif /* SORTLIST_TYPE_H */