tron@2186: /* $Id$ */ tron@2186: rubidium@9274: /** @file sortlist_type.h Base types for having sorted lists in GUIs. */ rubidium@9273: rubidium@9274: #ifndef SORTLIST_TYPE_H rubidium@9274: #define SORTLIST_TYPE_H belugas@9267: rubidium@9427: #include "core/enum_type.hpp" rubidium@9427: #include "core/bitmath_func.hpp" skidd13@9520: #include "core/mem_func.hpp" skidd13@9520: #include "core/sort_func.hpp" skidd13@9555: #include "core/smallvec_type.hpp" skidd13@9366: #include "date_type.h" peter1138@9365: rubidium@6248: enum SortListFlags { smatz@9372: VL_NONE = 0, ///< no sort smatz@9372: VL_DESC = 1 << 0, ///< sort descending or ascending smatz@9372: VL_RESORT = 1 << 1, ///< instruct the code to resort the list in the next loop smatz@9372: VL_REBUILD = 1 << 2, ///< rebuild the sort list smatz@9372: VL_FIRST_SORT = 1 << 3, ///< sort with qsort first smatz@9372: VL_END = 1 << 4, rubidium@6248: }; rubidium@5587: DECLARE_ENUM_AS_BIT_SET(SortListFlags); rubidium@5587: rubidium@6248: struct Listing { belugas@6117: bool order; ///< Ascending/descending belugas@6117: byte criteria; ///< Sorting criteria rubidium@6248: }; tron@588: rubidium@9182: template skidd13@9366: class GUIList : public SmallVector { skidd13@9366: public: smatz@9376: typedef int CDECL SortFunction(const T*, const T*); skidd13@9366: skidd13@9531: protected: skidd13@9366: SortFunction* const *func_list; ///< The sort criteria functions skidd13@9366: SortListFlags flags; ///< used to control sorting/resorting/etc. skidd13@9366: uint8 sort_type; ///< what criteria to sort on skidd13@9366: uint16 resort_timer; ///< resort list after a given amount of ticks if set skidd13@9366: skidd13@9366: /** skidd13@9366: * Check if the list is sortable skidd13@9366: * skidd13@9366: * @return true if we can sort the list skidd13@9366: */ skidd13@9366: bool IsSortable() const skidd13@9366: { smatz@9371: return (this->data != NULL && this->items >= 2); skidd13@9366: } skidd13@9366: skidd13@9366: /** skidd13@9366: * Reset the resort timer skidd13@9366: */ skidd13@9366: void ResetResortTimer() skidd13@9366: { skidd13@9366: /* Resort every 10 days */ skidd13@9366: this->resort_timer = DAY_TICKS * 10; skidd13@9366: } skidd13@9366: skidd13@9366: public: skidd13@9366: GUIList() : skidd13@9366: func_list(NULL), smatz@9372: flags(VL_FIRST_SORT), skidd13@9366: sort_type(0), skidd13@9366: resort_timer(1) skidd13@9366: {}; skidd13@9366: skidd13@9366: /** skidd13@9366: * Get the sorttype of the list skidd13@9366: * skidd13@9366: * @return The current sorttype skidd13@9366: */ skidd13@9366: uint8 SortType() const skidd13@9366: { skidd13@9366: return this->sort_type; skidd13@9366: } skidd13@9366: skidd13@9366: /** skidd13@9366: * Set the sorttype of the list skidd13@9366: * skidd13@9366: * @param n_type the new sort type skidd13@9366: */ skidd13@9366: void SetSortType(uint8 n_type) skidd13@9366: { skidd13@9366: if (this->sort_type != n_type) { smatz@9372: SETBITS(this->flags, VL_RESORT | VL_FIRST_SORT); skidd13@9366: this->sort_type = n_type; skidd13@9366: } skidd13@9366: } skidd13@9366: skidd13@9366: /** skidd13@9366: * Export current sort conditions skidd13@9366: * skidd13@9366: * @return the current sort conditions skidd13@9366: */ skidd13@9366: Listing GetListing() const skidd13@9366: { skidd13@9366: Listing l; skidd13@9366: l.order = HASBITS(this->flags, VL_DESC); skidd13@9366: l.criteria = this->sort_type; skidd13@9366: skidd13@9366: return l; skidd13@9366: } skidd13@9366: skidd13@9366: /** skidd13@9366: * Import sort conditions skidd13@9366: * skidd13@9366: * @param l The sport conditions we want to use skidd13@9366: */ skidd13@9366: void SetListing(Listing l) skidd13@9366: { skidd13@9366: if (l.order) { skidd13@9366: SETBITS(this->flags, VL_DESC); skidd13@9366: } else { skidd13@9366: CLRBITS(this->flags, VL_DESC); skidd13@9366: } skidd13@9366: this->sort_type = l.criteria; smatz@9372: smatz@9372: SETBITS(this->flags, VL_FIRST_SORT); skidd13@9366: } skidd13@9366: skidd13@9366: /** skidd13@9366: * Check if a resort is needed next loop skidd13@9366: * If used the resort timer will decrease every call skidd13@9366: * till 0. If 0 reached the resort bit will be set and skidd13@9366: * the timer will be reset. skidd13@9366: * skidd13@9366: * @return true if resort bit is set for next loop skidd13@9366: */ skidd13@9366: bool NeedResort() skidd13@9366: { skidd13@9366: if (--this->resort_timer == 0) { skidd13@9366: SETBITS(this->flags, VL_RESORT); skidd13@9366: this->ResetResortTimer(); skidd13@9366: return true; skidd13@9366: } skidd13@9366: return false; skidd13@9366: } skidd13@9366: skidd13@9366: /** skidd13@9366: * Force a resort next Sort call skidd13@9366: * Reset the resort timer if used too. skidd13@9366: */ skidd13@9366: void ForceResort() skidd13@9366: { skidd13@9366: SETBITS(this->flags, VL_RESORT); skidd13@9366: } skidd13@9366: skidd13@9366: /** skidd13@9366: * Check if the sort order is descending skidd13@9366: * skidd13@9366: * @return true if the sort order is descending skidd13@9366: */ skidd13@9366: bool IsDescSortOrder() const skidd13@9366: { skidd13@9366: return HASBITS(this->flags, VL_DESC); skidd13@9366: } skidd13@9366: skidd13@9366: /** skidd13@9366: * Toogle the sort order skidd13@9366: * Since that is the worst condition for the sort function skidd13@9366: * reverse the list here. skidd13@9366: */ skidd13@9520: void ToggleSortOrder() skidd13@9366: { skidd13@9366: this->flags ^= VL_DESC; skidd13@9366: skidd13@9520: if (this->IsSortable()) MemReverseT(this->data, this->items); skidd13@9366: } skidd13@9366: skidd13@9366: /** skidd13@9520: * Sort the list. skidd13@9520: * For the first sorting we use qsort since it is skidd13@9520: * faster for irregular sorted data. After that we skidd13@9520: * use gsort. skidd13@9366: * skidd13@9366: * @param compare The function to compare two list items skidd13@9379: * @return true if the list sequence has been altered skidd13@9366: * */ skidd13@9520: bool Sort(SortFunction *compare) skidd13@9366: { smatz@9371: /* Do not sort if the resort bit is not set */ skidd13@9379: if (!HASBITS(this->flags, VL_RESORT)) return false; smatz@9371: smatz@9371: CLRBITS(this->flags, VL_RESORT); smatz@9371: smatz@9371: this->ResetResortTimer(); smatz@9371: skidd13@9366: /* Do not sort when the list is not sortable */ skidd13@9379: if (!this->IsSortable()) return false; skidd13@9366: smatz@9372: const bool desc = HASBITS(this->flags, VL_DESC); smatz@9372: smatz@9372: if (HASBITS(this->flags, VL_FIRST_SORT)) { smatz@9386: CLRBITS(this->flags, VL_FIRST_SORT); smatz@9372: skidd13@9520: QSortT(this->data, this->items, compare, desc); skidd13@9379: return true; smatz@9372: } smatz@9372: skidd13@9520: GSortT(this->data, this->items, compare, desc); skidd13@9379: return true; skidd13@9366: } skidd13@9366: skidd13@9366: /** skidd13@9366: * Hand the array of sort function pointers to the sort list skidd13@9366: * skidd13@9366: * @param n_funcs The pointer to the first sort func skidd13@9366: */ skidd13@9366: void SetSortFuncs(SortFunction* const* n_funcs) skidd13@9366: { skidd13@9366: this->func_list = n_funcs; skidd13@9366: } skidd13@9366: skidd13@9366: /** skidd13@9366: * Overload of Sort() skidd13@9366: * Overloaded to reduce external code skidd13@9379: * skidd13@9379: * @return true if the list sequence has been altered skidd13@9366: */ skidd13@9379: bool Sort() skidd13@9366: { skidd13@9366: assert(this->func_list != NULL); skidd13@9379: return this->Sort(this->func_list[this->sort_type]); skidd13@9366: } skidd13@9366: skidd13@9366: /** skidd13@9366: * Check if a rebuild is needed skidd13@9366: * @return true if a rebuild is needed skidd13@9366: */ skidd13@9366: bool NeedRebuild() const skidd13@9366: { skidd13@9366: return HASBITS(this->flags, VL_REBUILD); skidd13@9366: } skidd13@9366: skidd13@9366: /** skidd13@9366: * Force that a rebuild is needed skidd13@9366: */ skidd13@9366: void ForceRebuild() skidd13@9366: { skidd13@9366: SETBITS(this->flags, VL_REBUILD); skidd13@9366: } skidd13@9366: skidd13@9366: /** skidd13@9366: * Notify the sortlist that the rebuild is done skidd13@9366: * skidd13@9366: * @note This forces a resort skidd13@9366: */ skidd13@9366: void RebuildDone() skidd13@9366: { skidd13@9366: CLRBITS(this->flags, VL_REBUILD); skidd13@9531: SETBITS(this->flags, VL_RESORT | VL_FIRST_SORT); skidd13@9366: } rubidium@6248: }; rubidium@6643: rubidium@9274: #endif /* SORTLIST_TYPE_H */