# 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/sort_func.hpp"
    00018 #include "core/smallvec_type.hpp"
    00019 #include "date_type.h"
    00020
    00022 enum SortListFlags {
    00023   VL_NONE       = 0,
    00024   VL_DESC       = 1 << 0,
    00025   VL_RESORT     = 1 << 1,
    00026   VL_REBUILD    = 1 << 2,
    00027   VL_FIRST_SORT = 1 << 3,
    00028   VL_FILTER     = 1 << 4,
    00029   VL_END        = 1 << 5,
    00030 };
    00031 DECLARE_ENUM_AS_BIT_SET(SortListFlags)
    00032
    00033
    00034 struct Listing {
    00035   bool order;
    00036   byte criteria;
    00037 };
    00039 struct Filtering {
    00040   bool state;
    00041   byte criteria;
    00042 };
    00043
    00049 template <typename T, typename F = const char*>
    00050 class GUIList : public SmallVector<T, 32> {
    00051 public:
    00052   typedef int CDECL SortFunction(const T*, const T*);
    00053   typedef bool CDECL FilterFunction(const T*, F);
    00054
    00055 protected:
    00056   SortFunction * const *sort_func_list;
    00057   FilterFunction * const *filter_func_list;
    00058   SortListFlags flags;
    00059   uint8 sort_type;
    00060   uint8 filter_type;
    00061   uint16 resort_timer;
    00062
    00068   bool IsSortable() const
    00069   {
    00070     return (this->data != NULL && this->items >= 2);
    00071   }
    00072
    00076   void ResetResortTimer()
    00077   {
    00078     /* Resort every 10 days */
    00079     this->resort_timer = DAY_TICKS * 10;
    00080   }
    00081
    00082 public:
    00083   GUIList() :
    00084     sort_func_list(NULL),
    00085     filter_func_list(NULL),
    00086     flags(VL_FIRST_SORT),
    00087     sort_type(0),
    00088     filter_type(0),
    00089     resort_timer(1)
    00090   {};
    00091
    00097   uint8 SortType() const
    00098   {
    00099     return this->sort_type;
    00100   }
    00101
    00107   void SetSortType(uint8 n_type)
    00108   {
    00109     if (this->sort_type != n_type) {
    00110       SETBITS(this->flags, VL_RESORT | VL_FIRST_SORT);
    00111       this->sort_type = n_type;
    00112     }
    00113   }
    00114
    00120   Listing GetListing() const
    00121   {
    00122     Listing l;
    00123     l.order = (this->flags & VL_DESC) != 0;
    00124     l.criteria = this->sort_type;
    00125
    00126     return l;
    00127   }
    00128
    00134   void SetListing(Listing l)
    00135   {
    00136     if (l.order) {
    00137       SETBITS(this->flags, VL_DESC);
    00138     } else {
    00139       CLRBITS(this->flags, VL_DESC);
    00140     }
    00141     this->sort_type = l.criteria;
    00142
    00143     SETBITS(this->flags, VL_FIRST_SORT);
    00144   }
    00145
    00151   uint8 FilterType() const
    00152   {
    00153     return this->filter_type;
    00154   }
    00155
    00161   void SetFilterType(uint8 n_type)
    00162   {
    00163     if (this->filter_type != n_type) {
    00164       this->filter_type = n_type;
    00165     }
    00166   }
    00167
    00173   Filtering GetFiltering() const
    00174   {
    00175     Filtering f;
    00176     f.state = (this->flags & VL_FILTER) != 0;
    00177     f.criteria = this->filter_type;
    00178
    00179     return f;
    00180   }
    00181
    00187   void SetFiltering(Filtering f)
    00188   {
    00189     if (f.state) {
    00190       SETBITS(this->flags, VL_FILTER);
    00191     } else {
    00192       CLRBITS(this->flags, VL_FILTER);
    00193     }
    00194     this->filter_type = f.criteria;
    00195   }
    00196
    00205   bool NeedResort()
    00206   {
    00207     if (--this->resort_timer == 0) {
    00208       SETBITS(this->flags, VL_RESORT);
    00209       this->ResetResortTimer();
    00210       return true;
    00211     }
    00212     return false;
    00213   }
    00214
    00219   void ForceResort()
    00220   {
    00221     SETBITS(this->flags, VL_RESORT);
    00222   }
    00223
    00229   bool IsDescSortOrder() const
    00230   {
    00231     return (this->flags & VL_DESC) != 0;
    00232   }
    00233
    00239   void ToggleSortOrder()
    00240   {
    00241     this->flags ^= VL_DESC;
    00242
    00243     if (this->IsSortable()) MemReverseT(this->data, this->items);
    00244   }
    00245
    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 */