sortlist_type.h
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00012 #ifndef SORTLIST_TYPE_H
00013 #define SORTLIST_TYPE_H
00014
00015 #include "core/enum_type.hpp"
00016 #include "core/bitmath_func.hpp"
00017 #include "core/mem_func.hpp"
00018 #include "core/sort_func.hpp"
00019 #include "core/smallvec_type.hpp"
00020 #include "date_type.h"
00021
00023 enum SortListFlags {
00024 VL_NONE = 0,
00025 VL_DESC = 1 << 0,
00026 VL_RESORT = 1 << 1,
00027 VL_REBUILD = 1 << 2,
00028 VL_FIRST_SORT = 1 << 3,
00029 VL_FILTER = 1 << 4,
00030 VL_END = 1 << 5,
00031 };
00032 DECLARE_ENUM_AS_BIT_SET(SortListFlags);
00033
00035 struct Listing {
00036 bool order;
00037 byte criteria;
00038 };
00040 struct Filtering {
00041 bool state;
00042 byte criteria;
00043 };
00044
00050 template <typename T, typename F = const char*>
00051 class GUIList : public SmallVector<T, 32> {
00052 public:
00053 typedef int CDECL SortFunction(const T*, const T*);
00054 typedef bool CDECL FilterFunction(const T*, F);
00055
00056 protected:
00057 SortFunction * const *sort_func_list;
00058 FilterFunction * const *filter_func_list;
00059 SortListFlags flags;
00060 uint8 sort_type;
00061 uint8 filter_type;
00062 uint16 resort_timer;
00063
00069 bool IsSortable() const
00070 {
00071 return (this->data != NULL && this->items >= 2);
00072 }
00073
00077 void ResetResortTimer()
00078 {
00079
00080 this->resort_timer = DAY_TICKS * 10;
00081 }
00082
00083 public:
00084 GUIList() :
00085 sort_func_list(NULL),
00086 filter_func_list(NULL),
00087 flags(VL_FIRST_SORT),
00088 sort_type(0),
00089 filter_type(0),
00090 resort_timer(1)
00091 {};
00092
00098 uint8 SortType() const
00099 {
00100 return this->sort_type;
00101 }
00102
00108 void SetSortType(uint8 n_type)
00109 {
00110 if (this->sort_type != n_type) {
00111 SETBITS(this->flags, VL_RESORT | VL_FIRST_SORT);
00112 this->sort_type = n_type;
00113 }
00114 }
00115
00121 Listing GetListing() const
00122 {
00123 Listing l;
00124 l.order = (this->flags & VL_DESC) != 0;
00125 l.criteria = this->sort_type;
00126
00127 return l;
00128 }
00129
00135 void SetListing(Listing l)
00136 {
00137 if (l.order) {
00138 SETBITS(this->flags, VL_DESC);
00139 } else {
00140 CLRBITS(this->flags, VL_DESC);
00141 }
00142 this->sort_type = l.criteria;
00143
00144 SETBITS(this->flags, VL_FIRST_SORT);
00145 }
00146
00152 uint8 FilterType() const
00153 {
00154 return this->filter_type;
00155 }
00156
00162 void SetFilterType(uint8 n_type)
00163 {
00164 if (this->filter_type != n_type) {
00165 this->filter_type = n_type;
00166 }
00167 }
00168
00174 Filtering GetFiltering() const
00175 {
00176 Filtering f;
00177 f.state = (this->flags & VL_FILTER) != 0;
00178 f.criteria = this->filter_type;
00179
00180 return f;
00181 }
00182
00188 void SetFiltering(Filtering f)
00189 {
00190 if (f.state) {
00191 SETBITS(this->flags, VL_FILTER);
00192 } else {
00193 CLRBITS(this->flags, VL_FILTER);
00194 }
00195 this->filter_type = f.criteria;
00196 }
00197
00206 bool NeedResort()
00207 {
00208 if (--this->resort_timer == 0) {
00209 SETBITS(this->flags, VL_RESORT);
00210 this->ResetResortTimer();
00211 return true;
00212 }
00213 return false;
00214 }
00215
00220 void ForceResort()
00221 {
00222 SETBITS(this->flags, VL_RESORT);
00223 }
00224
00230 bool IsDescSortOrder() const
00231 {
00232 return (this->flags & VL_DESC) != 0;
00233 }
00234
00240 void ToggleSortOrder()
00241 {
00242 this->flags ^= VL_DESC;
00243
00244 if (this->IsSortable()) MemReverseT(this->data, this->items);
00245 }
00246
00256 bool Sort(SortFunction *compare)
00257 {
00258
00259 if (!(this->flags & VL_RESORT)) return false;
00260
00261 CLRBITS(this->flags, VL_RESORT);
00262
00263 this->ResetResortTimer();
00264
00265
00266 if (!this->IsSortable()) return false;
00267
00268 const bool desc = (this->flags & VL_DESC) != 0;
00269
00270 if (this->flags & VL_FIRST_SORT) {
00271 CLRBITS(this->flags, VL_FIRST_SORT);
00272
00273 QSortT(this->data, this->items, compare, desc);
00274 return true;
00275 }
00276
00277 GSortT(this->data, this->items, compare, desc);
00278 return true;
00279 }
00280
00286 void SetSortFuncs(SortFunction * const *n_funcs)
00287 {
00288 this->sort_func_list = n_funcs;
00289 }
00290
00297 bool Sort()
00298 {
00299 assert(this->sort_func_list != NULL);
00300 return this->Sort(this->sort_func_list[this->sort_type]);
00301 }
00302
00308 bool IsFilterEnabled() const
00309 {
00310 return (this->flags & VL_FILTER) != 0;
00311 }
00312
00318 void SetFilterState(bool state)
00319 {
00320 if (state) {
00321 SETBITS(this->flags, VL_FILTER);
00322 } else {
00323 CLRBITS(this->flags, VL_FILTER);
00324 }
00325 }
00326
00334 bool Filter(FilterFunction *decide, F filter_data)
00335 {
00336
00337 if (!(this->flags & VL_FILTER)) return false;
00338
00339 bool changed = false;
00340 for (uint iter = 0; iter < this->items;) {
00341 T *item = &this->data[iter];
00342 if (!decide(item, filter_data)) {
00343 this->Erase(item);
00344 changed = true;
00345 } else {
00346 iter++;
00347 }
00348 }
00349
00350 return changed;
00351 }
00352
00358 void SetFilterFuncs(FilterFunction * const *n_funcs)
00359 {
00360 this->filter_func_list = n_funcs;
00361 }
00362
00369 bool Filter(F filter_data)
00370 {
00371 if (this->filter_func_list == NULL) return false;
00372 return this->Filter(this->filter_func_list[this->filter_type], filter_data);
00373 }
00374
00379 bool NeedRebuild() const
00380 {
00381 return (this->flags & VL_REBUILD) != 0;
00382 }
00383
00387 void ForceRebuild()
00388 {
00389 SETBITS(this->flags, VL_REBUILD);
00390 }
00391
00397 void RebuildDone()
00398 {
00399 CLRBITS(this->flags, VL_REBUILD);
00400 SETBITS(this->flags, VL_RESORT | VL_FIRST_SORT);
00401 }
00402 };
00403
00404 #endif