OpenTTD
settings_gui.cpp
Go to the documentation of this file.
1 /* $Id$ */
2 
3 /*
4  * This file is part of OpenTTD.
5  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
6  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
8  */
9 
12 #include "stdafx.h"
13 #include "currency.h"
14 #include "error.h"
15 #include "settings_gui.h"
16 #include "textbuf_gui.h"
17 #include "command_func.h"
18 #include "network/network.h"
19 #include "town.h"
20 #include "settings_internal.h"
21 #include "newgrf_townname.h"
22 #include "strings_func.h"
23 #include "window_func.h"
24 #include "string_func.h"
25 #include "widgets/dropdown_type.h"
26 #include "widgets/dropdown_func.h"
27 #include "highscore.h"
28 #include "base_media_base.h"
29 #include "company_base.h"
30 #include "company_func.h"
31 #include "viewport_func.h"
32 #include "core/geometry_func.hpp"
33 #include "ai/ai.hpp"
34 #include "blitter/factory.hpp"
35 #include "language.h"
36 #include "textfile_gui.h"
37 #include "stringfilter_type.h"
38 #include "querystring_gui.h"
39 
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 *BuildSetDropDownList(int *selected_index, bool allow_selection)
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, !allow_selection && (*selected_index != i));
125  }
126 
127  return list;
128 }
129 
130 DropDownList *BuildMusicSetDropDownList(int *selected_index)
131 {
132  return BuildSetDropDownList<BaseMusic>(selected_index, true);
133 }
134 
136 template <class TBaseSet>
138  const TBaseSet* baseset;
140 
141  BaseSetTextfileWindow(TextfileType file_type, const TBaseSet* baseset, StringID content_type) : TextfileWindow(file_type), baseset(baseset), content_type(content_type)
142  {
143  const char *textfile = this->baseset->GetTextfile(file_type);
144  this->LoadTextfile(textfile, BASESET_DIR);
145  }
146 
147  /* virtual */ void SetStringParameters(int widget) const
148  {
149  if (widget == WID_TF_CAPTION) {
150  SetDParam(0, content_type);
151  SetDParamStr(1, this->baseset->name);
152  }
153  }
154 };
155 
162 template <class TBaseSet>
164 {
165  DeleteWindowById(WC_TEXTFILE, file_type);
167 }
168 
170  GameSettings *opt;
171  bool reload;
172 
173  GameOptionsWindow(WindowDesc *desc) : Window(desc)
174  {
175  this->opt = &GetGameSettings();
176  this->reload = false;
177 
179  this->OnInvalidateData(0);
180  }
181 
183  {
186  if (this->reload) _switch_mode = SM_MENU;
187  }
188 
195  DropDownList *BuildDropDownList(int widget, int *selected_index) const
196  {
197  DropDownList *list = NULL;
198  switch (widget) {
199  case WID_GO_CURRENCY_DROPDOWN: { // Setup currencies dropdown
200  list = new DropDownList();
201  *selected_index = this->opt->locale.currency;
202  StringID *items = BuildCurrencyDropdown();
203  uint64 disabled = _game_mode == GM_MENU ? 0LL : ~GetMaskOfAllowedCurrencies();
204 
205  /* Add non-custom currencies; sorted naturally */
206  for (uint i = 0; i < CURRENCY_END; items++, i++) {
207  if (i == CURRENCY_CUSTOM) continue;
208  *list->Append() = new DropDownListStringItem(*items, i, HasBit(disabled, i));
209  }
211 
212  /* Append custom currency at the end */
213  *list->Append() = new DropDownListItem(-1, false); // separator line
214  *list->Append() = new DropDownListStringItem(STR_GAME_OPTIONS_CURRENCY_CUSTOM, CURRENCY_CUSTOM, HasBit(disabled, CURRENCY_CUSTOM));
215  break;
216  }
217 
218  case WID_GO_ROADSIDE_DROPDOWN: { // Setup road-side dropdown
219  list = new DropDownList();
220  *selected_index = this->opt->vehicle.road_side;
221  const StringID *items = _driveside_dropdown;
222  uint disabled = 0;
223 
224  /* You can only change the drive side if you are in the menu or ingame with
225  * no vehicles present. In a networking game only the server can change it */
226  extern bool RoadVehiclesAreBuilt();
227  if ((_game_mode != GM_MENU && RoadVehiclesAreBuilt()) || (_networking && !_network_server)) {
228  disabled = ~(1 << this->opt->vehicle.road_side); // disable the other value
229  }
230 
231  for (uint i = 0; *items != INVALID_STRING_ID; items++, i++) {
232  *list->Append() = new DropDownListStringItem(*items, i, HasBit(disabled, i));
233  }
234  break;
235  }
236 
237  case WID_GO_TOWNNAME_DROPDOWN: { // Setup townname dropdown
238  list = new DropDownList();
239  *selected_index = this->opt->game_creation.town_name;
240 
241  int enabled_item = (_game_mode == GM_MENU || Town::GetNumItems() == 0) ? -1 : *selected_index;
242 
243  /* Add and sort newgrf townnames generators */
244  for (int i = 0; i < _nb_grf_names; i++) {
245  int result = _nb_orig_names + i;
246  *list->Append() = new DropDownListStringItem(_grf_names[i], result, enabled_item != result && enabled_item >= 0);
247  }
249 
250  int newgrf_size = list->Length();
251  /* Insert newgrf_names at the top of the list */
252  if (newgrf_size > 0) {
253  *list->Append() = new DropDownListItem(-1, false); // separator line
254  newgrf_size++;
255  }
256 
257  /* Add and sort original townnames generators */
258  for (int i = 0; i < _nb_orig_names; i++) {
259  *list->Append() = new DropDownListStringItem(STR_GAME_OPTIONS_TOWN_NAME_ORIGINAL_ENGLISH + i, i, enabled_item != i && enabled_item >= 0);
260  }
261  QSortT(list->Begin() + newgrf_size, list->Length() - newgrf_size, DropDownListStringItem::NatSortFunc);
262  break;
263  }
264 
265  case WID_GO_AUTOSAVE_DROPDOWN: { // Setup autosave dropdown
266  list = new DropDownList();
267  *selected_index = _settings_client.gui.autosave;
268  const StringID *items = _autosave_dropdown;
269  for (uint i = 0; *items != INVALID_STRING_ID; items++, i++) {
270  *list->Append() = new DropDownListStringItem(*items, i, false);
271  }
272  break;
273  }
274 
275  case WID_GO_LANG_DROPDOWN: { // Setup interface language dropdown
276  list = new DropDownList();
277  for (uint i = 0; i < _languages.Length(); i++) {
278  if (&_languages[i] == _current_language) *selected_index = i;
279  *list->Append() = new DropDownListStringItem(SPECSTR_LANGUAGE_START + i, i, false);
280  }
282  break;
283  }
284 
285  case WID_GO_RESOLUTION_DROPDOWN: // Setup resolution dropdown
286  if (_num_resolutions == 0) break;
287 
288  list = new DropDownList();
289  *selected_index = GetCurRes();
290  for (int i = 0; i < _num_resolutions; i++) {
291  *list->Append() = new DropDownListStringItem(SPECSTR_RESOLUTION_START + i, i, false);
292  }
293  break;
294 
296  list = new DropDownList();
297  *selected_index = ZOOM_LVL_OUT_4X - _gui_zoom;
298  const StringID *items = _gui_zoom_dropdown;
299  for (int i = 0; *items != INVALID_STRING_ID; items++, i++) {
301  }
302  break;
303  }
304 
306  list = BuildSetDropDownList<BaseGraphics>(selected_index, (_game_mode == GM_MENU));
307  break;
308 
310  list = BuildSetDropDownList<BaseSounds>(selected_index, (_game_mode == GM_MENU));
311  break;
312 
314  list = BuildMusicSetDropDownList(selected_index);
315  break;
316 
317  default:
318  return NULL;
319  }
320 
321  return list;
322  }
323 
324  virtual void SetStringParameters(int widget) const
325  {
326  switch (widget) {
327  case WID_GO_CURRENCY_DROPDOWN: SetDParam(0, _currency_specs[this->opt->locale.currency].name); break;
328  case WID_GO_ROADSIDE_DROPDOWN: SetDParam(0, STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_LEFT + this->opt->vehicle.road_side); break;
330  case WID_GO_AUTOSAVE_DROPDOWN: SetDParam(0, _autosave_dropdown[_settings_client.gui.autosave]); break;
332  case WID_GO_RESOLUTION_DROPDOWN: SetDParam(0, GetCurRes() == _num_resolutions ? STR_GAME_OPTIONS_RESOLUTION_OTHER : SPECSTR_RESOLUTION_START + GetCurRes()); break;
333  case WID_GO_GUI_ZOOM_DROPDOWN: SetDParam(0, _gui_zoom_dropdown[ZOOM_LVL_OUT_4X - _gui_zoom]); break;
335  case WID_GO_BASE_GRF_STATUS: SetDParam(0, BaseGraphics::GetUsedSet()->GetNumInvalid()); break;
338  case WID_GO_BASE_MUSIC_STATUS: SetDParam(0, BaseMusic::GetUsedSet()->GetNumInvalid()); break;
339  }
340  }
341 
342  virtual void DrawWidget(const Rect &r, int widget) const
343  {
344  switch (widget) {
347  DrawStringMultiLine(r.left, r.right, r.top, UINT16_MAX, STR_BLACK_RAW_STRING);
348  break;
349 
352  DrawStringMultiLine(r.left, r.right, r.top, UINT16_MAX, STR_BLACK_RAW_STRING);
353  break;
354 
357  DrawStringMultiLine(r.left, r.right, r.top, UINT16_MAX, STR_BLACK_RAW_STRING);
358  break;
359  }
360  }
361 
362  virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
363  {
364  switch (widget) {
366  /* Find the biggest description for the default size. */
367  for (int i = 0; i < BaseGraphics::GetNumSets(); i++) {
369  size->height = max(size->height, (uint)GetStringHeight(STR_BLACK_RAW_STRING, size->width));
370  }
371  break;
372 
374  /* Find the biggest description for the default size. */
375  for (int i = 0; i < BaseGraphics::GetNumSets(); i++) {
376  uint invalid_files = BaseGraphics::GetSet(i)->GetNumInvalid();
377  if (invalid_files == 0) continue;
378 
379  SetDParam(0, invalid_files);
380  *size = maxdim(*size, GetStringBoundingBox(STR_GAME_OPTIONS_BASE_GRF_STATUS));
381  }
382  break;
383 
385  /* Find the biggest description for the default size. */
386  for (int i = 0; i < BaseSounds::GetNumSets(); i++) {
388  size->height = max(size->height, (uint)GetStringHeight(STR_BLACK_RAW_STRING, size->width));
389  }
390  break;
391 
393  /* Find the biggest description for the default size. */
394  for (int i = 0; i < BaseMusic::GetNumSets(); i++) {
395  SetDParamStr(0, BaseMusic::GetSet(i)->GetDescription(GetCurrentLanguageIsoCode()));
396  size->height = max(size->height, (uint)GetStringHeight(STR_BLACK_RAW_STRING, size->width));
397  }
398  break;
399 
401  /* Find the biggest description for the default size. */
402  for (int i = 0; i < BaseMusic::GetNumSets(); i++) {
403  uint invalid_files = BaseMusic::GetSet(i)->GetNumInvalid();
404  if (invalid_files == 0) continue;
405 
406  SetDParam(0, invalid_files);
407  *size = maxdim(*size, GetStringBoundingBox(STR_GAME_OPTIONS_BASE_MUSIC_STATUS));
408  }
409  break;
410 
411  default: {
412  int selected;
413  DropDownList *list = this->BuildDropDownList(widget, &selected);
414  if (list != NULL) {
415  /* Find the biggest item for the default size. */
416  for (const DropDownListItem * const *it = list->Begin(); it != list->End(); it++) {
417  Dimension string_dim;
418  int width = (*it)->Width();
419  string_dim.width = width + padding.width;
420  string_dim.height = (*it)->Height(width) + padding.height;
421  *size = maxdim(*size, string_dim);
422  }
423  delete list;
424  }
425  }
426  }
427  }
428 
429  virtual void OnClick(Point pt, int widget, int click_count)
430  {
431  if (widget >= WID_GO_BASE_GRF_TEXTFILE && widget < WID_GO_BASE_GRF_TEXTFILE + TFT_END) {
432  if (BaseGraphics::GetUsedSet() == NULL) return;
433 
434  ShowBaseSetTextfileWindow((TextfileType)(widget - WID_GO_BASE_GRF_TEXTFILE), BaseGraphics::GetUsedSet(), STR_CONTENT_TYPE_BASE_GRAPHICS);
435  return;
436  }
437  if (widget >= WID_GO_BASE_SFX_TEXTFILE && widget < WID_GO_BASE_SFX_TEXTFILE + TFT_END) {
438  if (BaseSounds::GetUsedSet() == NULL) return;
439 
440  ShowBaseSetTextfileWindow((TextfileType)(widget - WID_GO_BASE_SFX_TEXTFILE), BaseSounds::GetUsedSet(), STR_CONTENT_TYPE_BASE_SOUNDS);
441  return;
442  }
443  if (widget >= WID_GO_BASE_MUSIC_TEXTFILE && widget < WID_GO_BASE_MUSIC_TEXTFILE + TFT_END) {
444  if (BaseMusic::GetUsedSet() == NULL) return;
445 
446  ShowBaseSetTextfileWindow((TextfileType)(widget - WID_GO_BASE_MUSIC_TEXTFILE), BaseMusic::GetUsedSet(), STR_CONTENT_TYPE_BASE_MUSIC);
447  return;
448  }
449  switch (widget) {
450  case WID_GO_FULLSCREEN_BUTTON: // Click fullscreen on/off
451  /* try to toggle full-screen on/off */
452  if (!ToggleFullScreen(!_fullscreen)) {
453  ShowErrorMessage(STR_ERROR_FULLSCREEN_FAILED, INVALID_STRING_ID, WL_ERROR);
454  }
456  this->SetDirty();
457  break;
458 
459  default: {
460  int selected;
461  DropDownList *list = this->BuildDropDownList(widget, &selected);
462  if (list != NULL) {
463  ShowDropDownList(this, list, selected, widget);
464  } else {
465  if (widget == WID_GO_RESOLUTION_DROPDOWN) ShowErrorMessage(STR_ERROR_RESOLUTION_LIST_FAILED, INVALID_STRING_ID, WL_ERROR);
466  }
467  break;
468  }
469  }
470  }
471 
477  template <class T>
478  void SetMediaSet(int index)
479  {
480  if (_game_mode == GM_MENU) {
481  const char *name = T::GetSet(index)->name;
482 
483  free(T::ini_set);
484  T::ini_set = stredup(name);
485 
486  T::SetSet(name);
487  this->reload = true;
488  this->InvalidateData();
489  }
490  }
491 
492  virtual void OnDropdownSelect(int widget, int index)
493  {
494  switch (widget) {
495  case WID_GO_CURRENCY_DROPDOWN: // Currency
496  if (index == CURRENCY_CUSTOM) ShowCustCurrency();
497  this->opt->locale.currency = index;
499  break;
500 
501  case WID_GO_ROADSIDE_DROPDOWN: // Road side
502  if (this->opt->vehicle.road_side != index) { // only change if setting changed
503  uint i;
504  if (GetSettingFromName("vehicle.road_side", &i) == NULL) NOT_REACHED();
505  SetSettingValue(i, index);
507  }
508  break;
509 
510  case WID_GO_TOWNNAME_DROPDOWN: // Town names
511  if (_game_mode == GM_MENU || Town::GetNumItems() == 0) {
512  this->opt->game_creation.town_name = index;
514  }
515  break;
516 
517  case WID_GO_AUTOSAVE_DROPDOWN: // Autosave options
518  _settings_client.gui.autosave = index;
519  this->SetDirty();
520  break;
521 
522  case WID_GO_LANG_DROPDOWN: // Change interface language
523  ReadLanguagePack(&_languages[index]);
528  break;
529 
530  case WID_GO_RESOLUTION_DROPDOWN: // Change resolution
531  if (index < _num_resolutions && ChangeResInGame(_resolutions[index].width, _resolutions[index].height)) {
532  this->SetDirty();
533  }
534  break;
535 
538  _gui_zoom = (ZoomLevel)(ZOOM_LVL_OUT_4X - index);
542  break;
543 
545  this->SetMediaSet<BaseGraphics>(index);
546  break;
547 
549  this->SetMediaSet<BaseSounds>(index);
550  break;
551 
553  ChangeMusicSet(index);
554  break;
555  }
556  }
557 
563  virtual void OnInvalidateData(int data = 0, bool gui_scope = true)
564  {
565  if (!gui_scope) return;
567 
568  bool missing_files = BaseGraphics::GetUsedSet()->GetNumMissing() == 0;
569  this->GetWidget<NWidgetCore>(WID_GO_BASE_GRF_STATUS)->SetDataTip(missing_files ? STR_EMPTY : STR_GAME_OPTIONS_BASE_GRF_STATUS, STR_NULL);
570 
571  for (TextfileType tft = TFT_BEGIN; tft < TFT_END; tft++) {
575  }
576 
577  missing_files = BaseMusic::GetUsedSet()->GetNumInvalid() == 0;
578  this->GetWidget<NWidgetCore>(WID_GO_BASE_MUSIC_STATUS)->SetDataTip(missing_files ? STR_EMPTY : STR_GAME_OPTIONS_BASE_MUSIC_STATUS, STR_NULL);
579  }
580 };
581 
582 static const NWidgetPart _nested_game_options_widgets[] = {
584  NWidget(WWT_CLOSEBOX, COLOUR_GREY),
585  NWidget(WWT_CAPTION, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
586  EndContainer(),
587  NWidget(WWT_PANEL, COLOUR_GREY, WID_GO_BACKGROUND), SetPIP(6, 6, 10),
588  NWidget(NWID_HORIZONTAL), SetPIP(10, 10, 10),
589  NWidget(NWID_VERTICAL), SetPIP(0, 6, 0),
590  NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_ROAD_VEHICLES_FRAME, STR_NULL),
591  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),
592  EndContainer(),
593  NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_AUTOSAVE_FRAME, STR_NULL),
594  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),
595  EndContainer(),
596  NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_RESOLUTION, STR_NULL),
597  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),
599  NWidget(WWT_TEXT, COLOUR_GREY), SetMinimalSize(0, 12), SetFill(1, 0), SetDataTip(STR_GAME_OPTIONS_FULLSCREEN, STR_NULL),
600  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_GO_FULLSCREEN_BUTTON), SetMinimalSize(21, 9), SetDataTip(STR_EMPTY, STR_GAME_OPTIONS_FULLSCREEN_TOOLTIP),
601  EndContainer(),
602  EndContainer(),
603  NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_GUI_ZOOM_FRAME, STR_NULL),
604  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),
605  EndContainer(),
606  EndContainer(),
607 
608  NWidget(NWID_VERTICAL), SetPIP(0, 6, 0),
609  NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_TOWN_NAMES_FRAME, STR_NULL),
610  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),
611  EndContainer(),
612  NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_LANGUAGE, STR_NULL),
613  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),
614  EndContainer(),
615  NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_CURRENCY_UNITS_FRAME, STR_NULL),
616  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),
617  EndContainer(),
618  NWidget(NWID_SPACER), SetMinimalSize(0, 0), SetFill(0, 1),
619  EndContainer(),
620  EndContainer(),
621 
622  NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_BASE_GRF, STR_NULL), SetPadding(0, 10, 0, 10),
623  NWidget(NWID_HORIZONTAL), SetPIP(0, 30, 0),
624  NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_BASE_GRF_DROPDOWN), SetMinimalSize(150, 12), SetDataTip(STR_BLACK_RAW_STRING, STR_GAME_OPTIONS_BASE_GRF_TOOLTIP),
625  NWidget(WWT_TEXT, COLOUR_GREY, WID_GO_BASE_GRF_STATUS), SetMinimalSize(150, 12), SetDataTip(STR_EMPTY, STR_NULL), SetFill(1, 0),
626  EndContainer(),
627  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),
629  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),
630  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),
631  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),
632  EndContainer(),
633  EndContainer(),
634 
635  NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_BASE_SFX, STR_NULL), SetPadding(0, 10, 0, 10),
636  NWidget(NWID_HORIZONTAL), SetPIP(0, 30, 0),
637  NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_BASE_SFX_DROPDOWN), SetMinimalSize(150, 12), SetDataTip(STR_BLACK_RAW_STRING, STR_GAME_OPTIONS_BASE_SFX_TOOLTIP),
638  NWidget(NWID_SPACER), SetFill(1, 0),
639  EndContainer(),
640  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),
642  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),
643  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),
644  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),
645  EndContainer(),
646  EndContainer(),
647 
648  NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_BASE_MUSIC, STR_NULL), SetPadding(0, 10, 0, 10),
649  NWidget(NWID_HORIZONTAL), SetPIP(0, 30, 0),
650  NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_BASE_MUSIC_DROPDOWN), SetMinimalSize(150, 12), SetDataTip(STR_BLACK_RAW_STRING, STR_GAME_OPTIONS_BASE_MUSIC_TOOLTIP),
651  NWidget(WWT_TEXT, COLOUR_GREY, WID_GO_BASE_MUSIC_STATUS), SetMinimalSize(150, 12), SetDataTip(STR_EMPTY, STR_NULL), SetFill(1, 0),
652  EndContainer(),
653  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),
655  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),
656  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),
657  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),
658  EndContainer(),
659  EndContainer(),
660  EndContainer(),
661 };
662 
663 static WindowDesc _game_options_desc(
664  WDP_CENTER, "settings_game", 0, 0,
666  0,
667  _nested_game_options_widgets, lengthof(_nested_game_options_widgets)
668 );
669 
672 {
674  new GameOptionsWindow(&_game_options_desc);
675 }
676 
677 static int SETTING_HEIGHT = 11;
678 static const int LEVEL_WIDTH = 15;
679 
688 
689  SEF_LAST_FIELD = 0x04,
690  SEF_FILTERED = 0x08,
691 };
692 
701 };
703 
704 
708  bool type_hides;
711 };
712 
715  byte flags;
716  byte level;
717 
718  BaseSettingEntry() : flags(0), level(0) {}
719  virtual ~BaseSettingEntry() {}
720 
721  virtual void Init(byte level = 0);
722  virtual void FoldAll() {}
723  virtual void UnFoldAll() {}
724 
729  void SetLastField(bool last_field) { if (last_field) SETBITS(this->flags, SEF_LAST_FIELD); else CLRBITS(this->flags, SEF_LAST_FIELD); }
730 
731  virtual uint Length() const = 0;
732  virtual void GetFoldingState(bool &all_folded, bool &all_unfolded) const {}
733  virtual bool IsVisible(const BaseSettingEntry *item) const;
734  virtual BaseSettingEntry *FindEntry(uint row, uint *cur_row);
735  virtual uint GetMaxHelpHeight(int maxw) { return 0; }
736 
741  bool IsFiltered() const { return (this->flags & SEF_FILTERED) != 0; }
742 
743  virtual bool UpdateFilterState(SettingFilter &filter, bool force_visible) = 0;
744 
745  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;
746 
747 protected:
748  virtual void DrawSetting(GameSettings *settings_ptr, int left, int right, int y, bool highlight) const = 0;
749 };
750 
753  const char *name;
755  uint index;
756 
757  SettingEntry(const char *name);
758 
759  virtual void Init(byte level = 0);
760  virtual uint Length() const;
761  virtual uint GetMaxHelpHeight(int maxw);
762  virtual bool UpdateFilterState(SettingFilter &filter, bool force_visible);
763 
764  void SetButtons(byte new_val);
765 
770  inline StringID GetHelpText() const
771  {
772  return this->setting->desc.str_help;
773  }
774 
775  void SetValueDParams(uint first_param, int32 value) const;
776 
777 protected:
778  virtual void DrawSetting(GameSettings *settings_ptr, int left, int right, int y, bool highlight) const;
779 
780 private:
781  bool IsVisibleByRestrictionMode(RestrictionMode mode) const;
782 };
783 
786  typedef std::vector<BaseSettingEntry*> EntryVector;
787  EntryVector entries;
788 
789  template<typename T>
790  T *Add(T *item)
791  {
792  this->entries.push_back(item);
793  return item;
794  }
795 
796  void Init(byte level = 0);
797  void FoldAll();
798  void UnFoldAll();
799 
800  uint Length() const;
801  void GetFoldingState(bool &all_folded, bool &all_unfolded) const;
802  bool IsVisible(const BaseSettingEntry *item) const;
803  BaseSettingEntry *FindEntry(uint row, uint *cur_row);
804  uint GetMaxHelpHeight(int maxw);
805 
806  bool UpdateFilterState(SettingFilter &filter, bool force_visible);
807 
808  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;
809 };
810 
814  bool folded;
815 
816  SettingsPage(StringID title);
817 
818  virtual void Init(byte level = 0);
819  virtual void FoldAll();
820  virtual void UnFoldAll();
821 
822  virtual uint Length() const;
823  virtual void GetFoldingState(bool &all_folded, bool &all_unfolded) const;
824  virtual bool IsVisible(const BaseSettingEntry *item) const;
825  virtual BaseSettingEntry *FindEntry(uint row, uint *cur_row);
826  virtual uint GetMaxHelpHeight(int maxw) { return SettingsContainer::GetMaxHelpHeight(maxw); }
827 
828  virtual bool UpdateFilterState(SettingFilter &filter, bool force_visible);
829 
830  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;
831 
832 protected:
833  virtual void DrawSetting(GameSettings *settings_ptr, int left, int right, int y, bool highlight) const;
834 };
835 
836 /* == BaseSettingEntry methods == */
837 
842 void BaseSettingEntry::Init(byte level)
843 {
844  this->level = level;
845 }
846 
854 {
855  if (this->IsFiltered()) return false;
856  if (this == item) return true;
857  return false;
858 }
859 
866 BaseSettingEntry *BaseSettingEntry::FindEntry(uint row_num, uint *cur_row)
867 {
868  if (this->IsFiltered()) return NULL;
869  if (row_num == *cur_row) return this;
870  (*cur_row)++;
871  return NULL;
872 }
873 
903 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
904 {
905  if (this->IsFiltered()) return cur_row;
906  if (cur_row >= max_row) return cur_row;
907 
908  bool rtl = _current_text_dir == TD_RTL;
909  int offset = rtl ? -4 : 4;
910  int level_width = rtl ? -LEVEL_WIDTH : LEVEL_WIDTH;
911 
912  int x = rtl ? right : left;
913  if (cur_row >= first_row) {
914  int colour = _colour_gradient[COLOUR_ORANGE][4];
915  y += (cur_row - first_row) * SETTING_HEIGHT; // Compute correct y start position
916 
917  /* Draw vertical for parent nesting levels */
918  for (uint lvl = 0; lvl < this->level; lvl++) {
919  if (!HasBit(parent_last, lvl)) GfxDrawLine(x + offset, y, x + offset, y + SETTING_HEIGHT - 1, colour);
920  x += level_width;
921  }
922  /* draw own |- prefix */
923  int halfway_y = y + SETTING_HEIGHT / 2;
924  int bottom_y = (flags & SEF_LAST_FIELD) ? halfway_y : y + SETTING_HEIGHT - 1;
925  GfxDrawLine(x + offset, y, x + offset, bottom_y, colour);
926  /* Small horizontal line from the last vertical line */
927  GfxDrawLine(x + offset, halfway_y, x + level_width - offset, halfway_y, colour);
928  x += level_width;
929 
930  this->DrawSetting(settings_ptr, rtl ? left : x, rtl ? x : right, y, this == selected);
931  }
932  cur_row++;
933 
934  return cur_row;
935 }
936 
937 /* == SettingEntry methods == */
938 
943 SettingEntry::SettingEntry(const char *name)
944 {
945  this->name = name;
946  this->setting = NULL;
947  this->index = 0;
948 }
949 
954 void SettingEntry::Init(byte level)
955 {
956  BaseSettingEntry::Init(level);
957  this->setting = GetSettingFromName(this->name, &this->index);
958  assert(this->setting != NULL);
959 }
960 
966 void SettingEntry::SetButtons(byte new_val)
967 {
968  assert((new_val & ~SEF_BUTTONS_MASK) == 0); // Should not touch any flags outside the buttons
969  this->flags = (this->flags & ~SEF_BUTTONS_MASK) | new_val;
970 }
971 
974 {
975  return this->IsFiltered() ? 0 : 1;
976 }
977 
984 {
985  return GetStringHeight(this->GetHelpText(), maxw);
986 }
987 
994 {
995  /* There shall not be any restriction, i.e. all settings shall be visible. */
996  if (mode == RM_ALL) return true;
997 
998  GameSettings *settings_ptr = &GetGameSettings();
999  const SettingDesc *sd = this->setting;
1000 
1001  if (mode == RM_BASIC) return (this->setting->desc.cat & SC_BASIC_LIST) != 0;
1002  if (mode == RM_ADVANCED) return (this->setting->desc.cat & SC_ADVANCED_LIST) != 0;
1003 
1004  /* Read the current value. */
1005  const void *var = ResolveVariableAddress(settings_ptr, sd);
1006  int64 current_value = ReadValue(var, sd->save.conv);
1007 
1008  int64 filter_value;
1009 
1010  if (mode == RM_CHANGED_AGAINST_DEFAULT) {
1011  /* This entry shall only be visible, if the value deviates from its default value. */
1012 
1013  /* Read the default value. */
1014  filter_value = ReadValue(&sd->desc.def, sd->save.conv);
1015  } else {
1016  assert(mode == RM_CHANGED_AGAINST_NEW);
1017  /* This entry shall only be visible, if the value deviates from
1018  * its value is used when starting a new game. */
1019 
1020  /* Make sure we're not comparing the new game settings against itself. */
1021  assert(settings_ptr != &_settings_newgame);
1022 
1023  /* Read the new game's value. */
1024  var = ResolveVariableAddress(&_settings_newgame, sd);
1025  filter_value = ReadValue(var, sd->save.conv);
1026  }
1027 
1028  return current_value != filter_value;
1029 }
1030 
1037 bool SettingEntry::UpdateFilterState(SettingFilter &filter, bool force_visible)
1038 {
1039  CLRBITS(this->flags, SEF_FILTERED);
1040 
1041  bool visible = true;
1042 
1043  const SettingDesc *sd = this->setting;
1044  if (!force_visible && !filter.string.IsEmpty()) {
1045  /* Process the search text filter for this item. */
1046  filter.string.ResetState();
1047 
1048  const SettingDescBase *sdb = &sd->desc;
1049 
1050  SetDParam(0, STR_EMPTY);
1051  filter.string.AddLine(sdb->str);
1052  filter.string.AddLine(this->GetHelpText());
1053 
1054  visible = filter.string.GetState();
1055  }
1056 
1057  if (visible) {
1058  if (filter.type != ST_ALL && sd->GetType() != filter.type) {
1059  filter.type_hides = true;
1060  visible = false;
1061  }
1062  if (!this->IsVisibleByRestrictionMode(filter.mode)) {
1063  while (filter.min_cat < RM_ALL && (filter.min_cat == filter.mode || !this->IsVisibleByRestrictionMode(filter.min_cat))) filter.min_cat++;
1064  visible = false;
1065  }
1066  }
1067 
1068  if (!visible) SETBITS(this->flags, SEF_FILTERED);
1069  return visible;
1070 }
1071 
1072 
1073 static const void *ResolveVariableAddress(const GameSettings *settings_ptr, const SettingDesc *sd)
1074 {
1075  if ((sd->desc.flags & SGF_PER_COMPANY) != 0) {
1076  if (Company::IsValidID(_local_company) && _game_mode != GM_MENU) {
1078  } else {
1080  }
1081  } else {
1082  return GetVariableAddress(settings_ptr, &sd->save);
1083  }
1084 }
1085 
1091 void SettingEntry::SetValueDParams(uint first_param, int32 value) const
1092 {
1093  const SettingDescBase *sdb = &this->setting->desc;
1094  if (sdb->cmd == SDT_BOOLX) {
1095  SetDParam(first_param++, value != 0 ? STR_CONFIG_SETTING_ON : STR_CONFIG_SETTING_OFF);
1096  } else {
1097  if ((sdb->flags & SGF_MULTISTRING) != 0) {
1098  SetDParam(first_param++, sdb->str_val - sdb->min + value);
1099  } else if ((sdb->flags & SGF_DISPLAY_ABS) != 0) {
1100  SetDParam(first_param++, sdb->str_val + ((value >= 0) ? 1 : 0));
1101  value = abs(value);
1102  } else {
1103  SetDParam(first_param++, sdb->str_val + ((value == 0 && (sdb->flags & SGF_0ISDISABLED) != 0) ? 1 : 0));
1104  }
1105  SetDParam(first_param++, value);
1106  }
1107 }
1108 
1117 void SettingEntry::DrawSetting(GameSettings *settings_ptr, int left, int right, int y, bool highlight) const
1118 {
1119  const SettingDesc *sd = this->setting;
1120  const SettingDescBase *sdb = &sd->desc;
1121  const void *var = ResolveVariableAddress(settings_ptr, sd);
1122  int state = this->flags & SEF_BUTTONS_MASK;
1123 
1124  bool rtl = _current_text_dir == TD_RTL;
1125  uint buttons_left = rtl ? right + 1 - SETTING_BUTTON_WIDTH : left;
1126  uint text_left = left + (rtl ? 0 : SETTING_BUTTON_WIDTH + 5);
1127  uint text_right = right - (rtl ? SETTING_BUTTON_WIDTH + 5 : 0);
1128  uint button_y = y + (SETTING_HEIGHT - SETTING_BUTTON_HEIGHT) / 2;
1129 
1130  /* We do not allow changes of some items when we are a client in a networkgame */
1131  bool editable = sd->IsEditable();
1132 
1133  SetDParam(0, highlight ? STR_ORANGE_STRING1_WHITE : STR_ORANGE_STRING1_LTBLUE);
1134  int32 value = (int32)ReadValue(var, sd->save.conv);
1135  if (sdb->cmd == SDT_BOOLX) {
1136  /* Draw checkbox for boolean-value either on/off */
1137  DrawBoolButton(buttons_left, button_y, value != 0, editable);
1138  } else if ((sdb->flags & SGF_MULTISTRING) != 0) {
1139  /* Draw [v] button for settings of an enum-type */
1140  DrawDropDownButton(buttons_left, button_y, COLOUR_YELLOW, state != 0, editable);
1141  } else {
1142  /* Draw [<][>] boxes for settings of an integer-type */
1143  DrawArrowButtons(buttons_left, button_y, COLOUR_YELLOW, state,
1144  editable && value != (sdb->flags & SGF_0ISDISABLED ? 0 : sdb->min), editable && (uint32)value != sdb->max);
1145  }
1146  this->SetValueDParams(1, value);
1147  DrawString(text_left, text_right, y + (SETTING_HEIGHT - FONT_HEIGHT_NORMAL) / 2, sdb->str, highlight ? TC_WHITE : TC_LIGHT_BLUE);
1148 }
1149 
1150 /* == SettingsContainer methods == */
1151 
1156 void SettingsContainer::Init(byte level)
1157 {
1158  for (EntryVector::iterator it = this->entries.begin(); it != this->entries.end(); ++it) {
1159  (*it)->Init(level);
1160  }
1161 }
1162 
1165 {
1166  for (EntryVector::iterator it = this->entries.begin(); it != this->entries.end(); ++it) {
1167  (*it)->FoldAll();
1168  }
1169 }
1170 
1173 {
1174  for (EntryVector::iterator it = this->entries.begin(); it != this->entries.end(); ++it) {
1175  (*it)->UnFoldAll();
1176  }
1177 }
1178 
1184 void SettingsContainer::GetFoldingState(bool &all_folded, bool &all_unfolded) const
1185 {
1186  for (EntryVector::const_iterator it = this->entries.begin(); it != this->entries.end(); ++it) {
1187  (*it)->GetFoldingState(all_folded, all_unfolded);
1188  }
1189 }
1190 
1197 bool SettingsContainer::UpdateFilterState(SettingFilter &filter, bool force_visible)
1198 {
1199  bool visible = false;
1200  bool first_visible = true;
1201  for (EntryVector::reverse_iterator it = this->entries.rbegin(); it != this->entries.rend(); ++it) {
1202  visible |= (*it)->UpdateFilterState(filter, force_visible);
1203  (*it)->SetLastField(first_visible);
1204  if (visible && first_visible) first_visible = false;
1205  }
1206  return visible;
1207 }
1208 
1209 
1217 {
1218  for (EntryVector::const_iterator it = this->entries.begin(); it != this->entries.end(); ++it) {
1219  if ((*it)->IsVisible(item)) return true;
1220  }
1221  return false;
1222 }
1223 
1226 {
1227  uint length = 0;
1228  for (EntryVector::const_iterator it = this->entries.begin(); it != this->entries.end(); ++it) {
1229  length += (*it)->Length();
1230  }
1231  return length;
1232 }
1233 
1240 BaseSettingEntry *SettingsContainer::FindEntry(uint row_num, uint *cur_row)
1241 {
1242  BaseSettingEntry *pe = NULL;
1243  for (EntryVector::iterator it = this->entries.begin(); it != this->entries.end(); ++it) {
1244  pe = (*it)->FindEntry(row_num, cur_row);
1245  if (pe != NULL) {
1246  break;
1247  }
1248  }
1249  return pe;
1250 }
1251 
1258 {
1259  uint biggest = 0;
1260  for (EntryVector::const_iterator it = this->entries.begin(); it != this->entries.end(); ++it) {
1261  biggest = max(biggest, (*it)->GetMaxHelpHeight(maxw));
1262  }
1263  return biggest;
1264 }
1265 
1266 
1281 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
1282 {
1283  for (EntryVector::const_iterator it = this->entries.begin(); it != this->entries.end(); ++it) {
1284  cur_row = (*it)->Draw(settings_ptr, left, right, y, first_row, max_row, selected, cur_row, parent_last);
1285  if (cur_row >= max_row) {
1286  break;
1287  }
1288  }
1289  return cur_row;
1290 }
1291 
1292 /* == SettingsPage methods == */
1293 
1299 {
1300  this->title = title;
1301  this->folded = true;
1302 }
1303 
1308 void SettingsPage::Init(byte level)
1309 {
1310  BaseSettingEntry::Init(level);
1311  SettingsContainer::Init(level + 1);
1312 }
1313 
1316 {
1317  if (this->IsFiltered()) return;
1318  this->folded = true;
1319 
1321 }
1322 
1325 {
1326  if (this->IsFiltered()) return;
1327  this->folded = false;
1328 
1330 }
1331 
1337 void SettingsPage::GetFoldingState(bool &all_folded, bool &all_unfolded) const
1338 {
1339  if (this->IsFiltered()) return;
1340 
1341  if (this->folded) {
1342  all_unfolded = false;
1343  } else {
1344  all_folded = false;
1345  }
1346 
1347  SettingsContainer::GetFoldingState(all_folded, all_unfolded);
1348 }
1349 
1356 bool SettingsPage::UpdateFilterState(SettingFilter &filter, bool force_visible)
1357 {
1358  if (!force_visible && !filter.string.IsEmpty()) {
1359  filter.string.ResetState();
1360  filter.string.AddLine(this->title);
1361  force_visible = filter.string.GetState();
1362  }
1363 
1364  bool visible = SettingsContainer::UpdateFilterState(filter, force_visible);
1365  if (visible) {
1366  CLRBITS(this->flags, SEF_FILTERED);
1367  } else {
1368  SETBITS(this->flags, SEF_FILTERED);
1369  }
1370  return visible;
1371 }
1372 
1380 {
1381  if (this->IsFiltered()) return false;
1382  if (this == item) return true;
1383  if (this->folded) return false;
1384 
1385  return SettingsContainer::IsVisible(item);
1386 }
1387 
1390 {
1391  if (this->IsFiltered()) return 0;
1392  if (this->folded) return 1; // Only displaying the title
1393 
1394  return 1 + SettingsContainer::Length();
1395 }
1396 
1403 BaseSettingEntry *SettingsPage::FindEntry(uint row_num, uint *cur_row)
1404 {
1405  if (this->IsFiltered()) return NULL;
1406  if (row_num == *cur_row) return this;
1407  (*cur_row)++;
1408  if (this->folded) return NULL;
1409 
1410  return SettingsContainer::FindEntry(row_num, cur_row);
1411 }
1412 
1427 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
1428 {
1429  if (this->IsFiltered()) return cur_row;
1430  if (cur_row >= max_row) return cur_row;
1431 
1432  cur_row = BaseSettingEntry::Draw(settings_ptr, left, right, y, first_row, max_row, selected, cur_row, parent_last);
1433 
1434  if (!this->folded) {
1435  if (this->flags & SEF_LAST_FIELD) {
1436  assert(this->level < 8 * sizeof(parent_last));
1437  SetBit(parent_last, this->level); // Add own last-field state
1438  }
1439 
1440  cur_row = SettingsContainer::Draw(settings_ptr, left, right, y, first_row, max_row, selected, cur_row, parent_last);
1441  }
1442 
1443  return cur_row;
1444 }
1445 
1454 void SettingsPage::DrawSetting(GameSettings *settings_ptr, int left, int right, int y, bool highlight) const
1455 {
1456  bool rtl = _current_text_dir == TD_RTL;
1457  DrawSprite((this->folded ? SPR_CIRCLE_FOLDED : SPR_CIRCLE_UNFOLDED), PAL_NONE, rtl ? right - _circle_size.width : left, y + (SETTING_HEIGHT - _circle_size.height) / 2);
1458  DrawString(rtl ? left : left + _circle_size.width + 2, rtl ? right - _circle_size.width - 2 : right, y + (SETTING_HEIGHT - FONT_HEIGHT_NORMAL) / 2, this->title);
1459 }
1460 
1463 {
1464  static SettingsContainer *main = NULL;
1465 
1466  if (main == NULL)
1467  {
1468  /* Build up the dynamic settings-array only once per OpenTTD session */
1469  main = new SettingsContainer();
1470 
1471  SettingsPage *localisation = main->Add(new SettingsPage(STR_CONFIG_SETTING_LOCALISATION));
1472  {
1473  localisation->Add(new SettingEntry("locale.units_velocity"));
1474  localisation->Add(new SettingEntry("locale.units_power"));
1475  localisation->Add(new SettingEntry("locale.units_weight"));
1476  localisation->Add(new SettingEntry("locale.units_volume"));
1477  localisation->Add(new SettingEntry("locale.units_force"));
1478  localisation->Add(new SettingEntry("locale.units_height"));
1479  localisation->Add(new SettingEntry("gui.date_format_in_default_names"));
1480  }
1481 
1482  SettingsPage *graphics = main->Add(new SettingsPage(STR_CONFIG_SETTING_GRAPHICS));
1483  {
1484  graphics->Add(new SettingEntry("gui.zoom_min"));
1485  graphics->Add(new SettingEntry("gui.zoom_max"));
1486  graphics->Add(new SettingEntry("gui.smallmap_land_colour"));
1487  graphics->Add(new SettingEntry("gui.graph_line_thickness"));
1488  }
1489 
1490  SettingsPage *sound = main->Add(new SettingsPage(STR_CONFIG_SETTING_SOUND));
1491  {
1492  sound->Add(new SettingEntry("sound.click_beep"));
1493  sound->Add(new SettingEntry("sound.confirm"));
1494  sound->Add(new SettingEntry("sound.news_ticker"));
1495  sound->Add(new SettingEntry("sound.news_full"));
1496  sound->Add(new SettingEntry("sound.new_year"));
1497  sound->Add(new SettingEntry("sound.disaster"));
1498  sound->Add(new SettingEntry("sound.vehicle"));
1499  sound->Add(new SettingEntry("sound.ambient"));
1500  }
1501 
1502  SettingsPage *interface = main->Add(new SettingsPage(STR_CONFIG_SETTING_INTERFACE));
1503  {
1504  SettingsPage *general = interface->Add(new SettingsPage(STR_CONFIG_SETTING_INTERFACE_GENERAL));
1505  {
1506  general->Add(new SettingEntry("gui.osk_activation"));
1507  general->Add(new SettingEntry("gui.hover_delay_ms"));
1508  general->Add(new SettingEntry("gui.errmsg_duration"));
1509  general->Add(new SettingEntry("gui.window_snap_radius"));
1510  general->Add(new SettingEntry("gui.window_soft_limit"));
1511  general->Add(new SettingEntry("gui.right_mouse_wnd_close"));
1512  }
1513 
1514  SettingsPage *viewports = interface->Add(new SettingsPage(STR_CONFIG_SETTING_INTERFACE_VIEWPORTS));
1515  {
1516  viewports->Add(new SettingEntry("gui.auto_scrolling"));
1517  viewports->Add(new SettingEntry("gui.scroll_mode"));
1518  viewports->Add(new SettingEntry("gui.smooth_scroll"));
1519  /* While the horizontal scrollwheel scrolling is written as general code, only
1520  * the cocoa (OSX) driver generates input for it.
1521  * Since it's also able to completely disable the scrollwheel will we display it on all platforms anyway */
1522  viewports->Add(new SettingEntry("gui.scrollwheel_scrolling"));
1523  viewports->Add(new SettingEntry("gui.scrollwheel_multiplier"));
1524 #ifdef __APPLE__
1525  /* We might need to emulate a right mouse button on mac */
1526  viewports->Add(new SettingEntry("gui.right_mouse_btn_emulation"));
1527 #endif
1528  viewports->Add(new SettingEntry("gui.population_in_label"));
1529  viewports->Add(new SettingEntry("gui.liveries"));
1530  viewports->Add(new SettingEntry("construction.train_signal_side"));
1531  viewports->Add(new SettingEntry("gui.measure_tooltip"));
1532  viewports->Add(new SettingEntry("gui.loading_indicators"));
1533  viewports->Add(new SettingEntry("gui.show_track_reservation"));
1534  }
1535 
1536  SettingsPage *construction = interface->Add(new SettingsPage(STR_CONFIG_SETTING_INTERFACE_CONSTRUCTION));
1537  {
1538  construction->Add(new SettingEntry("gui.link_terraform_toolbar"));
1539  construction->Add(new SettingEntry("gui.enable_signal_gui"));
1540  construction->Add(new SettingEntry("gui.persistent_buildingtools"));
1541  construction->Add(new SettingEntry("gui.quick_goto"));
1542  construction->Add(new SettingEntry("gui.default_rail_type"));
1543  construction->Add(new SettingEntry("gui.disable_unsuitable_building"));
1544  }
1545 
1546  interface->Add(new SettingEntry("gui.autosave"));
1547  interface->Add(new SettingEntry("gui.toolbar_pos"));
1548  interface->Add(new SettingEntry("gui.statusbar_pos"));
1549  interface->Add(new SettingEntry("gui.prefer_teamchat"));
1550  interface->Add(new SettingEntry("gui.advanced_vehicle_list"));
1551  interface->Add(new SettingEntry("gui.timetable_in_ticks"));
1552  interface->Add(new SettingEntry("gui.timetable_arrival_departure"));
1553  interface->Add(new SettingEntry("gui.expenses_layout"));
1554  }
1555 
1556  SettingsPage *advisors = main->Add(new SettingsPage(STR_CONFIG_SETTING_ADVISORS));
1557  {
1558  advisors->Add(new SettingEntry("gui.coloured_news_year"));
1559  advisors->Add(new SettingEntry("news_display.general"));
1560  advisors->Add(new SettingEntry("news_display.new_vehicles"));
1561  advisors->Add(new SettingEntry("news_display.accident"));
1562  advisors->Add(new SettingEntry("news_display.company_info"));
1563  advisors->Add(new SettingEntry("news_display.acceptance"));
1564  advisors->Add(new SettingEntry("news_display.arrival_player"));
1565  advisors->Add(new SettingEntry("news_display.arrival_other"));
1566  advisors->Add(new SettingEntry("news_display.advice"));
1567  advisors->Add(new SettingEntry("gui.order_review_system"));
1568  advisors->Add(new SettingEntry("gui.vehicle_income_warn"));
1569  advisors->Add(new SettingEntry("gui.lost_vehicle_warn"));
1570  advisors->Add(new SettingEntry("gui.show_finances"));
1571  advisors->Add(new SettingEntry("news_display.economy"));
1572  advisors->Add(new SettingEntry("news_display.subsidies"));
1573  advisors->Add(new SettingEntry("news_display.open"));
1574  advisors->Add(new SettingEntry("news_display.close"));
1575  advisors->Add(new SettingEntry("news_display.production_player"));
1576  advisors->Add(new SettingEntry("news_display.production_other"));
1577  advisors->Add(new SettingEntry("news_display.production_nobody"));
1578  }
1579 
1580  SettingsPage *company = main->Add(new SettingsPage(STR_CONFIG_SETTING_COMPANY));
1581  {
1582  company->Add(new SettingEntry("gui.semaphore_build_before"));
1583  company->Add(new SettingEntry("gui.default_signal_type"));
1584  company->Add(new SettingEntry("gui.cycle_signal_types"));
1585  company->Add(new SettingEntry("gui.drag_signals_fixed_distance"));
1586  company->Add(new SettingEntry("gui.new_nonstop"));
1587  company->Add(new SettingEntry("gui.stop_location"));
1588  company->Add(new SettingEntry("gui.starting_colour"));
1589  company->Add(new SettingEntry("company.engine_renew"));
1590  company->Add(new SettingEntry("company.engine_renew_months"));
1591  company->Add(new SettingEntry("company.engine_renew_money"));
1592  company->Add(new SettingEntry("vehicle.servint_ispercent"));
1593  company->Add(new SettingEntry("vehicle.servint_trains"));
1594  company->Add(new SettingEntry("vehicle.servint_roadveh"));
1595  company->Add(new SettingEntry("vehicle.servint_ships"));
1596  company->Add(new SettingEntry("vehicle.servint_aircraft"));
1597  }
1598 
1599  SettingsPage *accounting = main->Add(new SettingsPage(STR_CONFIG_SETTING_ACCOUNTING));
1600  {
1601  accounting->Add(new SettingEntry("economy.inflation"));
1602  accounting->Add(new SettingEntry("difficulty.initial_interest"));
1603  accounting->Add(new SettingEntry("difficulty.max_loan"));
1604  accounting->Add(new SettingEntry("difficulty.subsidy_multiplier"));
1605  accounting->Add(new SettingEntry("economy.feeder_payment_share"));
1606  accounting->Add(new SettingEntry("economy.infrastructure_maintenance"));
1607  accounting->Add(new SettingEntry("difficulty.vehicle_costs"));
1608  accounting->Add(new SettingEntry("difficulty.construction_cost"));
1609  }
1610 
1611  SettingsPage *vehicles = main->Add(new SettingsPage(STR_CONFIG_SETTING_VEHICLES));
1612  {
1613  SettingsPage *physics = vehicles->Add(new SettingsPage(STR_CONFIG_SETTING_VEHICLES_PHYSICS));
1614  {
1615  physics->Add(new SettingEntry("vehicle.train_acceleration_model"));
1616  physics->Add(new SettingEntry("vehicle.train_slope_steepness"));
1617  physics->Add(new SettingEntry("vehicle.wagon_speed_limits"));
1618  physics->Add(new SettingEntry("vehicle.freight_trains"));
1619  physics->Add(new SettingEntry("vehicle.roadveh_acceleration_model"));
1620  physics->Add(new SettingEntry("vehicle.roadveh_slope_steepness"));
1621  physics->Add(new SettingEntry("vehicle.smoke_amount"));
1622  physics->Add(new SettingEntry("vehicle.plane_speed"));
1623  }
1624 
1625  SettingsPage *routing = vehicles->Add(new SettingsPage(STR_CONFIG_SETTING_VEHICLES_ROUTING));
1626  {
1627  routing->Add(new SettingEntry("pf.pathfinder_for_trains"));
1628  routing->Add(new SettingEntry("difficulty.line_reverse_mode"));
1629  routing->Add(new SettingEntry("pf.reverse_at_signals"));
1630  routing->Add(new SettingEntry("pf.forbid_90_deg"));
1631  routing->Add(new SettingEntry("pf.pathfinder_for_roadvehs"));
1632  routing->Add(new SettingEntry("pf.pathfinder_for_ships"));
1633  }
1634 
1635  vehicles->Add(new SettingEntry("order.no_servicing_if_no_breakdowns"));
1636  vehicles->Add(new SettingEntry("order.serviceathelipad"));
1637  }
1638 
1639  SettingsPage *limitations = main->Add(new SettingsPage(STR_CONFIG_SETTING_LIMITATIONS));
1640  {
1641  limitations->Add(new SettingEntry("construction.command_pause_level"));
1642  limitations->Add(new SettingEntry("construction.autoslope"));
1643  limitations->Add(new SettingEntry("construction.extra_dynamite"));
1644  limitations->Add(new SettingEntry("construction.max_heightlevel"));
1645  limitations->Add(new SettingEntry("construction.max_bridge_length"));
1646  limitations->Add(new SettingEntry("construction.max_bridge_height"));
1647  limitations->Add(new SettingEntry("construction.max_tunnel_length"));
1648  limitations->Add(new SettingEntry("station.never_expire_airports"));
1649  limitations->Add(new SettingEntry("vehicle.never_expire_vehicles"));
1650  limitations->Add(new SettingEntry("vehicle.max_trains"));
1651  limitations->Add(new SettingEntry("vehicle.max_roadveh"));
1652  limitations->Add(new SettingEntry("vehicle.max_aircraft"));
1653  limitations->Add(new SettingEntry("vehicle.max_ships"));
1654  limitations->Add(new SettingEntry("vehicle.max_train_length"));
1655  limitations->Add(new SettingEntry("station.station_spread"));
1656  limitations->Add(new SettingEntry("station.distant_join_stations"));
1657  limitations->Add(new SettingEntry("construction.road_stop_on_town_road"));
1658  limitations->Add(new SettingEntry("construction.road_stop_on_competitor_road"));
1659  limitations->Add(new SettingEntry("vehicle.disable_elrails"));
1660  }
1661 
1662  SettingsPage *disasters = main->Add(new SettingsPage(STR_CONFIG_SETTING_ACCIDENTS));
1663  {
1664  disasters->Add(new SettingEntry("difficulty.disasters"));
1665  disasters->Add(new SettingEntry("difficulty.economy"));
1666  disasters->Add(new SettingEntry("difficulty.vehicle_breakdowns"));
1667  disasters->Add(new SettingEntry("vehicle.plane_crashes"));
1668  }
1669 
1670  SettingsPage *genworld = main->Add(new SettingsPage(STR_CONFIG_SETTING_GENWORLD));
1671  {
1672  genworld->Add(new SettingEntry("game_creation.landscape"));
1673  genworld->Add(new SettingEntry("game_creation.land_generator"));
1674  genworld->Add(new SettingEntry("difficulty.terrain_type"));
1675  genworld->Add(new SettingEntry("game_creation.tgen_smoothness"));
1676  genworld->Add(new SettingEntry("game_creation.variety"));
1677  genworld->Add(new SettingEntry("game_creation.snow_line_height"));
1678  genworld->Add(new SettingEntry("game_creation.amount_of_rivers"));
1679  genworld->Add(new SettingEntry("game_creation.tree_placer"));
1680  genworld->Add(new SettingEntry("vehicle.road_side"));
1681  genworld->Add(new SettingEntry("economy.larger_towns"));
1682  genworld->Add(new SettingEntry("economy.initial_city_size"));
1683  genworld->Add(new SettingEntry("economy.town_layout"));
1684  genworld->Add(new SettingEntry("difficulty.industry_density"));
1685  genworld->Add(new SettingEntry("gui.pause_on_newgame"));
1686  }
1687 
1688  SettingsPage *environment = main->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT));
1689  {
1690  SettingsPage *authorities = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_AUTHORITIES));
1691  {
1692  authorities->Add(new SettingEntry("difficulty.town_council_tolerance"));
1693  authorities->Add(new SettingEntry("economy.bribe"));
1694  authorities->Add(new SettingEntry("economy.exclusive_rights"));
1695  authorities->Add(new SettingEntry("economy.fund_roads"));
1696  authorities->Add(new SettingEntry("economy.fund_buildings"));
1697  authorities->Add(new SettingEntry("economy.station_noise_level"));
1698  }
1699 
1700  SettingsPage *towns = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_TOWNS));
1701  {
1702  towns->Add(new SettingEntry("economy.town_growth_rate"));
1703  towns->Add(new SettingEntry("economy.allow_town_roads"));
1704  towns->Add(new SettingEntry("economy.allow_town_level_crossings"));
1705  towns->Add(new SettingEntry("economy.found_town"));
1706  }
1707 
1708  SettingsPage *industries = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_INDUSTRIES));
1709  {
1710  industries->Add(new SettingEntry("construction.raw_industry_construction"));
1711  industries->Add(new SettingEntry("construction.industry_platform"));
1712  industries->Add(new SettingEntry("economy.multiple_industry_per_town"));
1713  industries->Add(new SettingEntry("game_creation.oil_refinery_limit"));
1714  industries->Add(new SettingEntry("economy.smooth_economy"));
1715  }
1716 
1717  SettingsPage *cdist = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_CARGODIST));
1718  {
1719  cdist->Add(new SettingEntry("linkgraph.recalc_time"));
1720  cdist->Add(new SettingEntry("linkgraph.recalc_interval"));
1721  cdist->Add(new SettingEntry("linkgraph.distribution_pax"));
1722  cdist->Add(new SettingEntry("linkgraph.distribution_mail"));
1723  cdist->Add(new SettingEntry("linkgraph.distribution_armoured"));
1724  cdist->Add(new SettingEntry("linkgraph.distribution_default"));
1725  cdist->Add(new SettingEntry("linkgraph.accuracy"));
1726  cdist->Add(new SettingEntry("linkgraph.demand_distance"));
1727  cdist->Add(new SettingEntry("linkgraph.demand_size"));
1728  cdist->Add(new SettingEntry("linkgraph.short_path_saturation"));
1729  }
1730 
1731  environment->Add(new SettingEntry("station.modified_catchment"));
1732  environment->Add(new SettingEntry("construction.extra_tree_placement"));
1733  }
1734 
1735  SettingsPage *ai = main->Add(new SettingsPage(STR_CONFIG_SETTING_AI));
1736  {
1737  SettingsPage *npc = ai->Add(new SettingsPage(STR_CONFIG_SETTING_AI_NPC));
1738  {
1739  npc->Add(new SettingEntry("script.settings_profile"));
1740  npc->Add(new SettingEntry("script.script_max_opcode_till_suspend"));
1741  npc->Add(new SettingEntry("difficulty.competitor_speed"));
1742  npc->Add(new SettingEntry("ai.ai_in_multiplayer"));
1743  npc->Add(new SettingEntry("ai.ai_disable_veh_train"));
1744  npc->Add(new SettingEntry("ai.ai_disable_veh_roadveh"));
1745  npc->Add(new SettingEntry("ai.ai_disable_veh_aircraft"));
1746  npc->Add(new SettingEntry("ai.ai_disable_veh_ship"));
1747  }
1748 
1749  ai->Add(new SettingEntry("economy.give_money"));
1750  ai->Add(new SettingEntry("economy.allow_shares"));
1751  }
1752 
1753  main->Init();
1754  }
1755  return *main;
1756 }
1757 
1758 static const StringID _game_settings_restrict_dropdown[] = {
1759  STR_CONFIG_SETTING_RESTRICT_BASIC, // RM_BASIC
1760  STR_CONFIG_SETTING_RESTRICT_ADVANCED, // RM_ADVANCED
1761  STR_CONFIG_SETTING_RESTRICT_ALL, // RM_ALL
1762  STR_CONFIG_SETTING_RESTRICT_CHANGED_AGAINST_DEFAULT, // RM_CHANGED_AGAINST_DEFAULT
1763  STR_CONFIG_SETTING_RESTRICT_CHANGED_AGAINST_NEW, // RM_CHANGED_AGAINST_NEW
1764 };
1765 assert_compile(lengthof(_game_settings_restrict_dropdown) == RM_END);
1766 
1773 };
1774 
1777  static const int SETTINGTREE_LEFT_OFFSET = 5;
1778  static const int SETTINGTREE_RIGHT_OFFSET = 5;
1779  static const int SETTINGTREE_TOP_OFFSET = 5;
1780  static const int SETTINGTREE_BOTTOM_OFFSET = 5;
1781 
1783 
1789 
1795 
1796  Scrollbar *vscroll;
1797 
1798  GameSettingsWindow(WindowDesc *desc) : Window(desc), filter_editbox(50)
1799  {
1800  this->warn_missing = WHR_NONE;
1801  this->warn_lines = 0;
1803  this->filter.min_cat = RM_ALL;
1804  this->filter.type = ST_ALL;
1805  this->filter.type_hides = false;
1806  this->settings_ptr = &GetGameSettings();
1807 
1808  _circle_size = maxdim(GetSpriteSize(SPR_CIRCLE_FOLDED), GetSpriteSize(SPR_CIRCLE_UNFOLDED));
1809  GetSettingsTree().FoldAll(); // Close all sub-pages
1810 
1811  this->valuewindow_entry = NULL; // No setting entry for which a entry window is opened
1812  this->clicked_entry = NULL; // No numeric setting buttons are depressed
1813  this->last_clicked = NULL;
1814  this->valuedropdown_entry = NULL;
1815  this->closing_dropdown = false;
1816  this->manually_changed_folding = false;
1817 
1818  this->CreateNestedTree();
1819  this->vscroll = this->GetScrollbar(WID_GS_SCROLLBAR);
1821 
1822  this->querystrings[WID_GS_FILTER] = &this->filter_editbox;
1823  this->filter_editbox.cancel_button = QueryString::ACTION_CLEAR;
1825 
1826  this->InvalidateData();
1827  }
1828 
1829  virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
1830  {
1831  switch (widget) {
1832  case WID_GS_OPTIONSPANEL:
1833  resize->height = SETTING_HEIGHT = max(max<int>(_circle_size.height, SETTING_BUTTON_HEIGHT), FONT_HEIGHT_NORMAL) + 1;
1834  resize->width = 1;
1835 
1836  size->height = 5 * resize->height + SETTINGTREE_TOP_OFFSET + SETTINGTREE_BOTTOM_OFFSET;
1837  break;
1838 
1839  case WID_GS_HELP_TEXT: {
1840  static const StringID setting_types[] = {
1841  STR_CONFIG_SETTING_TYPE_CLIENT,
1842  STR_CONFIG_SETTING_TYPE_COMPANY_MENU, STR_CONFIG_SETTING_TYPE_COMPANY_INGAME,
1843  STR_CONFIG_SETTING_TYPE_GAME_MENU, STR_CONFIG_SETTING_TYPE_GAME_INGAME,
1844  };
1845  for (uint i = 0; i < lengthof(setting_types); i++) {
1846  SetDParam(0, setting_types[i]);
1847  size->width = max(size->width, GetStringBoundingBox(STR_CONFIG_SETTING_TYPE).width);
1848  }
1849  size->height = 2 * FONT_HEIGHT_NORMAL + WD_PAR_VSEP_NORMAL +
1850  max(size->height, GetSettingsTree().GetMaxHelpHeight(size->width));
1851  break;
1852  }
1853 
1855  case WID_GS_RESTRICT_TYPE:
1856  size->width = max(GetStringBoundingBox(STR_CONFIG_SETTING_RESTRICT_CATEGORY).width, GetStringBoundingBox(STR_CONFIG_SETTING_RESTRICT_TYPE).width);
1857  break;
1858 
1859  default:
1860  break;
1861  }
1862  }
1863 
1864  virtual void OnPaint()
1865  {
1866  if (this->closing_dropdown) {
1867  this->closing_dropdown = false;
1868  assert(this->valuedropdown_entry != NULL);
1869  this->valuedropdown_entry->SetButtons(0);
1870  this->valuedropdown_entry = NULL;
1871  }
1872 
1873  /* Reserve the correct number of lines for the 'some search results are hidden' notice in the central settings display panel. */
1874  const NWidgetBase *panel = this->GetWidget<NWidgetBase>(WID_GS_OPTIONSPANEL);
1875  StringID warn_str = STR_CONFIG_SETTING_CATEGORY_HIDES - 1 + this->warn_missing;
1876  int new_warn_lines;
1877  if (this->warn_missing == WHR_NONE) {
1878  new_warn_lines = 0;
1879  } else {
1880  SetDParam(0, _game_settings_restrict_dropdown[this->filter.min_cat]);
1881  new_warn_lines = GetStringLineCount(warn_str, panel->current_x);
1882  }
1883  if (this->warn_lines != new_warn_lines) {
1884  this->vscroll->SetCount(this->vscroll->GetCount() - this->warn_lines + new_warn_lines);
1885  this->warn_lines = new_warn_lines;
1886  }
1887 
1888  this->DrawWidgets();
1889 
1890  /* Draw the 'some search results are hidden' notice. */
1891  if (this->warn_missing != WHR_NONE) {
1892  const int left = panel->pos_x;
1893  const int right = left + panel->current_x - 1;
1894  const int top = panel->pos_y + WD_FRAMETEXT_TOP + (SETTING_HEIGHT - FONT_HEIGHT_NORMAL) * this->warn_lines / 2;
1895  SetDParam(0, _game_settings_restrict_dropdown[this->filter.min_cat]);
1896  if (this->warn_lines == 1) {
1897  /* If the warning fits at one line, center it. */
1898  DrawString(left + WD_FRAMETEXT_LEFT, right - WD_FRAMETEXT_RIGHT, top, warn_str, TC_FROMSTRING, SA_HOR_CENTER);
1899  } else {
1900  DrawStringMultiLine(left + WD_FRAMERECT_LEFT, right - WD_FRAMERECT_RIGHT, top, INT32_MAX, warn_str, TC_FROMSTRING, SA_HOR_CENTER);
1901  }
1902  }
1903  }
1904 
1905  virtual void SetStringParameters(int widget) const
1906  {
1907  switch (widget) {
1909  SetDParam(0, _game_settings_restrict_dropdown[this->filter.mode]);
1910  break;
1911 
1912  case WID_GS_TYPE_DROPDOWN:
1913  switch (this->filter.type) {
1914  case ST_GAME: SetDParam(0, _game_mode == GM_MENU ? STR_CONFIG_SETTING_TYPE_DROPDOWN_GAME_MENU : STR_CONFIG_SETTING_TYPE_DROPDOWN_GAME_INGAME); break;
1915  case ST_COMPANY: SetDParam(0, _game_mode == GM_MENU ? STR_CONFIG_SETTING_TYPE_DROPDOWN_COMPANY_MENU : STR_CONFIG_SETTING_TYPE_DROPDOWN_COMPANY_INGAME); break;
1916  case ST_CLIENT: SetDParam(0, STR_CONFIG_SETTING_TYPE_DROPDOWN_CLIENT); break;
1917  default: SetDParam(0, STR_CONFIG_SETTING_TYPE_DROPDOWN_ALL); break;
1918  }
1919  break;
1920  }
1921  }
1922 
1923  DropDownList *BuildDropDownList(int widget) const
1924  {
1925  DropDownList *list = NULL;
1926  switch (widget) {
1928  list = new DropDownList();
1929 
1930  for (int mode = 0; mode != RM_END; mode++) {
1931  /* If we are in adv. settings screen for the new game's settings,
1932  * we don't want to allow comparing with new game's settings. */
1933  bool disabled = mode == RM_CHANGED_AGAINST_NEW && settings_ptr == &_settings_newgame;
1934 
1935  *list->Append() = new DropDownListStringItem(_game_settings_restrict_dropdown[mode], mode, disabled);
1936  }
1937  break;
1938 
1939  case WID_GS_TYPE_DROPDOWN:
1940  list = new DropDownList();
1941  *list->Append() = new DropDownListStringItem(STR_CONFIG_SETTING_TYPE_DROPDOWN_ALL, ST_ALL, false);
1942  *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);
1943  *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);
1944  *list->Append() = new DropDownListStringItem(STR_CONFIG_SETTING_TYPE_DROPDOWN_CLIENT, ST_CLIENT, false);
1945  break;
1946  }
1947  return list;
1948  }
1949 
1950  virtual void DrawWidget(const Rect &r, int widget) const
1951  {
1952  switch (widget) {
1953  case WID_GS_OPTIONSPANEL: {
1954  int top_pos = r.top + SETTINGTREE_TOP_OFFSET + 1 + this->warn_lines * SETTING_HEIGHT;
1955  uint last_row = this->vscroll->GetPosition() + this->vscroll->GetCapacity() - this->warn_lines;
1956  int next_row = GetSettingsTree().Draw(settings_ptr, r.left + SETTINGTREE_LEFT_OFFSET, r.right - SETTINGTREE_RIGHT_OFFSET, top_pos,
1957  this->vscroll->GetPosition(), last_row, this->last_clicked);
1958  if (next_row == 0) DrawString(r.left + SETTINGTREE_LEFT_OFFSET, r.right - SETTINGTREE_RIGHT_OFFSET, top_pos, STR_CONFIG_SETTINGS_NONE);
1959  break;
1960  }
1961 
1962  case WID_GS_HELP_TEXT:
1963  if (this->last_clicked != NULL) {
1964  const SettingDesc *sd = this->last_clicked->setting;
1965 
1966  int y = r.top;
1967  switch (sd->GetType()) {
1968  case ST_COMPANY: SetDParam(0, _game_mode == GM_MENU ? STR_CONFIG_SETTING_TYPE_COMPANY_MENU : STR_CONFIG_SETTING_TYPE_COMPANY_INGAME); break;
1969  case ST_CLIENT: SetDParam(0, STR_CONFIG_SETTING_TYPE_CLIENT); break;
1970  case ST_GAME: SetDParam(0, _game_mode == GM_MENU ? STR_CONFIG_SETTING_TYPE_GAME_MENU : STR_CONFIG_SETTING_TYPE_GAME_INGAME); break;
1971  default: NOT_REACHED();
1972  }
1973  DrawString(r.left, r.right, y, STR_CONFIG_SETTING_TYPE);
1974  y += FONT_HEIGHT_NORMAL;
1975 
1976  int32 default_value = ReadValue(&sd->desc.def, sd->save.conv);
1977  this->last_clicked->SetValueDParams(0, default_value);
1978  DrawString(r.left, r.right, y, STR_CONFIG_SETTING_DEFAULT_VALUE);
1980 
1981  DrawStringMultiLine(r.left, r.right, y, r.bottom, this->last_clicked->GetHelpText(), TC_WHITE);
1982  }
1983  break;
1984 
1985  default:
1986  break;
1987  }
1988  }
1989 
1995  {
1996  if (this->last_clicked != pe) this->SetDirty();
1997  this->last_clicked = pe;
1998  }
1999 
2000  virtual void OnClick(Point pt, int widget, int click_count)
2001  {
2002  switch (widget) {
2003  case WID_GS_EXPAND_ALL:
2004  this->manually_changed_folding = true;
2006  this->InvalidateData();
2007  break;
2008 
2009  case WID_GS_COLLAPSE_ALL:
2010  this->manually_changed_folding = true;
2012  this->InvalidateData();
2013  break;
2014 
2015  case WID_GS_RESTRICT_DROPDOWN: {
2016  DropDownList *list = this->BuildDropDownList(widget);
2017  if (list != NULL) {
2018  ShowDropDownList(this, list, this->filter.mode, widget);
2019  }
2020  break;
2021  }
2022 
2023  case WID_GS_TYPE_DROPDOWN: {
2024  DropDownList *list = this->BuildDropDownList(widget);
2025  if (list != NULL) {
2026  ShowDropDownList(this, list, this->filter.type, widget);
2027  }
2028  break;
2029  }
2030  }
2031 
2032  if (widget != WID_GS_OPTIONSPANEL) return;
2033 
2034  uint btn = this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_GS_OPTIONSPANEL, SETTINGTREE_TOP_OFFSET);
2035  if (btn == INT_MAX || (int)btn < this->warn_lines) return;
2036  btn -= this->warn_lines;
2037 
2038  uint cur_row = 0;
2039  BaseSettingEntry *clicked_entry = GetSettingsTree().FindEntry(btn, &cur_row);
2040 
2041  if (clicked_entry == NULL) return; // Clicked below the last setting of the page
2042 
2043  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
2044  if (x < 0) return; // Clicked left of the entry
2045 
2046  SettingsPage *clicked_page = dynamic_cast<SettingsPage*>(clicked_entry);
2047  if (clicked_page != NULL) {
2048  this->SetDisplayedHelpText(NULL);
2049  clicked_page->folded = !clicked_page->folded; // Flip 'folded'-ness of the sub-page
2050 
2051  this->manually_changed_folding = true;
2052 
2053  this->InvalidateData();
2054  return;
2055  }
2056 
2057  SettingEntry *pe = dynamic_cast<SettingEntry*>(clicked_entry);
2058  assert(pe != NULL);
2059  const SettingDesc *sd = pe->setting;
2060 
2061  /* return if action is only active in network, or only settable by server */
2062  if (!sd->IsEditable()) {
2063  this->SetDisplayedHelpText(pe);
2064  return;
2065  }
2066 
2067  const void *var = ResolveVariableAddress(settings_ptr, sd);
2068  int32 value = (int32)ReadValue(var, sd->save.conv);
2069 
2070  /* clicked on the icon on the left side. Either scroller, bool on/off or dropdown */
2071  if (x < SETTING_BUTTON_WIDTH && (sd->desc.flags & SGF_MULTISTRING)) {
2072  const SettingDescBase *sdb = &sd->desc;
2073  this->SetDisplayedHelpText(pe);
2074 
2075  if (this->valuedropdown_entry == pe) {
2076  /* unclick the dropdown */
2077  HideDropDownMenu(this);
2078  this->closing_dropdown = false;
2079  this->valuedropdown_entry->SetButtons(0);
2080  this->valuedropdown_entry = NULL;
2081  } else {
2082  if (this->valuedropdown_entry != NULL) this->valuedropdown_entry->SetButtons(0);
2083  this->closing_dropdown = false;
2084 
2085  const NWidgetBase *wid = this->GetWidget<NWidgetBase>(WID_GS_OPTIONSPANEL);
2086  int rel_y = (pt.y - (int)wid->pos_y - SETTINGTREE_TOP_OFFSET) % wid->resize_y;
2087 
2088  Rect wi_rect;
2089  wi_rect.left = pt.x - (_current_text_dir == TD_RTL ? SETTING_BUTTON_WIDTH - 1 - x : x);
2090  wi_rect.right = wi_rect.left + SETTING_BUTTON_WIDTH - 1;
2091  wi_rect.top = pt.y - rel_y + (SETTING_HEIGHT - SETTING_BUTTON_HEIGHT) / 2;
2092  wi_rect.bottom = wi_rect.top + SETTING_BUTTON_HEIGHT - 1;
2093 
2094  /* For dropdowns we also have to check the y position thoroughly, the mouse may not above the just opening dropdown */
2095  if (pt.y >= wi_rect.top && pt.y <= wi_rect.bottom) {
2096  this->valuedropdown_entry = pe;
2097  this->valuedropdown_entry->SetButtons(SEF_LEFT_DEPRESSED);
2098 
2099  DropDownList *list = new DropDownList();
2100  for (int i = sdb->min; i <= (int)sdb->max; i++) {
2101  *list->Append() = new DropDownListStringItem(sdb->str_val + i - sdb->min, i, false);
2102  }
2103 
2104  ShowDropDownListAt(this, list, value, -1, wi_rect, COLOUR_ORANGE, true);
2105  }
2106  }
2107  this->SetDirty();
2108  } else if (x < SETTING_BUTTON_WIDTH) {
2109  this->SetDisplayedHelpText(pe);
2110  const SettingDescBase *sdb = &sd->desc;
2111  int32 oldvalue = value;
2112 
2113  switch (sdb->cmd) {
2114  case SDT_BOOLX: value ^= 1; break;
2115  case SDT_ONEOFMANY:
2116  case SDT_NUMX: {
2117  /* Add a dynamic step-size to the scroller. In a maximum of
2118  * 50-steps you should be able to get from min to max,
2119  * unless specified otherwise in the 'interval' variable
2120  * of the current setting. */
2121  uint32 step = (sdb->interval == 0) ? ((sdb->max - sdb->min) / 50) : sdb->interval;
2122  if (step == 0) step = 1;
2123 
2124  /* don't allow too fast scrolling */
2125  if ((this->flags & WF_TIMEOUT) && this->timeout_timer > 1) {
2126  _left_button_clicked = false;
2127  return;
2128  }
2129 
2130  /* Increase or decrease the value and clamp it to extremes */
2131  if (x >= SETTING_BUTTON_WIDTH / 2) {
2132  value += step;
2133  if (sdb->min < 0) {
2134  assert((int32)sdb->max >= 0);
2135  if (value > (int32)sdb->max) value = (int32)sdb->max;
2136  } else {
2137  if ((uint32)value > sdb->max) value = (int32)sdb->max;
2138  }
2139  if (value < sdb->min) value = sdb->min; // skip between "disabled" and minimum
2140  } else {
2141  value -= step;
2142  if (value < sdb->min) value = (sdb->flags & SGF_0ISDISABLED) ? 0 : sdb->min;
2143  }
2144 
2145  /* Set up scroller timeout for numeric values */
2146  if (value != oldvalue) {
2147  if (this->clicked_entry != NULL) { // Release previous buttons if any
2148  this->clicked_entry->SetButtons(0);
2149  }
2150  this->clicked_entry = pe;
2151  this->clicked_entry->SetButtons((x >= SETTING_BUTTON_WIDTH / 2) != (_current_text_dir == TD_RTL) ? SEF_RIGHT_DEPRESSED : SEF_LEFT_DEPRESSED);
2152  this->SetTimeout();
2153  _left_button_clicked = false;
2154  }
2155  break;
2156  }
2157 
2158  default: NOT_REACHED();
2159  }
2160 
2161  if (value != oldvalue) {
2162  if ((sd->desc.flags & SGF_PER_COMPANY) != 0) {
2163  SetCompanySetting(pe->index, value);
2164  } else {
2165  SetSettingValue(pe->index, value);
2166  }
2167  this->SetDirty();
2168  }
2169  } else {
2170  /* Only open editbox if clicked for the second time, and only for types where it is sensible for. */
2171  if (this->last_clicked == pe && sd->desc.cmd != SDT_BOOLX && !(sd->desc.flags & SGF_MULTISTRING)) {
2172  /* Show the correct currency-translated value */
2173  if (sd->desc.flags & SGF_CURRENCY) value *= _currency->rate;
2174 
2175  this->valuewindow_entry = pe;
2176  SetDParam(0, value);
2177  ShowQueryString(STR_JUST_INT, STR_CONFIG_SETTING_QUERY_CAPTION, 10, this, CS_NUMERAL, QSF_ENABLE_DEFAULT);
2178  }
2179  this->SetDisplayedHelpText(pe);
2180  }
2181  }
2182 
2183  virtual void OnTimeout()
2184  {
2185  if (this->clicked_entry != NULL) { // On timeout, release any depressed buttons
2186  this->clicked_entry->SetButtons(0);
2187  this->clicked_entry = NULL;
2188  this->SetDirty();
2189  }
2190  }
2191 
2192  virtual void OnQueryTextFinished(char *str)
2193  {
2194  /* The user pressed cancel */
2195  if (str == NULL) return;
2196 
2197  assert(this->valuewindow_entry != NULL);
2198  const SettingDesc *sd = this->valuewindow_entry->setting;
2199 
2200  int32 value;
2201  if (!StrEmpty(str)) {
2202  value = atoi(str);
2203 
2204  /* Save the correct currency-translated value */
2205  if (sd->desc.flags & SGF_CURRENCY) value /= _currency->rate;
2206  } else {
2207  value = (int32)(size_t)sd->desc.def;
2208  }
2209 
2210  if ((sd->desc.flags & SGF_PER_COMPANY) != 0) {
2211  SetCompanySetting(this->valuewindow_entry->index, value);
2212  } else {
2213  SetSettingValue(this->valuewindow_entry->index, value);
2214  }
2215  this->SetDirty();
2216  }
2217 
2218  virtual void OnDropdownSelect(int widget, int index)
2219  {
2220  switch (widget) {
2222  this->filter.mode = (RestrictionMode)index;
2223  if (this->filter.mode == RM_CHANGED_AGAINST_DEFAULT ||
2224  this->filter.mode == RM_CHANGED_AGAINST_NEW) {
2225 
2226  if (!this->manually_changed_folding) {
2227  /* Expand all when selecting 'changes'. Update the filter state first, in case it becomes less restrictive in some cases. */
2228  GetSettingsTree().UpdateFilterState(this->filter, false);
2230  }
2231  } else {
2232  /* Non-'changes' filter. Save as default. */
2234  }
2235  this->InvalidateData();
2236  break;
2237 
2238  case WID_GS_TYPE_DROPDOWN:
2239  this->filter.type = (SettingType)index;
2240  this->InvalidateData();
2241  break;
2242 
2243  default:
2244  if (widget < 0) {
2245  /* Deal with drop down boxes on the panel. */
2246  assert(this->valuedropdown_entry != NULL);
2247  const SettingDesc *sd = this->valuedropdown_entry->setting;
2248  assert(sd->desc.flags & SGF_MULTISTRING);
2249 
2250  if ((sd->desc.flags & SGF_PER_COMPANY) != 0) {
2251  SetCompanySetting(this->valuedropdown_entry->index, index);
2252  } else {
2253  SetSettingValue(this->valuedropdown_entry->index, index);
2254  }
2255 
2256  this->SetDirty();
2257  }
2258  break;
2259  }
2260  }
2261 
2262  virtual void OnDropdownClose(Point pt, int widget, int index, bool instant_close)
2263  {
2264  if (widget >= 0) {
2265  /* Normally the default implementation of OnDropdownClose() takes care of
2266  * a few things. We want that behaviour here too, but only for
2267  * "normal" dropdown boxes. The special dropdown boxes added for every
2268  * setting that needs one can't have this call. */
2269  Window::OnDropdownClose(pt, widget, index, instant_close);
2270  } else {
2271  /* We cannot raise the dropdown button just yet. OnClick needs some hint, whether
2272  * the same dropdown button was clicked again, and then not open the dropdown again.
2273  * So, we only remember that it was closed, and process it on the next OnPaint, which is
2274  * after OnClick. */
2275  assert(this->valuedropdown_entry != NULL);
2276  this->closing_dropdown = true;
2277  this->SetDirty();
2278  }
2279  }
2280 
2281  virtual void OnInvalidateData(int data = 0, bool gui_scope = true)
2282  {
2283  if (!gui_scope) return;
2284 
2285  /* Update which settings are to be visible. */
2286  RestrictionMode min_level = (this->filter.mode <= RM_ALL) ? this->filter.mode : RM_BASIC;
2287  this->filter.min_cat = min_level;
2288  this->filter.type_hides = false;
2289  GetSettingsTree().UpdateFilterState(this->filter, false);
2290 
2291  if (this->filter.string.IsEmpty()) {
2292  this->warn_missing = WHR_NONE;
2293  } else if (min_level < this->filter.min_cat) {
2294  this->warn_missing = this->filter.type_hides ? WHR_CATEGORY_TYPE : WHR_CATEGORY;
2295  } else {
2296  this->warn_missing = this->filter.type_hides ? WHR_TYPE : WHR_NONE;
2297  }
2298  this->vscroll->SetCount(GetSettingsTree().Length() + this->warn_lines);
2299 
2300  if (this->last_clicked != NULL && !GetSettingsTree().IsVisible(this->last_clicked)) {
2301  this->SetDisplayedHelpText(NULL);
2302  }
2303 
2304  bool all_folded = true;
2305  bool all_unfolded = true;
2306  GetSettingsTree().GetFoldingState(all_folded, all_unfolded);
2307  this->SetWidgetDisabledState(WID_GS_EXPAND_ALL, all_unfolded);
2308  this->SetWidgetDisabledState(WID_GS_COLLAPSE_ALL, all_folded);
2309  }
2310 
2311  virtual void OnEditboxChanged(int wid)
2312  {
2313  if (wid == WID_GS_FILTER) {
2314  this->filter.string.SetFilterTerm(this->filter_editbox.text.buf);
2315  if (!this->filter.string.IsEmpty() && !this->manually_changed_folding) {
2316  /* User never expanded/collapsed single pages and entered a filter term.
2317  * Expand everything, to save weird expand clicks, */
2319  }
2320  this->InvalidateData();
2321  }
2322  }
2323 
2324  virtual void OnResize()
2325  {
2326  this->vscroll->SetCapacityFromWidget(this, WID_GS_OPTIONSPANEL, SETTINGTREE_TOP_OFFSET + SETTINGTREE_BOTTOM_OFFSET);
2327  }
2328 };
2329 
2331 
2332 static const NWidgetPart _nested_settings_selection_widgets[] = {
2334  NWidget(WWT_CLOSEBOX, COLOUR_MAUVE),
2335  NWidget(WWT_CAPTION, COLOUR_MAUVE), SetDataTip(STR_CONFIG_SETTING_TREE_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
2336  NWidget(WWT_DEFSIZEBOX, COLOUR_MAUVE),
2337  EndContainer(),
2338  NWidget(WWT_PANEL, COLOUR_MAUVE),
2341  NWidget(WWT_TEXT, COLOUR_MAUVE, WID_GS_RESTRICT_CATEGORY), SetDataTip(STR_CONFIG_SETTING_RESTRICT_CATEGORY, STR_NULL),
2342  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),
2343  EndContainer(),
2345  NWidget(WWT_TEXT, COLOUR_MAUVE, WID_GS_RESTRICT_TYPE), SetDataTip(STR_CONFIG_SETTING_RESTRICT_TYPE, STR_NULL),
2346  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),
2347  EndContainer(),
2348  EndContainer(),
2351  NWidget(WWT_TEXT, COLOUR_MAUVE), SetFill(0, 1), SetDataTip(STR_CONFIG_SETTING_FILTER_TITLE, STR_NULL),
2352  NWidget(WWT_EDITBOX, COLOUR_MAUVE, WID_GS_FILTER), SetFill(1, 0), SetMinimalSize(50, 12), SetResize(1, 0),
2353  SetDataTip(STR_LIST_FILTER_OSKTITLE, STR_LIST_FILTER_TOOLTIP),
2354  EndContainer(),
2355  EndContainer(),
2358  NWidget(NWID_VSCROLLBAR, COLOUR_MAUVE, WID_GS_SCROLLBAR),
2359  EndContainer(),
2360  NWidget(WWT_PANEL, COLOUR_MAUVE), SetMinimalSize(400, 40),
2361  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_GS_HELP_TEXT), SetMinimalSize(300, 25), SetFill(1, 1), SetResize(1, 0),
2363  EndContainer(),
2365  NWidget(WWT_PUSHTXTBTN, COLOUR_MAUVE, WID_GS_EXPAND_ALL), SetDataTip(STR_CONFIG_SETTING_EXPAND_ALL, STR_NULL),
2366  NWidget(WWT_PUSHTXTBTN, COLOUR_MAUVE, WID_GS_COLLAPSE_ALL), SetDataTip(STR_CONFIG_SETTING_COLLAPSE_ALL, STR_NULL),
2367  NWidget(WWT_PANEL, COLOUR_MAUVE), SetFill(1, 0), SetResize(1, 0),
2368  EndContainer(),
2369  NWidget(WWT_RESIZEBOX, COLOUR_MAUVE),
2370  EndContainer(),
2371 };
2372 
2373 static WindowDesc _settings_selection_desc(
2374  WDP_CENTER, "settings", 510, 450,
2376  0,
2377  _nested_settings_selection_widgets, lengthof(_nested_settings_selection_widgets)
2378 );
2379 
2382 {
2384  new GameSettingsWindow(&_settings_selection_desc);
2385 }
2386 
2387 
2397 void DrawArrowButtons(int x, int y, Colours button_colour, byte state, bool clickable_left, bool clickable_right)
2398 {
2399  int colour = _colour_gradient[button_colour][2];
2400  Dimension dim = NWidgetScrollbar::GetHorizontalDimension();
2401 
2402  DrawFrameRect(x, y, x + dim.width - 1, y + dim.height - 1, button_colour, (state == 1) ? FR_LOWERED : FR_NONE);
2403  DrawFrameRect(x + dim.width, y, x + dim.width + dim.width - 1, y + dim.height - 1, button_colour, (state == 2) ? FR_LOWERED : FR_NONE);
2404  DrawSprite(SPR_ARROW_LEFT, PAL_NONE, x + WD_IMGBTN_LEFT, y + WD_IMGBTN_TOP);
2405  DrawSprite(SPR_ARROW_RIGHT, PAL_NONE, x + WD_IMGBTN_LEFT + dim.width, y + WD_IMGBTN_TOP);
2406 
2407  /* Grey out the buttons that aren't clickable */
2408  bool rtl = _current_text_dir == TD_RTL;
2409  if (rtl ? !clickable_right : !clickable_left) {
2410  GfxFillRect(x + 1, y, x + dim.width - 1, y + dim.height - 2, colour, FILLRECT_CHECKER);
2411  }
2412  if (rtl ? !clickable_left : !clickable_right) {
2413  GfxFillRect(x + dim.width + 1, y, x + dim.width + dim.width - 1, y + dim.height - 2, colour, FILLRECT_CHECKER);
2414  }
2415 }
2416 
2425 void DrawDropDownButton(int x, int y, Colours button_colour, bool state, bool clickable)
2426 {
2427  int colour = _colour_gradient[button_colour][2];
2428 
2429  DrawFrameRect(x, y, x + SETTING_BUTTON_WIDTH - 1, y + SETTING_BUTTON_HEIGHT - 1, button_colour, state ? FR_LOWERED : FR_NONE);
2430  DrawSprite(SPR_ARROW_DOWN, PAL_NONE, x + (SETTING_BUTTON_WIDTH - NWidgetScrollbar::GetVerticalDimension().width) / 2 + state, y + 2 + state);
2431 
2432  if (!clickable) {
2433  GfxFillRect(x + 1, y, x + SETTING_BUTTON_WIDTH - 1, y + SETTING_BUTTON_HEIGHT - 2, colour, FILLRECT_CHECKER);
2434  }
2435 }
2436 
2444 void DrawBoolButton(int x, int y, bool state, bool clickable)
2445 {
2446  static const Colours _bool_ctabs[2][2] = {{COLOUR_CREAM, COLOUR_RED}, {COLOUR_DARK_GREEN, COLOUR_GREEN}};
2447  DrawFrameRect(x, y, x + SETTING_BUTTON_WIDTH - 1, y + SETTING_BUTTON_HEIGHT - 1, _bool_ctabs[state][clickable], state ? FR_LOWERED : FR_NONE);
2448 }
2449 
2451  int query_widget;
2452 
2453  CustomCurrencyWindow(WindowDesc *desc) : Window(desc)
2454  {
2455  this->InitNested();
2456 
2457  SetButtonState();
2458  }
2459 
2460  void SetButtonState()
2461  {
2462  this->SetWidgetDisabledState(WID_CC_RATE_DOWN, _custom_currency.rate == 1);
2463  this->SetWidgetDisabledState(WID_CC_RATE_UP, _custom_currency.rate == UINT16_MAX);
2464  this->SetWidgetDisabledState(WID_CC_YEAR_DOWN, _custom_currency.to_euro == CF_NOEURO);
2465  this->SetWidgetDisabledState(WID_CC_YEAR_UP, _custom_currency.to_euro == MAX_YEAR);
2466  }
2467 
2468  virtual void SetStringParameters(int widget) const
2469  {
2470  switch (widget) {
2471  case WID_CC_RATE: SetDParam(0, 1); SetDParam(1, 1); break;
2472  case WID_CC_SEPARATOR: SetDParamStr(0, _custom_currency.separator); break;
2473  case WID_CC_PREFIX: SetDParamStr(0, _custom_currency.prefix); break;
2474  case WID_CC_SUFFIX: SetDParamStr(0, _custom_currency.suffix); break;
2475  case WID_CC_YEAR:
2476  SetDParam(0, (_custom_currency.to_euro != CF_NOEURO) ? STR_CURRENCY_SWITCH_TO_EURO : STR_CURRENCY_SWITCH_TO_EURO_NEVER);
2477  SetDParam(1, _custom_currency.to_euro);
2478  break;
2479 
2480  case WID_CC_PREVIEW:
2481  SetDParam(0, 10000);
2482  break;
2483  }
2484  }
2485 
2486  virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
2487  {
2488  switch (widget) {
2489  /* Set the appropriate width for the edit 'buttons' */
2490  case WID_CC_SEPARATOR_EDIT:
2491  case WID_CC_PREFIX_EDIT:
2492  case WID_CC_SUFFIX_EDIT:
2493  size->width = this->GetWidget<NWidgetBase>(WID_CC_RATE_DOWN)->smallest_x + this->GetWidget<NWidgetBase>(WID_CC_RATE_UP)->smallest_x;
2494  break;
2495 
2496  /* Make sure the window is wide enough for the widest exchange rate */
2497  case WID_CC_RATE:
2498  SetDParam(0, 1);
2499  SetDParam(1, INT32_MAX);
2500  *size = GetStringBoundingBox(STR_CURRENCY_EXCHANGE_RATE);
2501  break;
2502  }
2503  }
2504 
2505  virtual void OnClick(Point pt, int widget, int click_count)
2506  {
2507  int line = 0;
2508  int len = 0;
2509  StringID str = 0;
2510  CharSetFilter afilter = CS_ALPHANUMERAL;
2511 
2512  switch (widget) {
2513  case WID_CC_RATE_DOWN:
2514  if (_custom_currency.rate > 1) _custom_currency.rate--;
2515  if (_custom_currency.rate == 1) this->DisableWidget(WID_CC_RATE_DOWN);
2517  break;
2518 
2519  case WID_CC_RATE_UP:
2520  if (_custom_currency.rate < UINT16_MAX) _custom_currency.rate++;
2521  if (_custom_currency.rate == UINT16_MAX) this->DisableWidget(WID_CC_RATE_UP);
2523  break;
2524 
2525  case WID_CC_RATE:
2526  SetDParam(0, _custom_currency.rate);
2527  str = STR_JUST_INT;
2528  len = 5;
2529  line = WID_CC_RATE;
2530  afilter = CS_NUMERAL;
2531  break;
2532 
2533  case WID_CC_SEPARATOR_EDIT:
2534  case WID_CC_SEPARATOR:
2535  SetDParamStr(0, _custom_currency.separator);
2536  str = STR_JUST_RAW_STRING;
2537  len = 1;
2538  line = WID_CC_SEPARATOR;
2539  break;
2540 
2541  case WID_CC_PREFIX_EDIT:
2542  case WID_CC_PREFIX:
2543  SetDParamStr(0, _custom_currency.prefix);
2544  str = STR_JUST_RAW_STRING;
2545  len = 12;
2546  line = WID_CC_PREFIX;
2547  break;
2548 
2549  case WID_CC_SUFFIX_EDIT:
2550  case WID_CC_SUFFIX:
2551  SetDParamStr(0, _custom_currency.suffix);
2552  str = STR_JUST_RAW_STRING;
2553  len = 12;
2554  line = WID_CC_SUFFIX;
2555  break;
2556 
2557  case WID_CC_YEAR_DOWN:
2558  _custom_currency.to_euro = (_custom_currency.to_euro <= 2000) ? CF_NOEURO : _custom_currency.to_euro - 1;
2559  if (_custom_currency.to_euro == CF_NOEURO) this->DisableWidget(WID_CC_YEAR_DOWN);
2561  break;
2562 
2563  case WID_CC_YEAR_UP:
2564  _custom_currency.to_euro = Clamp(_custom_currency.to_euro + 1, 2000, MAX_YEAR);
2565  if (_custom_currency.to_euro == MAX_YEAR) this->DisableWidget(WID_CC_YEAR_UP);
2567  break;
2568 
2569  case WID_CC_YEAR:
2570  SetDParam(0, _custom_currency.to_euro);
2571  str = STR_JUST_INT;
2572  len = 7;
2573  line = WID_CC_YEAR;
2574  afilter = CS_NUMERAL;
2575  break;
2576  }
2577 
2578  if (len != 0) {
2579  this->query_widget = line;
2580  ShowQueryString(str, STR_CURRENCY_CHANGE_PARAMETER, len + 1, this, afilter, QSF_NONE);
2581  }
2582 
2583  this->SetTimeout();
2584  this->SetDirty();
2585  }
2586 
2587  virtual void OnQueryTextFinished(char *str)
2588  {
2589  if (str == NULL) return;
2590 
2591  switch (this->query_widget) {
2592  case WID_CC_RATE:
2593  _custom_currency.rate = Clamp(atoi(str), 1, UINT16_MAX);
2594  break;
2595 
2596  case WID_CC_SEPARATOR: // Thousands separator
2597  strecpy(_custom_currency.separator, str, lastof(_custom_currency.separator));
2598  break;
2599 
2600  case WID_CC_PREFIX:
2601  strecpy(_custom_currency.prefix, str, lastof(_custom_currency.prefix));
2602  break;
2603 
2604  case WID_CC_SUFFIX:
2605  strecpy(_custom_currency.suffix, str, lastof(_custom_currency.suffix));
2606  break;
2607 
2608  case WID_CC_YEAR: { // Year to switch to euro
2609  int val = atoi(str);
2610 
2611  _custom_currency.to_euro = (val < 2000 ? CF_NOEURO : min(val, MAX_YEAR));
2612  break;
2613  }
2614  }
2616  SetButtonState();
2617  }
2618 
2619  virtual void OnTimeout()
2620  {
2621  this->SetDirty();
2622  }
2623 };
2624 
2625 static const NWidgetPart _nested_cust_currency_widgets[] = {
2627  NWidget(WWT_CLOSEBOX, COLOUR_GREY),
2628  NWidget(WWT_CAPTION, COLOUR_GREY), SetDataTip(STR_CURRENCY_WINDOW, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
2629  EndContainer(),
2630  NWidget(WWT_PANEL, COLOUR_GREY),
2632  NWidget(NWID_HORIZONTAL), SetPIP(10, 0, 5),
2633  NWidget(WWT_PUSHARROWBTN, COLOUR_YELLOW, WID_CC_RATE_DOWN), SetDataTip(AWV_DECREASE, STR_CURRENCY_DECREASE_EXCHANGE_RATE_TOOLTIP),
2634  NWidget(WWT_PUSHARROWBTN, COLOUR_YELLOW, WID_CC_RATE_UP), SetDataTip(AWV_INCREASE, STR_CURRENCY_INCREASE_EXCHANGE_RATE_TOOLTIP),
2636  NWidget(WWT_TEXT, COLOUR_BLUE, WID_CC_RATE), SetDataTip(STR_CURRENCY_EXCHANGE_RATE, STR_CURRENCY_SET_EXCHANGE_RATE_TOOLTIP), SetFill(1, 0),
2637  EndContainer(),
2638  NWidget(NWID_HORIZONTAL), SetPIP(10, 0, 5),
2639  NWidget(WWT_PUSHBTN, COLOUR_DARK_BLUE, WID_CC_SEPARATOR_EDIT), SetDataTip(0x0, STR_CURRENCY_SET_CUSTOM_CURRENCY_SEPARATOR_TOOLTIP), SetFill(0, 1),
2641  NWidget(WWT_TEXT, COLOUR_BLUE, WID_CC_SEPARATOR), SetDataTip(STR_CURRENCY_SEPARATOR, STR_CURRENCY_SET_CUSTOM_CURRENCY_SEPARATOR_TOOLTIP), SetFill(1, 0),
2642  EndContainer(),
2643  NWidget(NWID_HORIZONTAL), SetPIP(10, 0, 5),
2644  NWidget(WWT_PUSHBTN, COLOUR_DARK_BLUE, WID_CC_PREFIX_EDIT), SetDataTip(0x0, STR_CURRENCY_SET_CUSTOM_CURRENCY_PREFIX_TOOLTIP), SetFill(0, 1),
2646  NWidget(WWT_TEXT, COLOUR_BLUE, WID_CC_PREFIX), SetDataTip(STR_CURRENCY_PREFIX, STR_CURRENCY_SET_CUSTOM_CURRENCY_PREFIX_TOOLTIP), SetFill(1, 0),
2647  EndContainer(),
2648  NWidget(NWID_HORIZONTAL), SetPIP(10, 0, 5),
2649  NWidget(WWT_PUSHBTN, COLOUR_DARK_BLUE, WID_CC_SUFFIX_EDIT), SetDataTip(0x0, STR_CURRENCY_SET_CUSTOM_CURRENCY_SUFFIX_TOOLTIP), SetFill(0, 1),
2651  NWidget(WWT_TEXT, COLOUR_BLUE, WID_CC_SUFFIX), SetDataTip(STR_CURRENCY_SUFFIX, STR_CURRENCY_SET_CUSTOM_CURRENCY_SUFFIX_TOOLTIP), SetFill(1, 0),
2652  EndContainer(),
2653  NWidget(NWID_HORIZONTAL), SetPIP(10, 0, 5),
2654  NWidget(WWT_PUSHARROWBTN, COLOUR_YELLOW, WID_CC_YEAR_DOWN), SetDataTip(AWV_DECREASE, STR_CURRENCY_DECREASE_CUSTOM_CURRENCY_TO_EURO_TOOLTIP),
2655  NWidget(WWT_PUSHARROWBTN, COLOUR_YELLOW, WID_CC_YEAR_UP), SetDataTip(AWV_INCREASE, STR_CURRENCY_INCREASE_CUSTOM_CURRENCY_TO_EURO_TOOLTIP),
2657  NWidget(WWT_TEXT, COLOUR_BLUE, WID_CC_YEAR), SetDataTip(STR_JUST_STRING, STR_CURRENCY_SET_CUSTOM_CURRENCY_TO_EURO_TOOLTIP), SetFill(1, 0),
2658  EndContainer(),
2659  EndContainer(),
2660  NWidget(WWT_LABEL, COLOUR_BLUE, WID_CC_PREVIEW),
2661  SetDataTip(STR_CURRENCY_PREVIEW, STR_CURRENCY_CUSTOM_CURRENCY_PREVIEW_TOOLTIP), SetPadding(15, 1, 18, 2),
2662  EndContainer(),
2663 };
2664 
2665 static WindowDesc _cust_currency_desc(
2666  WDP_CENTER, NULL, 0, 0,
2668  0,
2669  _nested_cust_currency_widgets, lengthof(_nested_cust_currency_widgets)
2670 );
2671 
2673 static void ShowCustCurrency()
2674 {
2676  new CustomCurrencyWindow(&_cust_currency_desc);
2677 }
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:2097
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:1848
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:3179
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
void ChangeMusicSet(int index)
Change the configured music set and reset playback.
Definition: music_gui.cpp:435
static Titem * Get(size_t index)
Returns Titem with given index.
Definition: pool_type.hpp:246
Switch to game intro menu.
Definition: openttd.h:32
virtual void UnFoldAll()
Recursively open all (filtered) folds of sub-pages.
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:70
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:1064
Use to select a base music set.
Generic functions for replacing base data (graphics, sounds).
fluid_settings_t * settings
FluidSynth settings handle.
Definition: fluidsynth.cpp:22
Show only settings which are different compared to the user&#39;s new game setting values.
Up button.
#define SETBITS(x, y)
Sets several bits in a variable.
const LanguageMetadata * _current_language
The currently loaded language.
Definition: strings.cpp: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:733
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:1809
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:1825
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:1838
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:489
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:219
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:1131
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:2058
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:165
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:310
char * stredup(const char *s, const char *last)
Create a duplicate of the given string.
Definition: string.cpp:138
Window for displaying the textfile of a BaseSet.
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:63
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:1156
virtual uint Length() const
Return number of rows needed to display the (filtered) entry.
Data structure describing one page of settings in the settings window.
#define SETTING_BUTTON_WIDTH
Width of setting buttons.
Definition: settings_gui.h:19
CharSetFilter
Valid filter types for IsValidChar.
Definition: string_type.h: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:1970
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:965
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:1143
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:813
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:2002
Open base GRF readme, changelog (+1) or license (+2).
void ReInitAllWindows()
Re-initialize all windows.
Definition: window.cpp:3403
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:1929
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:487
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:118
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:283
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:21
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:3220
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:733
(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:54