OpenTTD
settings_gui.cpp
Go to the documentation of this file.
1 /* $Id: settings_gui.cpp 27827 2017-03-25 12:21:17Z frosch $ */
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 
40 #include <vector>
41 
42 #include "safeguards.h"
43 
44 
45 static const StringID _driveside_dropdown[] = {
46  STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_LEFT,
47  STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_RIGHT,
49 };
50 
51 static const StringID _autosave_dropdown[] = {
52  STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_OFF,
53  STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_1_MONTH,
54  STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_3_MONTHS,
55  STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_6_MONTHS,
56  STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_12_MONTHS,
58 };
59 
60 static const StringID _gui_zoom_dropdown[] = {
61  STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_NORMAL,
62  STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_2X_ZOOM,
63  STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_4X_ZOOM,
65 };
66 
67 int _nb_orig_names = SPECSTR_TOWNNAME_LAST - SPECSTR_TOWNNAME_START + 1;
68 static StringID *_grf_names = NULL;
69 static int _nb_grf_names = 0;
70 
72 
73 static const void *ResolveVariableAddress(const GameSettings *settings_ptr, const SettingDesc *sd);
74 
77 {
79  _grf_names = GetGRFTownNameList();
80  _nb_grf_names = 0;
81  for (StringID *s = _grf_names; *s != INVALID_STRING_ID; s++) _nb_grf_names++;
82 }
83 
89 static inline StringID TownName(int town_name)
90 {
91  if (town_name < _nb_orig_names) return STR_GAME_OPTIONS_TOWN_NAME_ORIGINAL_ENGLISH + town_name;
92  town_name -= _nb_orig_names;
93  if (town_name < _nb_grf_names) return _grf_names[town_name];
94  return STR_UNDEFINED;
95 }
96 
101 static int GetCurRes()
102 {
103  int i;
104 
105  for (i = 0; i != _num_resolutions; i++) {
106  if ((int)_resolutions[i].width == _screen.width &&
107  (int)_resolutions[i].height == _screen.height) {
108  break;
109  }
110  }
111  return i;
112 }
113 
114 static void ShowCustCurrency();
115 
116 template <class T>
117 static DropDownList *BuiltSetDropDownList(int *selected_index)
118 {
119  int n = T::GetNumSets();
120  *selected_index = T::GetIndexOfUsedSet();
121 
122  DropDownList *list = new DropDownList();
123  for (int i = 0; i < n; i++) {
124  *list->Append() = new DropDownListCharStringItem(T::GetSet(i)->name, i, (_game_mode == GM_MENU) ? false : (*selected_index != i));
125  }
126 
127  return list;
128 }
129 
131 template <class TBaseSet>
133  const TBaseSet* baseset;
135 
136  BaseSetTextfileWindow(TextfileType file_type, const TBaseSet* baseset, StringID content_type) : TextfileWindow(file_type), baseset(baseset), content_type(content_type)
137  {
138  const char *textfile = this->baseset->GetTextfile(file_type);
139  this->LoadTextfile(textfile, BASESET_DIR);
140  }
141 
142  /* virtual */ void SetStringParameters(int widget) const
143  {
144  if (widget == WID_TF_CAPTION) {
145  SetDParam(0, content_type);
146  SetDParamStr(1, this->baseset->name);
147  }
148  }
149 };
150 
157 template <class TBaseSet>
159 {
162 }
163 
165  GameSettings *opt;
166  bool reload;
167 
168  GameOptionsWindow(WindowDesc *desc) : Window(desc)
169  {
170  this->opt = &GetGameSettings();
171  this->reload = false;
172 
174  this->OnInvalidateData(0);
175  }
176 
178  {
180  if (this->reload) _switch_mode = SM_MENU;
181  }
182 
189  DropDownList *BuildDropDownList(int widget, int *selected_index) const
190  {
191  DropDownList *list = NULL;
192  switch (widget) {
193  case WID_GO_CURRENCY_DROPDOWN: { // Setup currencies dropdown
194  list = new DropDownList();
195  *selected_index = this->opt->locale.currency;
196  StringID *items = BuildCurrencyDropdown();
197  uint64 disabled = _game_mode == GM_MENU ? 0LL : ~GetMaskOfAllowedCurrencies();
198 
199  /* Add non-custom currencies; sorted naturally */
200  for (uint i = 0; i < CURRENCY_END; items++, i++) {
201  if (i == CURRENCY_CUSTOM) continue;
202  *list->Append() = new DropDownListStringItem(*items, i, HasBit(disabled, i));
203  }
205 
206  /* Append custom currency at the end */
207  *list->Append() = new DropDownListItem(-1, false); // separator line
208  *list->Append() = new DropDownListStringItem(STR_GAME_OPTIONS_CURRENCY_CUSTOM, CURRENCY_CUSTOM, HasBit(disabled, CURRENCY_CUSTOM));
209  break;
210  }
211 
212  case WID_GO_ROADSIDE_DROPDOWN: { // Setup road-side dropdown
213  list = new DropDownList();
214  *selected_index = this->opt->vehicle.road_side;
215  const StringID *items = _driveside_dropdown;
216  uint disabled = 0;
217 
218  /* You can only change the drive side if you are in the menu or ingame with
219  * no vehicles present. In a networking game only the server can change it */
220  extern bool RoadVehiclesAreBuilt();
221  if ((_game_mode != GM_MENU && RoadVehiclesAreBuilt()) || (_networking && !_network_server)) {
222  disabled = ~(1 << this->opt->vehicle.road_side); // disable the other value
223  }
224 
225  for (uint i = 0; *items != INVALID_STRING_ID; items++, i++) {
226  *list->Append() = new DropDownListStringItem(*items, i, HasBit(disabled, i));
227  }
228  break;
229  }
230 
231  case WID_GO_TOWNNAME_DROPDOWN: { // Setup townname dropdown
232  list = new DropDownList();
233  *selected_index = this->opt->game_creation.town_name;
234 
235  int enabled_item = (_game_mode == GM_MENU || Town::GetNumItems() == 0) ? -1 : *selected_index;
236 
237  /* Add and sort newgrf townnames generators */
238  for (int i = 0; i < _nb_grf_names; i++) {
239  int result = _nb_orig_names + i;
240  *list->Append() = new DropDownListStringItem(_grf_names[i], result, enabled_item != result && enabled_item >= 0);
241  }
243 
244  int newgrf_size = list->Length();
245  /* Insert newgrf_names at the top of the list */
246  if (newgrf_size > 0) {
247  *list->Append() = new DropDownListItem(-1, false); // separator line
248  newgrf_size++;
249  }
250 
251  /* Add and sort original townnames generators */
252  for (int i = 0; i < _nb_orig_names; i++) {
253  *list->Append() = new DropDownListStringItem(STR_GAME_OPTIONS_TOWN_NAME_ORIGINAL_ENGLISH + i, i, enabled_item != i && enabled_item >= 0);
254  }
255  QSortT(list->Begin() + newgrf_size, list->Length() - newgrf_size, DropDownListStringItem::NatSortFunc);
256  break;
257  }
258 
259  case WID_GO_AUTOSAVE_DROPDOWN: { // Setup autosave dropdown
260  list = new DropDownList();
261  *selected_index = _settings_client.gui.autosave;
262  const StringID *items = _autosave_dropdown;
263  for (uint i = 0; *items != INVALID_STRING_ID; items++, i++) {
264  *list->Append() = new DropDownListStringItem(*items, i, false);
265  }
266  break;
267  }
268 
269  case WID_GO_LANG_DROPDOWN: { // Setup interface language dropdown
270  list = new DropDownList();
271  for (uint i = 0; i < _languages.Length(); i++) {
272  if (&_languages[i] == _current_language) *selected_index = i;
273  *list->Append() = new DropDownListStringItem(SPECSTR_LANGUAGE_START + i, i, false);
274  }
276  break;
277  }
278 
279  case WID_GO_RESOLUTION_DROPDOWN: // Setup resolution dropdown
280  if (_num_resolutions == 0) break;
281 
282  list = new DropDownList();
283  *selected_index = GetCurRes();
284  for (int i = 0; i < _num_resolutions; i++) {
285  *list->Append() = new DropDownListStringItem(SPECSTR_RESOLUTION_START + i, i, false);
286  }
287  break;
288 
290  list = new DropDownList();
291  *selected_index = ZOOM_LVL_OUT_4X - _gui_zoom;
292  const StringID *items = _gui_zoom_dropdown;
293  for (int i = 0; *items != INVALID_STRING_ID; items++, i++) {
295  }
296  break;
297  }
298 
300  list = BuiltSetDropDownList<BaseGraphics>(selected_index);
301  break;
302 
304  list = BuiltSetDropDownList<BaseSounds>(selected_index);
305  break;
306 
308  list = BuiltSetDropDownList<BaseMusic>(selected_index);
309  break;
310 
311  default:
312  return NULL;
313  }
314 
315  return list;
316  }
317 
318  virtual void SetStringParameters(int widget) const
319  {
320  switch (widget) {
321  case WID_GO_CURRENCY_DROPDOWN: SetDParam(0, _currency_specs[this->opt->locale.currency].name); break;
322  case WID_GO_ROADSIDE_DROPDOWN: SetDParam(0, STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_LEFT + this->opt->vehicle.road_side); break;
324  case WID_GO_AUTOSAVE_DROPDOWN: SetDParam(0, _autosave_dropdown[_settings_client.gui.autosave]); break;
326  case WID_GO_RESOLUTION_DROPDOWN: SetDParam(0, GetCurRes() == _num_resolutions ? STR_GAME_OPTIONS_RESOLUTION_OTHER : SPECSTR_RESOLUTION_START + GetCurRes()); break;
327  case WID_GO_GUI_ZOOM_DROPDOWN: SetDParam(0, _gui_zoom_dropdown[ZOOM_LVL_OUT_4X - _gui_zoom]); break;
329  case WID_GO_BASE_GRF_STATUS: SetDParam(0, BaseGraphics::GetUsedSet()->GetNumInvalid()); break;
332  case WID_GO_BASE_MUSIC_STATUS: SetDParam(0, BaseMusic::GetUsedSet()->GetNumInvalid()); break;
333  }
334  }
335 
336  virtual void DrawWidget(const Rect &r, int widget) const
337  {
338  switch (widget) {
341  DrawStringMultiLine(r.left, r.right, r.top, UINT16_MAX, STR_BLACK_RAW_STRING);
342  break;
343 
346  DrawStringMultiLine(r.left, r.right, r.top, UINT16_MAX, STR_BLACK_RAW_STRING);
347  break;
348 
351  DrawStringMultiLine(r.left, r.right, r.top, UINT16_MAX, STR_BLACK_RAW_STRING);
352  break;
353  }
354  }
355 
356  virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
357  {
358  switch (widget) {
360  /* Find the biggest description for the default size. */
361  for (int i = 0; i < BaseGraphics::GetNumSets(); i++) {
363  size->height = max(size->height, (uint)GetStringHeight(STR_BLACK_RAW_STRING, size->width));
364  }
365  break;
366 
368  /* Find the biggest description for the default size. */
369  for (int i = 0; i < BaseGraphics::GetNumSets(); i++) {
370  uint invalid_files = BaseGraphics::GetSet(i)->GetNumInvalid();
371  if (invalid_files == 0) continue;
372 
373  SetDParam(0, invalid_files);
374  *size = maxdim(*size, GetStringBoundingBox(STR_GAME_OPTIONS_BASE_GRF_STATUS));
375  }
376  break;
377 
379  /* Find the biggest description for the default size. */
380  for (int i = 0; i < BaseSounds::GetNumSets(); i++) {
382  size->height = max(size->height, (uint)GetStringHeight(STR_BLACK_RAW_STRING, size->width));
383  }
384  break;
385 
387  /* Find the biggest description for the default size. */
388  for (int i = 0; i < BaseMusic::GetNumSets(); i++) {
389  SetDParamStr(0, BaseMusic::GetSet(i)->GetDescription(GetCurrentLanguageIsoCode()));
390  size->height = max(size->height, (uint)GetStringHeight(STR_BLACK_RAW_STRING, size->width));
391  }
392  break;
393 
395  /* Find the biggest description for the default size. */
396  for (int i = 0; i < BaseMusic::GetNumSets(); i++) {
397  uint invalid_files = BaseMusic::GetSet(i)->GetNumInvalid();
398  if (invalid_files == 0) continue;
399 
400  SetDParam(0, invalid_files);
401  *size = maxdim(*size, GetStringBoundingBox(STR_GAME_OPTIONS_BASE_MUSIC_STATUS));
402  }
403  break;
404 
405  default: {
406  int selected;
407  DropDownList *list = this->BuildDropDownList(widget, &selected);
408  if (list != NULL) {
409  /* Find the biggest item for the default size. */
410  for (const DropDownListItem * const *it = list->Begin(); it != list->End(); it++) {
411  Dimension string_dim;
412  int width = (*it)->Width();
413  string_dim.width = width + padding.width;
414  string_dim.height = (*it)->Height(width) + padding.height;
415  *size = maxdim(*size, string_dim);
416  }
417  delete list;
418  }
419  }
420  }
421  }
422 
423  virtual void OnClick(Point pt, int widget, int click_count)
424  {
425  if (widget >= WID_GO_BASE_GRF_TEXTFILE && widget < WID_GO_BASE_GRF_TEXTFILE + TFT_END) {
426  if (BaseGraphics::GetUsedSet() == NULL) return;
427 
428  ShowBaseSetTextfileWindow((TextfileType)(widget - WID_GO_BASE_GRF_TEXTFILE), BaseGraphics::GetUsedSet(), STR_CONTENT_TYPE_BASE_GRAPHICS);
429  return;
430  }
431  if (widget >= WID_GO_BASE_SFX_TEXTFILE && widget < WID_GO_BASE_SFX_TEXTFILE + TFT_END) {
432  if (BaseSounds::GetUsedSet() == NULL) return;
433 
434  ShowBaseSetTextfileWindow((TextfileType)(widget - WID_GO_BASE_SFX_TEXTFILE), BaseSounds::GetUsedSet(), STR_CONTENT_TYPE_BASE_SOUNDS);
435  return;
436  }
437  if (widget >= WID_GO_BASE_MUSIC_TEXTFILE && widget < WID_GO_BASE_MUSIC_TEXTFILE + TFT_END) {
438  if (BaseMusic::GetUsedSet() == NULL) return;
439 
440  ShowBaseSetTextfileWindow((TextfileType)(widget - WID_GO_BASE_MUSIC_TEXTFILE), BaseMusic::GetUsedSet(), STR_CONTENT_TYPE_BASE_MUSIC);
441  return;
442  }
443  switch (widget) {
444  case WID_GO_FULLSCREEN_BUTTON: // Click fullscreen on/off
445  /* try to toggle full-screen on/off */
446  if (!ToggleFullScreen(!_fullscreen)) {
447  ShowErrorMessage(STR_ERROR_FULLSCREEN_FAILED, INVALID_STRING_ID, WL_ERROR);
448  }
450  this->SetDirty();
451  break;
452 
453  default: {
454  int selected;
455  DropDownList *list = this->BuildDropDownList(widget, &selected);
456  if (list != NULL) {
457  ShowDropDownList(this, list, selected, widget);
458  } else {
459  if (widget == WID_GO_RESOLUTION_DROPDOWN) ShowErrorMessage(STR_ERROR_RESOLUTION_LIST_FAILED, INVALID_STRING_ID, WL_ERROR);
460  }
461  break;
462  }
463  }
464  }
465 
471  template <class T>
472  void SetMediaSet(int index)
473  {
474  if (_game_mode == GM_MENU) {
475  const char *name = T::GetSet(index)->name;
476 
477  free(T::ini_set);
478  T::ini_set = stredup(name);
479 
480  T::SetSet(name);
481  this->reload = true;
482  this->InvalidateData();
483  }
484  }
485 
486  virtual void OnDropdownSelect(int widget, int index)
487  {
488  switch (widget) {
489  case WID_GO_CURRENCY_DROPDOWN: // Currency
490  if (index == CURRENCY_CUSTOM) ShowCustCurrency();
491  this->opt->locale.currency = index;
493  break;
494 
495  case WID_GO_ROADSIDE_DROPDOWN: // Road side
496  if (this->opt->vehicle.road_side != index) { // only change if setting changed
497  uint i;
498  if (GetSettingFromName("vehicle.road_side", &i) == NULL) NOT_REACHED();
499  SetSettingValue(i, index);
501  }
502  break;
503 
504  case WID_GO_TOWNNAME_DROPDOWN: // Town names
505  if (_game_mode == GM_MENU || Town::GetNumItems() == 0) {
506  this->opt->game_creation.town_name = index;
508  }
509  break;
510 
511  case WID_GO_AUTOSAVE_DROPDOWN: // Autosave options
512  _settings_client.gui.autosave = index;
513  this->SetDirty();
514  break;
515 
516  case WID_GO_LANG_DROPDOWN: // Change interface language
517  ReadLanguagePack(&_languages[index]);
522  break;
523 
524  case WID_GO_RESOLUTION_DROPDOWN: // Change resolution
525  if (index < _num_resolutions && ChangeResInGame(_resolutions[index].width, _resolutions[index].height)) {
526  this->SetDirty();
527  }
528  break;
529 
532  _gui_zoom = (ZoomLevel)(ZOOM_LVL_OUT_4X - index);
536  break;
537 
539  this->SetMediaSet<BaseGraphics>(index);
540  break;
541 
543  this->SetMediaSet<BaseSounds>(index);
544  break;
545 
547  this->SetMediaSet<BaseMusic>(index);
548  break;
549  }
550  }
551 
557  virtual void OnInvalidateData(int data = 0, bool gui_scope = true)
558  {
559  if (!gui_scope) return;
561 
562  bool missing_files = BaseGraphics::GetUsedSet()->GetNumMissing() == 0;
563  this->GetWidget<NWidgetCore>(WID_GO_BASE_GRF_STATUS)->SetDataTip(missing_files ? STR_EMPTY : STR_GAME_OPTIONS_BASE_GRF_STATUS, STR_NULL);
564 
565  for (TextfileType tft = TFT_BEGIN; tft < TFT_END; tft++) {
569  }
570 
571  missing_files = BaseMusic::GetUsedSet()->GetNumInvalid() == 0;
572  this->GetWidget<NWidgetCore>(WID_GO_BASE_MUSIC_STATUS)->SetDataTip(missing_files ? STR_EMPTY : STR_GAME_OPTIONS_BASE_MUSIC_STATUS, STR_NULL);
573  }
574 };
575 
576 static const NWidgetPart _nested_game_options_widgets[] = {
578  NWidget(WWT_CLOSEBOX, COLOUR_GREY),
579  NWidget(WWT_CAPTION, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
580  EndContainer(),
581  NWidget(WWT_PANEL, COLOUR_GREY, WID_GO_BACKGROUND), SetPIP(6, 6, 10),
582  NWidget(NWID_HORIZONTAL), SetPIP(10, 10, 10),
583  NWidget(NWID_VERTICAL), SetPIP(0, 6, 0),
584  NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_ROAD_VEHICLES_FRAME, STR_NULL),
585  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),
586  EndContainer(),
587  NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_AUTOSAVE_FRAME, STR_NULL),
588  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),
589  EndContainer(),
590  NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_RESOLUTION, STR_NULL),
591  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),
593  NWidget(WWT_TEXT, COLOUR_GREY), SetMinimalSize(0, 12), SetFill(1, 0), SetDataTip(STR_GAME_OPTIONS_FULLSCREEN, STR_NULL),
594  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_GO_FULLSCREEN_BUTTON), SetMinimalSize(21, 9), SetDataTip(STR_EMPTY, STR_GAME_OPTIONS_FULLSCREEN_TOOLTIP),
595  EndContainer(),
596  EndContainer(),
597  NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_GUI_ZOOM_FRAME, STR_NULL),
598  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),
599  EndContainer(),
600  EndContainer(),
601 
602  NWidget(NWID_VERTICAL), SetPIP(0, 6, 0),
603  NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_TOWN_NAMES_FRAME, STR_NULL),
604  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),
605  EndContainer(),
606  NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_LANGUAGE, STR_NULL),
607  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),
608  EndContainer(),
609  NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_CURRENCY_UNITS_FRAME, STR_NULL),
610  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),
611  EndContainer(),
612  NWidget(NWID_SPACER), SetMinimalSize(0, 0), SetFill(0, 1),
613  EndContainer(),
614  EndContainer(),
615 
616  NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_BASE_GRF, STR_NULL), SetPadding(0, 10, 0, 10),
617  NWidget(NWID_HORIZONTAL), SetPIP(0, 30, 0),
618  NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_BASE_GRF_DROPDOWN), SetMinimalSize(150, 12), SetDataTip(STR_BLACK_RAW_STRING, STR_GAME_OPTIONS_BASE_GRF_TOOLTIP),
619  NWidget(WWT_TEXT, COLOUR_GREY, WID_GO_BASE_GRF_STATUS), SetMinimalSize(150, 12), SetDataTip(STR_EMPTY, STR_NULL), SetFill(1, 0),
620  EndContainer(),
621  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),
623  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),
624  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),
625  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),
626  EndContainer(),
627  EndContainer(),
628 
629  NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_BASE_SFX, STR_NULL), SetPadding(0, 10, 0, 10),
630  NWidget(NWID_HORIZONTAL), SetPIP(0, 30, 0),
631  NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_BASE_SFX_DROPDOWN), SetMinimalSize(150, 12), SetDataTip(STR_BLACK_RAW_STRING, STR_GAME_OPTIONS_BASE_SFX_TOOLTIP),
632  NWidget(NWID_SPACER), SetFill(1, 0),
633  EndContainer(),
634  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),
636  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),
637  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),
638  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),
639  EndContainer(),
640  EndContainer(),
641 
642  NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_BASE_MUSIC, STR_NULL), SetPadding(0, 10, 0, 10),
643  NWidget(NWID_HORIZONTAL), SetPIP(0, 30, 0),
644  NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_BASE_MUSIC_DROPDOWN), SetMinimalSize(150, 12), SetDataTip(STR_BLACK_RAW_STRING, STR_GAME_OPTIONS_BASE_MUSIC_TOOLTIP),
645  NWidget(WWT_TEXT, COLOUR_GREY, WID_GO_BASE_MUSIC_STATUS), SetMinimalSize(150, 12), SetDataTip(STR_EMPTY, STR_NULL), SetFill(1, 0),
646  EndContainer(),
647  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),
649  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),
650  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),
651  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),
652  EndContainer(),
653  EndContainer(),
654  EndContainer(),
655 };
656 
657 static WindowDesc _game_options_desc(
658  WDP_CENTER, "settings_game", 0, 0,
660  0,
661  _nested_game_options_widgets, lengthof(_nested_game_options_widgets)
662 );
663 
666 {
668  new GameOptionsWindow(&_game_options_desc);
669 }
670 
671 static int SETTING_HEIGHT = 11;
672 static const int LEVEL_WIDTH = 15;
673 
682 
683  SEF_LAST_FIELD = 0x04,
684  SEF_FILTERED = 0x08,
685 };
686 
695 };
697 
698 
702  bool type_hides;
705 };
706 
709  byte flags;
710  byte level;
711 
712  BaseSettingEntry() : flags(0), level(0) {}
713  virtual ~BaseSettingEntry() {}
714 
715  virtual void Init(byte level = 0);
716  virtual void FoldAll() {}
717  virtual void UnFoldAll() {}
718 
723  void SetLastField(bool last_field) { if (last_field) SETBITS(this->flags, SEF_LAST_FIELD); else CLRBITS(this->flags, SEF_LAST_FIELD); }
724 
725  virtual uint Length() const = 0;
726  virtual void GetFoldingState(bool &all_folded, bool &all_unfolded) const {}
727  virtual bool IsVisible(const BaseSettingEntry *item) const;
728  virtual BaseSettingEntry *FindEntry(uint row, uint *cur_row);
729  virtual uint GetMaxHelpHeight(int maxw) { return 0; }
730 
735  bool IsFiltered() const { return (this->flags & SEF_FILTERED) != 0; }
736 
737  virtual bool UpdateFilterState(SettingFilter &filter, bool force_visible) = 0;
738 
739  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;
740 
741 protected:
742  virtual void DrawSetting(GameSettings *settings_ptr, int left, int right, int y, bool highlight) const = 0;
743 };
744 
747  const char *name;
749  uint index;
750 
751  SettingEntry(const char *name);
752 
753  virtual void Init(byte level = 0);
754  virtual uint Length() const;
755  virtual uint GetMaxHelpHeight(int maxw);
756  virtual bool UpdateFilterState(SettingFilter &filter, bool force_visible);
757 
758  void SetButtons(byte new_val);
759 
764  inline StringID GetHelpText() const
765  {
766  return this->setting->desc.str_help;
767  }
768 
769  void SetValueDParams(uint first_param, int32 value) const;
770 
771 protected:
772  virtual void DrawSetting(GameSettings *settings_ptr, int left, int right, int y, bool highlight) const;
773 
774 private:
775  bool IsVisibleByRestrictionMode(RestrictionMode mode) const;
776 };
777 
780  typedef std::vector<BaseSettingEntry*> EntryVector;
781  EntryVector entries;
782 
783  template<typename T>
784  T *Add(T *item)
785  {
786  this->entries.push_back(item);
787  return item;
788  }
789 
790  void Init(byte level = 0);
791  void FoldAll();
792  void UnFoldAll();
793 
794  uint Length() const;
795  void GetFoldingState(bool &all_folded, bool &all_unfolded) const;
796  bool IsVisible(const BaseSettingEntry *item) const;
797  BaseSettingEntry *FindEntry(uint row, uint *cur_row);
798  uint GetMaxHelpHeight(int maxw);
799 
800  bool UpdateFilterState(SettingFilter &filter, bool force_visible);
801 
802  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;
803 };
804 
808  bool folded;
809 
810  SettingsPage(StringID title);
811 
812  virtual void Init(byte level = 0);
813  virtual void FoldAll();
814  virtual void UnFoldAll();
815 
816  virtual uint Length() const;
817  virtual void GetFoldingState(bool &all_folded, bool &all_unfolded) const;
818  virtual bool IsVisible(const BaseSettingEntry *item) const;
819  virtual BaseSettingEntry *FindEntry(uint row, uint *cur_row);
820  virtual uint GetMaxHelpHeight(int maxw) { return SettingsContainer::GetMaxHelpHeight(maxw); }
821 
822  virtual bool UpdateFilterState(SettingFilter &filter, bool force_visible);
823 
824  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;
825 
826 protected:
827  virtual void DrawSetting(GameSettings *settings_ptr, int left, int right, int y, bool highlight) const;
828 };
829 
830 /* == BaseSettingEntry methods == */
831 
836 void BaseSettingEntry::Init(byte level)
837 {
838  this->level = level;
839 }
840 
848 {
849  if (this->IsFiltered()) return false;
850  if (this == item) return true;
851  return false;
852 }
853 
860 BaseSettingEntry *BaseSettingEntry::FindEntry(uint row_num, uint *cur_row)
861 {
862  if (this->IsFiltered()) return NULL;
863  if (row_num == *cur_row) return this;
864  (*cur_row)++;
865  return NULL;
866 }
867 
897 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
898 {
899  if (this->IsFiltered()) return cur_row;
900  if (cur_row >= max_row) return cur_row;
901 
902  bool rtl = _current_text_dir == TD_RTL;
903  int offset = rtl ? -4 : 4;
904  int level_width = rtl ? -LEVEL_WIDTH : LEVEL_WIDTH;
905 
906  int x = rtl ? right : left;
907  if (cur_row >= first_row) {
908  int colour = _colour_gradient[COLOUR_ORANGE][4];
909  y += (cur_row - first_row) * SETTING_HEIGHT; // Compute correct y start position
910 
911  /* Draw vertical for parent nesting levels */
912  for (uint lvl = 0; lvl < this->level; lvl++) {
913  if (!HasBit(parent_last, lvl)) GfxDrawLine(x + offset, y, x + offset, y + SETTING_HEIGHT - 1, colour);
914  x += level_width;
915  }
916  /* draw own |- prefix */
917  int halfway_y = y + SETTING_HEIGHT / 2;
918  int bottom_y = (flags & SEF_LAST_FIELD) ? halfway_y : y + SETTING_HEIGHT - 1;
919  GfxDrawLine(x + offset, y, x + offset, bottom_y, colour);
920  /* Small horizontal line from the last vertical line */
921  GfxDrawLine(x + offset, halfway_y, x + level_width - offset, halfway_y, colour);
922  x += level_width;
923 
924  this->DrawSetting(settings_ptr, rtl ? left : x, rtl ? x : right, y, this == selected);
925  }
926  cur_row++;
927 
928  return cur_row;
929 }
930 
931 /* == SettingEntry methods == */
932 
937 SettingEntry::SettingEntry(const char *name)
938 {
939  this->name = name;
940  this->setting = NULL;
941  this->index = 0;
942 }
943 
948 void SettingEntry::Init(byte level)
949 {
950  BaseSettingEntry::Init(level);
951  this->setting = GetSettingFromName(this->name, &this->index);
952  assert(this->setting != NULL);
953 }
954 
960 void SettingEntry::SetButtons(byte new_val)
961 {
962  assert((new_val & ~SEF_BUTTONS_MASK) == 0); // Should not touch any flags outside the buttons
963  this->flags = (this->flags & ~SEF_BUTTONS_MASK) | new_val;
964 }
965 
968 {
969  return this->IsFiltered() ? 0 : 1;
970 }
971 
978 {
979  return GetStringHeight(this->GetHelpText(), maxw);
980 }
981 
988 {
989  /* There shall not be any restriction, i.e. all settings shall be visible. */
990  if (mode == RM_ALL) return true;
991 
992  GameSettings *settings_ptr = &GetGameSettings();
993  const SettingDesc *sd = this->setting;
994 
995  if (mode == RM_BASIC) return (this->setting->desc.cat & SC_BASIC_LIST) != 0;
996  if (mode == RM_ADVANCED) return (this->setting->desc.cat & SC_ADVANCED_LIST) != 0;
997 
998  /* Read the current value. */
999  const void *var = ResolveVariableAddress(settings_ptr, sd);
1000  int64 current_value = ReadValue(var, sd->save.conv);
1001 
1002  int64 filter_value;
1003 
1004  if (mode == RM_CHANGED_AGAINST_DEFAULT) {
1005  /* This entry shall only be visible, if the value deviates from its default value. */
1006 
1007  /* Read the default value. */
1008  filter_value = ReadValue(&sd->desc.def, sd->save.conv);
1009  } else {
1010  assert(mode == RM_CHANGED_AGAINST_NEW);
1011  /* This entry shall only be visible, if the value deviates from
1012  * its value is used when starting a new game. */
1013 
1014  /* Make sure we're not comparing the new game settings against itself. */
1015  assert(settings_ptr != &_settings_newgame);
1016 
1017  /* Read the new game's value. */
1018  var = ResolveVariableAddress(&_settings_newgame, sd);
1019  filter_value = ReadValue(var, sd->save.conv);
1020  }
1021 
1022  return current_value != filter_value;
1023 }
1024 
1031 bool SettingEntry::UpdateFilterState(SettingFilter &filter, bool force_visible)
1032 {
1033  CLRBITS(this->flags, SEF_FILTERED);
1034 
1035  bool visible = true;
1036 
1037  const SettingDesc *sd = this->setting;
1038  if (!force_visible && !filter.string.IsEmpty()) {
1039  /* Process the search text filter for this item. */
1040  filter.string.ResetState();
1041 
1042  const SettingDescBase *sdb = &sd->desc;
1043 
1044  SetDParam(0, STR_EMPTY);
1045  filter.string.AddLine(sdb->str);
1046  filter.string.AddLine(this->GetHelpText());
1047 
1048  visible = filter.string.GetState();
1049  }
1050 
1051  if (visible) {
1052  if (filter.type != ST_ALL && sd->GetType() != filter.type) {
1053  filter.type_hides = true;
1054  visible = false;
1055  }
1056  if (!this->IsVisibleByRestrictionMode(filter.mode)) {
1057  while (filter.min_cat < RM_ALL && (filter.min_cat == filter.mode || !this->IsVisibleByRestrictionMode(filter.min_cat))) filter.min_cat++;
1058  visible = false;
1059  }
1060  }
1061 
1062  if (!visible) SETBITS(this->flags, SEF_FILTERED);
1063  return visible;
1064 }
1065 
1066 
1067 static const void *ResolveVariableAddress(const GameSettings *settings_ptr, const SettingDesc *sd)
1068 {
1069  if ((sd->desc.flags & SGF_PER_COMPANY) != 0) {
1070  if (Company::IsValidID(_local_company) && _game_mode != GM_MENU) {
1071  return GetVariableAddress(&Company::Get(_local_company)->settings, &sd->save);
1072  } else {
1074  }
1075  } else {
1076  return GetVariableAddress(settings_ptr, &sd->save);
1077  }
1078 }
1079 
1085 void SettingEntry::SetValueDParams(uint first_param, int32 value) const
1086 {
1087  const SettingDescBase *sdb = &this->setting->desc;
1088  if (sdb->cmd == SDT_BOOLX) {
1089  SetDParam(first_param++, value != 0 ? STR_CONFIG_SETTING_ON : STR_CONFIG_SETTING_OFF);
1090  } else {
1091  if ((sdb->flags & SGF_MULTISTRING) != 0) {
1092  SetDParam(first_param++, sdb->str_val - sdb->min + value);
1093  } else if ((sdb->flags & SGF_DISPLAY_ABS) != 0) {
1094  SetDParam(first_param++, sdb->str_val + ((value >= 0) ? 1 : 0));
1095  value = abs(value);
1096  } else {
1097  SetDParam(first_param++, sdb->str_val + ((value == 0 && (sdb->flags & SGF_0ISDISABLED) != 0) ? 1 : 0));
1098  }
1099  SetDParam(first_param++, value);
1100  }
1101 }
1102 
1111 void SettingEntry::DrawSetting(GameSettings *settings_ptr, int left, int right, int y, bool highlight) const
1112 {
1113  const SettingDesc *sd = this->setting;
1114  const SettingDescBase *sdb = &sd->desc;
1115  const void *var = ResolveVariableAddress(settings_ptr, sd);
1116  int state = this->flags & SEF_BUTTONS_MASK;
1117 
1118  bool rtl = _current_text_dir == TD_RTL;
1119  uint buttons_left = rtl ? right + 1 - SETTING_BUTTON_WIDTH : left;
1120  uint text_left = left + (rtl ? 0 : SETTING_BUTTON_WIDTH + 5);
1121  uint text_right = right - (rtl ? SETTING_BUTTON_WIDTH + 5 : 0);
1122  uint button_y = y + (SETTING_HEIGHT - SETTING_BUTTON_HEIGHT) / 2;
1123 
1124  /* We do not allow changes of some items when we are a client in a networkgame */
1125  bool editable = sd->IsEditable();
1126 
1127  SetDParam(0, highlight ? STR_ORANGE_STRING1_WHITE : STR_ORANGE_STRING1_LTBLUE);
1128  int32 value = (int32)ReadValue(var, sd->save.conv);
1129  if (sdb->cmd == SDT_BOOLX) {
1130  /* Draw checkbox for boolean-value either on/off */
1131  DrawBoolButton(buttons_left, button_y, value != 0, editable);
1132  } else if ((sdb->flags & SGF_MULTISTRING) != 0) {
1133  /* Draw [v] button for settings of an enum-type */
1134  DrawDropDownButton(buttons_left, button_y, COLOUR_YELLOW, state != 0, editable);
1135  } else {
1136  /* Draw [<][>] boxes for settings of an integer-type */
1137  DrawArrowButtons(buttons_left, button_y, COLOUR_YELLOW, state,
1138  editable && value != (sdb->flags & SGF_0ISDISABLED ? 0 : sdb->min), editable && (uint32)value != sdb->max);
1139  }
1140  this->SetValueDParams(1, value);
1141  DrawString(text_left, text_right, y + (SETTING_HEIGHT - FONT_HEIGHT_NORMAL) / 2, sdb->str, highlight ? TC_WHITE : TC_LIGHT_BLUE);
1142 }
1143 
1144 /* == SettingsContainer methods == */
1145 
1150 void SettingsContainer::Init(byte level)
1151 {
1152  for (EntryVector::iterator it = this->entries.begin(); it != this->entries.end(); ++it) {
1153  (*it)->Init(level);
1154  }
1155 }
1156 
1159 {
1160  for (EntryVector::iterator it = this->entries.begin(); it != this->entries.end(); ++it) {
1161  (*it)->FoldAll();
1162  }
1163 }
1164 
1167 {
1168  for (EntryVector::iterator it = this->entries.begin(); it != this->entries.end(); ++it) {
1169  (*it)->UnFoldAll();
1170  }
1171 }
1172 
1178 void SettingsContainer::GetFoldingState(bool &all_folded, bool &all_unfolded) const
1179 {
1180  for (EntryVector::const_iterator it = this->entries.begin(); it != this->entries.end(); ++it) {
1181  (*it)->GetFoldingState(all_folded, all_unfolded);
1182  }
1183 }
1184 
1191 bool SettingsContainer::UpdateFilterState(SettingFilter &filter, bool force_visible)
1192 {
1193  bool visible = false;
1194  bool first_visible = true;
1195  for (EntryVector::reverse_iterator it = this->entries.rbegin(); it != this->entries.rend(); ++it) {
1196  visible |= (*it)->UpdateFilterState(filter, force_visible);
1197  (*it)->SetLastField(first_visible);
1198  if (visible && first_visible) first_visible = false;
1199  }
1200  return visible;
1201 }
1202 
1203 
1211 {
1212  for (EntryVector::const_iterator it = this->entries.begin(); it != this->entries.end(); ++it) {
1213  if ((*it)->IsVisible(item)) return true;
1214  }
1215  return false;
1216 }
1217 
1220 {
1221  uint length = 0;
1222  for (EntryVector::const_iterator it = this->entries.begin(); it != this->entries.end(); ++it) {
1223  length += (*it)->Length();
1224  }
1225  return length;
1226 }
1227 
1234 BaseSettingEntry *SettingsContainer::FindEntry(uint row_num, uint *cur_row)
1235 {
1236  BaseSettingEntry *pe = NULL;
1237  for (EntryVector::iterator it = this->entries.begin(); it != this->entries.end(); ++it) {
1238  pe = (*it)->FindEntry(row_num, cur_row);
1239  if (pe != NULL) {
1240  break;
1241  }
1242  }
1243  return pe;
1244 }
1245 
1252 {
1253  uint biggest = 0;
1254  for (EntryVector::const_iterator it = this->entries.begin(); it != this->entries.end(); ++it) {
1255  biggest = max(biggest, (*it)->GetMaxHelpHeight(maxw));
1256  }
1257  return biggest;
1258 }
1259 
1260 
1275 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
1276 {
1277  for (EntryVector::const_iterator it = this->entries.begin(); it != this->entries.end(); ++it) {
1278  cur_row = (*it)->Draw(settings_ptr, left, right, y, first_row, max_row, selected, cur_row, parent_last);
1279  if (cur_row >= max_row) {
1280  break;
1281  }
1282  }
1283  return cur_row;
1284 }
1285 
1286 /* == SettingsPage methods == */
1287 
1293 {
1294  this->title = title;
1295  this->folded = true;
1296 }
1297 
1302 void SettingsPage::Init(byte level)
1303 {
1304  BaseSettingEntry::Init(level);
1305  SettingsContainer::Init(level + 1);
1306 }
1307 
1310 {
1311  if (this->IsFiltered()) return;
1312  this->folded = true;
1313 
1315 }
1316 
1319 {
1320  if (this->IsFiltered()) return;
1321  this->folded = false;
1322 
1324 }
1325 
1331 void SettingsPage::GetFoldingState(bool &all_folded, bool &all_unfolded) const
1332 {
1333  if (this->IsFiltered()) return;
1334 
1335  if (this->folded) {
1336  all_unfolded = false;
1337  } else {
1338  all_folded = false;
1339  }
1340 
1341  SettingsContainer::GetFoldingState(all_folded, all_unfolded);
1342 }
1343 
1350 bool SettingsPage::UpdateFilterState(SettingFilter &filter, bool force_visible)
1351 {
1352  if (!force_visible && !filter.string.IsEmpty()) {
1353  filter.string.ResetState();
1354  filter.string.AddLine(this->title);
1355  force_visible = filter.string.GetState();
1356  }
1357 
1358  bool visible = SettingsContainer::UpdateFilterState(filter, force_visible);
1359  if (visible) {
1360  CLRBITS(this->flags, SEF_FILTERED);
1361  } else {
1362  SETBITS(this->flags, SEF_FILTERED);
1363  }
1364  return visible;
1365 }
1366 
1374 {
1375  if (this->IsFiltered()) return false;
1376  if (this == item) return true;
1377  if (this->folded) return false;
1378 
1379  return SettingsContainer::IsVisible(item);
1380 }
1381 
1384 {
1385  if (this->IsFiltered()) return 0;
1386  if (this->folded) return 1; // Only displaying the title
1387 
1388  return 1 + SettingsContainer::Length();
1389 }
1390 
1397 BaseSettingEntry *SettingsPage::FindEntry(uint row_num, uint *cur_row)
1398 {
1399  if (this->IsFiltered()) return NULL;
1400  if (row_num == *cur_row) return this;
1401  (*cur_row)++;
1402  if (this->folded) return NULL;
1403 
1404  return SettingsContainer::FindEntry(row_num, cur_row);
1405 }
1406 
1421 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
1422 {
1423  if (this->IsFiltered()) return cur_row;
1424  if (cur_row >= max_row) return cur_row;
1425 
1426  cur_row = BaseSettingEntry::Draw(settings_ptr, left, right, y, first_row, max_row, selected, cur_row, parent_last);
1427 
1428  if (!this->folded) {
1429  if (this->flags & SEF_LAST_FIELD) {
1430  assert(this->level < 8 * sizeof(parent_last));
1431  SetBit(parent_last, this->level); // Add own last-field state
1432  }
1433 
1434  cur_row = SettingsContainer::Draw(settings_ptr, left, right, y, first_row, max_row, selected, cur_row, parent_last);
1435  }
1436 
1437  return cur_row;
1438 }
1439 
1448 void SettingsPage::DrawSetting(GameSettings *settings_ptr, int left, int right, int y, bool highlight) const
1449 {
1450  bool rtl = _current_text_dir == TD_RTL;
1451  DrawSprite((this->folded ? SPR_CIRCLE_FOLDED : SPR_CIRCLE_UNFOLDED), PAL_NONE, rtl ? right - _circle_size.width : left, y + (SETTING_HEIGHT - _circle_size.height) / 2);
1452  DrawString(rtl ? left : left + _circle_size.width + 2, rtl ? right - _circle_size.width - 2 : right, y + (SETTING_HEIGHT - FONT_HEIGHT_NORMAL) / 2, this->title);
1453 }
1454 
1457 {
1458  static SettingsContainer *main = NULL;
1459 
1460  if (main == NULL)
1461  {
1462  /* Build up the dynamic settings-array only once per OpenTTD session */
1463  main = new SettingsContainer();
1464 
1465  SettingsPage *localisation = main->Add(new SettingsPage(STR_CONFIG_SETTING_LOCALISATION));
1466  {
1467  localisation->Add(new SettingEntry("locale.units_velocity"));
1468  localisation->Add(new SettingEntry("locale.units_power"));
1469  localisation->Add(new SettingEntry("locale.units_weight"));
1470  localisation->Add(new SettingEntry("locale.units_volume"));
1471  localisation->Add(new SettingEntry("locale.units_force"));
1472  localisation->Add(new SettingEntry("locale.units_height"));
1473  localisation->Add(new SettingEntry("gui.date_format_in_default_names"));
1474  }
1475 
1476  SettingsPage *graphics = main->Add(new SettingsPage(STR_CONFIG_SETTING_GRAPHICS));
1477  {
1478  graphics->Add(new SettingEntry("gui.zoom_min"));
1479  graphics->Add(new SettingEntry("gui.zoom_max"));
1480  graphics->Add(new SettingEntry("gui.smallmap_land_colour"));
1481  graphics->Add(new SettingEntry("gui.graph_line_thickness"));
1482  }
1483 
1484  SettingsPage *sound = main->Add(new SettingsPage(STR_CONFIG_SETTING_SOUND));
1485  {
1486  sound->Add(new SettingEntry("sound.click_beep"));
1487  sound->Add(new SettingEntry("sound.confirm"));
1488  sound->Add(new SettingEntry("sound.news_ticker"));
1489  sound->Add(new SettingEntry("sound.news_full"));
1490  sound->Add(new SettingEntry("sound.new_year"));
1491  sound->Add(new SettingEntry("sound.disaster"));
1492  sound->Add(new SettingEntry("sound.vehicle"));
1493  sound->Add(new SettingEntry("sound.ambient"));
1494  }
1495 
1496  SettingsPage *interface = main->Add(new SettingsPage(STR_CONFIG_SETTING_INTERFACE));
1497  {
1498  SettingsPage *general = interface->Add(new SettingsPage(STR_CONFIG_SETTING_INTERFACE_GENERAL));
1499  {
1500  general->Add(new SettingEntry("gui.osk_activation"));
1501  general->Add(new SettingEntry("gui.hover_delay_ms"));
1502  general->Add(new SettingEntry("gui.errmsg_duration"));
1503  general->Add(new SettingEntry("gui.window_snap_radius"));
1504  general->Add(new SettingEntry("gui.window_soft_limit"));
1505  general->Add(new SettingEntry("gui.right_mouse_wnd_close"));
1506  }
1507 
1508  SettingsPage *viewports = interface->Add(new SettingsPage(STR_CONFIG_SETTING_INTERFACE_VIEWPORTS));
1509  {
1510  viewports->Add(new SettingEntry("gui.auto_scrolling"));
1511  viewports->Add(new SettingEntry("gui.reverse_scroll"));
1512  viewports->Add(new SettingEntry("gui.smooth_scroll"));
1513  viewports->Add(new SettingEntry("gui.left_mouse_btn_scrolling"));
1514  /* While the horizontal scrollwheel scrolling is written as general code, only
1515  * the cocoa (OSX) driver generates input for it.
1516  * Since it's also able to completely disable the scrollwheel will we display it on all platforms anyway */
1517  viewports->Add(new SettingEntry("gui.scrollwheel_scrolling"));
1518  viewports->Add(new SettingEntry("gui.scrollwheel_multiplier"));
1519 #ifdef __APPLE__
1520  /* We might need to emulate a right mouse button on mac */
1521  viewports->Add(new SettingEntry("gui.right_mouse_btn_emulation"));
1522 #endif
1523  viewports->Add(new SettingEntry("gui.population_in_label"));
1524  viewports->Add(new SettingEntry("gui.liveries"));
1525  viewports->Add(new SettingEntry("construction.train_signal_side"));
1526  viewports->Add(new SettingEntry("gui.measure_tooltip"));
1527  viewports->Add(new SettingEntry("gui.loading_indicators"));
1528  viewports->Add(new SettingEntry("gui.show_track_reservation"));
1529  }
1530 
1531  SettingsPage *construction = interface->Add(new SettingsPage(STR_CONFIG_SETTING_INTERFACE_CONSTRUCTION));
1532  {
1533  construction->Add(new SettingEntry("gui.link_terraform_toolbar"));
1534  construction->Add(new SettingEntry("gui.enable_signal_gui"));
1535  construction->Add(new SettingEntry("gui.persistent_buildingtools"));
1536  construction->Add(new SettingEntry("gui.quick_goto"));
1537  construction->Add(new SettingEntry("gui.default_rail_type"));
1538  construction->Add(new SettingEntry("gui.disable_unsuitable_building"));
1539  }
1540 
1541  interface->Add(new SettingEntry("gui.autosave"));
1542  interface->Add(new SettingEntry("gui.toolbar_pos"));
1543  interface->Add(new SettingEntry("gui.statusbar_pos"));
1544  interface->Add(new SettingEntry("gui.prefer_teamchat"));
1545  interface->Add(new SettingEntry("gui.advanced_vehicle_list"));
1546  interface->Add(new SettingEntry("gui.timetable_in_ticks"));
1547  interface->Add(new SettingEntry("gui.timetable_arrival_departure"));
1548  interface->Add(new SettingEntry("gui.expenses_layout"));
1549  }
1550 
1551  SettingsPage *advisors = main->Add(new SettingsPage(STR_CONFIG_SETTING_ADVISORS));
1552  {
1553  advisors->Add(new SettingEntry("gui.coloured_news_year"));
1554  advisors->Add(new SettingEntry("news_display.general"));
1555  advisors->Add(new SettingEntry("news_display.new_vehicles"));
1556  advisors->Add(new SettingEntry("news_display.accident"));
1557  advisors->Add(new SettingEntry("news_display.company_info"));
1558  advisors->Add(new SettingEntry("news_display.acceptance"));
1559  advisors->Add(new SettingEntry("news_display.arrival_player"));
1560  advisors->Add(new SettingEntry("news_display.arrival_other"));
1561  advisors->Add(new SettingEntry("news_display.advice"));
1562  advisors->Add(new SettingEntry("gui.order_review_system"));
1563  advisors->Add(new SettingEntry("gui.vehicle_income_warn"));
1564  advisors->Add(new SettingEntry("gui.lost_vehicle_warn"));
1565  advisors->Add(new SettingEntry("gui.show_finances"));
1566  advisors->Add(new SettingEntry("news_display.economy"));
1567  advisors->Add(new SettingEntry("news_display.subsidies"));
1568  advisors->Add(new SettingEntry("news_display.open"));
1569  advisors->Add(new SettingEntry("news_display.close"));
1570  advisors->Add(new SettingEntry("news_display.production_player"));
1571  advisors->Add(new SettingEntry("news_display.production_other"));
1572  advisors->Add(new SettingEntry("news_display.production_nobody"));
1573  }
1574 
1575  SettingsPage *company = main->Add(new SettingsPage(STR_CONFIG_SETTING_COMPANY));
1576  {
1577  company->Add(new SettingEntry("gui.semaphore_build_before"));
1578  company->Add(new SettingEntry("gui.default_signal_type"));
1579  company->Add(new SettingEntry("gui.cycle_signal_types"));
1580  company->Add(new SettingEntry("gui.drag_signals_fixed_distance"));
1581  company->Add(new SettingEntry("gui.new_nonstop"));
1582  company->Add(new SettingEntry("gui.stop_location"));
1583  company->Add(new SettingEntry("company.engine_renew"));
1584  company->Add(new SettingEntry("company.engine_renew_months"));
1585  company->Add(new SettingEntry("company.engine_renew_money"));
1586  company->Add(new SettingEntry("vehicle.servint_ispercent"));
1587  company->Add(new SettingEntry("vehicle.servint_trains"));
1588  company->Add(new SettingEntry("vehicle.servint_roadveh"));
1589  company->Add(new SettingEntry("vehicle.servint_ships"));
1590  company->Add(new SettingEntry("vehicle.servint_aircraft"));
1591  }
1592 
1593  SettingsPage *accounting = main->Add(new SettingsPage(STR_CONFIG_SETTING_ACCOUNTING));
1594  {
1595  accounting->Add(new SettingEntry("economy.inflation"));
1596  accounting->Add(new SettingEntry("difficulty.initial_interest"));
1597  accounting->Add(new SettingEntry("difficulty.max_loan"));
1598  accounting->Add(new SettingEntry("difficulty.subsidy_multiplier"));
1599  accounting->Add(new SettingEntry("economy.feeder_payment_share"));
1600  accounting->Add(new SettingEntry("economy.infrastructure_maintenance"));
1601  accounting->Add(new SettingEntry("difficulty.vehicle_costs"));
1602  accounting->Add(new SettingEntry("difficulty.construction_cost"));
1603  }
1604 
1605  SettingsPage *vehicles = main->Add(new SettingsPage(STR_CONFIG_SETTING_VEHICLES));
1606  {
1607  SettingsPage *physics = vehicles->Add(new SettingsPage(STR_CONFIG_SETTING_VEHICLES_PHYSICS));
1608  {
1609  physics->Add(new SettingEntry("vehicle.train_acceleration_model"));
1610  physics->Add(new SettingEntry("vehicle.train_slope_steepness"));
1611  physics->Add(new SettingEntry("vehicle.wagon_speed_limits"));
1612  physics->Add(new SettingEntry("vehicle.freight_trains"));
1613  physics->Add(new SettingEntry("vehicle.roadveh_acceleration_model"));
1614  physics->Add(new SettingEntry("vehicle.roadveh_slope_steepness"));
1615  physics->Add(new SettingEntry("vehicle.smoke_amount"));
1616  physics->Add(new SettingEntry("vehicle.plane_speed"));
1617  }
1618 
1619  SettingsPage *routing = vehicles->Add(new SettingsPage(STR_CONFIG_SETTING_VEHICLES_ROUTING));
1620  {
1621  routing->Add(new SettingEntry("pf.pathfinder_for_trains"));
1622  routing->Add(new SettingEntry("difficulty.line_reverse_mode"));
1623  routing->Add(new SettingEntry("pf.reverse_at_signals"));
1624  routing->Add(new SettingEntry("pf.forbid_90_deg"));
1625  routing->Add(new SettingEntry("pf.pathfinder_for_roadvehs"));
1626  routing->Add(new SettingEntry("pf.pathfinder_for_ships"));
1627  }
1628 
1629  vehicles->Add(new SettingEntry("order.no_servicing_if_no_breakdowns"));
1630  vehicles->Add(new SettingEntry("order.serviceathelipad"));
1631  }
1632 
1633  SettingsPage *limitations = main->Add(new SettingsPage(STR_CONFIG_SETTING_LIMITATIONS));
1634  {
1635  limitations->Add(new SettingEntry("construction.command_pause_level"));
1636  limitations->Add(new SettingEntry("construction.autoslope"));
1637  limitations->Add(new SettingEntry("construction.extra_dynamite"));
1638  limitations->Add(new SettingEntry("construction.max_heightlevel"));
1639  limitations->Add(new SettingEntry("construction.max_bridge_length"));
1640  limitations->Add(new SettingEntry("construction.max_bridge_height"));
1641  limitations->Add(new SettingEntry("construction.max_tunnel_length"));
1642  limitations->Add(new SettingEntry("station.never_expire_airports"));
1643  limitations->Add(new SettingEntry("vehicle.never_expire_vehicles"));
1644  limitations->Add(new SettingEntry("vehicle.max_trains"));
1645  limitations->Add(new SettingEntry("vehicle.max_roadveh"));
1646  limitations->Add(new SettingEntry("vehicle.max_aircraft"));
1647  limitations->Add(new SettingEntry("vehicle.max_ships"));
1648  limitations->Add(new SettingEntry("vehicle.max_train_length"));
1649  limitations->Add(new SettingEntry("station.station_spread"));
1650  limitations->Add(new SettingEntry("station.distant_join_stations"));
1651  limitations->Add(new SettingEntry("construction.road_stop_on_town_road"));
1652  limitations->Add(new SettingEntry("construction.road_stop_on_competitor_road"));
1653  limitations->Add(new SettingEntry("vehicle.disable_elrails"));
1654  }
1655 
1656  SettingsPage *disasters = main->Add(new SettingsPage(STR_CONFIG_SETTING_ACCIDENTS));
1657  {
1658  disasters->Add(new SettingEntry("difficulty.disasters"));
1659  disasters->Add(new SettingEntry("difficulty.economy"));
1660  disasters->Add(new SettingEntry("difficulty.vehicle_breakdowns"));
1661  disasters->Add(new SettingEntry("vehicle.plane_crashes"));
1662  }
1663 
1664  SettingsPage *genworld = main->Add(new SettingsPage(STR_CONFIG_SETTING_GENWORLD));
1665  {
1666  genworld->Add(new SettingEntry("game_creation.landscape"));
1667  genworld->Add(new SettingEntry("game_creation.land_generator"));
1668  genworld->Add(new SettingEntry("difficulty.terrain_type"));
1669  genworld->Add(new SettingEntry("game_creation.tgen_smoothness"));
1670  genworld->Add(new SettingEntry("game_creation.variety"));
1671  genworld->Add(new SettingEntry("game_creation.snow_line_height"));
1672  genworld->Add(new SettingEntry("game_creation.amount_of_rivers"));
1673  genworld->Add(new SettingEntry("game_creation.tree_placer"));
1674  genworld->Add(new SettingEntry("vehicle.road_side"));
1675  genworld->Add(new SettingEntry("economy.larger_towns"));
1676  genworld->Add(new SettingEntry("economy.initial_city_size"));
1677  genworld->Add(new SettingEntry("economy.town_layout"));
1678  genworld->Add(new SettingEntry("difficulty.industry_density"));
1679  genworld->Add(new SettingEntry("gui.pause_on_newgame"));
1680  }
1681 
1682  SettingsPage *environment = main->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT));
1683  {
1684  SettingsPage *authorities = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_AUTHORITIES));
1685  {
1686  authorities->Add(new SettingEntry("difficulty.town_council_tolerance"));
1687  authorities->Add(new SettingEntry("economy.bribe"));
1688  authorities->Add(new SettingEntry("economy.exclusive_rights"));
1689  authorities->Add(new SettingEntry("economy.fund_roads"));
1690  authorities->Add(new SettingEntry("economy.fund_buildings"));
1691  authorities->Add(new SettingEntry("economy.station_noise_level"));
1692  }
1693 
1694  SettingsPage *towns = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_TOWNS));
1695  {
1696  towns->Add(new SettingEntry("economy.town_growth_rate"));
1697  towns->Add(new SettingEntry("economy.allow_town_roads"));
1698  towns->Add(new SettingEntry("economy.allow_town_level_crossings"));
1699  towns->Add(new SettingEntry("economy.found_town"));
1700  }
1701 
1702  SettingsPage *industries = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_INDUSTRIES));
1703  {
1704  industries->Add(new SettingEntry("construction.raw_industry_construction"));
1705  industries->Add(new SettingEntry("construction.industry_platform"));
1706  industries->Add(new SettingEntry("economy.multiple_industry_per_town"));
1707  industries->Add(new SettingEntry("game_creation.oil_refinery_limit"));
1708  industries->Add(new SettingEntry("economy.smooth_economy"));
1709  }
1710 
1711  SettingsPage *cdist = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_CARGODIST));
1712  {
1713  cdist->Add(new SettingEntry("linkgraph.recalc_time"));
1714  cdist->Add(new SettingEntry("linkgraph.recalc_interval"));
1715  cdist->Add(new SettingEntry("linkgraph.distribution_pax"));
1716  cdist->Add(new SettingEntry("linkgraph.distribution_mail"));
1717  cdist->Add(new SettingEntry("linkgraph.distribution_armoured"));
1718  cdist->Add(new SettingEntry("linkgraph.distribution_default"));
1719  cdist->Add(new SettingEntry("linkgraph.accuracy"));
1720  cdist->Add(new SettingEntry("linkgraph.demand_distance"));
1721  cdist->Add(new SettingEntry("linkgraph.demand_size"));
1722  cdist->Add(new SettingEntry("linkgraph.short_path_saturation"));
1723  }
1724 
1725  environment->Add(new SettingEntry("station.modified_catchment"));
1726  environment->Add(new SettingEntry("construction.extra_tree_placement"));
1727  }
1728 
1729  SettingsPage *ai = main->Add(new SettingsPage(STR_CONFIG_SETTING_AI));
1730  {
1731  SettingsPage *npc = ai->Add(new SettingsPage(STR_CONFIG_SETTING_AI_NPC));
1732  {
1733  npc->Add(new SettingEntry("script.settings_profile"));
1734  npc->Add(new SettingEntry("script.script_max_opcode_till_suspend"));
1735  npc->Add(new SettingEntry("difficulty.competitor_speed"));
1736  npc->Add(new SettingEntry("ai.ai_in_multiplayer"));
1737  npc->Add(new SettingEntry("ai.ai_disable_veh_train"));
1738  npc->Add(new SettingEntry("ai.ai_disable_veh_roadveh"));
1739  npc->Add(new SettingEntry("ai.ai_disable_veh_aircraft"));
1740  npc->Add(new SettingEntry("ai.ai_disable_veh_ship"));
1741  }
1742 
1743  ai->Add(new SettingEntry("economy.give_money"));
1744  ai->Add(new SettingEntry("economy.allow_shares"));
1745  }
1746 
1747  main->Init();
1748  }
1749  return *main;
1750 }
1751 
1752 static const StringID _game_settings_restrict_dropdown[] = {
1753  STR_CONFIG_SETTING_RESTRICT_BASIC, // RM_BASIC
1754  STR_CONFIG_SETTING_RESTRICT_ADVANCED, // RM_ADVANCED
1755  STR_CONFIG_SETTING_RESTRICT_ALL, // RM_ALL
1756  STR_CONFIG_SETTING_RESTRICT_CHANGED_AGAINST_DEFAULT, // RM_CHANGED_AGAINST_DEFAULT
1757  STR_CONFIG_SETTING_RESTRICT_CHANGED_AGAINST_NEW, // RM_CHANGED_AGAINST_NEW
1758 };
1759 assert_compile(lengthof(_game_settings_restrict_dropdown) == RM_END);
1760 
1767 };
1768 
1771  static const int SETTINGTREE_LEFT_OFFSET = 5;
1772  static const int SETTINGTREE_RIGHT_OFFSET = 5;
1773  static const int SETTINGTREE_TOP_OFFSET = 5;
1774  static const int SETTINGTREE_BOTTOM_OFFSET = 5;
1775 
1777 
1783 
1789 
1790  Scrollbar *vscroll;
1791 
1792  GameSettingsWindow(WindowDesc *desc) : Window(desc), filter_editbox(50)
1793  {
1794  this->warn_missing = WHR_NONE;
1795  this->warn_lines = 0;
1797  this->filter.min_cat = RM_ALL;
1798  this->filter.type = ST_ALL;
1799  this->filter.type_hides = false;
1800  this->settings_ptr = &GetGameSettings();
1801 
1802  _circle_size = maxdim(GetSpriteSize(SPR_CIRCLE_FOLDED), GetSpriteSize(SPR_CIRCLE_UNFOLDED));
1803  GetSettingsTree().FoldAll(); // Close all sub-pages
1804 
1805  this->valuewindow_entry = NULL; // No setting entry for which a entry window is opened
1806  this->clicked_entry = NULL; // No numeric setting buttons are depressed
1807  this->last_clicked = NULL;
1808  this->valuedropdown_entry = NULL;
1809  this->closing_dropdown = false;
1810  this->manually_changed_folding = false;
1811 
1812  this->CreateNestedTree();
1813  this->vscroll = this->GetScrollbar(WID_GS_SCROLLBAR);
1815 
1816  this->querystrings[WID_GS_FILTER] = &this->filter_editbox;
1817  this->filter_editbox.cancel_button = QueryString::ACTION_CLEAR;
1819 
1820  this->InvalidateData();
1821  }
1822 
1823  virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
1824  {
1825  switch (widget) {
1826  case WID_GS_OPTIONSPANEL:
1827  resize->height = SETTING_HEIGHT = max(max<int>(_circle_size.height, SETTING_BUTTON_HEIGHT), FONT_HEIGHT_NORMAL) + 1;
1828  resize->width = 1;
1829 
1830  size->height = 5 * resize->height + SETTINGTREE_TOP_OFFSET + SETTINGTREE_BOTTOM_OFFSET;
1831  break;
1832 
1833  case WID_GS_HELP_TEXT: {
1834  static const StringID setting_types[] = {
1835  STR_CONFIG_SETTING_TYPE_CLIENT,
1836  STR_CONFIG_SETTING_TYPE_COMPANY_MENU, STR_CONFIG_SETTING_TYPE_COMPANY_INGAME,
1837  STR_CONFIG_SETTING_TYPE_GAME_MENU, STR_CONFIG_SETTING_TYPE_GAME_INGAME,
1838  };
1839  for (uint i = 0; i < lengthof(setting_types); i++) {
1840  SetDParam(0, setting_types[i]);
1841  size->width = max(size->width, GetStringBoundingBox(STR_CONFIG_SETTING_TYPE).width);
1842  }
1843  size->height = 2 * FONT_HEIGHT_NORMAL + WD_PAR_VSEP_NORMAL +
1844  max(size->height, GetSettingsTree().GetMaxHelpHeight(size->width));
1845  break;
1846  }
1847 
1849  case WID_GS_RESTRICT_TYPE:
1850  size->width = max(GetStringBoundingBox(STR_CONFIG_SETTING_RESTRICT_CATEGORY).width, GetStringBoundingBox(STR_CONFIG_SETTING_RESTRICT_TYPE).width);
1851  break;
1852 
1853  default:
1854  break;
1855  }
1856  }
1857 
1858  virtual void OnPaint()
1859  {
1860  if (this->closing_dropdown) {
1861  this->closing_dropdown = false;
1862  assert(this->valuedropdown_entry != NULL);
1863  this->valuedropdown_entry->SetButtons(0);
1864  this->valuedropdown_entry = NULL;
1865  }
1866 
1867  /* Reserve the correct number of lines for the 'some search results are hidden' notice in the central settings display panel. */
1868  const NWidgetBase *panel = this->GetWidget<NWidgetBase>(WID_GS_OPTIONSPANEL);
1869  StringID warn_str = STR_CONFIG_SETTING_CATEGORY_HIDES - 1 + this->warn_missing;
1870  int new_warn_lines;
1871  if (this->warn_missing == WHR_NONE) {
1872  new_warn_lines = 0;
1873  } else {
1874  SetDParam(0, _game_settings_restrict_dropdown[this->filter.min_cat]);
1875  new_warn_lines = GetStringLineCount(warn_str, panel->current_x);
1876  }
1877  if (this->warn_lines != new_warn_lines) {
1878  this->vscroll->SetCount(this->vscroll->GetCount() - this->warn_lines + new_warn_lines);
1879  this->warn_lines = new_warn_lines;
1880  }
1881 
1882  this->DrawWidgets();
1883 
1884  /* Draw the 'some search results are hidden' notice. */
1885  if (this->warn_missing != WHR_NONE) {
1886  const int left = panel->pos_x;
1887  const int right = left + panel->current_x - 1;
1888  const int top = panel->pos_y + WD_FRAMETEXT_TOP + (SETTING_HEIGHT - FONT_HEIGHT_NORMAL) * this->warn_lines / 2;
1889  SetDParam(0, _game_settings_restrict_dropdown[this->filter.min_cat]);
1890  if (this->warn_lines == 1) {
1891  /* If the warning fits at one line, center it. */
1892  DrawString(left + WD_FRAMETEXT_LEFT, right - WD_FRAMETEXT_RIGHT, top, warn_str, TC_FROMSTRING, SA_HOR_CENTER);
1893  } else {
1894  DrawStringMultiLine(left + WD_FRAMERECT_LEFT, right - WD_FRAMERECT_RIGHT, top, INT32_MAX, warn_str, TC_FROMSTRING, SA_HOR_CENTER);
1895  }
1896  }
1897  }
1898 
1899  virtual void SetStringParameters(int widget) const
1900  {
1901  switch (widget) {
1903  SetDParam(0, _game_settings_restrict_dropdown[this->filter.mode]);
1904  break;
1905 
1906  case WID_GS_TYPE_DROPDOWN:
1907  switch (this->filter.type) {
1908  case ST_GAME: SetDParam(0, _game_mode == GM_MENU ? STR_CONFIG_SETTING_TYPE_DROPDOWN_GAME_MENU : STR_CONFIG_SETTING_TYPE_DROPDOWN_GAME_INGAME); break;
1909  case ST_COMPANY: SetDParam(0, _game_mode == GM_MENU ? STR_CONFIG_SETTING_TYPE_DROPDOWN_COMPANY_MENU : STR_CONFIG_SETTING_TYPE_DROPDOWN_COMPANY_INGAME); break;
1910  case ST_CLIENT: SetDParam(0, STR_CONFIG_SETTING_TYPE_DROPDOWN_CLIENT); break;
1911  default: SetDParam(0, STR_CONFIG_SETTING_TYPE_DROPDOWN_ALL); break;
1912  }
1913  break;
1914  }
1915  }
1916 
1917  DropDownList *BuildDropDownList(int widget) const
1918  {
1919  DropDownList *list = NULL;
1920  switch (widget) {
1922  list = new DropDownList();
1923 
1924  for (int mode = 0; mode != RM_END; mode++) {
1925  /* If we are in adv. settings screen for the new game's settings,
1926  * we don't want to allow comparing with new game's settings. */
1927  bool disabled = mode == RM_CHANGED_AGAINST_NEW && settings_ptr == &_settings_newgame;
1928 
1929  *list->Append() = new DropDownListStringItem(_game_settings_restrict_dropdown[mode], mode, disabled);
1930  }
1931  break;
1932 
1933  case WID_GS_TYPE_DROPDOWN:
1934  list = new DropDownList();
1935  *list->Append() = new DropDownListStringItem(STR_CONFIG_SETTING_TYPE_DROPDOWN_ALL, ST_ALL, false);
1936  *list->Append() = new DropDownListStringItem(_game_mode == GM_MENU ? STR_CONFIG_SETTING_TYPE_DROPDOWN_GAME_MENU : STR_CONFIG_SETTING_TYPE_DROPDOWN_GAME_INGAME, ST_GAME, false);
1937  *list->Append() = new DropDownListStringItem(_game_mode == GM_MENU ? STR_CONFIG_SETTING_TYPE_DROPDOWN_COMPANY_MENU : STR_CONFIG_SETTING_TYPE_DROPDOWN_COMPANY_INGAME, ST_COMPANY, false);
1938  *list->Append() = new DropDownListStringItem(STR_CONFIG_SETTING_TYPE_DROPDOWN_CLIENT, ST_CLIENT, false);
1939  break;
1940  }
1941  return list;
1942  }
1943 
1944  virtual void DrawWidget(const Rect &r, int widget) const
1945  {
1946  switch (widget) {
1947  case WID_GS_OPTIONSPANEL: {
1948  int top_pos = r.top + SETTINGTREE_TOP_OFFSET + 1 + this->warn_lines * SETTING_HEIGHT;
1949  uint last_row = this->vscroll->GetPosition() + this->vscroll->GetCapacity() - this->warn_lines;
1950  int next_row = GetSettingsTree().Draw(settings_ptr, r.left + SETTINGTREE_LEFT_OFFSET, r.right - SETTINGTREE_RIGHT_OFFSET, top_pos,
1951  this->vscroll->GetPosition(), last_row, this->last_clicked);
1952  if (next_row == 0) DrawString(r.left + SETTINGTREE_LEFT_OFFSET, r.right - SETTINGTREE_RIGHT_OFFSET, top_pos, STR_CONFIG_SETTINGS_NONE);
1953  break;
1954  }
1955 
1956  case WID_GS_HELP_TEXT:
1957  if (this->last_clicked != NULL) {
1958  const SettingDesc *sd = this->last_clicked->setting;
1959 
1960  int y = r.top;
1961  switch (sd->GetType()) {
1962  case ST_COMPANY: SetDParam(0, _game_mode == GM_MENU ? STR_CONFIG_SETTING_TYPE_COMPANY_MENU : STR_CONFIG_SETTING_TYPE_COMPANY_INGAME); break;
1963  case ST_CLIENT: SetDParam(0, STR_CONFIG_SETTING_TYPE_CLIENT); break;
1964  case ST_GAME: SetDParam(0, _game_mode == GM_MENU ? STR_CONFIG_SETTING_TYPE_GAME_MENU : STR_CONFIG_SETTING_TYPE_GAME_INGAME); break;
1965  default: NOT_REACHED();
1966  }
1967  DrawString(r.left, r.right, y, STR_CONFIG_SETTING_TYPE);
1968  y += FONT_HEIGHT_NORMAL;
1969 
1970  int32 default_value = ReadValue(&sd->desc.def, sd->save.conv);
1971  this->last_clicked->SetValueDParams(0, default_value);
1972  DrawString(r.left, r.right, y, STR_CONFIG_SETTING_DEFAULT_VALUE);
1974 
1975  DrawStringMultiLine(r.left, r.right, y, r.bottom, this->last_clicked->GetHelpText(), TC_WHITE);
1976  }
1977  break;
1978 
1979  default:
1980  break;
1981  }
1982  }
1983 
1989  {
1990  if (this->last_clicked != pe) this->SetDirty();
1991  this->last_clicked = pe;
1992  }
1993 
1994  virtual void OnClick(Point pt, int widget, int click_count)
1995  {
1996  switch (widget) {
1997  case WID_GS_EXPAND_ALL:
1998  this->manually_changed_folding = true;
2000  this->InvalidateData();
2001  break;
2002 
2003  case WID_GS_COLLAPSE_ALL:
2004  this->manually_changed_folding = true;
2006  this->InvalidateData();
2007  break;
2008 
2009  case WID_GS_RESTRICT_DROPDOWN: {
2010  DropDownList *list = this->BuildDropDownList(widget);
2011  if (list != NULL) {
2012  ShowDropDownList(this, list, this->filter.mode, widget);
2013  }
2014  break;
2015  }
2016 
2017  case WID_GS_TYPE_DROPDOWN: {
2018  DropDownList *list = this->BuildDropDownList(widget);
2019  if (list != NULL) {
2020  ShowDropDownList(this, list, this->filter.type, widget);
2021  }
2022  break;
2023  }
2024  }
2025 
2026  if (widget != WID_GS_OPTIONSPANEL) return;
2027 
2028  uint btn = this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_GS_OPTIONSPANEL, SETTINGTREE_TOP_OFFSET);
2029  if (btn == INT_MAX || (int)btn < this->warn_lines) return;
2030  btn -= this->warn_lines;
2031 
2032  uint cur_row = 0;
2033  BaseSettingEntry *clicked_entry = GetSettingsTree().FindEntry(btn, &cur_row);
2034 
2035  if (clicked_entry == NULL) return; // Clicked below the last setting of the page
2036 
2037  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
2038  if (x < 0) return; // Clicked left of the entry
2039 
2040  SettingsPage *clicked_page = dynamic_cast<SettingsPage*>(clicked_entry);
2041  if (clicked_page != NULL) {
2042  this->SetDisplayedHelpText(NULL);
2043  clicked_page->folded = !clicked_page->folded; // Flip 'folded'-ness of the sub-page
2044 
2045  this->manually_changed_folding = true;
2046 
2047  this->InvalidateData();
2048  return;
2049  }
2050 
2051  SettingEntry *pe = dynamic_cast<SettingEntry*>(clicked_entry);
2052  assert(pe != NULL);
2053  const SettingDesc *sd = pe->setting;
2054 
2055  /* return if action is only active in network, or only settable by server */
2056  if (!sd->IsEditable()) {
2057  this->SetDisplayedHelpText(pe);
2058  return;
2059  }
2060 
2061  const void *var = ResolveVariableAddress(settings_ptr, sd);
2062  int32 value = (int32)ReadValue(var, sd->save.conv);
2063 
2064  /* clicked on the icon on the left side. Either scroller, bool on/off or dropdown */
2065  if (x < SETTING_BUTTON_WIDTH && (sd->desc.flags & SGF_MULTISTRING)) {
2066  const SettingDescBase *sdb = &sd->desc;
2067  this->SetDisplayedHelpText(pe);
2068 
2069  if (this->valuedropdown_entry == pe) {
2070  /* unclick the dropdown */
2071  HideDropDownMenu(this);
2072  this->closing_dropdown = false;
2073  this->valuedropdown_entry->SetButtons(0);
2074  this->valuedropdown_entry = NULL;
2075  } else {
2076  if (this->valuedropdown_entry != NULL) this->valuedropdown_entry->SetButtons(0);
2077  this->closing_dropdown = false;
2078 
2079  const NWidgetBase *wid = this->GetWidget<NWidgetBase>(WID_GS_OPTIONSPANEL);
2080  int rel_y = (pt.y - (int)wid->pos_y - SETTINGTREE_TOP_OFFSET) % wid->resize_y;
2081 
2082  Rect wi_rect;
2083  wi_rect.left = pt.x - (_current_text_dir == TD_RTL ? SETTING_BUTTON_WIDTH - 1 - x : x);
2084  wi_rect.right = wi_rect.left + SETTING_BUTTON_WIDTH - 1;
2085  wi_rect.top = pt.y - rel_y + (SETTING_HEIGHT - SETTING_BUTTON_HEIGHT) / 2;
2086  wi_rect.bottom = wi_rect.top + SETTING_BUTTON_HEIGHT - 1;
2087 
2088  /* For dropdowns we also have to check the y position thoroughly, the mouse may not above the just opening dropdown */
2089  if (pt.y >= wi_rect.top && pt.y <= wi_rect.bottom) {
2090  this->valuedropdown_entry = pe;
2091  this->valuedropdown_entry->SetButtons(SEF_LEFT_DEPRESSED);
2092 
2093  DropDownList *list = new DropDownList();
2094  for (int i = sdb->min; i <= (int)sdb->max; i++) {
2095  *list->Append() = new DropDownListStringItem(sdb->str_val + i - sdb->min, i, false);
2096  }
2097 
2098  ShowDropDownListAt(this, list, value, -1, wi_rect, COLOUR_ORANGE, true);
2099  }
2100  }
2101  this->SetDirty();
2102  } else if (x < SETTING_BUTTON_WIDTH) {
2103  this->SetDisplayedHelpText(pe);
2104  const SettingDescBase *sdb = &sd->desc;
2105  int32 oldvalue = value;
2106 
2107  switch (sdb->cmd) {
2108  case SDT_BOOLX: value ^= 1; break;
2109  case SDT_ONEOFMANY:
2110  case SDT_NUMX: {
2111  /* Add a dynamic step-size to the scroller. In a maximum of
2112  * 50-steps you should be able to get from min to max,
2113  * unless specified otherwise in the 'interval' variable
2114  * of the current setting. */
2115  uint32 step = (sdb->interval == 0) ? ((sdb->max - sdb->min) / 50) : sdb->interval;
2116  if (step == 0) step = 1;
2117 
2118  /* don't allow too fast scrolling */
2119  if ((this->flags & WF_TIMEOUT) && this->timeout_timer > 1) {
2120  _left_button_clicked = false;
2121  return;
2122  }
2123 
2124  /* Increase or decrease the value and clamp it to extremes */
2125  if (x >= SETTING_BUTTON_WIDTH / 2) {
2126  value += step;
2127  if (sdb->min < 0) {
2128  assert((int32)sdb->max >= 0);
2129  if (value > (int32)sdb->max) value = (int32)sdb->max;
2130  } else {
2131  if ((uint32)value > sdb->max) value = (int32)sdb->max;
2132  }
2133  if (value < sdb->min) value = sdb->min; // skip between "disabled" and minimum
2134  } else {
2135  value -= step;
2136  if (value < sdb->min) value = (sdb->flags & SGF_0ISDISABLED) ? 0 : sdb->min;
2137  }
2138 
2139  /* Set up scroller timeout for numeric values */
2140  if (value != oldvalue) {
2141  if (this->clicked_entry != NULL) { // Release previous buttons if any
2142  this->clicked_entry->SetButtons(0);
2143  }
2144  this->clicked_entry = pe;
2145  this->clicked_entry->SetButtons((x >= SETTING_BUTTON_WIDTH / 2) != (_current_text_dir == TD_RTL) ? SEF_RIGHT_DEPRESSED : SEF_LEFT_DEPRESSED);
2146  this->SetTimeout();
2147  _left_button_clicked = false;
2148  }
2149  break;
2150  }
2151 
2152  default: NOT_REACHED();
2153  }
2154 
2155  if (value != oldvalue) {
2156  if ((sd->desc.flags & SGF_PER_COMPANY) != 0) {
2157  SetCompanySetting(pe->index, value);
2158  } else {
2159  SetSettingValue(pe->index, value);
2160  }
2161  this->SetDirty();
2162  }
2163  } else {
2164  /* Only open editbox if clicked for the second time, and only for types where it is sensible for. */
2165  if (this->last_clicked == pe && sd->desc.cmd != SDT_BOOLX && !(sd->desc.flags & SGF_MULTISTRING)) {
2166  /* Show the correct currency-translated value */
2167  if (sd->desc.flags & SGF_CURRENCY) value *= _currency->rate;
2168 
2169  this->valuewindow_entry = pe;
2170  SetDParam(0, value);
2171  ShowQueryString(STR_JUST_INT, STR_CONFIG_SETTING_QUERY_CAPTION, 10, this, CS_NUMERAL, QSF_ENABLE_DEFAULT);
2172  }
2173  this->SetDisplayedHelpText(pe);
2174  }
2175  }
2176 
2177  virtual void OnTimeout()
2178  {
2179  if (this->clicked_entry != NULL) { // On timeout, release any depressed buttons
2180  this->clicked_entry->SetButtons(0);
2181  this->clicked_entry = NULL;
2182  this->SetDirty();
2183  }
2184  }
2185 
2186  virtual void OnQueryTextFinished(char *str)
2187  {
2188  /* The user pressed cancel */
2189  if (str == NULL) return;
2190 
2191  assert(this->valuewindow_entry != NULL);
2192  const SettingDesc *sd = this->valuewindow_entry->setting;
2193 
2194  int32 value;
2195  if (!StrEmpty(str)) {
2196  value = atoi(str);
2197 
2198  /* Save the correct currency-translated value */
2199  if (sd->desc.flags & SGF_CURRENCY) value /= _currency->rate;
2200  } else {
2201  value = (int32)(size_t)sd->desc.def;
2202  }
2203 
2204  if ((sd->desc.flags & SGF_PER_COMPANY) != 0) {
2205  SetCompanySetting(this->valuewindow_entry->index, value);
2206  } else {
2207  SetSettingValue(this->valuewindow_entry->index, value);
2208  }
2209  this->SetDirty();
2210  }
2211 
2212  virtual void OnDropdownSelect(int widget, int index)
2213  {
2214  switch (widget) {
2216  this->filter.mode = (RestrictionMode)index;
2217  if (this->filter.mode == RM_CHANGED_AGAINST_DEFAULT ||
2218  this->filter.mode == RM_CHANGED_AGAINST_NEW) {
2219 
2220  if (!this->manually_changed_folding) {
2221  /* Expand all when selecting 'changes'. Update the filter state first, in case it becomes less restrictive in some cases. */
2222  GetSettingsTree().UpdateFilterState(this->filter, false);
2224  }
2225  } else {
2226  /* Non-'changes' filter. Save as default. */
2228  }
2229  this->InvalidateData();
2230  break;
2231 
2232  case WID_GS_TYPE_DROPDOWN:
2233  this->filter.type = (SettingType)index;
2234  this->InvalidateData();
2235  break;
2236 
2237  default:
2238  if (widget < 0) {
2239  /* Deal with drop down boxes on the panel. */
2240  assert(this->valuedropdown_entry != NULL);
2241  const SettingDesc *sd = this->valuedropdown_entry->setting;
2242  assert(sd->desc.flags & SGF_MULTISTRING);
2243 
2244  if ((sd->desc.flags & SGF_PER_COMPANY) != 0) {
2245  SetCompanySetting(this->valuedropdown_entry->index, index);
2246  } else {
2247  SetSettingValue(this->valuedropdown_entry->index, index);
2248  }
2249 
2250  this->SetDirty();
2251  }
2252  break;
2253  }
2254  }
2255 
2256  virtual void OnDropdownClose(Point pt, int widget, int index, bool instant_close)
2257  {
2258  if (widget >= 0) {
2259  /* Normally the default implementation of OnDropdownClose() takes care of
2260  * a few things. We want that behaviour here too, but only for
2261  * "normal" dropdown boxes. The special dropdown boxes added for every
2262  * setting that needs one can't have this call. */
2263  Window::OnDropdownClose(pt, widget, index, instant_close);
2264  } else {
2265  /* We cannot raise the dropdown button just yet. OnClick needs some hint, whether
2266  * the same dropdown button was clicked again, and then not open the dropdown again.
2267  * So, we only remember that it was closed, and process it on the next OnPaint, which is
2268  * after OnClick. */
2269  assert(this->valuedropdown_entry != NULL);
2270  this->closing_dropdown = true;
2271  this->SetDirty();
2272  }
2273  }
2274 
2275  virtual void OnInvalidateData(int data = 0, bool gui_scope = true)
2276  {
2277  if (!gui_scope) return;
2278 
2279  /* Update which settings are to be visible. */
2280  RestrictionMode min_level = (this->filter.mode <= RM_ALL) ? this->filter.mode : RM_BASIC;
2281  this->filter.min_cat = min_level;
2282  this->filter.type_hides = false;
2283  GetSettingsTree().UpdateFilterState(this->filter, false);
2284 
2285  if (this->filter.string.IsEmpty()) {
2286  this->warn_missing = WHR_NONE;
2287  } else if (min_level < this->filter.min_cat) {
2288  this->warn_missing = this->filter.type_hides ? WHR_CATEGORY_TYPE : WHR_CATEGORY;
2289  } else {
2290  this->warn_missing = this->filter.type_hides ? WHR_TYPE : WHR_NONE;
2291  }
2292  this->vscroll->SetCount(GetSettingsTree().Length() + this->warn_lines);
2293 
2294  if (this->last_clicked != NULL && !GetSettingsTree().IsVisible(this->last_clicked)) {
2295  this->SetDisplayedHelpText(NULL);
2296  }
2297 
2298  bool all_folded = true;
2299  bool all_unfolded = true;
2300  GetSettingsTree().GetFoldingState(all_folded, all_unfolded);
2301  this->SetWidgetDisabledState(WID_GS_EXPAND_ALL, all_unfolded);
2302  this->SetWidgetDisabledState(WID_GS_COLLAPSE_ALL, all_folded);
2303  }
2304 
2305  virtual void OnEditboxChanged(int wid)
2306  {
2307  if (wid == WID_GS_FILTER) {
2308  this->filter.string.SetFilterTerm(this->filter_editbox.text.buf);
2309  if (!this->filter.string.IsEmpty() && !this->manually_changed_folding) {
2310  /* User never expanded/collapsed single pages and entered a filter term.
2311  * Expand everything, to save weird expand clicks, */
2313  }
2314  this->InvalidateData();
2315  }
2316  }
2317 
2318  virtual void OnResize()
2319  {
2320  this->vscroll->SetCapacityFromWidget(this, WID_GS_OPTIONSPANEL, SETTINGTREE_TOP_OFFSET + SETTINGTREE_BOTTOM_OFFSET);
2321  }
2322 };
2323 
2325 
2326 static const NWidgetPart _nested_settings_selection_widgets[] = {
2328  NWidget(WWT_CLOSEBOX, COLOUR_MAUVE),
2329  NWidget(WWT_CAPTION, COLOUR_MAUVE), SetDataTip(STR_CONFIG_SETTING_TREE_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
2330  NWidget(WWT_DEFSIZEBOX, COLOUR_MAUVE),
2331  EndContainer(),
2332  NWidget(WWT_PANEL, COLOUR_MAUVE),
2335  NWidget(WWT_TEXT, COLOUR_MAUVE, WID_GS_RESTRICT_CATEGORY), SetDataTip(STR_CONFIG_SETTING_RESTRICT_CATEGORY, STR_NULL),
2336  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),
2337  EndContainer(),
2339  NWidget(WWT_TEXT, COLOUR_MAUVE, WID_GS_RESTRICT_TYPE), SetDataTip(STR_CONFIG_SETTING_RESTRICT_TYPE, STR_NULL),
2340  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),
2341  EndContainer(),
2342  EndContainer(),
2345  NWidget(WWT_TEXT, COLOUR_MAUVE), SetFill(0, 1), SetDataTip(STR_CONFIG_SETTING_FILTER_TITLE, STR_NULL),
2346  NWidget(WWT_EDITBOX, COLOUR_MAUVE, WID_GS_FILTER), SetFill(1, 0), SetMinimalSize(50, 12), SetResize(1, 0),
2347  SetDataTip(STR_LIST_FILTER_OSKTITLE, STR_LIST_FILTER_TOOLTIP),
2348  EndContainer(),
2349  EndContainer(),
2352  NWidget(NWID_VSCROLLBAR, COLOUR_MAUVE, WID_GS_SCROLLBAR),
2353  EndContainer(),
2354  NWidget(WWT_PANEL, COLOUR_MAUVE), SetMinimalSize(400, 40),
2355  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_GS_HELP_TEXT), SetMinimalSize(300, 25), SetFill(1, 1), SetResize(1, 0),
2357  EndContainer(),
2359  NWidget(WWT_PUSHTXTBTN, COLOUR_MAUVE, WID_GS_EXPAND_ALL), SetDataTip(STR_CONFIG_SETTING_EXPAND_ALL, STR_NULL),
2360  NWidget(WWT_PUSHTXTBTN, COLOUR_MAUVE, WID_GS_COLLAPSE_ALL), SetDataTip(STR_CONFIG_SETTING_COLLAPSE_ALL, STR_NULL),
2361  NWidget(WWT_PANEL, COLOUR_MAUVE), SetFill(1, 0), SetResize(1, 0),
2362  EndContainer(),
2363  NWidget(WWT_RESIZEBOX, COLOUR_MAUVE),
2364  EndContainer(),
2365 };
2366 
2367 static WindowDesc _settings_selection_desc(
2368  WDP_CENTER, "settings", 510, 450,
2370  0,
2371  _nested_settings_selection_widgets, lengthof(_nested_settings_selection_widgets)
2372 );
2373 
2376 {
2378  new GameSettingsWindow(&_settings_selection_desc);
2379 }
2380 
2381 
2391 void DrawArrowButtons(int x, int y, Colours button_colour, byte state, bool clickable_left, bool clickable_right)
2392 {
2393  int colour = _colour_gradient[button_colour][2];
2394  Dimension dim = NWidgetScrollbar::GetHorizontalDimension();
2395 
2396  DrawFrameRect(x, y, x + dim.width - 1, y + dim.height - 1, button_colour, (state == 1) ? FR_LOWERED : FR_NONE);
2397  DrawFrameRect(x + dim.width, y, x + dim.width + dim.width - 1, y + dim.height - 1, button_colour, (state == 2) ? FR_LOWERED : FR_NONE);
2398  DrawSprite(SPR_ARROW_LEFT, PAL_NONE, x + WD_IMGBTN_LEFT, y + WD_IMGBTN_TOP);
2399  DrawSprite(SPR_ARROW_RIGHT, PAL_NONE, x + WD_IMGBTN_LEFT + dim.width, y + WD_IMGBTN_TOP);
2400 
2401  /* Grey out the buttons that aren't clickable */
2402  bool rtl = _current_text_dir == TD_RTL;
2403  if (rtl ? !clickable_right : !clickable_left) {
2404  GfxFillRect(x + 1, y, x + dim.width - 1, y + dim.height - 2, colour, FILLRECT_CHECKER);
2405  }
2406  if (rtl ? !clickable_left : !clickable_right) {
2407  GfxFillRect(x + dim.width + 1, y, x + dim.width + dim.width - 1, y + dim.height - 2, colour, FILLRECT_CHECKER);
2408  }
2409 }
2410 
2419 void DrawDropDownButton(int x, int y, Colours button_colour, bool state, bool clickable)
2420 {
2421  int colour = _colour_gradient[button_colour][2];
2422 
2423  DrawFrameRect(x, y, x + SETTING_BUTTON_WIDTH - 1, y + SETTING_BUTTON_HEIGHT - 1, button_colour, state ? FR_LOWERED : FR_NONE);
2424  DrawSprite(SPR_ARROW_DOWN, PAL_NONE, x + (SETTING_BUTTON_WIDTH - NWidgetScrollbar::GetVerticalDimension().width) / 2 + state, y + 2 + state);
2425 
2426  if (!clickable) {
2427  GfxFillRect(x + 1, y, x + SETTING_BUTTON_WIDTH - 1, y + SETTING_BUTTON_HEIGHT - 2, colour, FILLRECT_CHECKER);
2428  }
2429 }
2430 
2438 void DrawBoolButton(int x, int y, bool state, bool clickable)
2439 {
2440  static const Colours _bool_ctabs[2][2] = {{COLOUR_CREAM, COLOUR_RED}, {COLOUR_DARK_GREEN, COLOUR_GREEN}};
2441  DrawFrameRect(x, y, x + SETTING_BUTTON_WIDTH - 1, y + SETTING_BUTTON_HEIGHT - 1, _bool_ctabs[state][clickable], state ? FR_LOWERED : FR_NONE);
2442 }
2443 
2445  int query_widget;
2446 
2447  CustomCurrencyWindow(WindowDesc *desc) : Window(desc)
2448  {
2449  this->InitNested();
2450 
2451  SetButtonState();
2452  }
2453 
2454  void SetButtonState()
2455  {
2456  this->SetWidgetDisabledState(WID_CC_RATE_DOWN, _custom_currency.rate == 1);
2457  this->SetWidgetDisabledState(WID_CC_RATE_UP, _custom_currency.rate == UINT16_MAX);
2458  this->SetWidgetDisabledState(WID_CC_YEAR_DOWN, _custom_currency.to_euro == CF_NOEURO);
2459  this->SetWidgetDisabledState(WID_CC_YEAR_UP, _custom_currency.to_euro == MAX_YEAR);
2460  }
2461 
2462  virtual void SetStringParameters(int widget) const
2463  {
2464  switch (widget) {
2465  case WID_CC_RATE: SetDParam(0, 1); SetDParam(1, 1); break;
2466  case WID_CC_SEPARATOR: SetDParamStr(0, _custom_currency.separator); break;
2467  case WID_CC_PREFIX: SetDParamStr(0, _custom_currency.prefix); break;
2468  case WID_CC_SUFFIX: SetDParamStr(0, _custom_currency.suffix); break;
2469  case WID_CC_YEAR:
2470  SetDParam(0, (_custom_currency.to_euro != CF_NOEURO) ? STR_CURRENCY_SWITCH_TO_EURO : STR_CURRENCY_SWITCH_TO_EURO_NEVER);
2471  SetDParam(1, _custom_currency.to_euro);
2472  break;
2473 
2474  case WID_CC_PREVIEW:
2475  SetDParam(0, 10000);
2476  break;
2477  }
2478  }
2479 
2480  virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
2481  {
2482  switch (widget) {
2483  /* Set the appropriate width for the edit 'buttons' */
2484  case WID_CC_SEPARATOR_EDIT:
2485  case WID_CC_PREFIX_EDIT:
2486  case WID_CC_SUFFIX_EDIT:
2487  size->width = this->GetWidget<NWidgetBase>(WID_CC_RATE_DOWN)->smallest_x + this->GetWidget<NWidgetBase>(WID_CC_RATE_UP)->smallest_x;
2488  break;
2489 
2490  /* Make sure the window is wide enough for the widest exchange rate */
2491  case WID_CC_RATE:
2492  SetDParam(0, 1);
2493  SetDParam(1, INT32_MAX);
2494  *size = GetStringBoundingBox(STR_CURRENCY_EXCHANGE_RATE);
2495  break;
2496  }
2497  }
2498 
2499  virtual void OnClick(Point pt, int widget, int click_count)
2500  {
2501  int line = 0;
2502  int len = 0;
2503  StringID str = 0;
2504  CharSetFilter afilter = CS_ALPHANUMERAL;
2505 
2506  switch (widget) {
2507  case WID_CC_RATE_DOWN:
2508  if (_custom_currency.rate > 1) _custom_currency.rate--;
2509  if (_custom_currency.rate == 1) this->DisableWidget(WID_CC_RATE_DOWN);
2511  break;
2512 
2513  case WID_CC_RATE_UP:
2514  if (_custom_currency.rate < UINT16_MAX) _custom_currency.rate++;
2515  if (_custom_currency.rate == UINT16_MAX) this->DisableWidget(WID_CC_RATE_UP);
2517  break;
2518 
2519  case WID_CC_RATE:
2520  SetDParam(0, _custom_currency.rate);
2521  str = STR_JUST_INT;
2522  len = 5;
2523  line = WID_CC_RATE;
2524  afilter = CS_NUMERAL;
2525  break;
2526 
2527  case WID_CC_SEPARATOR_EDIT:
2528  case WID_CC_SEPARATOR:
2529  SetDParamStr(0, _custom_currency.separator);
2530  str = STR_JUST_RAW_STRING;
2531  len = 1;
2532  line = WID_CC_SEPARATOR;
2533  break;
2534 
2535  case WID_CC_PREFIX_EDIT:
2536  case WID_CC_PREFIX:
2537  SetDParamStr(0, _custom_currency.prefix);
2538  str = STR_JUST_RAW_STRING;
2539  len = 12;
2540  line = WID_CC_PREFIX;
2541  break;
2542 
2543  case WID_CC_SUFFIX_EDIT:
2544  case WID_CC_SUFFIX:
2545  SetDParamStr(0, _custom_currency.suffix);
2546  str = STR_JUST_RAW_STRING;
2547  len = 12;
2548  line = WID_CC_SUFFIX;
2549  break;
2550 
2551  case WID_CC_YEAR_DOWN:
2552  _custom_currency.to_euro = (_custom_currency.to_euro <= 2000) ? CF_NOEURO : _custom_currency.to_euro - 1;
2553  if (_custom_currency.to_euro == CF_NOEURO) this->DisableWidget(WID_CC_YEAR_DOWN);
2555  break;
2556 
2557  case WID_CC_YEAR_UP:
2558  _custom_currency.to_euro = Clamp(_custom_currency.to_euro + 1, 2000, MAX_YEAR);
2559  if (_custom_currency.to_euro == MAX_YEAR) this->DisableWidget(WID_CC_YEAR_UP);
2561  break;
2562 
2563  case WID_CC_YEAR:
2564  SetDParam(0, _custom_currency.to_euro);
2565  str = STR_JUST_INT;
2566  len = 7;
2567  line = WID_CC_YEAR;
2568  afilter = CS_NUMERAL;
2569  break;
2570  }
2571 
2572  if (len != 0) {
2573  this->query_widget = line;
2574  ShowQueryString(str, STR_CURRENCY_CHANGE_PARAMETER, len + 1, this, afilter, QSF_NONE);
2575  }
2576 
2577  this->SetTimeout();
2578  this->SetDirty();
2579  }
2580 
2581  virtual void OnQueryTextFinished(char *str)
2582  {
2583  if (str == NULL) return;
2584 
2585  switch (this->query_widget) {
2586  case WID_CC_RATE:
2587  _custom_currency.rate = Clamp(atoi(str), 1, UINT16_MAX);
2588  break;
2589 
2590  case WID_CC_SEPARATOR: // Thousands separator
2591  strecpy(_custom_currency.separator, str, lastof(_custom_currency.separator));
2592  break;
2593 
2594  case WID_CC_PREFIX:
2595  strecpy(_custom_currency.prefix, str, lastof(_custom_currency.prefix));
2596  break;
2597 
2598  case WID_CC_SUFFIX:
2599  strecpy(_custom_currency.suffix, str, lastof(_custom_currency.suffix));
2600  break;
2601 
2602  case WID_CC_YEAR: { // Year to switch to euro
2603  int val = atoi(str);
2604 
2605  _custom_currency.to_euro = (val < 2000 ? CF_NOEURO : min(val, MAX_YEAR));
2606  break;
2607  }
2608  }
2610  SetButtonState();
2611  }
2612 
2613  virtual void OnTimeout()
2614  {
2615  this->SetDirty();
2616  }
2617 };
2618 
2619 static const NWidgetPart _nested_cust_currency_widgets[] = {
2621  NWidget(WWT_CLOSEBOX, COLOUR_GREY),
2622  NWidget(WWT_CAPTION, COLOUR_GREY), SetDataTip(STR_CURRENCY_WINDOW, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
2623  EndContainer(),
2624  NWidget(WWT_PANEL, COLOUR_GREY),
2626  NWidget(NWID_HORIZONTAL), SetPIP(10, 0, 5),
2627  NWidget(WWT_PUSHARROWBTN, COLOUR_YELLOW, WID_CC_RATE_DOWN), SetDataTip(AWV_DECREASE, STR_CURRENCY_DECREASE_EXCHANGE_RATE_TOOLTIP),
2628  NWidget(WWT_PUSHARROWBTN, COLOUR_YELLOW, WID_CC_RATE_UP), SetDataTip(AWV_INCREASE, STR_CURRENCY_INCREASE_EXCHANGE_RATE_TOOLTIP),
2630  NWidget(WWT_TEXT, COLOUR_BLUE, WID_CC_RATE), SetDataTip(STR_CURRENCY_EXCHANGE_RATE, STR_CURRENCY_SET_EXCHANGE_RATE_TOOLTIP), SetFill(1, 0),
2631  EndContainer(),
2632  NWidget(NWID_HORIZONTAL), SetPIP(10, 0, 5),
2633  NWidget(WWT_PUSHBTN, COLOUR_DARK_BLUE, WID_CC_SEPARATOR_EDIT), SetDataTip(0x0, STR_CURRENCY_SET_CUSTOM_CURRENCY_SEPARATOR_TOOLTIP), SetFill(0, 1),
2635  NWidget(WWT_TEXT, COLOUR_BLUE, WID_CC_SEPARATOR), SetDataTip(STR_CURRENCY_SEPARATOR, STR_CURRENCY_SET_CUSTOM_CURRENCY_SEPARATOR_TOOLTIP), SetFill(1, 0),
2636  EndContainer(),
2637  NWidget(NWID_HORIZONTAL), SetPIP(10, 0, 5),
2638  NWidget(WWT_PUSHBTN, COLOUR_DARK_BLUE, WID_CC_PREFIX_EDIT), SetDataTip(0x0, STR_CURRENCY_SET_CUSTOM_CURRENCY_PREFIX_TOOLTIP), SetFill(0, 1),
2640  NWidget(WWT_TEXT, COLOUR_BLUE, WID_CC_PREFIX), SetDataTip(STR_CURRENCY_PREFIX, STR_CURRENCY_SET_CUSTOM_CURRENCY_PREFIX_TOOLTIP), SetFill(1, 0),
2641  EndContainer(),
2642  NWidget(NWID_HORIZONTAL), SetPIP(10, 0, 5),
2643  NWidget(WWT_PUSHBTN, COLOUR_DARK_BLUE, WID_CC_SUFFIX_EDIT), SetDataTip(0x0, STR_CURRENCY_SET_CUSTOM_CURRENCY_SUFFIX_TOOLTIP), SetFill(0, 1),
2645  NWidget(WWT_TEXT, COLOUR_BLUE, WID_CC_SUFFIX), SetDataTip(STR_CURRENCY_SUFFIX, STR_CURRENCY_SET_CUSTOM_CURRENCY_SUFFIX_TOOLTIP), SetFill(1, 0),
2646  EndContainer(),
2647  NWidget(NWID_HORIZONTAL), SetPIP(10, 0, 5),
2648  NWidget(WWT_PUSHARROWBTN, COLOUR_YELLOW, WID_CC_YEAR_DOWN), SetDataTip(AWV_DECREASE, STR_CURRENCY_DECREASE_CUSTOM_CURRENCY_TO_EURO_TOOLTIP),
2649  NWidget(WWT_PUSHARROWBTN, COLOUR_YELLOW, WID_CC_YEAR_UP), SetDataTip(AWV_INCREASE, STR_CURRENCY_INCREASE_CUSTOM_CURRENCY_TO_EURO_TOOLTIP),
2651  NWidget(WWT_TEXT, COLOUR_BLUE, WID_CC_YEAR), SetDataTip(STR_JUST_STRING, STR_CURRENCY_SET_CUSTOM_CURRENCY_TO_EURO_TOOLTIP), SetFill(1, 0),
2652  EndContainer(),
2653  EndContainer(),
2654  NWidget(WWT_LABEL, COLOUR_BLUE, WID_CC_PREVIEW),
2655  SetDataTip(STR_CURRENCY_PREVIEW, STR_CURRENCY_CUSTOM_CURRENCY_PREVIEW_TOOLTIP), SetPadding(15, 1, 18, 2),
2656  EndContainer(),
2657 };
2658 
2659 static WindowDesc _cust_currency_desc(
2660  WDP_CENTER, NULL, 0, 0,
2662  0,
2663  _nested_cust_currency_widgets, lengthof(_nested_cust_currency_widgets)
2664 );
2665 
2667 static void ShowCustCurrency()
2668 {
2670  new CustomCurrencyWindow(&_cust_currency_desc);
2671 }
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
Dropdown for the GUI zoom level.
virtual void OnTimeout()
Called when this window&#39;s timeout has been reached.
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:2089
bool _networking
are we in networking mode?
Definition: network.cpp:56
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:99
ResizeInfo resize
Resize information.
Definition: window_gui.h:317
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:1843
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:387
void SetWindowDirty(WindowClass cls, WindowNumber number)
Mark window as dirty (in need of repainting)
Definition: window.cpp:3120
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:448
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:361
Current suffix.
this setting can be different for each company (saved in company struct)
High level window description.
Definition: window_gui.h:168
Custom currency.
Definition: currency.h:58
WindowFlags flags
Window flags.
Definition: window_gui.h:305
int left
x position of left edge of the window
Definition: window_gui.h:312
All settings together for the game.
void DrawWidgets() const
Paint all widgets of a window.
Definition: widget.cpp:604
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.
virtual void OnClick(Point pt, int widget, int click_count)
A click with the left mouse button has been made on the window.
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:68
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
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:53
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
virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
Update size and resize step of a widget in the window.
Info about missing files etc.
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:1065
Use to select a base music set.
Generic functions for replacing base data (graphics, sounds).
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:50
Current separator.
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.
the number represents money, so when reading value multiply by exchange rate
DropDownList * BuildDropDownList(int widget, int *selected_index) const
Build the dropdown list for a specific widget.
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.
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:313
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:946
const T * Begin() const
Get the pointer to the first item (const)
virtual void OnDropdownClose(Point pt, int widget, int index, bool instant_close)
A dropdown window associated to this window has been closed.
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.
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:49
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.
int _num_resolutions
The number of resolutions.
Definition: driver.cpp:22
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
ZoomLevelByte _gui_zoom
GUI Zoom level.
Definition: gfx.cpp:60
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.
virtual void OnInvalidateData(int data=0, bool gui_scope=true)
Some data on this window has become invalid.
const SettingDesc * setting
Setting description of the setting.
void DisableWidget(byte widget_index)
Sets a widget to disabled.
Definition: window_gui.h:397
#define CLRBITS(x, y)
Clears several bits in a variable.
Town name dropdown.
NewGRF readme.
Definition: textfile_type.h:19
virtual void OnClick(Point pt, int widget, int click_count)
A click with the left mouse button has been made on the window.
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.
the value represents a limited number of string-options (internally integer)
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.
const T * End() const
Get the pointer behind the last valid item (const)
void CreateNestedTree(bool fill_nested=true)
Perform the first part of the initialization of a nested widget tree.
Definition: window.cpp:1804
Pure simple text.
Definition: widget_type.h:58
virtual void Init(byte level=0)
Initialization of an entire setting page.
Background of the window.
any number-type
virtual void OnQueryTextFinished(char *str)
The query window opened from this window has closed.
static const int LEVEL_WIDTH
Indenting width of a sub-page in pixels.
bool _left_button_clicked
Is left mouse button clicked?
Definition: gfx.cpp:40
void DrawFrameRect(int left, int top, int right, int bottom, Colours colour, FrameFlags flags)
Draw frame rectangle.
Definition: widget.cpp:177
T * Append(uint to_add=1)
Append an item and return it.
void SetCount(int num)
Sets the number of elements in the list.
Definition: widget_type.h:670
CompanyByte _local_company
Company controlled by the human player at this client. Can also be COMPANY_SPECTATOR.
Definition: company_cmd.cpp:46
Partial widget specification to allow NWidgets to be written nested.
Definition: widget_type.h:910
Functions related to (drawing on) viewports.
static int GetCurRes()
Get index of the current screen resolution.
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:271
void FinishInitNested(WindowNumber window_number=0)
Perform the second part of the initialization of a nested widget tree.
Definition: window.cpp:1820
void SetFilterTerm(const char *str)
Set the term to filter on.
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:1833
SettingEntry * last_clicked
If non-NULL, pointer to the last clicked setting.
void ShowErrorMessage(StringID summary_msg, StringID detailed_msg, WarningLevel wl, int x=0, int y=0, const GRFFile *textref_stack_grffile=NULL, uint textref_stack_size=0, const uint32 *textref_stack=NULL)
Display an error message in a window.
Definition: error_gui.cpp:378
Bottom offset of the text of the frame.
Definition: window_gui.h:75
SaveLoad save
Internal structure (going to savegame, parts to config)
virtual void OnClick(Point pt, int widget, int click_count)
A click with the left mouse button has been made on the window.
void SetDParamStr(uint n, const char *str)
This function is used to "bind" a C string to a OpenTTD dparam slot.
Definition: strings.cpp:279
enable the &#39;Default&#39; button ("\0" is returned)
Definition: textbuf_gui.h:23
bool ReadLanguagePack(const LanguageMetadata *lang)
Read a particular language.
Definition: strings.cpp:1716
Functions related to low-level strings.
Zoomed 4 times out.
Definition: zoom_type.h:26
bool type_hides
Whether the type hides filtered strings.
Only numeric ones.
Definition: string_type.h:28
Invisible widget that takes some space.
Definition: widget_type.h: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:211
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
uint Length() const
Get the number of items in the list.
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
display absolute value of the setting
uint pos_y
Vertical position of top-left corner of the widget in the window.
Definition: widget_type.h:178
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:909
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:323
void UpdateAllVirtCoords()
Update the viewport coordinates of all signs.
Definition: afterload.cpp:220
const char * name
Name of the setting.
#define FONT_HEIGHT_NORMAL
Height of characters in the normal (FS_NORMAL) font.
Definition: gfx_func.h:180
static NWidgetPart SetDataTip(uint32 data, StringID tip)
Widget part function for setting the data and tooltip.
Definition: widget_type.h:1014
Simple vector template class, with automatic delete.
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:76
static NWidgetPart SetMinimalSize(int16 x, int16 y)
Widget part function for setting the minimal size.
Definition: widget_type.h:947
virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
Update size and resize step of a widget in the window.
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
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:78
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.
virtual void OnQueryTextFinished(char *str)
The query window opened from this window has closed.
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:2048
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:163
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:307
char * stredup(const char *s, const char *last)
Create a duplicate of the given string.
Definition: string.cpp:126
Window for displaying the textfile of a BaseSet.
virtual void OnDropdownSelect(int widget, int index)
A dropdown option associated to this window has been selected.
Display settings associated to the "advanced" list.
virtual BaseSettingEntry * FindEntry(uint row, uint *cur_row)
Find setting entry at row row_num.
virtual void DrawWidget(const Rect &r, int widget) const
Draw the contents of a nested widget.
Collapse all button.
Frame.
Definition: widget_type.h:60
Description of selected base GRF.
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.
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:47
virtual void OnInvalidateData(int data=0, bool gui_scope=true)
Some data on this window has become invalid.
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:61
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
uint pos_x
Horizontal position of top-left corner of the widget in the window.
Definition: widget_type.h:177
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.
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 DeleteWindowByClass(WindowClass cls)
Delete all windows of a given class.
Definition: window.cpp:1150
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:18
CharSetFilter
Valid filter types for IsValidChar.
Definition: string_type.h:26
This entry is the last one in a (sub-)page.
void SetCompanySetting(uint index, int32 value)
Top function to save the new value of an element of the Settings struct.
Definition: settings.cpp:1960
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:959
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.
Dimension _resolutions[32]
List of resolutions.
Definition: driver.cpp:23
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:699
SettingEntry * valuedropdown_entry
If non-NULL, 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:1137
bool IsEditable(bool do_command=false) const
Check whether the setting is editable in the current gamemode.
Definition: settings.cpp:765
ZoomLevelByte zoom_min
minimum zoom out level
void InitGRFTownGeneratorNames()
Allocate memory for the NewGRF town names.
EntryVector entries
Settings on this page.
static void * GetVariableAddress(const void *object, const SaveLoad *sld)
Get the address of the variable.
Definition: saveload.h:525
StringID str_val
(Translated) first string describing the value.
ZoomLevel
All zoom levels we know.
Definition: zoom_type.h:21
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:1992
Open base GRF readme, changelog (+1) or license (+2).
void ReInitAllWindows()
Re-initialize all windows.
Definition: window.cpp:3344
Use to select a base GRF.
Description of selected base SFX.
Both numeric and alphabetic and spaces and stuff.
Definition: string_type.h:27
Category setting filtered matches away.
Declaration of functions and types defined in highscore.h and highscore_gui.h.
GUISettings gui
settings related to the GUI
Bit-mask for button flags.
Window caption (window title between closebox and stickybox)
Definition: widget_type.h: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
a value of zero means the feature is disabled
void UpdateCursorSize()
Update cursor dimension.
Definition: gfx.cpp:1530
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
TextDirection _current_text_dir
Text direction of the currently selected language.
Definition: strings.cpp:52
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
bitmasked number where only ONE bit may be set
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:1919
void ShowGameOptions()
Open the game options window.
virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
Update size and resize step of a widget in the 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
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
uint current_x
Current horizontal size (after resizing).
Definition: widget_type.h:174
virtual void SetStringParameters(int widget) const
Initialize string parameters for a widget.
virtual void OnResize()
Called after the window got resized.
virtual void SetStringParameters(int widget) const
Initialize string parameters for a widget.
bool SetFocusedWidget(int widget_index)
Set focus within this window to the given widget.
Definition: window.cpp:484
Up button.
SwitchMode _switch_mode
The next mainloop command.
Definition: gfx.cpp:47
void DrawDropDownButton(int x, int y, Colours button_colour, bool state, bool clickable)
Draw a dropdown button.
SettingType GetType() const
Return the type of the setting.
Definition: settings.cpp:780
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:57
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:768
List item containing a C char string.
Definition: dropdown_type.h:73
static bool IsValidID(size_t index)
Tests whether given index can be used to get valid (non-NULL) 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)
virtual void OnEditboxChanged(int wid)
The text in an editbox has been edited.
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-NULL, pointer to a clicked numeric setting (with a depressed left or right button)...
StringID str
(translated) string with descriptive text; gui and console
virtual void SetStringParameters(int widget) const
Initialize string parameters for a widget.
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
Company setting.
int32 min
minimum values
static void free(const void *ptr)
Version of the standard free that accepts const pointers.
Definition: depend.cpp:114
uint64 GetMaskOfAllowedCurrencies()
get a mask of the allowed currencies depending on the year
Definition: currency.cpp:116
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:314
The caption of the window.
Definition: misc_widget.h:50
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.
Base of the town class.
static void ShowCustCurrency()
Open custom currency window.
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-NULL, pointer to setting for which a value-entering window has been opened.
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.
#define DECLARE_POSTFIX_INCREMENT(type)
Some enums need to have allowed incrementing (i.e.
Definition: enum_type.hpp:16
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:280
Nothing was filtering matches away.
virtual void OnDropdownSelect(int widget, int index)
A dropdown option associated to this window has been selected.
virtual void DrawWidget(const Rect &r, int widget) const
Draw the contents of a nested widget.
void SetStringParameters(int widget) const
Initialize string parameters for a widget.
Use to select a base SFX.
#define SETTING_BUTTON_HEIGHT
Height of setting buttons.
Definition: settings_gui.h:20
uint8 timeout_timer
Timer value of the WF_TIMEOUT for flags.
Definition: window_gui.h:309
Errors (eg. saving/loading failed)
Definition: error.h:25
void GetFoldingState(bool &all_folded, bool &all_unfolded) const
Recursively accumulate the folding state of the tree.
static void QSortT(T *base, uint num, int(CDECL *comparator)(const T *, const T *), bool desc=false)
Type safe qsort()
Definition: sort_func.hpp:28
BaseSettingEntry * FindEntry(uint row, uint *cur_row)
Find the setting entry at row number row_num.
Info about corrupted files etc.
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
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:833
static NWidgetPart SetPIP(uint8 pre, uint8 inter, uint8 post)
Widget part function for setting a pre/inter/post spaces.
Definition: widget_type.h:1076
virtual void OnPaint()
The window must be repainted.
Description of selected base music set.
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:3161
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:315
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:406
void MarkWholeScreenDirty()
This function mark the whole screen as dirty.
Definition: gfx.cpp:1461
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:728
(Toggle) Button with text
Definition: widget_type.h:55
List all settings regardless of the default/newgame/... values.
virtual void OnTimeout()
Called when this window&#39;s timeout has been reached.
a boolean number
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
static int CDECL NatSortFunc(const DropDownListItem *const *first, const DropDownListItem *const *second)
Natural sorting comparator function for DropDownList::sort().
Definition: dropdown.cpp:53