summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/lang/english.txt1
-rw-r--r--src/network/network_gui.cpp141
-rw-r--r--src/script/api/game/game_window.hpp.sq2
-rw-r--r--src/script/api/script_window.hpp2
-rw-r--r--src/widgets/network_widget.h2
5 files changed, 105 insertions, 43 deletions
diff --git a/src/lang/english.txt b/src/lang/english.txt
index a71424493..e613f4b19 100644
--- a/src/lang/english.txt
+++ b/src/lang/english.txt
@@ -217,6 +217,7 @@ STR_UNITS_HEIGHT_IMPERIAL :{COMMA} ft
STR_UNITS_HEIGHT_SI :{COMMA} m
# Common window strings
+STR_LIST_FILTER_TITLE :{BLACK}Filter string:
STR_LIST_FILTER_OSKTITLE :{BLACK}Enter filter string
STR_LIST_FILTER_TOOLTIP :{BLACK}Enter a keyword to filter the list for
diff --git a/src/network/network_gui.cpp b/src/network/network_gui.cpp
index d6e6f070f..dbeb023b4 100644
--- a/src/network/network_gui.cpp
+++ b/src/network/network_gui.cpp
@@ -37,6 +37,8 @@
#include "table/strings.h"
#include "../table/sprites.h"
+#include "../stringfilter_type.h"
+
static void ShowNetworkStartServerWindow();
static void ShowNetworkLobbyWindow(NetworkGameList *ngl);
@@ -77,7 +79,7 @@ void UpdateNetworkGameWindow()
InvalidateWindowData(WC_NETWORK_WINDOW, WN_NETWORK_WINDOW_GAME, 0);
}
-typedef GUIList<NetworkGameList*> GUIGameServerList;
+typedef GUIList<NetworkGameList*, StringFilter&> GUIGameServerList;
typedef uint16 ServerListPosition;
static const ServerListPosition SLP_INVALID = 0xFFFF;
@@ -216,19 +218,22 @@ protected:
/* Constants for sorting servers */
static GUIGameServerList::SortFunction * const sorter_funcs[];
+ static GUIGameServerList::FilterFunction * const filter_funcs[];
NetworkGameList *server; ///< selected server
NetworkGameList *last_joined; ///< the last joined server
GUIGameServerList servers; ///< list with game servers.
ServerListPosition list_pos; ///< position of the selected server
- Scrollbar *vscroll;
+ Scrollbar *vscroll; ///< vertical scrollbar of the list of servers
QueryString name_editbox; ///< Client name editbox.
+ QueryString filter_editbox; ///< Editbox for filter on servers
/**
- * (Re)build the network game list as its amount has changed because
- * an item has been added or deleted for example
+ * (Re)build the GUI network game list (a.k.a. this->servers) as some
+ * major change has occurred. It ensures appropriate filtering and
+ * sorting, if both or either one is enabled.
*/
- void BuildNetworkGameList()
+ void BuildGUINetworkGameList()
{
if (!this->servers.NeedRebuild()) return;
@@ -239,9 +244,24 @@ protected:
*this->servers.Append() = ngl;
}
+ /* Apply the filter condition immediately, if a search string has been provided. */
+ StringFilter sf;
+ sf.SetFilterTerm(this->filter_editbox.text.buf);
+
+ if (!sf.IsEmpty()) {
+ this->servers.SetFilterState(true);
+ this->servers.Filter(sf);
+ } else {
+ this->servers.SetFilterState(false);
+ }
+
this->servers.Compact();
this->servers.RebuildDone();
this->vscroll->SetCount(this->servers.Length());
+
+ /* Sort the list of network games as requested. */
+ this->servers.Sort();
+ this->UpdateListPos();
}
/**
@@ -344,6 +364,16 @@ protected:
}
}
+ static bool CDECL NGameSearchFilter(NetworkGameList * const *item, StringFilter &sf)
+ {
+ assert(item != NULL);
+ assert((*item) != NULL);
+
+ sf.ResetState();
+ sf.AddLine((*item)->info.server_name);
+ return sf.GetState();
+ }
+
/**
* Draw a single server line.
* @param cur_item the server to draw.
@@ -428,7 +458,7 @@ protected:
}
public:
- NetworkGameWindow(const WindowDesc *desc) : name_editbox(NETWORK_CLIENT_NAME_LENGTH)
+ NetworkGameWindow(const WindowDesc *desc) : name_editbox(NETWORK_CLIENT_NAME_LENGTH), filter_editbox(120)
{
this->list_pos = SLP_INVALID;
this->server = NULL;
@@ -440,7 +470,10 @@ public:
this->querystrings[WID_NG_CLIENT] = &this->name_editbox;
this->name_editbox.text.Assign(_settings_client.network.client_name);
this->name_editbox.afilter = CS_ALPHANUMERAL;
- this->SetFocusedWidget(WID_NG_CLIENT);
+
+ this->querystrings[WID_NG_FILTER] = &this->filter_editbox;
+ this->filter_editbox.cancel_button = QueryString::ACTION_CLEAR;
+ this->SetFocusedWidget(WID_NG_FILTER);
this->last_joined = NetworkGameListAddItem(NetworkAddress(_settings_client.network.last_host, _settings_client.network.last_port));
this->server = this->last_joined;
@@ -448,8 +481,8 @@ public:
this->servers.SetListing(this->last_sorting);
this->servers.SetSortFuncs(this->sorter_funcs);
+ this->servers.SetFilterFuncs(this->filter_funcs);
this->servers.ForceRebuild();
- this->SortNetworkGameList();
}
~NetworkGameWindow()
@@ -561,7 +594,7 @@ public:
virtual void OnPaint()
{
if (this->servers.NeedRebuild()) {
- this->BuildNetworkGameList();
+ this->BuildGUINetworkGameList();
}
this->SortNetworkGameList();
@@ -681,7 +714,7 @@ public:
this->SetDirty();
break;
- case WID_NG_MATRIX: { // Matrix to show networkgames
+ case WID_NG_MATRIX: { // Show available network games
uint id_v = this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_NG_MATRIX);
this->server = (id_v < this->servers.Length()) ? this->servers[id_v] : NULL;
this->list_pos = (server == NULL) ? SLP_INVALID : id_v;
@@ -838,6 +871,14 @@ public:
virtual void OnEditboxChanged(int wid)
{
switch (wid) {
+ case WID_NG_FILTER: {
+ this->servers.ForceRebuild();
+ this->BuildGUINetworkGameList();
+ this->ScrollToSelectedServer();
+ this->SetDirty();
+ break;
+ }
+
case WID_NG_CLIENT:
/* Make sure the name does not start with a space, so TAB completion works */
if (!StrEmpty(this->name_editbox.text.buf) && this->name_editbox.text.buf[0] != ' ') {
@@ -876,6 +917,10 @@ GUIGameServerList::SortFunction * const NetworkGameWindow::sorter_funcs[] = {
&NGameAllowedSorter
};
+GUIGameServerList::FilterFunction * const NetworkGameWindow::filter_funcs[] = {
+ &NGameSearchFilter
+};
+
static NWidgetBase *MakeResizableHeader(int *biggest_index)
{
*biggest_index = max<int>(*biggest_index, WID_NG_INFO);
@@ -891,17 +936,19 @@ static const NWidgetPart _nested_network_game_widgets[] = {
NWidget(WWT_PANEL, COLOUR_LIGHT_BLUE, WID_NG_MAIN),
NWidget(NWID_VERTICAL), SetPIP(10, 7, 0),
NWidget(NWID_HORIZONTAL), SetPIP(10, 7, 10),
- NWidget(WWT_TEXT, COLOUR_LIGHT_BLUE, WID_NG_CONNECTION), SetDataTip(STR_NETWORK_SERVER_LIST_CONNECTION, STR_NULL),
- NWidget(WWT_DROPDOWN, COLOUR_LIGHT_BLUE, WID_NG_CONN_BTN),
- SetDataTip(STR_BLACK_STRING, STR_NETWORK_SERVER_LIST_CONNECTION_TOOLTIP),
- NWidget(NWID_SPACER), SetFill(1, 0), SetResize(1, 0),
- NWidget(WWT_TEXT, COLOUR_LIGHT_BLUE, WID_NG_CLIENT_LABEL), SetDataTip(STR_NETWORK_SERVER_LIST_PLAYER_NAME, STR_NULL),
- NWidget(WWT_EDITBOX, COLOUR_LIGHT_BLUE, WID_NG_CLIENT), SetMinimalSize(151, 12),
- SetDataTip(STR_NETWORK_SERVER_LIST_PLAYER_NAME_OSKTITLE, STR_NETWORK_SERVER_LIST_ENTER_NAME_TOOLTIP),
- EndContainer(),
- NWidget(NWID_HORIZONTAL), SetPIP(10, 7, 10),
/* LEFT SIDE */
- NWidget(NWID_VERTICAL),
+ NWidget(NWID_VERTICAL), SetPIP(0, 7, 0),
+ NWidget(NWID_HORIZONTAL), SetPIP(0, 7, 0),
+ NWidget(WWT_TEXT, COLOUR_LIGHT_BLUE, WID_NG_CONNECTION), SetDataTip(STR_NETWORK_SERVER_LIST_CONNECTION, STR_NULL),
+ NWidget(WWT_DROPDOWN, COLOUR_LIGHT_BLUE, WID_NG_CONN_BTN),
+ SetDataTip(STR_BLACK_STRING, STR_NETWORK_SERVER_LIST_CONNECTION_TOOLTIP),
+ NWidget(NWID_SPACER), SetFill(1, 0), SetResize(1, 0),
+ EndContainer(),
+ NWidget(NWID_HORIZONTAL), SetPIP(0, 7, 0),
+ NWidget(WWT_TEXT, COLOUR_LIGHT_BLUE, WID_NG_FILTER_LABEL), SetDataTip(STR_LIST_FILTER_TITLE, STR_NULL),
+ NWidget(WWT_EDITBOX, COLOUR_LIGHT_BLUE, WID_NG_FILTER), SetMinimalSize(251, 12), SetFill(1, 0), SetResize(1, 0),
+ SetDataTip(STR_LIST_FILTER_OSKTITLE, STR_LIST_FILTER_TOOLTIP),
+ EndContainer(),
NWidget(NWID_HORIZONTAL),
NWidget(NWID_VERTICAL),
NWidgetFunction(MakeResizableHeader),
@@ -910,36 +957,44 @@ static const NWidgetPart _nested_network_game_widgets[] = {
EndContainer(),
NWidget(NWID_VSCROLLBAR, COLOUR_LIGHT_BLUE, WID_NG_SCROLLBAR),
EndContainer(),
- NWidget(NWID_SPACER), SetMinimalSize(0, 7), SetResize(1, 0), SetFill(1, 1),
- NWidget(WWT_TEXT, COLOUR_LIGHT_BLUE, WID_NG_LASTJOINED_LABEL), SetFill(1, 0),
- SetDataTip(STR_NETWORK_SERVER_LIST_LAST_JOINED_SERVER, STR_NULL), SetResize(1, 0),
- NWidget(NWID_HORIZONTAL),
- NWidget(WWT_PANEL, COLOUR_LIGHT_BLUE, WID_NG_LASTJOINED), SetFill(1, 0), SetResize(1, 0),
- SetDataTip(0x0, STR_NETWORK_SERVER_LIST_CLICK_TO_SELECT_LAST),
+ NWidget(NWID_VERTICAL),
+ NWidget(WWT_TEXT, COLOUR_LIGHT_BLUE, WID_NG_LASTJOINED_LABEL), SetFill(1, 0),
+ SetDataTip(STR_NETWORK_SERVER_LIST_LAST_JOINED_SERVER, STR_NULL), SetResize(1, 0),
+ NWidget(NWID_HORIZONTAL),
+ NWidget(WWT_PANEL, COLOUR_LIGHT_BLUE, WID_NG_LASTJOINED), SetFill(1, 0), SetResize(1, 0),
+ SetDataTip(0x0, STR_NETWORK_SERVER_LIST_CLICK_TO_SELECT_LAST),
+ EndContainer(),
+ NWidget(WWT_EMPTY, INVALID_COLOUR, WID_NG_LASTJOINED_SPACER), SetFill(0, 0),
EndContainer(),
- NWidget(WWT_EMPTY, INVALID_COLOUR, WID_NG_LASTJOINED_SPACER), SetFill(0, 0),
EndContainer(),
EndContainer(),
/* RIGHT SIDE */
- NWidget(WWT_PANEL, COLOUR_LIGHT_BLUE, WID_NG_DETAILS),
- NWidget(NWID_VERTICAL, NC_EQUALSIZE), SetPIP(5, 5, 5),
- NWidget(WWT_EMPTY, INVALID_COLOUR, WID_NG_DETAILS_SPACER), SetMinimalSize(140, 155), SetResize(0, 1), SetFill(1, 1), // Make sure it's at least this wide
- NWidget(NWID_HORIZONTAL, NC_NONE), SetPIP(5, 5, 5),
- NWidget(NWID_SELECTION, INVALID_COLOUR, WID_NG_NEWGRF_MISSING_SEL),
- NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NG_NEWGRF_MISSING), SetFill(1, 0), SetDataTip(STR_NEWGRF_SETTINGS_FIND_MISSING_CONTENT_BUTTON, STR_NEWGRF_SETTINGS_FIND_MISSING_CONTENT_TOOLTIP),
- NWidget(NWID_SPACER), SetFill(1, 0),
+ NWidget(NWID_VERTICAL), SetPIP(0, 7, 0),
+ NWidget(NWID_HORIZONTAL), SetPIP(0, 7, 0),
+ NWidget(WWT_TEXT, COLOUR_LIGHT_BLUE, WID_NG_CLIENT_LABEL), SetDataTip(STR_NETWORK_SERVER_LIST_PLAYER_NAME, STR_NULL),
+ NWidget(WWT_EDITBOX, COLOUR_LIGHT_BLUE, WID_NG_CLIENT), SetMinimalSize(151, 12), SetFill(1, 0), SetResize(1, 0),
+ SetDataTip(STR_NETWORK_SERVER_LIST_PLAYER_NAME_OSKTITLE, STR_NETWORK_SERVER_LIST_ENTER_NAME_TOOLTIP),
+ EndContainer(),
+ NWidget(WWT_PANEL, COLOUR_LIGHT_BLUE, WID_NG_DETAILS),
+ NWidget(NWID_VERTICAL, NC_EQUALSIZE), SetPIP(5, 5, 5),
+ NWidget(WWT_EMPTY, INVALID_COLOUR, WID_NG_DETAILS_SPACER), SetMinimalSize(140, 155), SetResize(0, 1), SetFill(1, 1), // Make sure it's at least this wide
+ NWidget(NWID_HORIZONTAL, NC_NONE), SetPIP(5, 5, 5),
+ NWidget(NWID_SELECTION, INVALID_COLOUR, WID_NG_NEWGRF_MISSING_SEL),
+ NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NG_NEWGRF_MISSING), SetFill(1, 0), SetDataTip(STR_NEWGRF_SETTINGS_FIND_MISSING_CONTENT_BUTTON, STR_NEWGRF_SETTINGS_FIND_MISSING_CONTENT_TOOLTIP),
+ NWidget(NWID_SPACER), SetFill(1, 0),
+ EndContainer(),
EndContainer(),
- EndContainer(),
- NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(5, 5, 5),
- NWidget(NWID_SPACER), SetFill(1, 0),
- NWidget(NWID_SELECTION, INVALID_COLOUR, WID_NG_NEWGRF_SEL),
- NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NG_NEWGRF), SetFill(1, 0), SetDataTip(STR_INTRO_NEWGRF_SETTINGS, STR_NULL),
+ NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(5, 5, 5),
NWidget(NWID_SPACER), SetFill(1, 0),
+ NWidget(NWID_SELECTION, INVALID_COLOUR, WID_NG_NEWGRF_SEL),
+ NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NG_NEWGRF), SetFill(1, 0), SetDataTip(STR_INTRO_NEWGRF_SETTINGS, STR_NULL),
+ NWidget(NWID_SPACER), SetFill(1, 0),
+ EndContainer(),
+ EndContainer(),
+ NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(5, 5, 5),
+ NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NG_JOIN), SetFill(1, 0), SetDataTip(STR_NETWORK_SERVER_LIST_JOIN_GAME, STR_NULL),
+ NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NG_REFRESH), SetFill(1, 0), SetDataTip(STR_NETWORK_SERVER_LIST_REFRESH, STR_NETWORK_SERVER_LIST_REFRESH_TOOLTIP),
EndContainer(),
- EndContainer(),
- NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(5, 5, 5),
- NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NG_JOIN), SetFill(1, 0), SetDataTip(STR_NETWORK_SERVER_LIST_JOIN_GAME, STR_NULL),
- NWidget(WWT_PUSHTXTBTN, COLOUR_WHITE, WID_NG_REFRESH), SetFill(1, 0), SetDataTip(STR_NETWORK_SERVER_LIST_REFRESH, STR_NETWORK_SERVER_LIST_REFRESH_TOOLTIP),
EndContainer(),
EndContainer(),
EndContainer(),
diff --git a/src/script/api/game/game_window.hpp.sq b/src/script/api/game/game_window.hpp.sq
index c175fda6b..1ba8dc44b 100644
--- a/src/script/api/game/game_window.hpp.sq
+++ b/src/script/api/game/game_window.hpp.sq
@@ -662,6 +662,8 @@ void SQGSWindow_Register(Squirrel *engine)
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_NG_CONN_BTN, "WID_NG_CONN_BTN");
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_NG_CLIENT_LABEL, "WID_NG_CLIENT_LABEL");
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_NG_CLIENT, "WID_NG_CLIENT");
+ SQGSWindow.DefSQConst(engine, ScriptWindow::WID_NG_FILTER_LABEL, "WID_NG_FILTER_LABEL");
+ SQGSWindow.DefSQConst(engine, ScriptWindow::WID_NG_FILTER, "WID_NG_FILTER");
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_NG_HEADER, "WID_NG_HEADER");
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_NG_NAME, "WID_NG_NAME");
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_NG_CLIENTS, "WID_NG_CLIENTS");
diff --git a/src/script/api/script_window.hpp b/src/script/api/script_window.hpp
index bfe0f81e8..67c4ce3c0 100644
--- a/src/script/api/script_window.hpp
+++ b/src/script/api/script_window.hpp
@@ -1626,6 +1626,8 @@ public:
WID_NG_CONN_BTN = ::WID_NG_CONN_BTN, ///< 'Connection' droplist button.
WID_NG_CLIENT_LABEL = ::WID_NG_CLIENT_LABEL, ///< Label in front of client name edit box.
WID_NG_CLIENT = ::WID_NG_CLIENT, ///< Panel with editbox to set client name.
+ WID_NG_FILTER_LABEL = ::WID_NG_FILTER_LABEL, ///< Label in front of the filter/search edit box.
+ WID_NG_FILTER = ::WID_NG_FILTER, ///< Panel with the edit box to enter the search text.
WID_NG_HEADER = ::WID_NG_HEADER, ///< Header container of the matrix.
WID_NG_NAME = ::WID_NG_NAME, ///< 'Name' button.
diff --git a/src/widgets/network_widget.h b/src/widgets/network_widget.h
index 1c1c0f01e..f5773b8ea 100644
--- a/src/widgets/network_widget.h
+++ b/src/widgets/network_widget.h
@@ -20,6 +20,8 @@ enum NetworkGameWidgets {
WID_NG_CONN_BTN, ///< 'Connection' droplist button.
WID_NG_CLIENT_LABEL, ///< Label in front of client name edit box.
WID_NG_CLIENT, ///< Panel with editbox to set client name.
+ WID_NG_FILTER_LABEL, ///< Label in front of the filter/search edit box.
+ WID_NG_FILTER, ///< Panel with the edit box to enter the search text.
WID_NG_HEADER, ///< Header container of the matrix.
WID_NG_NAME, ///< 'Name' button.