@@ -1251,12 +1251,13 @@ void SQGSWindow_Register(Squirrel *engin
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_TE_DATE_PANEL, "WID_TE_DATE_PANEL");
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_TE_MUSIC_SOUND, "WID_TE_MUSIC_SOUND");
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_TE_HELP, "WID_TE_HELP");
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_TE_SWITCH_BAR, "WID_TE_SWITCH_BAR");
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_TD_SORT_ORDER, "WID_TD_SORT_ORDER");
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_TD_SORT_CRITERIA, "WID_TD_SORT_CRITERIA");
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_TD_FILTER, "WID_TD_FILTER");
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_TD_LIST, "WID_TD_LIST");
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_TD_SCROLLBAR, "WID_TD_SCROLLBAR");
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_TD_WORLD_POPULATION, "WID_TD_WORLD_POPULATION");
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_TA_CAPTION, "WID_TA_CAPTION");
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_TA_RATING_INFO, "WID_TA_RATING_INFO");
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_TA_COMMAND_LIST, "WID_TA_COMMAND_LIST");
@@ -2483,12 +2483,13 @@ public:
/* automatically generated from ../../widgets/town_widget.h */
/** Widgets of the #TownDirectoryWindow class. */
enum TownDirectoryWidgets {
WID_TD_SORT_ORDER = ::WID_TD_SORT_ORDER, ///< Direction of sort dropdown.
WID_TD_SORT_CRITERIA = ::WID_TD_SORT_CRITERIA, ///< Criteria of sort dropdown.
WID_TD_FILTER = ::WID_TD_FILTER, ///< Filter of name.
WID_TD_LIST = ::WID_TD_LIST, ///< List of towns.
WID_TD_SCROLLBAR = ::WID_TD_SCROLLBAR, ///< Scrollbar for the town list.
WID_TD_WORLD_POPULATION = ::WID_TD_WORLD_POPULATION, ///< The world's population.
};
/** Widgets of the #TownAuthorityWindow class. */
@@ -155,12 +155,18 @@ void RebuildTownKdtree();
enum TownRatingCheckType {
ROAD_REMOVE = 0, ///< Removal of a road owned by the town.
TUNNELBRIDGE_REMOVE = 1, ///< Removal of a tunnel or bridge owned by the towb.
TOWN_RATING_CHECK_TYPE_COUNT, ///< Number of town checking action types.
/** Special values for town list window for the data parameter of #InvalidateWindowData. */
enum TownDirectoryInvalidateWindowData {
TDIWD_FORCE_REBUILD,
TDIWD_FILTER_CHANGES, ///< The filename filter has changed (via the editbox)
/**
* This enum is used in conjunction with town->flags.
* IT simply states what bit is used for.
* It is pretty unrealistic (IMHO) to only have one church/stadium
* per town, NO MATTER the population of it.
* And there are 5 more bits available on flags...
@@ -28,12 +28,13 @@
#include "landscape.h"
#include "querystring_gui.h"
#include "window_func.h"
#include "townname_func.h"
#include "core/geometry_func.hpp"
#include "genworld.h"
#include "stringfilter_type.h"
#include "widgets/dropdown_func.h"
#include "widgets/town_widget.h"
#include "table/strings.h"
@@ -633,13 +634,13 @@ static const NWidgetPart _nested_town_di
EndContainer(),
NWidget(NWID_HORIZONTAL),
NWidget(NWID_VERTICAL),
NWidget(WWT_TEXTBTN, COLOUR_BROWN, WID_TD_SORT_ORDER), SetDataTip(STR_BUTTON_SORT_BY, STR_TOOLTIP_SORT_ORDER),
NWidget(WWT_DROPDOWN, COLOUR_BROWN, WID_TD_SORT_CRITERIA), SetDataTip(STR_JUST_STRING, STR_TOOLTIP_SORT_CRITERIA),
NWidget(WWT_PANEL, COLOUR_BROWN), SetResize(1, 0), EndContainer(),
NWidget(WWT_EDITBOX, COLOUR_BROWN, WID_TD_FILTER), SetFill(35, 12), SetDataTip(STR_LIST_FILTER_OSKTITLE, STR_LIST_FILTER_TOOLTIP),
NWidget(WWT_PANEL, COLOUR_BROWN, WID_TD_LIST), SetMinimalSize(196, 0), SetDataTip(0x0, STR_TOWN_DIRECTORY_LIST_TOOLTIP),
SetFill(1, 0), SetResize(0, 10), SetScrollbar(WID_TD_SCROLLBAR), EndContainer(),
NWidget(WWT_PANEL, COLOUR_BROWN),
NWidget(WWT_TEXT, COLOUR_BROWN, WID_TD_WORLD_POPULATION), SetPadding(2, 0, 0, 2), SetMinimalSize(196, 12), SetFill(1, 0), SetDataTip(STR_TOWN_POPULATION, STR_NULL),
@@ -659,12 +660,15 @@ private:
static const Town *last_town;
/* Constants for sorting towns */
static const StringID sorter_names[];
static GUITownList::SortFunction * const sorter_funcs[];
StringFilter string_filter; ///< Filter for towns
QueryString townname_editbox; ///< Filter editbox
GUITownList towns;
Scrollbar *vscroll;
void BuildSortTownList()
{
@@ -686,14 +690,14 @@ private:
this->SetWidgetDirty(WID_TD_LIST); // Force repaint of the displayed towns.
}
/** Sort by town name */
static bool TownNameSorter(const Town * const &a, const Town * const &b)
static char buf_cache[64];
char buf[64];
static char buf_cache[MAX_LENGTH_TOWN_NAME_CHARS * MAX_CHAR_LENGTH];
char buf[MAX_LENGTH_TOWN_NAME_CHARS * MAX_CHAR_LENGTH];
SetDParam(0, a->index);
GetString(buf, STR_TOWN_NAME, lastof(buf));
/* If 'b' is the same town as in the last round, use the cached value
* We do this to speed stuff up ('b' is called with the same value a lot of
@@ -736,24 +740,27 @@ private:
/* Sort unrated towns always on ascending town name. */
if (before) return TownDirectoryWindow::TownNameSorter(a, b);
return !TownDirectoryWindow::TownNameSorter(a, b);
public:
TownDirectoryWindow(WindowDesc *desc) : Window(desc)
TownDirectoryWindow(WindowDesc *desc) : Window(desc), townname_editbox(MAX_LENGTH_TOWN_NAME_CHARS * MAX_CHAR_LENGTH, MAX_LENGTH_TOWN_NAME_CHARS)
this->CreateNestedTree();
this->vscroll = this->GetScrollbar(WID_TD_SCROLLBAR);
this->towns.SetListing(this->last_sorting);
this->towns.SetSortFuncs(TownDirectoryWindow::sorter_funcs);
this->towns.ForceRebuild();
this->BuildSortTownList();
this->FinishInitNested(0);
this->querystrings[WID_TD_FILTER] = &this->townname_editbox;
this->townname_editbox.cancel_button = QueryString::ACTION_CLEAR;
void SetStringParameters(int widget) const override
switch (widget) {
case WID_TD_WORLD_POPULATION:
@@ -938,24 +945,62 @@ public:
void OnResize() override
this->vscroll->SetCapacityFromWidget(this, WID_TD_LIST);
virtual void OnEditboxChanged(int wid)
if (wid == WID_TD_FILTER) {
this->string_filter.SetFilterTerm(this->townname_editbox.text.buf);
this->InvalidateData(TDIWD_FILTER_CHANGES);
* Some data on this window has become invalid.
* @param data Information about the changed data.
* @param gui_scope Whether the call is done from GUI scope. You may not do everything when not in GUI scope. See #InvalidateWindowData() for details.
*/
void OnInvalidateData(int data = 0, bool gui_scope = true) override
if (data == 0) {
/* This needs to be done in command-scope to enforce rebuilding before resorting invalid data */
} else {
this->towns.ForceResort();
switch (data) {
case TDIWD_FORCE_REBUILD:
break;
case TDIWD_FILTER_CHANGES:
if (this->string_filter.IsEmpty()) {
this->towns.clear();
const Town *t;
FOR_ALL_TOWNS(t) {
this->string_filter.ResetState();
SetDParam(0, t->index);
this->string_filter.AddLine(buf);
if (this->string_filter.GetState()) this->towns.push_back(t);
this->towns.Sort();
this->towns.shrink_to_fit();
this->towns.RebuildDone();
this->vscroll->SetCount(this->towns.size()); // Update scrollbar as well.
default:
Listing TownDirectoryWindow::last_sorting = {false, 0};
const Town *TownDirectoryWindow::last_town = nullptr;
@@ -13,12 +13,13 @@
#define WIDGETS_TOWN_WIDGET_H
WID_TD_SORT_ORDER, ///< Direction of sort dropdown.
WID_TD_SORT_CRITERIA, ///< Criteria of sort dropdown.
WID_TD_FILTER, ///< Filter of name.
WID_TD_LIST, ///< List of towns.
WID_TD_SCROLLBAR, ///< Scrollbar for the town list.
WID_TD_WORLD_POPULATION, ///< The world's population.
Status change: