mirror of
https://github.com/OpenTTD/OpenTTD.git
synced 2025-03-06 06:15:04 +00:00
(svn r13267) -Codechange: extend GUIList with a GnomeSort
This commit is contained in:
parent
02b5ffa13f
commit
18acb21d65
@ -6,6 +6,7 @@
|
||||
#define SORTLIST_TYPE_H
|
||||
|
||||
#include "misc/smallvec.h"
|
||||
#include "date_type.h"
|
||||
|
||||
enum SortListFlags {
|
||||
VL_NONE = 0, ///< no sort
|
||||
@ -22,10 +23,249 @@ struct Listing {
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct GUIList : public SmallVector<T, 32> {
|
||||
class GUIList : public SmallVector<T, 32> {
|
||||
public:
|
||||
typedef int SortFunction(const T*, const T*);
|
||||
|
||||
public: // Temporary: public for conversion only
|
||||
SortFunction* const *func_list; ///< The sort criteria functions
|
||||
SortListFlags flags; ///< used to control sorting/resorting/etc.
|
||||
uint8 sort_type; ///< what criteria to sort on
|
||||
uint16 resort_timer; ///< resort list after a given amount of ticks if set
|
||||
byte sort_type; ///< what criteria to sort on
|
||||
|
||||
/**
|
||||
* Check if the list is sortable
|
||||
*
|
||||
* @return true if we can sort the list
|
||||
*/
|
||||
bool IsSortable() const
|
||||
{
|
||||
return (this->data != NULL && this->items > 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the resort timer
|
||||
*/
|
||||
void ResetResortTimer()
|
||||
{
|
||||
/* Resort every 10 days */
|
||||
this->resort_timer = DAY_TICKS * 10;
|
||||
}
|
||||
|
||||
public:
|
||||
GUIList() :
|
||||
func_list(NULL),
|
||||
flags(VL_NONE),
|
||||
sort_type(0),
|
||||
resort_timer(1)
|
||||
{};
|
||||
|
||||
/**
|
||||
* Get the sorttype of the list
|
||||
*
|
||||
* @return The current sorttype
|
||||
*/
|
||||
uint8 SortType() const
|
||||
{
|
||||
return this->sort_type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the sorttype of the list
|
||||
*
|
||||
* @param n_type the new sort type
|
||||
*/
|
||||
void SetSortType(uint8 n_type)
|
||||
{
|
||||
if (this->sort_type != n_type) {
|
||||
SETBITS(this->flags, VL_RESORT);
|
||||
this->sort_type = n_type;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Export current sort conditions
|
||||
*
|
||||
* @return the current sort conditions
|
||||
*/
|
||||
Listing GetListing() const
|
||||
{
|
||||
Listing l;
|
||||
l.order = HASBITS(this->flags, VL_DESC);
|
||||
l.criteria = this->sort_type;
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
/**
|
||||
* Import sort conditions
|
||||
*
|
||||
* @param l The sport conditions we want to use
|
||||
*/
|
||||
void SetListing(Listing l)
|
||||
{
|
||||
if (l.order) {
|
||||
SETBITS(this->flags, VL_DESC);
|
||||
} else {
|
||||
CLRBITS(this->flags, VL_DESC);
|
||||
}
|
||||
this->sort_type = l.criteria;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a resort is needed next loop
|
||||
* If used the resort timer will decrease every call
|
||||
* till 0. If 0 reached the resort bit will be set and
|
||||
* the timer will be reset.
|
||||
*
|
||||
* @return true if resort bit is set for next loop
|
||||
*/
|
||||
bool NeedResort()
|
||||
{
|
||||
if (--this->resort_timer == 0) {
|
||||
SETBITS(this->flags, VL_RESORT);
|
||||
this->ResetResortTimer();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Force a resort next Sort call
|
||||
* Reset the resort timer if used too.
|
||||
*/
|
||||
void ForceResort()
|
||||
{
|
||||
SETBITS(this->flags, VL_RESORT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the sort order is descending
|
||||
*
|
||||
* @return true if the sort order is descending
|
||||
*/
|
||||
bool IsDescSortOrder() const
|
||||
{
|
||||
return HASBITS(this->flags, VL_DESC);
|
||||
}
|
||||
|
||||
/**
|
||||
* Toogle the sort order
|
||||
* Since that is the worst condition for the sort function
|
||||
* reverse the list here.
|
||||
*/
|
||||
FORCEINLINE void ToggleSortOrder()
|
||||
{
|
||||
this->flags ^= VL_DESC;
|
||||
|
||||
if (this->IsSortable()) {
|
||||
T *a = this->data;
|
||||
T *b = a + (this->items - 1);
|
||||
|
||||
do {
|
||||
Swap(*a, *b);
|
||||
} while (((a + 1) != b) && (++a != --b));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* GnomeSort algorithm
|
||||
* This sorting uses a slightly modifyied Gnome search.
|
||||
* The basic Gnome search trys to sort already sorted
|
||||
* list parts. The modification skips these.
|
||||
*
|
||||
* @param compare The function to compare two list items
|
||||
* */
|
||||
FORCEINLINE void Sort(SortFunction compare)
|
||||
{
|
||||
/* Do not sort when the list is not sortable */
|
||||
if (!this->IsSortable()) return;
|
||||
|
||||
/* Do not sort if the resort bit is not set */
|
||||
if (!HASBITS(this->flags, VL_RESORT)) return;
|
||||
|
||||
T *a = this->data;
|
||||
T *b = a + 1;
|
||||
|
||||
uint length = this->items;
|
||||
uint offset = 0; // Jump variable
|
||||
const bool desc = HASBITS(this->flags, VL_DESC);
|
||||
|
||||
while (length > 1) {
|
||||
const int diff = compare(a, b);
|
||||
if ((!desc && diff <= 0) || (desc && diff >= 0)) {
|
||||
if (offset != 0) {
|
||||
/* Jump back to the last direction switch point */
|
||||
a += offset;
|
||||
b += offset;
|
||||
offset = 0;
|
||||
continue;
|
||||
}
|
||||
a++;
|
||||
b++;
|
||||
length--;
|
||||
} else {
|
||||
Swap(*a, *b);
|
||||
if (a != this->data) {
|
||||
offset++;
|
||||
a--;
|
||||
b--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this->ResetResortTimer();
|
||||
|
||||
CLRBITS(this->flags, VL_RESORT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hand the array of sort function pointers to the sort list
|
||||
*
|
||||
* @param n_funcs The pointer to the first sort func
|
||||
*/
|
||||
void SetSortFuncs(SortFunction* const* n_funcs)
|
||||
{
|
||||
this->func_list = n_funcs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overload of Sort()
|
||||
* Overloaded to reduce external code
|
||||
*/
|
||||
void Sort()
|
||||
{
|
||||
assert(this->func_list != NULL);
|
||||
this->Sort(this->func_list[this->sort_type]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a rebuild is needed
|
||||
* @return true if a rebuild is needed
|
||||
*/
|
||||
bool NeedRebuild() const
|
||||
{
|
||||
return HASBITS(this->flags, VL_REBUILD);
|
||||
}
|
||||
|
||||
/**
|
||||
* Force that a rebuild is needed
|
||||
*/
|
||||
void ForceRebuild()
|
||||
{
|
||||
SETBITS(this->flags, VL_REBUILD);
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify the sortlist that the rebuild is done
|
||||
*
|
||||
* @note This forces a resort
|
||||
*/
|
||||
void RebuildDone()
|
||||
{
|
||||
CLRBITS(this->flags, VL_REBUILD);
|
||||
SETBITS(this->flags, VL_RESORT);
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* SORTLIST_TYPE_H */
|
||||
|
Loading…
Reference in New Issue
Block a user