OpenTTD
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]);
531  break;
532 
533  case WID_GO_RESOLUTION_DROPDOWN: // Change resolution
534  if ((uint)index < _resolutions.size() && ChangeResInGame(_resolutions[index].width, _resolutions[index].height)) {
535  this->SetDirty();
536  }
537  break;
538 
541  _gui_zoom = (ZoomLevel)(ZOOM_LVL_OUT_4X - index);
544  FixTitleGameZoom();
546  break;
547 
550  _font_zoom = (ZoomLevel)(ZOOM_LVL_OUT_4X - index);
551  ClearFontCache();
554  break;
555 
557  this->SetMediaSet<BaseGraphics>(index);
558  break;
559 
561  this->SetMediaSet<BaseSounds>(index);
562  break;
563 
565  ChangeMusicSet(index);
566  break;
567  }
568  }
569 
575  void OnInvalidateData(int data = 0, bool gui_scope = true) override
576  {
577  if (!gui_scope) return;
579 
580  bool missing_files = BaseGraphics::GetUsedSet()->GetNumMissing() == 0;
581  this->GetWidget<NWidgetCore>(WID_GO_BASE_GRF_STATUS)->SetDataTip(missing_files ? STR_EMPTY : STR_GAME_OPTIONS_BASE_GRF_STATUS, STR_NULL);
582 
583  for (TextfileType tft = TFT_BEGIN; tft < TFT_END; tft++) {
587  }
588 
589  missing_files = BaseMusic::GetUsedSet()->GetNumInvalid() == 0;
590  this->GetWidget<NWidgetCore>(WID_GO_BASE_MUSIC_STATUS)->SetDataTip(missing_files ? STR_EMPTY : STR_GAME_OPTIONS_BASE_MUSIC_STATUS, STR_NULL);
591  }
592 };
593 
594 static const NWidgetPart _nested_game_options_widgets[] = {
596  NWidget(WWT_CLOSEBOX, COLOUR_GREY),
597  NWidget(WWT_CAPTION, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
598  EndContainer(),
599  NWidget(WWT_PANEL, COLOUR_GREY, WID_GO_BACKGROUND), SetPIP(6, 6, 10),
600  NWidget(NWID_HORIZONTAL), SetPIP(10, 10, 10),
601  NWidget(NWID_VERTICAL), SetPIP(0, 6, 0),
602  NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_ROAD_VEHICLES_FRAME, STR_NULL),
603  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),
604  EndContainer(),
605  NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_AUTOSAVE_FRAME, STR_NULL),
606  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),
607  EndContainer(),
608  NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_RESOLUTION, STR_NULL),
609  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),
611  NWidget(WWT_TEXT, COLOUR_GREY), SetMinimalSize(0, 12), SetFill(1, 0), SetDataTip(STR_GAME_OPTIONS_FULLSCREEN, STR_NULL),
612  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_GO_FULLSCREEN_BUTTON), SetMinimalSize(21, 9), SetDataTip(STR_EMPTY, STR_GAME_OPTIONS_FULLSCREEN_TOOLTIP),
613  EndContainer(),
614  EndContainer(),
615  NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_GUI_ZOOM_FRAME, STR_NULL),
616  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),
617  EndContainer(),
618  EndContainer(),
619 
620  NWidget(NWID_VERTICAL), SetPIP(0, 6, 0),
621  NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_TOWN_NAMES_FRAME, STR_NULL),
622  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),
623  EndContainer(),
624  NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_LANGUAGE, STR_NULL),
625  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),
626  EndContainer(),
627  NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_CURRENCY_UNITS_FRAME, STR_NULL),
628  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),
629  EndContainer(),
630  NWidget(NWID_SPACER), SetMinimalSize(0, 0), SetFill(0, 1),
631  NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_FONT_ZOOM, STR_NULL),
632  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),
633  EndContainer(),
634  EndContainer(),
635  EndContainer(),
636 
637  NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_BASE_GRF, STR_NULL), SetPadding(0, 10, 0, 10),
638  NWidget(NWID_HORIZONTAL), SetPIP(0, 30, 0),
639  NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_BASE_GRF_DROPDOWN), SetMinimalSize(150, 12), SetDataTip(STR_BLACK_RAW_STRING, STR_GAME_OPTIONS_BASE_GRF_TOOLTIP),
640  NWidget(WWT_TEXT, COLOUR_GREY, WID_GO_BASE_GRF_STATUS), SetMinimalSize(150, 12), SetDataTip(STR_EMPTY, STR_NULL), SetFill(1, 0),
641  EndContainer(),
642  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),
644  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),
645  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),
646  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),
647  EndContainer(),
648  EndContainer(),
649 
650  NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_BASE_SFX, STR_NULL), SetPadding(0, 10, 0, 10),
651  NWidget(NWID_HORIZONTAL), SetPIP(0, 30, 0),
652  NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_BASE_SFX_DROPDOWN), SetMinimalSize(150, 12), SetDataTip(STR_BLACK_RAW_STRING, STR_GAME_OPTIONS_BASE_SFX_TOOLTIP),
653  NWidget(NWID_SPACER), SetFill(1, 0),
654  EndContainer(),
655  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),
657  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),
658  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),
659  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),
660  EndContainer(),
661  EndContainer(),
662 
663  NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_BASE_MUSIC, STR_NULL), SetPadding(0, 10, 0, 10),
664  NWidget(NWID_HORIZONTAL), SetPIP(0, 30, 0),
665  NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_BASE_MUSIC_DROPDOWN), SetMinimalSize(150, 12), SetDataTip(STR_BLACK_RAW_STRING, STR_GAME_OPTIONS_BASE_MUSIC_TOOLTIP),
666  NWidget(WWT_TEXT, COLOUR_GREY, WID_GO_BASE_MUSIC_STATUS), SetMinimalSize(150, 12), SetDataTip(STR_EMPTY, STR_NULL), SetFill(1, 0),
667  EndContainer(),
668  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),
670  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),
671  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),
672  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),
673  EndContainer(),
674  EndContainer(),
675  EndContainer(),
676 };
677 
678 static WindowDesc _game_options_desc(
679  WDP_CENTER, "settings_game", 0, 0,
681  0,
682  _nested_game_options_widgets, lengthof(_nested_game_options_widgets)
683 );
684 
687 {
689  new GameOptionsWindow(&_game_options_desc);
690 }
691 
692 static int SETTING_HEIGHT = 11;
693 static const int LEVEL_WIDTH = 15;
694 
703 
704  SEF_LAST_FIELD = 0x04,
705  SEF_FILTERED = 0x08,
706 };
707 
716 };
718 
719 
723  bool type_hides;
726 };
727 
730  byte flags;
731  byte level;
732 
733  BaseSettingEntry() : flags(0), level(0) {}
734  virtual ~BaseSettingEntry() {}
735 
736  virtual void Init(byte level = 0);
737  virtual void FoldAll() {}
738  virtual void UnFoldAll() {}
739 
744  void SetLastField(bool last_field) { if (last_field) SETBITS(this->flags, SEF_LAST_FIELD); else CLRBITS(this->flags, SEF_LAST_FIELD); }
745 
746  virtual uint Length() const = 0;
747  virtual void GetFoldingState(bool &all_folded, bool &all_unfolded) const {}
748  virtual bool IsVisible(const BaseSettingEntry *item) const;
749  virtual BaseSettingEntry *FindEntry(uint row, uint *cur_row);
750  virtual uint GetMaxHelpHeight(int maxw) { return 0; }
751 
756  bool IsFiltered() const { return (this->flags & SEF_FILTERED) != 0; }
757 
758  virtual bool UpdateFilterState(SettingFilter &filter, bool force_visible) = 0;
759 
760  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;
761 
762 protected:
763  virtual void DrawSetting(GameSettings *settings_ptr, int left, int right, int y, bool highlight) const = 0;
764 };
765 
768  const char *name;
770  uint index;
771 
772  SettingEntry(const char *name);
773 
774  virtual void Init(byte level = 0);
775  virtual uint Length() const;
776  virtual uint GetMaxHelpHeight(int maxw);
777  virtual bool UpdateFilterState(SettingFilter &filter, bool force_visible);
778 
779  void SetButtons(byte new_val);
780 
785  inline StringID GetHelpText() const
786  {
787  return this->setting->desc.str_help;
788  }
789 
790  void SetValueDParams(uint first_param, int32 value) const;
791 
792 protected:
793  virtual void DrawSetting(GameSettings *settings_ptr, int left, int right, int y, bool highlight) const;
794 
795 private:
796  bool IsVisibleByRestrictionMode(RestrictionMode mode) const;
797 };
798 
801  typedef std::vector<BaseSettingEntry*> EntryVector;
802  EntryVector entries;
803 
804  template<typename T>
805  T *Add(T *item)
806  {
807  this->entries.push_back(item);
808  return item;
809  }
810 
811  void Init(byte level = 0);
812  void FoldAll();
813  void UnFoldAll();
814 
815  uint Length() const;
816  void GetFoldingState(bool &all_folded, bool &all_unfolded) const;
817  bool IsVisible(const BaseSettingEntry *item) const;
818  BaseSettingEntry *FindEntry(uint row, uint *cur_row);
819  uint GetMaxHelpHeight(int maxw);
820 
821  bool UpdateFilterState(SettingFilter &filter, bool force_visible);
822 
823  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;
824 };
825 
829  bool folded;
830 
831  SettingsPage(StringID title);
832 
833  virtual void Init(byte level = 0);
834  virtual void FoldAll();
835  virtual void UnFoldAll();
836 
837  virtual uint Length() const;
838  virtual void GetFoldingState(bool &all_folded, bool &all_unfolded) const;
839  virtual bool IsVisible(const BaseSettingEntry *item) const;
840  virtual BaseSettingEntry *FindEntry(uint row, uint *cur_row);
841  virtual uint GetMaxHelpHeight(int maxw) { return SettingsContainer::GetMaxHelpHeight(maxw); }
842 
843  virtual bool UpdateFilterState(SettingFilter &filter, bool force_visible);
844 
845  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;
846 
847 protected:
848  virtual void DrawSetting(GameSettings *settings_ptr, int left, int right, int y, bool highlight) const;
849 };
850 
851 /* == BaseSettingEntry methods == */
852 
857 void BaseSettingEntry::Init(byte level)
858 {
859  this->level = level;
860 }
861 
869 {
870  if (this->IsFiltered()) return false;
871  if (this == item) return true;
872  return false;
873 }
874 
881 BaseSettingEntry *BaseSettingEntry::FindEntry(uint row_num, uint *cur_row)
882 {
883  if (this->IsFiltered()) return nullptr;
884  if (row_num == *cur_row) return this;
885  (*cur_row)++;
886  return nullptr;
887 }
888 
918 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
919 {
920  if (this->IsFiltered()) return cur_row;
921  if (cur_row >= max_row) return cur_row;
922 
923  bool rtl = _current_text_dir == TD_RTL;
924  int offset = rtl ? -4 : 4;
925  int level_width = rtl ? -LEVEL_WIDTH : LEVEL_WIDTH;
926 
927  int x = rtl ? right : left;
928  if (cur_row >= first_row) {
929  int colour = _colour_gradient[COLOUR_ORANGE][4];
930  y += (cur_row - first_row) * SETTING_HEIGHT; // Compute correct y start position
931 
932  /* Draw vertical for parent nesting levels */
933  for (uint lvl = 0; lvl < this->level; lvl++) {
934  if (!HasBit(parent_last, lvl)) GfxDrawLine(x + offset, y, x + offset, y + SETTING_HEIGHT - 1, colour);
935  x += level_width;
936  }
937  /* draw own |- prefix */
938  int halfway_y = y + SETTING_HEIGHT / 2;
939  int bottom_y = (flags & SEF_LAST_FIELD) ? halfway_y : y + SETTING_HEIGHT - 1;
940  GfxDrawLine(x + offset, y, x + offset, bottom_y, colour);
941  /* Small horizontal line from the last vertical line */
942  GfxDrawLine(x + offset, halfway_y, x + level_width - offset, halfway_y, colour);
943  x += level_width;
944 
945  this->DrawSetting(settings_ptr, rtl ? left : x, rtl ? x : right, y, this == selected);
946  }
947  cur_row++;
948 
949  return cur_row;
950 }
951 
952 /* == SettingEntry methods == */
953 
958 SettingEntry::SettingEntry(const char *name)
959 {
960  this->name = name;
961  this->setting = nullptr;
962  this->index = 0;
963 }
964 
969 void SettingEntry::Init(byte level)
970 {
971  BaseSettingEntry::Init(level);
972  this->setting = GetSettingFromName(this->name, &this->index);
973  assert(this->setting != nullptr);
974 }
975 
981 void SettingEntry::SetButtons(byte new_val)
982 {
983  assert((new_val & ~SEF_BUTTONS_MASK) == 0); // Should not touch any flags outside the buttons
984  this->flags = (this->flags & ~SEF_BUTTONS_MASK) | new_val;
985 }
986 
989 {
990  return this->IsFiltered() ? 0 : 1;
991 }
992 
999 {
1000  return GetStringHeight(this->GetHelpText(), maxw);
1001 }
1002 
1009 {
1010  /* There shall not be any restriction, i.e. all settings shall be visible. */
1011  if (mode == RM_ALL) return true;
1012 
1013  GameSettings *settings_ptr = &GetGameSettings();
1014  const SettingDesc *sd = this->setting;
1015 
1016  if (mode == RM_BASIC) return (this->setting->desc.cat & SC_BASIC_LIST) != 0;
1017  if (mode == RM_ADVANCED) return (this->setting->desc.cat & SC_ADVANCED_LIST) != 0;
1018 
1019  /* Read the current value. */
1020  const void *var = ResolveVariableAddress(settings_ptr, sd);
1021  int64 current_value = ReadValue(var, sd->save.conv);
1022 
1023  int64 filter_value;
1024 
1025  if (mode == RM_CHANGED_AGAINST_DEFAULT) {
1026  /* This entry shall only be visible, if the value deviates from its default value. */
1027 
1028  /* Read the default value. */
1029  filter_value = ReadValue(&sd->desc.def, sd->save.conv);
1030  } else {
1031  assert(mode == RM_CHANGED_AGAINST_NEW);
1032  /* This entry shall only be visible, if the value deviates from
1033  * its value is used when starting a new game. */
1034 
1035  /* Make sure we're not comparing the new game settings against itself. */
1036  assert(settings_ptr != &_settings_newgame);
1037 
1038  /* Read the new game's value. */
1039  var = ResolveVariableAddress(&_settings_newgame, sd);
1040  filter_value = ReadValue(var, sd->save.conv);
1041  }
1042 
1043  return current_value != filter_value;
1044 }
1045 
1052 bool SettingEntry::UpdateFilterState(SettingFilter &filter, bool force_visible)
1053 {
1054  CLRBITS(this->flags, SEF_FILTERED);
1055 
1056  bool visible = true;
1057 
1058  const SettingDesc *sd = this->setting;
1059  if (!force_visible && !filter.string.IsEmpty()) {
1060  /* Process the search text filter for this item. */
1061  filter.string.ResetState();
1062 
1063  const SettingDescBase *sdb = &sd->desc;
1064 
1065  SetDParam(0, STR_EMPTY);
1066  filter.string.AddLine(sdb->str);
1067  filter.string.AddLine(this->GetHelpText());
1068 
1069  visible = filter.string.GetState();
1070  }
1071 
1072  if (visible) {
1073  if (filter.type != ST_ALL && sd->GetType() != filter.type) {
1074  filter.type_hides = true;
1075  visible = false;
1076  }
1077  if (!this->IsVisibleByRestrictionMode(filter.mode)) {
1078  while (filter.min_cat < RM_ALL && (filter.min_cat == filter.mode || !this->IsVisibleByRestrictionMode(filter.min_cat))) filter.min_cat++;
1079  visible = false;
1080  }
1081  }
1082 
1083  if (!visible) SETBITS(this->flags, SEF_FILTERED);
1084  return visible;
1085 }
1086 
1087 
1088 static const void *ResolveVariableAddress(const GameSettings *settings_ptr, const SettingDesc *sd)
1089 {
1090  if ((sd->desc.flags & SGF_PER_COMPANY) != 0) {
1091  if (Company::IsValidID(_local_company) && _game_mode != GM_MENU) {
1093  } else {
1095  }
1096  } else {
1097  return GetVariableAddress(settings_ptr, &sd->save);
1098  }
1099 }
1100 
1106 void SettingEntry::SetValueDParams(uint first_param, int32 value) const
1107 {
1108  const SettingDescBase *sdb = &this->setting->desc;
1109  if (sdb->cmd == SDT_BOOLX) {
1110  SetDParam(first_param++, value != 0 ? STR_CONFIG_SETTING_ON : STR_CONFIG_SETTING_OFF);
1111  } else {
1112  if ((sdb->flags & SGF_MULTISTRING) != 0) {
1113  SetDParam(first_param++, sdb->str_val - sdb->min + value);
1114  } else if ((sdb->flags & SGF_DISPLAY_ABS) != 0) {
1115  SetDParam(first_param++, sdb->str_val + ((value >= 0) ? 1 : 0));
1116  value = abs(value);
1117  } else {
1118  SetDParam(first_param++, sdb->str_val + ((value == 0 && (sdb->flags & SGF_0ISDISABLED) != 0) ? 1 : 0));
1119  }
1120  SetDParam(first_param++, value);
1121  }
1122 }
1123 
1132 void SettingEntry::DrawSetting(GameSettings *settings_ptr, int left, int right, int y, bool highlight) const
1133 {
1134  const SettingDesc *sd = this->setting;
1135  const SettingDescBase *sdb = &sd->desc;
1136  const void *var = ResolveVariableAddress(settings_ptr, sd);
1137  int state = this->flags & SEF_BUTTONS_MASK;
1138 
1139  bool rtl = _current_text_dir == TD_RTL;
1140  uint buttons_left = rtl ? right + 1 - SETTING_BUTTON_WIDTH : left;
1141  uint text_left = left + (rtl ? 0 : SETTING_BUTTON_WIDTH + 5);
1142  uint text_right = right - (rtl ? SETTING_BUTTON_WIDTH + 5 : 0);
1143  uint button_y = y + (SETTING_HEIGHT - SETTING_BUTTON_HEIGHT) / 2;
1144 
1145  /* We do not allow changes of some items when we are a client in a networkgame */
1146  bool editable = sd->IsEditable();
1147 
1148  SetDParam(0, highlight ? STR_ORANGE_STRING1_WHITE : STR_ORANGE_STRING1_LTBLUE);
1149  int32 value = (int32)ReadValue(var, sd->save.conv);
1150  if (sdb->cmd == SDT_BOOLX) {
1151  /* Draw checkbox for boolean-value either on/off */
1152  DrawBoolButton(buttons_left, button_y, value != 0, editable);
1153  } else if ((sdb->flags & SGF_MULTISTRING) != 0) {
1154  /* Draw [v] button for settings of an enum-type */
1155  DrawDropDownButton(buttons_left, button_y, COLOUR_YELLOW, state != 0, editable);
1156  } else {
1157  /* Draw [<][>] boxes for settings of an integer-type */
1158  DrawArrowButtons(buttons_left, button_y, COLOUR_YELLOW, state,
1159  editable && value != (sdb->flags & SGF_0ISDISABLED ? 0 : sdb->min), editable && (uint32)value != sdb->max);
1160  }
1161  this->SetValueDParams(1, value);
1162  DrawString(text_left, text_right, y + (SETTING_HEIGHT - FONT_HEIGHT_NORMAL) / 2, sdb->str, highlight ? TC_WHITE : TC_LIGHT_BLUE);
1163 }
1164 
1165 /* == SettingsContainer methods == */
1166 
1171 void SettingsContainer::Init(byte level)
1172 {
1173  for (EntryVector::iterator it = this->entries.begin(); it != this->entries.end(); ++it) {
1174  (*it)->Init(level);
1175  }
1176 }
1177 
1180 {
1181  for (EntryVector::iterator it = this->entries.begin(); it != this->entries.end(); ++it) {
1182  (*it)->FoldAll();
1183  }
1184 }
1185 
1188 {
1189  for (EntryVector::iterator it = this->entries.begin(); it != this->entries.end(); ++it) {
1190  (*it)->UnFoldAll();
1191  }
1192 }
1193 
1199 void SettingsContainer::GetFoldingState(bool &all_folded, bool &all_unfolded) const
1200 {
1201  for (EntryVector::const_iterator it = this->entries.begin(); it != this->entries.end(); ++it) {
1202  (*it)->GetFoldingState(all_folded, all_unfolded);
1203  }
1204 }
1205 
1212 bool SettingsContainer::UpdateFilterState(SettingFilter &filter, bool force_visible)
1213 {
1214  bool visible = false;
1215  bool first_visible = true;
1216  for (EntryVector::reverse_iterator it = this->entries.rbegin(); it != this->entries.rend(); ++it) {
1217  visible |= (*it)->UpdateFilterState(filter, force_visible);
1218  (*it)->SetLastField(first_visible);
1219  if (visible && first_visible) first_visible = false;
1220  }
1221  return visible;
1222 }
1223 
1224 
1232 {
1233  for (EntryVector::const_iterator it = this->entries.begin(); it != this->entries.end(); ++it) {
1234  if ((*it)->IsVisible(item)) return true;
1235  }
1236  return false;
1237 }
1238 
1241 {
1242  uint length = 0;
1243  for (EntryVector::const_iterator it = this->entries.begin(); it != this->entries.end(); ++it) {
1244  length += (*it)->Length();
1245  }
1246  return length;
1247 }
1248 
1255 BaseSettingEntry *SettingsContainer::FindEntry(uint row_num, uint *cur_row)
1256 {
1257  BaseSettingEntry *pe = nullptr;
1258  for (EntryVector::iterator it = this->entries.begin(); it != this->entries.end(); ++it) {
1259  pe = (*it)->FindEntry(row_num, cur_row);
1260  if (pe != nullptr) {
1261  break;
1262  }
1263  }
1264  return pe;
1265 }
1266 
1273 {
1274  uint biggest = 0;
1275  for (EntryVector::const_iterator it = this->entries.begin(); it != this->entries.end(); ++it) {
1276  biggest = max(biggest, (*it)->GetMaxHelpHeight(maxw));
1277  }
1278  return biggest;
1279 }
1280 
1281 
1296 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
1297 {
1298  for (EntryVector::const_iterator it = this->entries.begin(); it != this->entries.end(); ++it) {
1299  cur_row = (*it)->Draw(settings_ptr, left, right, y, first_row, max_row, selected, cur_row, parent_last);
1300  if (cur_row >= max_row) {
1301  break;
1302  }
1303  }
1304  return cur_row;
1305 }
1306 
1307 /* == SettingsPage methods == */
1308 
1314 {
1315  this->title = title;
1316  this->folded = true;
1317 }
1318 
1323 void SettingsPage::Init(byte level)
1324 {
1325  BaseSettingEntry::Init(level);
1326  SettingsContainer::Init(level + 1);
1327 }
1328 
1331 {
1332  if (this->IsFiltered()) return;
1333  this->folded = true;
1334 
1336 }
1337 
1340 {
1341  if (this->IsFiltered()) return;
1342  this->folded = false;
1343 
1345 }
1346 
1352 void SettingsPage::GetFoldingState(bool &all_folded, bool &all_unfolded) const
1353 {
1354  if (this->IsFiltered()) return;
1355 
1356  if (this->folded) {
1357  all_unfolded = false;
1358  } else {
1359  all_folded = false;
1360  }
1361 
1362  SettingsContainer::GetFoldingState(all_folded, all_unfolded);
1363 }
1364 
1371 bool SettingsPage::UpdateFilterState(SettingFilter &filter, bool force_visible)
1372 {
1373  if (!force_visible && !filter.string.IsEmpty()) {
1374  filter.string.ResetState();
1375  filter.string.AddLine(this->title);
1376  force_visible = filter.string.GetState();
1377  }
1378 
1379  bool visible = SettingsContainer::UpdateFilterState(filter, force_visible);
1380  if (visible) {
1381  CLRBITS(this->flags, SEF_FILTERED);
1382  } else {
1383  SETBITS(this->flags, SEF_FILTERED);
1384  }
1385  return visible;
1386 }
1387 
1395 {
1396  if (this->IsFiltered()) return false;
1397  if (this == item) return true;
1398  if (this->folded) return false;
1399 
1400  return SettingsContainer::IsVisible(item);
1401 }
1402 
1405 {
1406  if (this->IsFiltered()) return 0;
1407  if (this->folded) return 1; // Only displaying the title
1408 
1409  return 1 + SettingsContainer::Length();
1410 }
1411 
1418 BaseSettingEntry *SettingsPage::FindEntry(uint row_num, uint *cur_row)
1419 {
1420  if (this->IsFiltered()) return nullptr;
1421  if (row_num == *cur_row) return this;
1422  (*cur_row)++;
1423  if (this->folded) return nullptr;
1424 
1425  return SettingsContainer::FindEntry(row_num, cur_row);
1426 }
1427 
1442 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
1443 {
1444  if (this->IsFiltered()) return cur_row;
1445  if (cur_row >= max_row) return cur_row;
1446 
1447  cur_row = BaseSettingEntry::Draw(settings_ptr, left, right, y, first_row, max_row, selected, cur_row, parent_last);
1448 
1449  if (!this->folded) {
1450  if (this->flags & SEF_LAST_FIELD) {
1451  assert(this->level < 8 * sizeof(parent_last));
1452  SetBit(parent_last, this->level); // Add own last-field state
1453  }
1454 
1455  cur_row = SettingsContainer::Draw(settings_ptr, left, right, y, first_row, max_row, selected, cur_row, parent_last);
1456  }
1457 
1458  return cur_row;
1459 }
1460 
1469 void SettingsPage::DrawSetting(GameSettings *settings_ptr, int left, int right, int y, bool highlight) const
1470 {
1471  bool rtl = _current_text_dir == TD_RTL;
1472  DrawSprite((this->folded ? SPR_CIRCLE_FOLDED : SPR_CIRCLE_UNFOLDED), PAL_NONE, rtl ? right - _circle_size.width : left, y + (SETTING_HEIGHT - _circle_size.height) / 2);
1473  DrawString(rtl ? left : left + _circle_size.width + 2, rtl ? right - _circle_size.width - 2 : right, y + (SETTING_HEIGHT - FONT_HEIGHT_NORMAL) / 2, this->title);
1474 }
1475 
1478 {
1479  static SettingsContainer *main = nullptr;
1480 
1481  if (main == nullptr)
1482  {
1483  /* Build up the dynamic settings-array only once per OpenTTD session */
1484  main = new SettingsContainer();
1485 
1486  SettingsPage *localisation = main->Add(new SettingsPage(STR_CONFIG_SETTING_LOCALISATION));
1487  {
1488  localisation->Add(new SettingEntry("locale.units_velocity"));
1489  localisation->Add(new SettingEntry("locale.units_power"));
1490  localisation->Add(new SettingEntry("locale.units_weight"));
1491  localisation->Add(new SettingEntry("locale.units_volume"));
1492  localisation->Add(new SettingEntry("locale.units_force"));
1493  localisation->Add(new SettingEntry("locale.units_height"));
1494  localisation->Add(new SettingEntry("gui.date_format_in_default_names"));
1495  }
1496 
1497  SettingsPage *graphics = main->Add(new SettingsPage(STR_CONFIG_SETTING_GRAPHICS));
1498  {
1499  graphics->Add(new SettingEntry("gui.zoom_min"));
1500  graphics->Add(new SettingEntry("gui.zoom_max"));
1501  graphics->Add(new SettingEntry("gui.smallmap_land_colour"));
1502  graphics->Add(new SettingEntry("gui.graph_line_thickness"));
1503  }
1504 
1505  SettingsPage *sound = main->Add(new SettingsPage(STR_CONFIG_SETTING_SOUND));
1506  {
1507  sound->Add(new SettingEntry("sound.click_beep"));
1508  sound->Add(new SettingEntry("sound.confirm"));
1509  sound->Add(new SettingEntry("sound.news_ticker"));
1510  sound->Add(new SettingEntry("sound.news_full"));
1511  sound->Add(new SettingEntry("sound.new_year"));
1512  sound->Add(new SettingEntry("sound.disaster"));
1513  sound->Add(new SettingEntry("sound.vehicle"));
1514  sound->Add(new SettingEntry("sound.ambient"));
1515  }
1516 
1517  SettingsPage *interface = main->Add(new SettingsPage(STR_CONFIG_SETTING_INTERFACE));
1518  {
1519  SettingsPage *general = interface->Add(new SettingsPage(STR_CONFIG_SETTING_INTERFACE_GENERAL));
1520  {
1521  general->Add(new SettingEntry("gui.osk_activation"));
1522  general->Add(new SettingEntry("gui.hover_delay_ms"));
1523  general->Add(new SettingEntry("gui.errmsg_duration"));
1524  general->Add(new SettingEntry("gui.window_snap_radius"));
1525  general->Add(new SettingEntry("gui.window_soft_limit"));
1526  general->Add(new SettingEntry("gui.right_mouse_wnd_close"));
1527  }
1528 
1529  SettingsPage *viewports = interface->Add(new SettingsPage(STR_CONFIG_SETTING_INTERFACE_VIEWPORTS));
1530  {
1531  viewports->Add(new SettingEntry("gui.auto_scrolling"));
1532  viewports->Add(new SettingEntry("gui.scroll_mode"));
1533  viewports->Add(new SettingEntry("gui.smooth_scroll"));
1534  /* While the horizontal scrollwheel scrolling is written as general code, only
1535  * the cocoa (OSX) driver generates input for it.
1536  * Since it's also able to completely disable the scrollwheel will we display it on all platforms anyway */
1537  viewports->Add(new SettingEntry("gui.scrollwheel_scrolling"));
1538  viewports->Add(new SettingEntry("gui.scrollwheel_multiplier"));
1539 #ifdef __APPLE__
1540  /* We might need to emulate a right mouse button on mac */
1541  viewports->Add(new SettingEntry("gui.right_mouse_btn_emulation"));
1542 #endif
1543  viewports->Add(new SettingEntry("gui.population_in_label"));
1544  viewports->Add(new SettingEntry("gui.liveries"));
1545  viewports->Add(new SettingEntry("construction.train_signal_side"));
1546  viewports->Add(new SettingEntry("gui.measure_tooltip"));
1547  viewports->Add(new SettingEntry("gui.loading_indicators"));
1548  viewports->Add(new SettingEntry("gui.show_track_reservation"));
1549  }
1550 
1551  SettingsPage *construction = interface->Add(new SettingsPage(STR_CONFIG_SETTING_INTERFACE_CONSTRUCTION));
1552  {
1553  construction->Add(new SettingEntry("gui.link_terraform_toolbar"));
1554  construction->Add(new SettingEntry("gui.enable_signal_gui"));
1555  construction->Add(new SettingEntry("gui.persistent_buildingtools"));
1556  construction->Add(new SettingEntry("gui.quick_goto"));
1557  construction->Add(new SettingEntry("gui.default_rail_type"));
1558  construction->Add(new SettingEntry("gui.disable_unsuitable_building"));
1559  }
1560 
1561  interface->Add(new SettingEntry("gui.autosave"));
1562  interface->Add(new SettingEntry("gui.toolbar_pos"));
1563  interface->Add(new SettingEntry("gui.statusbar_pos"));
1564  interface->Add(new SettingEntry("gui.prefer_teamchat"));
1565  interface->Add(new SettingEntry("gui.advanced_vehicle_list"));
1566  interface->Add(new SettingEntry("gui.timetable_in_ticks"));
1567  interface->Add(new SettingEntry("gui.timetable_arrival_departure"));
1568  interface->Add(new SettingEntry("gui.expenses_layout"));
1569  }
1570 
1571  SettingsPage *advisors = main->Add(new SettingsPage(STR_CONFIG_SETTING_ADVISORS));
1572  {
1573  advisors->Add(new SettingEntry("gui.coloured_news_year"));
1574  advisors->Add(new SettingEntry("news_display.general"));
1575  advisors->Add(new SettingEntry("news_display.new_vehicles"));
1576  advisors->Add(new SettingEntry("news_display.accident"));
1577  advisors->Add(new SettingEntry("news_display.company_info"));
1578  advisors->Add(new SettingEntry("news_display.acceptance"));
1579  advisors->Add(new SettingEntry("news_display.arrival_player"));
1580  advisors->Add(new SettingEntry("news_display.arrival_other"));
1581  advisors->Add(new SettingEntry("news_display.advice"));
1582  advisors->Add(new SettingEntry("gui.order_review_system"));
1583  advisors->Add(new SettingEntry("gui.vehicle_income_warn"));
1584  advisors->Add(new SettingEntry("gui.lost_vehicle_warn"));
1585  advisors->Add(new SettingEntry("gui.show_finances"));
1586  advisors->Add(new SettingEntry("news_display.economy"));
1587  advisors->Add(new SettingEntry("news_display.subsidies"));
1588  advisors->Add(new SettingEntry("news_display.open"));
1589  advisors->Add(new SettingEntry("news_display.close"));
1590  advisors->Add(new SettingEntry("news_display.production_player"));
1591  advisors->Add(new SettingEntry("news_display.production_other"));
1592  advisors->Add(new SettingEntry("news_display.production_nobody"));
1593  }
1594 
1595  SettingsPage *company = main->Add(new SettingsPage(STR_CONFIG_SETTING_COMPANY));
1596  {
1597  company->Add(new SettingEntry("gui.semaphore_build_before"));
1598  company->Add(new SettingEntry("gui.default_signal_type"));
1599  company->Add(new SettingEntry("gui.cycle_signal_types"));
1600  company->Add(new SettingEntry("gui.drag_signals_fixed_distance"));
1601  company->Add(new SettingEntry("gui.new_nonstop"));
1602  company->Add(new SettingEntry("gui.stop_location"));
1603  company->Add(new SettingEntry("gui.starting_colour"));
1604  company->Add(new SettingEntry("company.engine_renew"));
1605  company->Add(new SettingEntry("company.engine_renew_months"));
1606  company->Add(new SettingEntry("company.engine_renew_money"));
1607  company->Add(new SettingEntry("vehicle.servint_ispercent"));
1608  company->Add(new SettingEntry("vehicle.servint_trains"));
1609  company->Add(new SettingEntry("vehicle.servint_roadveh"));
1610  company->Add(new SettingEntry("vehicle.servint_ships"));
1611  company->Add(new SettingEntry("vehicle.servint_aircraft"));
1612  }
1613 
1614  SettingsPage *accounting = main->Add(new SettingsPage(STR_CONFIG_SETTING_ACCOUNTING));
1615  {
1616  accounting->Add(new SettingEntry("economy.inflation"));
1617  accounting->Add(new SettingEntry("difficulty.initial_interest"));
1618  accounting->Add(new SettingEntry("difficulty.max_loan"));
1619  accounting->Add(new SettingEntry("difficulty.subsidy_multiplier"));
1620  accounting->Add(new SettingEntry("economy.feeder_payment_share"));
1621  accounting->Add(new SettingEntry("economy.infrastructure_maintenance"));
1622  accounting->Add(new SettingEntry("difficulty.vehicle_costs"));
1623  accounting->Add(new SettingEntry("difficulty.construction_cost"));
1624  }
1625 
1626  SettingsPage *vehicles = main->Add(new SettingsPage(STR_CONFIG_SETTING_VEHICLES));
1627  {
1628  SettingsPage *physics = vehicles->Add(new SettingsPage(STR_CONFIG_SETTING_VEHICLES_PHYSICS));
1629  {
1630  physics->Add(new SettingEntry("vehicle.train_acceleration_model"));
1631  physics->Add(new SettingEntry("vehicle.train_slope_steepness"));
1632  physics->Add(new SettingEntry("vehicle.wagon_speed_limits"));
1633  physics->Add(new SettingEntry("vehicle.freight_trains"));
1634  physics->Add(new SettingEntry("vehicle.roadveh_acceleration_model"));
1635  physics->Add(new SettingEntry("vehicle.roadveh_slope_steepness"));
1636  physics->Add(new SettingEntry("vehicle.smoke_amount"));
1637  physics->Add(new SettingEntry("vehicle.plane_speed"));
1638  }
1639 
1640  SettingsPage *routing = vehicles->Add(new SettingsPage(STR_CONFIG_SETTING_VEHICLES_ROUTING));
1641  {
1642  routing->Add(new SettingEntry("pf.pathfinder_for_trains"));
1643  routing->Add(new SettingEntry("difficulty.line_reverse_mode"));
1644  routing->Add(new SettingEntry("pf.reverse_at_signals"));
1645  routing->Add(new SettingEntry("pf.forbid_90_deg"));
1646  routing->Add(new SettingEntry("pf.pathfinder_for_roadvehs"));
1647  routing->Add(new SettingEntry("pf.pathfinder_for_ships"));
1648  }
1649 
1650  vehicles->Add(new SettingEntry("order.no_servicing_if_no_breakdowns"));
1651  vehicles->Add(new SettingEntry("order.serviceathelipad"));
1652  }
1653 
1654  SettingsPage *limitations = main->Add(new SettingsPage(STR_CONFIG_SETTING_LIMITATIONS));
1655  {
1656  limitations->Add(new SettingEntry("construction.command_pause_level"));
1657  limitations->Add(new SettingEntry("construction.autoslope"));
1658  limitations->Add(new SettingEntry("construction.extra_dynamite"));
1659  limitations->Add(new SettingEntry("construction.max_heightlevel"));
1660  limitations->Add(new SettingEntry("construction.max_bridge_length"));
1661  limitations->Add(new SettingEntry("construction.max_bridge_height"));
1662  limitations->Add(new SettingEntry("construction.max_tunnel_length"));
1663  limitations->Add(new SettingEntry("station.never_expire_airports"));
1664  limitations->Add(new SettingEntry("vehicle.never_expire_vehicles"));
1665  limitations->Add(new SettingEntry("vehicle.max_trains"));
1666  limitations->Add(new SettingEntry("vehicle.max_roadveh"));
1667  limitations->Add(new SettingEntry("vehicle.max_aircraft"));
1668  limitations->Add(new SettingEntry("vehicle.max_ships"));
1669  limitations->Add(new SettingEntry("vehicle.max_train_length"));
1670  limitations->Add(new SettingEntry("station.station_spread"));
1671  limitations->Add(new SettingEntry("station.distant_join_stations"));
1672  limitations->Add(new SettingEntry("construction.road_stop_on_town_road"));
1673  limitations->Add(new SettingEntry("construction.road_stop_on_competitor_road"));
1674  limitations->Add(new SettingEntry("vehicle.disable_elrails"));
1675  }
1676 
1677  SettingsPage *disasters = main->Add(new SettingsPage(STR_CONFIG_SETTING_ACCIDENTS));
1678  {
1679  disasters->Add(new SettingEntry("difficulty.disasters"));
1680  disasters->Add(new SettingEntry("difficulty.economy"));
1681  disasters->Add(new SettingEntry("difficulty.vehicle_breakdowns"));
1682  disasters->Add(new SettingEntry("vehicle.plane_crashes"));
1683  }
1684 
1685  SettingsPage *genworld = main->Add(new SettingsPage(STR_CONFIG_SETTING_GENWORLD));
1686  {
1687  genworld->Add(new SettingEntry("game_creation.landscape"));
1688  genworld->Add(new SettingEntry("game_creation.land_generator"));
1689  genworld->Add(new SettingEntry("difficulty.terrain_type"));
1690  genworld->Add(new SettingEntry("game_creation.tgen_smoothness"));
1691  genworld->Add(new SettingEntry("game_creation.variety"));
1692  genworld->Add(new SettingEntry("game_creation.snow_line_height"));
1693  genworld->Add(new SettingEntry("game_creation.amount_of_rivers"));
1694  genworld->Add(new SettingEntry("game_creation.tree_placer"));
1695  genworld->Add(new SettingEntry("vehicle.road_side"));
1696  genworld->Add(new SettingEntry("economy.larger_towns"));
1697  genworld->Add(new SettingEntry("economy.initial_city_size"));
1698  genworld->Add(new SettingEntry("economy.town_layout"));
1699  genworld->Add(new SettingEntry("difficulty.industry_density"));
1700  genworld->Add(new SettingEntry("gui.pause_on_newgame"));
1701  }
1702 
1703  SettingsPage *environment = main->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT));
1704  {
1705  SettingsPage *authorities = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_AUTHORITIES));
1706  {
1707  authorities->Add(new SettingEntry("difficulty.town_council_tolerance"));
1708  authorities->Add(new SettingEntry("economy.bribe"));
1709  authorities->Add(new SettingEntry("economy.exclusive_rights"));
1710  authorities->Add(new SettingEntry("economy.fund_roads"));
1711  authorities->Add(new SettingEntry("economy.fund_buildings"));
1712  authorities->Add(new SettingEntry("economy.station_noise_level"));
1713  }
1714 
1715  SettingsPage *towns = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_TOWNS));
1716  {
1717  towns->Add(new SettingEntry("economy.town_growth_rate"));
1718  towns->Add(new SettingEntry("economy.allow_town_roads"));
1719  towns->Add(new SettingEntry("economy.allow_town_level_crossings"));
1720  towns->Add(new SettingEntry("economy.found_town"));
1721  towns->Add(new SettingEntry("economy.town_cargogen_mode"));
1722  }
1723 
1724  SettingsPage *industries = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_INDUSTRIES));
1725  {
1726  industries->Add(new SettingEntry("construction.raw_industry_construction"));
1727  industries->Add(new SettingEntry("construction.industry_platform"));
1728  industries->Add(new SettingEntry("economy.multiple_industry_per_town"));
1729  industries->Add(new SettingEntry("game_creation.oil_refinery_limit"));
1730  industries->Add(new SettingEntry("economy.smooth_economy"));
1731  industries->Add(new SettingEntry("station.serve_neutral_industries"));
1732  }
1733 
1734  SettingsPage *cdist = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_CARGODIST));
1735  {
1736  cdist->Add(new SettingEntry("linkgraph.recalc_time"));
1737  cdist->Add(new SettingEntry("linkgraph.recalc_interval"));
1738  cdist->Add(new SettingEntry("linkgraph.distribution_pax"));
1739  cdist->Add(new SettingEntry("linkgraph.distribution_mail"));
1740  cdist->Add(new SettingEntry("linkgraph.distribution_armoured"));
1741  cdist->Add(new SettingEntry("linkgraph.distribution_default"));
1742  cdist->Add(new SettingEntry("linkgraph.accuracy"));
1743  cdist->Add(new SettingEntry("linkgraph.demand_distance"));
1744  cdist->Add(new SettingEntry("linkgraph.demand_size"));
1745  cdist->Add(new SettingEntry("linkgraph.short_path_saturation"));
1746  }
1747 
1748  environment->Add(new SettingEntry("station.modified_catchment"));
1749  environment->Add(new SettingEntry("construction.extra_tree_placement"));
1750  }
1751 
1752  SettingsPage *ai = main->Add(new SettingsPage(STR_CONFIG_SETTING_AI));
1753  {
1754  SettingsPage *npc = ai->Add(new SettingsPage(STR_CONFIG_SETTING_AI_NPC));
1755  {
1756  npc->Add(new SettingEntry("script.settings_profile"));
1757  npc->Add(new SettingEntry("script.script_max_opcode_till_suspend"));
1758  npc->Add(new SettingEntry("script.script_max_memory_megabytes"));
1759  npc->Add(new SettingEntry("difficulty.competitor_speed"));
1760  npc->Add(new SettingEntry("ai.ai_in_multiplayer"));
1761  npc->Add(new SettingEntry("ai.ai_disable_veh_train"));
1762  npc->Add(new SettingEntry("ai.ai_disable_veh_roadveh"));
1763  npc->Add(new SettingEntry("ai.ai_disable_veh_aircraft"));
1764  npc->Add(new SettingEntry("ai.ai_disable_veh_ship"));
1765  }
1766 
1767  ai->Add(new SettingEntry("economy.give_money"));
1768  ai->Add(new SettingEntry("economy.allow_shares"));
1769  ai->Add(new SettingEntry("economy.min_years_for_shares"));
1770  }
1771 
1772  main->Init();
1773  }
1774  return *main;
1775 }
1776 
1777 static const StringID _game_settings_restrict_dropdown[] = {
1778  STR_CONFIG_SETTING_RESTRICT_BASIC, // RM_BASIC
1779  STR_CONFIG_SETTING_RESTRICT_ADVANCED, // RM_ADVANCED
1780  STR_CONFIG_SETTING_RESTRICT_ALL, // RM_ALL
1781  STR_CONFIG_SETTING_RESTRICT_CHANGED_AGAINST_DEFAULT, // RM_CHANGED_AGAINST_DEFAULT
1782  STR_CONFIG_SETTING_RESTRICT_CHANGED_AGAINST_NEW, // RM_CHANGED_AGAINST_NEW
1783 };
1784 assert_compile(lengthof(_game_settings_restrict_dropdown) == RM_END);
1785 
1792 };
1793 
1796  static const int SETTINGTREE_LEFT_OFFSET = 5;
1797  static const int SETTINGTREE_RIGHT_OFFSET = 5;
1798  static const int SETTINGTREE_TOP_OFFSET = 5;
1799  static const int SETTINGTREE_BOTTOM_OFFSET = 5;
1800 
1802 
1808 
1814 
1815  Scrollbar *vscroll;
1816 
1817  GameSettingsWindow(WindowDesc *desc) : Window(desc), filter_editbox(50)
1818  {
1819  this->warn_missing = WHR_NONE;
1820  this->warn_lines = 0;
1822  this->filter.min_cat = RM_ALL;
1823  this->filter.type = ST_ALL;
1824  this->filter.type_hides = false;
1825  this->settings_ptr = &GetGameSettings();
1826 
1827  _circle_size = maxdim(GetSpriteSize(SPR_CIRCLE_FOLDED), GetSpriteSize(SPR_CIRCLE_UNFOLDED));
1828  GetSettingsTree().FoldAll(); // Close all sub-pages
1829 
1830  this->valuewindow_entry = nullptr; // No setting entry for which a entry window is opened
1831  this->clicked_entry = nullptr; // No numeric setting buttons are depressed
1832  this->last_clicked = nullptr;
1833  this->valuedropdown_entry = nullptr;
1834  this->closing_dropdown = false;
1835  this->manually_changed_folding = false;
1836 
1837  this->CreateNestedTree();
1838  this->vscroll = this->GetScrollbar(WID_GS_SCROLLBAR);
1840 
1841  this->querystrings[WID_GS_FILTER] = &this->filter_editbox;
1842  this->filter_editbox.cancel_button = QueryString::ACTION_CLEAR;
1844 
1845  this->InvalidateData();
1846  }
1847 
1848  void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override
1849  {
1850  switch (widget) {
1851  case WID_GS_OPTIONSPANEL:
1852  resize->height = SETTING_HEIGHT = max(max<int>(_circle_size.height, SETTING_BUTTON_HEIGHT), FONT_HEIGHT_NORMAL) + 1;
1853  resize->width = 1;
1854 
1855  size->height = 5 * resize->height + SETTINGTREE_TOP_OFFSET + SETTINGTREE_BOTTOM_OFFSET;
1856  break;
1857 
1858  case WID_GS_HELP_TEXT: {
1859  static const StringID setting_types[] = {
1860  STR_CONFIG_SETTING_TYPE_CLIENT,
1861  STR_CONFIG_SETTING_TYPE_COMPANY_MENU, STR_CONFIG_SETTING_TYPE_COMPANY_INGAME,
1862  STR_CONFIG_SETTING_TYPE_GAME_MENU, STR_CONFIG_SETTING_TYPE_GAME_INGAME,
1863  };
1864  for (uint i = 0; i < lengthof(setting_types); i++) {
1865  SetDParam(0, setting_types[i]);
1866  size->width = max(size->width, GetStringBoundingBox(STR_CONFIG_SETTING_TYPE).width);
1867  }
1868  size->height = 2 * FONT_HEIGHT_NORMAL + WD_PAR_VSEP_NORMAL +
1869  max(size->height, GetSettingsTree().GetMaxHelpHeight(size->width));
1870  break;
1871  }
1872 
1874  case WID_GS_RESTRICT_TYPE:
1875  size->width = max(GetStringBoundingBox(STR_CONFIG_SETTING_RESTRICT_CATEGORY).width, GetStringBoundingBox(STR_CONFIG_SETTING_RESTRICT_TYPE).width);
1876  break;
1877 
1878  default:
1879  break;
1880  }
1881  }
1882 
1883  void OnPaint() override
1884  {
1885  if (this->closing_dropdown) {
1886  this->closing_dropdown = false;
1887  assert(this->valuedropdown_entry != nullptr);
1888  this->valuedropdown_entry->SetButtons(0);
1889  this->valuedropdown_entry = nullptr;
1890  }
1891 
1892  /* Reserve the correct number of lines for the 'some search results are hidden' notice in the central settings display panel. */
1893  const NWidgetBase *panel = this->GetWidget<NWidgetBase>(WID_GS_OPTIONSPANEL);
1894  StringID warn_str = STR_CONFIG_SETTING_CATEGORY_HIDES - 1 + this->warn_missing;
1895  int new_warn_lines;
1896  if (this->warn_missing == WHR_NONE) {
1897  new_warn_lines = 0;
1898  } else {
1899  SetDParam(0, _game_settings_restrict_dropdown[this->filter.min_cat]);
1900  new_warn_lines = GetStringLineCount(warn_str, panel->current_x);
1901  }
1902  if (this->warn_lines != new_warn_lines) {
1903  this->vscroll->SetCount(this->vscroll->GetCount() - this->warn_lines + new_warn_lines);
1904  this->warn_lines = new_warn_lines;
1905  }
1906 
1907  this->DrawWidgets();
1908 
1909  /* Draw the 'some search results are hidden' notice. */
1910  if (this->warn_missing != WHR_NONE) {
1911  const int left = panel->pos_x;
1912  const int right = left + panel->current_x - 1;
1913  const int top = panel->pos_y + WD_FRAMETEXT_TOP + (SETTING_HEIGHT - FONT_HEIGHT_NORMAL) * this->warn_lines / 2;
1914  SetDParam(0, _game_settings_restrict_dropdown[this->filter.min_cat]);
1915  if (this->warn_lines == 1) {
1916  /* If the warning fits at one line, center it. */
1917  DrawString(left + WD_FRAMETEXT_LEFT, right - WD_FRAMETEXT_RIGHT, top, warn_str, TC_FROMSTRING, SA_HOR_CENTER);
1918  } else {
1919  DrawStringMultiLine(left + WD_FRAMERECT_LEFT, right - WD_FRAMERECT_RIGHT, top, INT32_MAX, warn_str, TC_FROMSTRING, SA_HOR_CENTER);
1920  }
1921  }
1922  }
1923 
1924  void SetStringParameters(int widget) const override
1925  {
1926  switch (widget) {
1928  SetDParam(0, _game_settings_restrict_dropdown[this->filter.mode]);
1929  break;
1930 
1931  case WID_GS_TYPE_DROPDOWN:
1932  switch (this->filter.type) {
1933  case ST_GAME: SetDParam(0, _game_mode == GM_MENU ? STR_CONFIG_SETTING_TYPE_DROPDOWN_GAME_MENU : STR_CONFIG_SETTING_TYPE_DROPDOWN_GAME_INGAME); break;
1934  case ST_COMPANY: SetDParam(0, _game_mode == GM_MENU ? STR_CONFIG_SETTING_TYPE_DROPDOWN_COMPANY_MENU : STR_CONFIG_SETTING_TYPE_DROPDOWN_COMPANY_INGAME); break;
1935  case ST_CLIENT: SetDParam(0, STR_CONFIG_SETTING_TYPE_DROPDOWN_CLIENT); break;
1936  default: SetDParam(0, STR_CONFIG_SETTING_TYPE_DROPDOWN_ALL); break;
1937  }
1938  break;
1939  }
1940  }
1941 
1942  DropDownList BuildDropDownList(int widget) const
1943  {
1944  DropDownList list;
1945  switch (widget) {
1947  for (int mode = 0; mode != RM_END; mode++) {
1948  /* If we are in adv. settings screen for the new game's settings,
1949  * we don't want to allow comparing with new game's settings. */
1950  bool disabled = mode == RM_CHANGED_AGAINST_NEW && settings_ptr == &_settings_newgame;
1951 
1952  list.emplace_back(new DropDownListStringItem(_game_settings_restrict_dropdown[mode], mode, disabled));
1953  }
1954  break;
1955 
1956  case WID_GS_TYPE_DROPDOWN:
1957  list.emplace_back(new DropDownListStringItem(STR_CONFIG_SETTING_TYPE_DROPDOWN_ALL, ST_ALL, false));
1958  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));
1959  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));
1960  list.emplace_back(new DropDownListStringItem(STR_CONFIG_SETTING_TYPE_DROPDOWN_CLIENT, ST_CLIENT, false));
1961  break;
1962  }
1963  return list;
1964  }
1965 
1966  void DrawWidget(const Rect &r, int widget) const override
1967  {
1968  switch (widget) {
1969  case WID_GS_OPTIONSPANEL: {
1970  int top_pos = r.top + SETTINGTREE_TOP_OFFSET + 1 + this->warn_lines * SETTING_HEIGHT;
1971  uint last_row = this->vscroll->GetPosition() + this->vscroll->GetCapacity() - this->warn_lines;
1972  int next_row = GetSettingsTree().Draw(settings_ptr, r.left + SETTINGTREE_LEFT_OFFSET, r.right - SETTINGTREE_RIGHT_OFFSET, top_pos,
1973  this->vscroll->GetPosition(), last_row, this->last_clicked);
1974  if (next_row == 0) DrawString(r.left + SETTINGTREE_LEFT_OFFSET, r.right - SETTINGTREE_RIGHT_OFFSET, top_pos, STR_CONFIG_SETTINGS_NONE);
1975  break;
1976  }
1977 
1978  case WID_GS_HELP_TEXT:
1979  if (this->last_clicked != nullptr) {
1980  const SettingDesc *sd = this->last_clicked->setting;
1981 
1982  int y = r.top;
1983  switch (sd->GetType()) {
1984  case ST_COMPANY: SetDParam(0, _game_mode == GM_MENU ? STR_CONFIG_SETTING_TYPE_COMPANY_MENU : STR_CONFIG_SETTING_TYPE_COMPANY_INGAME); break;
1985  case ST_CLIENT: SetDParam(0, STR_CONFIG_SETTING_TYPE_CLIENT); break;
1986  case ST_GAME: SetDParam(0, _game_mode == GM_MENU ? STR_CONFIG_SETTING_TYPE_GAME_MENU : STR_CONFIG_SETTING_TYPE_GAME_INGAME); break;
1987  default: NOT_REACHED();
1988  }
1989  DrawString(r.left, r.right, y, STR_CONFIG_SETTING_TYPE);
1990  y += FONT_HEIGHT_NORMAL;
1991 
1992  int32 default_value = ReadValue(&sd->desc.def, sd->save.conv);
1993  this->last_clicked->SetValueDParams(0, default_value);
1994  DrawString(r.left, r.right, y, STR_CONFIG_SETTING_DEFAULT_VALUE);
1996 
1997  DrawStringMultiLine(r.left, r.right, y, r.bottom, this->last_clicked->GetHelpText(), TC_WHITE);
1998  }
1999  break;
2000 
2001  default:
2002  break;
2003  }
2004  }
2005 
2011  {
2012  if (this->last_clicked != pe) this->SetDirty();
2013  this->last_clicked = pe;
2014  }
2015 
2016  void OnClick(Point pt, int widget, int click_count) override
2017  {
2018  switch (widget) {
2019  case WID_GS_EXPAND_ALL:
2020  this->manually_changed_folding = true;
2022  this->InvalidateData();
2023  break;
2024 
2025  case WID_GS_COLLAPSE_ALL:
2026  this->manually_changed_folding = true;
2028  this->InvalidateData();
2029  break;
2030 
2031  case WID_GS_RESTRICT_DROPDOWN: {
2032  DropDownList list = this->BuildDropDownList(widget);
2033  if (!list.empty()) {
2034  ShowDropDownList(this, std::move(list), this->filter.mode, widget);
2035  }
2036  break;
2037  }
2038 
2039  case WID_GS_TYPE_DROPDOWN: {
2040  DropDownList list = this->BuildDropDownList(widget);
2041  if (!list.empty()) {
2042  ShowDropDownList(this, std::move(list), this->filter.type, widget);
2043  }
2044  break;
2045  }
2046  }
2047 
2048  if (widget != WID_GS_OPTIONSPANEL) return;
2049 
2050  uint btn = this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_GS_OPTIONSPANEL, SETTINGTREE_TOP_OFFSET);
2051  if (btn == INT_MAX || (int)btn < this->warn_lines) return;
2052  btn -= this->warn_lines;
2053 
2054  uint cur_row = 0;
2055  BaseSettingEntry *clicked_entry = GetSettingsTree().FindEntry(btn, &cur_row);
2056 
2057  if (clicked_entry == nullptr) return; // Clicked below the last setting of the page
2058 
2059  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
2060  if (x < 0) return; // Clicked left of the entry
2061 
2062  SettingsPage *clicked_page = dynamic_cast<SettingsPage*>(clicked_entry);
2063  if (clicked_page != nullptr) {
2064  this->SetDisplayedHelpText(nullptr);
2065  clicked_page->folded = !clicked_page->folded; // Flip 'folded'-ness of the sub-page
2066 
2067  this->manually_changed_folding = true;
2068 
2069  this->InvalidateData();
2070  return;
2071  }
2072 
2073  SettingEntry *pe = dynamic_cast<SettingEntry*>(clicked_entry);
2074  assert(pe != nullptr);
2075  const SettingDesc *sd = pe->setting;
2076 
2077  /* return if action is only active in network, or only settable by server */
2078  if (!sd->IsEditable()) {
2079  this->SetDisplayedHelpText(pe);
2080  return;
2081  }
2082 
2083  const void *var = ResolveVariableAddress(settings_ptr, sd);
2084  int32 value = (int32)ReadValue(var, sd->save.conv);
2085 
2086  /* clicked on the icon on the left side. Either scroller, bool on/off or dropdown */
2087  if (x < SETTING_BUTTON_WIDTH && (sd->desc.flags & SGF_MULTISTRING)) {
2088  const SettingDescBase *sdb = &sd->desc;
2089  this->SetDisplayedHelpText(pe);
2090 
2091  if (this->valuedropdown_entry == pe) {
2092  /* unclick the dropdown */
2093  HideDropDownMenu(this);
2094  this->closing_dropdown = false;
2095  this->valuedropdown_entry->SetButtons(0);
2096  this->valuedropdown_entry = nullptr;
2097  } else {
2098  if (this->valuedropdown_entry != nullptr) this->valuedropdown_entry->SetButtons(0);
2099  this->closing_dropdown = false;
2100 
2101  const NWidgetBase *wid = this->GetWidget<NWidgetBase>(WID_GS_OPTIONSPANEL);
2102  int rel_y = (pt.y - (int)wid->pos_y - SETTINGTREE_TOP_OFFSET) % wid->resize_y;
2103 
2104  Rect wi_rect;
2105  wi_rect.left = pt.x - (_current_text_dir == TD_RTL ? SETTING_BUTTON_WIDTH - 1 - x : x);
2106  wi_rect.right = wi_rect.left + SETTING_BUTTON_WIDTH - 1;
2107  wi_rect.top = pt.y - rel_y + (SETTING_HEIGHT - SETTING_BUTTON_HEIGHT) / 2;
2108  wi_rect.bottom = wi_rect.top + SETTING_BUTTON_HEIGHT - 1;
2109 
2110  /* For dropdowns we also have to check the y position thoroughly, the mouse may not above the just opening dropdown */
2111  if (pt.y >= wi_rect.top && pt.y <= wi_rect.bottom) {
2112  this->valuedropdown_entry = pe;
2113  this->valuedropdown_entry->SetButtons(SEF_LEFT_DEPRESSED);
2114 
2115  DropDownList list;
2116  for (int i = sdb->min; i <= (int)sdb->max; i++) {
2117  list.emplace_back(new DropDownListStringItem(sdb->str_val + i - sdb->min, i, false));
2118  }
2119 
2120  ShowDropDownListAt(this, std::move(list), value, -1, wi_rect, COLOUR_ORANGE, true);
2121  }
2122  }
2123  this->SetDirty();
2124  } else if (x < SETTING_BUTTON_WIDTH) {
2125  this->SetDisplayedHelpText(pe);
2126  const SettingDescBase *sdb = &sd->desc;
2127  int32 oldvalue = value;
2128 
2129  switch (sdb->cmd) {
2130  case SDT_BOOLX: value ^= 1; break;
2131  case SDT_ONEOFMANY:
2132  case SDT_NUMX: {
2133  /* Add a dynamic step-size to the scroller. In a maximum of
2134  * 50-steps you should be able to get from min to max,
2135  * unless specified otherwise in the 'interval' variable
2136  * of the current setting. */
2137  uint32 step = (sdb->interval == 0) ? ((sdb->max - sdb->min) / 50) : sdb->interval;
2138  if (step == 0) step = 1;
2139 
2140  /* don't allow too fast scrolling */
2141  if ((this->flags & WF_TIMEOUT) && this->timeout_timer > 1) {
2142  _left_button_clicked = false;
2143  return;
2144  }
2145 
2146  /* Increase or decrease the value and clamp it to extremes */
2147  if (x >= SETTING_BUTTON_WIDTH / 2) {
2148  value += step;
2149  if (sdb->min < 0) {
2150  assert((int32)sdb->max >= 0);
2151  if (value > (int32)sdb->max) value = (int32)sdb->max;
2152  } else {
2153  if ((uint32)value > sdb->max) value = (int32)sdb->max;
2154  }
2155  if (value < sdb->min) value = sdb->min; // skip between "disabled" and minimum
2156  } else {
2157  value -= step;
2158  if (value < sdb->min) value = (sdb->flags & SGF_0ISDISABLED) ? 0 : sdb->min;
2159  }
2160 
2161  /* Set up scroller timeout for numeric values */
2162  if (value != oldvalue) {
2163  if (this->clicked_entry != nullptr) { // Release previous buttons if any
2164  this->clicked_entry->SetButtons(0);
2165  }
2166  this->clicked_entry = pe;
2167  this->clicked_entry->SetButtons((x >= SETTING_BUTTON_WIDTH / 2) != (_current_text_dir == TD_RTL) ? SEF_RIGHT_DEPRESSED : SEF_LEFT_DEPRESSED);
2168  this->SetTimeout();
2169  _left_button_clicked = false;
2170  }
2171  break;
2172  }
2173 
2174  default: NOT_REACHED();
2175  }
2176 
2177  if (value != oldvalue) {
2178  if ((sd->desc.flags & SGF_PER_COMPANY) != 0) {
2179  SetCompanySetting(pe->index, value);
2180  } else {
2181  SetSettingValue(pe->index, value);
2182  }
2183  this->SetDirty();
2184  }
2185  } else {
2186  /* Only open editbox if clicked for the second time, and only for types where it is sensible for. */
2187  if (this->last_clicked == pe && sd->desc.cmd != SDT_BOOLX && !(sd->desc.flags & SGF_MULTISTRING)) {
2188  /* Show the correct currency-translated value */
2189  if (sd->desc.flags & SGF_CURRENCY) value *= _currency->rate;
2190 
2191  this->valuewindow_entry = pe;
2192  SetDParam(0, value);
2193  ShowQueryString(STR_JUST_INT, STR_CONFIG_SETTING_QUERY_CAPTION, 10, this, CS_NUMERAL, QSF_ENABLE_DEFAULT);
2194  }
2195  this->SetDisplayedHelpText(pe);
2196  }
2197  }
2198 
2199  void OnTimeout() override
2200  {
2201  if (this->clicked_entry != nullptr) { // On timeout, release any depressed buttons
2202  this->clicked_entry->SetButtons(0);
2203  this->clicked_entry = nullptr;
2204  this->SetDirty();
2205  }
2206  }
2207 
2208  void OnQueryTextFinished(char *str) override
2209  {
2210  /* The user pressed cancel */
2211  if (str == nullptr) return;
2212 
2213  assert(this->valuewindow_entry != nullptr);
2214  const SettingDesc *sd = this->valuewindow_entry->setting;
2215 
2216  int32 value;
2217  if (!StrEmpty(str)) {
2218  value = atoi(str);
2219 
2220  /* Save the correct currency-translated value */
2221  if (sd->desc.flags & SGF_CURRENCY) value /= _currency->rate;
2222  } else {
2223  value = (int32)(size_t)sd->desc.def;
2224  }
2225 
2226  if ((sd->desc.flags & SGF_PER_COMPANY) != 0) {
2227  SetCompanySetting(this->valuewindow_entry->index, value);
2228  } else {
2229  SetSettingValue(this->valuewindow_entry->index, value);
2230  }
2231  this->SetDirty();
2232  }
2233 
2234  void OnDropdownSelect(int widget, int index) override
2235  {
2236  switch (widget) {
2238  this->filter.mode = (RestrictionMode)index;
2239  if (this->filter.mode == RM_CHANGED_AGAINST_DEFAULT ||
2240  this->filter.mode == RM_CHANGED_AGAINST_NEW) {
2241 
2242  if (!this->manually_changed_folding) {
2243  /* Expand all when selecting 'changes'. Update the filter state first, in case it becomes less restrictive in some cases. */
2244  GetSettingsTree().UpdateFilterState(this->filter, false);
2246  }
2247  } else {
2248  /* Non-'changes' filter. Save as default. */
2250  }
2251  this->InvalidateData();
2252  break;
2253 
2254  case WID_GS_TYPE_DROPDOWN:
2255  this->filter.type = (SettingType)index;
2256  this->InvalidateData();
2257  break;
2258 
2259  default:
2260  if (widget < 0) {
2261  /* Deal with drop down boxes on the panel. */
2262  assert(this->valuedropdown_entry != nullptr);
2263  const SettingDesc *sd = this->valuedropdown_entry->setting;
2264  assert(sd->desc.flags & SGF_MULTISTRING);
2265 
2266  if ((sd->desc.flags & SGF_PER_COMPANY) != 0) {
2267  SetCompanySetting(this->valuedropdown_entry->index, index);
2268  } else {
2269  SetSettingValue(this->valuedropdown_entry->index, index);
2270  }
2271 
2272  this->SetDirty();
2273  }
2274  break;
2275  }
2276  }
2277 
2278  void OnDropdownClose(Point pt, int widget, int index, bool instant_close) override
2279  {
2280  if (widget >= 0) {
2281  /* Normally the default implementation of OnDropdownClose() takes care of
2282  * a few things. We want that behaviour here too, but only for
2283  * "normal" dropdown boxes. The special dropdown boxes added for every
2284  * setting that needs one can't have this call. */
2285  Window::OnDropdownClose(pt, widget, index, instant_close);
2286  } else {
2287  /* We cannot raise the dropdown button just yet. OnClick needs some hint, whether
2288  * the same dropdown button was clicked again, and then not open the dropdown again.
2289  * So, we only remember that it was closed, and process it on the next OnPaint, which is
2290  * after OnClick. */
2291  assert(this->valuedropdown_entry != nullptr);
2292  this->closing_dropdown = true;
2293  this->SetDirty();
2294  }
2295  }
2296 
2297  void OnInvalidateData(int data = 0, bool gui_scope = true) override
2298  {
2299  if (!gui_scope) return;
2300 
2301  /* Update which settings are to be visible. */
2302  RestrictionMode min_level = (this->filter.mode <= RM_ALL) ? this->filter.mode : RM_BASIC;
2303  this->filter.min_cat = min_level;
2304  this->filter.type_hides = false;
2305  GetSettingsTree().UpdateFilterState(this->filter, false);
2306 
2307  if (this->filter.string.IsEmpty()) {
2308  this->warn_missing = WHR_NONE;
2309  } else if (min_level < this->filter.min_cat) {
2310  this->warn_missing = this->filter.type_hides ? WHR_CATEGORY_TYPE : WHR_CATEGORY;
2311  } else {
2312  this->warn_missing = this->filter.type_hides ? WHR_TYPE : WHR_NONE;
2313  }
2314  this->vscroll->SetCount(GetSettingsTree().Length() + this->warn_lines);
2315 
2316  if (this->last_clicked != nullptr && !GetSettingsTree().IsVisible(this->last_clicked)) {
2317  this->SetDisplayedHelpText(nullptr);
2318  }
2319 
2320  bool all_folded = true;
2321  bool all_unfolded = true;
2322  GetSettingsTree().GetFoldingState(all_folded, all_unfolded);
2323  this->SetWidgetDisabledState(WID_GS_EXPAND_ALL, all_unfolded);
2324  this->SetWidgetDisabledState(WID_GS_COLLAPSE_ALL, all_folded);
2325  }
2326 
2327  void OnEditboxChanged(int wid) override
2328  {
2329  if (wid == WID_GS_FILTER) {
2330  this->filter.string.SetFilterTerm(this->filter_editbox.text.buf);
2331  if (!this->filter.string.IsEmpty() && !this->manually_changed_folding) {
2332  /* User never expanded/collapsed single pages and entered a filter term.
2333  * Expand everything, to save weird expand clicks, */
2335  }
2336  this->InvalidateData();
2337  }
2338  }
2339 
2340  void OnResize() override
2341  {
2342  this->vscroll->SetCapacityFromWidget(this, WID_GS_OPTIONSPANEL, SETTINGTREE_TOP_OFFSET + SETTINGTREE_BOTTOM_OFFSET);
2343  }
2344 };
2345 
2347 
2348 static const NWidgetPart _nested_settings_selection_widgets[] = {
2350  NWidget(WWT_CLOSEBOX, COLOUR_MAUVE),
2351  NWidget(WWT_CAPTION, COLOUR_MAUVE), SetDataTip(STR_CONFIG_SETTING_TREE_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
2352  NWidget(WWT_DEFSIZEBOX, COLOUR_MAUVE),
2353  EndContainer(),
2354  NWidget(WWT_PANEL, COLOUR_MAUVE),
2357  NWidget(WWT_TEXT, COLOUR_MAUVE, WID_GS_RESTRICT_CATEGORY), SetDataTip(STR_CONFIG_SETTING_RESTRICT_CATEGORY, STR_NULL),
2358  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),
2359  EndContainer(),
2361  NWidget(WWT_TEXT, COLOUR_MAUVE, WID_GS_RESTRICT_TYPE), SetDataTip(STR_CONFIG_SETTING_RESTRICT_TYPE, STR_NULL),
2362  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),
2363  EndContainer(),
2364  EndContainer(),
2367  NWidget(WWT_TEXT, COLOUR_MAUVE), SetFill(0, 1), SetDataTip(STR_CONFIG_SETTING_FILTER_TITLE, STR_NULL),
2368  NWidget(WWT_EDITBOX, COLOUR_MAUVE, WID_GS_FILTER), SetFill(1, 0), SetMinimalSize(50, 12), SetResize(1, 0),
2369  SetDataTip(STR_LIST_FILTER_OSKTITLE, STR_LIST_FILTER_TOOLTIP),
2370  EndContainer(),
2371  EndContainer(),
2374  NWidget(NWID_VSCROLLBAR, COLOUR_MAUVE, WID_GS_SCROLLBAR),
2375  EndContainer(),
2376  NWidget(WWT_PANEL, COLOUR_MAUVE), SetMinimalSize(400, 40),
2377  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_GS_HELP_TEXT), SetMinimalSize(300, 25), SetFill(1, 1), SetResize(1, 0),
2379  EndContainer(),
2381  NWidget(WWT_PUSHTXTBTN, COLOUR_MAUVE, WID_GS_EXPAND_ALL), SetDataTip(STR_CONFIG_SETTING_EXPAND_ALL, STR_NULL),
2382  NWidget(WWT_PUSHTXTBTN, COLOUR_MAUVE, WID_GS_COLLAPSE_ALL), SetDataTip(STR_CONFIG_SETTING_COLLAPSE_ALL, STR_NULL),
2383  NWidget(WWT_PANEL, COLOUR_MAUVE), SetFill(1, 0), SetResize(1, 0),
2384  EndContainer(),
2385  NWidget(WWT_RESIZEBOX, COLOUR_MAUVE),
2386  EndContainer(),
2387 };
2388 
2389 static WindowDesc _settings_selection_desc(
2390  WDP_CENTER, "settings", 510, 450,
2392  0,
2393  _nested_settings_selection_widgets, lengthof(_nested_settings_selection_widgets)
2394 );
2395 
2398 {
2400  new GameSettingsWindow(&_settings_selection_desc);
2401 }
2402 
2403 
2413 void DrawArrowButtons(int x, int y, Colours button_colour, byte state, bool clickable_left, bool clickable_right)
2414 {
2415  int colour = _colour_gradient[button_colour][2];
2416  Dimension dim = NWidgetScrollbar::GetHorizontalDimension();
2417 
2418  DrawFrameRect(x, y, x + dim.width - 1, y + dim.height - 1, button_colour, (state == 1) ? FR_LOWERED : FR_NONE);
2419  DrawFrameRect(x + dim.width, y, x + dim.width + dim.width - 1, y + dim.height - 1, button_colour, (state == 2) ? FR_LOWERED : FR_NONE);
2420  DrawSprite(SPR_ARROW_LEFT, PAL_NONE, x + WD_IMGBTN_LEFT, y + WD_IMGBTN_TOP);
2421  DrawSprite(SPR_ARROW_RIGHT, PAL_NONE, x + WD_IMGBTN_LEFT + dim.width, y + WD_IMGBTN_TOP);
2422 
2423  /* Grey out the buttons that aren't clickable */
2424  bool rtl = _current_text_dir == TD_RTL;
2425  if (rtl ? !clickable_right : !clickable_left) {
2426  GfxFillRect(x + 1, y, x + dim.width - 1, y + dim.height - 2, colour, FILLRECT_CHECKER);
2427  }
2428  if (rtl ? !clickable_left : !clickable_right) {
2429  GfxFillRect(x + dim.width + 1, y, x + dim.width + dim.width - 1, y + dim.height - 2, colour, FILLRECT_CHECKER);
2430  }
2431 }
2432 
2441 void DrawDropDownButton(int x, int y, Colours button_colour, bool state, bool clickable)
2442 {
2443  int colour = _colour_gradient[button_colour][2];
2444 
2445  DrawFrameRect(x, y, x + SETTING_BUTTON_WIDTH - 1, y + SETTING_BUTTON_HEIGHT - 1, button_colour, state ? FR_LOWERED : FR_NONE);
2446  DrawSprite(SPR_ARROW_DOWN, PAL_NONE, x + (SETTING_BUTTON_WIDTH - NWidgetScrollbar::GetVerticalDimension().width) / 2 + state, y + 2 + state);
2447 
2448  if (!clickable) {
2449  GfxFillRect(x + 1, y, x + SETTING_BUTTON_WIDTH - 1, y + SETTING_BUTTON_HEIGHT - 2, colour, FILLRECT_CHECKER);
2450  }
2451 }
2452 
2460 void DrawBoolButton(int x, int y, bool state, bool clickable)
2461 {
2462  static const Colours _bool_ctabs[2][2] = {{COLOUR_CREAM, COLOUR_RED}, {COLOUR_DARK_GREEN, COLOUR_GREEN}};
2463  DrawFrameRect(x, y, x + SETTING_BUTTON_WIDTH - 1, y + SETTING_BUTTON_HEIGHT - 1, _bool_ctabs[state][clickable], state ? FR_LOWERED : FR_NONE);
2464 }
2465 
2467  int query_widget;
2468 
2469  CustomCurrencyWindow(WindowDesc *desc) : Window(desc)
2470  {
2471  this->InitNested();
2472 
2473  SetButtonState();
2474  }
2475 
2476  void SetButtonState()
2477  {
2478  this->SetWidgetDisabledState(WID_CC_RATE_DOWN, _custom_currency.rate == 1);
2479  this->SetWidgetDisabledState(WID_CC_RATE_UP, _custom_currency.rate == UINT16_MAX);
2480  this->SetWidgetDisabledState(WID_CC_YEAR_DOWN, _custom_currency.to_euro == CF_NOEURO);
2481  this->SetWidgetDisabledState(WID_CC_YEAR_UP, _custom_currency.to_euro == MAX_YEAR);
2482  }
2483 
2484  void SetStringParameters(int widget) const override
2485  {
2486  switch (widget) {
2487  case WID_CC_RATE: SetDParam(0, 1); SetDParam(1, 1); break;
2488  case WID_CC_SEPARATOR: SetDParamStr(0, _custom_currency.separator); break;
2489  case WID_CC_PREFIX: SetDParamStr(0, _custom_currency.prefix); break;
2490  case WID_CC_SUFFIX: SetDParamStr(0, _custom_currency.suffix); break;
2491  case WID_CC_YEAR:
2492  SetDParam(0, (_custom_currency.to_euro != CF_NOEURO) ? STR_CURRENCY_SWITCH_TO_EURO : STR_CURRENCY_SWITCH_TO_EURO_NEVER);
2493  SetDParam(1, _custom_currency.to_euro);
2494  break;
2495 
2496  case WID_CC_PREVIEW:
2497  SetDParam(0, 10000);
2498  break;
2499  }
2500  }
2501 
2502  void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override
2503  {
2504  switch (widget) {
2505  /* Set the appropriate width for the edit 'buttons' */
2506  case WID_CC_SEPARATOR_EDIT:
2507  case WID_CC_PREFIX_EDIT:
2508  case WID_CC_SUFFIX_EDIT:
2509  size->width = this->GetWidget<NWidgetBase>(WID_CC_RATE_DOWN)->smallest_x + this->GetWidget<NWidgetBase>(WID_CC_RATE_UP)->smallest_x;
2510  break;
2511 
2512  /* Make sure the window is wide enough for the widest exchange rate */
2513  case WID_CC_RATE:
2514  SetDParam(0, 1);
2515  SetDParam(1, INT32_MAX);
2516  *size = GetStringBoundingBox(STR_CURRENCY_EXCHANGE_RATE);
2517  break;
2518  }
2519  }
2520 
2521  void OnClick(Point pt, int widget, int click_count) override
2522  {
2523  int line = 0;
2524  int len = 0;
2525  StringID str = 0;
2526  CharSetFilter afilter = CS_ALPHANUMERAL;
2527 
2528  switch (widget) {
2529  case WID_CC_RATE_DOWN:
2530  if (_custom_currency.rate > 1) _custom_currency.rate--;
2531  if (_custom_currency.rate == 1) this->DisableWidget(WID_CC_RATE_DOWN);
2533  break;
2534 
2535  case WID_CC_RATE_UP:
2536  if (_custom_currency.rate < UINT16_MAX) _custom_currency.rate++;
2537  if (_custom_currency.rate == UINT16_MAX) this->DisableWidget(WID_CC_RATE_UP);
2539  break;
2540 
2541  case WID_CC_RATE:
2542  SetDParam(0, _custom_currency.rate);
2543  str = STR_JUST_INT;
2544  len = 5;
2545  line = WID_CC_RATE;
2546  afilter = CS_NUMERAL;
2547  break;
2548 
2549  case WID_CC_SEPARATOR_EDIT:
2550  case WID_CC_SEPARATOR:
2551  SetDParamStr(0, _custom_currency.separator);
2552  str = STR_JUST_RAW_STRING;
2553  len = 1;
2554  line = WID_CC_SEPARATOR;
2555  break;
2556 
2557  case WID_CC_PREFIX_EDIT:
2558  case WID_CC_PREFIX:
2559  SetDParamStr(0, _custom_currency.prefix);
2560  str = STR_JUST_RAW_STRING;
2561  len = 12;
2562  line = WID_CC_PREFIX;
2563  break;
2564 
2565  case WID_CC_SUFFIX_EDIT:
2566  case WID_CC_SUFFIX:
2567  SetDParamStr(0, _custom_currency.suffix);
2568  str = STR_JUST_RAW_STRING;
2569  len = 12;
2570  line = WID_CC_SUFFIX;
2571  break;
2572 
2573  case WID_CC_YEAR_DOWN:
2574  _custom_currency.to_euro = (_custom_currency.to_euro <= 2000) ? CF_NOEURO : _custom_currency.to_euro - 1;
2575  if (_custom_currency.to_euro == CF_NOEURO) this->DisableWidget(WID_CC_YEAR_DOWN);
2577  break;
2578 
2579  case WID_CC_YEAR_UP:
2580  _custom_currency.to_euro = Clamp(_custom_currency.to_euro + 1, 2000, MAX_YEAR);
2581  if (_custom_currency.to_euro == MAX_YEAR) this->DisableWidget(WID_CC_YEAR_UP);
2583  break;
2584 
2585  case WID_CC_YEAR:
2586  SetDParam(0, _custom_currency.to_euro);
2587  str = STR_JUST_INT;
2588  len = 7;
2589  line = WID_CC_YEAR;
2590  afilter = CS_NUMERAL;
2591  break;
2592  }
2593 
2594  if (len != 0) {
2595  this->query_widget = line;
2596  ShowQueryString(str, STR_CURRENCY_CHANGE_PARAMETER, len + 1, this, afilter, QSF_NONE);
2597  }
2598 
2599  this->SetTimeout();
2600  this->SetDirty();
2601  }
2602 
2603  void OnQueryTextFinished(char *str) override
2604  {
2605  if (str == nullptr) return;
2606 
2607  switch (this->query_widget) {
2608  case WID_CC_RATE:
2609  _custom_currency.rate = Clamp(atoi(str), 1, UINT16_MAX);
2610  break;
2611 
2612  case WID_CC_SEPARATOR: // Thousands separator
2613  strecpy(_custom_currency.separator, str, lastof(_custom_currency.separator));
2614  break;
2615 
2616  case WID_CC_PREFIX:
2617  strecpy(_custom_currency.prefix, str, lastof(_custom_currency.prefix));
2618  break;
2619 
2620  case WID_CC_SUFFIX:
2621  strecpy(_custom_currency.suffix, str, lastof(_custom_currency.suffix));
2622  break;
2623 
2624  case WID_CC_YEAR: { // Year to switch to euro
2625  int val = atoi(str);
2626 
2627  _custom_currency.to_euro = (val < 2000 ? CF_NOEURO : min(val, MAX_YEAR));
2628  break;
2629  }
2630  }
2632  SetButtonState();
2633  }
2634 
2635  void OnTimeout() override
2636  {
2637  this->SetDirty();
2638  }
2639 };
2640 
2641 static const NWidgetPart _nested_cust_currency_widgets[] = {
2643  NWidget(WWT_CLOSEBOX, COLOUR_GREY),
2644  NWidget(WWT_CAPTION, COLOUR_GREY), SetDataTip(STR_CURRENCY_WINDOW, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
2645  EndContainer(),
2646  NWidget(WWT_PANEL, COLOUR_GREY),
2648  NWidget(NWID_HORIZONTAL), SetPIP(10, 0, 5),
2649  NWidget(WWT_PUSHARROWBTN, COLOUR_YELLOW, WID_CC_RATE_DOWN), SetDataTip(AWV_DECREASE, STR_CURRENCY_DECREASE_EXCHANGE_RATE_TOOLTIP),
2650  NWidget(WWT_PUSHARROWBTN, COLOUR_YELLOW, WID_CC_RATE_UP), SetDataTip(AWV_INCREASE, STR_CURRENCY_INCREASE_EXCHANGE_RATE_TOOLTIP),
2652  NWidget(WWT_TEXT, COLOUR_BLUE, WID_CC_RATE), SetDataTip(STR_CURRENCY_EXCHANGE_RATE, STR_CURRENCY_SET_EXCHANGE_RATE_TOOLTIP), SetFill(1, 0),
2653  EndContainer(),
2654  NWidget(NWID_HORIZONTAL), SetPIP(10, 0, 5),
2655  NWidget(WWT_PUSHBTN, COLOUR_DARK_BLUE, WID_CC_SEPARATOR_EDIT), SetDataTip(0x0, STR_CURRENCY_SET_CUSTOM_CURRENCY_SEPARATOR_TOOLTIP), SetFill(0, 1),
2657  NWidget(WWT_TEXT, COLOUR_BLUE, WID_CC_SEPARATOR), SetDataTip(STR_CURRENCY_SEPARATOR, STR_CURRENCY_SET_CUSTOM_CURRENCY_SEPARATOR_TOOLTIP), SetFill(1, 0),
2658  EndContainer(),
2659  NWidget(NWID_HORIZONTAL), SetPIP(10, 0, 5),
2660  NWidget(WWT_PUSHBTN, COLOUR_DARK_BLUE, WID_CC_PREFIX_EDIT), SetDataTip(0x0, STR_CURRENCY_SET_CUSTOM_CURRENCY_PREFIX_TOOLTIP), SetFill(0, 1),
2662  NWidget(WWT_TEXT, COLOUR_BLUE, WID_CC_PREFIX), SetDataTip(STR_CURRENCY_PREFIX, STR_CURRENCY_SET_CUSTOM_CURRENCY_PREFIX_TOOLTIP), SetFill(1, 0),
2663  EndContainer(),
2664  NWidget(NWID_HORIZONTAL), SetPIP(10, 0, 5),
2665  NWidget(WWT_PUSHBTN, COLOUR_DARK_BLUE, WID_CC_SUFFIX_EDIT), SetDataTip(0x0, STR_CURRENCY_SET_CUSTOM_CURRENCY_SUFFIX_TOOLTIP), SetFill(0, 1),
2667  NWidget(WWT_TEXT, COLOUR_BLUE, WID_CC_SUFFIX), SetDataTip(STR_CURRENCY_SUFFIX, STR_CURRENCY_SET_CUSTOM_CURRENCY_SUFFIX_TOOLTIP), SetFill(1, 0),
2668  EndContainer(),
2669  NWidget(NWID_HORIZONTAL), SetPIP(10, 0, 5),
2670  NWidget(WWT_PUSHARROWBTN, COLOUR_YELLOW, WID_CC_YEAR_DOWN), SetDataTip(AWV_DECREASE, STR_CURRENCY_DECREASE_CUSTOM_CURRENCY_TO_EURO_TOOLTIP),
2671  NWidget(WWT_PUSHARROWBTN, COLOUR_YELLOW, WID_CC_YEAR_UP), SetDataTip(AWV_INCREASE, STR_CURRENCY_INCREASE_CUSTOM_CURRENCY_TO_EURO_TOOLTIP),
2673  NWidget(WWT_TEXT, COLOUR_BLUE, WID_CC_YEAR), SetDataTip(STR_JUST_STRING, STR_CURRENCY_SET_CUSTOM_CURRENCY_TO_EURO_TOOLTIP), SetFill(1, 0),
2674  EndContainer(),
2675  EndContainer(),
2676  NWidget(WWT_LABEL, COLOUR_BLUE, WID_CC_PREVIEW),
2677  SetDataTip(STR_CURRENCY_PREVIEW, STR_CURRENCY_CUSTOM_CURRENCY_PREVIEW_TOOLTIP), SetPadding(15, 1, 18, 2),
2678  EndContainer(),
2679 };
2680 
2681 static WindowDesc _cust_currency_desc(
2682  WDP_CENTER, nullptr, 0, 0,
2684  0,
2685  _nested_cust_currency_widgets, lengthof(_nested_cust_currency_widgets)
2686 );
2687 
2689 static void ShowCustCurrency()
2690 {
2692  new CustomCurrencyWindow(&_cust_currency_desc);
2693 }
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:1867
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:3215
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:291
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:20
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:547
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:1828
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:1844
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:1857
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:499
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:176
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:78
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:1133
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:80
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:2057
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:498
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:1175
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:1971
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:700
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:1162
bool IsEditable(bool do_command=false) const
Check whether the setting is editable in the current gamemode.
Definition: settings.cpp:784
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:823
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:3451
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:1531
int GetStringLineCount(StringID str, int maxw)
Calculates number of lines of string.
Definition: gfx.cpp:572
static size_t GetNumItems()
Returns number of valid items in the pool.
Definition: pool_type.hpp:321
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:1930
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:799
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:770
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:280
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:92
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:835
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:3256
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:1462
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:621
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