# sortlist_type.h

Go to the documentation of this file.

    00001 /* $Id$ */
    00002
    00003 /*
    00004  * This file is part of OpenTTD.
    00005  * 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.
    00006  * 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.
    00007  * 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/>.
    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     /* Resort every 10 days */
    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     /* Do not sort if the resort bit is not set */
    00259     if (!(this->flags & VL_RESORT)) return false;
    00260
    00261     CLRBITS(this->flags, VL_RESORT);
    00262
    00263     this->ResetResortTimer();
    00264
    00265     /* Do not sort when the list is not sortable */
    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     /* Do not filter if the filter bit is not set */
    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 /* SORTLIST_TYPE_H */