# HG changeset patch # User rubidium # Date 2009-09-26 08:30:02 # Node ID e645e6b06ab7abc39dc034073c5f5228a418ad22 # Parent f017e16bdf17cd76cb53aa432e50bd9f680b6dbe (svn r17639) -Codechange: let the difficulty settings GUI make really use the nested widget features diff --git a/src/settings_gui.cpp b/src/settings_gui.cpp --- a/src/settings_gui.cpp +++ b/src/settings_gui.cpp @@ -521,27 +521,23 @@ enum GameDifficultyWidgets { GDW_LOWER_BG, GDW_ACCEPT, GDW_CANCEL, + + GDW_OPTIONS_START, }; void SetDifficultyLevel(int mode, DifficultySettings *gm_opt); -struct GameDifficultyWindow : public Window { +class GameDifficultyWindow : public Window { private: - static const uint GAME_DIFFICULTY_NUM = 18; - bool clicked_increase; - uint8 clicked_button; - uint8 timeout; - /* Temporary holding place of values in the difficulty window until 'Save' is clicked */ GameSettings opt_mod_temp; - enum { - GAMEDIFF_WND_TOP_OFFSET = 45, - GAMEDIFF_WND_ROWSIZE = 9, - NO_SETTINGS_BUTTON = 0xFF, - }; +public: + /** The number of difficulty settings */ + static const uint GAME_DIFFICULTY_NUM = 18; + /** The number of widgets per difficulty setting */ + static const uint WIDGETS_PER_DIFFICULTY = 3; -public: GameDifficultyWindow(const WindowDesc *desc) : Window() { this->InitNested(desc); @@ -549,9 +545,6 @@ public: /* Copy current settings (ingame or in intro) to temporary holding place * change that when setting stuff, copy back on clicking 'OK' */ this->opt_mod_temp = (_game_mode == GM_MENU) ? _settings_newgame : _settings_game; - this->clicked_increase = false; - this->clicked_button = NO_SETTINGS_BUTTON; - this->timeout = 0; /* Setup disabled buttons when creating window * disable all other difficulty buttons during gameplay except for 'custom' */ this->SetWidgetsDisabledState(_game_mode == GM_NORMAL, @@ -563,87 +556,85 @@ public: this->SetWidgetDisabledState(GDW_HIGHSCORE, _game_mode == GM_EDITOR || _networking); // highscore chart in multiplayer this->SetWidgetDisabledState(GDW_ACCEPT, _networking && !_network_server); // Save-button in multiplayer (and if client) this->LowerWidget(GDW_LVL_EASY + this->opt_mod_temp.difficulty.diff_level); + this->OnInvalidateData(); + } + + virtual void SetStringParameters(int widget) const + { + widget -= GDW_OPTIONS_START; + if (widget < 0 || (widget % 3) != 2) return; + + widget /= 3; + + uint i; + const SettingDesc *sd = GetSettingFromName("difficulty.max_no_competitors", &i) + widget; + int32 value = (int32)ReadValue(GetVariableAddress(&this->opt_mod_temp, &sd->save), sd->save.conv); + SetDParam(0, sd->desc.str + value); + } + + virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *resize) + { + /* Only for the 'descriptions' */ + int index = widget - GDW_OPTIONS_START; + if (index < 0 || (index % 3) != 2) return; + + index /= 3; + + uint i; + const SettingDesc *sd = GetSettingFromName("difficulty.max_no_competitors", &i) + index; + const SettingDescBase *sdb = &sd->desc; + + /* Get the string and try all strings from the smallest to the highest value */ + StringID str = this->GetWidget(widget)->widget_data; + for (int32 value = sdb->min; (uint32)value <= sdb->max; value += sdb->interval) { + SetDParam(0, sdb->str + value); + *size = maxdim(*size, GetStringBoundingBox(str)); + } } virtual void OnPaint() { this->DrawWidgets(); - - uint i; - const SettingDesc *sd = GetSettingFromName("difficulty.max_no_competitors", &i); - int y = GAMEDIFF_WND_TOP_OFFSET; - StringID str = STR_DIFFICULTY_LEVEL_SETTING_MAXIMUM_NO_COMPETITORS; - for (i = 0; i < GAME_DIFFICULTY_NUM; i++, sd++) { - const SettingDescBase *sdb = &sd->desc; - /* skip deprecated difficulty options */ - if (!SlIsObjectCurrentlyValid(sd->save.version_from, sd->save.version_to)) continue; - int32 value = (int32)ReadValue(GetVariableAddress(&this->opt_mod_temp, &sd->save), sd->save.conv); - bool editable = (_game_mode == GM_MENU || (sdb->flags & SGF_NEWGAME_ONLY) == 0); - - DrawArrowButtons(5, y, COLOUR_YELLOW, - (this->clicked_button == i) ? 1 + !!this->clicked_increase : 0, - editable && sdb->min != value, - editable && sdb->max != (uint32)value); - - value += sdb->str; - SetDParam(0, value); - DrawString(30, this->width, y, str); - - y += GAMEDIFF_WND_ROWSIZE + 2; // space items apart a bit - str++; - } } virtual void OnClick(Point pt, int widget) { - switch (widget) { - case GDW_SETTING_BG: { // Difficulty settings widget, decode click - /* Don't allow clients to make any changes */ - if (_networking && !_network_server) return; + if (widget >= GDW_OPTIONS_START) { + widget -= GDW_OPTIONS_START; + if ((widget % 3) == 2) return; - const int x = pt.x - 5; - if (!IsInsideMM(x, 0, 21)) return; // Button area + /* Don't allow clients to make any changes */ + if (_networking && !_network_server) return; - const int y = pt.y - GAMEDIFF_WND_TOP_OFFSET; - if (y < 0) return; + uint i; + const SettingDesc *sd = GetSettingFromName("difficulty.max_no_competitors", &i) + (widget / 3); + const SettingDescBase *sdb = &sd->desc; - /* Get button from Y coord. */ - uint8 btn = y / (GAMEDIFF_WND_ROWSIZE + 2); - if (btn >= 1) btn++; // Skip the deprecated option "competitor start time" - if (btn >= 8) btn++; // Skip the deprecated option "competitor intelligence" - if (btn >= GAME_DIFFICULTY_NUM || y % (GAMEDIFF_WND_ROWSIZE + 2) >= 9) return; - - uint i; - const SettingDesc *sd = GetSettingFromName("difficulty.max_no_competitors", &i) + btn; - const SettingDescBase *sdb = &sd->desc; + /* Clicked disabled button? */ + bool editable = (_game_mode == GM_MENU || (sdb->flags & SGF_NEWGAME_ONLY) == 0); + if (!editable) return; - /* Clicked disabled button? */ - bool editable = (_game_mode == GM_MENU || (sdb->flags & SGF_NEWGAME_ONLY) == 0); - if (!editable) return; - - this->timeout = 5; - int32 val = (int32)ReadValue(GetVariableAddress(&this->opt_mod_temp, &sd->save), sd->save.conv); + int32 val = (int32)ReadValue(GetVariableAddress(&this->opt_mod_temp, &sd->save), sd->save.conv); + if (widget % 3 == 1) { + /* Increase button clicked */ + val = min(val + sdb->interval, (int32)sdb->max); + } else { + /* Decrease button clicked */ + val -= sdb->interval; + val = max(val, sdb->min); + } - if (x >= 10) { - /* Increase button clicked */ - val = min(val + sdb->interval, (int32)sdb->max); - this->clicked_increase = true; - } else { - /* Decrease button clicked */ - val -= sdb->interval; - val = max(val, sdb->min); - this->clicked_increase = false; - } - this->clicked_button = btn; + /* save value in temporary variable */ + WriteValue(GetVariableAddress(&this->opt_mod_temp, &sd->save), sd->save.conv, val); + this->RaiseWidget(GDW_LVL_EASY + this->opt_mod_temp.difficulty.diff_level); + SetDifficultyLevel(3, &this->opt_mod_temp.difficulty); // set difficulty level to custom + this->LowerWidget(GDW_LVL_CUSTOM); + this->OnInvalidateData(); + this->SetDirty(); + return; + } - /* save value in temporary variable */ - WriteValue(GetVariableAddress(&this->opt_mod_temp, &sd->save), sd->save.conv, val); - this->RaiseWidget(GDW_LVL_EASY + this->opt_mod_temp.difficulty.diff_level); - SetDifficultyLevel(3, &this->opt_mod_temp.difficulty); // set difficulty level to custom - this->LowerWidget(GDW_LVL_CUSTOM); - this->SetDirty(); - } break; - + switch (widget) { case GDW_LVL_EASY: case GDW_LVL_MEDIUM: case GDW_LVL_HARD: @@ -652,6 +643,7 @@ public: this->RaiseWidget(GDW_LVL_EASY + this->opt_mod_temp.difficulty.diff_level); SetDifficultyLevel(widget - GDW_LVL_EASY, &this->opt_mod_temp.difficulty); this->LowerWidget(GDW_LVL_EASY + this->opt_mod_temp.difficulty.diff_level); + this->OnInvalidateData(); this->SetDirty(); break; @@ -689,47 +681,94 @@ public: } } - virtual void OnTick() + virtual void OnInvalidateData(int data = 0) { - if (this->timeout != 0) { - this->timeout--; - if (this->timeout == 0) this->clicked_button = NO_SETTINGS_BUTTON; - this->SetDirty(); + uint i; + const SettingDesc *sd = GetSettingFromName("difficulty.max_no_competitors", &i); + for (i = 0; i < GAME_DIFFICULTY_NUM; i++, sd++) { + const SettingDescBase *sdb = &sd->desc; + /* skip deprecated difficulty options */ + if (!SlIsObjectCurrentlyValid(sd->save.version_from, sd->save.version_to)) continue; + int32 value = (int32)ReadValue(GetVariableAddress(&this->opt_mod_temp, &sd->save), sd->save.conv); + bool editable = (_game_mode == GM_MENU || (sdb->flags & SGF_NEWGAME_ONLY) == 0); + + this->SetWidgetDisabledState(GDW_OPTIONS_START + i * 3 + 0, !editable || sdb->min == value); + this->SetWidgetDisabledState(GDW_OPTIONS_START + i * 3 + 1, !editable || sdb->max == (uint32)value); } } }; +static NWidgetBase *MakeDifficultyOptionsWidgets(int *biggest_index) +{ + NWidgetVertical *vert_desc = new NWidgetVertical; + + int widnum = GDW_OPTIONS_START; + uint i, j; + const SettingDesc *sd = GetSettingFromName("difficulty.max_no_competitors", &i); + + for (i = 0, j = 0; i < GameDifficultyWindow::GAME_DIFFICULTY_NUM; i++, sd++, widnum += GameDifficultyWindow::WIDGETS_PER_DIFFICULTY) { + if (!SlIsObjectCurrentlyValid(sd->save.version_from, sd->save.version_to)) continue; + + NWidgetHorizontal *hor = new NWidgetHorizontal; + + /* [<] button. */ + NWidgetLeaf *leaf = new NWidgetLeaf(WWT_PUSHTXTBTN, COLOUR_YELLOW, widnum, STR_BLACK_SMALL_ARROW_LEFT, STR_TOOLTIP_HSCROLL_BAR_SCROLLS_LIST); + hor->Add(leaf); + + /* [>] button. */ + leaf = new NWidgetLeaf(WWT_PUSHTXTBTN, COLOUR_YELLOW, widnum + 1, STR_BLACK_SMALL_ARROW_RIGHT, STR_TOOLTIP_HSCROLL_BAR_SCROLLS_LIST); + hor->Add(leaf); + + /* Some spacing between the text and the description */ + NWidgetSpacer *spacer = new NWidgetSpacer(5, 0); + hor->Add(spacer); + + /* Descriptive text. */ + leaf = new NWidgetLeaf(WWT_TEXT, COLOUR_YELLOW, widnum + 2, STR_DIFFICULTY_LEVEL_SETTING_MAXIMUM_NO_COMPETITORS + (j++), STR_NULL); + leaf->SetFill(true, false); + hor->Add(leaf); + vert_desc->Add(hor); + + /* Space vertically */ + vert_desc->Add(new NWidgetSpacer(0, 2)); + } + *biggest_index = widnum - 1; + return vert_desc; +} + + /** Widget definition for the game difficulty settings window */ static const NWidgetPart _nested_game_difficulty_widgets[] = { - NWidget(WWT_CAPTION, COLOUR_MAUVE, GDW_CAPTION), SetMinimalSize(370, 14), SetDataTip(STR_DIFFICULTY_LEVEL_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), + NWidget(WWT_CAPTION, COLOUR_MAUVE, GDW_CAPTION), SetDataTip(STR_DIFFICULTY_LEVEL_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS), NWidget(WWT_PANEL, COLOUR_MAUVE, GDW_UPPER_BG), - NWidget(NWID_SPACER), SetMinimalSize(0, 2), - NWidget(NWID_HORIZONTAL), - NWidget(NWID_SPACER), SetMinimalSize(10, 0), - NWidget(WWT_PUSHTXTBTN, COLOUR_YELLOW, GDW_LVL_EASY), SetMinimalSize(87, 12), SetDataTip(STR_DIFFICULTY_LEVEL_EASY, STR_NULL), - NWidget(WWT_PUSHTXTBTN, COLOUR_YELLOW, GDW_LVL_MEDIUM), SetMinimalSize(87, 12), SetDataTip(STR_DIFFICULTY_LEVEL_MEDIUM, STR_NULL), - NWidget(WWT_PUSHTXTBTN, COLOUR_YELLOW, GDW_LVL_HARD), SetMinimalSize(87, 12), SetDataTip(STR_DIFFICULTY_LEVEL_HARD, STR_NULL), - NWidget(WWT_PUSHTXTBTN, COLOUR_YELLOW, GDW_LVL_CUSTOM), SetMinimalSize(87, 12), SetDataTip(STR_DIFFICULTY_LEVEL_CUSTOM, STR_NULL), - NWidget(NWID_SPACER), SetMinimalSize(12, 0), + NWidget(NWID_VERTICAL), SetPIP(2, 0, 2), + NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(10, 0, 10), + NWidget(WWT_TEXTBTN, COLOUR_YELLOW, GDW_LVL_EASY), SetDataTip(STR_DIFFICULTY_LEVEL_EASY, STR_NULL), SetFill(true, false), + NWidget(WWT_TEXTBTN, COLOUR_YELLOW, GDW_LVL_MEDIUM), SetDataTip(STR_DIFFICULTY_LEVEL_MEDIUM, STR_NULL), SetFill(true, false), + NWidget(WWT_TEXTBTN, COLOUR_YELLOW, GDW_LVL_HARD), SetDataTip(STR_DIFFICULTY_LEVEL_HARD, STR_NULL), SetFill(true, false), + NWidget(WWT_TEXTBTN, COLOUR_YELLOW, GDW_LVL_CUSTOM), SetDataTip(STR_DIFFICULTY_LEVEL_CUSTOM, STR_NULL), SetFill(true, false), + EndContainer(), + NWidget(NWID_HORIZONTAL), SetPIP(10, 0, 10), + NWidget(WWT_PUSHTXTBTN, COLOUR_GREEN, GDW_HIGHSCORE), SetDataTip(STR_DIFFICULTY_LEVEL_HIGH_SCORE_BUTTON, STR_NULL), SetFill(true, false), + EndContainer(), EndContainer(), - NWidget(NWID_HORIZONTAL), - NWidget(NWID_SPACER), SetMinimalSize(10, 0), - NWidget(WWT_TEXTBTN, COLOUR_GREEN, GDW_HIGHSCORE), SetMinimalSize(348, 12), SetDataTip(STR_DIFFICULTY_LEVEL_HIGH_SCORE_BUTTON, STR_NULL), - NWidget(NWID_SPACER), SetMinimalSize(12, 0), + EndContainer(), + NWidget(WWT_PANEL, COLOUR_MAUVE, GDW_SETTING_BG), + NWidget(NWID_VERTICAL), SetPIP(3, 0, 1), + NWidget(NWID_HORIZONTAL), SetPIP(5, 0, 5), + NWidgetFunction(MakeDifficultyOptionsWidgets), + EndContainer(), EndContainer(), - NWidget(NWID_SPACER), SetMinimalSize(0, 2), - EndContainer(), - NWidget(WWT_PANEL, COLOUR_MAUVE, GDW_SETTING_BG), SetMinimalSize(370, 221), EndContainer(), NWidget(WWT_PANEL, COLOUR_MAUVE, GDW_LOWER_BG), - NWidget(NWID_SPACER), SetMinimalSize(0, 2), - NWidget(NWID_HORIZONTAL), - NWidget(NWID_SPACER), SetMinimalSize(105, 0), - NWidget(WWT_PUSHTXTBTN, COLOUR_YELLOW, GDW_ACCEPT), SetMinimalSize(81, 12), SetDataTip(STR_DIFFICULTY_LEVEL_SAVE, STR_NULL), - NWidget(WWT_PUSHTXTBTN, COLOUR_YELLOW, GDW_CANCEL), SetMinimalSize(81, 12), SetDataTip(STR_BUTTON_CANCEL, STR_NULL), - NWidget(NWID_SPACER), SetMinimalSize(103, 0), + NWidget(NWID_VERTICAL), SetPIP(2, 0, 2), + NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(10, 0, 10), + NWidget(NWID_SPACER), SetFill(true, false), + NWidget(WWT_PUSHTXTBTN, COLOUR_YELLOW, GDW_ACCEPT), SetDataTip(STR_DIFFICULTY_LEVEL_SAVE, STR_NULL), SetFill(true, false), + NWidget(WWT_PUSHTXTBTN, COLOUR_YELLOW, GDW_CANCEL), SetDataTip(STR_BUTTON_CANCEL, STR_NULL), SetFill(true, false), + NWidget(NWID_SPACER), SetFill(true, false), + EndContainer(), EndContainer(), - NWidget(NWID_SPACER), SetMinimalSize(0, 2), EndContainer(), }; @@ -737,7 +776,7 @@ static const NWidgetPart _nested_game_di static const WindowDesc _game_difficulty_desc( WDP_CENTER, WDP_CENTER, 370, 279, 370, 279, WC_GAME_OPTIONS, WC_NONE, - WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET, + WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS, NULL, _nested_game_difficulty_widgets, lengthof(_nested_game_difficulty_widgets) );