OpenTTD Source  1.10.0-RC1
settings_gui.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of OpenTTD.
3  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
6  */
7 
10 #include "stdafx.h"
11 #include "currency.h"
12 #include "error.h"
13 #include "settings_gui.h"
14 #include "textbuf_gui.h"
15 #include "command_func.h"
16 #include "network/network.h"
17 #include "town.h"
18 #include "settings_internal.h"
19 #include "newgrf_townname.h"
20 #include "strings_func.h"
21 #include "window_func.h"
22 #include "string_func.h"
23 #include "widgets/dropdown_type.h"
24 #include "widgets/dropdown_func.h"
25 #include "highscore.h"
26 #include "base_media_base.h"
27 #include "company_base.h"
28 #include "company_func.h"
29 #include "viewport_func.h"
30 #include "core/geometry_func.hpp"
31 #include "ai/ai.hpp"
32 #include "blitter/factory.hpp"
33 #include "language.h"
34 #include "textfile_gui.h"
35 #include "stringfilter_type.h"
36 #include "querystring_gui.h"
37 #include "fontcache.h"
38 #include "zoom_func.h"
39 
40 #include <vector>
41 
42 #include "safeguards.h"
43 
44 
45 static const StringID _driveside_dropdown[] = {
46  STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_LEFT,
47  STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_RIGHT,
49 };
50 
51 static const StringID _autosave_dropdown[] = {
52  STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_OFF,
53  STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_1_MONTH,
54  STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_3_MONTHS,
55  STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_6_MONTHS,
56  STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_12_MONTHS,
58 };
59 
60 static const StringID _gui_zoom_dropdown[] = {
61  STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_NORMAL,
62  STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_2X_ZOOM,
63  STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_4X_ZOOM,
65 };
66 
67 static const StringID _font_zoom_dropdown[] = {
68  STR_GAME_OPTIONS_FONT_ZOOM_DROPDOWN_NORMAL,
69  STR_GAME_OPTIONS_FONT_ZOOM_DROPDOWN_2X_ZOOM,
70  STR_GAME_OPTIONS_FONT_ZOOM_DROPDOWN_4X_ZOOM,
72 };
73 
74 int _nb_orig_names = SPECSTR_TOWNNAME_LAST - SPECSTR_TOWNNAME_START + 1;
75 static StringID *_grf_names = nullptr;
76 static int _nb_grf_names = 0;
77 
79 
80 static const void *ResolveVariableAddress(const GameSettings *settings_ptr, const SettingDesc *sd);
81 
84 {
86  _grf_names = GetGRFTownNameList();
87  _nb_grf_names = 0;
88  for (StringID *s = _grf_names; *s != INVALID_STRING_ID; s++) _nb_grf_names++;
89 }
90 
96 static inline StringID TownName(int town_name)
97 {
98  if (town_name < _nb_orig_names) return STR_GAME_OPTIONS_TOWN_NAME_ORIGINAL_ENGLISH + town_name;
99  town_name -= _nb_orig_names;
100  if (town_name < _nb_grf_names) return _grf_names[town_name];
101  return STR_UNDEFINED;
102 }
103 
108 static uint GetCurRes()
109 {
110  uint i;
111 
112  for (i = 0; i != _resolutions.size(); i++) {
113  if (_resolutions[i] == Dimension(_screen.width, _screen.height)) break;
114  }
115  return i;
116 }
117 
118 static void ShowCustCurrency();
119 
120 template <class T>
121 static DropDownList BuildSetDropDownList(int *selected_index, bool allow_selection)
122 {
123  int n = T::GetNumSets();
124  *selected_index = T::GetIndexOfUsedSet();
125 
126  DropDownList list;
127  for (int i = 0; i < n; i++) {
128  list.emplace_back(new DropDownListCharStringItem(T::GetSet(i)->name, i, !allow_selection && (*selected_index != i)));
129  }
130 
131  return list;
132 }
133 
134 DropDownList BuildMusicSetDropDownList(int *selected_index)
135 {
136  return BuildSetDropDownList<BaseMusic>(selected_index, true);
137 }
138 
140 template <class TBaseSet>
142  const TBaseSet* baseset;
144 
145  BaseSetTextfileWindow(TextfileType file_type, const TBaseSet* baseset, StringID content_type) : TextfileWindow(file_type), baseset(baseset), content_type(content_type)
146  {
147  const char *textfile = this->baseset->GetTextfile(file_type);
148  this->LoadTextfile(textfile, BASESET_DIR);
149  }
150 
151  void SetStringParameters(int widget) const override
152  {
153  if (widget == WID_TF_CAPTION) {
154  SetDParam(0, content_type);
155  SetDParamStr(1, this->baseset->name);
156  }
157  }
158 };
159 
166 template <class TBaseSet>
168 {
169  DeleteWindowById(WC_TEXTFILE, file_type);
171 }
172 
174  GameSettings *opt;
175  bool reload;
176 
177  GameOptionsWindow(WindowDesc *desc) : Window(desc)
178  {
179  this->opt = &GetGameSettings();
180  this->reload = false;
181 
183  this->OnInvalidateData(0);
184  }
185 
187  {
190  if (this->reload) _switch_mode = SM_MENU;
191  }
192 
199  DropDownList BuildDropDownList(int widget, int *selected_index) const
200  {
201  DropDownList list;
202  switch (widget) {
203  case WID_GO_CURRENCY_DROPDOWN: { // Setup currencies dropdown
204  *selected_index = this->opt->locale.currency;
205  StringID *items = BuildCurrencyDropdown();
206  uint64 disabled = _game_mode == GM_MENU ? 0LL : ~GetMaskOfAllowedCurrencies();
207 
208  /* Add non-custom currencies; sorted naturally */
209  for (uint i = 0; i < CURRENCY_END; items++, i++) {
210  if (i == CURRENCY_CUSTOM) continue;
211  list.emplace_back(new DropDownListStringItem(*items, i, HasBit(disabled, i)));
212  }
213  std::sort(list.begin(), list.end(), DropDownListStringItem::NatSortFunc);
214 
215  /* Append custom currency at the end */
216  list.emplace_back(new DropDownListItem(-1, false)); // separator line
217  list.emplace_back(new DropDownListStringItem(STR_GAME_OPTIONS_CURRENCY_CUSTOM, CURRENCY_CUSTOM, HasBit(disabled, CURRENCY_CUSTOM)));
218  break;
219  }
220 
221  case WID_GO_ROADSIDE_DROPDOWN: { // Setup road-side dropdown
222  *selected_index = this->opt->vehicle.road_side;
223  const StringID *items = _driveside_dropdown;
224  uint disabled = 0;
225 
226  /* You can only change the drive side if you are in the menu or ingame with
227  * no vehicles present. In a networking game only the server can change it */
228  extern bool RoadVehiclesAreBuilt();
229  if ((_game_mode != GM_MENU && RoadVehiclesAreBuilt()) || (_networking && !_network_server)) {
230  disabled = ~(1 << this->opt->vehicle.road_side); // disable the other value
231  }
232 
233  for (uint i = 0; *items != INVALID_STRING_ID; items++, i++) {
234  list.emplace_back(new DropDownListStringItem(*items, i, HasBit(disabled, i)));
235  }
236  break;
237  }
238 
239  case WID_GO_TOWNNAME_DROPDOWN: { // Setup townname dropdown
240  *selected_index = this->opt->game_creation.town_name;
241 
242  int enabled_item = (_game_mode == GM_MENU || Town::GetNumItems() == 0) ? -1 : *selected_index;
243 
244  /* Add and sort newgrf townnames generators */
245  for (int i = 0; i < _nb_grf_names; i++) {
246  int result = _nb_orig_names + i;
247  list.emplace_back(new DropDownListStringItem(_grf_names[i], result, enabled_item != result && enabled_item >= 0));
248  }
249  std::sort(list.begin(), list.end(), DropDownListStringItem::NatSortFunc);
250 
251  size_t newgrf_size = list.size();
252  /* Insert newgrf_names at the top of the list */
253  if (newgrf_size > 0) {
254  list.emplace_back(new DropDownListItem(-1, false)); // separator line
255  newgrf_size++;
256  }
257 
258  /* Add and sort original townnames generators */
259  for (int i = 0; i < _nb_orig_names; i++) {
260  list.emplace_back(new DropDownListStringItem(STR_GAME_OPTIONS_TOWN_NAME_ORIGINAL_ENGLISH + i, i, enabled_item != i && enabled_item >= 0));
261  }
262  std::sort(list.begin() + newgrf_size, list.end(), DropDownListStringItem::NatSortFunc);
263  break;
264  }
265 
266  case WID_GO_AUTOSAVE_DROPDOWN: { // Setup autosave dropdown
267  *selected_index = _settings_client.gui.autosave;
268  const StringID *items = _autosave_dropdown;
269  for (uint i = 0; *items != INVALID_STRING_ID; items++, i++) {
270  list.emplace_back(new DropDownListStringItem(*items, i, false));
271  }
272  break;
273  }
274 
275  case WID_GO_LANG_DROPDOWN: { // Setup interface language dropdown
276  for (uint i = 0; i < _languages.size(); i++) {
277  if (&_languages[i] == _current_language) *selected_index = i;
278  list.emplace_back(new DropDownListStringItem(SPECSTR_LANGUAGE_START + i, i, false));
279  }
280  std::sort(list.begin(), list.end(), DropDownListStringItem::NatSortFunc);
281  break;
282  }
283 
284  case WID_GO_RESOLUTION_DROPDOWN: // Setup resolution dropdown
285  if (_resolutions.empty()) break;
286 
287  *selected_index = GetCurRes();
288  for (uint i = 0; i < _resolutions.size(); i++) {
289  list.emplace_back(new DropDownListStringItem(SPECSTR_RESOLUTION_START + i, i, false));
290  }
291  break;
292 
294  *selected_index = ZOOM_LVL_OUT_4X - _gui_zoom;
295  const StringID *items = _gui_zoom_dropdown;
296  for (int i = 0; *items != INVALID_STRING_ID; items++, i++) {
297  list.emplace_back(new DropDownListStringItem(*items, i, _settings_client.gui.zoom_min > ZOOM_LVL_OUT_4X - i));
298  }
299  break;
300  }
301 
303  *selected_index = ZOOM_LVL_OUT_4X - _font_zoom;
304  const StringID *items = _font_zoom_dropdown;
305  for (int i = 0; *items != INVALID_STRING_ID; items++, i++) {
306  list.emplace_back(new DropDownListStringItem(*items, i, false));
307  }
308  break;
309  }
310 
312  list = BuildSetDropDownList<BaseGraphics>(selected_index, (_game_mode == GM_MENU));
313  break;
314 
316  list = BuildSetDropDownList<BaseSounds>(selected_index, (_game_mode == GM_MENU));
317  break;
318 
320  list = BuildMusicSetDropDownList(selected_index);
321  break;
322  }
323 
324  return list;
325  }
326 
327  void SetStringParameters(int widget) const override
328  {
329  switch (widget) {
330  case WID_GO_CURRENCY_DROPDOWN: SetDParam(0, _currency_specs[this->opt->locale.currency].name); break;
331  case WID_GO_ROADSIDE_DROPDOWN: SetDParam(0, STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_LEFT + this->opt->vehicle.road_side); break;
333  case WID_GO_AUTOSAVE_DROPDOWN: SetDParam(0, _autosave_dropdown[_settings_client.gui.autosave]); break;
335  case WID_GO_RESOLUTION_DROPDOWN: SetDParam(0, GetCurRes() == _resolutions.size() ? STR_GAME_OPTIONS_RESOLUTION_OTHER : SPECSTR_RESOLUTION_START + GetCurRes()); break;
336  case WID_GO_GUI_ZOOM_DROPDOWN: SetDParam(0, _gui_zoom_dropdown[ZOOM_LVL_OUT_4X - _gui_zoom]); break;
337  case WID_GO_FONT_ZOOM_DROPDOWN: SetDParam(0, _font_zoom_dropdown[ZOOM_LVL_OUT_4X - _font_zoom]); break;
339  case WID_GO_BASE_GRF_STATUS: SetDParam(0, BaseGraphics::GetUsedSet()->GetNumInvalid()); break;
342  case WID_GO_BASE_MUSIC_STATUS: SetDParam(0, BaseMusic::GetUsedSet()->GetNumInvalid()); break;
343  }
344  }
345 
346  void DrawWidget(const Rect &r, int widget) const override
347  {
348  switch (widget) {
351  DrawStringMultiLine(r.left, r.right, r.top, UINT16_MAX, STR_BLACK_RAW_STRING);
352  break;
353 
356  DrawStringMultiLine(r.left, r.right, r.top, UINT16_MAX, STR_BLACK_RAW_STRING);
357  break;
358 
361  DrawStringMultiLine(r.left, r.right, r.top, UINT16_MAX, STR_BLACK_RAW_STRING);
362  break;
363  }
364  }
365 
366  void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override
367  {
368  switch (widget) {
370  /* Find the biggest description for the default size. */
371  for (int i = 0; i < BaseGraphics::GetNumSets(); i++) {
373  size->height = max(size->height, (uint)GetStringHeight(STR_BLACK_RAW_STRING, size->width));
374  }
375  break;
376 
378  /* Find the biggest description for the default size. */
379  for (int i = 0; i < BaseGraphics::GetNumSets(); i++) {
380  uint invalid_files = BaseGraphics::GetSet(i)->GetNumInvalid();
381  if (invalid_files == 0) continue;
382 
383  SetDParam(0, invalid_files);
384  *size = maxdim(*size, GetStringBoundingBox(STR_GAME_OPTIONS_BASE_GRF_STATUS));
385  }
386  break;
387 
389  /* Find the biggest description for the default size. */
390  for (int i = 0; i < BaseSounds::GetNumSets(); i++) {
392  size->height = max(size->height, (uint)GetStringHeight(STR_BLACK_RAW_STRING, size->width));
393  }
394  break;
395 
397  /* Find the biggest description for the default size. */
398  for (int i = 0; i < BaseMusic::GetNumSets(); i++) {
399  SetDParamStr(0, BaseMusic::GetSet(i)->GetDescription(GetCurrentLanguageIsoCode()));
400  size->height = max(size->height, (uint)GetStringHeight(STR_BLACK_RAW_STRING, size->width));
401  }
402  break;
403 
405  /* Find the biggest description for the default size. */
406  for (int i = 0; i < BaseMusic::GetNumSets(); i++) {
407  uint invalid_files = BaseMusic::GetSet(i)->GetNumInvalid();
408  if (invalid_files == 0) continue;
409 
410  SetDParam(0, invalid_files);
411  *size = maxdim(*size, GetStringBoundingBox(STR_GAME_OPTIONS_BASE_MUSIC_STATUS));
412  }
413  break;
414 
415  default: {
416  int selected;
417  DropDownList list = this->BuildDropDownList(widget, &selected);
418  if (!list.empty()) {
419  /* Find the biggest item for the default size. */
420  for (const auto &ddli : list) {
421  Dimension string_dim;
422  int width = ddli->Width();
423  string_dim.width = width + padding.width;
424  string_dim.height = ddli->Height(width) + padding.height;
425  *size = maxdim(*size, string_dim);
426  }
427  }
428  }
429  }
430  }
431 
432  void OnClick(Point pt, int widget, int click_count) override
433  {
434  if (widget >= WID_GO_BASE_GRF_TEXTFILE && widget < WID_GO_BASE_GRF_TEXTFILE + TFT_END) {
435  if (BaseGraphics::GetUsedSet() == nullptr) return;
436 
437  ShowBaseSetTextfileWindow((TextfileType)(widget - WID_GO_BASE_GRF_TEXTFILE), BaseGraphics::GetUsedSet(), STR_CONTENT_TYPE_BASE_GRAPHICS);
438  return;
439  }
440  if (widget >= WID_GO_BASE_SFX_TEXTFILE && widget < WID_GO_BASE_SFX_TEXTFILE + TFT_END) {
441  if (BaseSounds::GetUsedSet() == nullptr) return;
442 
443  ShowBaseSetTextfileWindow((TextfileType)(widget - WID_GO_BASE_SFX_TEXTFILE), BaseSounds::GetUsedSet(), STR_CONTENT_TYPE_BASE_SOUNDS);
444  return;
445  }
446  if (widget >= WID_GO_BASE_MUSIC_TEXTFILE && widget < WID_GO_BASE_MUSIC_TEXTFILE + TFT_END) {
447  if (BaseMusic::GetUsedSet() == nullptr) return;
448 
449  ShowBaseSetTextfileWindow((TextfileType)(widget - WID_GO_BASE_MUSIC_TEXTFILE), BaseMusic::GetUsedSet(), STR_CONTENT_TYPE_BASE_MUSIC);
450  return;
451  }
452  switch (widget) {
453  case WID_GO_FULLSCREEN_BUTTON: // Click fullscreen on/off
454  /* try to toggle full-screen on/off */
455  if (!ToggleFullScreen(!_fullscreen)) {
456  ShowErrorMessage(STR_ERROR_FULLSCREEN_FAILED, INVALID_STRING_ID, WL_ERROR);
457  }
459  this->SetDirty();
460  break;
461 
462  default: {
463  int selected;
464  DropDownList list = this->BuildDropDownList(widget, &selected);
465  if (!list.empty()) {
466  ShowDropDownList(this, std::move(list), selected, widget);
467  } else {
468  if (widget == WID_GO_RESOLUTION_DROPDOWN) ShowErrorMessage(STR_ERROR_RESOLUTION_LIST_FAILED, INVALID_STRING_ID, WL_ERROR);
469  }
470  break;
471  }
472  }
473  }
474 
480  template <class T>
481  void SetMediaSet(int index)
482  {
483  if (_game_mode == GM_MENU) {
484  const char *name = T::GetSet(index)->name;
485 
486  free(T::ini_set);
487  T::ini_set = stredup(name);
488 
489  T::SetSet(name);
490  this->reload = true;
491  this->InvalidateData();
492  }
493  }
494 
495  void OnDropdownSelect(int widget, int index) override
496  {
497  switch (widget) {
498  case WID_GO_CURRENCY_DROPDOWN: // Currency
499  if (index == CURRENCY_CUSTOM) ShowCustCurrency();
500  this->opt->locale.currency = index;
502  break;
503 
504  case WID_GO_ROADSIDE_DROPDOWN: // Road side
505  if (this->opt->vehicle.road_side != index) { // only change if setting changed
506  uint i;
507  if (GetSettingFromName("vehicle.road_side", &i) == nullptr) NOT_REACHED();
508  SetSettingValue(i, index);
510  }
511  break;
512 
513  case WID_GO_TOWNNAME_DROPDOWN: // Town names
514  if (_game_mode == GM_MENU || Town::GetNumItems() == 0) {
515  this->opt->game_creation.town_name = index;
517  }
518  break;
519 
520  case WID_GO_AUTOSAVE_DROPDOWN: // Autosave options
521  _settings_client.gui.autosave = index;
522  this->SetDirty();
523  break;
524 
525  case WID_GO_LANG_DROPDOWN: // Change interface language
526  ReadLanguagePack(&_languages[index]);
529  ClearAllCachedNames();
532  break;
533 
534  case WID_GO_RESOLUTION_DROPDOWN: // Change resolution
535  if ((uint)index < _resolutions.size() && ChangeResInGame(_resolutions[index].width, _resolutions[index].height)) {
536  this->SetDirty();
537  }
538  break;
539 
542  _gui_zoom = (ZoomLevel)(ZOOM_LVL_OUT_4X - index);
545  FixTitleGameZoom();
547  break;
548 
551  _font_zoom = (ZoomLevel)(ZOOM_LVL_OUT_4X - index);
552  ClearFontCache();
555  break;
556 
558  this->SetMediaSet<BaseGraphics>(index);
559  break;
560 
562  this->SetMediaSet<BaseSounds>(index);
563  break;
564 
566  ChangeMusicSet(index);
567  break;
568  }
569  }
570 
576  void OnInvalidateData(int data = 0, bool gui_scope = true) override
577  {
578  if (!gui_scope) return;
580 
581  bool missing_files = BaseGraphics::GetUsedSet()->GetNumMissing() == 0;
582  this->GetWidget<NWidgetCore>(WID_GO_BASE_GRF_STATUS)->SetDataTip(missing_files ? STR_EMPTY : STR_GAME_OPTIONS_BASE_GRF_STATUS, STR_NULL);
583 
584  for (TextfileType tft = TFT_BEGIN; tft < TFT_END; tft++) {
588  }
589 
590  missing_files = BaseMusic::GetUsedSet()->GetNumInvalid() == 0;
591  this->GetWidget<NWidgetCore>(WID_GO_BASE_MUSIC_STATUS)->SetDataTip(missing_files ? STR_EMPTY : STR_GAME_OPTIONS_BASE_MUSIC_STATUS, STR_NULL);
592  }
593 };
594 
595 static const NWidgetPart _nested_game_options_widgets[] = {
597  NWidget(WWT_CLOSEBOX, COLOUR_GREY),
598  NWidget(WWT_CAPTION, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
599  EndContainer(),
600  NWidget(WWT_PANEL, COLOUR_GREY, WID_GO_BACKGROUND), SetPIP(6, 6, 10),
601  NWidget(NWID_HORIZONTAL), SetPIP(10, 10, 10),
602  NWidget(NWID_VERTICAL), SetPIP(0, 6, 0),
603  NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_ROAD_VEHICLES_FRAME, STR_NULL),
604  NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_ROADSIDE_DROPDOWN), SetMinimalSize(150, 12), SetDataTip(STR_BLACK_STRING, STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_TOOLTIP), SetFill(1, 0),
605  EndContainer(),
606  NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_AUTOSAVE_FRAME, STR_NULL),
607  NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_AUTOSAVE_DROPDOWN), SetMinimalSize(150, 12), SetDataTip(STR_BLACK_STRING, STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_TOOLTIP), SetFill(1, 0),
608  EndContainer(),
609  NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_RESOLUTION, STR_NULL),
610  NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_RESOLUTION_DROPDOWN), SetMinimalSize(150, 12), SetDataTip(STR_BLACK_STRING, STR_GAME_OPTIONS_RESOLUTION_TOOLTIP), SetFill(1, 0), SetPadding(0, 0, 3, 0),
612  NWidget(WWT_TEXT, COLOUR_GREY), SetMinimalSize(0, 12), SetFill(1, 0), SetDataTip(STR_GAME_OPTIONS_FULLSCREEN, STR_NULL),
613  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_GO_FULLSCREEN_BUTTON), SetMinimalSize(21, 9), SetDataTip(STR_EMPTY, STR_GAME_OPTIONS_FULLSCREEN_TOOLTIP),
614  EndContainer(),
615  EndContainer(),
616  NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_GUI_ZOOM_FRAME, STR_NULL),
617  NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_GUI_ZOOM_DROPDOWN), SetMinimalSize(150, 12), SetDataTip(STR_BLACK_STRING, STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_TOOLTIP), SetFill(1, 0),
618  EndContainer(),
619  EndContainer(),
620 
621  NWidget(NWID_VERTICAL), SetPIP(0, 6, 0),
622  NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_TOWN_NAMES_FRAME, STR_NULL),
623  NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_TOWNNAME_DROPDOWN), SetMinimalSize(150, 12), SetDataTip(STR_BLACK_STRING, STR_GAME_OPTIONS_TOWN_NAMES_DROPDOWN_TOOLTIP), SetFill(1, 0),
624  EndContainer(),
625  NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_LANGUAGE, STR_NULL),
626  NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_LANG_DROPDOWN), SetMinimalSize(150, 12), SetDataTip(STR_BLACK_RAW_STRING, STR_GAME_OPTIONS_LANGUAGE_TOOLTIP), SetFill(1, 0),
627  EndContainer(),
628  NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_CURRENCY_UNITS_FRAME, STR_NULL),
629  NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_CURRENCY_DROPDOWN), SetMinimalSize(150, 12), SetDataTip(STR_BLACK_STRING, STR_GAME_OPTIONS_CURRENCY_UNITS_DROPDOWN_TOOLTIP), SetFill(1, 0),
630  EndContainer(),
631  NWidget(NWID_SPACER), SetMinimalSize(0, 0), SetFill(0, 1),
632  NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_FONT_ZOOM, STR_NULL),
633  NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_FONT_ZOOM_DROPDOWN), SetMinimalSize(150, 12), SetDataTip(STR_BLACK_STRING, STR_GAME_OPTIONS_FONT_ZOOM_DROPDOWN_TOOLTIP), SetFill(1, 0),
634  EndContainer(),
635  EndContainer(),
636  EndContainer(),
637 
638  NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_BASE_GRF, STR_NULL), SetPadding(0, 10, 0, 10),
639  NWidget(NWID_HORIZONTAL), SetPIP(0, 30, 0),
640  NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_BASE_GRF_DROPDOWN), SetMinimalSize(150, 12), SetDataTip(STR_BLACK_RAW_STRING, STR_GAME_OPTIONS_BASE_GRF_TOOLTIP),
641  NWidget(WWT_TEXT, COLOUR_GREY, WID_GO_BASE_GRF_STATUS), SetMinimalSize(150, 12), SetDataTip(STR_EMPTY, STR_NULL), SetFill(1, 0),
642  EndContainer(),
643  NWidget(WWT_TEXT, COLOUR_GREY, WID_GO_BASE_GRF_DESCRIPTION), SetMinimalSize(330, 0), SetDataTip(STR_EMPTY, STR_GAME_OPTIONS_BASE_GRF_DESCRIPTION_TOOLTIP), SetFill(1, 0), SetPadding(6, 0, 6, 0),
645  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_GO_BASE_GRF_TEXTFILE + TFT_README), SetFill(1, 0), SetResize(1, 0), SetDataTip(STR_TEXTFILE_VIEW_README, STR_NULL),
646  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_GO_BASE_GRF_TEXTFILE + TFT_CHANGELOG), SetFill(1, 0), SetResize(1, 0), SetDataTip(STR_TEXTFILE_VIEW_CHANGELOG, STR_NULL),
647  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_GO_BASE_GRF_TEXTFILE + TFT_LICENSE), SetFill(1, 0), SetResize(1, 0), SetDataTip(STR_TEXTFILE_VIEW_LICENCE, STR_NULL),
648  EndContainer(),
649  EndContainer(),
650 
651  NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_BASE_SFX, STR_NULL), SetPadding(0, 10, 0, 10),
652  NWidget(NWID_HORIZONTAL), SetPIP(0, 30, 0),
653  NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_BASE_SFX_DROPDOWN), SetMinimalSize(150, 12), SetDataTip(STR_BLACK_RAW_STRING, STR_GAME_OPTIONS_BASE_SFX_TOOLTIP),
654  NWidget(NWID_SPACER), SetFill(1, 0),
655  EndContainer(),
656  NWidget(WWT_TEXT, COLOUR_GREY, WID_GO_BASE_SFX_DESCRIPTION), SetMinimalSize(330, 0), SetDataTip(STR_EMPTY, STR_GAME_OPTIONS_BASE_SFX_DESCRIPTION_TOOLTIP), SetFill(1, 0), SetPadding(6, 0, 6, 0),
658  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_GO_BASE_SFX_TEXTFILE + TFT_README), SetFill(1, 0), SetResize(1, 0), SetDataTip(STR_TEXTFILE_VIEW_README, STR_NULL),
659  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_GO_BASE_SFX_TEXTFILE + TFT_CHANGELOG), SetFill(1, 0), SetResize(1, 0), SetDataTip(STR_TEXTFILE_VIEW_CHANGELOG, STR_NULL),
660  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_GO_BASE_SFX_TEXTFILE + TFT_LICENSE), SetFill(1, 0), SetResize(1, 0), SetDataTip(STR_TEXTFILE_VIEW_LICENCE, STR_NULL),
661  EndContainer(),
662  EndContainer(),
663 
664  NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_BASE_MUSIC, STR_NULL), SetPadding(0, 10, 0, 10),
665  NWidget(NWID_HORIZONTAL), SetPIP(0, 30, 0),
666  NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_BASE_MUSIC_DROPDOWN), SetMinimalSize(150, 12), SetDataTip(STR_BLACK_RAW_STRING, STR_GAME_OPTIONS_BASE_MUSIC_TOOLTIP),
667  NWidget(WWT_TEXT, COLOUR_GREY, WID_GO_BASE_MUSIC_STATUS), SetMinimalSize(150, 12), SetDataTip(STR_EMPTY, STR_NULL), SetFill(1, 0),
668  EndContainer(),
669  NWidget(WWT_TEXT, COLOUR_GREY, WID_GO_BASE_MUSIC_DESCRIPTION), SetMinimalSize(330, 0), SetDataTip(STR_EMPTY, STR_GAME_OPTIONS_BASE_MUSIC_DESCRIPTION_TOOLTIP), SetFill(1, 0), SetPadding(6, 0, 6, 0),
671  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_GO_BASE_MUSIC_TEXTFILE + TFT_README), SetFill(1, 0), SetResize(1, 0), SetDataTip(STR_TEXTFILE_VIEW_README, STR_NULL),
672  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_GO_BASE_MUSIC_TEXTFILE + TFT_CHANGELOG), SetFill(1, 0), SetResize(1, 0), SetDataTip(STR_TEXTFILE_VIEW_CHANGELOG, STR_NULL),
673  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_GO_BASE_MUSIC_TEXTFILE + TFT_LICENSE), SetFill(1, 0), SetResize(1, 0), SetDataTip(STR_TEXTFILE_VIEW_LICENCE, STR_NULL),
674  EndContainer(),
675  EndContainer(),
676  EndContainer(),
677 };
678 
679 static WindowDesc _game_options_desc(
680  WDP_CENTER, "settings_game", 0, 0,
682  0,
683  _nested_game_options_widgets, lengthof(_nested_game_options_widgets)
684 );
685 
688 {
690  new GameOptionsWindow(&_game_options_desc);
691 }
692 
693 static int SETTING_HEIGHT = 11;
694 static const int LEVEL_WIDTH = 15;
695 
704 
705  SEF_LAST_FIELD = 0x04,
706  SEF_FILTERED = 0x08,
707 };
708 
717 };
719 
720 
724  bool type_hides;
727 };
728 
731  byte flags;
732  byte level;
733 
734  BaseSettingEntry() : flags(0), level(0) {}
735  virtual ~BaseSettingEntry() {}
736 
737  virtual void Init(byte level = 0);
738  virtual void FoldAll() {}
739  virtual void UnFoldAll() {}
740 
745  void SetLastField(bool last_field) { if (last_field) SETBITS(this->flags, SEF_LAST_FIELD); else CLRBITS(this->flags, SEF_LAST_FIELD); }
746 
747  virtual uint Length() const = 0;
748  virtual void GetFoldingState(bool &all_folded, bool &all_unfolded) const {}
749  virtual bool IsVisible(const BaseSettingEntry *item) const;
750  virtual BaseSettingEntry *FindEntry(uint row, uint *cur_row);
751  virtual uint GetMaxHelpHeight(int maxw) { return 0; }
752 
757  bool IsFiltered() const { return (this->flags & SEF_FILTERED) != 0; }
758 
759  virtual bool UpdateFilterState(SettingFilter &filter, bool force_visible) = 0;
760 
761  virtual uint Draw(GameSettings *settings_ptr, int left, int right, int y, uint first_row, uint max_row, BaseSettingEntry *selected, uint cur_row = 0, uint parent_last = 0) const;
762 
763 protected:
764  virtual void DrawSetting(GameSettings *settings_ptr, int left, int right, int y, bool highlight) const = 0;
765 };
766 
769  const char *name;
771  uint index;
772 
773  SettingEntry(const char *name);
774 
775  virtual void Init(byte level = 0);
776  virtual uint Length() const;
777  virtual uint GetMaxHelpHeight(int maxw);
778  virtual bool UpdateFilterState(SettingFilter &filter, bool force_visible);
779 
780  void SetButtons(byte new_val);
781 
786  inline StringID GetHelpText() const
787  {
788  return this->setting->desc.str_help;
789  }
790 
791  void SetValueDParams(uint first_param, int32 value) const;
792 
793 protected:
794  virtual void DrawSetting(GameSettings *settings_ptr, int left, int right, int y, bool highlight) const;
795 
796 private:
797  bool IsVisibleByRestrictionMode(RestrictionMode mode) const;
798 };
799 
802  typedef std::vector<BaseSettingEntry*> EntryVector;
803  EntryVector entries;
804 
805  template<typename T>
806  T *Add(T *item)
807  {
808  this->entries.push_back(item);
809  return item;
810  }
811 
812  void Init(byte level = 0);
813  void FoldAll();
814  void UnFoldAll();
815 
816  uint Length() const;
817  void GetFoldingState(bool &all_folded, bool &all_unfolded) const;
818  bool IsVisible(const BaseSettingEntry *item) const;
819  BaseSettingEntry *FindEntry(uint row, uint *cur_row);
820  uint GetMaxHelpHeight(int maxw);
821 
822  bool UpdateFilterState(SettingFilter &filter, bool force_visible);
823 
824  uint Draw(GameSettings *settings_ptr, int left, int right, int y, uint first_row, uint max_row, BaseSettingEntry *selected, uint cur_row = 0, uint parent_last = 0) const;
825 };
826 
830  bool folded;
831 
832  SettingsPage(StringID title);
833 
834  virtual void Init(byte level = 0);
835  virtual void FoldAll();
836  virtual void UnFoldAll();
837 
838  virtual uint Length() const;
839  virtual void GetFoldingState(bool &all_folded, bool &all_unfolded) const;
840  virtual bool IsVisible(const BaseSettingEntry *item) const;
841  virtual BaseSettingEntry *FindEntry(uint row, uint *cur_row);
842  virtual uint GetMaxHelpHeight(int maxw) { return SettingsContainer::GetMaxHelpHeight(maxw); }
843 
844  virtual bool UpdateFilterState(SettingFilter &filter, bool force_visible);
845 
846  virtual uint Draw(GameSettings *settings_ptr, int left, int right, int y, uint first_row, uint max_row, BaseSettingEntry *selected, uint cur_row = 0, uint parent_last = 0) const;
847 
848 protected:
849  virtual void DrawSetting(GameSettings *settings_ptr, int left, int right, int y, bool highlight) const;
850 };
851 
852 /* == BaseSettingEntry methods == */
853 
858 void BaseSettingEntry::Init(byte level)
859 {
860  this->level = level;
861 }
862 
870 {
871  if (this->IsFiltered()) return false;
872  if (this == item) return true;
873  return false;
874 }
875 
882 BaseSettingEntry *BaseSettingEntry::FindEntry(uint row_num, uint *cur_row)
883 {
884  if (this->IsFiltered()) return nullptr;
885  if (row_num == *cur_row) return this;
886  (*cur_row)++;
887  return nullptr;
888 }
889 
919 uint BaseSettingEntry::Draw(GameSettings *settings_ptr, int left, int right, int y, uint first_row, uint max_row, BaseSettingEntry *selected, uint cur_row, uint parent_last) const
920 {
921  if (this->IsFiltered()) return cur_row;
922  if (cur_row >= max_row) return cur_row;
923 
924  bool rtl = _current_text_dir == TD_RTL;
925  int offset = rtl ? -4 : 4;
926  int level_width = rtl ? -LEVEL_WIDTH : LEVEL_WIDTH;
927 
928  int x = rtl ? right : left;
929  if (cur_row >= first_row) {
930  int colour = _colour_gradient[COLOUR_ORANGE][4];
931  y += (cur_row - first_row) * SETTING_HEIGHT; // Compute correct y start position
932 
933  /* Draw vertical for parent nesting levels */
934  for (uint lvl = 0; lvl < this->level; lvl++) {
935  if (!HasBit(parent_last, lvl)) GfxDrawLine(x + offset, y, x + offset, y + SETTING_HEIGHT - 1, colour);
936  x += level_width;
937  }
938  /* draw own |- prefix */
939  int halfway_y = y + SETTING_HEIGHT / 2;
940  int bottom_y = (flags & SEF_LAST_FIELD) ? halfway_y : y + SETTING_HEIGHT - 1;
941  GfxDrawLine(x + offset, y, x + offset, bottom_y, colour);
942  /* Small horizontal line from the last vertical line */
943  GfxDrawLine(x + offset, halfway_y, x + level_width - offset, halfway_y, colour);
944  x += level_width;
945 
946  this->DrawSetting(settings_ptr, rtl ? left : x, rtl ? x : right, y, this == selected);
947  }
948  cur_row++;
949 
950  return cur_row;
951 }
952 
953 /* == SettingEntry methods == */
954 
959 SettingEntry::SettingEntry(const char *name)
960 {
961  this->name = name;
962  this->setting = nullptr;
963  this->index = 0;
964 }
965 
970 void SettingEntry::Init(byte level)
971 {
972  BaseSettingEntry::Init(level);
973  this->setting = GetSettingFromName(this->name, &this->index);
974  assert(this->setting != nullptr);
975 }
976 
982 void SettingEntry::SetButtons(byte new_val)
983 {
984  assert((new_val & ~SEF_BUTTONS_MASK) == 0); // Should not touch any flags outside the buttons
985  this->flags = (this->flags & ~SEF_BUTTONS_MASK) | new_val;
986 }
987 
990 {
991  return this->IsFiltered() ? 0 : 1;
992 }
993 
1000 {
1001  return GetStringHeight(this->GetHelpText(), maxw);
1002 }
1003 
1010 {
1011  /* There shall not be any restriction, i.e. all settings shall be visible. */
1012  if (mode == RM_ALL) return true;
1013 
1014  GameSettings *settings_ptr = &GetGameSettings();
1015  const SettingDesc *sd = this->setting;
1016 
1017  if (mode == RM_BASIC) return (this->setting->desc.cat & SC_BASIC_LIST) != 0;
1018  if (mode == RM_ADVANCED) return (this->setting->desc.cat & SC_ADVANCED_LIST) != 0;
1019 
1020  /* Read the current value. */
1021  const void *var = ResolveVariableAddress(settings_ptr, sd);
1022  int64 current_value = ReadValue(var, sd->save.conv);
1023 
1024  int64 filter_value;
1025 
1026  if (mode == RM_CHANGED_AGAINST_DEFAULT) {
1027  /* This entry shall only be visible, if the value deviates from its default value. */
1028 
1029  /* Read the default value. */
1030  filter_value = ReadValue(&sd->desc.def, sd->save.conv);
1031  } else {
1032  assert(mode == RM_CHANGED_AGAINST_NEW);
1033  /* This entry shall only be visible, if the value deviates from
1034  * its value is used when starting a new game. */
1035 
1036  /* Make sure we're not comparing the new game settings against itself. */
1037  assert(settings_ptr != &_settings_newgame);
1038 
1039  /* Read the new game's value. */
1040  var = ResolveVariableAddress(&_settings_newgame, sd);
1041  filter_value = ReadValue(var, sd->save.conv);
1042  }
1043 
1044  return current_value != filter_value;
1045 }
1046 
1053 bool SettingEntry::UpdateFilterState(SettingFilter &filter, bool force_visible)
1054 {
1055  CLRBITS(this->flags, SEF_FILTERED);
1056 
1057  bool visible = true;
1058 
1059  const SettingDesc *sd = this->setting;
1060  if (!force_visible && !filter.string.IsEmpty()) {
1061  /* Process the search text filter for this item. */
1062  filter.string.ResetState();
1063 
1064  const SettingDescBase *sdb = &sd->desc;
1065 
1066  SetDParam(0, STR_EMPTY);
1067  filter.string.AddLine(sdb->str);
1068  filter.string.AddLine(this->GetHelpText());
1069 
1070  visible = filter.string.GetState();
1071  }
1072 
1073  if (visible) {
1074  if (filter.type != ST_ALL && sd->GetType() != filter.type) {
1075  filter.type_hides = true;
1076  visible = false;
1077  }
1078  if (!this->IsVisibleByRestrictionMode(filter.mode)) {
1079  while (filter.min_cat < RM_ALL && (filter.min_cat == filter.mode || !this->IsVisibleByRestrictionMode(filter.min_cat))) filter.min_cat++;
1080  visible = false;
1081  }
1082  }
1083 
1084  if (!visible) SETBITS(this->flags, SEF_FILTERED);
1085  return visible;
1086 }
1087 
1088 
1089 static const void *ResolveVariableAddress(const GameSettings *settings_ptr, const SettingDesc *sd)
1090 {
1091  if ((sd->desc.flags & SGF_PER_COMPANY) != 0) {
1092  if (Company::IsValidID(_local_company) && _game_mode != GM_MENU) {
1094  } else {
1096  }
1097  } else {
1098  return GetVariableAddress(settings_ptr, &sd->save);
1099  }
1100 }
1101 
1107 void SettingEntry::SetValueDParams(uint first_param, int32 value) const
1108 {
1109  const SettingDescBase *sdb = &this->setting->desc;
1110  if (sdb->cmd == SDT_BOOLX) {
1111  SetDParam(first_param++, value != 0 ? STR_CONFIG_SETTING_ON : STR_CONFIG_SETTING_OFF);
1112  } else {
1113  if ((sdb->flags & SGF_MULTISTRING) != 0) {
1114  SetDParam(first_param++, sdb->str_val - sdb->min + value);
1115  } else if ((sdb->flags & SGF_DISPLAY_ABS) != 0) {
1116  SetDParam(first_param++, sdb->str_val + ((value >= 0) ? 1 : 0));
1117  value = abs(value);
1118  } else {
1119  SetDParam(first_param++, sdb->str_val + ((value == 0 && (sdb->flags & SGF_0ISDISABLED) != 0) ? 1 : 0));
1120  }
1121  SetDParam(first_param++, value);
1122  }
1123 }
1124 
1133 void SettingEntry::DrawSetting(GameSettings *settings_ptr, int left, int right, int y, bool highlight) const
1134 {
1135  const SettingDesc *sd = this->setting;
1136  const SettingDescBase *sdb = &sd->desc;
1137  const void *var = ResolveVariableAddress(settings_ptr, sd);
1138  int state = this->flags & SEF_BUTTONS_MASK;
1139 
1140  bool rtl = _current_text_dir == TD_RTL;
1141  uint buttons_left = rtl ? right + 1 - SETTING_BUTTON_WIDTH : left;
1142  uint text_left = left + (rtl ? 0 : SETTING_BUTTON_WIDTH + 5);
1143  uint text_right = right - (rtl ? SETTING_BUTTON_WIDTH + 5 : 0);
1144  uint button_y = y + (SETTING_HEIGHT - SETTING_BUTTON_HEIGHT) / 2;
1145 
1146  /* We do not allow changes of some items when we are a client in a networkgame */
1147  bool editable = sd->IsEditable();
1148 
1149  SetDParam(0, highlight ? STR_ORANGE_STRING1_WHITE : STR_ORANGE_STRING1_LTBLUE);
1150  int32 value = (int32)ReadValue(var, sd->save.conv);
1151  if (sdb->cmd == SDT_BOOLX) {
1152  /* Draw checkbox for boolean-value either on/off */
1153  DrawBoolButton(buttons_left, button_y, value != 0, editable);
1154  } else if ((sdb->flags & SGF_MULTISTRING) != 0) {
1155  /* Draw [v] button for settings of an enum-type */
1156  DrawDropDownButton(buttons_left, button_y, COLOUR_YELLOW, state != 0, editable);
1157  } else {
1158  /* Draw [<][>] boxes for settings of an integer-type */
1159  DrawArrowButtons(buttons_left, button_y, COLOUR_YELLOW, state,
1160  editable && value != (sdb->flags & SGF_0ISDISABLED ? 0 : sdb->min), editable && (uint32)value != sdb->max);
1161  }
1162  this->SetValueDParams(1, value);
1163  DrawString(text_left, text_right, y + (SETTING_HEIGHT - FONT_HEIGHT_NORMAL) / 2, sdb->str, highlight ? TC_WHITE : TC_LIGHT_BLUE);
1164 }
1165 
1166 /* == SettingsContainer methods == */
1167 
1172 void SettingsContainer::Init(byte level)
1173 {
1174  for (EntryVector::iterator it = this->entries.begin(); it != this->entries.end(); ++it) {
1175  (*it)->Init(level);
1176  }
1177 }
1178 
1181 {
1182  for (EntryVector::iterator it = this->entries.begin(); it != this->entries.end(); ++it) {
1183  (*it)->FoldAll();
1184  }
1185 }
1186 
1189 {
1190  for (EntryVector::iterator it = this->entries.begin(); it != this->entries.end(); ++it) {
1191  (*it)->UnFoldAll();
1192  }
1193 }
1194 
1200 void SettingsContainer::GetFoldingState(bool &all_folded, bool &all_unfolded) const
1201 {
1202  for (EntryVector::const_iterator it = this->entries.begin(); it != this->entries.end(); ++it) {
1203  (*it)->GetFoldingState(all_folded, all_unfolded);
1204  }
1205 }
1206 
1213 bool SettingsContainer::UpdateFilterState(SettingFilter &filter, bool force_visible)
1214 {
1215  bool visible = false;
1216  bool first_visible = true;
1217  for (EntryVector::reverse_iterator it = this->entries.rbegin(); it != this->entries.rend(); ++it) {
1218  visible |= (*it)->UpdateFilterState(filter, force_visible);
1219  (*it)->SetLastField(first_visible);
1220  if (visible && first_visible) first_visible = false;
1221  }
1222  return visible;
1223 }
1224 
1225 
1233 {
1234  for (EntryVector::const_iterator it = this->entries.begin(); it != this->entries.end(); ++it) {
1235  if ((*it)->IsVisible(item)) return true;
1236  }
1237  return false;
1238 }
1239 
1242 {
1243  uint length = 0;
1244  for (EntryVector::const_iterator it = this->entries.begin(); it != this->entries.end(); ++it) {
1245  length += (*it)->Length();
1246  }
1247  return length;
1248 }
1249 
1256 BaseSettingEntry *SettingsContainer::FindEntry(uint row_num, uint *cur_row)
1257 {
1258  BaseSettingEntry *pe = nullptr;
1259  for (EntryVector::iterator it = this->entries.begin(); it != this->entries.end(); ++it) {
1260  pe = (*it)->FindEntry(row_num, cur_row);
1261  if (pe != nullptr) {
1262  break;
1263  }
1264  }
1265  return pe;
1266 }
1267 
1274 {
1275  uint biggest = 0;
1276  for (EntryVector::const_iterator it = this->entries.begin(); it != this->entries.end(); ++it) {
1277  biggest = max(biggest, (*it)->GetMaxHelpHeight(maxw));
1278  }
1279  return biggest;
1280 }
1281 
1282 
1297 uint SettingsContainer::Draw(GameSettings *settings_ptr, int left, int right, int y, uint first_row, uint max_row, BaseSettingEntry *selected, uint cur_row, uint parent_last) const
1298 {
1299  for (EntryVector::const_iterator it = this->entries.begin(); it != this->entries.end(); ++it) {
1300  cur_row = (*it)->Draw(settings_ptr, left, right, y, first_row, max_row, selected, cur_row, parent_last);
1301  if (cur_row >= max_row) {
1302  break;
1303  }
1304  }
1305  return cur_row;
1306 }
1307 
1308 /* == SettingsPage methods == */
1309 
1315 {
1316  this->title = title;
1317  this->folded = true;
1318 }
1319 
1324 void SettingsPage::Init(byte level)
1325 {
1326  BaseSettingEntry::Init(level);
1327  SettingsContainer::Init(level + 1);
1328 }
1329 
1332 {
1333  if (this->IsFiltered()) return;
1334  this->folded = true;
1335 
1337 }
1338 
1341 {
1342  if (this->IsFiltered()) return;
1343  this->folded = false;
1344 
1346 }
1347 
1353 void SettingsPage::GetFoldingState(bool &all_folded, bool &all_unfolded) const
1354 {
1355  if (this->IsFiltered()) return;
1356 
1357  if (this->folded) {
1358  all_unfolded = false;
1359  } else {
1360  all_folded = false;
1361  }
1362 
1363  SettingsContainer::GetFoldingState(all_folded, all_unfolded);
1364 }
1365 
1372 bool SettingsPage::UpdateFilterState(SettingFilter &filter, bool force_visible)
1373 {
1374  if (!force_visible && !filter.string.IsEmpty()) {
1375  filter.string.ResetState();
1376  filter.string.AddLine(this->title);
1377  force_visible = filter.string.GetState();
1378  }
1379 
1380  bool visible = SettingsContainer::UpdateFilterState(filter, force_visible);
1381  if (visible) {
1382  CLRBITS(this->flags, SEF_FILTERED);
1383  } else {
1384  SETBITS(this->flags, SEF_FILTERED);
1385  }
1386  return visible;
1387 }
1388 
1396 {
1397  if (this->IsFiltered()) return false;
1398  if (this == item) return true;
1399  if (this->folded) return false;
1400 
1401  return SettingsContainer::IsVisible(item);
1402 }
1403 
1406 {
1407  if (this->IsFiltered()) return 0;
1408  if (this->folded) return 1; // Only displaying the title
1409 
1410  return 1 + SettingsContainer::Length();
1411 }
1412 
1419 BaseSettingEntry *SettingsPage::FindEntry(uint row_num, uint *cur_row)
1420 {
1421  if (this->IsFiltered()) return nullptr;
1422  if (row_num == *cur_row) return this;
1423  (*cur_row)++;
1424  if (this->folded) return nullptr;
1425 
1426  return SettingsContainer::FindEntry(row_num, cur_row);
1427 }
1428 
1443 uint SettingsPage::Draw(GameSettings *settings_ptr, int left, int right, int y, uint first_row, uint max_row, BaseSettingEntry *selected, uint cur_row, uint parent_last) const
1444 {
1445  if (this->IsFiltered()) return cur_row;
1446  if (cur_row >= max_row) return cur_row;
1447 
1448  cur_row = BaseSettingEntry::Draw(settings_ptr, left, right, y, first_row, max_row, selected, cur_row, parent_last);
1449 
1450  if (!this->folded) {
1451  if (this->flags & SEF_LAST_FIELD) {
1452  assert(this->level < 8 * sizeof(parent_last));
1453  SetBit(parent_last, this->level); // Add own last-field state
1454  }
1455 
1456  cur_row = SettingsContainer::Draw(settings_ptr, left, right, y, first_row, max_row, selected, cur_row, parent_last);
1457  }
1458 
1459  return cur_row;
1460 }
1461 
1470 void SettingsPage::DrawSetting(GameSettings *settings_ptr, int left, int right, int y, bool highlight) const
1471 {
1472  bool rtl = _current_text_dir == TD_RTL;
1473  DrawSprite((this->folded ? SPR_CIRCLE_FOLDED : SPR_CIRCLE_UNFOLDED), PAL_NONE, rtl ? right - _circle_size.width : left, y + (SETTING_HEIGHT - _circle_size.height) / 2);
1474  DrawString(rtl ? left : left + _circle_size.width + 2, rtl ? right - _circle_size.width - 2 : right, y + (SETTING_HEIGHT - FONT_HEIGHT_NORMAL) / 2, this->title);
1475 }
1476 
1479 {
1480  static SettingsContainer *main = nullptr;
1481 
1482  if (main == nullptr)
1483  {
1484  /* Build up the dynamic settings-array only once per OpenTTD session */
1485  main = new SettingsContainer();
1486 
1487  SettingsPage *localisation = main->Add(new SettingsPage(STR_CONFIG_SETTING_LOCALISATION));
1488  {
1489  localisation->Add(new SettingEntry("locale.units_velocity"));
1490  localisation->Add(new SettingEntry("locale.units_power"));
1491  localisation->Add(new SettingEntry("locale.units_weight"));
1492  localisation->Add(new SettingEntry("locale.units_volume"));
1493  localisation->Add(new SettingEntry("locale.units_force"));
1494  localisation->Add(new SettingEntry("locale.units_height"));
1495  localisation->Add(new SettingEntry("gui.date_format_in_default_names"));
1496  }
1497 
1498  SettingsPage *graphics = main->Add(new SettingsPage(STR_CONFIG_SETTING_GRAPHICS));
1499  {
1500  graphics->Add(new SettingEntry("gui.zoom_min"));
1501  graphics->Add(new SettingEntry("gui.zoom_max"));
1502  graphics->Add(new SettingEntry("gui.smallmap_land_colour"));
1503  graphics->Add(new SettingEntry("gui.graph_line_thickness"));
1504  }
1505 
1506  SettingsPage *sound = main->Add(new SettingsPage(STR_CONFIG_SETTING_SOUND));
1507  {
1508  sound->Add(new SettingEntry("sound.click_beep"));
1509  sound->Add(new SettingEntry("sound.confirm"));
1510  sound->Add(new SettingEntry("sound.news_ticker"));
1511  sound->Add(new SettingEntry("sound.news_full"));
1512  sound->Add(new SettingEntry("sound.new_year"));
1513  sound->Add(new SettingEntry("sound.disaster"));
1514  sound->Add(new SettingEntry("sound.vehicle"));
1515  sound->Add(new SettingEntry("sound.ambient"));
1516  }
1517 
1518  SettingsPage *interface = main->Add(new SettingsPage(STR_CONFIG_SETTING_INTERFACE));
1519  {
1520  SettingsPage *general = interface->Add(new SettingsPage(STR_CONFIG_SETTING_INTERFACE_GENERAL));
1521  {
1522  general->Add(new SettingEntry("gui.osk_activation"));
1523  general->Add(new SettingEntry("gui.hover_delay_ms"));
1524  general->Add(new SettingEntry("gui.errmsg_duration"));
1525  general->Add(new SettingEntry("gui.window_snap_radius"));
1526  general->Add(new SettingEntry("gui.window_soft_limit"));
1527  general->Add(new SettingEntry("gui.right_mouse_wnd_close"));
1528  }
1529 
1530  SettingsPage *viewports = interface->Add(new SettingsPage(STR_CONFIG_SETTING_INTERFACE_VIEWPORTS));
1531  {
1532  viewports->Add(new SettingEntry("gui.auto_scrolling"));
1533  viewports->Add(new SettingEntry("gui.scroll_mode"));
1534  viewports->Add(new SettingEntry("gui.smooth_scroll"));
1535  /* While the horizontal scrollwheel scrolling is written as general code, only
1536  * the cocoa (OSX) driver generates input for it.
1537  * Since it's also able to completely disable the scrollwheel will we display it on all platforms anyway */
1538  viewports->Add(new SettingEntry("gui.scrollwheel_scrolling"));
1539  viewports->Add(new SettingEntry("gui.scrollwheel_multiplier"));
1540 #ifdef __APPLE__
1541  /* We might need to emulate a right mouse button on mac */
1542  viewports->Add(new SettingEntry("gui.right_mouse_btn_emulation"));
1543 #endif
1544  viewports->Add(new SettingEntry("gui.population_in_label"));
1545  viewports->Add(new SettingEntry("gui.liveries"));
1546  viewports->Add(new SettingEntry("construction.train_signal_side"));
1547  viewports->Add(new SettingEntry("gui.measure_tooltip"));
1548  viewports->Add(new SettingEntry("gui.loading_indicators"));
1549  viewports->Add(new SettingEntry("gui.show_track_reservation"));
1550  }
1551 
1552  SettingsPage *construction = interface->Add(new SettingsPage(STR_CONFIG_SETTING_INTERFACE_CONSTRUCTION));
1553  {
1554  construction->Add(new SettingEntry("gui.link_terraform_toolbar"));
1555  construction->Add(new SettingEntry("gui.enable_signal_gui"));
1556  construction->Add(new SettingEntry("gui.persistent_buildingtools"));
1557  construction->Add(new SettingEntry("gui.quick_goto"));
1558  construction->Add(new SettingEntry("gui.default_rail_type"));
1559  construction->Add(new SettingEntry("gui.disable_unsuitable_building"));
1560  }
1561 
1562  interface->Add(new SettingEntry("gui.autosave"));
1563  interface->Add(new SettingEntry("gui.toolbar_pos"));
1564  interface->Add(new SettingEntry("gui.statusbar_pos"));
1565  interface->Add(new SettingEntry("gui.prefer_teamchat"));
1566  interface->Add(new SettingEntry("gui.advanced_vehicle_list"));
1567  interface->Add(new SettingEntry("gui.timetable_in_ticks"));
1568  interface->Add(new SettingEntry("gui.timetable_arrival_departure"));
1569  interface->Add(new SettingEntry("gui.expenses_layout"));
1570  interface->Add(new SettingEntry("gui.show_newgrf_name"));
1571  }
1572 
1573  SettingsPage *advisors = main->Add(new SettingsPage(STR_CONFIG_SETTING_ADVISORS));
1574  {
1575  advisors->Add(new SettingEntry("gui.coloured_news_year"));
1576  advisors->Add(new SettingEntry("news_display.general"));
1577  advisors->Add(new SettingEntry("news_display.new_vehicles"));
1578  advisors->Add(new SettingEntry("news_display.accident"));
1579  advisors->Add(new SettingEntry("news_display.company_info"));
1580  advisors->Add(new SettingEntry("news_display.acceptance"));
1581  advisors->Add(new SettingEntry("news_display.arrival_player"));
1582  advisors->Add(new SettingEntry("news_display.arrival_other"));
1583  advisors->Add(new SettingEntry("news_display.advice"));
1584  advisors->Add(new SettingEntry("gui.order_review_system"));
1585  advisors->Add(new SettingEntry("gui.vehicle_income_warn"));
1586  advisors->Add(new SettingEntry("gui.lost_vehicle_warn"));
1587  advisors->Add(new SettingEntry("gui.show_finances"));
1588  advisors->Add(new SettingEntry("news_display.economy"));
1589  advisors->Add(new SettingEntry("news_display.subsidies"));
1590  advisors->Add(new SettingEntry("news_display.open"));
1591  advisors->Add(new SettingEntry("news_display.close"));
1592  advisors->Add(new SettingEntry("news_display.production_player"));
1593  advisors->Add(new SettingEntry("news_display.production_other"));
1594  advisors->Add(new SettingEntry("news_display.production_nobody"));
1595  }
1596 
1597  SettingsPage *company = main->Add(new SettingsPage(STR_CONFIG_SETTING_COMPANY));
1598  {
1599  company->Add(new SettingEntry("gui.semaphore_build_before"));
1600  company->Add(new SettingEntry("gui.default_signal_type"));
1601  company->Add(new SettingEntry("gui.cycle_signal_types"));
1602  company->Add(new SettingEntry("gui.drag_signals_fixed_distance"));
1603  company->Add(new SettingEntry("gui.new_nonstop"));
1604  company->Add(new SettingEntry("gui.stop_location"));
1605  company->Add(new SettingEntry("gui.starting_colour"));
1606  company->Add(new SettingEntry("company.engine_renew"));
1607  company->Add(new SettingEntry("company.engine_renew_months"));
1608  company->Add(new SettingEntry("company.engine_renew_money"));
1609  company->Add(new SettingEntry("vehicle.servint_ispercent"));
1610  company->Add(new SettingEntry("vehicle.servint_trains"));
1611  company->Add(new SettingEntry("vehicle.servint_roadveh"));
1612  company->Add(new SettingEntry("vehicle.servint_ships"));
1613  company->Add(new SettingEntry("vehicle.servint_aircraft"));
1614  }
1615 
1616  SettingsPage *accounting = main->Add(new SettingsPage(STR_CONFIG_SETTING_ACCOUNTING));
1617  {
1618  accounting->Add(new SettingEntry("economy.inflation"));
1619  accounting->Add(new SettingEntry("difficulty.initial_interest"));
1620  accounting->Add(new SettingEntry("difficulty.max_loan"));
1621  accounting->Add(new SettingEntry("difficulty.subsidy_multiplier"));
1622  accounting->Add(new SettingEntry("economy.feeder_payment_share"));
1623  accounting->Add(new SettingEntry("economy.infrastructure_maintenance"));
1624  accounting->Add(new SettingEntry("difficulty.vehicle_costs"));
1625  accounting->Add(new SettingEntry("difficulty.construction_cost"));
1626  }
1627 
1628  SettingsPage *vehicles = main->Add(new SettingsPage(STR_CONFIG_SETTING_VEHICLES));
1629  {
1630  SettingsPage *physics = vehicles->Add(new SettingsPage(STR_CONFIG_SETTING_VEHICLES_PHYSICS));
1631  {
1632  physics->Add(new SettingEntry("vehicle.train_acceleration_model"));
1633  physics->Add(new SettingEntry("vehicle.train_slope_steepness"));
1634  physics->Add(new SettingEntry("vehicle.wagon_speed_limits"));
1635  physics->Add(new SettingEntry("vehicle.freight_trains"));
1636  physics->Add(new SettingEntry("vehicle.roadveh_acceleration_model"));
1637  physics->Add(new SettingEntry("vehicle.roadveh_slope_steepness"));
1638  physics->Add(new SettingEntry("vehicle.smoke_amount"));
1639  physics->Add(new SettingEntry("vehicle.plane_speed"));
1640  }
1641 
1642  SettingsPage *routing = vehicles->Add(new SettingsPage(STR_CONFIG_SETTING_VEHICLES_ROUTING));
1643  {
1644  routing->Add(new SettingEntry("pf.pathfinder_for_trains"));
1645  routing->Add(new SettingEntry("difficulty.line_reverse_mode"));
1646  routing->Add(new SettingEntry("pf.reverse_at_signals"));
1647  routing->Add(new SettingEntry("pf.forbid_90_deg"));
1648  routing->Add(new SettingEntry("pf.pathfinder_for_roadvehs"));
1649  routing->Add(new SettingEntry("pf.pathfinder_for_ships"));
1650  }
1651 
1652  vehicles->Add(new SettingEntry("order.no_servicing_if_no_breakdowns"));
1653  vehicles->Add(new SettingEntry("order.serviceathelipad"));
1654  }
1655 
1656  SettingsPage *limitations = main->Add(new SettingsPage(STR_CONFIG_SETTING_LIMITATIONS));
1657  {
1658  limitations->Add(new SettingEntry("construction.command_pause_level"));
1659  limitations->Add(new SettingEntry("construction.autoslope"));
1660  limitations->Add(new SettingEntry("construction.extra_dynamite"));
1661  limitations->Add(new SettingEntry("construction.max_heightlevel"));
1662  limitations->Add(new SettingEntry("construction.max_bridge_length"));
1663  limitations->Add(new SettingEntry("construction.max_bridge_height"));
1664  limitations->Add(new SettingEntry("construction.max_tunnel_length"));
1665  limitations->Add(new SettingEntry("station.never_expire_airports"));
1666  limitations->Add(new SettingEntry("vehicle.never_expire_vehicles"));
1667  limitations->Add(new SettingEntry("vehicle.max_trains"));
1668  limitations->Add(new SettingEntry("vehicle.max_roadveh"));
1669  limitations->Add(new SettingEntry("vehicle.max_aircraft"));
1670  limitations->Add(new SettingEntry("vehicle.max_ships"));
1671  limitations->Add(new SettingEntry("vehicle.max_train_length"));
1672  limitations->Add(new SettingEntry("station.station_spread"));
1673  limitations->Add(new SettingEntry("station.distant_join_stations"));
1674  limitations->Add(new SettingEntry("construction.road_stop_on_town_road"));
1675  limitations->Add(new SettingEntry("construction.road_stop_on_competitor_road"));
1676  limitations->Add(new SettingEntry("vehicle.disable_elrails"));
1677  }
1678 
1679  SettingsPage *disasters = main->Add(new SettingsPage(STR_CONFIG_SETTING_ACCIDENTS));
1680  {
1681  disasters->Add(new SettingEntry("difficulty.disasters"));
1682  disasters->Add(new SettingEntry("difficulty.economy"));
1683  disasters->Add(new SettingEntry("difficulty.vehicle_breakdowns"));
1684  disasters->Add(new SettingEntry("vehicle.plane_crashes"));
1685  }
1686 
1687  SettingsPage *genworld = main->Add(new SettingsPage(STR_CONFIG_SETTING_GENWORLD));
1688  {
1689  genworld->Add(new SettingEntry("game_creation.landscape"));
1690  genworld->Add(new SettingEntry("game_creation.land_generator"));
1691  genworld->Add(new SettingEntry("difficulty.terrain_type"));
1692  genworld->Add(new SettingEntry("game_creation.tgen_smoothness"));
1693  genworld->Add(new SettingEntry("game_creation.variety"));
1694  genworld->Add(new SettingEntry("game_creation.snow_line_height"));
1695  genworld->Add(new SettingEntry("game_creation.amount_of_rivers"));
1696  genworld->Add(new SettingEntry("game_creation.tree_placer"));
1697  genworld->Add(new SettingEntry("vehicle.road_side"));
1698  genworld->Add(new SettingEntry("economy.larger_towns"));
1699  genworld->Add(new SettingEntry("economy.initial_city_size"));
1700  genworld->Add(new SettingEntry("economy.town_layout"));
1701  genworld->Add(new SettingEntry("difficulty.industry_density"));
1702  genworld->Add(new SettingEntry("gui.pause_on_newgame"));
1703  genworld->Add(new SettingEntry("game_creation.ending_year"));
1704  }
1705 
1706  SettingsPage *environment = main->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT));
1707  {
1708  SettingsPage *authorities = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_AUTHORITIES));
1709  {
1710  authorities->Add(new SettingEntry("difficulty.town_council_tolerance"));
1711  authorities->Add(new SettingEntry("economy.bribe"));
1712  authorities->Add(new SettingEntry("economy.exclusive_rights"));
1713  authorities->Add(new SettingEntry("economy.fund_roads"));
1714  authorities->Add(new SettingEntry("economy.fund_buildings"));
1715  authorities->Add(new SettingEntry("economy.station_noise_level"));
1716  }
1717 
1718  SettingsPage *towns = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_TOWNS));
1719  {
1720  towns->Add(new SettingEntry("economy.town_growth_rate"));
1721  towns->Add(new SettingEntry("economy.allow_town_roads"));
1722  towns->Add(new SettingEntry("economy.allow_town_level_crossings"));
1723  towns->Add(new SettingEntry("economy.found_town"));
1724  towns->Add(new SettingEntry("economy.town_cargogen_mode"));
1725  }
1726 
1727  SettingsPage *industries = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_INDUSTRIES));
1728  {
1729  industries->Add(new SettingEntry("construction.raw_industry_construction"));
1730  industries->Add(new SettingEntry("construction.industry_platform"));
1731  industries->Add(new SettingEntry("economy.multiple_industry_per_town"));
1732  industries->Add(new SettingEntry("game_creation.oil_refinery_limit"));
1733  industries->Add(new SettingEntry("economy.smooth_economy"));
1734  industries->Add(new SettingEntry("station.serve_neutral_industries"));
1735  }
1736 
1737  SettingsPage *cdist = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_CARGODIST));
1738  {
1739  cdist->Add(new SettingEntry("linkgraph.recalc_time"));
1740  cdist->Add(new SettingEntry("linkgraph.recalc_interval"));
1741  cdist->Add(new SettingEntry("linkgraph.distribution_pax"));
1742  cdist->Add(new SettingEntry("linkgraph.distribution_mail"));
1743  cdist->Add(new SettingEntry("linkgraph.distribution_armoured"));
1744  cdist->Add(new SettingEntry("linkgraph.distribution_default"));
1745  cdist->Add(new SettingEntry("linkgraph.accuracy"));
1746  cdist->Add(new SettingEntry("linkgraph.demand_distance"));
1747  cdist->Add(new SettingEntry("linkgraph.demand_size"));
1748  cdist->Add(new SettingEntry("linkgraph.short_path_saturation"));
1749  }
1750 
1751  environment->Add(new SettingEntry("station.modified_catchment"));
1752  environment->Add(new SettingEntry("construction.extra_tree_placement"));
1753  }
1754 
1755  SettingsPage *ai = main->Add(new SettingsPage(STR_CONFIG_SETTING_AI));
1756  {
1757  SettingsPage *npc = ai->Add(new SettingsPage(STR_CONFIG_SETTING_AI_NPC));
1758  {
1759  npc->Add(new SettingEntry("script.settings_profile"));
1760  npc->Add(new SettingEntry("script.script_max_opcode_till_suspend"));
1761  npc->Add(new SettingEntry("script.script_max_memory_megabytes"));
1762  npc->Add(new SettingEntry("difficulty.competitor_speed"));
1763  npc->Add(new SettingEntry("ai.ai_in_multiplayer"));
1764  npc->Add(new SettingEntry("ai.ai_disable_veh_train"));
1765  npc->Add(new SettingEntry("ai.ai_disable_veh_roadveh"));
1766  npc->Add(new SettingEntry("ai.ai_disable_veh_aircraft"));
1767  npc->Add(new SettingEntry("ai.ai_disable_veh_ship"));
1768  }
1769 
1770  ai->Add(new SettingEntry("economy.give_money"));
1771  ai->Add(new SettingEntry("economy.allow_shares"));
1772  ai->Add(new SettingEntry("economy.min_years_for_shares"));
1773  }
1774 
1775  main->Init();
1776  }
1777  return *main;
1778 }
1779 
1780 static const StringID _game_settings_restrict_dropdown[] = {
1781  STR_CONFIG_SETTING_RESTRICT_BASIC, // RM_BASIC
1782  STR_CONFIG_SETTING_RESTRICT_ADVANCED, // RM_ADVANCED
1783  STR_CONFIG_SETTING_RESTRICT_ALL, // RM_ALL
1784  STR_CONFIG_SETTING_RESTRICT_CHANGED_AGAINST_DEFAULT, // RM_CHANGED_AGAINST_DEFAULT
1785  STR_CONFIG_SETTING_RESTRICT_CHANGED_AGAINST_NEW, // RM_CHANGED_AGAINST_NEW
1786 };
1787 assert_compile(lengthof(_game_settings_restrict_dropdown) == RM_END);
1788 
1795 };
1796 
1799  static const int SETTINGTREE_LEFT_OFFSET = 5;
1800  static const int SETTINGTREE_RIGHT_OFFSET = 5;
1801  static const int SETTINGTREE_TOP_OFFSET = 5;
1802  static const int SETTINGTREE_BOTTOM_OFFSET = 5;
1803 
1805 
1811 
1817 
1818  Scrollbar *vscroll;
1819 
1820  GameSettingsWindow(WindowDesc *desc) : Window(desc), filter_editbox(50)
1821  {
1822  this->warn_missing = WHR_NONE;
1823  this->warn_lines = 0;
1825  this->filter.min_cat = RM_ALL;
1826  this->filter.type = ST_ALL;
1827  this->filter.type_hides = false;
1828  this->settings_ptr = &GetGameSettings();
1829 
1830  _circle_size = maxdim(GetSpriteSize(SPR_CIRCLE_FOLDED), GetSpriteSize(SPR_CIRCLE_UNFOLDED));
1831  GetSettingsTree().FoldAll(); // Close all sub-pages
1832 
1833  this->valuewindow_entry = nullptr; // No setting entry for which a entry window is opened
1834  this->clicked_entry = nullptr; // No numeric setting buttons are depressed
1835  this->last_clicked = nullptr;
1836  this->valuedropdown_entry = nullptr;
1837  this->closing_dropdown = false;
1838  this->manually_changed_folding = false;
1839 
1840  this->CreateNestedTree();
1841  this->vscroll = this->GetScrollbar(WID_GS_SCROLLBAR);
1843 
1844  this->querystrings[WID_GS_FILTER] = &this->filter_editbox;
1845  this->filter_editbox.cancel_button = QueryString::ACTION_CLEAR;
1847 
1848  this->InvalidateData();
1849  }
1850 
1851  void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override
1852  {
1853  switch (widget) {
1854  case WID_GS_OPTIONSPANEL:
1855  resize->height = SETTING_HEIGHT = max(max<int>(_circle_size.height, SETTING_BUTTON_HEIGHT), FONT_HEIGHT_NORMAL) + 1;
1856  resize->width = 1;
1857 
1858  size->height = 5 * resize->height + SETTINGTREE_TOP_OFFSET + SETTINGTREE_BOTTOM_OFFSET;
1859  break;
1860 
1861  case WID_GS_HELP_TEXT: {
1862  static const StringID setting_types[] = {
1863  STR_CONFIG_SETTING_TYPE_CLIENT,
1864  STR_CONFIG_SETTING_TYPE_COMPANY_MENU, STR_CONFIG_SETTING_TYPE_COMPANY_INGAME,
1865  STR_CONFIG_SETTING_TYPE_GAME_MENU, STR_CONFIG_SETTING_TYPE_GAME_INGAME,
1866  };
1867  for (uint i = 0; i < lengthof(setting_types); i++) {
1868  SetDParam(0, setting_types[i]);
1869  size->width = max(size->width, GetStringBoundingBox(STR_CONFIG_SETTING_TYPE).width);
1870  }
1871  size->height = 2 * FONT_HEIGHT_NORMAL + WD_PAR_VSEP_NORMAL +
1872  max(size->height, GetSettingsTree().GetMaxHelpHeight(size->width));
1873  break;
1874  }
1875 
1877  case WID_GS_RESTRICT_TYPE:
1878  size->width = max(GetStringBoundingBox(STR_CONFIG_SETTING_RESTRICT_CATEGORY).width, GetStringBoundingBox(STR_CONFIG_SETTING_RESTRICT_TYPE).width);
1879  break;
1880 
1881  default:
1882  break;
1883  }
1884  }
1885 
1886  void OnPaint() override
1887  {
1888  if (this->closing_dropdown) {
1889  this->closing_dropdown = false;
1890  assert(this->valuedropdown_entry != nullptr);
1891  this->valuedropdown_entry->SetButtons(0);
1892  this->valuedropdown_entry = nullptr;
1893  }
1894 
1895  /* Reserve the correct number of lines for the 'some search results are hidden' notice in the central settings display panel. */
1896  const NWidgetBase *panel = this->GetWidget<NWidgetBase>(WID_GS_OPTIONSPANEL);
1897  StringID warn_str = STR_CONFIG_SETTING_CATEGORY_HIDES - 1 + this->warn_missing;
1898  int new_warn_lines;
1899  if (this->warn_missing == WHR_NONE) {
1900  new_warn_lines = 0;
1901  } else {
1902  SetDParam(0, _game_settings_restrict_dropdown[this->filter.min_cat]);
1903  new_warn_lines = GetStringLineCount(warn_str, panel->current_x);
1904  }
1905  if (this->warn_lines != new_warn_lines) {
1906  this->vscroll->SetCount(this->vscroll->GetCount() - this->warn_lines + new_warn_lines);
1907  this->warn_lines = new_warn_lines;
1908  }
1909 
1910  this->DrawWidgets();
1911 
1912  /* Draw the 'some search results are hidden' notice. */
1913  if (this->warn_missing != WHR_NONE) {
1914  const int left = panel->pos_x;
1915  const int right = left + panel->current_x - 1;
1916  const int top = panel->pos_y + WD_FRAMETEXT_TOP + (SETTING_HEIGHT - FONT_HEIGHT_NORMAL) * this->warn_lines / 2;
1917  SetDParam(0, _game_settings_restrict_dropdown[this->filter.min_cat]);
1918  if (this->warn_lines == 1) {
1919  /* If the warning fits at one line, center it. */
1920  DrawString(left + WD_FRAMETEXT_LEFT, right - WD_FRAMETEXT_RIGHT, top, warn_str, TC_FROMSTRING, SA_HOR_CENTER);
1921  } else {
1922  DrawStringMultiLine(left + WD_FRAMERECT_LEFT, right - WD_FRAMERECT_RIGHT, top, INT32_MAX, warn_str, TC_FROMSTRING, SA_HOR_CENTER);
1923  }
1924  }
1925  }
1926 
1927  void SetStringParameters(int widget) const override
1928  {
1929  switch (widget) {
1931  SetDParam(0, _game_settings_restrict_dropdown[this->filter.mode]);
1932  break;
1933 
1934  case WID_GS_TYPE_DROPDOWN:
1935  switch (this->filter.type) {
1936  case ST_GAME: SetDParam(0, _game_mode == GM_MENU ? STR_CONFIG_SETTING_TYPE_DROPDOWN_GAME_MENU : STR_CONFIG_SETTING_TYPE_DROPDOWN_GAME_INGAME); break;
1937  case ST_COMPANY: SetDParam(0, _game_mode == GM_MENU ? STR_CONFIG_SETTING_TYPE_DROPDOWN_COMPANY_MENU : STR_CONFIG_SETTING_TYPE_DROPDOWN_COMPANY_INGAME); break;
1938  case ST_CLIENT: SetDParam(0, STR_CONFIG_SETTING_TYPE_DROPDOWN_CLIENT); break;
1939  default: SetDParam(0, STR_CONFIG_SETTING_TYPE_DROPDOWN_ALL); break;
1940  }
1941  break;
1942  }
1943  }
1944 
1945  DropDownList BuildDropDownList(int widget) const
1946  {
1947  DropDownList list;
1948  switch (widget) {
1950  for (int mode = 0; mode != RM_END; mode++) {
1951  /* If we are in adv. settings screen for the new game's settings,
1952  * we don't want to allow comparing with new game's settings. */
1953  bool disabled = mode == RM_CHANGED_AGAINST_NEW && settings_ptr == &_settings_newgame;
1954 
1955  list.emplace_back(new DropDownListStringItem(_game_settings_restrict_dropdown[mode], mode, disabled));
1956  }
1957  break;
1958 
1959  case WID_GS_TYPE_DROPDOWN:
1960  list.emplace_back(new DropDownListStringItem(STR_CONFIG_SETTING_TYPE_DROPDOWN_ALL, ST_ALL, false));
1961  list.emplace_back(new DropDownListStringItem(_game_mode == GM_MENU ? STR_CONFIG_SETTING_TYPE_DROPDOWN_GAME_MENU : STR_CONFIG_SETTING_TYPE_DROPDOWN_GAME_INGAME, ST_GAME, false));
1962  list.emplace_back(new DropDownListStringItem(_game_mode == GM_MENU ? STR_CONFIG_SETTING_TYPE_DROPDOWN_COMPANY_MENU : STR_CONFIG_SETTING_TYPE_DROPDOWN_COMPANY_INGAME, ST_COMPANY, false));
1963  list.emplace_back(new DropDownListStringItem(STR_CONFIG_SETTING_TYPE_DROPDOWN_CLIENT, ST_CLIENT, false));
1964  break;
1965  }
1966  return list;
1967  }
1968 
1969  void DrawWidget(const Rect &r, int widget) const override
1970  {
1971  switch (widget) {
1972  case WID_GS_OPTIONSPANEL: {
1973  int top_pos = r.top + SETTINGTREE_TOP_OFFSET + 1 + this->warn_lines * SETTING_HEIGHT;
1974  uint last_row = this->vscroll->GetPosition() + this->vscroll->GetCapacity() - this->warn_lines;
1975  int next_row = GetSettingsTree().Draw(settings_ptr, r.left + SETTINGTREE_LEFT_OFFSET, r.right - SETTINGTREE_RIGHT_OFFSET, top_pos,
1976  this->vscroll->GetPosition(), last_row, this->last_clicked);
1977  if (next_row == 0) DrawString(r.left + SETTINGTREE_LEFT_OFFSET, r.right - SETTINGTREE_RIGHT_OFFSET, top_pos, STR_CONFIG_SETTINGS_NONE);
1978  break;
1979  }
1980 
1981  case WID_GS_HELP_TEXT:
1982  if (this->last_clicked != nullptr) {
1983  const SettingDesc *sd = this->last_clicked->setting;
1984 
1985  int y = r.top;
1986  switch (sd->GetType()) {
1987  case ST_COMPANY: SetDParam(0, _game_mode == GM_MENU ? STR_CONFIG_SETTING_TYPE_COMPANY_MENU : STR_CONFIG_SETTING_TYPE_COMPANY_INGAME); break;
1988  case ST_CLIENT: SetDParam(0, STR_CONFIG_SETTING_TYPE_CLIENT); break;
1989  case ST_GAME: SetDParam(0, _game_mode == GM_MENU ? STR_CONFIG_SETTING_TYPE_GAME_MENU : STR_CONFIG_SETTING_TYPE_GAME_INGAME); break;
1990  default: NOT_REACHED();
1991  }
1992  DrawString(r.left, r.right, y, STR_CONFIG_SETTING_TYPE);
1993  y += FONT_HEIGHT_NORMAL;
1994 
1995  int32 default_value = ReadValue(&sd->desc.def, sd->save.conv);
1996  this->last_clicked->SetValueDParams(0, default_value);
1997  DrawString(r.left, r.right, y, STR_CONFIG_SETTING_DEFAULT_VALUE);
1999 
2000  DrawStringMultiLine(r.left, r.right, y, r.bottom, this->last_clicked->GetHelpText(), TC_WHITE);
2001  }
2002  break;
2003 
2004  default:
2005  break;
2006  }
2007  }
2008 
2014  {
2015  if (this->last_clicked != pe) this->SetDirty();
2016  this->last_clicked = pe;
2017  }
2018 
2019  void OnClick(Point pt, int widget, int click_count) override
2020  {
2021  switch (widget) {
2022  case WID_GS_EXPAND_ALL:
2023  this->manually_changed_folding = true;
2025  this->InvalidateData();
2026  break;
2027 
2028  case WID_GS_COLLAPSE_ALL:
2029  this->manually_changed_folding = true;
2031  this->InvalidateData();
2032  break;
2033 
2034  case WID_GS_RESTRICT_DROPDOWN: {
2035  DropDownList list = this->BuildDropDownList(widget);
2036  if (!list.empty()) {
2037  ShowDropDownList(this, std::move(list), this->filter.mode, widget);
2038  }
2039  break;
2040  }
2041 
2042  case WID_GS_TYPE_DROPDOWN: {
2043  DropDownList list = this->BuildDropDownList(widget);
2044  if (!list.empty()) {
2045  ShowDropDownList(this, std::move(list), this->filter.type, widget);
2046  }
2047  break;
2048  }
2049  }
2050 
2051  if (widget != WID_GS_OPTIONSPANEL) return;
2052 
2053  uint btn = this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_GS_OPTIONSPANEL, SETTINGTREE_TOP_OFFSET);
2054  if (btn == INT_MAX || (int)btn < this->warn_lines) return;
2055  btn -= this->warn_lines;
2056 
2057  uint cur_row = 0;
2058  BaseSettingEntry *clicked_entry = GetSettingsTree().FindEntry(btn, &cur_row);
2059 
2060  if (clicked_entry == nullptr) return; // Clicked below the last setting of the page
2061 
2062  int x = (_current_text_dir == TD_RTL ? this->width - 1 - pt.x : pt.x) - SETTINGTREE_LEFT_OFFSET - (clicked_entry->level + 1) * LEVEL_WIDTH; // Shift x coordinate
2063  if (x < 0) return; // Clicked left of the entry
2064 
2065  SettingsPage *clicked_page = dynamic_cast<SettingsPage*>(clicked_entry);
2066  if (clicked_page != nullptr) {
2067  this->SetDisplayedHelpText(nullptr);
2068  clicked_page->folded = !clicked_page->folded; // Flip 'folded'-ness of the sub-page
2069 
2070  this->manually_changed_folding = true;
2071 
2072  this->InvalidateData();
2073  return;
2074  }
2075 
2076  SettingEntry *pe = dynamic_cast<SettingEntry*>(clicked_entry);
2077  assert(pe != nullptr);
2078  const SettingDesc *sd = pe->setting;
2079 
2080  /* return if action is only active in network, or only settable by server */
2081  if (!sd->IsEditable()) {
2082  this->SetDisplayedHelpText(pe);
2083  return;
2084  }
2085 
2086  const void *var = ResolveVariableAddress(settings_ptr, sd);
2087  int32 value = (int32)ReadValue(var, sd->save.conv);
2088 
2089  /* clicked on the icon on the left side. Either scroller, bool on/off or dropdown */
2090  if (x < SETTING_BUTTON_WIDTH && (sd->desc.flags & SGF_MULTISTRING)) {
2091  const SettingDescBase *sdb = &sd->desc;
2092  this->SetDisplayedHelpText(pe);
2093 
2094  if (this->valuedropdown_entry == pe) {
2095  /* unclick the dropdown */
2096  HideDropDownMenu(this);
2097  this->closing_dropdown = false;
2098  this->valuedropdown_entry->SetButtons(0);
2099  this->valuedropdown_entry = nullptr;
2100  } else {
2101  if (this->valuedropdown_entry != nullptr) this->valuedropdown_entry->SetButtons(0);
2102  this->closing_dropdown = false;
2103 
2104  const NWidgetBase *wid = this->GetWidget<NWidgetBase>(WID_GS_OPTIONSPANEL);
2105  int rel_y = (pt.y - (int)wid->pos_y - SETTINGTREE_TOP_OFFSET) % wid->resize_y;
2106 
2107  Rect wi_rect;
2108  wi_rect.left = pt.x - (_current_text_dir == TD_RTL ? SETTING_BUTTON_WIDTH - 1 - x : x);
2109  wi_rect.right = wi_rect.left + SETTING_BUTTON_WIDTH - 1;
2110  wi_rect.top = pt.y - rel_y + (SETTING_HEIGHT - SETTING_BUTTON_HEIGHT) / 2;
2111  wi_rect.bottom = wi_rect.top + SETTING_BUTTON_HEIGHT - 1;
2112 
2113  /* For dropdowns we also have to check the y position thoroughly, the mouse may not above the just opening dropdown */
2114  if (pt.y >= wi_rect.top && pt.y <= wi_rect.bottom) {
2115  this->valuedropdown_entry = pe;
2116  this->valuedropdown_entry->SetButtons(SEF_LEFT_DEPRESSED);
2117 
2118  DropDownList list;
2119  for (int i = sdb->min; i <= (int)sdb->max; i++) {
2120  list.emplace_back(new DropDownListStringItem(sdb->str_val + i - sdb->min, i, false));
2121  }
2122 
2123  ShowDropDownListAt(this, std::move(list), value, -1, wi_rect, COLOUR_ORANGE, true);
2124  }
2125  }
2126  this->SetDirty();
2127  } else if (x < SETTING_BUTTON_WIDTH) {
2128  this->SetDisplayedHelpText(pe);
2129  const SettingDescBase *sdb = &sd->desc;
2130  int32 oldvalue = value;
2131 
2132  switch (sdb->cmd) {
2133  case SDT_BOOLX: value ^= 1; break;
2134  case SDT_ONEOFMANY:
2135  case SDT_NUMX: {
2136  /* Add a dynamic step-size to the scroller. In a maximum of
2137  * 50-steps you should be able to get from min to max,
2138  * unless specified otherwise in the 'interval' variable
2139  * of the current setting. */
2140  uint32 step = (sdb->interval == 0) ? ((sdb->max - sdb->min) / 50) : sdb->interval;
2141  if (step == 0) step = 1;
2142 
2143  /* don't allow too fast scrolling */
2144  if ((this->flags & WF_TIMEOUT) && this->timeout_timer > 1) {
2145  _left_button_clicked = false;
2146  return;
2147  }
2148 
2149  /* Increase or decrease the value and clamp it to extremes */
2150  if (x >= SETTING_BUTTON_WIDTH / 2) {
2151  value += step;
2152  if (sdb->min < 0) {
2153  assert((int32)sdb->max >= 0);
2154  if (value > (int32)sdb->max) value = (int32)sdb->max;
2155  } else {
2156  if ((uint32)value > sdb->max) value = (int32)sdb->max;
2157  }
2158  if (value < sdb->min) value = sdb->min; // skip between "disabled" and minimum
2159  } else {
2160  value -= step;
2161  if (value < sdb->min) value = (sdb->flags & SGF_0ISDISABLED) ? 0 : sdb->min;
2162  }
2163 
2164  /* Set up scroller timeout for numeric values */
2165  if (value != oldvalue) {
2166  if (this->clicked_entry != nullptr) { // Release previous buttons if any
2167  this->clicked_entry->SetButtons(0);
2168  }
2169  this->clicked_entry = pe;
2170  this->clicked_entry->SetButtons((x >= SETTING_BUTTON_WIDTH / 2) != (_current_text_dir == TD_RTL) ? SEF_RIGHT_DEPRESSED : SEF_LEFT_DEPRESSED);
2171  this->SetTimeout();
2172  _left_button_clicked = false;
2173  }
2174  break;
2175  }
2176 
2177  default: NOT_REACHED();
2178  }
2179 
2180  if (value != oldvalue) {
2181  if ((sd->desc.flags & SGF_PER_COMPANY) != 0) {
2182  SetCompanySetting(pe->index, value);
2183  } else {
2184  SetSettingValue(pe->index, value);
2185  }
2186  this->SetDirty();
2187  }
2188  } else {
2189  /* Only open editbox if clicked for the second time, and only for types where it is sensible for. */
2190  if (this->last_clicked == pe && sd->desc.cmd != SDT_BOOLX && !(sd->desc.flags & SGF_MULTISTRING)) {
2191  /* Show the correct currency-translated value */
2192  if (sd->desc.flags & SGF_CURRENCY) value *= _currency->rate;
2193 
2194  this->valuewindow_entry = pe;
2195  SetDParam(0, value);
2196  ShowQueryString(STR_JUST_INT, STR_CONFIG_SETTING_QUERY_CAPTION, 10, this, CS_NUMERAL, QSF_ENABLE_DEFAULT);
2197  }
2198  this->SetDisplayedHelpText(pe);
2199  }
2200  }
2201 
2202  void OnTimeout() override
2203  {
2204  if (this->clicked_entry != nullptr) { // On timeout, release any depressed buttons
2205  this->clicked_entry->SetButtons(0);
2206  this->clicked_entry = nullptr;
2207  this->SetDirty();
2208  }
2209  }
2210 
2211  void OnQueryTextFinished(char *str) override
2212  {
2213  /* The user pressed cancel */
2214  if (str == nullptr) return;
2215 
2216  assert(this->valuewindow_entry != nullptr);
2217  const SettingDesc *sd = this->valuewindow_entry->setting;
2218 
2219  int32 value;
2220  if (!StrEmpty(str)) {
2221  value = atoi(str);
2222 
2223  /* Save the correct currency-translated value */
2224  if (sd->desc.flags & SGF_CURRENCY) value /= _currency->rate;
2225  } else {
2226  value = (int32)(size_t)sd->desc.def;
2227  }
2228 
2229  if ((sd->desc.flags & SGF_PER_COMPANY) != 0) {
2230  SetCompanySetting(this->valuewindow_entry->index, value);
2231  } else {
2232  SetSettingValue(this->valuewindow_entry->index, value);
2233  }
2234  this->SetDirty();
2235  }
2236 
2237  void OnDropdownSelect(int widget, int index) override
2238  {
2239  switch (widget) {
2241  this->filter.mode = (RestrictionMode)index;
2242  if (this->filter.mode == RM_CHANGED_AGAINST_DEFAULT ||
2243  this->filter.mode == RM_CHANGED_AGAINST_NEW) {
2244 
2245  if (!this->manually_changed_folding) {
2246  /* Expand all when selecting 'changes'. Update the filter state first, in case it becomes less restrictive in some cases. */
2247  GetSettingsTree().UpdateFilterState(this->filter, false);
2249  }
2250  } else {
2251  /* Non-'changes' filter. Save as default. */
2253  }
2254  this->InvalidateData();
2255  break;
2256 
2257  case WID_GS_TYPE_DROPDOWN:
2258  this->filter.type = (SettingType)index;
2259  this->InvalidateData();
2260  break;
2261 
2262  default:
2263  if (widget < 0) {
2264  /* Deal with drop down boxes on the panel. */
2265  assert(this->valuedropdown_entry != nullptr);
2266  const SettingDesc *sd = this->valuedropdown_entry->setting;
2267  assert(sd->desc.flags & SGF_MULTISTRING);
2268 
2269  if ((sd->desc.flags & SGF_PER_COMPANY) != 0) {
2270  SetCompanySetting(this->valuedropdown_entry->index, index);
2271  } else {
2272  SetSettingValue(this->valuedropdown_entry->index, index);
2273  }
2274 
2275  this->SetDirty();
2276  }
2277  break;
2278  }
2279  }
2280 
2281  void OnDropdownClose(Point pt, int widget, int index, bool instant_close) override
2282  {
2283  if (widget >= 0) {
2284  /* Normally the default implementation of OnDropdownClose() takes care of
2285  * a few things. We want that behaviour here too, but only for
2286  * "normal" dropdown boxes. The special dropdown boxes added for every
2287  * setting that needs one can't have this call. */
2288  Window::OnDropdownClose(pt, widget, index, instant_close);
2289  } else {
2290  /* We cannot raise the dropdown button just yet. OnClick needs some hint, whether
2291  * the same dropdown button was clicked again, and then not open the dropdown again.
2292  * So, we only remember that it was closed, and process it on the next OnPaint, which is
2293  * after OnClick. */
2294  assert(this->valuedropdown_entry != nullptr);
2295  this->closing_dropdown = true;
2296  this->SetDirty();
2297  }
2298  }
2299 
2300  void OnInvalidateData(int data = 0, bool gui_scope = true) override
2301  {
2302  if (!gui_scope) return;
2303 
2304  /* Update which settings are to be visible. */
2305  RestrictionMode min_level = (this->filter.mode <= RM_ALL) ? this->filter.mode : RM_BASIC;
2306  this->filter.min_cat = min_level;
2307  this->filter.type_hides = false;
2308  GetSettingsTree().UpdateFilterState(this->filter, false);
2309 
2310  if (this->filter.string.IsEmpty()) {
2311  this->warn_missing = WHR_NONE;
2312  } else if (min_level < this->filter.min_cat) {
2313  this->warn_missing = this->filter.type_hides ? WHR_CATEGORY_TYPE : WHR_CATEGORY;
2314  } else {
2315  this->warn_missing = this->filter.type_hides ? WHR_TYPE : WHR_NONE;
2316  }
2317  this->vscroll->SetCount(GetSettingsTree().Length() + this->warn_lines);
2318 
2319  if (this->last_clicked != nullptr && !GetSettingsTree().IsVisible(this->last_clicked)) {
2320  this->SetDisplayedHelpText(nullptr);
2321  }
2322 
2323  bool all_folded = true;
2324  bool all_unfolded = true;
2325  GetSettingsTree().GetFoldingState(all_folded, all_unfolded);
2326  this->SetWidgetDisabledState(WID_GS_EXPAND_ALL, all_unfolded);
2327  this->SetWidgetDisabledState(WID_GS_COLLAPSE_ALL, all_folded);
2328  }
2329 
2330  void OnEditboxChanged(int wid) override
2331  {
2332  if (wid == WID_GS_FILTER) {
2333  this->filter.string.SetFilterTerm(this->filter_editbox.text.buf);
2334  if (!this->filter.string.IsEmpty() && !this->manually_changed_folding) {
2335  /* User never expanded/collapsed single pages and entered a filter term.
2336  * Expand everything, to save weird expand clicks, */
2338  }
2339  this->InvalidateData();
2340  }
2341  }
2342 
2343  void OnResize() override
2344  {
2345  this->vscroll->SetCapacityFromWidget(this, WID_GS_OPTIONSPANEL, SETTINGTREE_TOP_OFFSET + SETTINGTREE_BOTTOM_OFFSET);
2346  }
2347 };
2348 
2350 
2351 static const NWidgetPart _nested_settings_selection_widgets[] = {
2353  NWidget(WWT_CLOSEBOX, COLOUR_MAUVE),
2354  NWidget(WWT_CAPTION, COLOUR_MAUVE), SetDataTip(STR_CONFIG_SETTING_TREE_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
2355  NWidget(WWT_DEFSIZEBOX, COLOUR_MAUVE),
2356  EndContainer(),
2357  NWidget(WWT_PANEL, COLOUR_MAUVE),
2360  NWidget(WWT_TEXT, COLOUR_MAUVE, WID_GS_RESTRICT_CATEGORY), SetDataTip(STR_CONFIG_SETTING_RESTRICT_CATEGORY, STR_NULL),
2361  NWidget(WWT_DROPDOWN, COLOUR_MAUVE, WID_GS_RESTRICT_DROPDOWN), SetMinimalSize(100, 12), SetDataTip(STR_BLACK_STRING, STR_CONFIG_SETTING_RESTRICT_DROPDOWN_HELPTEXT), SetFill(1, 0), SetResize(1, 0),
2362  EndContainer(),
2364  NWidget(WWT_TEXT, COLOUR_MAUVE, WID_GS_RESTRICT_TYPE), SetDataTip(STR_CONFIG_SETTING_RESTRICT_TYPE, STR_NULL),
2365  NWidget(WWT_DROPDOWN, COLOUR_MAUVE, WID_GS_TYPE_DROPDOWN), SetMinimalSize(100, 12), SetDataTip(STR_BLACK_STRING, STR_CONFIG_SETTING_TYPE_DROPDOWN_HELPTEXT), SetFill(1, 0), SetResize(1, 0),
2366  EndContainer(),
2367  EndContainer(),
2370  NWidget(WWT_TEXT, COLOUR_MAUVE), SetFill(0, 1), SetDataTip(STR_CONFIG_SETTING_FILTER_TITLE, STR_NULL),
2371  NWidget(WWT_EDITBOX, COLOUR_MAUVE, WID_GS_FILTER), SetFill(1, 0), SetMinimalSize(50, 12), SetResize(1, 0),
2372  SetDataTip(STR_LIST_FILTER_OSKTITLE, STR_LIST_FILTER_TOOLTIP),
2373  EndContainer(),
2374  EndContainer(),
2377  NWidget(NWID_VSCROLLBAR, COLOUR_MAUVE, WID_GS_SCROLLBAR),
2378  EndContainer(),
2379  NWidget(WWT_PANEL, COLOUR_MAUVE), SetMinimalSize(400, 40),
2380  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_GS_HELP_TEXT), SetMinimalSize(300, 25), SetFill(1, 1), SetResize(1, 0),
2382  EndContainer(),
2384  NWidget(WWT_PUSHTXTBTN, COLOUR_MAUVE, WID_GS_EXPAND_ALL), SetDataTip(STR_CONFIG_SETTING_EXPAND_ALL, STR_NULL),
2385  NWidget(WWT_PUSHTXTBTN, COLOUR_MAUVE, WID_GS_COLLAPSE_ALL), SetDataTip(STR_CONFIG_SETTING_COLLAPSE_ALL, STR_NULL),
2386  NWidget(WWT_PANEL, COLOUR_MAUVE), SetFill(1, 0), SetResize(1, 0),
2387  EndContainer(),
2388  NWidget(WWT_RESIZEBOX, COLOUR_MAUVE),
2389  EndContainer(),
2390 };
2391 
2392 static WindowDesc _settings_selection_desc(
2393  WDP_CENTER, "settings", 510, 450,
2395  0,
2396  _nested_settings_selection_widgets, lengthof(_nested_settings_selection_widgets)
2397 );
2398 
2401 {
2403  new GameSettingsWindow(&_settings_selection_desc);
2404 }
2405 
2406 
2416 void DrawArrowButtons(int x, int y, Colours button_colour, byte state, bool clickable_left, bool clickable_right)
2417 {
2418  int colour = _colour_gradient[button_colour][2];
2419  Dimension dim = NWidgetScrollbar::GetHorizontalDimension();
2420 
2421  DrawFrameRect(x, y, x + dim.width - 1, y + dim.height - 1, button_colour, (state == 1) ? FR_LOWERED : FR_NONE);
2422  DrawFrameRect(x + dim.width, y, x + dim.width + dim.width - 1, y + dim.height - 1, button_colour, (state == 2) ? FR_LOWERED : FR_NONE);
2423  DrawSprite(SPR_ARROW_LEFT, PAL_NONE, x + WD_IMGBTN_LEFT, y + WD_IMGBTN_TOP);
2424  DrawSprite(SPR_ARROW_RIGHT, PAL_NONE, x + WD_IMGBTN_LEFT + dim.width, y + WD_IMGBTN_TOP);
2425 
2426  /* Grey out the buttons that aren't clickable */
2427  bool rtl = _current_text_dir == TD_RTL;
2428  if (rtl ? !clickable_right : !clickable_left) {
2429  GfxFillRect(x + 1, y, x + dim.width - 1, y + dim.height - 2, colour, FILLRECT_CHECKER);
2430  }
2431  if (rtl ? !clickable_left : !clickable_right) {
2432  GfxFillRect(x + dim.width + 1, y, x + dim.width + dim.width - 1, y + dim.height - 2, colour, FILLRECT_CHECKER);
2433  }
2434 }
2435 
2444 void DrawDropDownButton(int x, int y, Colours button_colour, bool state, bool clickable)
2445 {
2446  int colour = _colour_gradient[button_colour][2];
2447 
2448  DrawFrameRect(x, y, x + SETTING_BUTTON_WIDTH - 1, y + SETTING_BUTTON_HEIGHT - 1, button_colour, state ? FR_LOWERED : FR_NONE);
2449  DrawSprite(SPR_ARROW_DOWN, PAL_NONE, x + (SETTING_BUTTON_WIDTH - NWidgetScrollbar::GetVerticalDimension().width) / 2 + state, y + 2 + state);
2450 
2451  if (!clickable) {
2452  GfxFillRect(x + 1, y, x + SETTING_BUTTON_WIDTH - 1, y + SETTING_BUTTON_HEIGHT - 2, colour, FILLRECT_CHECKER);
2453  }
2454 }
2455 
2463 void DrawBoolButton(int x, int y, bool state, bool clickable)
2464 {
2465  static const Colours _bool_ctabs[2][2] = {{COLOUR_CREAM, COLOUR_RED}, {COLOUR_DARK_GREEN, COLOUR_GREEN}};
2466  DrawFrameRect(x, y, x + SETTING_BUTTON_WIDTH - 1, y + SETTING_BUTTON_HEIGHT - 1, _bool_ctabs[state][clickable], state ? FR_LOWERED : FR_NONE);
2467 }
2468 
2470  int query_widget;
2471 
2472  CustomCurrencyWindow(WindowDesc *desc) : Window(desc)
2473  {
2474  this->InitNested();
2475 
2476  SetButtonState();
2477  }
2478 
2479  void SetButtonState()
2480  {
2481  this->SetWidgetDisabledState(WID_CC_RATE_DOWN, _custom_currency.rate == 1);
2482  this->SetWidgetDisabledState(WID_CC_RATE_UP, _custom_currency.rate == UINT16_MAX);
2483  this->SetWidgetDisabledState(WID_CC_YEAR_DOWN, _custom_currency.to_euro == CF_NOEURO);
2484  this->SetWidgetDisabledState(WID_CC_YEAR_UP, _custom_currency.to_euro == MAX_YEAR);
2485  }
2486 
2487  void SetStringParameters(int widget) const override
2488  {
2489  switch (widget) {
2490  case WID_CC_RATE: SetDParam(0, 1); SetDParam(1, 1); break;
2491  case WID_CC_SEPARATOR: SetDParamStr(0, _custom_currency.separator); break;
2492  case WID_CC_PREFIX: SetDParamStr(0, _custom_currency.prefix); break;
2493  case WID_CC_SUFFIX: SetDParamStr(0, _custom_currency.suffix); break;
2494  case WID_CC_YEAR:
2495  SetDParam(0, (_custom_currency.to_euro != CF_NOEURO) ? STR_CURRENCY_SWITCH_TO_EURO : STR_CURRENCY_SWITCH_TO_EURO_NEVER);
2496  SetDParam(1, _custom_currency.to_euro);
2497  break;
2498 
2499  case WID_CC_PREVIEW:
2500  SetDParam(0, 10000);
2501  break;
2502  }
2503  }
2504 
2505  void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override
2506  {
2507  switch (widget) {
2508  /* Set the appropriate width for the edit 'buttons' */
2509  case WID_CC_SEPARATOR_EDIT:
2510  case WID_CC_PREFIX_EDIT:
2511  case WID_CC_SUFFIX_EDIT:
2512  size->width = this->GetWidget<NWidgetBase>(WID_CC_RATE_DOWN)->smallest_x + this->GetWidget<NWidgetBase>(WID_CC_RATE_UP)->smallest_x;
2513  break;
2514 
2515  /* Make sure the window is wide enough for the widest exchange rate */
2516  case WID_CC_RATE:
2517  SetDParam(0, 1);
2518  SetDParam(1, INT32_MAX);
2519  *size = GetStringBoundingBox(STR_CURRENCY_EXCHANGE_RATE);
2520  break;
2521  }
2522  }
2523 
2524  void OnClick(Point pt, int widget, int click_count) override
2525  {
2526  int line = 0;
2527  int len = 0;
2528  StringID str = 0;
2529  CharSetFilter afilter = CS_ALPHANUMERAL;
2530 
2531  switch (widget) {
2532  case WID_CC_RATE_DOWN:
2533  if (_custom_currency.rate > 1) _custom_currency.rate--;
2534  if (_custom_currency.rate == 1) this->DisableWidget(WID_CC_RATE_DOWN);
2536  break;
2537 
2538  case WID_CC_RATE_UP:
2539  if (_custom_currency.rate < UINT16_MAX) _custom_currency.rate++;
2540  if (_custom_currency.rate == UINT16_MAX) this->DisableWidget(WID_CC_RATE_UP);
2542  break;
2543 
2544  case WID_CC_RATE:
2545  SetDParam(0, _custom_currency.rate);
2546  str = STR_JUST_INT;
2547  len = 5;
2548  line = WID_CC_RATE;
2549  afilter = CS_NUMERAL;
2550  break;
2551 
2552  case WID_CC_SEPARATOR_EDIT:
2553  case WID_CC_SEPARATOR:
2554  SetDParamStr(0, _custom_currency.separator);
2555  str = STR_JUST_RAW_STRING;
2556  len = 1;
2557  line = WID_CC_SEPARATOR;
2558  break;
2559 
2560  case WID_CC_PREFIX_EDIT:
2561  case WID_CC_PREFIX:
2562  SetDParamStr(0, _custom_currency.prefix);
2563  str = STR_JUST_RAW_STRING;
2564  len = 12;
2565  line = WID_CC_PREFIX;
2566  break;
2567 
2568  case WID_CC_SUFFIX_EDIT:
2569  case WID_CC_SUFFIX:
2570  SetDParamStr(0, _custom_currency.suffix);
2571  str = STR_JUST_RAW_STRING;
2572  len = 12;
2573  line = WID_CC_SUFFIX;
2574  break;
2575 
2576  case WID_CC_YEAR_DOWN:
2577  _custom_currency.to_euro = (_custom_currency.to_euro <= 2000) ? CF_NOEURO : _custom_currency.to_euro - 1;
2578  if (_custom_currency.to_euro == CF_NOEURO) this->DisableWidget(WID_CC_YEAR_DOWN);
2580  break;
2581 
2582  case WID_CC_YEAR_UP:
2583  _custom_currency.to_euro = Clamp(_custom_currency.to_euro + 1, 2000, MAX_YEAR);
2584  if (_custom_currency.to_euro == MAX_YEAR) this->DisableWidget(WID_CC_YEAR_UP);
2586  break;
2587 
2588  case WID_CC_YEAR:
2589  SetDParam(0, _custom_currency.to_euro);
2590  str = STR_JUST_INT;
2591  len = 7;
2592  line = WID_CC_YEAR;
2593  afilter = CS_NUMERAL;
2594  break;
2595  }
2596 
2597  if (len != 0) {
2598  this->query_widget = line;
2599  ShowQueryString(str, STR_CURRENCY_CHANGE_PARAMETER, len + 1, this, afilter, QSF_NONE);
2600  }
2601 
2602  this->SetTimeout();
2603  this->SetDirty();
2604  }
2605 
2606  void OnQueryTextFinished(char *str) override
2607  {
2608  if (str == nullptr) return;
2609 
2610  switch (this->query_widget) {
2611  case WID_CC_RATE:
2612  _custom_currency.rate = Clamp(atoi(str), 1, UINT16_MAX);
2613  break;
2614 
2615  case WID_CC_SEPARATOR: // Thousands separator
2616  strecpy(_custom_currency.separator, str, lastof(_custom_currency.separator));
2617  break;
2618 
2619  case WID_CC_PREFIX:
2620  strecpy(_custom_currency.prefix, str, lastof(_custom_currency.prefix));
2621  break;
2622 
2623  case WID_CC_SUFFIX:
2624  strecpy(_custom_currency.suffix, str, lastof(_custom_currency.suffix));
2625  break;
2626 
2627  case WID_CC_YEAR: { // Year to switch to euro
2628  int val = atoi(str);
2629 
2630  _custom_currency.to_euro = (val < 2000 ? CF_NOEURO : min(val, MAX_YEAR));
2631  break;
2632  }
2633  }
2635  SetButtonState();
2636  }
2637 
2638  void OnTimeout() override
2639  {
2640  this->SetDirty();
2641  }
2642 };
2643 
2644 static const NWidgetPart _nested_cust_currency_widgets[] = {
2646  NWidget(WWT_CLOSEBOX, COLOUR_GREY),
2647  NWidget(WWT_CAPTION, COLOUR_GREY), SetDataTip(STR_CURRENCY_WINDOW, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
2648  EndContainer(),
2649  NWidget(WWT_PANEL, COLOUR_GREY),
2651  NWidget(NWID_HORIZONTAL), SetPIP(10, 0, 5),
2652  NWidget(WWT_PUSHARROWBTN, COLOUR_YELLOW, WID_CC_RATE_DOWN), SetDataTip(AWV_DECREASE, STR_CURRENCY_DECREASE_EXCHANGE_RATE_TOOLTIP),
2653  NWidget(WWT_PUSHARROWBTN, COLOUR_YELLOW, WID_CC_RATE_UP), SetDataTip(AWV_INCREASE, STR_CURRENCY_INCREASE_EXCHANGE_RATE_TOOLTIP),
2655  NWidget(WWT_TEXT, COLOUR_BLUE, WID_CC_RATE), SetDataTip(STR_CURRENCY_EXCHANGE_RATE, STR_CURRENCY_SET_EXCHANGE_RATE_TOOLTIP), SetFill(1, 0),
2656  EndContainer(),
2657  NWidget(NWID_HORIZONTAL), SetPIP(10, 0, 5),
2658  NWidget(WWT_PUSHBTN, COLOUR_DARK_BLUE, WID_CC_SEPARATOR_EDIT), SetDataTip(0x0, STR_CURRENCY_SET_CUSTOM_CURRENCY_SEPARATOR_TOOLTIP), SetFill(0, 1),
2660  NWidget(WWT_TEXT, COLOUR_BLUE, WID_CC_SEPARATOR), SetDataTip(STR_CURRENCY_SEPARATOR, STR_CURRENCY_SET_CUSTOM_CURRENCY_SEPARATOR_TOOLTIP), SetFill(1, 0),
2661  EndContainer(),
2662  NWidget(NWID_HORIZONTAL), SetPIP(10, 0, 5),
2663  NWidget(WWT_PUSHBTN, COLOUR_DARK_BLUE, WID_CC_PREFIX_EDIT), SetDataTip(0x0, STR_CURRENCY_SET_CUSTOM_CURRENCY_PREFIX_TOOLTIP), SetFill(0, 1),
2665  NWidget(WWT_TEXT, COLOUR_BLUE, WID_CC_PREFIX), SetDataTip(STR_CURRENCY_PREFIX, STR_CURRENCY_SET_CUSTOM_CURRENCY_PREFIX_TOOLTIP), SetFill(1, 0),
2666  EndContainer(),
2667  NWidget(NWID_HORIZONTAL), SetPIP(10, 0, 5),
2668  NWidget(WWT_PUSHBTN, COLOUR_DARK_BLUE, WID_CC_SUFFIX_EDIT), SetDataTip(0x0, STR_CURRENCY_SET_CUSTOM_CURRENCY_SUFFIX_TOOLTIP), SetFill(0, 1),
2670  NWidget(WWT_TEXT, COLOUR_BLUE, WID_CC_SUFFIX), SetDataTip(STR_CURRENCY_SUFFIX, STR_CURRENCY_SET_CUSTOM_CURRENCY_SUFFIX_TOOLTIP), SetFill(1, 0),
2671  EndContainer(),
2672  NWidget(NWID_HORIZONTAL), SetPIP(10, 0, 5),
2673  NWidget(WWT_PUSHARROWBTN, COLOUR_YELLOW, WID_CC_YEAR_DOWN), SetDataTip(AWV_DECREASE, STR_CURRENCY_DECREASE_CUSTOM_CURRENCY_TO_EURO_TOOLTIP),
2674  NWidget(WWT_PUSHARROWBTN, COLOUR_YELLOW, WID_CC_YEAR_UP), SetDataTip(AWV_INCREASE, STR_CURRENCY_INCREASE_CUSTOM_CURRENCY_TO_EURO_TOOLTIP),
2676  NWidget(WWT_TEXT, COLOUR_BLUE, WID_CC_YEAR), SetDataTip(STR_JUST_STRING, STR_CURRENCY_SET_CUSTOM_CURRENCY_TO_EURO_TOOLTIP), SetFill(1, 0),
2677  EndContainer(),
2678  EndContainer(),
2679  NWidget(WWT_LABEL, COLOUR_BLUE, WID_CC_PREVIEW),
2680  SetDataTip(STR_CURRENCY_PREVIEW, STR_CURRENCY_CUSTOM_CURRENCY_PREVIEW_TOOLTIP), SetPadding(15, 1, 18, 2),
2681  EndContainer(),
2682 };
2683 
2684 static WindowDesc _cust_currency_desc(
2685  WDP_CENTER, nullptr, 0, 0,
2687  0,
2688  _nested_cust_currency_widgets, lengthof(_nested_cust_currency_widgets)
2689 );
2690 
2692 static void ShowCustCurrency()
2693 {
2695  new CustomCurrencyWindow(&_cust_currency_desc);
2696 }
RestrictionMode mode
Filter based on category.
Currency dropdown.
Functions related to OTTD&#39;s strings.
End for iteration.
VehicleSettings vehicle
options for vehicles
Empty widget, place holder to reserve space in widget array.
Definition: widget_type.h:46
void OnInvalidateData(int data=0, bool gui_scope=true) override
Some data on this window has become invalid.
Dropdown for the GUI zoom level.
Definition of stuff that is very close to a company, like the company struct itself.
void CheckForMissingGlyphs(bool base_font, MissingGlyphSearcher *searcher)
Check whether the currently loaded language pack uses characters that the currently loaded font does ...
Definition: strings.cpp:2097
bool _networking
are we in networking mode?
Definition: network.cpp:52
const void * def
default value given when none is present
virtual bool IsVisible(const BaseSettingEntry *item) const
Check whether an entry is visible and not folded or filtered away.
bool IsFiltered() const
Check whether an entry is hidden due to filters.
Horizontally center the text.
Definition: gfx_func.h:95
ResizeInfo resize
Resize information.
Definition: window_gui.h:322
static NWidgetPart SetResize(int16 dx, int16 dy)
Widget part function for setting the resize step.
Definition: widget_type.h:928
Window(WindowDesc *desc)
Empty constructor, initialization has been moved to InitNested() called from the constructor of the d...
Definition: window.cpp:1870
uint Draw(GameSettings *settings_ptr, int left, int right, int y, uint first_row, uint max_row, BaseSettingEntry *selected, uint cur_row=0, uint parent_last=0) const
Draw a row in the settings panel.
void GfxFillRect(int left, int top, int right, int bottom, int colour, FillRectMode mode)
Applies a certain FillRectMode-operation to a rectangle [left, right] x [top, bottom] on the screen...
Definition: gfx.cpp:110
Rate of currency.
void SetWidgetDisabledState(byte widget_index, bool disab_stat)
Sets the enabled/disabled status of a widget.
Definition: window_gui.h:392
void OnEditboxChanged(int wid) override
The text in an editbox has been edited.
void SetWindowDirty(WindowClass cls, WindowNumber number)
Mark window as dirty (in need of repainting)
Definition: window.cpp:3218
int warn_lines
Number of lines used for warning about missing search results.
void SetWidgetLoweredState(byte widget_index, bool lowered_stat)
Sets the lowered/raised status of a widget.
Definition: window_gui.h:453
uint GetMaxHelpHeight(int maxw)
Get the biggest height of the help texts, if the width is at least maxw.
void SetTimeout()
Set the timeout flag of the window and initiate the timer.
Definition: window_gui.h:366
void OnClick(Point pt, int widget, int click_count) override
A click with the left mouse button has been made on the window.
Current suffix.
void OnInvalidateData(int data=0, bool gui_scope=true) override
Some data on this window has become invalid.
High level window description.
Definition: window_gui.h:166
Custom currency.
Definition: currency.h:56
void SetStringParameters(int widget) const override
Initialize string parameters for a widget.
WindowFlags flags
Window flags.
Definition: window_gui.h:310
int left
x position of left edge of the window
Definition: window_gui.h:317
bitmasked number where only ONE bit may be set
All settings together for the game.
void DrawWidgets() const
Paint all widgets of a window.
Definition: widget.cpp:602
void ChangeMusicSet(int index)
Change the configured music set and reset playback.
Definition: music_gui.cpp:433
static Titem * Get(size_t index)
Returns Titem with given index.
Definition: pool_type.hpp:329
Switch to game intro menu.
Definition: openttd.h:30
virtual void UnFoldAll()
Recursively open all (filtered) folds of sub-pages.
SettingsPage(StringID title)
Constructor for a sub-page in the &#39;advanced settings&#39; window.
Centered label.
Definition: widget_type.h:55
Scrollbar data structure.
Definition: widget_type.h:587
CurrencySpec _currency_specs[CURRENCY_END]
Array of currencies used by the system.
Definition: currency.cpp:71
Functions to handle different currencies.
virtual void Init(byte level=0)
Initialization of a setting entry.
int GetNumInvalid() const
Get the number of invalid files.
Data structure describing a single setting in a tab.
Of a numeric setting entry, the right button is depressed.
Normal amount of vertical space between two paragraphs of text.
Definition: window_gui.h:137
static T SetBit(T &x, const uint8 y)
Set a bit in a variable.
textfile; Window numbers:
Definition: window_type.h:180
Horizontal container.
Definition: widget_type.h:73
any number-type
void ResetState()
Reset the matching state to process a new item.
void UnFoldAll()
Recursively open all folds of sub-pages.
void SetMediaSet(int index)
Set the base media set.
byte _colour_gradient[COLOUR_END][8]
All 16 colour gradients 8 colours per gradient from darkest (0) to lightest (7)
Definition: gfx.cpp:52
Arrow to the right or in case of RTL to the left.
Definition: widget_type.h:36
Arrow to the left or in case of RTL to the right.
Definition: widget_type.h:35
Info about missing files etc.
void OnQueryTextFinished(char *str) override
The query window opened from this window has closed.
SettingGuiFlag flags
handles how a setting would show up in the GUI (text/currency, etc.)
Open base SFX readme, changelog (+1) or license (+2).
Open base music readme, changelog (+1) or license (+2).
bool GetState() const
Get the matching state of the current item.
void ShowQueryString(StringID str, StringID caption, uint maxsize, Window *parent, CharSetFilter afilter, QueryStringFlags flags)
Show a query popup window with a textbox in it.
Definition: misc_gui.cpp:1119
void OnClick(Point pt, int widget, int click_count) override
A click with the left mouse button has been made on the window.
Use to select a base music set.
Generic functions for replacing base data (graphics, sounds).
fluid_settings_t * settings
FluidSynth settings handle.
Definition: fluidsynth.cpp:21
Show only settings which are different compared to the user&#39;s new game setting values.
Up button.
#define SETBITS(x, y)
Sets several bits in a variable.
const LanguageMetadata * _current_language
The currently loaded language.
Definition: strings.cpp:46
Current separator.
void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override
Update size and resize step of a widget in the window.
bool closing_dropdown
True, if the dropdown list is currently closing.
static Dimension _circle_size
Dimension of the circle +/- icon. This is here as not all users are within the class of the settings ...
Separator edit button.
Panel widget containing the option lists.
a textbox for typing
Definition: widget_type.h:69
Resize box (normally at bottom-right of a window)
Definition: widget_type.h:66
static const int ACTION_CLEAR
Clear editbox.
static uint GetCurRes()
Get index of the current screen resolution.
NewGRF changelog.
Definition: textfile_type.h:18
Filter for settings list.
int top
y position of top edge of the window
Definition: window_gui.h:318
Header of Action 0F "universal holder" structure and functions.
Type setting filtered matches away.
int64 ReadValue(const void *ptr, VarType conv)
Return a signed-long version of the value of a setting.
Definition: saveload.cpp:755
the value represents a limited number of string-options (internally integer)
WarnHiddenResult
Warnings about hidden search results.
void SetButtons(byte new_val)
Set the button-depressed flags (SEF_LEFT_DEPRESSED and SEF_RIGHT_DEPRESSED) to a specified value...
WarnHiddenResult warn_missing
Whether and how to warn about missing search results.
void ShowErrorMessage(StringID summary_msg, StringID detailed_msg, WarningLevel wl, int x=0, int y=0, const GRFFile *textref_stack_grffile=nullptr, uint textref_stack_size=0, const uint32 *textref_stack=nullptr)
Display an error message in a window.
Definition: error_gui.cpp:380
void SetStringParameters(int widget) const override
Initialize string parameters for a widget.
Normal push-button (no toggle button) with custom drawing.
Definition: widget_type.h:101
int GetStringHeight(const char *str, int maxw, FontSize fontsize)
Calculates height of string (in pixels).
Definition: gfx.cpp:685
The drop down box to choose client/game/company/all settings.
LanguageList _languages
The actual list of language meta data.
Definition: strings.cpp:45
Close box (at top-left of a window)
Definition: widget_type.h:67
Window to edit settings of the game.
Properties of config file settings.
uint Length() const
Return number of rows needed to display the whole page.
Settings displayed in the list of basic settings.
Dropdown to select the road side (to set the right side ;)).
void SetLastField(bool last_field)
Set whether this is the last visible entry of the parent node.
String filter and state.
#define lastof(x)
Get the last element of an fixed size array.
Definition: depend.cpp:48
Settings displayed in the list of advanced settings.
Show only settings which are different compared to default values.
Stuff related to the text buffer GUI.
void OnClick(Point pt, int widget, int click_count) override
A click with the left mouse button has been made on the window.
const SettingDesc * setting
Setting description of the setting.
void DisableWidget(byte widget_index)
Sets a widget to disabled.
Definition: window_gui.h:402
#define CLRBITS(x, y)
Clears several bits in a variable.
Town name dropdown.
NewGRF readme.
Definition: textfile_type.h:17
Subdirectory for all base data (base sets, intro game)
Definition: fileio_type.h:116
static T max(const T a, const T b)
Returns the maximum of two values.
Definition: math_func.hpp:24
static StringID TownName(int town_name)
Get a town name.
virtual uint GetMaxHelpHeight(int maxw)
Get the biggest height of the help text(s), if the width is at least maxw.
Common string list item.
Definition: dropdown_type.h:39
static int GetNumSets()
Count the number of available graphics sets.
int GetNumMissing() const
Get the number of missing files.
void CreateNestedTree(bool fill_nested=true)
Perform the first part of the initialization of a nested widget tree.
Definition: window.cpp:1831
Pure simple text.
Definition: widget_type.h:56
this setting can be different for each company (saved in company struct)
virtual void Init(byte level=0)
Initialization of an entire setting page.
Background of the window.
void SetStringParameters(int widget) const override
Initialize string parameters for a widget.
static const int LEVEL_WIDTH
Indenting width of a sub-page in pixels.
void OnTimeout() override
Called when this window&#39;s timeout has been reached.
bool _left_button_clicked
Is left mouse button clicked?
Definition: gfx.cpp:39
void DrawFrameRect(int left, int top, int right, int bottom, Colours colour, FrameFlags flags)
Draw frame rectangle.
Definition: widget.cpp:175
std::vector< Dimension > _resolutions
List of resolutions.
Definition: driver.cpp:20
void SetCount(int num)
Sets the number of elements in the list.
Definition: widget_type.h:668
Partial widget specification to allow NWidgets to be written nested.
Definition: widget_type.h:908
Functions related to (drawing on) viewports.
Dropdown for the font zoom level.
NewGRF license.
Definition: textfile_type.h:19
Base for the GUIs that have an edit box in them.
Data structure for an opened window.
Definition: window_gui.h:276
void FinishInitNested(WindowNumber window_number=0)
Perform the second part of the initialization of a nested widget tree.
Definition: window.cpp:1847
void SetFilterTerm(const char *str)
Set the term to filter on.
Functions to read fonts from files and cache them.
void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override
Update size and resize step of a widget in the window.
static NWidgetPart SetPadding(uint8 top, uint8 right, uint8 bottom, uint8 left)
Widget part function for setting additional space around a widget.
Definition: widget_type.h:1044
void InitNested(WindowNumber number=0)
Perform complete initialization of the Window with nested widgets, to allow use.
Definition: window.cpp:1860
SettingEntry * last_clicked
If non-nullptr, pointer to the last clicked setting.
Bottom offset of the text of the frame.
Definition: window_gui.h:73
SaveLoad save
Internal structure (going to savegame, parts to config)
void SetDParamStr(uint n, const char *str)
This function is used to "bind" a C string to a OpenTTD dparam slot.
Definition: strings.cpp:279
enable the &#39;Default&#39; button ("\0" is returned)
Definition: textbuf_gui.h:21
bool ReadLanguagePack(const LanguageMetadata *lang)
Read a particular language.
Definition: strings.cpp:1713
Functions related to low-level strings.
bool type_hides
Whether the type hides filtered strings.
Only numeric ones.
Definition: string_type.h:28
Invisible widget that takes some space.
Definition: widget_type.h:77
bool UpdateFilterState(SettingFilter &filter, bool force_visible)
Update the filter state.
VarType conv
type of the variable to be saved, int
Definition: saveload.h:501
Functions related to errors.
Used in setting filter to match all types.
Default window size box (at top-right of a window, between WWT_SHADEBOX and WWT_STICKYBOX) ...
Definition: widget_type.h:63
int GetScrolledRowFromWidget(int clickpos, const Window *const w, int widget, int padding=0, int line_height=-1) const
Compute the row of a scrolled widget that a user clicked in.
Definition: widget.cpp:1957
Of a numeric setting entry, the left button is depressed.
Dropdown to say how often to autosave.
bool manually_changed_folding
Whether the user expanded/collapsed something manually.
CompanySettings company
default values for per-company settings
static GameSettings * settings_ptr
Pointer to the game settings being displayed and modified.
StringID str_help
(Translated) string with help text; gui only.
Suffix edit button.
int main(int argc, char *argv[])
Entry point.
Definition: depend.cpp:927
SettingEntry(const char *name)
Constructor for a single setting in the &#39;advanced settings&#39; window.
virtual uint Length() const
Return number of rows needed to display the (filtered) entry.
byte road_side
the side of the road vehicles drive on
void SetDisplayedHelpText(SettingEntry *pe)
Set the entry that should have its help text displayed, and mark the window dirty so it gets repainte...
SmallMap< int, QueryString * > querystrings
QueryString associated to WWT_EDITBOX widgets.
Definition: window_gui.h:328
void UpdateAllVirtCoords()
Update the viewport coordinates of all signs.
Definition: afterload.cpp:217
const char * name
Name of the setting.
#define FONT_HEIGHT_NORMAL
Height of characters in the normal (FS_NORMAL) font.
Definition: gfx_func.h:177
static NWidgetPart SetDataTip(uint32 data, StringID tip)
Widget part function for setting the data and tooltip.
Definition: widget_type.h:1012
virtual void DrawSetting(GameSettings *settings_ptr, int left, int right, int y, bool highlight) const
Function to draw setting value (button + text + current value)
Data stored about a string that can be modified in the GUI.
ClientSettings _settings_client
The current settings for this game.
Definition: settings.cpp:79
static NWidgetPart SetMinimalSize(int16 x, int16 y)
Widget part function for setting the minimal size.
Definition: widget_type.h:945
static bool NatSortFunc(std::unique_ptr< const DropDownListItem > const &first, std::unique_ptr< const DropDownListItem > const &second)
Natural sorting comparator function for DropDownList::sort().
Definition: dropdown.cpp:52
Definition of base types and functions in a cross-platform compatible way.
void LoadStringWidthTable(bool monospace)
Initialize _stringwidth_table cache.
Definition: gfx.cpp:1271
static const int CF_NOEURO
Currency never switches to the Euro (as far as known).
Definition: currency.h:16
void OnDropdownClose(Point pt, int widget, int index, bool instant_close) override
A dropdown window associated to this window has been closed.
A number of safeguards to prevent using unsafe methods.
Standard setting.
Normal push-button (no toggle button) with text caption.
Definition: widget_type.h:102
static int SETTING_HEIGHT
Height of a single setting in the tree view in pixels.
Geometry functions.
GameSettings _settings_newgame
Game settings for new games (updated from the intro screen).
Definition: settings.cpp:81
byte level
Nesting level of this setting entry.
Simple depressed panel.
Definition: widget_type.h:48
StringID GetHelpText() const
Get the help text of a single setting.
Display settings associated to the "basic" list.
bool IsVisibleByRestrictionMode(RestrictionMode mode) const
Checks whether an entry shall be made visible based on the restriction mode.
Offset at bottom to draw below the text.
Definition: window_gui.h:67
Custom currency; Window numbers:
Definition: window_type.h:612
const SettingDesc * GetSettingFromName(const char *name, uint *i)
Given a name of setting, return a setting description of it.
Definition: settings.cpp:2065
Window timeout counter.
Definition: window_gui.h:232
StringID title
Title of the sub-page.
StringID * BuildCurrencyDropdown()
Build a list of currency names StringIDs to use in a dropdown list.
Definition: currency.cpp:166
Information about languages and their files.
SettingFilter filter
Filter for the list.
const Scrollbar * GetScrollbar(uint widnum) const
Return the Scrollbar to a widget index.
Definition: window.cpp:309
char * stredup(const char *s, const char *last)
Create a duplicate of the given string.
Definition: string.cpp:136
Window for displaying the textfile of a BaseSet.
int pos_x
Horizontal position of top-left corner of the widget in the window.
Definition: widget_type.h:175
Display settings associated to the "advanced" list.
virtual BaseSettingEntry * FindEntry(uint row, uint *cur_row)
Find setting entry at row row_num.
Collapse all button.
Frame.
Definition: widget_type.h:58
Description of selected base GRF.
void OnQueryTextFinished(char *str) override
The query window opened from this window has closed.
void Init(byte level=0)
Initialization of an entire setting page.
static const GraphicsSet * GetSet(int index)
Get the name of the graphics set at the specified index.
Center the window.
Definition: window_gui.h:155
Label upfront to the type drop-down box to restrict the list of settings to show. ...
virtual void LoadTextfile(const char *textfile, Subdirectory dir)
Loads the textfile text from file and setup lines.
static NWidgetPart NWidget(WidgetType tp, Colours col, int16 idx=-1)
Widget part function for starting a new &#39;real&#39; widget.
Definition: widget_type.h:1112
SettingType type
Filter based on type.
Containers for BaseSettingEntry.
Prefix edit button.
Baseclass for nested widgets.
Definition: widget_type.h:124
Down button.
void OnDropdownSelect(int widget, int index) override
A dropdown option associated to this window has been selected.
int DrawString(int left, int right, int top, const char *str, TextColour colour, StringAlignment align, bool underline, FontSize fontsize)
Draw string, possibly truncated to make it fit in its allocated space.
Definition: gfx.cpp:636
Language dropdown.
Entry is hidden by the string filter.
Basic functions/variables used all over the place.
Toggle fullscreen.
void SetValueDParams(uint first_param, int32 value) const
Set the DParams for drawing the value of a setting.
uint index
Index of the setting in the settings table.
RestrictionMode
How the list of advanced settings is filtered.
SettingEntryFlags
Flags for SettingEntry.
Right offset of the text of the frame.
Definition: window_gui.h:71
Current prefix.
#define lengthof(x)
Return the length of an fixed size array.
Definition: depend.cpp:40
bool RoadVehiclesAreBuilt()
Verify whether a road vehicle is available.
Definition: road_cmd.cpp:183
void GfxClearSpriteCache()
Remove all encoded sprites from the sprite cache without discarding sprite location information...
TextfileType
Additional text files accompanying Tar archives.
Definition: textfile_type.h:14
Dropdown for the resolution.
always the last item
Definition: currency.h:64
uint resize_y
Vertical resize step (0 means not resizable).
Definition: widget_type.h:165
static T min(const T a, const T b)
Returns the minimum of two values.
Definition: math_func.hpp:40
bool folded
Sub-page is folded (not visible except for its title)
static StringID * _grf_names
Pointer to town names defined by NewGRFs.
virtual bool UpdateFilterState(SettingFilter &filter, bool force_visible)
Update the filter state.
void DrawWidget(const Rect &r, int widget) const override
Draw the contents of a nested widget.
Top offset of the text of the frame.
Definition: window_gui.h:72
StringFilter string
Filter string.
Left offset of the text of the frame.
Definition: window_gui.h:70
Year of introduction.
int cancel_button
Widget button of parent window to simulate when pressing CANCEL in OSK.
void DrawArrowButtons(int x, int y, Colours button_colour, byte state, bool clickable_left, bool clickable_right)
Draw [<][>] boxes.
uint32 StringID
Numeric value that represents a string, independent of the selected language.
Definition: strings_type.h:16
void OnPaint() override
The window must be repainted.
void DeleteWindowByClass(WindowClass cls)
Delete all windows of a given class.
Definition: window.cpp:1178
virtual uint Length() const
Return number of rows needed to display the (filtered) entry.
Data structure describing one page of settings in the settings window.
#define SETTING_BUTTON_WIDTH
Width of setting buttons.
Definition: settings_gui.h:17
CharSetFilter
Valid filter types for IsValidChar.
Definition: string_type.h:26
This entry is the last one in a (sub-)page.
void SetCompanySetting(uint index, int32 value)
Top function to save the new value of an element of the Settings struct.
Definition: settings.cpp:1979
the number represents money, so when reading value multiply by exchange rate
Offset at top to draw above the text.
Definition: window_gui.h:66
Expand all button.
static T Clamp(const T a, const T min, const T max)
Clamp a value between an interval.
Definition: math_func.hpp:137
virtual void GetFoldingState(bool &all_folded, bool &all_unfolded) const
Recursively accumulate the folding state of the (filtered) tree.
bool IsVisible(const BaseSettingEntry *item) const
Check whether an entry is visible and not folded or filtered away.
void SetDirty() const
Mark entire window as dirty (in need of re-paint)
Definition: window.cpp:984
RestrictionMode min_cat
Minimum category needed to display all filtered strings (RM_BASIC, RM_ADVANCED, or RM_ALL)...
void FoldAll()
Recursively close all folds of sub-pages.
virtual void FoldAll()
Recursively close all (filtered) folds of sub-pages.
uint8 settings_restriction_mode
selected restriction mode in adv. settings GUI.
Dimension GetStringBoundingBox(const char *str, FontSize start_fontsize)
Return the string dimension in pixels.
Definition: gfx.cpp:838
SettingEntry * valuedropdown_entry
If non-nullptr, pointer to the value for which a dropdown window is currently opened.
void AddLine(const char *str)
Pass another text line from the current item to the filter.
uint16 GetCount() const
Gets the number of elements in the list.
Definition: widget_type.h:611
const TBaseSet * baseset
View the textfile of this BaseSet.
Dimension maxdim(const Dimension &d1, const Dimension &d2)
Compute bounding box of both dimensions.
Draw only every second pixel, used for greying-out.
Definition: gfx_type.h:283
No window, redirects to WC_MAIN_WINDOW.
Definition: window_type.h:38
void DeleteWindowById(WindowClass cls, WindowNumber number, bool force)
Delete a window by its class and window number (if it is open).
Definition: window.cpp:1165
bool IsEditable(bool do_command=false) const
Check whether the setting is editable in the current gamemode.
Definition: settings.cpp:792
void InitGRFTownGeneratorNames()
Allocate memory for the NewGRF town names.
EntryVector entries
Settings on this page.
void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override
Update size and resize step of a widget in the window.
static void * GetVariableAddress(const void *object, const SaveLoad *sld)
Get the address of the variable.
Definition: saveload.h:825
StringID str_val
(Translated) first string describing the value.
Functions related to companies.
char *const buf
buffer in which text is saved
Definition: textbuf_type.h:32
const char * GetCurrentLanguageIsoCode()
Get the ISO language code of the currently loaded language.
Definition: strings.cpp:1997
Open base GRF readme, changelog (+1) or license (+2).
void ReInitAllWindows()
Re-initialize all windows.
Definition: window.cpp:3454
Use to select a base GRF.
Description of selected base SFX.
Both numeric and alphabetic and spaces and stuff.
Definition: string_type.h:27
Category setting filtered matches away.
Declaration of functions and types defined in highscore.h and highscore_gui.h.
GUISettings gui
settings related to the GUI
Bit-mask for button flags.
Window caption (window title between closebox and stickybox)
Definition: widget_type.h:59
void ShowBaseSetTextfileWindow(TextfileType file_type, const TBaseSet *baseset, StringID content_type)
Open the BaseSet version of the textfile window.
Window for displaying a textfile.
Definition: textfile_gui.h:21
If set the frame is lowered and the background colour brighter (ie. buttons when pressed) ...
Definition: window_gui.h:29
static bool StrEmpty(const char *s)
Check if a string buffer is empty.
Definition: string_func.h:57
void UpdateCursorSize()
Update cursor dimension.
Definition: gfx.cpp:1669
int GetStringLineCount(StringID str, int maxw)
Calculates number of lines of string.
Definition: gfx.cpp:710
static size_t GetNumItems()
Returns number of valid items in the pool.
Definition: pool_type.hpp:359
a value of zero means the feature is disabled
TextDirection _current_text_dir
Text direction of the currently selected language.
Definition: strings.cpp:48
virtual uint Draw(GameSettings *settings_ptr, int left, int right, int y, uint first_row, uint max_row, BaseSettingEntry *selected, uint cur_row=0, uint parent_last=0) const
Draw a row in the settings panel.
static GameSettings & GetGameSettings()
Get the settings-object applicable for the current situation: the newgame settings when we&#39;re in the ...
Searching and filtering using a stringterm.
TextfileType file_type
Type of textfile to view.
Definition: textfile_gui.h:22
Top offset of image in the button.
Definition: window_gui.h:40
Vertical container.
Definition: widget_type.h:75
bool SetSettingValue(uint index, int32 value, bool force_newgame)
Top function to save the new value of an element of the Settings struct.
Definition: settings.cpp:1938
void ShowGameOptions()
Open the game options window.
char own_name[32]
the localized name of this language
Definition: language.h:30
Label upfront to the category drop-down box to restrict the list of settings to show.
static T abs(const T a)
Returns the absolute value of (scalar) variable.
Definition: math_func.hpp:81
Functions for setting GUIs.
virtual uint Draw(GameSettings *settings_ptr, int left, int right, int y, uint first_row, uint max_row, BaseSettingEntry *selected, uint cur_row=0, uint parent_last=0) const
Draw a row in the settings panel.
static NWidgetPart EndContainer()
Widget part function for denoting the end of a container (horizontal, vertical, WWT_FRAME, WWT_INSET, or WWT_PANEL).
Definition: widget_type.h:997
Functions related to zooming.
Game setting.
Scrollbar * vscroll
Vertical scrollbar.
Definition: textfile_gui.h:23
Functions and types used internally for the settings configurations.
char * strecpy(char *dst, const char *src, const char *last)
Copies characters from one buffer to another.
Definition: depend.cpp:66
ZoomLevel _font_zoom
Font Zoom level.
Definition: gfx.cpp:60
uint current_x
Current horizontal size (after resizing).
Definition: widget_type.h:172
bool SetFocusedWidget(int widget_index)
Set focus within this window to the given widget.
Definition: window.cpp:495
Up button.
ZoomLevel _gui_zoom
GUI Zoom level.
Definition: gfx.cpp:59
SwitchMode _switch_mode
The next mainloop command.
Definition: gfx.cpp:46
void DrawDropDownButton(int x, int y, Colours button_colour, bool state, bool clickable)
Draw a dropdown button.
void OnTimeout() override
Called when this window&#39;s timeout has been reached.
display absolute value of the setting
SettingType GetType() const
Return the type of the setting.
Definition: settings.cpp:807
SettingDescType cmd
various flags for the variable
Text filter.
LocaleSettings locale
settings related to used currency/unit system in the current game
virtual void Init(byte level=0)
Initialization of a setting entry.
static SettingsContainer & GetSettingsTree()
Construct settings tree.
void ShowGameSettings()
Open advanced settings window.
byte town_name
the town name generator used for town names
GRFTextWrapper * name
NOSAVE: GRF name (Action 0x08)
virtual BaseSettingEntry * FindEntry(uint row, uint *cur_row)
Find setting entry at row row_num.
static int _nb_grf_names
Number of town names defined by NewGRFs.
Functions related to commands.
bool _network_server
network-server is active
Definition: network.cpp:53
Coordinates of a point in 2D.
byte flags
Flags of the setting entry.
Dimension GetSpriteSize(SpriteID sprid, Point *offset, ZoomLevel zoom)
Get the size of a sprite.
Definition: gfx.cpp:908
List item containing a C char string.
Definition: dropdown_type.h:69
static bool IsValidID(size_t index)
Tests whether given index can be used to get valid (non-nullptr) Titem.
Definition: pool_type.hpp:318
virtual void DrawSetting(GameSettings *settings_ptr, int left, int right, int y, bool highlight) const
Function to draw setting value (button + text + current value)
Drop down list.
Definition: widget_type.h:68
Normal push-button (no toggle button) with arrow caption.
Definition: widget_type.h:104
uint16 GetCapacity() const
Gets the number of visible elements of the scrollbar.
Definition: widget_type.h:620
SettingEntry * clicked_entry
If non-nullptr, pointer to a clicked numeric setting (with a depressed left or right button)...
StringID str
(translated) string with descriptive text; gui and console
StringID content_type
STR_CONTENT_TYPE_xxx for title.
The drop down box to restrict the list of settings.
static const StringID INVALID_STRING_ID
Constant representing an invalid string (16bit in case it is used in savegames)
Definition: strings_type.h:17
DropDownList BuildDropDownList(int widget, int *selected_index) const
Build the dropdown list for a specific widget.
Company setting.
int32 min
minimum values
static void free(const void *ptr)
Version of the standard free that accepts const pointers.
Definition: depend.cpp:129
uint64 GetMaskOfAllowedCurrencies()
get a mask of the allowed currencies depending on the year
Definition: currency.cpp:119
Offset at right to draw the frame rectangular area.
Definition: window_gui.h:61
int width
width of the window (number of pixels to the right in x direction)
Definition: window_gui.h:319
The caption of the window.
Definition: misc_widget.h:49
static NWidgetPart SetFill(uint fill_x, uint fill_y)
Widget part function for setting filling.
Definition: widget_type.h:981
static bool HasBit(const T x, const uint8 y)
Checks if a bit in a value is set.
Base functions for all AIs.
ZoomLevel
All zoom levels we know.
Definition: zoom_type.h:19
Base of the town class.
static void ShowCustCurrency()
Open custom currency window.
void SetStringParameters(int widget) const override
Initialize string parameters for a widget.
#define DECLARE_POSTFIX_INCREMENT(enum_type)
Some enums need to have allowed incrementing (i.e.
Definition: enum_type.hpp:14
GameCreationSettings game_creation
settings used during the creation of a game (map)
QueryString filter_editbox
Filter editbox;.
void DrawBoolButton(int x, int y, bool state, bool clickable)
Draw a toggle button.
void SetCapacityFromWidget(Window *w, int widget, int padding=0)
Set capacity of visible elements from the size and resize properties of a widget. ...
Definition: widget.cpp:1971
Client setting.
Specification of a rectangle with absolute coordinates of all edges.
Vertical scrollbar.
Definition: widget_type.h:82
int _nb_orig_names
Number of original town names.
Both category and type settings filtered matches away.
Text is written right-to-left by default.
Definition: strings_type.h:24
SettingEntry * valuewindow_entry
If non-nullptr, pointer to setting for which a value-entering window has been opened.
a boolean number
Window functions not directly related to making/drawing windows.
SettingType
Type of settings for filtering.
const char * GetTextfile(TextfileType type, Subdirectory dir, const char *filename)
Search a textfile file next to the given content.
Information area to display help text of the selected option.
virtual void OnDropdownClose(Point pt, int widget, int index, bool instant_close)
A dropdown window associated to this window has been closed.
Definition: window.cpp:282
Nothing was filtering matches away.
void DrawWidget(const Rect &r, int widget) const override
Draw the contents of a nested widget.
ZoomLevel zoom_min
minimum zoom out level
Use to select a base SFX.
#define SETTING_BUTTON_HEIGHT
Height of setting buttons.
Definition: settings_gui.h:19
uint8 timeout_timer
Timer value of the WF_TIMEOUT for flags.
Definition: window_gui.h:314
Errors (eg. saving/loading failed)
Definition: error.h:23
Zoomed 4 times out.
Definition: zoom_type.h:24
void GetFoldingState(bool &all_folded, bool &all_unfolded) const
Recursively accumulate the folding state of the tree.
void OnDropdownSelect(int widget, int index) override
A dropdown option associated to this window has been selected.
BaseSettingEntry * FindEntry(uint row, uint *cur_row)
Find the setting entry at row number row_num.
Info about corrupted files etc.
void OnResize() override
Called after the window got resized.
uint32 max
maximum values
Left offset of the image in the button.
Definition: window_gui.h:38
int32 interval
the interval to use between settings in the &#39;settings&#39; window. If interval is &#39;0&#39; the interval is dyn...
static NWidgetPart SetScrollbar(int index)
Attach a scrollbar to a widget.
Definition: widget_type.h:1093
CompanyID _local_company
Company controlled by the human player at this client. Can also be COMPANY_SPECTATOR.
Definition: company_cmd.cpp:44
Base list item class from which others are derived.
Definition: dropdown_type.h:22
byte autosave
how often should we do autosaves?
SettingDescBase desc
Settings structure (going to configuration file)
Dimensions (a width and height) of a rectangle in 2D.
Value of the NCB_EQUALSIZE flag.
Definition: widget_type.h:427
Query string window; Window numbers:
Definition: window_type.h:116
bool IsEmpty() const
Check whether any filter words were entered.
Offset at left to draw the frame rectangular area.
Definition: window_gui.h:60
static const Year MAX_YEAR
MAX_YEAR, nicely rounded value of the number of years that can be encoded in a single 32 bits date...
Definition: date_type.h:94
Factory to &#39;query&#39; all available blitters.
Game options window; Window numbers:
Definition: window_type.h:606
static const GraphicsSet * GetUsedSet()
Return the used set.
void DrawSprite(SpriteID img, PaletteID pal, int x, int y, const SubSprite *sub, ZoomLevel zoom)
Draw a sprite, not in a viewport.
Definition: gfx.cpp:973
static NWidgetPart SetPIP(uint8 pre, uint8 inter, uint8 post)
Widget part function for setting a pre/inter/post spaces.
Definition: widget_type.h:1074
Description of selected base music set.
int pos_y
Vertical position of top-left corner of the widget in the window.
Definition: widget_type.h:176
void InvalidateData(int data=0, bool gui_scope=true)
Mark this window&#39;s data as invalid (in need of re-computing)
Definition: window.cpp:3259
Down button.
virtual bool IsVisible(const BaseSettingEntry *item) const
Check whether an entry is visible and not folded or filtered away.
int height
Height of the window (number of pixels down in y direction)
Definition: window_gui.h:320
virtual bool UpdateFilterState(SettingFilter &filter, bool force_visible)
Update the filter state.
void EnableWidget(byte widget_index)
Sets a widget to Enabled.
Definition: window_gui.h:411
void MarkWholeScreenDirty()
This function mark the whole screen as dirty.
Definition: gfx.cpp:1600
GUI functions related to textfiles.
int DrawStringMultiLine(int left, int right, int top, int bottom, const char *str, TextColour colour, StringAlignment align, bool underline, FontSize fontsize)
Draw string, possibly over multiple lines.
Definition: gfx.cpp:759
virtual void OnInvalidateData(int data=0, bool gui_scope=true)
Some data on this window has become invalid.
Definition: window_gui.h:743
(Toggle) Button with text
Definition: widget_type.h:53
List all settings regardless of the default/newgame/... values.
uint16 GetPosition() const
Gets the position of the first visible element in the list.
Definition: widget_type.h:629
byte currency
currency we currently use
static void SetDParam(uint n, uint64 v)
Set a string parameter v at index n in the global string parameter array.
Definition: strings_func.h:199