From 03046f614f4fb8c88d1a8ee05e0caee2bde887bc Mon Sep 17 00:00:00 2001 From: frosch Date: Sat, 9 Jun 2012 19:54:16 +0000 Subject: (svn r24337) -Feature: Allow filtering for multiple words (separated by whitespace resp. quoted) in the sign list, content- and NewGRF-guis. --- src/signs_gui.cpp | 55 ++++++++++++++++++------------------------------------- 1 file changed, 18 insertions(+), 37 deletions(-) (limited to 'src/signs_gui.cpp') diff --git a/src/signs_gui.cpp b/src/signs_gui.cpp index 55a527136..6f23f81b9 100644 --- a/src/signs_gui.cpp +++ b/src/signs_gui.cpp @@ -22,6 +22,7 @@ #include "viewport_func.h" #include "querystring_gui.h" #include "sortlist_type.h" +#include "stringfilter_type.h" #include "string_func.h" #include "core/geometry_func.hpp" #include "hotkeys.h" @@ -32,35 +33,23 @@ #include "table/strings.h" #include "table/sprites.h" -/** - * Contains the necessary information to decide if a sign should - * be filtered out or not. This struct is sent as parameter to the - * sort functions of the GUISignList. - */ -struct FilterInfo { - const char *string; ///< String to match sign names against - bool case_sensitive; ///< Should case sensitive matching be used? -}; - struct SignList { /** - * A GUIList contains signs and uses a custom data structure called #FilterInfo for - * passing data to the sort functions. + * A GUIList contains signs and uses a StringFilter for filtering. */ - typedef GUIList GUISignList; + typedef GUIList GUISignList; static const Sign *last_sign; GUISignList signs; - char filter_string[MAX_LENGTH_SIGN_NAME_CHARS * MAX_CHAR_LENGTH]; ///< 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? /** * Creates a SignList with filtering disabled by default. */ - SignList() + SignList() : string_filter(&match_case) { - filter_string[0] = '\0'; } void BuildSignsList() @@ -108,26 +97,28 @@ struct SignList { this->last_sign = NULL; } - /** Filter sign list by sign name (case sensitive setting in FilterInfo) */ - static bool CDECL SignNameFilter(const Sign * const *a, FilterInfo filter_info) + /** Filter sign list by sign name */ + static bool CDECL SignNameFilter(const Sign * const *a, StringFilter &filter) { /* Get sign string */ char buf1[MAX_LENGTH_SIGN_NAME_CHARS * MAX_CHAR_LENGTH]; SetDParam(0, (*a)->index); GetString(buf1, STR_SIGN_NAME, lastof(buf1)); - return (filter_info.case_sensitive ? strstr(buf1, filter_info.string) : strcasestr(buf1, filter_info.string)) != NULL; + filter.ResetState(); + filter.AddLine(buf1); + return filter.GetState(); } /** Filter sign list excluding OWNER_DEITY */ - static bool CDECL OwnerDeityFilter(const Sign * const *a, FilterInfo filter_info) + static bool CDECL OwnerDeityFilter(const Sign * const *a, StringFilter &filter) { /* You should never be able to edit signs of owner DEITY */ return (*a)->owner != OWNER_DEITY; } /** Filter sign list by owner */ - static bool CDECL OwnerVisibilityFilter(const Sign * const *a, FilterInfo filter_info) + static bool CDECL OwnerVisibilityFilter(const Sign * const *a, StringFilter &filter) { assert(!HasBit(_display_opt, DO_SHOW_COMPETITOR_SIGNS)); /* Hide sign if non-own signs are hidden in the viewport */ @@ -137,11 +128,10 @@ struct SignList { /** Filter out signs from the sign list that does not match the name filter */ void FilterSignList() { - FilterInfo filter_info = {this->filter_string, this->match_case}; - this->signs.Filter(&SignNameFilter, filter_info); - if (_game_mode != GM_EDITOR) this->signs.Filter(&OwnerDeityFilter, filter_info); + this->signs.Filter(&SignNameFilter, this->string_filter); + if (_game_mode != GM_EDITOR) this->signs.Filter(&OwnerDeityFilter, this->string_filter); if (!HasBit(_display_opt, DO_SHOW_COMPETITOR_SIGNS)) { - this->signs.Filter(&OwnerVisibilityFilter, filter_info); + this->signs.Filter(&OwnerVisibilityFilter, this->string_filter); } } }; @@ -200,17 +190,8 @@ struct SignListWindow : QueryStringBaseWindow, SignList { void SetFilterString(const char *new_filter_string) { /* check if there is a new filter string */ - if (!StrEmpty(new_filter_string)) { - /* Copy new filter string */ - strecpy(this->filter_string, new_filter_string, lastof(this->filter_string)); - - this->EnableWidget(WID_SIL_FILTER_CLEAR_BTN); - } else { - /* There is no new string -> clear this->filter_string */ - this->filter_string[0] = '\0'; - - this->DisableWidget(WID_SIL_FILTER_CLEAR_BTN); - } + this->string_filter.SetFilterTerm(new_filter_string); + this->SetWidgetDisabledState(WID_SIL_FILTER_CLEAR_BTN, StrEmpty(new_filter_string)); /* Repaint the clear button since its disabled state may have changed */ this->SetWidgetDirty(WID_SIL_FILTER_CLEAR_BTN); @@ -386,7 +367,7 @@ struct SignListWindow : QueryStringBaseWindow, SignList { /* When there is a filter string, we always need to rebuild the list even if * the amount of signs in total is unchanged, as the subset of signs that is * accepted by the filter might has changed. */ - if (data == 0 || data == -1 || !StrEmpty(this->filter_string)) { // New or deleted sign, changed visibility setting or there is a filter string + if (data == 0 || data == -1 || !this->string_filter.IsEmpty()) { // New or deleted sign, changed visibility setting or there is a filter string /* This needs to be done in command-scope to enforce rebuilding before resorting invalid data */ this->signs.ForceRebuild(); } else { // Change of sign contents while there is no filter string -- cgit v1.2.3-54-g00ecf