summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/signs.cpp12
-rw-r--r--src/signs_func.h1
-rw-r--r--src/signs_gui.cpp136
3 files changed, 90 insertions, 59 deletions
diff --git a/src/signs.cpp b/src/signs.cpp
index 8c1ad123c..369295a60 100644
--- a/src/signs.cpp
+++ b/src/signs.cpp
@@ -24,7 +24,6 @@
#include "table/strings.h"
SignID _new_sign_id;
-bool _sign_sort_dirty;
/* Initialize the sign-pool */
DEFINE_OLD_POOL_GENERIC(Sign, Sign)
@@ -111,8 +110,7 @@ CommandCost CmdPlaceSign(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
si->z = GetSlopeZ(x, y);
UpdateSignVirtCoords(si);
MarkSignDirty(si);
- InvalidateWindow(WC_SIGN_LIST, 0);
- _sign_sort_dirty = true;
+ InvalidateWindowData(WC_SIGN_LIST, 0, 0);
_new_sign_id = si->index;
}
@@ -148,8 +146,7 @@ CommandCost CmdRenameSign(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
MarkSignDirty(si);
UpdateSignVirtCoords(si);
MarkSignDirty(si);
- InvalidateWindow(WC_SIGN_LIST, 0);
- _sign_sort_dirty = true;
+ InvalidateWindowData(WC_SIGN_LIST, 0, 1);
}
} else { // Delete sign
if (flags & DC_EXEC) {
@@ -158,8 +155,7 @@ CommandCost CmdRenameSign(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
MarkSignDirty(si);
delete si;
- InvalidateWindow(WC_SIGN_LIST, 0);
- _sign_sort_dirty = true;
+ InvalidateWindowData(WC_SIGN_LIST, 0, 1);
}
}
@@ -242,8 +238,6 @@ static void Load_SIGN()
Sign *si = new (index) Sign();
SlObject(si, _sign_desc);
}
-
- _sign_sort_dirty = true;
}
extern const ChunkHandler _sign_chunk_handlers[] = {
diff --git a/src/signs_func.h b/src/signs_func.h
index 519a47096..34267a882 100644
--- a/src/signs_func.h
+++ b/src/signs_func.h
@@ -8,7 +8,6 @@
#include "signs_type.h"
extern SignID _new_sign_id;
-extern bool _sign_sort_dirty;
void UpdateAllSignVirtCoords();
void PlaceProc_Sign(TileIndex tile);
diff --git a/src/signs_gui.cpp b/src/signs_gui.cpp
index 7a0e9c44b..db0c84c0f 100644
--- a/src/signs_gui.cpp
+++ b/src/signs_gui.cpp
@@ -21,67 +21,80 @@
#include "gfx_func.h"
#include "viewport_func.h"
#include "querystring_gui.h"
+#include "sortlist_type.h"
#include "table/strings.h"
#include "table/sprites.h"
-static const Sign **_sign_sort;
-static uint _num_sign_sort;
+struct SignList {
+ typedef GUIList<const Sign *> GUISignList;
-static char _bufcache[64];
-static const Sign *_last_sign;
+ static const Sign *last_sign;
+ GUISignList signs;
-static int CDECL SignNameSorter(const void *a, const void *b)
-{
- const Sign *sign0 = *(const Sign**)a;
- const Sign *sign1 = *(const Sign**)b;
- char buf1[64];
+ void BuildSignsList()
+ {
+ if (!this->signs.NeedRebuild()) return;
+
+ DEBUG(misc, 3, "Building sign list");
- SetDParam(0, sign0->index);
- GetString(buf1, STR_SIGN_NAME, lastof(buf1));
+ this->signs.Clear();
- if (sign1 != _last_sign) {
- _last_sign = sign1;
- SetDParam(0, sign1->index);
- GetString(_bufcache, STR_SIGN_NAME, lastof(_bufcache));
+ const Sign *si;
+ FOR_ALL_SIGNS(si) *this->signs.Append() = si;
+
+ this->signs.Compact();
+ this->signs.RebuildDone();
}
- return strcmp(buf1, _bufcache); // sort by name
-}
+ /** Sort signs by their name */
+ static int CDECL SignNameSorter(const Sign* const *a, const Sign* const *b)
+ {
+ static char buf_cache[64];
+ char buf[64];
-static void GlobalSortSignList()
-{
- const Sign *si;
- uint n = 0;
+ SetDParam(0, (*a)->index);
+ GetString(buf, STR_SIGN_NAME, lastof(buf));
- /* Create array for sorting */
- _sign_sort = ReallocT(_sign_sort, GetMaxSignIndex() + 1);
+ if (*b != last_sign) {
+ last_sign = *b;
+ SetDParam(0, (*b)->index);
+ GetString(buf_cache, STR_SIGN_NAME, lastof(buf_cache));
+ }
- FOR_ALL_SIGNS(si) _sign_sort[n++] = si;
- _num_sign_sort = n;
+ return strcasecmp(buf, buf_cache);
+ }
- qsort((void*)_sign_sort, n, sizeof(_sign_sort[0]), SignNameSorter);
+ void SortSignsList()
+ {
+ if (!this->signs.Sort(&SignNameSorter)) return;
- _sign_sort_dirty = false;
+ /* Reset the name sorter sort cache */
+ this->last_sign = NULL;
+ }
+};
- DEBUG(misc, 3, "Resorting global signs list");
-}
+const Sign *SignList::last_sign = NULL;
-struct SignListWindow : Window {
+struct SignListWindow : Window, SignList {
SignListWindow(const WindowDesc *desc, WindowNumber window_number) : Window(desc, window_number)
{
this->vscroll.cap = 12;
this->resize.step_height = 10;
this->resize.height = this->height - 10 * 7; // minimum if 5 in the list
+ this->signs.ForceRebuild();
+ this->signs.NeedResort();
+
this->FindWindowPlacementAndResize(desc);
}
virtual void OnPaint()
{
- if (_sign_sort_dirty) GlobalSortSignList();
+ BuildSignsList();
+ SortSignsList();
- SetVScrollCount(this, _num_sign_sort);
+ SetVScrollCount(this, this->signs.Length());
SetDParam(0, this->vscroll.count);
this->DrawWidgets();
@@ -95,7 +108,7 @@ struct SignListWindow : Window {
/* Start drawing the signs */
for (uint16 i = this->vscroll.pos; i < this->vscroll.cap + this->vscroll.pos && i < this->vscroll.count; i++) {
- const Sign *si = _sign_sort[i];
+ const Sign *si = this->signs[i];
if (si->owner != OWNER_NONE) DrawPlayerIcon(si->owner, 4, y + 1);
@@ -114,7 +127,7 @@ struct SignListWindow : Window {
id_v += this->vscroll.pos;
if (id_v >= this->vscroll.count) return;
- const Sign *si = _sign_sort[id_v];
+ const Sign *si = this->signs[id_v];
ScrollMainWindowToTile(TileVirtXY(si->x, si->y));
}
}
@@ -123,6 +136,15 @@ struct SignListWindow : Window {
{
this->vscroll.cap += delta.y / 10;
}
+
+ virtual void OnInvalidateData(int data)
+ {
+ if (data == 0) {
+ this->signs.ForceRebuild();
+ } else {
+ this->signs.ForceResort();
+ }
+ }
};
static const Widget _sign_list_widget[] = {
@@ -163,7 +185,7 @@ enum QueryEditSignWidgets {
QUERY_EDIT_SIGN_WIDGET_NEXT,
};
-struct SignWindow : QueryStringBaseWindow {
+struct SignWindow : QueryStringBaseWindow, SignList {
SignID cur_sign;
SignWindow(const WindowDesc *desc, const Sign *si) : QueryStringBaseWindow(desc)
@@ -210,36 +232,52 @@ struct SignWindow : QueryStringBaseWindow {
{
switch (widget) {
case QUERY_EDIT_SIGN_WIDGET_PREVIOUS: {
- if (_sign_sort_dirty) GlobalSortSignList();
- SignID sign_index = _sign_sort[_num_sign_sort - 1]->index;
- for (uint i = 1; i < _num_sign_sort; i++) {
- if (this->cur_sign == _sign_sort[i]->index) {
- sign_index = _sign_sort[i - 1]->index;
+ /* Rebuild the sign list */
+ this->signs.ForceRebuild();
+ this->signs.NeedResort();
+ this->BuildSignsList();
+ this->SortSignsList();
+
+ /* By default pick the last entry */
+ const Sign *si = this->signs[this->signs.Length(
+ ) - 1];
+
+ for (uint i = 1; i < this->signs.Length(); i++) {
+ if (this->cur_sign == this->signs[i]->index) {
+ si = this->signs[i - 1];
break;
}
}
- const Sign *si = GetSign(sign_index);
/* Scroll to sign and reopen window */
ScrollMainWindowToTile(TileVirtXY(si->x, si->y));
UpdateSignEditWindow(si);
- } break;
+ break;
+ }
case QUERY_EDIT_SIGN_WIDGET_NEXT: {
- if (_sign_sort_dirty) GlobalSortSignList();
- SignID sign_index = _sign_sort[0]->index;
- for (uint i = 0; i < _num_sign_sort - 1; i++) {
- if (this->cur_sign == _sign_sort[i]->index) {
- sign_index = _sign_sort[i + 1]->index;
+ /* Rebuild the sign list */
+ this->signs.ForceRebuild();
+ this->signs.NeedResort();
+ this->BuildSignsList();
+ this->SortSignsList();
+
+ /* By default pick the last entry */
+ const Sign *si = this->signs[this->signs.Length(
+ ) - 1];
+
+ for (uint i = 0; i < this->signs.Length() - 1; i++) {
+ if (this->cur_sign == this->signs[i]->index) {
+ si = this->signs[i + 1];
break;
}
}
- const Sign *si = GetSign(sign_index);
/* Scroll to sign and reopen window */
ScrollMainWindowToTile(TileVirtXY(si->x, si->y));
UpdateSignEditWindow(si);
- } break;
+ break;
+ }
case QUERY_EDIT_SIGN_WIDGET_TEXT:
ShowOnScreenKeyboard(this, widget, QUERY_EDIT_SIGN_WIDGET_CANCEL, QUERY_EDIT_SIGN_WIDGET_OK);