From e0c7c872e2f7c67b4a7c642e85c70aaff975b06f Mon Sep 17 00:00:00 2001 From: frosch Date: Sun, 10 Apr 2011 15:30:08 +0000 Subject: [PATCH] (svn r22312) -Codechange: Add GameOptionsWindow::BuildDropDownList() for construction of all dropdown lists in the GameOptionsWindow. -Change: Sort the items in the currency dropdown; separate the "Custom" item with a horizontal line from the rest. -Change: Separate default and NewGRF-supplied townnames with a horizontal line and only sort them within these groups. -Fix: Resize all dropdown lists in the GameOptionsWindow, so no text is truncated. --- src/settings_gui.cpp | 287 ++++++++++++++++++++++++++----------------- 1 file changed, 176 insertions(+), 111 deletions(-) diff --git a/src/settings_gui.cpp b/src/settings_gui.cpp index 0203b75746..bf2d872601 100644 --- a/src/settings_gui.cpp +++ b/src/settings_gui.cpp @@ -59,21 +59,6 @@ static const StringID _autosave_dropdown[] = { INVALID_STRING_ID, }; -/** - * Fill a static array with consecutive stringIDs for use with a drop down. - * @param base First stringID. - * @param num Number of stringIDs (must be at most 32). - * *return Pointer to the static buffer with stringIDs. - */ -static StringID *BuildDynamicDropdown(StringID base, int num) -{ - static StringID buf[32 + 1]; - StringID *p = buf; - while (--num >= 0) *p++ = base++; - *p = INVALID_STRING_ID; - return buf; -} - int _nb_orig_names = SPECSTR_TOWNNAME_LAST - SPECSTR_TOWNNAME_START + 1; ///< Number of original town names. static StringID *_grf_names = NULL; ///< Pointer to town names defined by NewGRFs. static int _nb_grf_names = 0; ///< Number of town names defined by NewGRFs. @@ -139,44 +124,20 @@ enum GameOptionsWidgets { GOW_BASE_MUSIC_DESCRIPTION, ///< Description of selected base music set }; -/** - * Update/redraw the townnames dropdown - * @param w the window the dropdown belongs to - * @param sel the currently selected townname generator - */ -static void ShowTownnameDropdown(Window *w, int sel) -{ - typedef std::map TownList; - TownList townnames; - - /* Add and sort original townnames generators */ - for (int i = 0; i < _nb_orig_names; i++) townnames[STR_GAME_OPTIONS_TOWN_NAME_ORIGINAL_ENGLISH + i] = i; - - /* Add and sort newgrf townnames generators */ - for (int i = 0; i < _nb_grf_names; i++) townnames[_grf_names[i]] = _nb_orig_names + i; - - DropDownList *list = new DropDownList(); - for (TownList::iterator it = townnames.begin(); it != townnames.end(); it++) { - list->push_back(new DropDownListStringItem((*it).first, (*it).second, !(_game_mode == GM_MENU || Town::GetNumItems() == 0 || (*it).second == sel))); - } - - ShowDropDownList(w, list, sel, GOW_TOWNNAME_DROPDOWN); -} - static void ShowCustCurrency(); template -static void ShowSetMenu(Window *w, int widget) +static DropDownList *BuiltSetDropDownList(int *selected_index) { int n = T::GetNumSets(); - int current = T::GetIndexOfUsedSet(); + *selected_index = T::GetIndexOfUsedSet(); DropDownList *list = new DropDownList(); for (int i = 0; i < n; i++) { - list->push_back(new DropDownListCharStringItem(T::GetSet(i)->name, i, (_game_mode == GM_MENU) ? false : (current != i))); + list->push_back(new DropDownListCharStringItem(T::GetSet(i)->name, i, (_game_mode == GM_MENU) ? false : (*selected_index != i))); } - ShowDropDownList(w, list, current, widget); + return list; } struct GameOptionsWindow : Window { @@ -198,6 +159,153 @@ struct GameOptionsWindow : Window { if (this->reload) _switch_mode = SM_MENU; } + /** + * Build the dropdown list for a specific widget. + * @param widget Widget to build list for + * @param selected_index Currently selected item + * @return the built dropdown list, or NULL if the widget has no dropdown menu. + */ + DropDownList *BuildDropDownList(int widget, int *selected_index) const + { + DropDownList *list = NULL; + switch (widget) { + case GOW_CURRENCY_DROPDOWN: { // Setup currencies dropdown + list = new DropDownList(); + *selected_index = this->opt->locale.currency; + StringID *items = BuildCurrencyDropdown(); + uint disabled = _game_mode == GM_MENU ? 0 : ~GetMaskOfAllowedCurrencies(); + int custom_index = -1; + + /* Add non-custom currencies; sorted naturally */ + for (uint i = 0; *items != INVALID_STRING_ID; items++, i++) { + if (*items == STR_GAME_OPTIONS_CURRENCY_CUSTOM) { + custom_index = i; + } else { + list->push_back(new DropDownListStringItem(*items, i, HasBit(disabled, i))); + } + } + list->sort(DropDownListStringItem::NatSortFunc); + + /* Append custom currency at the end */ + if (custom_index >= 0) { + list->push_back(new DropDownListItem(-1, false)); // separator line + list->push_back(new DropDownListStringItem(STR_GAME_OPTIONS_CURRENCY_CUSTOM, custom_index, HasBit(disabled, custom_index))); + } + break; + } + + case GOW_DISTANCE_DROPDOWN: { // Setup distance unit dropdown + list = new DropDownList(); + *selected_index = this->opt->locale.units; + const StringID *items = _units_dropdown; + for (uint i = 0; *items != INVALID_STRING_ID; items++, i++) { + list->push_back(new DropDownListStringItem(*items, i, false)); + } + break; + } + + case GOW_ROADSIDE_DROPDOWN: { // Setup road-side dropdown + list = new DropDownList(); + *selected_index = this->opt->vehicle.road_side; + const StringID *items = _driveside_dropdown; + uint disabled = 0; + + /* You can only change the drive side if you are in the menu or ingame with + * no vehicles present. In a networking game only the server can change it */ + extern bool RoadVehiclesAreBuilt(); + if ((_game_mode != GM_MENU && RoadVehiclesAreBuilt()) || (_networking && !_network_server)) { + disabled = ~(1 << this->opt->vehicle.road_side); // disable the other value + } + + for (uint i = 0; *items != INVALID_STRING_ID; items++, i++) { + list->push_back(new DropDownListStringItem(*items, i, HasBit(disabled, i))); + } + break; + } + + case GOW_TOWNNAME_DROPDOWN: { // Setup townname dropdown + list = new DropDownList(); + *selected_index = this->opt->game_creation.town_name; + + int enabled_item = (_game_mode == GM_MENU || Town::GetNumItems() == 0) ? -1 : *selected_index; + + /* Add and sort original townnames generators */ + for (int i = 0; i < _nb_orig_names; i++) { + list->push_back(new DropDownListStringItem(STR_GAME_OPTIONS_TOWN_NAME_ORIGINAL_ENGLISH + i, i, enabled_item != i && enabled_item >= 0)); + } + list->sort(DropDownListStringItem::NatSortFunc); + + /* Add and sort newgrf townnames generators */ + DropDownList newgrf_names; + for (int i = 0; i < _nb_grf_names; i++) { + int result = _nb_orig_names + i; + newgrf_names.push_back(new DropDownListStringItem(_grf_names[i], result, enabled_item != result && enabled_item >= 0)); + } + newgrf_names.sort(DropDownListStringItem::NatSortFunc); + + /* Append newgrf_names at the end of list */ + if (newgrf_names.size() > 0) { + list->push_back(new DropDownListItem(-1, false)); // separator line + list->splice(list->end(), newgrf_names); + } + break; + } + + case GOW_AUTOSAVE_DROPDOWN: { // Setup autosave dropdown + list = new DropDownList(); + *selected_index = _settings_client.gui.autosave; + const StringID *items = _autosave_dropdown; + for (uint i = 0; *items != INVALID_STRING_ID; items++, i++) { + list->push_back(new DropDownListStringItem(*items, i, false)); + } + break; + } + + case GOW_LANG_DROPDOWN: { // Setup interface language dropdown + list = new DropDownList(); + for (uint i = 0; i < _languages.Length(); i++) { + if (&_languages[i] == _current_language) *selected_index = i; + list->push_back(new DropDownListStringItem(SPECSTR_LANGUAGE_START + i, i, false)); + } + list->sort(DropDownListStringItem::NatSortFunc); + break; + } + + case GOW_RESOLUTION_DROPDOWN: // Setup resolution dropdown + list = new DropDownList(); + *selected_index = GetCurRes(); + for (int i = 0; i < _num_resolutions; i++) { + list->push_back(new DropDownListStringItem(SPECSTR_RESOLUTION_START + i, i, false)); + } + break; + + case GOW_SCREENSHOT_DROPDOWN: // Setup screenshot format dropdown + list = new DropDownList(); + *selected_index = _cur_screenshot_format; + for (uint i = 0; i < _num_screenshot_formats; i++) { + list->push_back(new DropDownListStringItem(SPECSTR_SCREENSHOT_START + i, i, false)); + } + break; + + case GOW_BASE_GRF_DROPDOWN: + list = BuiltSetDropDownList(selected_index); + break; + + case GOW_BASE_SFX_DROPDOWN: + list = BuiltSetDropDownList(selected_index); + break; + + case GOW_BASE_MUSIC_DROPDOWN: + list = BuiltSetDropDownList(selected_index); + break; + + default: + return NULL; + } + + return list; + } + virtual void SetStringParameters(int widget) const { switch (widget) { @@ -285,66 +393,30 @@ struct GameOptionsWindow : Window { *size = maxdim(*size, GetStringBoundingBox(STR_GAME_OPTIONS_BASE_MUSIC_STATUS)); } break; + + default: { + int selected; + DropDownList *list = this->BuildDropDownList(widget, &selected); + if (list != NULL) { + /* Find the biggest item for the default size. */ + for (DropDownList::iterator it = list->begin(); it != list->end(); it++) { + static const Dimension extra = {WD_DROPDOWNTEXT_LEFT + WD_DROPDOWNTEXT_RIGHT, WD_DROPDOWNTEXT_TOP + WD_DROPDOWNTEXT_BOTTOM}; + Dimension string_dim; + int width = (*it)->Width(); + string_dim.width = width + extra.width; + string_dim.height = (*it)->Height(width) + extra.height; + *size = maxdim(*size, string_dim); + delete *it; + } + delete list; + } + } } } virtual void OnClick(Point pt, int widget, int click_count) { switch (widget) { - case GOW_CURRENCY_DROPDOWN: // Setup currencies dropdown - ShowDropDownMenu(this, BuildCurrencyDropdown(), this->opt->locale.currency, GOW_CURRENCY_DROPDOWN, _game_mode == GM_MENU ? 0 : ~GetMaskOfAllowedCurrencies(), 0); - break; - - case GOW_DISTANCE_DROPDOWN: // Setup distance unit dropdown - ShowDropDownMenu(this, _units_dropdown, this->opt->locale.units, GOW_DISTANCE_DROPDOWN, 0, 0); - break; - - case GOW_ROADSIDE_DROPDOWN: { // Setup road-side dropdown - int i = 0; - extern bool RoadVehiclesAreBuilt(); - - /* You can only change the drive side if you are in the menu or ingame with - * no vehicles present. In a networking game only the server can change it */ - if ((_game_mode != GM_MENU && RoadVehiclesAreBuilt()) || (_networking && !_network_server)) { - i = (-1) ^ (1 << this->opt->vehicle.road_side); // disable the other value - } - - ShowDropDownMenu(this, _driveside_dropdown, this->opt->vehicle.road_side, GOW_ROADSIDE_DROPDOWN, i, 0); - break; - } - - case GOW_TOWNNAME_DROPDOWN: // Setup townname dropdown - ShowTownnameDropdown(this, this->opt->game_creation.town_name); - break; - - case GOW_AUTOSAVE_DROPDOWN: // Setup autosave dropdown - ShowDropDownMenu(this, _autosave_dropdown, _settings_client.gui.autosave, GOW_AUTOSAVE_DROPDOWN, 0, 0); - break; - - case GOW_LANG_DROPDOWN: { // Setup interface language dropdown - typedef std::map LangList; - - /* Sort language names */ - LangList langs; - int current_lang = 0; - for (int i = 0; i < (int)_languages.Length(); i++) { - if (&_languages[i] == _current_language) current_lang = i; - langs[SPECSTR_LANGUAGE_START + i] = i; - } - - DropDownList *list = new DropDownList(); - for (LangList::iterator it = langs.begin(); it != langs.end(); it++) { - list->push_back(new DropDownListStringItem((*it).first, (*it).second, false)); - } - - ShowDropDownList(this, list, current_lang, GOW_LANG_DROPDOWN); - break; - } - - case GOW_RESOLUTION_DROPDOWN: // Setup resolution dropdown - ShowDropDownMenu(this, BuildDynamicDropdown(SPECSTR_RESOLUTION_START, _num_resolutions), GetCurRes(), GOW_RESOLUTION_DROPDOWN, 0, 0); - break; - case GOW_FULLSCREEN_BUTTON: // Click fullscreen on/off /* try to toggle full-screen on/off */ if (!ToggleFullScreen(!_fullscreen)) { @@ -354,21 +426,14 @@ struct GameOptionsWindow : Window { this->SetDirty(); break; - case GOW_SCREENSHOT_DROPDOWN: // Setup screenshot format dropdown - ShowDropDownMenu(this, BuildDynamicDropdown(SPECSTR_SCREENSHOT_START, _num_screenshot_formats), _cur_screenshot_format, GOW_SCREENSHOT_DROPDOWN, 0, 0); - break; - - case GOW_BASE_GRF_DROPDOWN: - ShowSetMenu(this, GOW_BASE_GRF_DROPDOWN); - break; - - case GOW_BASE_SFX_DROPDOWN: - ShowSetMenu(this, GOW_BASE_SFX_DROPDOWN); - break; - - case GOW_BASE_MUSIC_DROPDOWN: - ShowSetMenu(this, GOW_BASE_MUSIC_DROPDOWN); + default: { + int selected; + DropDownList *list = this->BuildDropDownList(widget, &selected); + if (list != NULL) { + ShowDropDownList(this, list, selected, widget); + } break; + } } }