# sortlist_type.h

Go to the documentation of this file.

    00001 /* $Id: sortlist_type.h 15377 2009-02-06 18:00:05Z rubidium $ */
    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     /* Resort every 10 days */
    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     /* Do not sort if the resort bit is not set */
    00244     if (!HASBITS(this->flags, VL_RESORT)) return false;
    00245
    00246     CLRBITS(this->flags, VL_RESORT);
    00247
    00248     this->ResetResortTimer();
    00249
    00250     /* Do not sort when the list is not sortable */
    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     /* Do not filter if the filter bit is not set */
    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 /* SORTLIST_TYPE_H */