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/>.
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. */
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
31 DECLARE_ENUM_AS_BIT_SET(SortListFlags
)
33 /** Data structure describing how to show the list (what sort direction and criteria). */
35 bool order
; ///< Ascending/descending
36 byte criteria
; ///< Sorting criteria
38 /** Data structure describing what to show in the list (filter criteria). */
40 bool state
; ///< Filter on/off
41 byte criteria
; ///< Filtering criteria
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> {
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.
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
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);
74 * Reset the resort timer
76 void ResetResortTimer()
78 /* Resort every 10 days */
79 this->resort_timer
= DAY_TICKS
* 10;
85 filter_func_list(NULL
),
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
123 l
.order
= (this->flags
& VL_DESC
) != 0;
124 l
.criteria
= this->sort_type
;
130 * Import sort conditions
132 * @param l The sort conditions we want to use
134 void SetListing(Listing l
)
137 SETBITS(this->flags
, VL_DESC
);
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
176 f
.state
= (this->flags
& VL_FILTER
) != 0;
177 f
.criteria
= this->filter_type
;
183 * Import filter conditions
185 * @param f The filter conditions we want to use
187 void SetFiltering(Filtering f
)
190 SETBITS(this->flags
, VL_FILTER
);
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
207 if (--this->resort_timer
== 0) {
208 SETBITS(this->flags
, VL_RESORT
);
209 this->ResetResortTimer();
216 * Force a resort next Sort call
217 * Reset the resort timer if used too.
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
);
248 * For the first sorting we use quick sort since it is
249 * faster for irregular sorted data. After that we
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
);
277 GSortT(this->data
, this->items
, compare
, desc
);
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
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
)
321 SETBITS(this->flags
, VL_FILTER
);
323 CLRBITS(this->flags
, VL_FILTER
);
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
)) {
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
389 SETBITS(this->flags
, VL_REBUILD
);
393 * Notify the sortlist that the rebuild is done
395 * @note This forces a resort
399 CLRBITS(this->flags
, VL_REBUILD
);
400 SETBITS(this->flags
, VL_RESORT
| VL_FIRST_SORT
);
404 #endif /* SORTLIST_TYPE_H */