OpenTTD
settings_gui.cpp
Go to the documentation of this file.
1 /* $Id$ */
2 
3 /*
4  * This file is part of OpenTTD.
5  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
6  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
8  */
9 
12 #include "stdafx.h"
13 #include "currency.h"
14 #include "error.h"
15 #include "settings_gui.h"
16 #include "textbuf_gui.h"
17 #include "command_func.h"
18 #include "network/network.h"
19 #include "town.h"
20 #include "settings_internal.h"
21 #include "newgrf_townname.h"
22 #include "strings_func.h"
23 #include "window_func.h"
24 #include "string_func.h"
25 #include "widgets/dropdown_type.h"
26 #include "widgets/dropdown_func.h"
27 #include "highscore.h"
28 #include "base_media_base.h"
29 #include "company_base.h"
30 #include "company_func.h"
31 #include "viewport_func.h"
32 #include "core/geometry_func.hpp"
33 #include "ai/ai.hpp"
34 #include "blitter/factory.hpp"
35 #include "language.h"
36 #include "textfile_gui.h"
37 #include "stringfilter_type.h"
38 #include "querystring_gui.h"
39 #include "fontcache.h"
40 
41 #include <vector>
42 
43 #include "safeguards.h"
44 
45 
46 static const StringID _driveside_dropdown[] = {
47  STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_LEFT,
48  STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_RIGHT,
50 };
51 
52 static const StringID _autosave_dropdown[] = {
53  STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_OFF,
54  STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_1_MONTH,
55  STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_3_MONTHS,
56  STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_6_MONTHS,
57  STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_12_MONTHS,
59 };
60 
61 static const StringID _gui_zoom_dropdown[] = {
62  STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_NORMAL,
63  STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_2X_ZOOM,
64  STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_4X_ZOOM,
66 };
67 
68 static const StringID _font_zoom_dropdown[] = {
69  STR_GAME_OPTIONS_FONT_ZOOM_DROPDOWN_NORMAL,
70  STR_GAME_OPTIONS_FONT_ZOOM_DROPDOWN_2X_ZOOM,
71  STR_GAME_OPTIONS_FONT_ZOOM_DROPDOWN_4X_ZOOM,
73 };
74 
75 int _nb_orig_names = SPECSTR_TOWNNAME_LAST - SPECSTR_TOWNNAME_START + 1;
76 static StringID *_grf_names = NULL;
77 static int _nb_grf_names = 0;
78 
80 
81 static const void *ResolveVariableAddress(const GameSettings *settings_ptr, const SettingDesc *sd);
82 
85 {
87  _grf_names = GetGRFTownNameList();
88  _nb_grf_names = 0;
89  for (StringID *s = _grf_names; *s != INVALID_STRING_ID; s++) _nb_grf_names++;
90 }
91 
97 static inline StringID TownName(int town_name)
98 {
99  if (town_name < _nb_orig_names) return STR_GAME_OPTIONS_TOWN_NAME_ORIGINAL_ENGLISH + town_name;
100  town_name -= _nb_orig_names;
101  if (town_name < _nb_grf_names) return _grf_names[town_name];
102  return STR_UNDEFINED;
103 }
104 
109 static int GetCurRes()
110 {
111  int i;
112 
113  for (i = 0; i != _num_resolutions; i++) {
114  if ((int)_resolutions[i].width == _screen.width &&
115  (int)_resolutions[i].height == _screen.height) {
116  break;
117  }
118  }
119  return i;
120 }
121 
122 static void ShowCustCurrency();
123 
124 template <class T>
125 static DropDownList *BuildSetDropDownList(int *selected_index, bool allow_selection)
126 {
127  int n = T::GetNumSets();
128  *selected_index = T::GetIndexOfUsedSet();
129 
130  DropDownList *list = new DropDownList();
131  for (int i = 0; i < n; i++) {
132  *list->Append() = new DropDownListCharStringItem(T::GetSet(i)->name, i, !allow_selection && (*selected_index != i));
133  }
134 
135  return list;
136 }
137 
138 DropDownList *BuildMusicSetDropDownList(int *selected_index)
139 {
140  return BuildSetDropDownList<BaseMusic>(selected_index, true);
141 }
142 
144 template <class TBaseSet>
146  const TBaseSet* baseset;
148 
149  BaseSetTextfileWindow(TextfileType file_type, const TBaseSet* baseset, StringID content_type) : TextfileWindow(file_type), baseset(baseset), content_type(content_type)
150  {
151  const char *textfile = this->baseset->GetTextfile(file_type);
152  this->LoadTextfile(textfile, BASESET_DIR);
153  }
154 
155  /* virtual */ void SetStringParameters(int widget) const
156  {
157  if (widget == WID_TF_CAPTION) {
158  SetDParam(0, content_type);
159  SetDParamStr(1, this->baseset->name);
160  }
161  }
162 };
163 
170 template <class TBaseSet>
172 {
173  DeleteWindowById(WC_TEXTFILE, file_type);
175 }
176 
178  GameSettings *opt;
179  bool reload;
180 
181  GameOptionsWindow(WindowDesc *desc) : Window(desc)
182  {
183  this->opt = &GetGameSettings();
184  this->reload = false;
185 
187  this->OnInvalidateData(0);
188  }
189 
191  {
194  if (this->reload) _switch_mode = SM_MENU;
195  }
196 
203  DropDownList *BuildDropDownList(int widget, int *selected_index) const
204  {
205  DropDownList *list = NULL;
206  switch (widget) {
207  case WID_GO_CURRENCY_DROPDOWN: { // Setup currencies dropdown
208  list = new DropDownList();
209  *selected_index = this->opt->locale.currency;
210  StringID *items = BuildCurrencyDropdown();
211  uint64 disabled = _game_mode == GM_MENU ? 0LL : ~GetMaskOfAllowedCurrencies();
212 
213  /* Add non-custom currencies; sorted naturally */
214  for (uint i = 0; i < CURRENCY_END; items++, i++) {
215  if (i == CURRENCY_CUSTOM) continue;
216  *list->Append() = new DropDownListStringItem(*items, i, HasBit(disabled, i));
217  }
219 
220  /* Append custom currency at the end */
221  *list->Append() = new DropDownListItem(-1, false); // separator line
222  *list->Append() = new DropDownListStringItem(STR_GAME_OPTIONS_CURRENCY_CUSTOM, CURRENCY_CUSTOM, HasBit(disabled, CURRENCY_CUSTOM));
223  break;
224  }
225 
226  case WID_GO_ROADSIDE_DROPDOWN: { // Setup road-side dropdown
227  list = new DropDownList();
228  *selected_index = this->opt->vehicle.road_side;
229  const StringID *items = _driveside_dropdown;
230  uint disabled = 0;
231 
232  /* You can only change the drive side if you are in the menu or ingame with
233  * no vehicles present. In a networking game only the server can change it */
234  extern bool RoadVehiclesAreBuilt();
235  if ((_game_mode != GM_MENU && RoadVehiclesAreBuilt()) || (_networking && !_network_server)) {
236  disabled = ~(1 << this->opt->vehicle.road_side); // disable the other value
237  }
238 
239  for (uint i = 0; *items != INVALID_STRING_ID; items++, i++) {
240  *list->Append() = new DropDownListStringItem(*items, i, HasBit(disabled, i));
241  }
242  break;
243  }
244 
245  case WID_GO_TOWNNAME_DROPDOWN: { // Setup townname dropdown
246  list = new DropDownList();
247  *selected_index = this->opt->game_creation.town_name;
248 
249  int enabled_item = (_game_mode == GM_MENU || Town::GetNumItems() == 0) ? -1 : *selected_index;
250 
251  /* Add and sort newgrf townnames generators */
252  for (int i = 0; i < _nb_grf_names; i++) {
253  int result = _nb_orig_names + i;
254  *list->Append() = new DropDownListStringItem(_grf_names[i], result, enabled_item != result && enabled_item >= 0);
255  }
257 
258  int newgrf_size = list->Length();
259  /* Insert newgrf_names at the top of the list */
260  if (newgrf_size > 0) {
261  *list->Append() = new DropDownListItem(-1, false); // separator line
262  newgrf_size++;
263  }
264 
265  /* Add and sort original townnames generators */
266  for (int i = 0; i < _nb_orig_names; i++) {
267  *list->Append() = new DropDownListStringItem(STR_GAME_OPTIONS_TOWN_NAME_ORIGINAL_ENGLISH + i, i, enabled_item != i && enabled_item >= 0);
268  }
269  QSortT(list->Begin() + newgrf_size, list->Length() - newgrf_size, DropDownListStringItem::NatSortFunc);
270  break;
271  }
272 
273  case WID_GO_AUTOSAVE_DROPDOWN: { // Setup autosave dropdown
274  list = new DropDownList();
275  *selected_index = _settings_client.gui.autosave;
276  const StringID *items = _autosave_dropdown;
277  for (uint i = 0; *items != INVALID_STRING_ID; items++, i++) {
278  *list->Append() = new DropDownListStringItem(*items, i, false);
279  }
280  break;
281  }
282 
283  case WID_GO_LANG_DROPDOWN: { // Setup interface language dropdown
284  list = new DropDownList();
285  for (uint i = 0; i < _languages.Length(); i++) {
286  if (&_languages[i] == _current_language) *selected_index = i;
287  *list->Append() = new DropDownListStringItem(SPECSTR_LANGUAGE_START + i, i, false);
288  }
290  break;
291  }
292 
293  case WID_GO_RESOLUTION_DROPDOWN: // Setup resolution dropdown
294  if (_num_resolutions == 0) break;
295 
296  list = new DropDownList();
297  *selected_index = GetCurRes();
298  for (int i = 0; i < _num_resolutions; i++) {
299  *list->Append() = new DropDownListStringItem(SPECSTR_RESOLUTION_START + i, i, false);
300  }
301  break;
302 
304  list = new DropDownList();
305  *selected_index = ZOOM_LVL_OUT_4X - _gui_zoom;
306  const StringID *items = _gui_zoom_dropdown;
307  for (int i = 0; *items != INVALID_STRING_ID; items++, i++) {
309  }
310  break;
311  }
312 
314  list = new DropDownList();
315  *selected_index = ZOOM_LVL_OUT_4X - _font_zoom;
316  const StringID *items = _font_zoom_dropdown;
317  for (int i = 0; *items != INVALID_STRING_ID; items++, i++) {
318  *list->Append() = new DropDownListStringItem(*items, i, false);
319  }
320  break;
321  }
322 
324  list = BuildSetDropDownList<BaseGraphics>(selected_index, (_game_mode == GM_MENU));
325  break;
326 
328  list = BuildSetDropDownList<BaseSounds>(selected_index, (_game_mode == GM_MENU));
329  break;
330 
332  list = BuildMusicSetDropDownList(selected_index);
333  break;
334 
335  default:
336  return NULL;
337  }
338 
339  return list;
340  }
341 
342  virtual void SetStringParameters(int widget) const
343  {
344  switch (widget) {
345  case WID_GO_CURRENCY_DROPDOWN: SetDParam(0, _currency_specs[this->opt->locale.currency].name); break;
346  case WID_GO_ROADSIDE_DROPDOWN: SetDParam(0, STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_LEFT + this->opt->vehicle.road_side); break;
348  case WID_GO_AUTOSAVE_DROPDOWN: SetDParam(0, _autosave_dropdown[_settings_client.gui.autosave]); break;
350  case WID_GO_RESOLUTION_DROPDOWN: SetDParam(0, GetCurRes() == _num_resolutions ? STR_GAME_OPTIONS_RESOLUTION_OTHER : SPECSTR_RESOLUTION_START + GetCurRes()); break;
351  case WID_GO_GUI_ZOOM_DROPDOWN: SetDParam(0, _gui_zoom_dropdown[ZOOM_LVL_OUT_4X - _gui_zoom]); break;
352  case WID_GO_FONT_ZOOM_DROPDOWN: SetDParam(0, _font_zoom_dropdown[ZOOM_LVL_OUT_4X - _font_zoom]); break;
354  case WID_GO_BASE_GRF_STATUS: SetDParam(0, BaseGraphics::GetUsedSet()->GetNumInvalid()); break;
357  case WID_GO_BASE_MUSIC_STATUS: SetDParam(0, BaseMusic::GetUsedSet()->GetNumInvalid()); break;
358  }
359  }
360 
361  virtual void DrawWidget(const Rect &r, int widget) const
362  {
363  switch (widget) {
366  DrawStringMultiLine(r.left, r.right, r.top, UINT16_MAX, STR_BLACK_RAW_STRING);
367  break;
368 
371  DrawStringMultiLine(r.left, r.right, r.top, UINT16_MAX, STR_BLACK_RAW_STRING);
372  break;
373 
376  DrawStringMultiLine(r.left, r.right, r.top, UINT16_MAX, STR_BLACK_RAW_STRING);
377  break;
378  }
379  }
380 
381  virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
382  {
383  switch (widget) {
385  /* Find the biggest description for the default size. */
386  for (int i = 0; i < BaseGraphics::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 < BaseGraphics::GetNumSets(); i++) {
395  uint invalid_files = BaseGraphics::GetSet(i)->GetNumInvalid();
396  if (invalid_files == 0) continue;
397 
398  SetDParam(0, invalid_files);
399  *size = maxdim(*size, GetStringBoundingBox(STR_GAME_OPTIONS_BASE_GRF_STATUS));
400  }
401  break;
402 
404  /* Find the biggest description for the default size. */
405  for (int i = 0; i < BaseSounds::GetNumSets(); i++) {
407  size->height = max(size->height, (uint)GetStringHeight(STR_BLACK_RAW_STRING, size->width));
408  }
409  break;
410 
412  /* Find the biggest description for the default size. */
413  for (int i = 0; i < BaseMusic::GetNumSets(); i++) {
414  SetDParamStr(0, BaseMusic::GetSet(i)->GetDescription(GetCurrentLanguageIsoCode()));
415  size->height = max(size->height, (uint)GetStringHeight(STR_BLACK_RAW_STRING, size->width));
416  }
417  break;
418 
420  /* Find the biggest description for the default size. */
421  for (int i = 0; i < BaseMusic::GetNumSets(); i++) {
422  uint invalid_files = BaseMusic::GetSet(i)->GetNumInvalid();
423  if (invalid_files == 0) continue;
424 
425  SetDParam(0, invalid_files);
426  *size = maxdim(*size, GetStringBoundingBox(STR_GAME_OPTIONS_BASE_MUSIC_STATUS));
427  }
428  break;
429 
430  default: {
431  int selected;
432  DropDownList *list = this->BuildDropDownList(widget, &selected);
433  if (list != NULL) {
434  /* Find the biggest item for the default size. */
435  for (const DropDownListItem * const *it = list->Begin(); it != list->End(); it++) {
436  Dimension string_dim;
437  int width = (*it)->Width();
438  string_dim.width = width + padding.width;
439  string_dim.height = (*it)->Height(width) + padding.height;
440  *size = maxdim(*size, string_dim);
441  }
442  delete list;
443  }
444  }
445  }
446  }
447 
448  virtual void OnClick(Point pt, int widget, int click_count)
449  {
450  if (widget >= WID_GO_BASE_GRF_TEXTFILE && widget < WID_GO_BASE_GRF_TEXTFILE + TFT_END) {
451  if (BaseGraphics::GetUsedSet() == NULL) return;
452 
453  ShowBaseSetTextfileWindow((TextfileType)(widget - WID_GO_BASE_GRF_TEXTFILE), BaseGraphics::GetUsedSet(), STR_CONTENT_TYPE_BASE_GRAPHICS);
454  return;
455  }
456  if (widget >= WID_GO_BASE_SFX_TEXTFILE && widget < WID_GO_BASE_SFX_TEXTFILE + TFT_END) {
457  if (BaseSounds::GetUsedSet() == NULL) return;
458 
459  ShowBaseSetTextfileWindow((TextfileType)(widget - WID_GO_BASE_SFX_TEXTFILE), BaseSounds::GetUsedSet(), STR_CONTENT_TYPE_BASE_SOUNDS);
460  return;
461  }
462  if (widget >= WID_GO_BASE_MUSIC_TEXTFILE && widget < WID_GO_BASE_MUSIC_TEXTFILE + TFT_END) {
463  if (BaseMusic::GetUsedSet() == NULL) return;
464 
465  ShowBaseSetTextfileWindow((TextfileType)(widget - WID_GO_BASE_MUSIC_TEXTFILE), BaseMusic::GetUsedSet(), STR_CONTENT_TYPE_BASE_MUSIC);
466  return;
467  }
468  switch (widget) {
469  case WID_GO_FULLSCREEN_BUTTON: // Click fullscreen on/off
470  /* try to toggle full-screen on/off */
471  if (!ToggleFullScreen(!_fullscreen)) {
472  ShowErrorMessage(STR_ERROR_FULLSCREEN_FAILED, INVALID_STRING_ID, WL_ERROR);
473  }
475  this->SetDirty();
476  break;
477 
478  default: {
479  int selected;
480  DropDownList *list = this->BuildDropDownList(widget, &selected);
481  if (list != NULL) {
482  ShowDropDownList(this, list, selected, widget);
483  } else {
484  if (widget == WID_GO_RESOLUTION_DROPDOWN) ShowErrorMessage(STR_ERROR_RESOLUTION_LIST_FAILED, INVALID_STRING_ID, WL_ERROR);
485  }
486  break;
487  }
488  }
489  }
490 
496  template <class T>
497  void SetMediaSet(int index)
498  {
499  if (_game_mode == GM_MENU) {
500  const char *name = T::GetSet(index)->name;
501 
502  free(T::ini_set);
503  T::ini_set = stredup(name);
504 
505  T::SetSet(name);
506  this->reload = true;
507  this->InvalidateData();
508  }
509  }
510 
511  virtual void OnDropdownSelect(int widget, int index)
512  {
513  switch (widget) {
514  case WID_GO_CURRENCY_DROPDOWN: // Currency
515  if (index == CURRENCY_CUSTOM) ShowCustCurrency();
516  this->opt->locale.currency = index;
518  break;
519 
520  case WID_GO_ROADSIDE_DROPDOWN: // Road side
521  if (this->opt->vehicle.road_side != index) { // only change if setting changed
522  uint i;
523  if (GetSettingFromName("vehicle.road_side", &i) == NULL) NOT_REACHED();
524  SetSettingValue(i, index);
526  }
527  break;
528 
529  case WID_GO_TOWNNAME_DROPDOWN: // Town names
530  if (_game_mode == GM_MENU || Town::GetNumItems() == 0) {
531  this->opt->game_creation.town_name = index;
533  }
534  break;
535 
536  case WID_GO_AUTOSAVE_DROPDOWN: // Autosave options
537  _settings_client.gui.autosave = index;
538  this->SetDirty();
539  break;
540 
541  case WID_GO_LANG_DROPDOWN: // Change interface language
542  ReadLanguagePack(&_languages[index]);
547  break;
548 
549  case WID_GO_RESOLUTION_DROPDOWN: // Change resolution
550  if (index < _num_resolutions && ChangeResInGame(_resolutions[index].width, _resolutions[index].height)) {
551  this->SetDirty();
552  }
553  break;
554 
557  _gui_zoom = (ZoomLevel)(ZOOM_LVL_OUT_4X - index);
561  break;
562 
565  _font_zoom = (ZoomLevel)(ZOOM_LVL_OUT_4X - index);
566  ClearFontCache();
569  break;
570 
572  this->SetMediaSet<BaseGraphics>(index);
573  break;
574 
576  this->SetMediaSet<BaseSounds>(index);
577  break;
578 
580  ChangeMusicSet(index);
581  break;
582  }
583  }
584 
590  virtual void OnInvalidateData(int data = 0, bool gui_scope = true)
591  {
592  if (!gui_scope) return;
594 
595  bool missing_files = BaseGraphics::GetUsedSet()->GetNumMissing() == 0;
596  this->GetWidget<NWidgetCore>(WID_GO_BASE_GRF_STATUS)->SetDataTip(missing_files ? STR_EMPTY : STR_GAME_OPTIONS_BASE_GRF_STATUS, STR_NULL);
597 
598  for (TextfileType tft = TFT_BEGIN; tft < TFT_END; tft++) {
602  }
603 
604  missing_files = BaseMusic::GetUsedSet()->GetNumInvalid() == 0;
605  this->GetWidget<NWidgetCore>(WID_GO_BASE_MUSIC_STATUS)->SetDataTip(missing_files ? STR_EMPTY : STR_GAME_OPTIONS_BASE_MUSIC_STATUS, STR_NULL);
606  }
607 };
608 
609 static const NWidgetPart _nested_game_options_widgets[] = {
611  NWidget(WWT_CLOSEBOX, COLOUR_GREY),
612  NWidget(WWT_CAPTION, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
613  EndContainer(),
614  NWidget(WWT_PANEL, COLOUR_GREY, WID_GO_BACKGROUND), SetPIP(6, 6, 10),
615  NWidget(NWID_HORIZONTAL), SetPIP(10, 10, 10),
616  NWidget(NWID_VERTICAL), SetPIP(0, 6, 0),
617  NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_ROAD_VEHICLES_FRAME, STR_NULL),
618  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),
619  EndContainer(),
620  NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_AUTOSAVE_FRAME, STR_NULL),
621  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),
622  EndContainer(),
623  NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_RESOLUTION, STR_NULL),
624  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),
626  NWidget(WWT_TEXT, COLOUR_GREY), SetMinimalSize(0, 12), SetFill(1, 0), SetDataTip(STR_GAME_OPTIONS_FULLSCREEN, STR_NULL),
627  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_GO_FULLSCREEN_BUTTON), SetMinimalSize(21, 9), SetDataTip(STR_EMPTY, STR_GAME_OPTIONS_FULLSCREEN_TOOLTIP),
628  EndContainer(),
629  EndContainer(),
630  NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_GUI_ZOOM_FRAME, STR_NULL),
631  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),
632  EndContainer(),
633  EndContainer(),
634 
635  NWidget(NWID_VERTICAL), SetPIP(0, 6, 0),
636  NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_TOWN_NAMES_FRAME, STR_NULL),
637  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),
638  EndContainer(),
639  NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_LANGUAGE, STR_NULL),
640  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),
641  EndContainer(),
642  NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_CURRENCY_UNITS_FRAME, STR_NULL),
643  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),
644  EndContainer(),
645  NWidget(NWID_SPACER), SetMinimalSize(0, 0), SetFill(0, 1),
646  NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_FONT_ZOOM, STR_NULL),
647  NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_FONT_ZOOM_DROPDOWN), SetMinimalSize(150, 12), SetDataTip(STR_BLACK_STRING, STR_GAME_OPTIONS_FONT_ZOOM_DROPDOWN_TOOLTIP), SetFill(1, 0),
648  EndContainer(),
649  EndContainer(),
650  EndContainer(),
651 
652  NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_BASE_GRF, STR_NULL), SetPadding(0, 10, 0, 10),
653  NWidget(NWID_HORIZONTAL), SetPIP(0, 30, 0),
654  NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_BASE_GRF_DROPDOWN), SetMinimalSize(150, 12), SetDataTip(STR_BLACK_RAW_STRING, STR_GAME_OPTIONS_BASE_GRF_TOOLTIP),
655  NWidget(WWT_TEXT, COLOUR_GREY, WID_GO_BASE_GRF_STATUS), SetMinimalSize(150, 12), SetDataTip(STR_EMPTY, STR_NULL), SetFill(1, 0),
656  EndContainer(),
657  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),
659  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),
660  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),
661  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),
662  EndContainer(),
663  EndContainer(),
664 
665  NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_BASE_SFX, STR_NULL), SetPadding(0, 10, 0, 10),
666  NWidget(NWID_HORIZONTAL), SetPIP(0, 30, 0),
667  NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_BASE_SFX_DROPDOWN), SetMinimalSize(150, 12), SetDataTip(STR_BLACK_RAW_STRING, STR_GAME_OPTIONS_BASE_SFX_TOOLTIP),
668  NWidget(NWID_SPACER), SetFill(1, 0),
669  EndContainer(),
670  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),
672  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),
673  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),
674  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),
675  EndContainer(),
676  EndContainer(),
677 
678  NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_BASE_MUSIC, STR_NULL), SetPadding(0, 10, 0, 10),
679  NWidget(NWID_HORIZONTAL), SetPIP(0, 30, 0),
680  NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_BASE_MUSIC_DROPDOWN), SetMinimalSize(150, 12), SetDataTip(STR_BLACK_RAW_STRING, STR_GAME_OPTIONS_BASE_MUSIC_TOOLTIP),
681  NWidget(WWT_TEXT, COLOUR_GREY, WID_GO_BASE_MUSIC_STATUS), SetMinimalSize(150, 12), SetDataTip(STR_EMPTY, STR_NULL), SetFill(1, 0),
682  EndContainer(),
683  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),
685  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),
686  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),
687  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),
688  EndContainer(),
689  EndContainer(),
690  EndContainer(),
691 };
692 
693 static WindowDesc _game_options_desc(
694  WDP_CENTER, "settings_game", 0, 0,
696  0,
697  _nested_game_options_widgets, lengthof(_nested_game_options_widgets)
698 );
699 
702 {
704  new GameOptionsWindow(&_game_options_desc);
705 }
706 
707 static int SETTING_HEIGHT = 11;
708 static const int LEVEL_WIDTH = 15;
709 
718 
719  SEF_LAST_FIELD = 0x04,
720  SEF_FILTERED = 0x08,
721 };
722 
731 };
733 
734 
738  bool type_hides;
741 };
742 
745  byte flags;
746  byte level;
747 
748  BaseSettingEntry() : flags(0), level(0) {}
749  virtual ~BaseSettingEntry() {}
750 
751  virtual void Init(byte level = 0);
752  virtual void FoldAll() {}
753  virtual void UnFoldAll() {}
754 
759  void SetLastField(bool last_field) { if (last_field) SETBITS(this->flags, SEF_LAST_FIELD); else CLRBITS(this->flags, SEF_LAST_FIELD); }
760 
761  virtual uint Length() const = 0;
762  virtual void GetFoldingState(bool &all_folded, bool &all_unfolded) const {}
763  virtual bool IsVisible(const BaseSettingEntry *item) const;
764  virtual BaseSettingEntry *FindEntry(uint row, uint *cur_row);
765  virtual uint GetMaxHelpHeight(int maxw) { return 0; }
766 
771  bool IsFiltered() const { return (this->flags & SEF_FILTERED) != 0; }
772 
773  virtual bool UpdateFilterState(SettingFilter &filter, bool force_visible) = 0;
774 
775  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;
776 
777 protected:
778  virtual void DrawSetting(GameSettings *settings_ptr, int left, int right, int y, bool highlight) const = 0;
779 };
780 
783  const char *name;
785  uint index;
786 
787  SettingEntry(const char *name);
788 
789  virtual void Init(byte level = 0);
790  virtual uint Length() const;
791  virtual uint GetMaxHelpHeight(int maxw);
792  virtual bool UpdateFilterState(SettingFilter &filter, bool force_visible);
793 
794  void SetButtons(byte new_val);
795 
800  inline StringID GetHelpText() const
801  {
802  return this->setting->desc.str_help;
803  }
804 
805  void SetValueDParams(uint first_param, int32 value) const;
806 
807 protected:
808  virtual void DrawSetting(GameSettings *settings_ptr, int left, int right, int y, bool highlight) const;
809 
810 private:
811  bool IsVisibleByRestrictionMode(RestrictionMode mode) const;
812 };
813 
816  typedef std::vector<BaseSettingEntry*> EntryVector;
817  EntryVector entries;
818 
819  template<typename T>
820  T *Add(T *item)
821  {
822  this->entries.push_back(item);
823  return item;
824  }
825 
826  void Init(byte level = 0);
827  void FoldAll();
828  void UnFoldAll();
829 
830  uint Length() const;
831  void GetFoldingState(bool &all_folded, bool &all_unfolded) const;
832  bool IsVisible(const BaseSettingEntry *item) const;
833  BaseSettingEntry *FindEntry(uint row, uint *cur_row);
834  uint GetMaxHelpHeight(int maxw);
835 
836  bool UpdateFilterState(SettingFilter &filter, bool force_visible);
837 
838  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;
839 };
840 
844  bool folded;
845 
846  SettingsPage(StringID title);
847 
848  virtual void Init(byte level = 0);
849  virtual void FoldAll();
850  virtual void UnFoldAll();
851 
852  virtual uint Length() const;
853  virtual void GetFoldingState(bool &all_folded, bool &all_unfolded) const;
854  virtual bool IsVisible(const BaseSettingEntry *item) const;
855  virtual BaseSettingEntry *FindEntry(uint row, uint *cur_row);
856  virtual uint GetMaxHelpHeight(int maxw) { return SettingsContainer::GetMaxHelpHeight(maxw); }
857 
858  virtual bool UpdateFilterState(SettingFilter &filter, bool force_visible);
859 
860  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;
861 
862 protected:
863  virtual void DrawSetting(GameSettings *settings_ptr, int left, int right, int y, bool highlight) const;
864 };
865 
866 /* == BaseSettingEntry methods == */
867 
872 void BaseSettingEntry::Init(byte level)
873 {
874  this->level = level;
875 }
876 
884 {
885  if (this->IsFiltered()) return false;
886  if (this == item) return true;
887  return false;
888 }
889 
896 BaseSettingEntry *BaseSettingEntry::FindEntry(uint row_num, uint *cur_row)
897 {
898  if (this->IsFiltered()) return NULL;
899  if (row_num == *cur_row) return this;
900  (*cur_row)++;
901  return NULL;
902 }
903 
933 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
934 {
935  if (this->IsFiltered()) return cur_row;
936  if (cur_row >= max_row) return cur_row;
937 
938  bool rtl = _current_text_dir == TD_RTL;
939  int offset = rtl ? -4 : 4;
940  int level_width = rtl ? -LEVEL_WIDTH : LEVEL_WIDTH;
941 
942  int x = rtl ? right : left;
943  if (cur_row >= first_row) {
944  int colour = _colour_gradient[COLOUR_ORANGE][4];
945  y += (cur_row - first_row) * SETTING_HEIGHT; // Compute correct y start position
946 
947  /* Draw vertical for parent nesting levels */
948  for (uint lvl = 0; lvl < this->level; lvl++) {
949  if (!HasBit(parent_last, lvl)) GfxDrawLine(x + offset, y, x + offset, y + SETTING_HEIGHT - 1, colour);
950  x += level_width;
951  }
952  /* draw own |- prefix */
953  int halfway_y = y + SETTING_HEIGHT / 2;
954  int bottom_y = (flags & SEF_LAST_FIELD) ? halfway_y : y + SETTING_HEIGHT - 1;
955  GfxDrawLine(x + offset, y, x + offset, bottom_y, colour);
956  /* Small horizontal line from the last vertical line */
957  GfxDrawLine(x + offset, halfway_y, x + level_width - offset, halfway_y, colour);
958  x += level_width;
959 
960  this->DrawSetting(settings_ptr, rtl ? left : x, rtl ? x : right, y, this == selected);
961  }
962  cur_row++;
963 
964  return cur_row;
965 }
966 
967 /* == SettingEntry methods == */
968 
973 SettingEntry::SettingEntry(const char *name)
974 {
975  this->name = name;
976  this->setting = NULL;
977  this->index = 0;
978 }
979 
984 void SettingEntry::Init(byte level)
985 {
986  BaseSettingEntry::Init(level);
987  this->setting = GetSettingFromName(this->name, &this->index);
988  assert(this->setting != NULL);
989 }
990 
996 void SettingEntry::SetButtons(byte new_val)
997 {
998  assert((new_val & ~SEF_BUTTONS_MASK) == 0); // Should not touch any flags outside the buttons
999  this->flags = (this->flags & ~SEF_BUTTONS_MASK) | new_val;
1000 }
1001 
1004 {
1005  return this->IsFiltered() ? 0 : 1;
1006 }
1007 
1014 {
1015  return GetStringHeight(this->GetHelpText(), maxw);
1016 }
1017 
1024 {
1025  /* There shall not be any restriction, i.e. all settings shall be visible. */
1026  if (mode == RM_ALL) return true;
1027 
1028  GameSettings *settings_ptr = &GetGameSettings();
1029  const SettingDesc *sd = this->setting;
1030 
1031  if (mode == RM_BASIC) return (this->setting->desc.cat & SC_BASIC_LIST) != 0;
1032  if (mode == RM_ADVANCED) return (this->setting->desc.cat & SC_ADVANCED_LIST) != 0;
1033 
1034  /* Read the current value. */
1035  const void *var = ResolveVariableAddress(settings_ptr, sd);
1036  int64 current_value = ReadValue(var, sd->save.conv);
1037 
1038  int64 filter_value;
1039 
1040  if (mode == RM_CHANGED_AGAINST_DEFAULT) {
1041  /* This entry shall only be visible, if the value deviates from its default value. */
1042 
1043  /* Read the default value. */
1044  filter_value = ReadValue(&sd->desc.def, sd->save.conv);
1045  } else {
1046  assert(mode == RM_CHANGED_AGAINST_NEW);
1047  /* This entry shall only be visible, if the value deviates from
1048  * its value is used when starting a new game. */
1049 
1050  /* Make sure we're not comparing the new game settings against itself. */
1051  assert(settings_ptr != &_settings_newgame);
1052 
1053  /* Read the new game's value. */
1054  var = ResolveVariableAddress(&_settings_newgame, sd);
1055  filter_value = ReadValue(var, sd->save.conv);
1056  }
1057 
1058  return current_value != filter_value;
1059 }
1060 
1067 bool SettingEntry::UpdateFilterState(SettingFilter &filter, bool force_visible)
1068 {
1069  CLRBITS(this->flags, SEF_FILTERED);
1070 
1071  bool visible = true;
1072 
1073  const SettingDesc *sd = this->setting;
1074  if (!force_visible && !filter.string.IsEmpty()) {
1075  /* Process the search text filter for this item. */
1076  filter.string.ResetState();
1077 
1078  const SettingDescBase *sdb = &sd->desc;
1079 
1080  SetDParam(0, STR_EMPTY);
1081  filter.string.AddLine(sdb->str);
1082  filter.string.AddLine(this->GetHelpText());
1083 
1084  visible = filter.string.GetState();
1085  }
1086 
1087  if (visible) {
1088  if (filter.type != ST_ALL && sd->GetType() != filter.type) {
1089  filter.type_hides = true;
1090  visible = false;
1091  }
1092  if (!this->IsVisibleByRestrictionMode(filter.mode)) {
1093  while (filter.min_cat < RM_ALL && (filter.min_cat == filter.mode || !this->IsVisibleByRestrictionMode(filter.min_cat))) filter.min_cat++;
1094  visible = false;
1095  }
1096  }
1097 
1098  if (!visible) SETBITS(this->flags, SEF_FILTERED);
1099  return visible;
1100 }
1101 
1102 
1103 static const void *ResolveVariableAddress(const GameSettings *settings_ptr, const SettingDesc *sd)
1104 {
1105  if ((sd->desc.flags & SGF_PER_COMPANY) != 0) {
1106  if (Company::IsValidID(_local_company) && _game_mode != GM_MENU) {
1108  } else {
1110  }
1111  } else {
1112  return GetVariableAddress(settings_ptr, &sd->save);
1113  }
1114 }
1115 
1121 void SettingEntry::SetValueDParams(uint first_param, int32 value) const
1122 {
1123  const SettingDescBase *sdb = &this->setting->desc;
1124  if (sdb->cmd == SDT_BOOLX) {
1125  SetDParam(first_param++, value != 0 ? STR_CONFIG_SETTING_ON : STR_CONFIG_SETTING_OFF);
1126  } else {
1127  if ((sdb->flags & SGF_MULTISTRING) != 0) {
1128  SetDParam(first_param++, sdb->str_val - sdb->min + value);
1129  } else if ((sdb->flags & SGF_DISPLAY_ABS) != 0) {
1130  SetDParam(first_param++, sdb->str_val + ((value >= 0) ? 1 : 0));
1131  value = abs(value);
1132  } else {
1133  SetDParam(first_param++, sdb->str_val + ((value == 0 && (sdb->flags & SGF_0ISDISABLED) != 0) ? 1 : 0));
1134  }
1135  SetDParam(first_param++, value);
1136  }
1137 }
1138 
1147 void SettingEntry::DrawSetting(GameSettings *settings_ptr, int left, int right, int y, bool highlight) const
1148 {
1149  const SettingDesc *sd = this->setting;
1150  const SettingDescBase *sdb = &sd->desc;
1151  const void *var = ResolveVariableAddress(settings_ptr, sd);
1152  int state = this->flags & SEF_BUTTONS_MASK;
1153 
1154  bool rtl = _current_text_dir == TD_RTL;
1155  uint buttons_left = rtl ? right + 1 - SETTING_BUTTON_WIDTH : left;
1156  uint text_left = left + (rtl ? 0 : SETTING_BUTTON_WIDTH + 5);
1157  uint text_right = right - (rtl ? SETTING_BUTTON_WIDTH + 5 : 0);
1158  uint button_y = y + (SETTING_HEIGHT - SETTING_BUTTON_HEIGHT) / 2;
1159 
1160  /* We do not allow changes of some items when we are a client in a networkgame */
1161  bool editable = sd->IsEditable();
1162 
1163  SetDParam(0, highlight ? STR_ORANGE_STRING1_WHITE : STR_ORANGE_STRING1_LTBLUE);
1164  int32 value = (int32)ReadValue(var, sd->save.conv);
1165  if (sdb->cmd == SDT_BOOLX) {
1166  /* Draw checkbox for boolean-value either on/off */
1167  DrawBoolButton(buttons_left, button_y, value != 0, editable);
1168  } else if ((sdb->flags & SGF_MULTISTRING) != 0) {
1169  /* Draw [v] button for settings of an enum-type */
1170  DrawDropDownButton(buttons_left, button_y, COLOUR_YELLOW, state != 0, editable);
1171  } else {
1172  /* Draw [<][>] boxes for settings of an integer-type */
1173  DrawArrowButtons(buttons_left, button_y, COLOUR_YELLOW, state,
1174  editable && value != (sdb->flags & SGF_0ISDISABLED ? 0 : sdb->min), editable && (uint32)value != sdb->max);
1175  }
1176  this->SetValueDParams(1, value);
1177  DrawString(text_left, text_right, y + (SETTING_HEIGHT - FONT_HEIGHT_NORMAL) / 2, sdb->str, highlight ? TC_WHITE : TC_LIGHT_BLUE);
1178 }
1179 
1180 /* == SettingsContainer methods == */
1181 
1186 void SettingsContainer::Init(byte level)
1187 {
1188  for (EntryVector::iterator it = this->entries.begin(); it != this->entries.end(); ++it) {
1189  (*it)->Init(level);
1190  }
1191 }
1192 
1195 {
1196  for (EntryVector::iterator it = this->entries.begin(); it != this->entries.end(); ++it) {
1197  (*it)->FoldAll();
1198  }
1199 }
1200 
1203 {
1204  for (EntryVector::iterator it = this->entries.begin(); it != this->entries.end(); ++it) {
1205  (*it)->UnFoldAll();
1206  }
1207 }
1208 
1214 void SettingsContainer::GetFoldingState(bool &all_folded, bool &all_unfolded) const
1215 {
1216  for (EntryVector::const_iterator it = this->entries.begin(); it != this->entries.end(); ++it) {
1217  (*it)->GetFoldingState(all_folded, all_unfolded);
1218  }
1219 }
1220 
1227 bool SettingsContainer::UpdateFilterState(SettingFilter &filter, bool force_visible)
1228 {
1229  bool visible = false;
1230  bool first_visible = true;
1231  for (EntryVector::reverse_iterator it = this->entries.rbegin(); it != this->entries.rend(); ++it) {
1232  visible |= (*it)->UpdateFilterState(filter, force_visible);
1233  (*it)->SetLastField(first_visible);
1234  if (visible && first_visible) first_visible = false;
1235  }
1236  return visible;
1237 }
1238 
1239 
1247 {
1248  for (EntryVector::const_iterator it = this->entries.begin(); it != this->entries.end(); ++it) {
1249  if ((*it)->IsVisible(item)) return true;
1250  }
1251  return false;
1252 }
1253 
1256 {
1257  uint length = 0;
1258  for (EntryVector::const_iterator it = this->entries.begin(); it != this->entries.end(); ++it) {
1259  length += (*it)->Length();
1260  }
1261  return length;
1262 }
1263 
1270 BaseSettingEntry *SettingsContainer::FindEntry(uint row_num, uint *cur_row)
1271 {
1272  BaseSettingEntry *pe = NULL;
1273  for (EntryVector::iterator it = this->entries.begin(); it != this->entries.end(); ++it) {
1274  pe = (*it)->FindEntry(row_num, cur_row);
1275  if (pe != NULL) {
1276  break;
1277  }
1278  }
1279  return pe;
1280 }
1281 
1288 {
1289  uint biggest = 0;
1290  for (EntryVector::const_iterator it = this->entries.begin(); it != this->entries.end(); ++it) {
1291  biggest = max(biggest, (*it)->GetMaxHelpHeight(maxw));
1292  }
1293  return biggest;
1294 }
1295 
1296 
1311 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
1312 {
1313  for (EntryVector::const_iterator it = this->entries.begin(); it != this->entries.end(); ++it) {
1314  cur_row = (*it)->Draw(settings_ptr, left, right, y, first_row, max_row, selected, cur_row, parent_last);
1315  if (cur_row >= max_row) {
1316  break;
1317  }
1318  }
1319  return cur_row;
1320 }
1321 
1322 /* == SettingsPage methods == */
1323 
1329 {
1330  this->title = title;
1331  this->folded = true;
1332 }
1333 
1338 void SettingsPage::Init(byte level)
1339 {
1340  BaseSettingEntry::Init(level);
1341  SettingsContainer::Init(level + 1);
1342 }
1343 
1346 {
1347  if (this->IsFiltered()) return;
1348  this->folded = true;
1349 
1351 }
1352 
1355 {
1356  if (this->IsFiltered()) return;
1357  this->folded = false;
1358 
1360 }
1361 
1367 void SettingsPage::GetFoldingState(bool &all_folded, bool &all_unfolded) const
1368 {
1369  if (this->IsFiltered()) return;
1370 
1371  if (this->folded) {
1372  all_unfolded = false;
1373  } else {
1374  all_folded = false;
1375  }
1376 
1377  SettingsContainer::GetFoldingState(all_folded, all_unfolded);
1378 }
1379 
1386 bool SettingsPage::UpdateFilterState(SettingFilter &filter, bool force_visible)
1387 {
1388  if (!force_visible && !filter.string.IsEmpty()) {
1389  filter.string.ResetState();
1390  filter.string.AddLine(this->title);
1391  force_visible = filter.string.GetState();
1392  }
1393 
1394  bool visible = SettingsContainer::UpdateFilterState(filter, force_visible);
1395  if (visible) {
1396  CLRBITS(this->flags, SEF_FILTERED);
1397  } else {
1398  SETBITS(this->flags, SEF_FILTERED);
1399  }
1400  return visible;
1401 }
1402 
1410 {
1411  if (this->IsFiltered()) return false;
1412  if (this == item) return true;
1413  if (this->folded) return false;
1414 
1415  return SettingsContainer::IsVisible(item);
1416 }
1417 
1420 {
1421  if (this->IsFiltered()) return 0;
1422  if (this->folded) return 1; // Only displaying the title
1423 
1424  return 1 + SettingsContainer::Length();
1425 }
1426 
1433 BaseSettingEntry *SettingsPage::FindEntry(uint row_num, uint *cur_row)
1434 {
1435  if (this->IsFiltered()) return NULL;
1436  if (row_num == *cur_row) return this;
1437  (*cur_row)++;
1438  if (this->folded) return NULL;
1439 
1440  return SettingsContainer::FindEntry(row_num, cur_row);
1441 }
1442 
1457 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
1458 {
1459  if (this->IsFiltered()) return cur_row;
1460  if (cur_row >= max_row) return cur_row;
1461 
1462  cur_row = BaseSettingEntry::Draw(settings_ptr, left, right, y, first_row, max_row, selected, cur_row, parent_last);
1463 
1464  if (!this->folded) {
1465  if (this->flags & SEF_LAST_FIELD) {
1466  assert(this->level < 8 * sizeof(parent_last));
1467  SetBit(parent_last, this->level); // Add own last-field state
1468  }
1469 
1470  cur_row = SettingsContainer::Draw(settings_ptr, left, right, y, first_row, max_row, selected, cur_row, parent_last);
1471  }
1472 
1473  return cur_row;
1474 }
1475 
1484 void SettingsPage::DrawSetting(GameSettings *settings_ptr, int left, int right, int y, bool highlight) const
1485 {
1486  bool rtl = _current_text_dir == TD_RTL;
1487  DrawSprite((this->folded ? SPR_CIRCLE_FOLDED : SPR_CIRCLE_UNFOLDED), PAL_NONE, rtl ? right - _circle_size.width : left, y + (SETTING_HEIGHT - _circle_size.height) / 2);
1488  DrawString(rtl ? left : left + _circle_size.width + 2, rtl ? right - _circle_size.width - 2 : right, y + (SETTING_HEIGHT - FONT_HEIGHT_NORMAL) / 2, this->title);
1489 }
1490 
1493 {
1494  static SettingsContainer *main = NULL;
1495 
1496  if (main == NULL)
1497  {
1498  /* Build up the dynamic settings-array only once per OpenTTD session */
1499  main = new SettingsContainer();
1500 
1501  SettingsPage *localisation = main->Add(new SettingsPage(STR_CONFIG_SETTING_LOCALISATION));
1502  {
1503  localisation->Add(new SettingEntry("locale.units_velocity"));
1504  localisation->Add(new SettingEntry("locale.units_power"));
1505  localisation->Add(new SettingEntry("locale.units_weight"));
1506  localisation->Add(new SettingEntry("locale.units_volume"));
1507  localisation->Add(new SettingEntry("locale.units_force"));
1508  localisation->Add(new SettingEntry("locale.units_height"));
1509  localisation->Add(new SettingEntry("gui.date_format_in_default_names"));
1510  }
1511 
1512  SettingsPage *graphics = main->Add(new SettingsPage(STR_CONFIG_SETTING_GRAPHICS));
1513  {
1514  graphics->Add(new SettingEntry("gui.zoom_min"));
1515  graphics->Add(new SettingEntry("gui.zoom_max"));
1516  graphics->Add(new SettingEntry("gui.smallmap_land_colour"));
1517  graphics->Add(new SettingEntry("gui.graph_line_thickness"));
1518  }
1519 
1520  SettingsPage *sound = main->Add(new SettingsPage(STR_CONFIG_SETTING_SOUND));
1521  {
1522  sound->Add(new SettingEntry("sound.click_beep"));
1523  sound->Add(new SettingEntry("sound.confirm"));
1524  sound->Add(new SettingEntry("sound.news_ticker"));
1525  sound->Add(new SettingEntry("sound.news_full"));
1526  sound->Add(new SettingEntry("sound.new_year"));
1527  sound->Add(new SettingEntry("sound.disaster"));
1528  sound->Add(new SettingEntry("sound.vehicle"));
1529  sound->Add(new SettingEntry("sound.ambient"));
1530  }
1531 
1532  SettingsPage *interface = main->Add(new SettingsPage(STR_CONFIG_SETTING_INTERFACE));
1533  {
1534  SettingsPage *general = interface->Add(new SettingsPage(STR_CONFIG_SETTING_INTERFACE_GENERAL));
1535  {
1536  general->Add(new SettingEntry("gui.osk_activation"));
1537  general->Add(new SettingEntry("gui.hover_delay_ms"));
1538  general->Add(new SettingEntry("gui.errmsg_duration"));
1539  general->Add(new SettingEntry("gui.window_snap_radius"));
1540  general->Add(new SettingEntry("gui.window_soft_limit"));
1541  general->Add(new SettingEntry("gui.right_mouse_wnd_close"));
1542  }
1543 
1544  SettingsPage *viewports = interface->Add(new SettingsPage(STR_CONFIG_SETTING_INTERFACE_VIEWPORTS));
1545  {
1546  viewports->Add(new SettingEntry("gui.auto_scrolling"));
1547  viewports->Add(new SettingEntry("gui.scroll_mode"));
1548  viewports->Add(new SettingEntry("gui.smooth_scroll"));
1549  /* While the horizontal scrollwheel scrolling is written as general code, only
1550  * the cocoa (OSX) driver generates input for it.
1551  * Since it's also able to completely disable the scrollwheel will we display it on all platforms anyway */
1552  viewports->Add(new SettingEntry("gui.scrollwheel_scrolling"));
1553  viewports->Add(new SettingEntry("gui.scrollwheel_multiplier"));
1554 #ifdef __APPLE__
1555  /* We might need to emulate a right mouse button on mac */
1556  viewports->Add(new SettingEntry("gui.right_mouse_btn_emulation"));
1557 #endif
1558  viewports->Add(new SettingEntry("gui.population_in_label"));
1559  viewports->Add(new SettingEntry("gui.liveries"));
1560  viewports->Add(new SettingEntry("construction.train_signal_side"));
1561  viewports->Add(new SettingEntry("gui.measure_tooltip"));
1562  viewports->Add(new SettingEntry("gui.loading_indicators"));
1563  viewports->Add(new SettingEntry("gui.show_track_reservation"));
1564  }
1565 
1566  SettingsPage *construction = interface->Add(new SettingsPage(STR_CONFIG_SETTING_INTERFACE_CONSTRUCTION));
1567  {
1568  construction->Add(new SettingEntry("gui.link_terraform_toolbar"));
1569  construction->Add(new SettingEntry("gui.enable_signal_gui"));
1570  construction->Add(new SettingEntry("gui.persistent_buildingtools"));
1571  construction->Add(new SettingEntry("gui.quick_goto"));
1572  construction->Add(new SettingEntry("gui.default_rail_type"));
1573  construction->Add(new SettingEntry("gui.disable_unsuitable_building"));
1574  }
1575 
1576  interface->Add(new SettingEntry("gui.autosave"));
1577  interface->Add(new SettingEntry("gui.toolbar_pos"));
1578  interface->Add(new SettingEntry("gui.statusbar_pos"));
1579  interface->Add(new SettingEntry("gui.prefer_teamchat"));
1580  interface->Add(new SettingEntry("gui.advanced_vehicle_list"));
1581  interface->Add(new SettingEntry("gui.timetable_in_ticks"));
1582  interface->Add(new SettingEntry("gui.timetable_arrival_departure"));
1583  interface->Add(new SettingEntry("gui.expenses_layout"));
1584  }
1585 
1586  SettingsPage *advisors = main->Add(new SettingsPage(STR_CONFIG_SETTING_ADVISORS));
1587  {
1588  advisors->Add(new SettingEntry("gui.coloured_news_year"));
1589  advisors->Add(new SettingEntry("news_display.general"));
1590  advisors->Add(new SettingEntry("news_display.new_vehicles"));
1591  advisors->Add(new SettingEntry("news_display.accident"));
1592  advisors->Add(new SettingEntry("news_display.company_info"));
1593  advisors->Add(new SettingEntry("news_display.acceptance"));
1594  advisors->Add(new SettingEntry("news_display.arrival_player"));
1595  advisors->Add(new SettingEntry("news_display.arrival_other"));
1596  advisors->Add(new SettingEntry("news_display.advice"));
1597  advisors->Add(new SettingEntry("gui.order_review_system"));
1598  advisors->Add(new SettingEntry("gui.vehicle_income_warn"));
1599  advisors->Add(new SettingEntry("gui.lost_vehicle_warn"));
1600  advisors->Add(new SettingEntry("gui.show_finances"));
1601  advisors->Add(new SettingEntry("news_display.economy"));
1602  advisors->Add(new SettingEntry("news_display.subsidies"));
1603  advisors->Add(new SettingEntry("news_display.open"));
1604  advisors->Add(new SettingEntry("news_display.close"));
1605  advisors->Add(new SettingEntry("news_display.production_player"));
1606  advisors->Add(new SettingEntry("news_display.production_other"));
1607  advisors->Add(new SettingEntry("news_display.production_nobody"));
1608  }
1609 
1610  SettingsPage *company = main->Add(new SettingsPage(STR_CONFIG_SETTING_COMPANY));
1611  {
1612  company->Add(new SettingEntry("gui.semaphore_build_before"));
1613  company->Add(new SettingEntry("gui.default_signal_type"));
1614  company->Add(new SettingEntry("gui.cycle_signal_types"));
1615  company->Add(new SettingEntry("gui.drag_signals_fixed_distance"));
1616  company->Add(new SettingEntry("gui.new_nonstop"));
1617  company->Add(new SettingEntry("gui.stop_location"));
1618  company->Add(new SettingEntry("gui.starting_colour"));
1619  company->Add(new SettingEntry("company.engine_renew"));
1620  company->Add(new SettingEntry("company.engine_renew_months"));
1621  company->Add(new SettingEntry("company.engine_renew_money"));
1622  company->Add(new SettingEntry("vehicle.servint_ispercent"));
1623  company->Add(new SettingEntry("vehicle.servint_trains"));
1624  company->Add(new SettingEntry("vehicle.servint_roadveh"));
1625  company->Add(new SettingEntry("vehicle.servint_ships"));
1626  company->Add(new SettingEntry("vehicle.servint_aircraft"));
1627  }
1628 
1629  SettingsPage *accounting = main->Add(new SettingsPage(STR_CONFIG_SETTING_ACCOUNTING));
1630  {
1631  accounting->Add(new SettingEntry("economy.inflation"));
1632  accounting->Add(new SettingEntry("difficulty.initial_interest"));
1633  accounting->Add(new SettingEntry("difficulty.max_loan"));
1634  accounting->Add(new SettingEntry("difficulty.subsidy_multiplier"));
1635  accounting->Add(new SettingEntry("economy.feeder_payment_share"));
1636  accounting->Add(new SettingEntry("economy.infrastructure_maintenance"));
1637  accounting->Add(new SettingEntry("difficulty.vehicle_costs"));
1638  accounting->Add(new SettingEntry("difficulty.construction_cost"));
1639  }
1640 
1641  SettingsPage *vehicles = main->Add(new SettingsPage(STR_CONFIG_SETTING_VEHICLES));
1642  {
1643  SettingsPage *physics = vehicles->Add(new SettingsPage(STR_CONFIG_SETTING_VEHICLES_PHYSICS));
1644  {
1645  physics->Add(new SettingEntry("vehicle.train_acceleration_model"));
1646  physics->Add(new SettingEntry("vehicle.train_slope_steepness"));
1647  physics->Add(new SettingEntry("vehicle.wagon_speed_limits"));
1648  physics->Add(new SettingEntry("vehicle.freight_trains"));
1649  physics->Add(new SettingEntry("vehicle.roadveh_acceleration_model"));
1650  physics->Add(new SettingEntry("vehicle.roadveh_slope_steepness"));
1651  physics->Add(new SettingEntry("vehicle.smoke_amount"));
1652  physics->Add(new SettingEntry("vehicle.plane_speed"));
1653  }
1654 
1655  SettingsPage *routing = vehicles->Add(new SettingsPage(STR_CONFIG_SETTING_VEHICLES_ROUTING));
1656  {
1657  routing->Add(new SettingEntry("pf.pathfinder_for_trains"));
1658  routing->Add(new SettingEntry("difficulty.line_reverse_mode"));
1659  routing->Add(new SettingEntry("pf.reverse_at_signals"));
1660  routing->Add(new SettingEntry("pf.forbid_90_deg"));
1661  routing->Add(new SettingEntry("pf.pathfinder_for_roadvehs"));
1662  routing->Add(new SettingEntry("pf.pathfinder_for_ships"));
1663  }
1664 
1665  vehicles->Add(new SettingEntry("order.no_servicing_if_no_breakdowns"));
1666  vehicles->Add(new SettingEntry("order.serviceathelipad"));
1667  }
1668 
1669  SettingsPage *limitations = main->Add(new SettingsPage(STR_CONFIG_SETTING_LIMITATIONS));
1670  {
1671  limitations->Add(new SettingEntry("construction.command_pause_level"));
1672  limitations->Add(new SettingEntry("construction.autoslope"));
1673  limitations->Add(new SettingEntry("construction.extra_dynamite"));
1674  limitations->Add(new SettingEntry("construction.max_heightlevel"));
1675  limitations->Add(new SettingEntry("construction.max_bridge_length"));
1676  limitations->Add(new SettingEntry("construction.max_bridge_height"));
1677  limitations->Add(new SettingEntry("construction.max_tunnel_length"));
1678  limitations->Add(new SettingEntry("station.never_expire_airports"));
1679  limitations->Add(new SettingEntry("vehicle.never_expire_vehicles"));
1680  limitations->Add(new SettingEntry("vehicle.max_trains"));
1681  limitations->Add(new SettingEntry("vehicle.max_roadveh"));
1682  limitations->Add(new SettingEntry("vehicle.max_aircraft"));
1683  limitations->Add(new SettingEntry("vehicle.max_ships"));
1684  limitations->Add(new SettingEntry("vehicle.max_train_length"));
1685  limitations->Add(new SettingEntry("station.station_spread"));
1686  limitations->Add(new SettingEntry("station.distant_join_stations"));
1687  limitations->Add(new SettingEntry("construction.road_stop_on_town_road"));
1688  limitations->Add(new SettingEntry("construction.road_stop_on_competitor_road"));
1689  limitations->Add(new SettingEntry("vehicle.disable_elrails"));
1690  }
1691 
1692  SettingsPage *disasters = main->Add(new SettingsPage(STR_CONFIG_SETTING_ACCIDENTS));
1693  {
1694  disasters->Add(new SettingEntry("difficulty.disasters"));
1695  disasters->Add(new SettingEntry("difficulty.economy"));
1696  disasters->Add(new SettingEntry("difficulty.vehicle_breakdowns"));
1697  disasters->Add(new SettingEntry("vehicle.plane_crashes"));
1698  }
1699 
1700  SettingsPage *genworld = main->Add(new SettingsPage(STR_CONFIG_SETTING_GENWORLD));
1701  {
1702  genworld->Add(new SettingEntry("game_creation.landscape"));
1703  genworld->Add(new SettingEntry("game_creation.land_generator"));
1704  genworld->Add(new SettingEntry("difficulty.terrain_type"));
1705  genworld->Add(new SettingEntry("game_creation.tgen_smoothness"));
1706  genworld->Add(new SettingEntry("game_creation.variety"));
1707  genworld->Add(new SettingEntry("game_creation.snow_line_height"));
1708  genworld->Add(new SettingEntry("game_creation.amount_of_rivers"));
1709  genworld->Add(new SettingEntry("game_creation.tree_placer"));
1710  genworld->Add(new SettingEntry("vehicle.road_side"));
1711  genworld->Add(new SettingEntry("economy.larger_towns"));
1712  genworld->Add(new SettingEntry("economy.initial_city_size"));
1713  genworld->Add(new SettingEntry("economy.town_layout"));
1714  genworld->Add(new SettingEntry("difficulty.industry_density"));
1715  genworld->Add(new SettingEntry("gui.pause_on_newgame"));
1716  }
1717 
1718  SettingsPage *environment = main->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT));
1719  {
1720  SettingsPage *authorities = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_AUTHORITIES));
1721  {
1722  authorities->Add(new SettingEntry("difficulty.town_council_tolerance"));
1723  authorities->Add(new SettingEntry("economy.bribe"));
1724  authorities->Add(new SettingEntry("economy.exclusive_rights"));
1725  authorities->Add(new SettingEntry("economy.fund_roads"));
1726  authorities->Add(new SettingEntry("economy.fund_buildings"));
1727  authorities->Add(new SettingEntry("economy.station_noise_level"));
1728  }
1729 
1730  SettingsPage *towns = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_TOWNS));
1731  {
1732  towns->Add(new SettingEntry("economy.town_growth_rate"));
1733  towns->Add(new SettingEntry("economy.allow_town_roads"));
1734  towns->Add(new SettingEntry("economy.allow_town_level_crossings"));
1735  towns->Add(new SettingEntry("economy.found_town"));
1736  }
1737 
1738  SettingsPage *industries = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_INDUSTRIES));
1739  {
1740  industries->Add(new SettingEntry("construction.raw_industry_construction"));
1741  industries->Add(new SettingEntry("construction.industry_platform"));
1742  industries->Add(new SettingEntry("economy.multiple_industry_per_town"));
1743  industries->Add(new SettingEntry("game_creation.oil_refinery_limit"));
1744  industries->Add(new SettingEntry("economy.smooth_economy"));
1745  }
1746 
1747  SettingsPage *cdist = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_CARGODIST));
1748  {
1749  cdist->Add(new SettingEntry("linkgraph.recalc_time"));
1750  cdist->Add(new SettingEntry("linkgraph.recalc_interval"));
1751  cdist->Add(new SettingEntry("linkgraph.distribution_pax"));
1752  cdist->Add(new SettingEntry("linkgraph.distribution_mail"));
1753  cdist->Add(new SettingEntry("linkgraph.distribution_armoured"));
1754  cdist->Add(new SettingEntry("linkgraph.distribution_default"));
1755  cdist->Add(new SettingEntry("linkgraph.accuracy"));
1756  cdist->Add(new SettingEntry("linkgraph.demand_distance"));
1757  cdist->Add(new SettingEntry("linkgraph.demand_size"));
1758  cdist->Add(new SettingEntry("linkgraph.short_path_saturation"));
1759  }
1760 
1761  environment->Add(new SettingEntry("station.modified_catchment"));
1762  environment->Add(new SettingEntry("construction.extra_tree_placement"));
1763  }
1764 
1765  SettingsPage *ai = main->Add(new SettingsPage(STR_CONFIG_SETTING_AI));
1766  {
1767  SettingsPage *npc = ai->Add(new SettingsPage(STR_CONFIG_SETTING_AI_NPC));
1768  {
1769  npc->Add(new SettingEntry("script.settings_profile"));
1770  npc->Add(new SettingEntry("script.script_max_opcode_till_suspend"));
1771  npc->Add(new SettingEntry("difficulty.competitor_speed"));
1772  npc->Add(new SettingEntry("ai.ai_in_multiplayer"));
1773  npc->Add(new SettingEntry("ai.ai_disable_veh_train"));
1774  npc->Add(new SettingEntry("ai.ai_disable_veh_roadveh"));
1775  npc->Add(new SettingEntry("ai.ai_disable_veh_aircraft"));
1776  npc->Add(new SettingEntry("ai.ai_disable_veh_ship"));
1777  }
1778 
1779  ai->Add(new SettingEntry("economy.give_money"));
1780  ai->Add(new SettingEntry("economy.allow_shares"));
1781  }
1782 
1783  main->Init();
1784  }
1785  return *main;
1786 }
1787 
1788 static const StringID _game_settings_restrict_dropdown[] = {
1789  STR_CONFIG_SETTING_RESTRICT_BASIC, // RM_BASIC
1790  STR_CONFIG_SETTING_RESTRICT_ADVANCED, // RM_ADVANCED
1791  STR_CONFIG_SETTING_RESTRICT_ALL, // RM_ALL
1792  STR_CONFIG_SETTING_RESTRICT_CHANGED_AGAINST_DEFAULT, // RM_CHANGED_AGAINST_DEFAULT
1793  STR_CONFIG_SETTING_RESTRICT_CHANGED_AGAINST_NEW, // RM_CHANGED_AGAINST_NEW
1794 };
1795 assert_compile(lengthof(_game_settings_restrict_dropdown) == RM_END);
1796 
1803 };
1804 
1807  static const int SETTINGTREE_LEFT_OFFSET = 5;
1808  static const int SETTINGTREE_RIGHT_OFFSET = 5;
1809  static const int SETTINGTREE_TOP_OFFSET = 5;
1810  static const int SETTINGTREE_BOTTOM_OFFSET = 5;
1811 
1813 
1819 
1825 
1826  Scrollbar *vscroll;
1827 
1828  GameSettingsWindow(WindowDesc *desc) : Window(desc), filter_editbox(50)
1829  {
1830  this->warn_missing = WHR_NONE;
1831  this->warn_lines = 0;
1833  this->filter.min_cat = RM_ALL;
1834  this->filter.type = ST_ALL;
1835  this->filter.type_hides = false;
1836  this->settings_ptr = &GetGameSettings();
1837 
1838  _circle_size = maxdim(GetSpriteSize(SPR_CIRCLE_FOLDED), GetSpriteSize(SPR_CIRCLE_UNFOLDED));
1839  GetSettingsTree().FoldAll(); // Close all sub-pages
1840 
1841  this->valuewindow_entry = NULL; // No setting entry for which a entry window is opened
1842  this->clicked_entry = NULL; // No numeric setting buttons are depressed
1843  this->last_clicked = NULL;
1844  this->valuedropdown_entry = NULL;
1845  this->closing_dropdown = false;
1846  this->manually_changed_folding = false;
1847 
1848  this->CreateNestedTree();
1849  this->vscroll = this->GetScrollbar(WID_GS_SCROLLBAR);
1851 
1852  this->querystrings[WID_GS_FILTER] = &this->filter_editbox;
1853  this->filter_editbox.cancel_button = QueryString::ACTION_CLEAR;
1855 
1856  this->InvalidateData();
1857  }
1858 
1859  virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
1860  {
1861  switch (widget) {
1862  case WID_GS_OPTIONSPANEL:
1863  resize->height = SETTING_HEIGHT = max(max<int>(_circle_size.height, SETTING_BUTTON_HEIGHT), FONT_HEIGHT_NORMAL) + 1;
1864  resize->width = 1;
1865 
1866  size->height = 5 * resize->height + SETTINGTREE_TOP_OFFSET + SETTINGTREE_BOTTOM_OFFSET;
1867  break;
1868 
1869  case WID_GS_HELP_TEXT: {
1870  static const StringID setting_types[] = {
1871  STR_CONFIG_SETTING_TYPE_CLIENT,
1872  STR_CONFIG_SETTING_TYPE_COMPANY_MENU, STR_CONFIG_SETTING_TYPE_COMPANY_INGAME,
1873  STR_CONFIG_SETTING_TYPE_GAME_MENU, STR_CONFIG_SETTING_TYPE_GAME_INGAME,
1874  };
1875  for (uint i = 0; i < lengthof(setting_types); i++) {
1876  SetDParam(0, setting_types[i]);
1877  size->width = max(size->width, GetStringBoundingBox(STR_CONFIG_SETTING_TYPE).width);
1878  }
1879  size->height = 2 * FONT_HEIGHT_NORMAL + WD_PAR_VSEP_NORMAL +
1880  max(size->height, GetSettingsTree().GetMaxHelpHeight(size->width));
1881  break;
1882  }
1883 
1885  case WID_GS_RESTRICT_TYPE:
1886  size->width = max(GetStringBoundingBox(STR_CONFIG_SETTING_RESTRICT_CATEGORY).width, GetStringBoundingBox(STR_CONFIG_SETTING_RESTRICT_TYPE).width);
1887  break;
1888 
1889  default:
1890  break;
1891  }
1892  }
1893 
1894  virtual void OnPaint()
1895  {
1896  if (this->closing_dropdown) {
1897  this->closing_dropdown = false;
1898  assert(this->valuedropdown_entry != NULL);
1899  this->valuedropdown_entry->SetButtons(0);
1900  this->valuedropdown_entry = NULL;
1901  }
1902 
1903  /* Reserve the correct number of lines for the 'some search results are hidden' notice in the central settings display panel. */
1904  const NWidgetBase *panel = this->GetWidget<NWidgetBase>(WID_GS_OPTIONSPANEL);
1905  StringID warn_str = STR_CONFIG_SETTING_CATEGORY_HIDES - 1 + this->warn_missing;
1906  int new_warn_lines;
1907  if (this->warn_missing == WHR_NONE) {
1908  new_warn_lines = 0;
1909  } else {
1910  SetDParam(0, _game_settings_restrict_dropdown[this->filter.min_cat]);
1911  new_warn_lines = GetStringLineCount(warn_str, panel->current_x);
1912  }
1913  if (this->warn_lines != new_warn_lines) {
1914  this->vscroll->SetCount(this->vscroll->GetCount() - this->warn_lines + new_warn_lines);
1915  this->warn_lines = new_warn_lines;
1916  }
1917 
1918  this->DrawWidgets();
1919 
1920  /* Draw the 'some search results are hidden' notice. */
1921  if (this->warn_missing != WHR_NONE) {
1922  const int left = panel->pos_x;
1923  const int right = left + panel->current_x - 1;
1924  const int top = panel->pos_y + WD_FRAMETEXT_TOP + (SETTING_HEIGHT - FONT_HEIGHT_NORMAL) * this->warn_lines / 2;
1925  SetDParam(0, _game_settings_restrict_dropdown[this->filter.min_cat]);
1926  if (this->warn_lines == 1) {
1927  /* If the warning fits at one line, center it. */
1928  DrawString(left + WD_FRAMETEXT_LEFT, right - WD_FRAMETEXT_RIGHT, top, warn_str, TC_FROMSTRING, SA_HOR_CENTER);
1929  } else {
1930  DrawStringMultiLine(left + WD_FRAMERECT_LEFT, right - WD_FRAMERECT_RIGHT, top, INT32_MAX, warn_str, TC_FROMSTRING, SA_HOR_CENTER);
1931  }
1932  }
1933  }
1934 
1935  virtual void SetStringParameters(int widget) const
1936  {
1937  switch (widget) {
1939  SetDParam(0, _game_settings_restrict_dropdown[this->filter.mode]);
1940  break;
1941 
1942  case WID_GS_TYPE_DROPDOWN:
1943  switch (this->filter.type) {
1944  case ST_GAME: SetDParam(0, _game_mode == GM_MENU ? STR_CONFIG_SETTING_TYPE_DROPDOWN_GAME_MENU : STR_CONFIG_SETTING_TYPE_DROPDOWN_GAME_INGAME); break;
1945  case ST_COMPANY: SetDParam(0, _game_mode == GM_MENU ? STR_CONFIG_SETTING_TYPE_DROPDOWN_COMPANY_MENU : STR_CONFIG_SETTING_TYPE_DROPDOWN_COMPANY_INGAME); break;
1946  case ST_CLIENT: SetDParam(0, STR_CONFIG_SETTING_TYPE_DROPDOWN_CLIENT); break;
1947  default: SetDParam(0, STR_CONFIG_SETTING_TYPE_DROPDOWN_ALL); break;
1948  }
1949  break;
1950  }
1951  }
1952 
1953  DropDownList *BuildDropDownList(int widget) const
1954  {
1955  DropDownList *list = NULL;
1956  switch (widget) {
1958  list = new DropDownList();
1959 
1960  for (int mode = 0; mode != RM_END; mode++) {
1961  /* If we are in adv. settings screen for the new game's settings,
1962  * we don't want to allow comparing with new game's settings. */
1963  bool disabled = mode == RM_CHANGED_AGAINST_NEW && settings_ptr == &_settings_newgame;
1964 
1965  *list->Append() = new DropDownListStringItem(_game_settings_restrict_dropdown[mode], mode, disabled);
1966  }
1967  break;
1968 
1969  case WID_GS_TYPE_DROPDOWN:
1970  list = new DropDownList();
1971  *list->Append() = new DropDownListStringItem(STR_CONFIG_SETTING_TYPE_DROPDOWN_ALL, ST_ALL, false);
1972  *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);
1973  *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);
1974  *list->Append() = new DropDownListStringItem(STR_CONFIG_SETTING_TYPE_DROPDOWN_CLIENT, ST_CLIENT, false);
1975  break;
1976  }
1977  return list;
1978  }
1979 
1980  virtual void DrawWidget(const Rect &r, int widget) const
1981  {
1982  switch (widget) {
1983  case WID_GS_OPTIONSPANEL: {
1984  int top_pos = r.top + SETTINGTREE_TOP_OFFSET + 1 + this->warn_lines * SETTING_HEIGHT;
1985  uint last_row = this->vscroll->GetPosition() + this->vscroll->GetCapacity() - this->warn_lines;
1986  int next_row = GetSettingsTree().Draw(settings_ptr, r.left + SETTINGTREE_LEFT_OFFSET, r.right - SETTINGTREE_RIGHT_OFFSET, top_pos,
1987  this->vscroll->GetPosition(), last_row, this->last_clicked);
1988  if (next_row == 0) DrawString(r.left + SETTINGTREE_LEFT_OFFSET, r.right - SETTINGTREE_RIGHT_OFFSET, top_pos, STR_CONFIG_SETTINGS_NONE);
1989  break;
1990  }
1991 
1992  case WID_GS_HELP_TEXT:
1993  if (this->last_clicked != NULL) {
1994  const SettingDesc *sd = this->last_clicked->setting;
1995 
1996  int y = r.top;
1997  switch (sd->GetType()) {
1998  case ST_COMPANY: SetDParam(0, _game_mode == GM_MENU ? STR_CONFIG_SETTING_TYPE_COMPANY_MENU : STR_CONFIG_SETTING_TYPE_COMPANY_INGAME); break;
1999  case ST_CLIENT: SetDParam(0, STR_CONFIG_SETTING_TYPE_CLIENT); break;
2000  case ST_GAME: SetDParam(0, _game_mode == GM_MENU ? STR_CONFIG_SETTING_TYPE_GAME_MENU : STR_CONFIG_SETTING_TYPE_GAME_INGAME); break;
2001  default: NOT_REACHED();
2002  }
2003  DrawString(r.left, r.right, y, STR_CONFIG_SETTING_TYPE);
2004  y += FONT_HEIGHT_NORMAL;
2005 
2006  int32 default_value = ReadValue(&sd->desc.def, sd->save.conv);
2007  this->last_clicked->SetValueDParams(0, default_value);
2008  DrawString(r.left, r.right, y, STR_CONFIG_SETTING_DEFAULT_VALUE);
2010 
2011  DrawStringMultiLine(r.left, r.right, y, r.bottom, this->last_clicked->GetHelpText(), TC_WHITE);
2012  }
2013  break;
2014 
2015  default:
2016  break;
2017  }
2018  }
2019 
2025  {
2026  if (this->last_clicked != pe) this->SetDirty();
2027  this->last_clicked = pe;
2028  }
2029 
2030  virtual void OnClick(Point pt, int widget, int click_count)
2031  {
2032  switch (widget) {
2033  case WID_GS_EXPAND_ALL:
2034  this->manually_changed_folding = true;
2036  this->InvalidateData();
2037  break;
2038 
2039  case WID_GS_COLLAPSE_ALL:
2040  this->manually_changed_folding = true;
2042  this->InvalidateData();
2043  break;
2044 
2045  case WID_GS_RESTRICT_DROPDOWN: {
2046  DropDownList *list = this->BuildDropDownList(widget);
2047  if (list != NULL) {
2048  ShowDropDownList(this, list, this->filter.mode, widget);
2049  }
2050  break;
2051  }
2052 
2053  case WID_GS_TYPE_DROPDOWN: {
2054  DropDownList *list = this->BuildDropDownList(widget);
2055  if (list != NULL) {
2056  ShowDropDownList(this, list, this->filter.type, widget);
2057  }
2058  break;
2059  }
2060  }
2061 
2062  if (widget != WID_GS_OPTIONSPANEL) return;
2063 
2064  uint btn = this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_GS_OPTIONSPANEL, SETTINGTREE_TOP_OFFSET);
2065  if (btn == INT_MAX || (int)btn < this->warn_lines) return;
2066  btn -= this->warn_lines;
2067 
2068  uint cur_row = 0;
2069  BaseSettingEntry *clicked_entry = GetSettingsTree().FindEntry(btn, &cur_row);
2070 
2071  if (clicked_entry == NULL) return; // Clicked below the last setting of the page
2072 
2073  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
2074  if (x < 0) return; // Clicked left of the entry
2075 
2076  SettingsPage *clicked_page = dynamic_cast<SettingsPage*>(clicked_entry);
2077  if (clicked_page != NULL) {
2078  this->SetDisplayedHelpText(NULL);
2079  clicked_page->folded = !clicked_page->folded; // Flip 'folded'-ness of the sub-page
2080 
2081  this->manually_changed_folding = true;
2082 
2083  this->InvalidateData();
2084  return;
2085  }
2086 
2087  SettingEntry *pe = dynamic_cast<SettingEntry*>(clicked_entry);
2088  assert(pe != NULL);
2089  const SettingDesc *sd = pe->setting;
2090 
2091  /* return if action is only active in network, or only settable by server */
2092  if (!sd->IsEditable()) {
2093  this->SetDisplayedHelpText(pe);
2094  return;
2095  }
2096 
2097  const void *var = ResolveVariableAddress(settings_ptr, sd);
2098  int32 value = (int32)ReadValue(var, sd->save.conv);
2099 
2100  /* clicked on the icon on the left side. Either scroller, bool on/off or dropdown */
2101  if (x < SETTING_BUTTON_WIDTH && (sd->desc.flags & SGF_MULTISTRING)) {
2102  const SettingDescBase *sdb = &sd->desc;
2103  this->SetDisplayedHelpText(pe);
2104 
2105  if (this->valuedropdown_entry == pe) {
2106  /* unclick the dropdown */
2107  HideDropDownMenu(this);
2108  this->closing_dropdown = false;
2109  this->valuedropdown_entry->SetButtons(0);
2110  this->valuedropdown_entry = NULL;
2111  } else {
2112  if (this->valuedropdown_entry != NULL) this->valuedropdown_entry->SetButtons(0);
2113  this->closing_dropdown = false;
2114 
2115  const NWidgetBase *wid = this->GetWidget<NWidgetBase>(WID_GS_OPTIONSPANEL);
2116  int rel_y = (pt.y - (int)wid->pos_y - SETTINGTREE_TOP_OFFSET) % wid->resize_y;
2117 
2118  Rect wi_rect;
2119  wi_rect.left = pt.x - (_current_text_dir == TD_RTL ? SETTING_BUTTON_WIDTH - 1 - x : x);
2120  wi_rect.right = wi_rect.left + SETTING_BUTTON_WIDTH - 1;
2121  wi_rect.top = pt.y - rel_y + (SETTING_HEIGHT - SETTING_BUTTON_HEIGHT) / 2;
2122  wi_rect.bottom = wi_rect.top + SETTING_BUTTON_HEIGHT - 1;
2123 
2124  /* For dropdowns we also have to check the y position thoroughly, the mouse may not above the just opening dropdown */
2125  if (pt.y >= wi_rect.top && pt.y <= wi_rect.bottom) {
2126  this->valuedropdown_entry = pe;
2127  this->valuedropdown_entry->SetButtons(SEF_LEFT_DEPRESSED);
2128 
2129  DropDownList *list = new DropDownList();
2130  for (int i = sdb->min; i <= (int)sdb->max; i++) {
2131  *list->Append() = new DropDownListStringItem(sdb->str_val + i - sdb->min, i, false);
2132  }
2133 
2134  ShowDropDownListAt(this, list, value, -1, wi_rect, COLOUR_ORANGE, true);
2135  }
2136  }
2137  this->SetDirty();
2138  } else if (x < SETTING_BUTTON_WIDTH) {
2139  this->SetDisplayedHelpText(pe);
2140  const SettingDescBase *sdb = &sd->desc;
2141  int32 oldvalue = value;
2142 
2143  switch (sdb->cmd) {
2144  case SDT_BOOLX: value ^= 1; break;
2145  case SDT_ONEOFMANY:
2146  case SDT_NUMX: {
2147  /* Add a dynamic step-size to the scroller. In a maximum of
2148  * 50-steps you should be able to get from min to max,
2149  * unless specified otherwise in the 'interval' variable
2150  * of the current setting. */
2151  uint32 step = (sdb->interval == 0) ? ((sdb->max - sdb->min) / 50) : sdb->interval;
2152  if (step == 0) step = 1;
2153 
2154  /* don't allow too fast scrolling */
2155  if ((this->flags & WF_TIMEOUT) && this->timeout_timer > 1) {
2156  _left_button_clicked = false;
2157  return;
2158  }
2159 
2160  /* Increase or decrease the value and clamp it to extremes */
2161  if (x >= SETTING_BUTTON_WIDTH / 2) {
2162  value += step;
2163  if (sdb->min < 0) {
2164  assert((int32)sdb->max >= 0);
2165  if (value > (int32)sdb->max) value = (int32)sdb->max;
2166  } else {
2167  if ((uint32)value > sdb->max) value = (int32)sdb->max;
2168  }
2169  if (value < sdb->min) value = sdb->min; // skip between "disabled" and minimum
2170  } else {
2171  value -= step;
2172  if (value < sdb->min) value = (sdb->flags & SGF_0ISDISABLED) ? 0 : sdb->min;
2173  }
2174 
2175  /* Set up scroller timeout for numeric values */
2176  if (value != oldvalue) {
2177  if (this->clicked_entry != NULL) { // Release previous buttons if any
2178  this->clicked_entry->SetButtons(0);
2179  }
2180  this->clicked_entry = pe;
2181  this->clicked_entry->SetButtons((x >= SETTING_BUTTON_WIDTH / 2) != (_current_text_dir == TD_RTL) ? SEF_RIGHT_DEPRESSED : SEF_LEFT_DEPRESSED);
2182  this->SetTimeout();
2183  _left_button_clicked = false;
2184  }
2185  break;
2186  }
2187 
2188  default: NOT_REACHED();
2189  }
2190 
2191  if (value != oldvalue) {
2192  if ((sd->desc.flags & SGF_PER_COMPANY) != 0) {
2193  SetCompanySetting(pe->index, value);
2194  } else {
2195  SetSettingValue(pe->index, value);
2196  }
2197  this->SetDirty();
2198  }
2199  } else {
2200  /* Only open editbox if clicked for the second time, and only for types where it is sensible for. */
2201  if (this->last_clicked == pe && sd->desc.cmd != SDT_BOOLX && !(sd->desc.flags & SGF_MULTISTRING)) {
2202  /* Show the correct currency-translated value */
2203  if (sd->desc.flags & SGF_CURRENCY) value *= _currency->rate;
2204 
2205  this->valuewindow_entry = pe;
2206  SetDParam(0, value);
2207  ShowQueryString(STR_JUST_INT, STR_CONFIG_SETTING_QUERY_CAPTION, 10, this, CS_NUMERAL, QSF_ENABLE_DEFAULT);
2208  }
2209  this->SetDisplayedHelpText(pe);
2210  }
2211  }
2212 
2213  virtual void OnTimeout()
2214  {
2215  if (this->clicked_entry != NULL) { // On timeout, release any depressed buttons
2216  this->clicked_entry->SetButtons(0);
2217  this->clicked_entry = NULL;
2218  this->SetDirty();
2219  }
2220  }
2221 
2222  virtual void OnQueryTextFinished(char *str)
2223  {
2224  /* The user pressed cancel */
2225  if (str == NULL) return;
2226 
2227  assert(this->valuewindow_entry != NULL);
2228  const SettingDesc *sd = this->valuewindow_entry->setting;
2229 
2230  int32 value;
2231  if (!StrEmpty(str)) {
2232  value = atoi(str);
2233 
2234  /* Save the correct currency-translated value */
2235  if (sd->desc.flags & SGF_CURRENCY) value /= _currency->rate;
2236  } else {
2237  value = (int32)(size_t)sd->desc.def;
2238  }
2239 
2240  if ((sd->desc.flags & SGF_PER_COMPANY) != 0) {
2241  SetCompanySetting(this->valuewindow_entry->index, value);
2242  } else {
2243  SetSettingValue(this->valuewindow_entry->index, value);
2244  }
2245  this->SetDirty();
2246  }
2247 
2248  virtual void OnDropdownSelect(int widget, int index)
2249  {
2250  switch (widget) {
2252  this->filter.mode = (RestrictionMode)index;
2253  if (this->filter.mode == RM_CHANGED_AGAINST_DEFAULT ||
2254  this->filter.mode == RM_CHANGED_AGAINST_NEW) {
2255 
2256  if (!this->manually_changed_folding) {
2257  /* Expand all when selecting 'changes'. Update the filter state first, in case it becomes less restrictive in some cases. */
2258  GetSettingsTree().UpdateFilterState(this->filter, false);
2260  }
2261  } else {
2262  /* Non-'changes' filter. Save as default. */
2264  }
2265  this->InvalidateData();
2266  break;
2267 
2268  case WID_GS_TYPE_DROPDOWN:
2269  this->filter.type = (SettingType)index;
2270  this->InvalidateData();
2271  break;
2272 
2273  default:
2274  if (widget < 0) {
2275  /* Deal with drop down boxes on the panel. */
2276  assert(this->valuedropdown_entry != NULL);
2277  const SettingDesc *sd = this->valuedropdown_entry->setting;
2278  assert(sd->desc.flags & SGF_MULTISTRING);
2279 
2280  if ((sd->desc.flags & SGF_PER_COMPANY) != 0) {
2281  SetCompanySetting(this->valuedropdown_entry->index, index);
2282  } else {
2283  SetSettingValue(this->valuedropdown_entry->index, index);
2284  }
2285 
2286  this->SetDirty();
2287  }
2288  break;
2289  }
2290  }
2291 
2292  virtual void OnDropdownClose(Point pt, int widget, int index, bool instant_close)
2293  {
2294  if (widget >= 0) {
2295  /* Normally the default implementation of OnDropdownClose() takes care of
2296  * a few things. We want that behaviour here too, but only for
2297  * "normal" dropdown boxes. The special dropdown boxes added for every
2298  * setting that needs one can't have this call. */
2299  Window::OnDropdownClose(pt, widget, index, instant_close);
2300  } else {
2301  /* We cannot raise the dropdown button just yet. OnClick needs some hint, whether
2302  * the same dropdown button was clicked again, and then not open the dropdown again.
2303  * So, we only remember that it was closed, and process it on the next OnPaint, which is
2304  * after OnClick. */
2305  assert(this->valuedropdown_entry != NULL);
2306  this->closing_dropdown = true;
2307  this->SetDirty();
2308  }
2309  }
2310 
2311  virtual void OnInvalidateData(int data = 0, bool gui_scope = true)
2312  {
2313  if (!gui_scope) return;
2314 
2315  /* Update which settings are to be visible. */
2316  RestrictionMode min_level = (this->filter.mode <= RM_ALL) ? this->filter.mode : RM_BASIC;
2317  this->filter.min_cat = min_level;
2318  this->filter.type_hides = false;
2319  GetSettingsTree().UpdateFilterState(this->filter, false);
2320 
2321  if (this->filter.string.IsEmpty()) {
2322  this->warn_missing = WHR_NONE;
2323  } else if (min_level < this->filter.min_cat) {
2324  this->warn_missing = this->filter.type_hides ? WHR_CATEGORY_TYPE : WHR_CATEGORY;
2325  } else {
2326  this->warn_missing = this->filter.type_hides ? WHR_TYPE : WHR_NONE;
2327  }
2328  this->vscroll->SetCount(GetSettingsTree().Length() + this->warn_lines);
2329 
2330  if (this->last_clicked != NULL && !GetSettingsTree().IsVisible(this->last_clicked)) {
2331  this->SetDisplayedHelpText(NULL);
2332  }
2333 
2334  bool all_folded = true;
2335  bool all_unfolded = true;
2336  GetSettingsTree().GetFoldingState(all_folded, all_unfolded);
2337  this->SetWidgetDisabledState(WID_GS_EXPAND_ALL, all_unfolded);
2338  this->SetWidgetDisabledState(WID_GS_COLLAPSE_ALL, all_folded);
2339  }
2340 
2341  virtual void OnEditboxChanged(int wid)
2342  {
2343  if (wid == WID_GS_FILTER) {
2344  this->filter.string.SetFilterTerm(this->filter_editbox.text.buf);
2345  if (!this->filter.string.IsEmpty() && !this->manually_changed_folding) {
2346  /* User never expanded/collapsed single pages and entered a filter term.
2347  * Expand everything, to save weird expand clicks, */
2349  }
2350  this->InvalidateData();
2351  }
2352  }
2353 
2354  virtual void OnResize()
2355  {
2356  this->vscroll->SetCapacityFromWidget(this, WID_GS_OPTIONSPANEL, SETTINGTREE_TOP_OFFSET + SETTINGTREE_BOTTOM_OFFSET);
2357  }
2358 };
2359 
2361 
2362 static const NWidgetPart _nested_settings_selection_widgets[] = {
2364  NWidget(WWT_CLOSEBOX, COLOUR_MAUVE),
2365  NWidget(WWT_CAPTION, COLOUR_MAUVE), SetDataTip(STR_CONFIG_SETTING_TREE_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
2366  NWidget(WWT_DEFSIZEBOX, COLOUR_MAUVE),
2367  EndContainer(),
2368  NWidget(WWT_PANEL, COLOUR_MAUVE),
2371  NWidget(WWT_TEXT, COLOUR_MAUVE, WID_GS_RESTRICT_CATEGORY), SetDataTip(STR_CONFIG_SETTING_RESTRICT_CATEGORY, STR_NULL),
2372  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),
2373  EndContainer(),
2375  NWidget(WWT_TEXT, COLOUR_MAUVE, WID_GS_RESTRICT_TYPE), SetDataTip(STR_CONFIG_SETTING_RESTRICT_TYPE, STR_NULL),
2376  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),
2377  EndContainer(),
2378  EndContainer(),
2381  NWidget(WWT_TEXT, COLOUR_MAUVE), SetFill(0, 1), SetDataTip(STR_CONFIG_SETTING_FILTER_TITLE, STR_NULL),
2382  NWidget(WWT_EDITBOX, COLOUR_MAUVE, WID_GS_FILTER), SetFill(1, 0), SetMinimalSize(50, 12), SetResize(1, 0),
2383  SetDataTip(STR_LIST_FILTER_OSKTITLE, STR_LIST_FILTER_TOOLTIP),
2384  EndContainer(),
2385  EndContainer(),
2388  NWidget(NWID_VSCROLLBAR, COLOUR_MAUVE, WID_GS_SCROLLBAR),
2389  EndContainer(),
2390  NWidget(WWT_PANEL, COLOUR_MAUVE), SetMinimalSize(400, 40),
2391  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_GS_HELP_TEXT), SetMinimalSize(300, 25), SetFill(1, 1), SetResize(1, 0),
2393  EndContainer(),
2395  NWidget(WWT_PUSHTXTBTN, COLOUR_MAUVE, WID_GS_EXPAND_ALL), SetDataTip(STR_CONFIG_SETTING_EXPAND_ALL, STR_NULL),
2396  NWidget(WWT_PUSHTXTBTN, COLOUR_MAUVE, WID_GS_COLLAPSE_ALL), SetDataTip(STR_CONFIG_SETTING_COLLAPSE_ALL, STR_NULL),
2397  NWidget(WWT_PANEL, COLOUR_MAUVE), SetFill(1, 0), SetResize(1, 0),
2398  EndContainer(),
2399  NWidget(WWT_RESIZEBOX, COLOUR_MAUVE),
2400  EndContainer(),
2401 };
2402 
2403 static WindowDesc _settings_selection_desc(
2404  WDP_CENTER, "settings", 510, 450,
2406  0,
2407  _nested_settings_selection_widgets, lengthof(_nested_settings_selection_widgets)
2408 );
2409 
2412 {
2414  new GameSettingsWindow(&_settings_selection_desc);
2415 }
2416 
2417 
2427 void DrawArrowButtons(int x, int y, Colours button_colour, byte state, bool clickable_left, bool clickable_right)
2428 {
2429  int colour = _colour_gradient[button_colour][2];
2430  Dimension dim = NWidgetScrollbar::GetHorizontalDimension();
2431 
2432  DrawFrameRect(x, y, x + dim.width - 1, y + dim.height - 1, button_colour, (state == 1) ? FR_LOWERED : FR_NONE);
2433  DrawFrameRect(x + dim.width, y, x + dim.width + dim.width - 1, y + dim.height - 1, button_colour, (state == 2) ? FR_LOWERED : FR_NONE);
2434  DrawSprite(SPR_ARROW_LEFT, PAL_NONE, x + WD_IMGBTN_LEFT, y + WD_IMGBTN_TOP);
2435  DrawSprite(SPR_ARROW_RIGHT, PAL_NONE, x + WD_IMGBTN_LEFT + dim.width, y + WD_IMGBTN_TOP);
2436 
2437  /* Grey out the buttons that aren't clickable */
2438  bool rtl = _current_text_dir == TD_RTL;
2439  if (rtl ? !clickable_right : !clickable_left) {
2440  GfxFillRect(x + 1, y, x + dim.width - 1, y + dim.height - 2, colour, FILLRECT_CHECKER);
2441  }
2442  if (rtl ? !clickable_left : !clickable_right) {
2443  GfxFillRect(x + dim.width + 1, y, x + dim.width + dim.width - 1, y + dim.height - 2, colour, FILLRECT_CHECKER);
2444  }
2445 }
2446 
2455 void DrawDropDownButton(int x, int y, Colours button_colour, bool state, bool clickable)
2456 {
2457  int colour = _colour_gradient[button_colour][2];
2458 
2459  DrawFrameRect(x, y, x + SETTING_BUTTON_WIDTH - 1, y + SETTING_BUTTON_HEIGHT - 1, button_colour, state ? FR_LOWERED : FR_NONE);
2460  DrawSprite(SPR_ARROW_DOWN, PAL_NONE, x + (SETTING_BUTTON_WIDTH - NWidgetScrollbar::GetVerticalDimension().width) / 2 + state, y + 2 + state);
2461 
2462  if (!clickable) {
2463  GfxFillRect(x + 1, y, x + SETTING_BUTTON_WIDTH - 1, y + SETTING_BUTTON_HEIGHT - 2, colour, FILLRECT_CHECKER);
2464  }
2465 }
2466 
2474 void DrawBoolButton(int x, int y, bool state, bool clickable)
2475 {
2476  static const Colours _bool_ctabs[2][2] = {{COLOUR_CREAM, COLOUR_RED}, {COLOUR_DARK_GREEN, COLOUR_GREEN}};
2477  DrawFrameRect(x, y, x + SETTING_BUTTON_WIDTH - 1, y + SETTING_BUTTON_HEIGHT - 1, _bool_ctabs[state][clickable], state ? FR_LOWERED : FR_NONE);
2478 }
2479 
2481  int query_widget;
2482 
2483  CustomCurrencyWindow(WindowDesc *desc) : Window(desc)
2484  {
2485  this->InitNested();
2486 
2487  SetButtonState();
2488  }
2489 
2490  void SetButtonState()
2491  {
2492  this->SetWidgetDisabledState(WID_CC_RATE_DOWN, _custom_currency.rate == 1);
2493  this->SetWidgetDisabledState(WID_CC_RATE_UP, _custom_currency.rate == UINT16_MAX);
2494  this->SetWidgetDisabledState(WID_CC_YEAR_DOWN, _custom_currency.to_euro == CF_NOEURO);
2495  this->SetWidgetDisabledState(WID_CC_YEAR_UP, _custom_currency.to_euro == MAX_YEAR);
2496  }
2497 
2498  virtual void SetStringParameters(int widget) const
2499  {
2500  switch (widget) {
2501  case WID_CC_RATE: SetDParam(0, 1); SetDParam(1, 1); break;
2502  case WID_CC_SEPARATOR: SetDParamStr(0, _custom_currency.separator); break;
2503  case WID_CC_PREFIX: SetDParamStr(0, _custom_currency.prefix); break;
2504  case WID_CC_SUFFIX: SetDParamStr(0, _custom_currency.suffix); break;
2505  case WID_CC_YEAR:
2506  SetDParam(0, (_custom_currency.to_euro != CF_NOEURO) ? STR_CURRENCY_SWITCH_TO_EURO : STR_CURRENCY_SWITCH_TO_EURO_NEVER);
2507  SetDParam(1, _custom_currency.to_euro);
2508  break;
2509 
2510  case WID_CC_PREVIEW:
2511  SetDParam(0, 10000);
2512  break;
2513  }
2514  }
2515 
2516  virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
2517  {
2518  switch (widget) {
2519  /* Set the appropriate width for the edit 'buttons' */
2520  case WID_CC_SEPARATOR_EDIT:
2521  case WID_CC_PREFIX_EDIT:
2522  case WID_CC_SUFFIX_EDIT:
2523  size->width = this->GetWidget<NWidgetBase>(WID_CC_RATE_DOWN)->smallest_x + this->GetWidget<NWidgetBase>(WID_CC_RATE_UP)->smallest_x;
2524  break;
2525 
2526  /* Make sure the window is wide enough for the widest exchange rate */
2527  case WID_CC_RATE:
2528  SetDParam(0, 1);
2529  SetDParam(1, INT32_MAX);
2530  *size = GetStringBoundingBox(STR_CURRENCY_EXCHANGE_RATE);
2531  break;
2532  }
2533  }
2534 
2535  virtual void OnClick(Point pt, int widget, int click_count)
2536  {
2537  int line = 0;
2538  int len = 0;
2539  StringID str = 0;
2540  CharSetFilter afilter = CS_ALPHANUMERAL;
2541 
2542  switch (widget) {
2543  case WID_CC_RATE_DOWN:
2544  if (_custom_currency.rate > 1) _custom_currency.rate--;
2545  if (_custom_currency.rate == 1) this->DisableWidget(WID_CC_RATE_DOWN);
2547  break;
2548 
2549  case WID_CC_RATE_UP:
2550  if (_custom_currency.rate < UINT16_MAX) _custom_currency.rate++;
2551  if (_custom_currency.rate == UINT16_MAX) this->DisableWidget(WID_CC_RATE_UP);
2553  break;
2554 
2555  case WID_CC_RATE:
2556  SetDParam(0, _custom_currency.rate);
2557  str = STR_JUST_INT;
2558  len = 5;
2559  line = WID_CC_RATE;
2560  afilter = CS_NUMERAL;
2561  break;
2562 
2563  case WID_CC_SEPARATOR_EDIT:
2564  case WID_CC_SEPARATOR:
2565  SetDParamStr(0, _custom_currency.separator);
2566  str = STR_JUST_RAW_STRING;
2567  len = 1;
2568  line = WID_CC_SEPARATOR;
2569  break;
2570 
2571  case WID_CC_PREFIX_EDIT:
2572  case WID_CC_PREFIX:
2573  SetDParamStr(0, _custom_currency.prefix);
2574  str = STR_JUST_RAW_STRING;
2575  len = 12;
2576  line = WID_CC_PREFIX;
2577  break;
2578 
2579  case WID_CC_SUFFIX_EDIT:
2580  case WID_CC_SUFFIX:
2581  SetDParamStr(0, _custom_currency.suffix);
2582  str = STR_JUST_RAW_STRING;
2583  len = 12;
2584  line = WID_CC_SUFFIX;
2585  break;
2586 
2587  case WID_CC_YEAR_DOWN:
2588  _custom_currency.to_euro = (_custom_currency.to_euro <= 2000) ? CF_NOEURO : _custom_currency.to_euro - 1;
2589  if (_custom_currency.to_euro == CF_NOEURO) this->DisableWidget(WID_CC_YEAR_DOWN);
2591  break;
2592 
2593  case WID_CC_YEAR_UP:
2594  _custom_currency.to_euro = Clamp(_custom_currency.to_euro + 1, 2000, MAX_YEAR);
2595  if (_custom_currency.to_euro == MAX_YEAR) this->DisableWidget(WID_CC_YEAR_UP);
2597  break;
2598 
2599  case WID_CC_YEAR:
2600  SetDParam(0, _custom_currency.to_euro);
2601  str = STR_JUST_INT;
2602  len = 7;
2603  line = WID_CC_YEAR;
2604  afilter = CS_NUMERAL;
2605  break;
2606  }
2607 
2608  if (len != 0) {
2609  this->query_widget = line;
2610  ShowQueryString(str, STR_CURRENCY_CHANGE_PARAMETER, len + 1, this, afilter, QSF_NONE);
2611  }
2612 
2613  this->SetTimeout();
2614  this->SetDirty();
2615  }
2616 
2617  virtual void OnQueryTextFinished(char *str)
2618  {
2619  if (str == NULL) return;
2620 
2621  switch (this->query_widget) {
2622  case WID_CC_RATE:
2623  _custom_currency.rate = Clamp(atoi(str), 1, UINT16_MAX);
2624  break;
2625 
2626  case WID_CC_SEPARATOR: // Thousands separator
2627  strecpy(_custom_currency.separator, str, lastof(_custom_currency.separator));
2628  break;
2629 
2630  case WID_CC_PREFIX:
2631  strecpy(_custom_currency.prefix, str, lastof(_custom_currency.prefix));
2632  break;
2633 
2634  case WID_CC_SUFFIX:
2635  strecpy(_custom_currency.suffix, str, lastof(_custom_currency.suffix));
2636  break;
2637 
2638  case WID_CC_YEAR: { // Year to switch to euro
2639  int val = atoi(str);
2640 
2641  _custom_currency.to_euro = (val < 2000 ? CF_NOEURO : min(val, MAX_YEAR));
2642  break;
2643  }
2644  }
2646  SetButtonState();
2647  }
2648 
2649  virtual void OnTimeout()
2650  {
2651  this->SetDirty();
2652  }
2653 };
2654 
2655 static const NWidgetPart _nested_cust_currency_widgets[] = {
2657  NWidget(WWT_CLOSEBOX, COLOUR_GREY),
2658  NWidget(WWT_CAPTION, COLOUR_GREY), SetDataTip(STR_CURRENCY_WINDOW, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
2659  EndContainer(),
2660  NWidget(WWT_PANEL, COLOUR_GREY),
2662  NWidget(NWID_HORIZONTAL), SetPIP(10, 0, 5),
2663  NWidget(WWT_PUSHARROWBTN, COLOUR_YELLOW, WID_CC_RATE_DOWN), SetDataTip(AWV_DECREASE, STR_CURRENCY_DECREASE_EXCHANGE_RATE_TOOLTIP),
2664  NWidget(WWT_PUSHARROWBTN, COLOUR_YELLOW, WID_CC_RATE_UP), SetDataTip(AWV_INCREASE, STR_CURRENCY_INCREASE_EXCHANGE_RATE_TOOLTIP),
2666  NWidget(WWT_TEXT, COLOUR_BLUE, WID_CC_RATE), SetDataTip(STR_CURRENCY_EXCHANGE_RATE, STR_CURRENCY_SET_EXCHANGE_RATE_TOOLTIP), SetFill(1, 0),
2667  EndContainer(),
2668  NWidget(NWID_HORIZONTAL), SetPIP(10, 0, 5),
2669  NWidget(WWT_PUSHBTN, COLOUR_DARK_BLUE, WID_CC_SEPARATOR_EDIT), SetDataTip(0x0, STR_CURRENCY_SET_CUSTOM_CURRENCY_SEPARATOR_TOOLTIP), SetFill(0, 1),
2671  NWidget(WWT_TEXT, COLOUR_BLUE, WID_CC_SEPARATOR), SetDataTip(STR_CURRENCY_SEPARATOR, STR_CURRENCY_SET_CUSTOM_CURRENCY_SEPARATOR_TOOLTIP), SetFill(1, 0),
2672  EndContainer(),
2673  NWidget(NWID_HORIZONTAL), SetPIP(10, 0, 5),
2674  NWidget(WWT_PUSHBTN, COLOUR_DARK_BLUE, WID_CC_PREFIX_EDIT), SetDataTip(0x0, STR_CURRENCY_SET_CUSTOM_CURRENCY_PREFIX_TOOLTIP), SetFill(0, 1),
2676  NWidget(WWT_TEXT, COLOUR_BLUE, WID_CC_PREFIX), SetDataTip(STR_CURRENCY_PREFIX, STR_CURRENCY_SET_CUSTOM_CURRENCY_PREFIX_TOOLTIP), SetFill(1, 0),
2677  EndContainer(),
2678  NWidget(NWID_HORIZONTAL), SetPIP(10, 0, 5),
2679  NWidget(WWT_PUSHBTN, COLOUR_DARK_BLUE, WID_CC_SUFFIX_EDIT), SetDataTip(0x0, STR_CURRENCY_SET_CUSTOM_CURRENCY_SUFFIX_TOOLTIP), SetFill(0, 1),
2681  NWidget(WWT_TEXT, COLOUR_BLUE, WID_CC_SUFFIX), SetDataTip(STR_CURRENCY_SUFFIX, STR_CURRENCY_SET_CUSTOM_CURRENCY_SUFFIX_TOOLTIP), SetFill(1, 0),
2682  EndContainer(),
2683  NWidget(NWID_HORIZONTAL), SetPIP(10, 0, 5),
2684  NWidget(WWT_PUSHARROWBTN, COLOUR_YELLOW, WID_CC_YEAR_DOWN), SetDataTip(AWV_DECREASE, STR_CURRENCY_DECREASE_CUSTOM_CURRENCY_TO_EURO_TOOLTIP),
2685  NWidget(WWT_PUSHARROWBTN, COLOUR_YELLOW, WID_CC_YEAR_UP), SetDataTip(AWV_INCREASE, STR_CURRENCY_INCREASE_CUSTOM_CURRENCY_TO_EURO_TOOLTIP),
2687  NWidget(WWT_TEXT, COLOUR_BLUE, WID_CC_YEAR), SetDataTip(STR_JUST_STRING, STR_CURRENCY_SET_CUSTOM_CURRENCY_TO_EURO_TOOLTIP), SetFill(1, 0),
2688  EndContainer(),
2689  EndContainer(),
2690  NWidget(WWT_LABEL, COLOUR_BLUE, WID_CC_PREVIEW),
2691  SetDataTip(STR_CURRENCY_PREVIEW, STR_CURRENCY_CUSTOM_CURRENCY_PREVIEW_TOOLTIP), SetPadding(15, 1, 18, 2),
2692  EndContainer(),
2693 };
2694 
2695 static WindowDesc _cust_currency_desc(
2696  WDP_CENTER, NULL, 0, 0,
2698  0,
2699  _nested_cust_currency_widgets, lengthof(_nested_cust_currency_widgets)
2700 );
2701 
2703 static void ShowCustCurrency()
2704 {
2706  new CustomCurrencyWindow(&_cust_currency_desc);
2707 }
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:324
static NWidgetPart SetResize(int16 dx, int16 dy)
Widget part function for setting the resize step.
Definition: widget_type.h:930
Window(WindowDesc *desc)
Empty constructor, initialization has been moved to InitNested() called from the constructor of the d...
Definition: window.cpp:1851
uint Draw(GameSettings *settings_ptr, int left, int right, int y, uint first_row, uint max_row, BaseSettingEntry *selected, uint cur_row=0, uint parent_last=0) const
Draw a row in the settings panel.
void GfxFillRect(int left, int top, int right, int bottom, int colour, FillRectMode mode)
Applies a certain FillRectMode-operation to a rectangle [left, right] x [top, bottom] on the screen...
Definition: gfx.cpp:113
Rate of currency.
void SetWidgetDisabledState(byte widget_index, bool disab_stat)
Sets the enabled/disabled status of a widget.
Definition: window_gui.h:394
void SetWindowDirty(WindowClass cls, WindowNumber number)
Mark window as dirty (in need of repainting)
Definition: window.cpp:3201
int warn_lines
Number of lines used for warning about missing search results.
void SetWidgetLoweredState(byte widget_index, bool lowered_stat)
Sets the lowered/raised status of a widget.
Definition: window_gui.h:455
uint GetMaxHelpHeight(int maxw)
Get the biggest height of the help texts, if the width is at least maxw.
void SetTimeout()
Set the timeout flag of the window and initiate the timer.
Definition: window_gui.h:368
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:312
int left
x position of left edge of the window
Definition: window_gui.h:319
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:320
Header of Action 0F "universal holder" structure and functions.
Type setting filtered matches away.
int64 ReadValue(const void *ptr, VarType conv)
Return a signed-long version of the value of a setting.
Definition: saveload.cpp:752
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:548
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:404
#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:1812
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.
Dropdown for the font zoom level.
NewGRF license.
Definition: textfile_type.h:21
Base for the GUIs that have an edit box in them.
Data structure for an opened window.
Definition: window_gui.h:278
void FinishInitNested(WindowNumber window_number=0)
Perform the second part of the initialization of a nested widget tree.
Definition: window.cpp:1828
void SetFilterTerm(const char *str)
Set the term to filter on.
Functions to read fonts from files and cache them.
static NWidgetPart SetPadding(uint8 top, uint8 right, uint8 bottom, uint8 left)
Widget part function for setting additional space around a widget.
Definition: widget_type.h:1046
void InitNested(WindowNumber number=0)
Perform complete initialization of the Window with nested widgets, to allow use.
Definition: window.cpp:1841
SettingEntry * last_clicked
If non-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:330
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:1132
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:311
char * stredup(const char *s, const char *last)
Create a duplicate of the given string.
Definition: string.cpp:138
Window for displaying the textfile of a BaseSet.
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:500
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:1159
virtual uint Length() const
Return number of rows needed to display the (filtered) entry.
Data structure describing one page of settings in the settings window.
#define SETTING_BUTTON_WIDTH
Width of setting buttons.
Definition: settings_gui.h:19
CharSetFilter
Valid filter types for IsValidChar.
Definition: string_type.h: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:968
RestrictionMode min_cat
Minimum category needed to display all filtered strings (RM_BASIC, RM_ADVANCED, or RM_ALL)...
void FoldAll()
Recursively close all folds of sub-pages.
virtual void FoldAll()
Recursively close all (filtered) folds of sub-pages.
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:700
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:1146
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:3436
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:1532
int GetStringLineCount(StringID str, int maxw)
Calculates number of lines of string.
Definition: gfx.cpp:573
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:488
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:769
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
ZoomLevelByte _font_zoom
Font Zoom level.
Definition: gfx.cpp:61
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:321
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:284
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:316
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:834
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:3242
Down button.
virtual bool IsVisible(const BaseSettingEntry *item) const
Check whether an entry is visible and not folded or filtered away.
int height
Height of the window (number of pixels down in y direction)
Definition: window_gui.h:322
virtual bool UpdateFilterState(SettingFilter &filter, bool force_visible)
Update the filter state.
void EnableWidget(byte widget_index)
Sets a widget to Enabled.
Definition: window_gui.h:413
void MarkWholeScreenDirty()
This function mark the whole screen as dirty.
Definition: gfx.cpp:1463
GUI functions related to textfiles.
int DrawStringMultiLine(int left, int right, int top, int bottom, const char *str, TextColour colour, StringAlignment align, bool underline, FontSize fontsize)
Draw string, possibly over multiple lines.
Definition: gfx.cpp:621
virtual void OnInvalidateData(int data=0, bool gui_scope=true)
Some data on this window has become invalid.
Definition: window_gui.h:748
(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