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