Files
@ r11281:2a8f284d1a02
Branch filter:
Location: cpp/openttd-patchpack/source/src/sortlist_type.h
r11281:2a8f284d1a02
8.1 KiB
text/x-c
(svn r15635) -Fix [FS#2707]: don't allow more than 64 road vehicles to reserve a slot at a single road stop. 255 + 1 gives trouble, but 64 is even more than the roadstop would be able to handle within the slot timeout time.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 | /* $Id$ */
/** @file sortlist_type.h Base types for having sorted lists in GUIs. */
#ifndef SORTLIST_TYPE_H
#define SORTLIST_TYPE_H
#include "core/enum_type.hpp"
#include "core/bitmath_func.hpp"
#include "core/mem_func.hpp"
#include "core/sort_func.hpp"
#include "core/smallvec_type.hpp"
#include "date_type.h"
enum SortListFlags {
VL_NONE = 0, ///< no sort
VL_DESC = 1 << 0, ///< sort descending or ascending
VL_RESORT = 1 << 1, ///< instruct the code to resort the list in the next loop
VL_REBUILD = 1 << 2, ///< rebuild the sort list
VL_FIRST_SORT = 1 << 3, ///< sort with qsort first
VL_FILTER = 1 << 4, ///< filter disabled/enabled
VL_END = 1 << 5,
};
DECLARE_ENUM_AS_BIT_SET(SortListFlags);
struct Listing {
bool order; ///< Ascending/descending
byte criteria; ///< Sorting criteria
};
struct Filtering {
bool state; ///< Filter on/off
byte criteria; ///< Filtering criteria
};
template <typename T, typename F = const char*>
class GUIList : public SmallVector<T, 32> {
public:
typedef int CDECL SortFunction(const T*, const T*);
typedef bool CDECL FilterFunction(const T*, F);
protected:
SortFunction * const *sort_func_list; ///< the sort criteria functions
FilterFunction * const *filter_func_list; ///< the filter criteria functions
SortListFlags flags; ///< used to control sorting/resorting/etc.
uint8 sort_type; ///< what criteria to sort on
uint8 filter_type; ///< what criteria to filter on
uint16 resort_timer; ///< resort list after a given amount of ticks if set
/**
* Check if the list is sortable
*
* @return true if we can sort the list
*/
bool IsSortable() const
{
return (this->data != NULL && this->items >= 2);
}
/**
* Reset the resort timer
*/
void ResetResortTimer()
{
/* Resort every 10 days */
this->resort_timer = DAY_TICKS * 10;
}
public:
GUIList() :
sort_func_list(NULL),
filter_func_list(NULL),
flags(VL_FIRST_SORT),
sort_type(0),
filter_type(0),
resort_timer(1)
{};
/**
* Get the sorttype of the list
*
* @return The current sorttype
*/
uint8 SortType() const
{
return this->sort_type;
}
/**
* Set the sorttype of the list
*
* @param n_type the new sort type
*/
void SetSortType(uint8 n_type)
{
if (this->sort_type != n_type) {
SETBITS(this->flags, VL_RESORT | VL_FIRST_SORT);
this->sort_type = n_type;
}
}
/**
* Export current sort conditions
*
* @return the current sort conditions
*/
Listing GetListing() const
{
Listing l;
l.order = HASBITS(this->flags, VL_DESC);
l.criteria = this->sort_type;
return l;
}
/**
* Import sort conditions
*
* @param l The sort conditions we want to use
*/
void SetListing(Listing l)
{
if (l.order) {
SETBITS(this->flags, VL_DESC);
} else {
CLRBITS(this->flags, VL_DESC);
}
this->sort_type = l.criteria;
SETBITS(this->flags, VL_FIRST_SORT);
}
/**
* Get the filtertype of the list
*
* @return The current filtertype
*/
uint8 FilterType() const
{
return this->filter_type;
}
/**
* Set the filtertype of the list
*
* @param n_type the new filter type
*/
void SetFilterType(uint8 n_type)
{
if (this->filter_type != n_type) {
this->filter_type = n_type;
}
}
/**
* Export current filter conditions
*
* @return the current filter conditions
*/
Filtering GetFiltering() const
{
Filtering f;
f.state = HASBITS(this->flags, VL_FILTER);
f.criteria = this->filter_type;
return f;
}
/**
* Import filter conditions
*
* @param f The filter conditions we want to use
*/
void SetFiltering(Filtering f)
{
if (f.state) {
SETBITS(this->flags, VL_FILTER);
} else {
CLRBITS(this->flags, VL_FILTER);
}
this->filter_type = f.criteria;
}
/**
* Check if a resort is needed next loop
* If used the resort timer will decrease every call
* till 0. If 0 reached the resort bit will be set and
* the timer will be reset.
*
* @return true if resort bit is set for next loop
*/
bool NeedResort()
{
if (--this->resort_timer == 0) {
SETBITS(this->flags, VL_RESORT);
this->ResetResortTimer();
return true;
}
return false;
}
/**
* Force a resort next Sort call
* Reset the resort timer if used too.
*/
void ForceResort()
{
SETBITS(this->flags, VL_RESORT);
}
/**
* Check if the sort order is descending
*
* @return true if the sort order is descending
*/
bool IsDescSortOrder() const
{
return HASBITS(this->flags, VL_DESC);
}
/**
* Toogle the sort order
* Since that is the worst condition for the sort function
* reverse the list here.
*/
void ToggleSortOrder()
{
this->flags ^= VL_DESC;
if (this->IsSortable()) MemReverseT(this->data, this->items);
}
/**
* Sort the list.
* For the first sorting we use qsort since it is
* faster for irregular sorted data. After that we
* use gsort.
*
* @param compare The function to compare two list items
* @return true if the list sequence has been altered
* */
bool Sort(SortFunction *compare)
{
/* Do not sort if the resort bit is not set */
if (!HASBITS(this->flags, VL_RESORT)) return false;
CLRBITS(this->flags, VL_RESORT);
this->ResetResortTimer();
/* Do not sort when the list is not sortable */
if (!this->IsSortable()) return false;
const bool desc = HASBITS(this->flags, VL_DESC);
if (HASBITS(this->flags, VL_FIRST_SORT)) {
CLRBITS(this->flags, VL_FIRST_SORT);
QSortT(this->data, this->items, compare, desc);
return true;
}
GSortT(this->data, this->items, compare, desc);
return true;
}
/**
* Hand the array of sort function pointers to the sort list
*
* @param n_funcs The pointer to the first sort func
*/
void SetSortFuncs(SortFunction * const *n_funcs)
{
this->sort_func_list = n_funcs;
}
/**
* Overload of Sort()
* Overloaded to reduce external code
*
* @return true if the list sequence has been altered
*/
bool Sort()
{
assert(this->sort_func_list != NULL);
return this->Sort(this->sort_func_list[this->sort_type]);
}
/**
* Check if the filter is enabled
*
* @return true if the filter is enabled
*/
bool IsFilterEnabled() const
{
return HASBITS(this->flags, VL_FILTER);
}
/**
* Enable or disable the filter
*
* @param state If filtering should be enabled or disabled
*/
void SetFilterState(bool state)
{
if (state) {
SETBITS(this->flags, VL_FILTER);
} else {
CLRBITS(this->flags, VL_FILTER);
}
}
/**
* Filter the list.
*
* @param decide The function to decide about an item
* @param filter_data Additional data passed to the filter function
* @return true if the list has been altered by filtering
*/
bool Filter(FilterFunction *decide, F filter_data)
{
/* Do not filter if the filter bit is not set */
if (!HASBITS(this->flags, VL_FILTER)) return false;
bool changed = false;
for (uint iter = 0; iter < this->items;) {
T *item = &this->data[iter];
if (!decide(item, filter_data)) {
this->Erase(item);
changed = true;
} else {
iter++;
}
}
return changed;
}
/**
* Hand the array of filter function pointers to the sort list
*
* @param n_funcs The pointer to the first filter func
*/
void SetFilterFuncs(FilterFunction * const *n_funcs)
{
this->filter_func_list = n_funcs;
}
/**
* Filter the data with the currently selected filter.
*
* @param filter_data Additional data passed to the filter function.
* @return true if the list has been altered by filtering
*/
bool Filter(F filter_data)
{
if (this->filter_func_list == NULL) return false;
return this->Filter(this->filter_func_list[this->filter_type], filter_data);
}
/**
* Check if a rebuild is needed
* @return true if a rebuild is needed
*/
bool NeedRebuild() const
{
return HASBITS(this->flags, VL_REBUILD);
}
/**
* Force that a rebuild is needed
*/
void ForceRebuild()
{
SETBITS(this->flags, VL_REBUILD);
}
/**
* Notify the sortlist that the rebuild is done
*
* @note This forces a resort
*/
void RebuildDone()
{
CLRBITS(this->flags, VL_REBUILD);
SETBITS(this->flags, VL_RESORT | VL_FIRST_SORT);
}
};
#endif /* SORTLIST_TYPE_H */
|