# HG changeset patch # User frosch # Date 2012-11-14 22:50:35 # Node ID 20d2473dd1cb0f6983d298e4aeb4915c5bd1b0ec # Parent 2d286bcddff93578c6155b765c1baebec99bda74 (svn r24742) -Codechange: Remove QueryStringBaseWindow and store QueryStrings per widget instead. diff --git a/src/ai/ai_gui.cpp b/src/ai/ai_gui.cpp --- a/src/ai/ai_gui.cpp +++ b/src/ai/ai_gui.cpp @@ -981,7 +981,7 @@ static bool SetScriptButtonColour(NWidge /** * Window with everything an AI prints via ScriptLog. */ -struct AIDebugWindow : public QueryStringBaseWindow { +struct AIDebugWindow : public Window { static const int top_offset; ///< Offset of the text at the top of the WID_AID_LOG_PANEL. static const int bottom_offset; ///< Offset of the text at the bottom of the WID_AID_LOG_PANEL. @@ -994,6 +994,7 @@ struct AIDebugWindow : public QueryStrin bool show_break_box; ///< Whether the break/debug box is visible. static bool break_check_enabled; ///< Stop an AI when it prints a matching string static char break_string[MAX_BREAK_STR_STRING_LENGTH]; ///< The string to match to the AI output + QueryString break_editbox; ///< Break editbox static StringFilter break_string_filter; ///< Log filter for break. static bool case_sensitive_break_check; ///< Is the matching done case-sensitive int highlight_row; ///< The output row that matches the given string, or -1 @@ -1010,7 +1011,7 @@ struct AIDebugWindow : public QueryStrin * @param desc The description of the window. * @param number The window number (actually unused). */ - AIDebugWindow(const WindowDesc *desc, WindowNumber number) : QueryStringBaseWindow(MAX_BREAK_STR_STRING_LENGTH) + AIDebugWindow(const WindowDesc *desc, WindowNumber number) : break_editbox(MAX_BREAK_STR_STRING_LENGTH) { this->CreateNestedTree(desc); this->vscroll = this->GetScrollbar(WID_AID_SCROLLBAR); @@ -1032,8 +1033,10 @@ struct AIDebugWindow : public QueryStrin this->autoscroll = true; this->highlight_row = -1; + this->querystrings[WID_AID_BREAK_STR_EDIT_BOX] = &this->break_editbox; + /* Restore the break string value from static variable */ - this->text.Assign(this->break_string); + this->break_editbox.text.Assign(this->break_string); /* Restore button state from static class variables */ if (ai_debug_company == OWNER_DEITY) { @@ -1356,7 +1359,7 @@ struct AIDebugWindow : public QueryStrin { if (wid == WID_AID_BREAK_STR_EDIT_BOX) { /* Save the current string to static member so it can be restored next time the window is opened. */ - strecpy(this->break_string, this->text.buf, lastof(this->break_string)); + strecpy(this->break_string, this->break_editbox.text.buf, lastof(this->break_string)); break_string_filter.SetFilterTerm(this->break_string); } } diff --git a/src/fios_gui.cpp b/src/fios_gui.cpp --- a/src/fios_gui.cpp +++ b/src/fios_gui.cpp @@ -228,8 +228,9 @@ static void MakeSortedSaveGameList() QSortT(_fios_items.Get(sort_start), s_amount, CompareFiosItems); } -struct SaveLoadWindow : public QueryStringBaseWindow { +struct SaveLoadWindow : public Window { private: + QueryString filename_editbox; ///< Filename editbox. FiosItem o_dir; const FiosItem *selected; Scrollbar *vscroll; @@ -238,11 +239,11 @@ public: /** Generate a default save filename. */ void GenerateFileName() { - GenerateDefaultSaveName(this->text.buf, &this->text.buf[this->text.max_bytes - 1]); - this->text.UpdateSize(); + GenerateDefaultSaveName(this->filename_editbox.text.buf, &this->filename_editbox.text.buf[this->filename_editbox.text.max_bytes - 1]); + this->filename_editbox.text.UpdateSize(); } - SaveLoadWindow(const WindowDesc *desc, SaveLoadDialogMode mode) : QueryStringBaseWindow(64) + SaveLoadWindow(const WindowDesc *desc, SaveLoadDialogMode mode) : filename_editbox(64) { static const StringID saveload_captions[] = { STR_SAVELOAD_LOAD_CAPTION, @@ -259,12 +260,13 @@ public: switch (mode) { case SLD_SAVE_GAME: this->GenerateFileName(); break; case SLD_SAVE_HEIGHTMAP: - case SLD_SAVE_SCENARIO: this->text.Assign("UNNAMED"); break; + case SLD_SAVE_SCENARIO: this->filename_editbox.text.Assign("UNNAMED"); break; default: break; } - this->ok_button = WID_SL_SAVE_GAME; - this->afilter = CS_ALPHANUMERAL; + this->querystrings[WID_SL_SAVE_OSK_TITLE] = &this->filename_editbox; + this->filename_editbox.ok_button = WID_SL_SAVE_GAME; + this->filename_editbox.afilter = CS_ALPHANUMERAL; this->CreateNestedTree(desc, true); if (mode == SLD_LOAD_GAME) this->GetWidget(WID_SL_CONTENT_DOWNLOAD_SEL)->SetDisplayedPlane(SZSP_HORIZONTAL); @@ -567,7 +569,7 @@ public: } if (_saveload_mode == SLD_SAVE_GAME || _saveload_mode == SLD_SAVE_SCENARIO || _saveload_mode == SLD_SAVE_HEIGHTMAP) { /* Copy clicked name to editbox */ - this->text.Assign(file->title); + this->filename_editbox.text.Assign(file->title); this->SetWidgetDirty(WID_SL_SAVE_OSK_TITLE); } } else if (!_load_check_data.HasErrors()) { @@ -631,7 +633,7 @@ public: if (!(_saveload_mode == SLD_SAVE_GAME || _saveload_mode == SLD_SAVE_SCENARIO || _saveload_mode == SLD_SAVE_HEIGHTMAP)) return; if (this->IsWidgetLowered(WID_SL_DELETE_SELECTION)) { // Delete button clicked - if (!FiosDelete(this->text.buf)) { + if (!FiosDelete(this->filename_editbox.text.buf)) { ShowErrorMessage(STR_ERROR_UNABLE_TO_DELETE_FILE, INVALID_STRING_ID, WL_ERROR); } else { this->InvalidateData(); @@ -641,10 +643,10 @@ public: } else if (this->IsWidgetLowered(WID_SL_SAVE_GAME)) { // Save button clicked if (_saveload_mode == SLD_SAVE_GAME || _saveload_mode == SLD_SAVE_SCENARIO) { _switch_mode = SM_SAVE_GAME; - FiosMakeSavegameName(_file_to_saveload.name, this->text.buf, sizeof(_file_to_saveload.name)); + FiosMakeSavegameName(_file_to_saveload.name, this->filename_editbox.text.buf, sizeof(_file_to_saveload.name)); } else { _switch_mode = SM_SAVE_HEIGHTMAP; - FiosMakeHeightmapName(_file_to_saveload.name, this->text.buf, sizeof(_file_to_saveload.name)); + FiosMakeHeightmapName(_file_to_saveload.name, this->filename_editbox.text.buf, sizeof(_file_to_saveload.name)); } /* In the editor set up the vehicle engines correctly (date might have changed) */ diff --git a/src/genworld_gui.cpp b/src/genworld_gui.cpp --- a/src/genworld_gui.cpp +++ b/src/genworld_gui.cpp @@ -303,22 +303,24 @@ static const StringID _variety[] = { assert_compile(lengthof(_num_inds) == ID_END + 1); -struct GenerateLandscapeWindow : public QueryStringBaseWindow { +struct GenerateLandscapeWindow : public Window { uint widget_id; uint x; uint y; char name[64]; GenenerateLandscapeWindowMode mode; + QueryString seed_editbox; - GenerateLandscapeWindow(const WindowDesc *desc, WindowNumber number = 0) : QueryStringBaseWindow(11) + GenerateLandscapeWindow(const WindowDesc *desc, WindowNumber number = 0) : seed_editbox(11) { this->InitNested(desc, number); this->LowerWidget(_settings_newgame.game_creation.landscape + WID_GL_TEMPERATE); - this->text.Print("%u", _settings_newgame.game_creation.generation_seed); - this->caption = STR_NULL; - this->afilter = CS_NUMERAL; + this->querystrings[WID_GL_RANDOM_EDITBOX] = &this->seed_editbox; + this->seed_editbox.text.Print("%u", _settings_newgame.game_creation.generation_seed); + this->seed_editbox.caption = STR_NULL; + this->seed_editbox.afilter = CS_NUMERAL; this->mode = (GenenerateLandscapeWindowMode)this->window_number; @@ -547,7 +549,7 @@ struct GenerateLandscapeWindow : public case WID_GL_RANDOM_BUTTON: // Random seed _settings_newgame.game_creation.generation_seed = InteractiveRandom(); - this->text.Print("%u", _settings_newgame.game_creation.generation_seed); + this->seed_editbox.text.Print("%u", _settings_newgame.game_creation.generation_seed); this->SetDirty(); break; @@ -698,7 +700,7 @@ struct GenerateLandscapeWindow : public * As UINT32_MAX is a 'magic' value (use random seed) it * should not be possible to be entered into the input * field; the generate seed button can be used instead. */ - _settings_newgame.game_creation.generation_seed = minu(strtoul(this->text.buf, NULL, 10), UINT32_MAX - 1); + _settings_newgame.game_creation.generation_seed = minu(strtoul(this->seed_editbox.text.buf, NULL, 10), UINT32_MAX - 1); } } diff --git a/src/misc_gui.cpp b/src/misc_gui.cpp --- a/src/misc_gui.cpp +++ b/src/misc_gui.cpp @@ -812,30 +812,33 @@ void QueryString::DrawEditBox(const Wind } /** Class for the string query window. */ -struct QueryStringWindow : public QueryStringBaseWindow +struct QueryStringWindow : public Window { + QueryString editbox; ///< Editbox. QueryStringFlags flags; ///< Flags controlling behaviour of the window. QueryStringWindow(StringID str, StringID caption, uint max_bytes, uint max_chars, const WindowDesc *desc, Window *parent, CharSetFilter afilter, QueryStringFlags flags) : - QueryStringBaseWindow(max_bytes, max_chars) + editbox(max_bytes, max_chars) { - GetString(this->text.buf, str, &this->text.buf[this->text.max_bytes - 1]); - str_validate(this->text.buf, &this->text.buf[this->text.max_bytes - 1], SVS_NONE); + char *last_of = &this->editbox.text.buf[this->editbox.text.max_bytes - 1]; + GetString(this->editbox.text.buf, str, last_of); + str_validate(this->editbox.text.buf, last_of, SVS_NONE); /* Make sure the name isn't too long for the text buffer in the number of * characters (not bytes). max_chars also counts the '\0' characters. */ - while (Utf8StringLength(this->text.buf) + 1 > this->text.max_chars) { - *Utf8PrevChar(this->text.buf + strlen(this->text.buf)) = '\0'; + while (Utf8StringLength(this->editbox.text.buf) + 1 > this->editbox.text.max_chars) { + *Utf8PrevChar(this->editbox.text.buf + strlen(this->editbox.text.buf)) = '\0'; } - this->text.UpdateSize(); + this->editbox.text.UpdateSize(); - if ((flags & QSF_ACCEPT_UNCHANGED) == 0) this->orig = strdup(this->text.buf); + if ((flags & QSF_ACCEPT_UNCHANGED) == 0) this->editbox.orig = strdup(this->editbox.text.buf); - this->caption = caption; - this->cancel_button = WID_QS_CANCEL; - this->ok_button = WID_QS_OK; - this->afilter = afilter; + this->querystrings[WID_QS_TEXT] = &this->editbox; + this->editbox.caption = caption; + this->editbox.cancel_button = WID_QS_CANCEL; + this->editbox.ok_button = WID_QS_OK; + this->editbox.afilter = afilter; this->flags = flags; this->InitNested(desc, WN_QUERY_STRING); @@ -858,20 +861,20 @@ struct QueryStringWindow : public QueryS virtual void SetStringParameters(int widget) const { - if (widget == WID_QS_CAPTION) SetDParam(0, this->caption); + if (widget == WID_QS_CAPTION) SetDParam(0, this->editbox.caption); } void OnOk() { - if (this->orig == NULL || strcmp(this->text.buf, this->orig) != 0) { + if (this->editbox.orig == NULL || strcmp(this->editbox.text.buf, this->editbox.orig) != 0) { /* If the parent is NULL, the editbox is handled by general function * HandleOnEditText */ if (this->parent != NULL) { - this->parent->OnQueryTextFinished(this->text.buf); + this->parent->OnQueryTextFinished(this->editbox.text.buf); } else { - HandleOnEditText(this->text.buf); + HandleOnEditText(this->editbox.text.buf); } - this->handled = true; + this->editbox.handled = true; } } @@ -879,7 +882,7 @@ struct QueryStringWindow : public QueryS { switch (widget) { case WID_QS_DEFAULT: - this->text.buf[0] = '\0'; + this->editbox.text.DeleteAll(); /* FALL THROUGH */ case WID_QS_OK: this->OnOk(); @@ -892,7 +895,7 @@ struct QueryStringWindow : public QueryS ~QueryStringWindow() { - if (!this->handled && this->parent != NULL) { + if (!this->editbox.handled && this->parent != NULL) { Window *parent = this->parent; this->parent = NULL; // so parent doesn't try to delete us again parent->OnQueryTextFinished(NULL); diff --git a/src/network/network_chat_gui.cpp b/src/network/network_chat_gui.cpp --- a/src/network/network_chat_gui.cpp +++ b/src/network/network_chat_gui.cpp @@ -284,10 +284,11 @@ static void SendChat(const char *buf, De } /** Window to enter the chat message in. */ -struct NetworkChatWindow : public QueryStringBaseWindow { +struct NetworkChatWindow : public Window { DestType dtype; ///< The type of destination. StringID dest_string; ///< String representation of the destination. int dest; ///< The identifier of the destination. + QueryString message_editbox; ///< Message editbox. /** * Create a chat input window. @@ -295,13 +296,14 @@ struct NetworkChatWindow : public QueryS * @param type The type of destination. * @param dest The actual destination index. */ - NetworkChatWindow(const WindowDesc *desc, DestType type, int dest) : QueryStringBaseWindow(NETWORK_CHAT_LENGTH) + NetworkChatWindow(const WindowDesc *desc, DestType type, int dest) : message_editbox(NETWORK_CHAT_LENGTH) { this->dtype = type; this->dest = dest; - this->cancel_button = WID_NC_CLOSE; - this->ok_button = WID_NC_SENDBUTTON; - this->afilter = CS_ALPHANUMERAL; + this->querystrings[WID_NC_TEXTBOX] = &this->message_editbox; + this->message_editbox.cancel_button = WID_NC_CLOSE; + this->message_editbox.ok_button = WID_NC_SENDBUTTON; + this->message_editbox.afilter = CS_ALPHANUMERAL; static const StringID chat_captions[] = { STR_NETWORK_CHAT_ALL_CAPTION, @@ -383,9 +385,9 @@ struct NetworkChatWindow : public QueryS void ChatTabCompletion() { static char _chat_tab_completion_buf[NETWORK_CHAT_LENGTH]; - assert(this->text.max_bytes == lengthof(_chat_tab_completion_buf)); + assert(this->message_editbox.text.max_bytes == lengthof(_chat_tab_completion_buf)); - Textbuf *tb = &this->text; + Textbuf *tb = &this->message_editbox.text; size_t len, tb_len; uint item; char *tb_buf, *pre_buf; @@ -437,9 +439,9 @@ struct NetworkChatWindow : public QueryS /* Change to the found name. Add ': ' if we are at the start of the line (pretty) */ if (pre_buf == tb_buf) { - this->text.Print("%s: ", cur_name); + this->message_editbox.text.Print("%s: ", cur_name); } else { - this->text.Print("%s %s", pre_buf, cur_name); + this->message_editbox.text.Print("%s %s", pre_buf, cur_name); } this->SetDirty(); @@ -450,7 +452,7 @@ struct NetworkChatWindow : public QueryS if (second_scan) { /* We walked all posibilities, and the user presses tab again.. revert to original text */ - this->text.Assign(_chat_tab_completion_buf); + this->message_editbox.text.Assign(_chat_tab_completion_buf); _chat_tab_completion_active = false; this->SetDirty(); @@ -491,7 +493,7 @@ struct NetworkChatWindow : public QueryS { switch (widget) { /* Send */ - case WID_NC_SENDBUTTON: SendChat(this->text.buf, this->dtype, this->dest); + case WID_NC_SENDBUTTON: SendChat(this->message_editbox.text.buf, this->dtype, this->dest); /* FALL THROUGH */ case WID_NC_CLOSE: /* Cancel */ delete this; break; } diff --git a/src/network/network_content_gui.cpp b/src/network/network_content_gui.cpp --- a/src/network/network_content_gui.cpp +++ b/src/network/network_content_gui.cpp @@ -276,7 +276,7 @@ public: }; /** Window that lists the content that's at the content server */ -class NetworkContentListWindow : public QueryStringBaseWindow, ContentCallback { +class NetworkContentListWindow : public Window, ContentCallback { /** List with content infos. */ typedef GUIList GUIContentList; @@ -289,6 +289,7 @@ class NetworkContentListWindow : public GUIContentList content; ///< List with content bool auto_select; ///< Automatically select all content when the meta-data becomes available StringFilter string_filter; ///< Filter for content list + QueryString filter_editbox; ///< Filter editbox; const ContentInfo *selected; ///< The selected content info int list_pos; ///< Our position in the list @@ -405,8 +406,8 @@ public: * @param select_all Whether the select all button is allowed or not. */ NetworkContentListWindow(const WindowDesc *desc, bool select_all) : - QueryStringBaseWindow(EDITBOX_MAX_SIZE), auto_select(select_all), + filter_editbox(EDITBOX_MAX_SIZE), selected(NULL), list_pos(0) { @@ -416,7 +417,8 @@ public: this->GetWidget(WID_NCL_SEL_ALL_UPDATE)->SetDisplayedPlane(select_all); - this->afilter = CS_ALPHANUMERAL; + this->querystrings[WID_NCL_FILTER] = &this->filter_editbox; + this->filter_editbox.afilter = CS_ALPHANUMERAL; this->SetFocusedWidget(WID_NCL_FILTER); _network_content_client.AddCallback(this); @@ -780,7 +782,7 @@ public: virtual void OnEditboxChanged(int wid) { if (wid == WID_NCL_FILTER) { - this->string_filter.SetFilterTerm(this->text.buf); + this->string_filter.SetFilterTerm(this->filter_editbox.text.buf); this->content.SetFilterState(!this->string_filter.IsEmpty()); this->content.ForceRebuild(); this->InvalidateData(); diff --git a/src/network/network_gui.cpp b/src/network/network_gui.cpp --- a/src/network/network_gui.cpp +++ b/src/network/network_gui.cpp @@ -209,7 +209,7 @@ public: } }; -class NetworkGameWindow : public QueryStringBaseWindow { +class NetworkGameWindow : public Window { protected: /* Runtime saved values */ static Listing last_sorting; @@ -222,6 +222,7 @@ protected: GUIGameServerList servers; ///< list with game servers. ServerListPosition list_pos; ///< position of the selected server Scrollbar *vscroll; + QueryString name_editbox; ///< Client name editbox. /** * (Re)build the network game list as its amount has changed because @@ -435,7 +436,7 @@ protected: } public: - NetworkGameWindow(const WindowDesc *desc) : QueryStringBaseWindow(NETWORK_CLIENT_NAME_LENGTH) + NetworkGameWindow(const WindowDesc *desc) : name_editbox(NETWORK_CLIENT_NAME_LENGTH) { this->list_pos = SLP_INVALID; this->server = NULL; @@ -444,8 +445,9 @@ public: this->vscroll = this->GetScrollbar(WID_NG_SCROLLBAR); this->FinishInitNested(desc, WN_NETWORK_WINDOW_GAME); - this->text.Assign(_settings_client.network.client_name); - this->afilter = CS_ALPHANUMERAL; + 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->last_joined = NetworkGameListAddItem(NetworkAddress(_settings_client.network.last_host, _settings_client.network.last_port)); @@ -850,8 +852,8 @@ public: { if (wid == WID_NG_CLIENT) { /* The name is only allowed when it starts with a letter! */ - if (!StrEmpty(this->text.buf) && this->text.buf[0] != ' ') { - strecpy(_settings_client.network.client_name, this->text.buf, lastof(_settings_client.network.client_name)); + if (!StrEmpty(this->name_editbox.text.buf) && this->name_editbox.text.buf[0] != ' ') { + strecpy(_settings_client.network.client_name, this->name_editbox.text.buf, lastof(_settings_client.network.client_name)); } else { strecpy(_settings_client.network.client_name, "Player", lastof(_settings_client.network.client_name)); } @@ -998,16 +1000,18 @@ void ShowNetworkGameWindow() new NetworkGameWindow(&_network_game_window_desc); } -struct NetworkStartServerWindow : public QueryStringBaseWindow { +struct NetworkStartServerWindow : public Window { byte widget_id; ///< The widget that has the pop-up input menu + QueryString name_editbox; ///< Server name editbox. - NetworkStartServerWindow(const WindowDesc *desc) : QueryStringBaseWindow(NETWORK_NAME_LENGTH) + NetworkStartServerWindow(const WindowDesc *desc) : name_editbox(NETWORK_NAME_LENGTH) { this->InitNested(desc, WN_NETWORK_WINDOW_START); - this->text.Assign(_settings_client.network.server_name); + this->querystrings[WID_NSS_GAMENAME] = &this->name_editbox; + this->name_editbox.text.Assign(_settings_client.network.server_name); - this->afilter = CS_ALPHANUMERAL; + this->name_editbox.afilter = CS_ALPHANUMERAL; this->SetFocusedWidget(WID_NSS_GAMENAME); } @@ -1171,7 +1175,7 @@ struct NetworkStartServerWindow : public virtual void OnEditboxChanged(int wid) { if (wid == WID_NSS_GAMENAME) { - strecpy(_settings_client.network.server_name, this->text.buf, lastof(_settings_client.network.server_name)); + strecpy(_settings_client.network.server_name, this->name_editbox.text.buf, lastof(_settings_client.network.server_name)); } } @@ -2101,25 +2105,28 @@ void ShowNetworkNeedPassword(NetworkPass ShowQueryString(STR_EMPTY, caption, NETWORK_PASSWORD_LENGTH, w, CS_ALPHANUMERAL, QSF_NONE); } -struct NetworkCompanyPasswordWindow : public QueryStringBaseWindow { - NetworkCompanyPasswordWindow(const WindowDesc *desc, Window *parent) : QueryStringBaseWindow(lengthof(_settings_client.network.default_company_pass)) +struct NetworkCompanyPasswordWindow : public Window { + QueryString password_editbox; ///< Password editbox. + + NetworkCompanyPasswordWindow(const WindowDesc *desc, Window *parent) : password_editbox(lengthof(_settings_client.network.default_company_pass)) { this->InitNested(desc, 0); this->parent = parent; - this->cancel_button = WID_NCP_CANCEL; - this->ok_button = WID_NCP_OK; - this->afilter = CS_ALPHANUMERAL; + this->querystrings[WID_NCP_PASSWORD] = &this->password_editbox; + this->password_editbox.cancel_button = WID_NCP_CANCEL; + this->password_editbox.ok_button = WID_NCP_OK; + this->password_editbox.afilter = CS_ALPHANUMERAL; this->SetFocusedWidget(WID_NCP_PASSWORD); } void OnOk() { if (this->IsWidgetLowered(WID_NCP_SAVE_AS_DEFAULT_PASSWORD)) { - strecpy(_settings_client.network.default_company_pass, this->text.buf, lastof(_settings_client.network.default_company_pass)); + strecpy(_settings_client.network.default_company_pass, this->password_editbox.text.buf, lastof(_settings_client.network.default_company_pass)); } - NetworkChangeCompanyPassword(_local_company, this->text.buf); + NetworkChangeCompanyPassword(_local_company, this->password_editbox.text.buf); } virtual void OnClick(Point pt, int widget, int click_count) diff --git a/src/newgrf_gui.cpp b/src/newgrf_gui.cpp --- a/src/newgrf_gui.cpp +++ b/src/newgrf_gui.cpp @@ -585,7 +585,7 @@ static void NewGRFConfirmationCallback(W /** * Window for showing NewGRF files */ -struct NewGRFWindow : public QueryStringBaseWindow, NewGRFScanCallback { +struct NewGRFWindow : public Window, NewGRFScanCallback { typedef GUIList GUIGRFConfigList; static const uint EDITBOX_MAX_SIZE = 50; @@ -599,6 +599,7 @@ struct NewGRFWindow : public QueryString const GRFConfig *avail_sel; ///< Currently selected available grf. \c NULL is none is selected. int avail_pos; ///< Index of #avail_sel if existing, else \c -1. StringFilter string_filter; ///< Filter for available grf. + QueryString filter_editbox; ///< Filter editbox; GRFConfig *actives; ///< Temporary active grf list to which changes are made. GRFConfig *active_sel; ///< Selected active grf item. @@ -613,7 +614,7 @@ struct NewGRFWindow : public QueryString Scrollbar *vscroll; Scrollbar *vscroll2; - NewGRFWindow(const WindowDesc *desc, bool editable, bool show_params, bool execute, GRFConfig **orig_list) : QueryStringBaseWindow(EDITBOX_MAX_SIZE) + NewGRFWindow(const WindowDesc *desc, bool editable, bool show_params, bool execute, GRFConfig **orig_list) : filter_editbox(EDITBOX_MAX_SIZE) { this->avail_sel = NULL; this->avail_pos = -1; @@ -637,6 +638,7 @@ struct NewGRFWindow : public QueryString this->GetWidget(WID_NS_SHOW_APPLY)->SetDisplayedPlane(this->editable ? 0 : this->show_params ? 1 : SZSP_HORIZONTAL); this->FinishInitNested(desc, WN_GAME_OPTIONS_NEWGRF_STATE); + this->querystrings[WID_NS_FILTER] = &this->filter_editbox; this->SetFocusedWidget(WID_NS_FILTER); this->avails.SetListing(this->last_sorting); @@ -1279,7 +1281,7 @@ struct NewGRFWindow : public QueryString { if (!this->editable) return; - string_filter.SetFilterTerm(this->text.buf); + string_filter.SetFilterTerm(this->filter_editbox.text.buf); this->avails.SetFilterState(!string_filter.IsEmpty()); this->avails.ForceRebuild(); this->InvalidateData(0); diff --git a/src/osk_gui.cpp b/src/osk_gui.cpp --- a/src/osk_gui.cpp +++ b/src/osk_gui.cpp @@ -40,18 +40,19 @@ struct OskWindow : public Window { char *orig_str_buf; ///< Original string. bool shift; ///< Is the shift effectively pressed? - OskWindow(const WindowDesc *desc, QueryStringBaseWindow *parent, int button) : Window() + OskWindow(const WindowDesc *desc, Window *parent, int button) : Window() { this->parent = parent; assert(parent != NULL); NWidgetCore *par_wid = parent->GetWidget(button); assert(par_wid != NULL); - this->caption = (par_wid->widget_data != STR_NULL) ? par_wid->widget_data : parent->caption; - this->qs = parent; + assert(parent->querystrings.Contains(button)); + this->qs = parent->querystrings.Find(button)->second; + this->caption = (par_wid->widget_data != STR_NULL) ? par_wid->widget_data : this->qs->caption; this->text_btn = button; - this->text = &parent->text; + this->text = &this->qs->text; /* make a copy in case we need to reset later */ this->orig_str_buf = strdup(this->qs->text.buf); @@ -423,7 +424,7 @@ void GetKeyboardLayout() * @param parent pointer to the Window where this keyboard originated from * @param button widget number of parent's textbox */ -void ShowOnScreenKeyboard(QueryStringBaseWindow *parent, int button) +void ShowOnScreenKeyboard(Window *parent, int button) { DeleteWindowById(WC_OSK, 0); @@ -438,10 +439,10 @@ void ShowOnScreenKeyboard(QueryStringBas * @param parent window that just updated its orignal text * @param button widget number of parent's textbox to update */ -void UpdateOSKOriginalText(const QueryStringBaseWindow *parent, int button) +void UpdateOSKOriginalText(const Window *parent, int button) { OskWindow *osk = dynamic_cast(FindWindowById(WC_OSK, 0)); - if (osk == NULL || osk->qs != parent || osk->text_btn != button) return; + if (osk == NULL || osk->parent != parent || osk->text_btn != button) return; free(osk->orig_str_buf); osk->orig_str_buf = strdup(osk->qs->text.buf); diff --git a/src/querystring_gui.h b/src/querystring_gui.h --- a/src/querystring_gui.h +++ b/src/querystring_gui.h @@ -64,14 +64,7 @@ public: HandleEditBoxResult HandleEditBoxKey(Window *w, int wid, uint16 key, uint16 keycode, EventState &state); }; -struct QueryStringBaseWindow : public Window, public QueryString { - QueryStringBaseWindow(uint16 size, uint16 chars = UINT16_MAX) : Window(), QueryString(size, chars) - { - } - -}; - -void ShowOnScreenKeyboard(QueryStringBaseWindow *parent, int button); -void UpdateOSKOriginalText(const QueryStringBaseWindow *parent, int button); +void ShowOnScreenKeyboard(Window *parent, int button); +void UpdateOSKOriginalText(const Window *parent, int button); #endif /* QUERYSTRING_GUI_H */ diff --git a/src/settings_gui.cpp b/src/settings_gui.cpp --- a/src/settings_gui.cpp +++ b/src/settings_gui.cpp @@ -1956,7 +1956,7 @@ static const StringID _game_settings_res }; assert_compile(lengthof(_game_settings_restrict_dropdown) == RM_END); -struct GameSettingsWindow : QueryStringBaseWindow { +struct GameSettingsWindow : Window { static const int SETTINGTREE_LEFT_OFFSET = 5; ///< Position of left edge of setting values static const int SETTINGTREE_RIGHT_OFFSET = 5; ///< Position of right edge of setting values static const int SETTINGTREE_TOP_OFFSET = 5; ///< Position of top edge of setting values @@ -1971,13 +1971,14 @@ struct GameSettingsWindow : QueryStringB bool closing_dropdown; ///< True, if the dropdown list is currently closing. StringFilter string_filter; ///< Text filter for settings. + QueryString filter_editbox; ///< Filter editbox; bool manually_changed_folding; ///< Whether the user expanded/collapsed something manually. RestrictionMode cur_restriction_mode; ///< Currently selected index of the drop down list for the restrict drop down. Scrollbar *vscroll; - GameSettingsWindow(const WindowDesc *desc) : QueryStringBaseWindow(50), cur_restriction_mode((RestrictionMode)_settings_client.gui.settings_restriction_mode) + GameSettingsWindow(const WindowDesc *desc) : filter_editbox(50), cur_restriction_mode((RestrictionMode)_settings_client.gui.settings_restriction_mode) { static bool first_time = true; @@ -2002,6 +2003,7 @@ struct GameSettingsWindow : QueryStringB this->vscroll = this->GetScrollbar(WID_GS_SCROLLBAR); this->FinishInitNested(desc, WN_GAME_OPTIONS_GAME_SETTINGS); + this->querystrings[WID_GS_FILTER] = &this->filter_editbox; this->SetFocusedWidget(WID_GS_FILTER); this->InvalidateData(); @@ -2408,7 +2410,7 @@ struct GameSettingsWindow : QueryStringB virtual void OnEditboxChanged(int wid) { if (wid == WID_GS_FILTER) { - string_filter.SetFilterTerm(this->text.buf); + string_filter.SetFilterTerm(this->filter_editbox.text.buf); if (!string_filter.IsEmpty() && !this->manually_changed_folding) { /* User never expanded/collapsed single pages and entered a filter term. * Expand everything, to save weird expand clicks, */ diff --git a/src/signs_gui.cpp b/src/signs_gui.cpp --- a/src/signs_gui.cpp +++ b/src/signs_gui.cpp @@ -144,11 +144,12 @@ enum SignListHotkeys { SLHK_FOCUS_FILTER_BOX, ///< Focus the edit box for editing the filter string }; -struct SignListWindow : QueryStringBaseWindow, SignList { +struct SignListWindow : Window, SignList { + QueryString filter_editbox; ///< Filter editbox; int text_offset; ///< Offset of the sign text relative to the left edge of the WID_SIL_LIST widget. Scrollbar *vscroll; - SignListWindow(const WindowDesc *desc, WindowNumber window_number) : QueryStringBaseWindow(MAX_LENGTH_SIGN_NAME_CHARS * MAX_CHAR_LENGTH, MAX_LENGTH_SIGN_NAME_CHARS) + SignListWindow(const WindowDesc *desc, WindowNumber window_number) : filter_editbox(MAX_LENGTH_SIGN_NAME_CHARS * MAX_CHAR_LENGTH, MAX_LENGTH_SIGN_NAME_CHARS) { this->CreateNestedTree(desc); this->vscroll = this->GetScrollbar(WID_SIL_SCROLLBAR); @@ -156,9 +157,10 @@ struct SignListWindow : QueryStringBaseW this->SetWidgetLoweredState(WID_SIL_FILTER_MATCH_CASE_BTN, SignList::match_case); /* Initialize the text edit widget */ - this->ok_button = WID_SIL_FILTER_ENTER_BTN; - this->cancel_button = WID_SIL_FILTER_CLEAR_BTN; - this->afilter = CS_ALPHANUMERAL; + this->querystrings[WID_SIL_FILTER_TEXT] = &this->filter_editbox; + this->filter_editbox.ok_button = WID_SIL_FILTER_ENTER_BTN; + this->filter_editbox.cancel_button = WID_SIL_FILTER_CLEAR_BTN; + this->filter_editbox.afilter = CS_ALPHANUMERAL; /* Initialize the filtering variables */ this->SetFilterString(""); @@ -175,7 +177,7 @@ struct SignListWindow : QueryStringBaseW */ void ClearFilterTextWidget() { - this->text.DeleteAll(); + this->filter_editbox.text.DeleteAll(); this->SetWidgetDirty(WID_SIL_FILTER_TEXT); } @@ -314,7 +316,7 @@ struct SignListWindow : QueryStringBaseW virtual void OnEditboxChanged(int widget) { - if (widget == WID_SIL_FILTER_TEXT) this->SetFilterString(this->text.buf); + if (widget == WID_SIL_FILTER_TEXT) this->SetFilterString(this->filter_editbox.text.buf); } void BuildSortSignList() @@ -428,15 +430,17 @@ static bool RenameSign(SignID index, con return remove; } -struct SignWindow : QueryStringBaseWindow, SignList { +struct SignWindow : Window, SignList { + QueryString name_editbox; SignID cur_sign; - SignWindow(const WindowDesc *desc, const Sign *si) : QueryStringBaseWindow(MAX_LENGTH_SIGN_NAME_CHARS * MAX_CHAR_LENGTH, MAX_LENGTH_SIGN_NAME_CHARS) + SignWindow(const WindowDesc *desc, const Sign *si) : name_editbox(MAX_LENGTH_SIGN_NAME_CHARS * MAX_CHAR_LENGTH, MAX_LENGTH_SIGN_NAME_CHARS) { - this->caption = STR_EDIT_SIGN_CAPTION; - this->cancel_button = WID_QES_CANCEL; - this->ok_button = WID_QES_OK; - this->afilter = CS_ALPHANUMERAL; + this->querystrings[WID_QES_TEXT] = &this->name_editbox; + this->name_editbox.caption = STR_EDIT_SIGN_CAPTION; + this->name_editbox.cancel_button = WID_QES_CANCEL; + this->name_editbox.ok_button = WID_QES_OK; + this->name_editbox.afilter = CS_ALPHANUMERAL; this->InitNested(desc, WN_QUERY_STRING_SIGN); @@ -450,9 +454,9 @@ struct SignWindow : QueryStringBaseWindo /* Display an empty string when the sign hasnt been edited yet */ if (si->name != NULL) { SetDParam(0, si->index); - this->text.Assign(STR_SIGN_NAME); + this->name_editbox.text.Assign(STR_SIGN_NAME); } else { - this->text.DeleteAll(); + this->name_editbox.text.DeleteAll(); } this->cur_sign = si->index; @@ -492,7 +496,7 @@ struct SignWindow : QueryStringBaseWindo { switch (widget) { case WID_QES_CAPTION: - SetDParam(0, this->caption); + SetDParam(0, this->name_editbox.caption); break; } } @@ -523,7 +527,7 @@ struct SignWindow : QueryStringBaseWindo break; case WID_QES_OK: - if (RenameSign(this->cur_sign, this->text.buf)) break; + if (RenameSign(this->cur_sign, this->name_editbox.text.buf)) break; /* FALL THROUGH */ case WID_QES_CANCEL: diff --git a/src/town_gui.cpp b/src/town_gui.cpp --- a/src/town_gui.cpp +++ b/src/town_gui.cpp @@ -978,23 +978,25 @@ static const NWidgetPart _nested_found_t }; /** Found a town window class. */ -struct FoundTownWindow : QueryStringBaseWindow { +struct FoundTownWindow : Window { private: TownSize town_size; ///< Selected town size TownLayout town_layout; ///< Selected town layout bool city; ///< Are we building a city? + QueryString townname_editbox; ///< Townname editbox bool townnamevalid; ///< Is generated town name valid? uint32 townnameparts; ///< Generated town name TownNameParams params; ///< Town name parameters public: FoundTownWindow(const WindowDesc *desc, WindowNumber window_number) : - QueryStringBaseWindow(MAX_LENGTH_TOWN_NAME_CHARS * MAX_CHAR_LENGTH, MAX_LENGTH_TOWN_NAME_CHARS), town_size(TSZ_MEDIUM), town_layout(_settings_game.economy.town_layout), + townname_editbox(MAX_LENGTH_TOWN_NAME_CHARS * MAX_CHAR_LENGTH, MAX_LENGTH_TOWN_NAME_CHARS), params(_settings_game.game_creation.town_name) { this->InitNested(desc, window_number); + this->querystrings[WID_TF_TOWN_NAME_EDITBOX] = &this->townname_editbox; this->RandomTownName(); this->UpdateButtons(true); } @@ -1004,10 +1006,10 @@ public: this->townnamevalid = GenerateTownName(&this->townnameparts); if (!this->townnamevalid) { - this->text.DeleteAll(); + this->townname_editbox.text.DeleteAll(); } else { - GetTownName(this->text.buf, &this->params, this->townnameparts, &this->text.buf[this->text.max_bytes - 1]); - this->text.UpdateSize(); + GetTownName(this->townname_editbox.text.buf, &this->params, this->townnameparts, &this->townname_editbox.text.buf[this->townname_editbox.text.max_bytes - 1]); + this->townname_editbox.text.UpdateSize(); } UpdateOSKOriginalText(this, WID_TF_TOWN_NAME_EDITBOX); @@ -1041,12 +1043,12 @@ public: const char *name = NULL; if (!this->townnamevalid) { - name = this->text.buf; + name = this->townname_editbox.text.buf; } else { /* If user changed the name, send it */ char buf[MAX_LENGTH_TOWN_NAME_CHARS * MAX_CHAR_LENGTH]; GetTownName(buf, &this->params, this->townnameparts, lastof(buf)); - if (strcmp(buf, this->text.buf) != 0) name = this->text.buf; + if (strcmp(buf, this->townname_editbox.text.buf) != 0) name = this->townname_editbox.text.buf; } bool success = DoCommandP(tile, this->town_size | this->city << 2 | this->town_layout << 3 | random << 6, diff --git a/src/widget.cpp b/src/widget.cpp --- a/src/widget.cpp +++ b/src/widget.cpp @@ -2367,7 +2367,7 @@ void NWidgetLeaf::Draw(const Window *w) case WWT_EDITBOX: { DrawFrameRect(r.left, r.top, r.right, r.bottom, this->colour, FR_LOWERED | FR_DARKENED); - const QueryString *query = dynamic_cast(w); + const QueryString *query = w->GetQueryString(this->index); if (query != NULL) query->DrawEditBox(w, this->index); break; } diff --git a/src/window.cpp b/src/window.cpp --- a/src/window.cpp +++ b/src/window.cpp @@ -227,6 +227,28 @@ Scrollbar *Window::GetScrollbar(uint wid return this->GetWidget(widnum); } +/** + * Return the querystring associated to a editbox. + * @param widnum Editbox widget index + * @return QueryString or NULL. + */ +const QueryString *Window::GetQueryString(uint widnum) const +{ + const SmallMap::Pair *query = this->querystrings.Find(widnum); + return query != this->querystrings.End() ? query->second : NULL; +} + +/** + * Return the querystring associated to a editbox. + * @param widnum Editbox widget index + * @return QueryString or NULL. + */ +QueryString *Window::GetQueryString(uint widnum) +{ + SmallMap::Pair *query = this->querystrings.Find(widnum); + return query != this->querystrings.End() ? query->second : NULL; +} + /** * Set the window that has the focus @@ -450,9 +472,8 @@ static void DispatchLeftClickEvent(Windo case WWT_EDITBOX: if (!focused_widget_changed) { // Only open the OSK window if clicking on an already focused edit box /* Open the OSK window if clicked on an edit box */ - QueryStringBaseWindow *qs = dynamic_cast(w); - if (qs != NULL) { - ShowOnScreenKeyboard(qs, widget_index); + if (w->querystrings.Contains(widget_index)) { + ShowOnScreenKeyboard(w, widget_index); } } break; @@ -1622,12 +1643,8 @@ static void DecreaseWindowCounters() } /* Handle editboxes */ - for (uint i = 0; i < w->nested_array_size; i++) { - NWidgetBase *nwid = w->nested_array[i]; - if (nwid != NULL && nwid->type == WWT_EDITBOX) { - QueryString *query = dynamic_cast(w); - if (query != NULL) query->HandleEditBox(w, i); - } + for (SmallMap::Pair *it = w->querystrings.Begin(); it != w->querystrings.End(); ++it) { + it->second->HandleEditBox(w, it->first); } w->OnMouseLoop(); @@ -2245,7 +2262,7 @@ EventState Window::HandleEditBoxKey(int { EventState state = ES_NOT_HANDLED; - QueryString *query = dynamic_cast(this); + QueryString *query = this->GetQueryString(wid); if (query == NULL) return state; switch (query->HandleEditBoxKey(this, wid, key, keycode, state)) { diff --git a/src/window_gui.h b/src/window_gui.h --- a/src/window_gui.h +++ b/src/window_gui.h @@ -18,6 +18,7 @@ #include "tile_type.h" #include "widget_type.h" #include "core/smallvec_type.hpp" +#include "core/smallmap_type.hpp" /** State of handling an event. */ enum EventState { @@ -240,6 +241,8 @@ struct ViewportData : ViewPort { int32 dest_scrollpos_y; ///< Current destination y coordinate to display (virtual screen coordinate of topleft corner of the viewport). }; +struct QueryString; + /** * Data structure for an opened window */ @@ -295,6 +298,7 @@ public: ViewportData *viewport; ///< Pointer to viewport data, if present. uint32 desc_flags; ///< Window/widgets default flags setting. @see WindowDefaultFlag const NWidgetCore *nested_focus; ///< Currently focused nested widget, or \c NULL if no nested widget has focus. + SmallMap querystrings; ///< QueryString associated to WWT_EDITBOX widgets. NWidgetBase *nested_root; ///< Root of the nested tree. NWidgetBase **nested_array; ///< Array of pointers into the tree. Do not access directly, use #Window::GetWidget() instead. uint nested_array_size; ///< Size of the nested array. @@ -315,6 +319,9 @@ public: const Scrollbar *GetScrollbar(uint widnum) const; Scrollbar *GetScrollbar(uint widnum); + const QueryString *GetQueryString(uint widnum) const; + QueryString *GetQueryString(uint widnum); + void InitNested(const WindowDesc *desc, WindowNumber number = 0); void CreateNestedTree(const WindowDesc *desc, bool fill_nested = true); void FinishInitNested(const WindowDesc *desc, WindowNumber window_number = 0);