00001
00002
00005 #ifndef SORTLIST_TYPE_H
00006 #define SORTLIST_TYPE_H
00007
00008 #include "core/enum_type.hpp"
00009 #include "core/bitmath_func.hpp"
00010 #include "core/mem_func.hpp"
00011 #include "core/sort_func.hpp"
00012 #include "core/smallvec_type.hpp"
00013 #include "date_type.h"
00014
00015 enum SortListFlags {
00016 VL_NONE = 0,
00017 VL_DESC = 1 << 0,
00018 VL_RESORT = 1 << 1,
00019 VL_REBUILD = 1 << 2,
00020 VL_FIRST_SORT = 1 << 3,
00021 VL_FILTER = 1 << 4,
00022 VL_END = 1 << 5,
00023 };
00024 DECLARE_ENUM_AS_BIT_SET(SortListFlags);
00025
00026 struct Listing {
00027 bool order;
00028 byte criteria;
00029 };
00030 struct Filtering {
00031 bool state;
00032 byte criteria;
00033 };
00034
00035 template <typename T, typename F = const char*>
00036 class GUIList : public SmallVector<T, 32> {
00037 public:
00038 typedef int CDECL SortFunction(const T*, const T*);
00039 typedef bool CDECL FilterFunction(const T*, F);
00040
00041 protected:
00042 SortFunction * const *sort_func_list;
00043 FilterFunction * const *filter_func_list;
00044 SortListFlags flags;
00045 uint8 sort_type;
00046 uint8 filter_type;
00047 uint16 resort_timer;
00048
00054 bool IsSortable() const
00055 {
00056 return (this->data != NULL && this->items >= 2);
00057 }
00058
00062 void ResetResortTimer()
00063 {
00064
00065 this->resort_timer = DAY_TICKS * 10;
00066 }
00067
00068 public:
00069 GUIList() :
00070 sort_func_list(NULL),
00071 filter_func_list(NULL),
00072 flags(VL_FIRST_SORT),
00073 sort_type(0),
00074 filter_type(0),
00075 resort_timer(1)
00076 {};
00077
00083 uint8 SortType() const
00084 {
00085 return this->sort_type;
00086 }
00087
00093 void SetSortType(uint8 n_type)
00094 {
00095 if (this->sort_type != n_type) {
00096 SETBITS(this->flags, VL_RESORT | VL_FIRST_SORT);
00097 this->sort_type = n_type;
00098 }
00099 }
00100
00106 Listing GetListing() const
00107 {
00108 Listing l;
00109 l.order = HASBITS(this->flags, VL_DESC);
00110 l.criteria = this->sort_type;
00111
00112 return l;
00113 }
00114
00120 void SetListing(Listing l)
00121 {
00122 if (l.order) {
00123 SETBITS(this->flags, VL_DESC);
00124 } else {
00125 CLRBITS(this->flags, VL_DESC);
00126 }
00127 this->sort_type = l.criteria;
00128
00129 SETBITS(this->flags, VL_FIRST_SORT);
00130 }
00131
00137 uint8 FilterType() const
00138 {
00139 return this->filter_type;
00140 }
00141
00147 void SetFilterType(uint8 n_type)
00148 {
00149 if (this->filter_type != n_type) {
00150 this->filter_type = n_type;
00151 }
00152 }
00153
00159 Filtering GetFiltering() const
00160 {
00161 Filtering f;
00162 f.state = HASBITS(this->flags, VL_FILTER);
00163 f.criteria = this->filter_type;
00164
00165 return f;
00166 }
00167
00173 void SetFiltering(Filtering f)
00174 {
00175 if (f.state) {
00176 SETBITS(this->flags, VL_FILTER);
00177 } else {
00178 CLRBITS(this->flags, VL_FILTER);
00179 }
00180 this->filter_type = f.criteria;
00181 }
00182
00191 bool NeedResort()
00192 {
00193 if (--this->resort_timer == 0) {
00194 SETBITS(this->flags, VL_RESORT);
00195 this->ResetResortTimer();
00196 return true;
00197 }
00198 return false;
00199 }
00200
00205 void ForceResort()
00206 {
00207 SETBITS(this->flags, VL_RESORT);
00208 }
00209
00215 bool IsDescSortOrder() const
00216 {
00217 return HASBITS(this->flags, VL_DESC);
00218 }
00219
00225 void ToggleSortOrder()
00226 {
00227 this->flags ^= VL_DESC;
00228
00229 if (this->IsSortable()) MemReverseT(this->data, this->items);
00230 }
00231
00241 bool Sort(SortFunction *compare)
00242 {
00243
00244 if (!HASBITS(this->flags, VL_RESORT)) return false;
00245
00246 CLRBITS(this->flags, VL_RESORT);
00247
00248 this->ResetResortTimer();
00249
00250
00251 if (!this->IsSortable()) return false;
00252
00253 const bool desc = HASBITS(this->flags, VL_DESC);
00254
00255 if (HASBITS(this->flags, VL_FIRST_SORT)) {
00256 CLRBITS(this->flags, VL_FIRST_SORT);
00257
00258 QSortT(this->data, this->items, compare, desc);
00259 return true;
00260 }
00261
00262 GSortT(this->data, this->items, compare, desc);
00263 return true;
00264 }
00265
00271 void SetSortFuncs(SortFunction * const *n_funcs)
00272 {
00273 this->sort_func_list = n_funcs;
00274 }
00275
00282 bool Sort()
00283 {
00284 assert(this->sort_func_list != NULL);
00285 return this->Sort(this->sort_func_list[this->sort_type]);
00286 }
00287
00293 bool IsFilterEnabled() const
00294 {
00295 return HASBITS(this->flags, VL_FILTER);
00296 }
00297
00303 void SetFilterState(bool state)
00304 {
00305 if (state) {
00306 SETBITS(this->flags, VL_FILTER);
00307 } else {
00308 CLRBITS(this->flags, VL_FILTER);
00309 }
00310 }
00311
00319 bool Filter(FilterFunction *decide, F filter_data)
00320 {
00321
00322 if (!HASBITS(this->flags, VL_FILTER)) return false;
00323
00324 bool changed = false;
00325 for (uint iter = 0; iter < this->items;) {
00326 T *item = &this->data[iter];
00327 if (!decide(item, filter_data)) {
00328 this->Erase(item);
00329 changed = true;
00330 } else {
00331 iter++;
00332 }
00333 }
00334
00335 return changed;
00336 }
00337
00343 void SetFilterFuncs(FilterFunction * const *n_funcs)
00344 {
00345 this->filter_func_list = n_funcs;
00346 }
00347
00354 bool Filter(F filter_data)
00355 {
00356 if (this->filter_func_list == NULL) return false;
00357 return this->Filter(this->filter_func_list[this->filter_type], filter_data);
00358 }
00359
00364 bool NeedRebuild() const
00365 {
00366 return HASBITS(this->flags, VL_REBUILD);
00367 }
00368
00372 void ForceRebuild()
00373 {
00374 SETBITS(this->flags, VL_REBUILD);
00375 }
00376
00382 void RebuildDone()
00383 {
00384 CLRBITS(this->flags, VL_REBUILD);
00385 SETBITS(this->flags, VL_RESORT | VL_FIRST_SORT);
00386 }
00387 };
00388
00389 #endif