mirror of
https://github.com/OpenTTD/OpenTTD.git
synced 2025-03-13 02:52:37 +00:00
Codechange: Sort and filter sign names directly rather than through string system. (#7304)
This provides a notable performance benefit in the Sign List window when there are many signs.
This commit is contained in:
parent
c3bc7d657e
commit
cbaf52fbe1
@ -41,11 +41,11 @@ struct SignList {
|
|||||||
*/
|
*/
|
||||||
typedef GUIList<const Sign *, StringFilter &> GUISignList;
|
typedef GUIList<const Sign *, StringFilter &> GUISignList;
|
||||||
|
|
||||||
static const Sign *last_sign;
|
|
||||||
GUISignList signs;
|
GUISignList signs;
|
||||||
|
|
||||||
StringFilter string_filter; ///< The match string to be used when the GUIList is (re)-sorted.
|
StringFilter string_filter; ///< The match string to be used when the GUIList is (re)-sorted.
|
||||||
static bool match_case; ///< Should case sensitive matching be used?
|
static bool match_case; ///< Should case sensitive matching be used?
|
||||||
|
static char default_name[64]; ///< Default sign name, used if Sign::name is NULL.
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a SignList with filtering disabled by default.
|
* Creates a SignList with filtering disabled by default.
|
||||||
@ -74,19 +74,17 @@ struct SignList {
|
|||||||
/** Sort signs by their name */
|
/** Sort signs by their name */
|
||||||
static int CDECL SignNameSorter(const Sign * const *a, const Sign * const *b)
|
static int CDECL SignNameSorter(const Sign * const *a, const Sign * const *b)
|
||||||
{
|
{
|
||||||
static char buf_cache[64];
|
/* Signs are very very rarely using the default text, but there can also be
|
||||||
char buf[64];
|
* a lot of them. Therefore a worthwhile performance gain can be made by
|
||||||
|
* directly comparing Sign::name instead of going through the string
|
||||||
|
* system for each comparison. */
|
||||||
|
const char *a_name = (*a)->name;
|
||||||
|
const char *b_name = (*b)->name;
|
||||||
|
|
||||||
SetDParam(0, (*a)->index);
|
if (a_name == NULL) a_name = SignList::default_name;
|
||||||
GetString(buf, STR_SIGN_NAME, lastof(buf));
|
if (b_name == NULL) b_name = SignList::default_name;
|
||||||
|
|
||||||
if (*b != last_sign) {
|
int r = strnatcmp(a_name, b_name); // Sort by name (natural sorting).
|
||||||
last_sign = *b;
|
|
||||||
SetDParam(0, (*b)->index);
|
|
||||||
GetString(buf_cache, STR_SIGN_NAME, lastof(buf_cache));
|
|
||||||
}
|
|
||||||
|
|
||||||
int r = strnatcmp(buf, buf_cache); // Sort by name (natural sorting).
|
|
||||||
|
|
||||||
return r != 0 ? r : ((*a)->index - (*b)->index);
|
return r != 0 ? r : ((*a)->index - (*b)->index);
|
||||||
}
|
}
|
||||||
@ -94,21 +92,18 @@ struct SignList {
|
|||||||
void SortSignsList()
|
void SortSignsList()
|
||||||
{
|
{
|
||||||
if (!this->signs.Sort(&SignNameSorter)) return;
|
if (!this->signs.Sort(&SignNameSorter)) return;
|
||||||
|
|
||||||
/* Reset the name sorter sort cache */
|
|
||||||
this->last_sign = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Filter sign list by sign name */
|
/** Filter sign list by sign name */
|
||||||
static bool CDECL SignNameFilter(const Sign * const *a, StringFilter &filter)
|
static bool CDECL SignNameFilter(const Sign * const *a, StringFilter &filter)
|
||||||
{
|
{
|
||||||
/* Get sign string */
|
/* Same performance benefit as above for sorting. */
|
||||||
char buf1[MAX_LENGTH_SIGN_NAME_CHARS * MAX_CHAR_LENGTH];
|
const char *a_name = (*a)->name;
|
||||||
SetDParam(0, (*a)->index);
|
|
||||||
GetString(buf1, STR_SIGN_NAME, lastof(buf1));
|
if (a_name == NULL) a_name = SignList::default_name;
|
||||||
|
|
||||||
filter.ResetState();
|
filter.ResetState();
|
||||||
filter.AddLine(buf1);
|
filter.AddLine(a_name);
|
||||||
return filter.GetState();
|
return filter.GetState();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,8 +133,8 @@ struct SignList {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const Sign *SignList::last_sign = NULL;
|
|
||||||
bool SignList::match_case = false;
|
bool SignList::match_case = false;
|
||||||
|
char SignList::default_name[64];
|
||||||
|
|
||||||
/** Enum referring to the Hotkeys in the sign list window */
|
/** Enum referring to the Hotkeys in the sign list window */
|
||||||
enum SignListHotkeys {
|
enum SignListHotkeys {
|
||||||
@ -171,6 +166,15 @@ struct SignListWindow : Window, SignList {
|
|||||||
this->BuildSortSignList();
|
this->BuildSortSignList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void OnInit()
|
||||||
|
{
|
||||||
|
/* Default sign name, used if Sign::name is NULL. */
|
||||||
|
GetString(SignList::default_name, STR_DEFAULT_SIGN_NAME, lastof(SignList::default_name));
|
||||||
|
this->signs.ForceResort();
|
||||||
|
this->SortSignsList();
|
||||||
|
this->SetDirty();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function sets the filter string of the sign list. The contents of
|
* This function sets the filter string of the sign list. The contents of
|
||||||
* the edit widget is not updated by this function. Depending on if the
|
* the edit widget is not updated by this function. Depending on if the
|
||||||
@ -188,7 +192,7 @@ struct SignListWindow : Window, SignList {
|
|||||||
|
|
||||||
virtual void OnPaint()
|
virtual void OnPaint()
|
||||||
{
|
{
|
||||||
if (this->signs.NeedRebuild()) this->BuildSortSignList();
|
if (!this->IsShaded() && this->signs.NeedRebuild()) this->BuildSortSignList();
|
||||||
this->DrawWidgets();
|
this->DrawWidgets();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user