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 
564  _font_zoom = (ZoomLevel)(ZOOM_LVL_OUT_4X - index);
565  ClearFontCache();
568  break;
569 
571  this->SetMediaSet<BaseGraphics>(index);
572  break;
573 
575  this->SetMediaSet<BaseSounds>(index);
576  break;
577 
579  ChangeMusicSet(index);
580  break;
581  }
582  }
583 
589  virtual void OnInvalidateData(int data = 0, bool gui_scope = true)
590  {
591  if (!gui_scope) return;
593 
594  bool missing_files = BaseGraphics::GetUsedSet()->GetNumMissing() == 0;
595  this->GetWidget<NWidgetCore>(WID_GO_BASE_GRF_STATUS)->SetDataTip(missing_files ? STR_EMPTY : STR_GAME_OPTIONS_BASE_GRF_STATUS, STR_NULL);
596 
597  for (TextfileType tft = TFT_BEGIN; tft < TFT_END; tft++) {
601  }
602 
603  missing_files = BaseMusic::GetUsedSet()->GetNumInvalid() == 0;
604  this->GetWidget<NWidgetCore>(WID_GO_BASE_MUSIC_STATUS)->SetDataTip(missing_files ? STR_EMPTY : STR_GAME_OPTIONS_BASE_MUSIC_STATUS, STR_NULL);
605  }
606 };
607 
608 static const NWidgetPart _nested_game_options_widgets[] = {
610  NWidget(WWT_CLOSEBOX, COLOUR_GREY),
611  NWidget(WWT_CAPTION, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
612  EndContainer(),
613  NWidget(WWT_PANEL, COLOUR_GREY, WID_GO_BACKGROUND), SetPIP(6, 6, 10),
614  NWidget(NWID_HORIZONTAL), SetPIP(10, 10, 10),
615  NWidget(NWID_VERTICAL), SetPIP(0, 6, 0),
616  NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_ROAD_VEHICLES_FRAME, STR_NULL),
617  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),
618  EndContainer(),
619  NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_AUTOSAVE_FRAME, STR_NULL),
620  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),
621  EndContainer(),
622  NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_RESOLUTION, STR_NULL),
623  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),
625  NWidget(WWT_TEXT, COLOUR_GREY), SetMinimalSize(0, 12), SetFill(1, 0), SetDataTip(STR_GAME_OPTIONS_FULLSCREEN, STR_NULL),
626  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_GO_FULLSCREEN_BUTTON), SetMinimalSize(21, 9), SetDataTip(STR_EMPTY, STR_GAME_OPTIONS_FULLSCREEN_TOOLTIP),
627  EndContainer(),
628  EndContainer(),
629  NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_GUI_ZOOM_FRAME, STR_NULL),
630  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),
631  EndContainer(),
632  EndContainer(),
633 
634  NWidget(NWID_VERTICAL), SetPIP(0, 6, 0),
635  NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_TOWN_NAMES_FRAME, STR_NULL),
636  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),
637  EndContainer(),
638  NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_LANGUAGE, STR_NULL),
639  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),
640  EndContainer(),
641  NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_CURRENCY_UNITS_FRAME, STR_NULL),
642  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),
643  EndContainer(),
644  NWidget(NWID_SPACER), SetMinimalSize(0, 0), SetFill(0, 1),
645  NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_FONT_ZOOM, STR_NULL),
646  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),
647  EndContainer(),
648  EndContainer(),
649  EndContainer(),
650 
651  NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_BASE_GRF, STR_NULL), SetPadding(0, 10, 0, 10),
652  NWidget(NWID_HORIZONTAL), SetPIP(0, 30, 0),
653  NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_BASE_GRF_DROPDOWN), SetMinimalSize(150, 12), SetDataTip(STR_BLACK_RAW_STRING, STR_GAME_OPTIONS_BASE_GRF_TOOLTIP),
654  NWidget(WWT_TEXT, COLOUR_GREY, WID_GO_BASE_GRF_STATUS), SetMinimalSize(150, 12), SetDataTip(STR_EMPTY, STR_NULL), SetFill(1, 0),
655  EndContainer(),
656  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),
658  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),
659  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),
660  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),
661  EndContainer(),
662  EndContainer(),
663 
664  NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_BASE_SFX, STR_NULL), SetPadding(0, 10, 0, 10),
665  NWidget(NWID_HORIZONTAL), SetPIP(0, 30, 0),
666  NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_BASE_SFX_DROPDOWN), SetMinimalSize(150, 12), SetDataTip(STR_BLACK_RAW_STRING, STR_GAME_OPTIONS_BASE_SFX_TOOLTIP),
667  NWidget(NWID_SPACER), SetFill(1, 0),
668  EndContainer(),
669  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),
671  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),
672  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),
673  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),
674  EndContainer(),
675  EndContainer(),
676 
677  NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_BASE_MUSIC, STR_NULL), SetPadding(0, 10, 0, 10),
678  NWidget(NWID_HORIZONTAL), SetPIP(0, 30, 0),
679  NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_BASE_MUSIC_DROPDOWN), SetMinimalSize(150, 12), SetDataTip(STR_BLACK_RAW_STRING, STR_GAME_OPTIONS_BASE_MUSIC_TOOLTIP),
680  NWidget(WWT_TEXT, COLOUR_GREY, WID_GO_BASE_MUSIC_STATUS), SetMinimalSize(150, 12), SetDataTip(STR_EMPTY, STR_NULL), SetFill(1, 0),
681  EndContainer(),
682  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),
684  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),
685  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),
686  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),
687  EndContainer(),
688  EndContainer(),
689  EndContainer(),
690 };
691 
692 static WindowDesc _game_options_desc(
693  WDP_CENTER, "settings_game", 0, 0,
695  0,
696  _nested_game_options_widgets, lengthof(_nested_game_options_widgets)
697 );
698 
701 {
703  new GameOptionsWindow(&_game_options_desc);
704 }
705 
706 static int SETTING_HEIGHT = 11;
707 static const int LEVEL_WIDTH = 15;
708 
717 
718  SEF_LAST_FIELD = 0x04,
719  SEF_FILTERED = 0x08,
720 };
721 
730 };
732 
733 
737  bool type_hides;
740 };
741 
744  byte flags;
745  byte level;
746 
747  BaseSettingEntry() : flags(0), level(0) {}
748  virtual ~BaseSettingEntry() {}
749 
750  virtual void Init(byte level = 0);
751  virtual void FoldAll() {}
752  virtual void UnFoldAll() {}
753 
758  void SetLastField(bool last_field) { if (last_field) SETBITS(this->flags, SEF_LAST_FIELD); else CLRBITS(this->flags, SEF_LAST_FIELD); }
759 
760  virtual uint Length() const = 0;
761  virtual void GetFoldingState(bool &all_folded, bool &all_unfolded) const {}
762  virtual bool IsVisible(const BaseSettingEntry *item) const;
763  virtual BaseSettingEntry *FindEntry(uint row, uint *cur_row);
764  virtual uint GetMaxHelpHeight(int maxw) { return 0; }
765 
770  bool IsFiltered() const { return (this->flags & SEF_FILTERED) != 0; }
771 
772  virtual bool UpdateFilterState(SettingFilter &filter, bool force_visible) = 0;
773 
774  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;
775 
776 protected:
777  virtual void DrawSetting(GameSettings *settings_ptr, int left, int right, int y, bool highlight) const = 0;
778 };
779 
782  const char *name;
784  uint index;
785 
786  SettingEntry(const char *name);
787 
788  virtual void Init(byte level = 0);
789  virtual uint Length() const;
790  virtual uint GetMaxHelpHeight(int maxw);
791  virtual bool UpdateFilterState(SettingFilter &filter, bool force_visible);
792 
793  void SetButtons(byte new_val);
794 
799  inline StringID GetHelpText() const
800  {
801  return this->setting->desc.str_help;
802  }
803 
804  void SetValueDParams(uint first_param, int32 value) const;
805 
806 protected:
807  virtual void DrawSetting(GameSettings *settings_ptr, int left, int right, int y, bool highlight) const;
808 
809 private:
810  bool IsVisibleByRestrictionMode(RestrictionMode mode) const;
811 };
812 
815  typedef std::vector<BaseSettingEntry*> EntryVector;
816  EntryVector entries;
817 
818  template<typename T>
819  T *Add(T *item)
820  {
821  this->entries.push_back(item);
822  return item;
823  }
824 
825  void Init(byte level = 0);
826  void FoldAll();
827  void UnFoldAll();
828 
829  uint Length() const;
830  void GetFoldingState(bool &all_folded, bool &all_unfolded) const;
831  bool IsVisible(const BaseSettingEntry *item) const;
832  BaseSettingEntry *FindEntry(uint row, uint *cur_row);
833  uint GetMaxHelpHeight(int maxw);
834 
835  bool UpdateFilterState(SettingFilter &filter, bool force_visible);
836 
837  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;
838 };
839 
843  bool folded;
844 
845  SettingsPage(StringID title);
846 
847  virtual void Init(byte level = 0);
848  virtual void FoldAll();
849  virtual void UnFoldAll();
850 
851  virtual uint Length() const;
852  virtual void GetFoldingState(bool &all_folded, bool &all_unfolded) const;
853  virtual bool IsVisible(const BaseSettingEntry *item) const;
854  virtual BaseSettingEntry *FindEntry(uint row, uint *cur_row);
855  virtual uint GetMaxHelpHeight(int maxw) { return SettingsContainer::GetMaxHelpHeight(maxw); }
856 
857  virtual bool UpdateFilterState(SettingFilter &filter, bool force_visible);
858 
859  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;
860 
861 protected:
862  virtual void DrawSetting(GameSettings *settings_ptr, int left, int right, int y, bool highlight) const;
863 };
864 
865 /* == BaseSettingEntry methods == */
866 
871 void BaseSettingEntry::Init(byte level)
872 {
873  this->level = level;
874 }
875 
883 {
884  if (this->IsFiltered()) return false;
885  if (this == item) return true;
886  return false;
887 }
888 
895 BaseSettingEntry *BaseSettingEntry::FindEntry(uint row_num, uint *cur_row)
896 {
897  if (this->IsFiltered()) return NULL;
898  if (row_num == *cur_row) return this;
899  (*cur_row)++;
900  return NULL;
901 }
902 
932 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
933 {
934  if (this->IsFiltered()) return cur_row;
935  if (cur_row >= max_row) return cur_row;
936 
937  bool rtl = _current_text_dir == TD_RTL;
938  int offset = rtl ? -4 : 4;
939  int level_width = rtl ? -LEVEL_WIDTH : LEVEL_WIDTH;
940 
941  int x = rtl ? right : left;
942  if (cur_row >= first_row) {
943  int colour = _colour_gradient[COLOUR_ORANGE][4];
944  y += (cur_row - first_row) * SETTING_HEIGHT; // Compute correct y start position
945 
946  /* Draw vertical for parent nesting levels */
947  for (uint lvl = 0; lvl < this->level; lvl++) {
948  if (!HasBit(parent_last, lvl)) GfxDrawLine(x + offset, y, x + offset, y + SETTING_HEIGHT - 1, colour);
949  x += level_width;
950  }
951  /* draw own |- prefix */
952  int halfway_y = y + SETTING_HEIGHT / 2;
953  int bottom_y = (flags & SEF_LAST_FIELD) ? halfway_y : y + SETTING_HEIGHT - 1;
954  GfxDrawLine(x + offset, y, x + offset, bottom_y, colour);
955  /* Small horizontal line from the last vertical line */
956  GfxDrawLine(x + offset, halfway_y, x + level_width - offset, halfway_y, colour);
957  x += level_width;
958 
959  this->DrawSetting(settings_ptr, rtl ? left : x, rtl ? x : right, y, this == selected);
960  }
961  cur_row++;
962 
963  return cur_row;
964 }
965 
966 /* == SettingEntry methods == */
967 
972 SettingEntry::SettingEntry(const char *name)
973 {
974  this->name = name;
975  this->setting = NULL;
976  this->index = 0;
977 }
978 
983 void SettingEntry::Init(byte level)
984 {
985  BaseSettingEntry::Init(level);
986  this->setting = GetSettingFromName(this->name, &this->index);
987  assert(this->setting != NULL);
988 }
989 
995 void SettingEntry::SetButtons(byte new_val)
996 {
997  assert((new_val & ~SEF_BUTTONS_MASK) == 0); // Should not touch any flags outside the buttons
998  this->flags = (this->flags & ~SEF_BUTTONS_MASK) | new_val;
999 }
1000 
1003 {
1004  return this->IsFiltered() ? 0 : 1;
1005 }
1006 
1013 {
1014  return GetStringHeight(this->GetHelpText(), maxw);
1015 }
1016 
1023 {
1024  /* There shall not be any restriction, i.e. all settings shall be visible. */
1025  if (mode == RM_ALL) return true;
1026 
1027  GameSettings *settings_ptr = &GetGameSettings();
1028  const SettingDesc *sd = this->setting;
1029 
1030  if (mode == RM_BASIC) return (this->setting->desc.cat & SC_BASIC_LIST) != 0;
1031  if (mode == RM_ADVANCED) return (this->setting->desc.cat & SC_ADVANCED_LIST) != 0;
1032 
1033  /* Read the current value. */
1034  const void *var = ResolveVariableAddress(settings_ptr, sd);
1035  int64 current_value = ReadValue(var, sd->save.conv);
1036 
1037  int64 filter_value;
1038 
1039  if (mode == RM_CHANGED_AGAINST_DEFAULT) {
1040  /* This entry shall only be visible, if the value deviates from its default value. */
1041 
1042  /* Read the default value. */
1043  filter_value = ReadValue(&sd->desc.def, sd->save.conv);
1044  } else {
1045  assert(mode == RM_CHANGED_AGAINST_NEW);
1046  /* This entry shall only be visible, if the value deviates from
1047  * its value is used when starting a new game. */
1048 
1049  /* Make sure we're not comparing the new game settings against itself. */
1050  assert(settings_ptr != &_settings_newgame);
1051 
1052  /* Read the new game's value. */
1053  var = ResolveVariableAddress(&_settings_newgame, sd);
1054  filter_value = ReadValue(var, sd->save.conv);
1055  }
1056 
1057  return current_value != filter_value;
1058 }
1059 
1066 bool SettingEntry::UpdateFilterState(SettingFilter &filter, bool force_visible)
1067 {
1068  CLRBITS(this->flags, SEF_FILTERED);
1069 
1070  bool visible = true;
1071 
1072  const SettingDesc *sd = this->setting;
1073  if (!force_visible && !filter.string.IsEmpty()) {
1074  /* Process the search text filter for this item. */
1075  filter.string.ResetState();
1076 
1077  const SettingDescBase *sdb = &sd->desc;
1078 
1079  SetDParam(0, STR_EMPTY);
1080  filter.string.AddLine(sdb->str);
1081  filter.string.AddLine(this->GetHelpText());
1082 
1083  visible = filter.string.GetState();
1084  }
1085 
1086  if (visible) {
1087  if (filter.type != ST_ALL && sd->GetType() != filter.type) {
1088  filter.type_hides = true;
1089  visible = false;
1090  }
1091  if (!this->IsVisibleByRestrictionMode(filter.mode)) {
1092  while (filter.min_cat < RM_ALL && (filter.min_cat == filter.mode || !this->IsVisibleByRestrictionMode(filter.min_cat))) filter.min_cat++;
1093  visible = false;
1094  }
1095  }
1096 
1097  if (!visible) SETBITS(this->flags, SEF_FILTERED);
1098  return visible;
1099 }
1100 
1101 
1102 static const void *ResolveVariableAddress(const GameSettings *settings_ptr, const SettingDesc *sd)
1103 {
1104  if ((sd->desc.flags & SGF_PER_COMPANY) != 0) {
1105  if (Company::IsValidID(_local_company) && _game_mode != GM_MENU) {
1107  } else {
1109  }
1110  } else {
1111  return GetVariableAddress(settings_ptr, &sd->save);
1112  }
1113 }
1114 
1120 void SettingEntry::SetValueDParams(uint first_param, int32 value) const
1121 {
1122  const SettingDescBase *sdb = &this->setting->desc;
1123  if (sdb->cmd == SDT_BOOLX) {
1124  SetDParam(first_param++, value != 0 ? STR_CONFIG_SETTING_ON : STR_CONFIG_SETTING_OFF);
1125  } else {
1126  if ((sdb->flags & SGF_MULTISTRING) != 0) {
1127  SetDParam(first_param++, sdb->str_val - sdb->min + value);
1128  } else if ((sdb->flags & SGF_DISPLAY_ABS) != 0) {
1129  SetDParam(first_param++, sdb->str_val + ((value >= 0) ? 1 : 0));
1130  value = abs(value);
1131  } else {
1132  SetDParam(first_param++, sdb->str_val + ((value == 0 && (sdb->flags & SGF_0ISDISABLED) != 0) ? 1 : 0));
1133  }
1134  SetDParam(first_param++, value);
1135  }
1136 }
1137 
1146 void SettingEntry::DrawSetting(GameSettings *settings_ptr, int left, int right, int y, bool highlight) const
1147 {
1148  const SettingDesc *sd = this->setting;
1149  const SettingDescBase *sdb = &sd->desc;
1150  const void *var = ResolveVariableAddress(settings_ptr, sd);
1151  int state = this->flags & SEF_BUTTONS_MASK;
1152 
1153  bool rtl = _current_text_dir == TD_RTL;
1154  uint buttons_left = rtl ? right + 1 - SETTING_BUTTON_WIDTH : left;
1155  uint text_left = left + (rtl ? 0 : SETTING_BUTTON_WIDTH + 5);
1156  uint text_right = right - (rtl ? SETTING_BUTTON_WIDTH + 5 : 0);
1157  uint button_y = y + (SETTING_HEIGHT - SETTING_BUTTON_HEIGHT) / 2;
1158 
1159  /* We do not allow changes of some items when we are a client in a networkgame */
1160  bool editable = sd->IsEditable();
1161 
1162  SetDParam(0, highlight ? STR_ORANGE_STRING1_WHITE : STR_ORANGE_STRING1_LTBLUE);
1163  int32 value = (int32)ReadValue(var, sd->save.conv);
1164  if (sdb->cmd == SDT_BOOLX) {
1165  /* Draw checkbox for boolean-value either on/off */
1166  DrawBoolButton(buttons_left, button_y, value != 0, editable);
1167  } else if ((sdb->flags & SGF_MULTISTRING) != 0) {
1168  /* Draw [v] button for settings of an enum-type */
1169  DrawDropDownButton(buttons_left, button_y, COLOUR_YELLOW, state != 0, editable);
1170  } else {
1171  /* Draw [<][>] boxes for settings of an integer-type */
1172  DrawArrowButtons(buttons_left, button_y, COLOUR_YELLOW, state,
1173  editable && value != (sdb->flags & SGF_0ISDISABLED ? 0 : sdb->min), editable && (uint32)value != sdb->max);
1174  }
1175  this->SetValueDParams(1, value);
1176  DrawString(text_left, text_right, y + (SETTING_HEIGHT - FONT_HEIGHT_NORMAL) / 2, sdb->str, highlight ? TC_WHITE : TC_LIGHT_BLUE);
1177 }
1178 
1179 /* == SettingsContainer methods == */
1180 
1185 void SettingsContainer::Init(byte level)
1186 {
1187  for (EntryVector::iterator it = this->entries.begin(); it != this->entries.end(); ++it) {
1188  (*it)->Init(level);
1189  }
1190 }
1191 
1194 {
1195  for (EntryVector::iterator it = this->entries.begin(); it != this->entries.end(); ++it) {
1196  (*it)->FoldAll();
1197  }
1198 }
1199 
1202 {
1203  for (EntryVector::iterator it = this->entries.begin(); it != this->entries.end(); ++it) {
1204  (*it)->UnFoldAll();
1205  }
1206 }
1207 
1213 void SettingsContainer::GetFoldingState(bool &all_folded, bool &all_unfolded) const
1214 {
1215  for (EntryVector::const_iterator it = this->entries.begin(); it != this->entries.end(); ++it) {
1216  (*it)->GetFoldingState(all_folded, all_unfolded);
1217  }
1218 }
1219 
1226 bool SettingsContainer::UpdateFilterState(SettingFilter &filter, bool force_visible)
1227 {
1228  bool visible = false;
1229  bool first_visible = true;
1230  for (EntryVector::reverse_iterator it = this->entries.rbegin(); it != this->entries.rend(); ++it) {
1231  visible |= (*it)->UpdateFilterState(filter, force_visible);
1232  (*it)->SetLastField(first_visible);
1233  if (visible && first_visible) first_visible = false;
1234  }
1235  return visible;
1236 }
1237 
1238 
1246 {
1247  for (EntryVector::const_iterator it = this->entries.begin(); it != this->entries.end(); ++it) {
1248  if ((*it)->IsVisible(item)) return true;
1249  }
1250  return false;
1251 }
1252 
1255 {
1256  uint length = 0;
1257  for (EntryVector::const_iterator it = this->entries.begin(); it != this->entries.end(); ++it) {
1258  length += (*it)->Length();
1259  }
1260  return length;
1261 }
1262 
1269 BaseSettingEntry *SettingsContainer::FindEntry(uint row_num, uint *cur_row)
1270 {
1271  BaseSettingEntry *pe = NULL;
1272  for (EntryVector::iterator it = this->entries.begin(); it != this->entries.end(); ++it) {
1273  pe = (*it)->FindEntry(row_num, cur_row);
1274  if (pe != NULL) {
1275  break;
1276  }
1277  }
1278  return pe;
1279 }
1280 
1287 {
1288  uint biggest = 0;
1289  for (EntryVector::const_iterator it = this->entries.begin(); it != this->entries.end(); ++it) {
1290  biggest = max(biggest, (*it)->GetMaxHelpHeight(maxw));
1291  }
1292  return biggest;
1293 }
1294 
1295 
1310 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
1311 {
1312  for (EntryVector::const_iterator it = this->entries.begin(); it != this->entries.end(); ++it) {
1313  cur_row = (*it)->Draw(settings_ptr, left, right, y, first_row, max_row, selected, cur_row, parent_last);
1314  if (cur_row >= max_row) {
1315  break;
1316  }
1317  }
1318  return cur_row;
1319 }
1320 
1321 /* == SettingsPage methods == */
1322 
1328 {
1329  this->title = title;
1330  this->folded = true;
1331 }
1332 
1337 void SettingsPage::Init(byte level)
1338 {
1339  BaseSettingEntry::Init(level);
1340  SettingsContainer::Init(level + 1);
1341 }
1342 
1345 {
1346  if (this->IsFiltered()) return;
1347  this->folded = true;
1348 
1350 }
1351 
1354 {
1355  if (this->IsFiltered()) return;
1356  this->folded = false;
1357 
1359 }
1360 
1366 void SettingsPage::GetFoldingState(bool &all_folded, bool &all_unfolded) const
1367 {
1368  if (this->IsFiltered()) return;
1369 
1370  if (this->folded) {
1371  all_unfolded = false;
1372  } else {
1373  all_folded = false;
1374  }
1375 
1376  SettingsContainer::GetFoldingState(all_folded, all_unfolded);
1377 }
1378 
1385 bool SettingsPage::UpdateFilterState(SettingFilter &filter, bool force_visible)
1386 {
1387  if (!force_visible && !filter.string.IsEmpty()) {
1388  filter.string.ResetState();
1389  filter.string.AddLine(this->title);
1390  force_visible = filter.string.GetState();
1391  }
1392 
1393  bool visible = SettingsContainer::UpdateFilterState(filter, force_visible);
1394  if (visible) {
1395  CLRBITS(this->flags, SEF_FILTERED);
1396  } else {
1397  SETBITS(this->flags, SEF_FILTERED);
1398  }
1399  return visible;
1400 }
1401 
1409 {
1410  if (this->IsFiltered()) return false;
1411  if (this == item) return true;
1412  if (this->folded) return false;
1413 
1414  return SettingsContainer::IsVisible(item);
1415 }
1416 
1419 {
1420  if (this->IsFiltered()) return 0;
1421  if (this->folded) return 1; // Only displaying the title
1422 
1423  return 1 + SettingsContainer::Length();
1424 }
1425 
1432 BaseSettingEntry *SettingsPage::FindEntry(uint row_num, uint *cur_row)
1433 {
1434  if (this->IsFiltered()) return NULL;
1435  if (row_num == *cur_row) return this;
1436  (*cur_row)++;
1437  if (this->folded) return NULL;
1438 
1439  return SettingsContainer::FindEntry(row_num, cur_row);
1440 }
1441 
1456 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
1457 {
1458  if (this->IsFiltered()) return cur_row;
1459  if (cur_row >= max_row) return cur_row;
1460 
1461  cur_row = BaseSettingEntry::Draw(settings_ptr, left, right, y, first_row, max_row, selected, cur_row, parent_last);
1462 
1463  if (!this->folded) {
1464  if (this->flags & SEF_LAST_FIELD) {
1465  assert(this->level < 8 * sizeof(parent_last));
1466  SetBit(parent_last, this->level); // Add own last-field state
1467  }
1468 
1469  cur_row = SettingsContainer::Draw(settings_ptr, left, right, y, first_row, max_row, selected, cur_row, parent_last);
1470  }
1471 
1472  return cur_row;
1473 }
1474 
1483 void SettingsPage::DrawSetting(GameSettings *settings_ptr, int left, int right, int y, bool highlight) const
1484 {
1485  bool rtl = _current_text_dir == TD_RTL;
1486  DrawSprite((this->folded ? SPR_CIRCLE_FOLDED : SPR_CIRCLE_UNFOLDED), PAL_NONE, rtl ? right - _circle_size.width : left, y + (SETTING_HEIGHT - _circle_size.height) / 2);
1487  DrawString(rtl ? left : left + _circle_size.width + 2, rtl ? right - _circle_size.width - 2 : right, y + (SETTING_HEIGHT - FONT_HEIGHT_NORMAL) / 2, this->title);
1488 }
1489 
1492 {
1493  static SettingsContainer *main = NULL;
1494 
1495  if (main == NULL)
1496  {
1497  /* Build up the dynamic settings-array only once per OpenTTD session */
1498  main = new SettingsContainer();
1499 
1500  SettingsPage *localisation = main->Add(new SettingsPage(STR_CONFIG_SETTING_LOCALISATION));
1501  {
1502  localisation->Add(new SettingEntry("locale.units_velocity"));
1503  localisation->Add(new SettingEntry("locale.units_power"));
1504  localisation->Add(new SettingEntry("locale.units_weight"));
1505  localisation->Add(new SettingEntry("locale.units_volume"));
1506  localisation->Add(new SettingEntry("locale.units_force"));
1507  localisation->Add(new SettingEntry("locale.units_height"));
1508  localisation->Add(new SettingEntry("gui.date_format_in_default_names"));
1509  }
1510 
1511  SettingsPage *graphics = main->Add(new SettingsPage(STR_CONFIG_SETTING_GRAPHICS));
1512  {
1513  graphics->Add(new SettingEntry("gui.zoom_min"));
1514  graphics->Add(new SettingEntry("gui.zoom_max"));
1515  graphics->Add(new SettingEntry("gui.smallmap_land_colour"));
1516  graphics->Add(new SettingEntry("gui.graph_line_thickness"));
1517  }
1518 
1519  SettingsPage *sound = main->Add(new SettingsPage(STR_CONFIG_SETTING_SOUND));
1520  {
1521  sound->Add(new SettingEntry("sound.click_beep"));
1522  sound->Add(new SettingEntry("sound.confirm"));
1523  sound->Add(new SettingEntry("sound.news_ticker"));
1524  sound->Add(new SettingEntry("sound.news_full"));
1525  sound->Add(new SettingEntry("sound.new_year"));
1526  sound->Add(new SettingEntry("sound.disaster"));
1527  sound->Add(new SettingEntry("sound.vehicle"));
1528  sound->Add(new SettingEntry("sound.ambient"));
1529  }
1530 
1531  SettingsPage *interface = main->Add(new SettingsPage(STR_CONFIG_SETTING_INTERFACE));
1532  {
1533  SettingsPage *general = interface->Add(new SettingsPage(STR_CONFIG_SETTING_INTERFACE_GENERAL));
1534  {
1535  general->Add(new SettingEntry("gui.osk_activation"));
1536  general->Add(new SettingEntry("gui.hover_delay_ms"));
1537  general->Add(new SettingEntry("gui.errmsg_duration"));
1538  general->Add(new SettingEntry("gui.window_snap_radius"));
1539  general->Add(new SettingEntry("gui.window_soft_limit"));
1540  general->Add(new SettingEntry("gui.right_mouse_wnd_close"));
1541  }
1542 
1543  SettingsPage *viewports = interface->Add(new SettingsPage(STR_CONFIG_SETTING_INTERFACE_VIEWPORTS));
1544  {
1545  viewports->Add(new SettingEntry("gui.auto_scrolling"));
1546  viewports->Add(new SettingEntry("gui.scroll_mode"));
1547  viewports->Add(new SettingEntry("gui.smooth_scroll"));
1548  /* While the horizontal scrollwheel scrolling is written as general code, only
1549  * the cocoa (OSX) driver generates input for it.
1550  * Since it's also able to completely disable the scrollwheel will we display it on all platforms anyway */
1551  viewports->Add(new SettingEntry("gui.scrollwheel_scrolling"));
1552  viewports->Add(new SettingEntry("gui.scrollwheel_multiplier"));
1553 #ifdef __APPLE__
1554  /* We might need to emulate a right mouse button on mac */
1555  viewports->Add(new SettingEntry("gui.right_mouse_btn_emulation"));
1556 #endif
1557  viewports->Add(new SettingEntry("gui.population_in_label"));
1558  viewports->Add(new SettingEntry("gui.liveries"));
1559  viewports->Add(new SettingEntry("construction.train_signal_side"));
1560  viewports->Add(new SettingEntry("gui.measure_tooltip"));
1561  viewports->Add(new SettingEntry("gui.loading_indicators"));
1562  viewports->Add(new SettingEntry("gui.show_track_reservation"));
1563  }
1564 
1565  SettingsPage *construction = interface->Add(new SettingsPage(STR_CONFIG_SETTING_INTERFACE_CONSTRUCTION));
1566  {
1567  construction->Add(new SettingEntry("gui.link_terraform_toolbar"));
1568  construction->Add(new SettingEntry("gui.enable_signal_gui"));
1569  construction->Add(new SettingEntry("gui.persistent_buildingtools"));
1570  construction->Add(new SettingEntry("gui.quick_goto"));
1571  construction->Add(new SettingEntry("gui.default_rail_type"));
1572  construction->Add(new SettingEntry("gui.disable_unsuitable_building"));
1573  }
1574 
1575  interface->Add(new SettingEntry("gui.autosave"));
1576  interface->Add(new SettingEntry("gui.toolbar_pos"));
1577  interface->Add(new SettingEntry("gui.statusbar_pos"));
1578  interface->Add(new SettingEntry("gui.prefer_teamchat"));
1579  interface->Add(new SettingEntry("gui.advanced_vehicle_list"));
1580  interface->Add(new SettingEntry("gui.timetable_in_ticks"));
1581  interface->Add(new SettingEntry("gui.timetable_arrival_departure"));
1582  interface->Add(new SettingEntry("gui.expenses_layout"));
1583  }
1584 
1585  SettingsPage *advisors = main->Add(new SettingsPage(STR_CONFIG_SETTING_ADVISORS));
1586  {
1587  advisors->Add(new SettingEntry("gui.coloured_news_year"));
1588  advisors->Add(new SettingEntry("news_display.general"));
1589  advisors->Add(new SettingEntry("news_display.new_vehicles"));
1590  advisors->Add(new SettingEntry("news_display.accident"));
1591  advisors->Add(new SettingEntry("news_display.company_info"));
1592  advisors->Add(new SettingEntry("news_display.acceptance"));
1593  advisors->Add(new SettingEntry("news_display.arrival_player"));
1594  advisors->Add(new SettingEntry("news_display.arrival_other"));
1595  advisors->Add(new SettingEntry("news_display.advice"));
1596  advisors->Add(new SettingEntry("gui.order_review_system"));
1597  advisors->Add(new SettingEntry("gui.vehicle_income_warn"));
1598  advisors->Add(new SettingEntry("gui.lost_vehicle_warn"));
1599  advisors->Add(new SettingEntry("gui.show_finances"));
1600  advisors->Add(new SettingEntry("news_display.economy"));
1601  advisors->Add(new SettingEntry("news_display.subsidies"));
1602  advisors->Add(new SettingEntry("news_display.open"));
1603  advisors->Add(new SettingEntry("news_display.close"));
1604  advisors->Add(new SettingEntry("news_display.production_player"));
1605  advisors->Add(new SettingEntry("news_display.production_other"));
1606  advisors->Add(new SettingEntry("news_display.production_nobody"));
1607  }
1608 
1609  SettingsPage *company = main->Add(new SettingsPage(STR_CONFIG_SETTING_COMPANY));
1610  {
1611  company->Add(new SettingEntry("gui.semaphore_build_before"));
1612  company->Add(new SettingEntry("gui.default_signal_type"));
1613  company->Add(new SettingEntry("gui.cycle_signal_types"));
1614  company->Add(new SettingEntry("gui.drag_signals_fixed_distance"));
1615  company->Add(new SettingEntry("gui.new_nonstop"));
1616  company->Add(new SettingEntry("gui.stop_location"));
1617  company->Add(new SettingEntry("gui.starting_colour"));
1618  company->Add(new SettingEntry("company.engine_renew"));
1619  company->Add(new SettingEntry("company.engine_renew_months"));
1620  company->Add(new SettingEntry("company.engine_renew_money"));
1621  company->Add(new SettingEntry("vehicle.servint_ispercent"));
1622  company->Add(new SettingEntry("vehicle.servint_trains"));
1623  company->Add(new SettingEntry("vehicle.servint_roadveh"));
1624  company->Add(new SettingEntry("vehicle.servint_ships"));
1625  company->Add(new SettingEntry("vehicle.servint_aircraft"));
1626  }
1627 
1628  SettingsPage *accounting = main->Add(new SettingsPage(STR_CONFIG_SETTING_ACCOUNTING));
1629  {
1630  accounting->Add(new SettingEntry("economy.inflation"));
1631  accounting->Add(new SettingEntry("difficulty.initial_interest"));
1632  accounting->Add(new SettingEntry("difficulty.max_loan"));
1633  accounting->Add(new SettingEntry("difficulty.subsidy_multiplier"));
1634  accounting->Add(new SettingEntry("economy.feeder_payment_share"));
1635  accounting->Add(new SettingEntry("economy.infrastructure_maintenance"));
1636  accounting->Add(new SettingEntry("difficulty.vehicle_costs"));
1637  accounting->Add(new SettingEntry("difficulty.construction_cost"));
1638  }
1639 
1640  SettingsPage *vehicles = main->Add(new SettingsPage(STR_CONFIG_SETTING_VEHICLES));
1641  {
1642  SettingsPage *physics = vehicles->Add(new SettingsPage(STR_CONFIG_SETTING_VEHICLES_PHYSICS));
1643  {
1644  physics->Add(new SettingEntry("vehicle.train_acceleration_model"));
1645  physics->Add(new SettingEntry("vehicle.train_slope_steepness"));
1646  physics->Add(new SettingEntry("vehicle.wagon_speed_limits"));
1647  physics->Add(new SettingEntry("vehicle.freight_trains"));
1648  physics->Add(new SettingEntry("vehicle.roadveh_acceleration_model"));
1649  physics->Add(new SettingEntry("vehicle.roadveh_slope_steepness"));
1650  physics->Add(new SettingEntry("vehicle.smoke_amount"));
1651  physics->Add(new SettingEntry("vehicle.plane_speed"));
1652  }
1653 
1654  SettingsPage *routing = vehicles->Add(new SettingsPage(STR_CONFIG_SETTING_VEHICLES_ROUTING));
1655  {
1656  routing->Add(new SettingEntry("pf.pathfinder_for_trains"));
1657  routing->Add(new SettingEntry("difficulty.line_reverse_mode"));
1658  routing->Add(new SettingEntry("pf.reverse_at_signals"));
1659  routing->Add(new SettingEntry("pf.forbid_90_deg"));
1660  routing->Add(new SettingEntry("pf.pathfinder_for_roadvehs"));
1661  routing->Add(new SettingEntry("pf.pathfinder_for_ships"));
1662  }
1663 
1664  vehicles->Add(new SettingEntry("order.no_servicing_if_no_breakdowns"));
1665  vehicles->Add(new SettingEntry("order.serviceathelipad"));
1666  }
1667 
1668  SettingsPage *limitations = main->Add(new SettingsPage(STR_CONFIG_SETTING_LIMITATIONS));
1669  {
1670  limitations->Add(new SettingEntry("construction.command_pause_level"));
1671  limitations->Add(new SettingEntry("construction.autoslope"));
1672  limitations->Add(new SettingEntry("construction.extra_dynamite"));
1673  limitations->Add(new SettingEntry("construction.max_heightlevel"));
1674  limitations->Add(new SettingEntry("construction.max_bridge_length"));
1675  limitations->Add(new SettingEntry("construction.max_bridge_height"));
1676  limitations->Add(new SettingEntry("construction.max_tunnel_length"));
1677  limitations->Add(new SettingEntry("station.never_expire_airports"));
1678  limitations->Add(new SettingEntry("vehicle.never_expire_vehicles"));
1679  limitations->Add(new SettingEntry("vehicle.max_trains"));
1680  limitations->Add(new SettingEntry("vehicle.max_roadveh"));
1681  limitations->Add(new SettingEntry("vehicle.max_aircraft"));
1682  limitations->Add(new SettingEntry("vehicle.max_ships"));
1683  limitations->Add(new SettingEntry("vehicle.max_train_length"));
1684  limitations->Add(new SettingEntry("station.station_spread"));
1685  limitations->Add(new SettingEntry("station.distant_join_stations"));
1686  limitations->Add(new SettingEntry("construction.road_stop_on_town_road"));
1687  limitations->Add(new SettingEntry("construction.road_stop_on_competitor_road"));
1688  limitations->Add(new SettingEntry("vehicle.disable_elrails"));
1689  }
1690 
1691  SettingsPage *disasters = main->Add(new SettingsPage(STR_CONFIG_SETTING_ACCIDENTS));
1692  {
1693  disasters->Add(new SettingEntry("difficulty.disasters"));
1694  disasters->Add(new SettingEntry("difficulty.economy"));
1695  disasters->Add(new SettingEntry("difficulty.vehicle_breakdowns"));
1696  disasters->Add(new SettingEntry("vehicle.plane_crashes"));
1697  }
1698 
1699  SettingsPage *genworld = main->Add(new SettingsPage(STR_CONFIG_SETTING_GENWORLD));
1700  {
1701  genworld->Add(new SettingEntry("game_creation.landscape"));
1702  genworld->Add(new SettingEntry("game_creation.land_generator"));
1703  genworld->Add(new SettingEntry("difficulty.terrain_type"));
1704  genworld->Add(new SettingEntry("game_creation.tgen_smoothness"));
1705  genworld->Add(new SettingEntry("game_creation.variety"));
1706  genworld->Add(new SettingEntry("game_creation.snow_line_height"));
1707  genworld->Add(new SettingEntry("game_creation.amount_of_rivers"));
1708  genworld->Add(new SettingEntry("game_creation.tree_placer"));
1709  genworld->Add(new SettingEntry("vehicle.road_side"));
1710  genworld->Add(new SettingEntry("economy.larger_towns"));
1711  genworld->Add(new SettingEntry("economy.initial_city_size"));
1712  genworld->Add(new SettingEntry("economy.town_layout"));
1713  genworld->Add(new SettingEntry("difficulty.industry_density"));
1714  genworld->Add(new SettingEntry("gui.pause_on_newgame"));
1715  }
1716 
1717  SettingsPage *environment = main->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT));
1718  {
1719  SettingsPage *authorities = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_AUTHORITIES));
1720  {
1721  authorities->Add(new SettingEntry("difficulty.town_council_tolerance"));
1722  authorities->Add(new SettingEntry("economy.bribe"));
1723  authorities->Add(new SettingEntry("economy.exclusive_rights"));
1724  authorities->Add(new SettingEntry("economy.fund_roads"));
1725  authorities->Add(new SettingEntry("economy.fund_buildings"));
1726  authorities->Add(new SettingEntry("economy.station_noise_level"));
1727  }
1728 
1729  SettingsPage *towns = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_TOWNS));
1730  {
1731  towns->Add(new SettingEntry("economy.town_growth_rate"));
1732  towns->Add(new SettingEntry("economy.allow_town_roads"));
1733  towns->Add(new SettingEntry("economy.allow_town_level_crossings"));
1734  towns->Add(new SettingEntry("economy.found_town"));
1735  }
1736 
1737  SettingsPage *industries = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_INDUSTRIES));
1738  {
1739  industries->Add(new SettingEntry("construction.raw_industry_construction"));
1740  industries->Add(new SettingEntry("construction.industry_platform"));
1741  industries->Add(new SettingEntry("economy.multiple_industry_per_town"));
1742  industries->Add(new SettingEntry("game_creation.oil_refinery_limit"));
1743  industries->Add(new SettingEntry("economy.smooth_economy"));
1744  }
1745 
1746  SettingsPage *cdist = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_CARGODIST));
1747  {
1748  cdist->Add(new SettingEntry("linkgraph.recalc_time"));
1749  cdist->Add(new SettingEntry("linkgraph.recalc_interval"));
1750  cdist->Add(new SettingEntry("linkgraph.distribution_pax"));
1751  cdist->Add(new SettingEntry("linkgraph.distribution_mail"));
1752  cdist->Add(new SettingEntry("linkgraph.distribution_armoured"));
1753  cdist->Add(new SettingEntry("linkgraph.distribution_default"));
1754  cdist->Add(new SettingEntry("linkgraph.accuracy"));
1755  cdist->Add(new SettingEntry("linkgraph.demand_distance"));
1756  cdist->Add(new SettingEntry("linkgraph.demand_size"));
1757  cdist->Add(new SettingEntry("linkgraph.short_path_saturation"));
1758  }
1759 
1760  environment->Add(new SettingEntry("station.modified_catchment"));
1761  environment->Add(new SettingEntry("construction.extra_tree_placement"));
1762  }
1763 
1764  SettingsPage *ai = main->Add(new SettingsPage(STR_CONFIG_SETTING_AI));
1765  {
1766  SettingsPage *npc = ai->Add(new SettingsPage(STR_CONFIG_SETTING_AI_NPC));
1767  {
1768  npc->Add(new SettingEntry("script.settings_profile"));
1769  npc->Add(new SettingEntry("script.script_max_opcode_till_suspend"));
1770  npc->Add(new SettingEntry("difficulty.competitor_speed"));
1771  npc->Add(new SettingEntry("ai.ai_in_multiplayer"));
1772  npc->Add(new SettingEntry("ai.ai_disable_veh_train"));
1773  npc->Add(new SettingEntry("ai.ai_disable_veh_roadveh"));
1774  npc->Add(new SettingEntry("ai.ai_disable_veh_aircraft"));
1775  npc->Add(new SettingEntry("ai.ai_disable_veh_ship"));
1776  }
1777 
1778  ai->Add(new SettingEntry("economy.give_money"));
1779  ai->Add(new SettingEntry("economy.allow_shares"));
1780  }
1781 
1782  main->Init();
1783  }
1784  return *main;
1785 }
1786 
1787 static const StringID _game_settings_restrict_dropdown[] = {
1788  STR_CONFIG_SETTING_RESTRICT_BASIC, // RM_BASIC
1789  STR_CONFIG_SETTING_RESTRICT_ADVANCED, // RM_ADVANCED
1790  STR_CONFIG_SETTING_RESTRICT_ALL, // RM_ALL
1791  STR_CONFIG_SETTING_RESTRICT_CHANGED_AGAINST_DEFAULT, // RM_CHANGED_AGAINST_DEFAULT
1792  STR_CONFIG_SETTING_RESTRICT_CHANGED_AGAINST_NEW, // RM_CHANGED_AGAINST_NEW
1793 };
1794 assert_compile(lengthof(_game_settings_restrict_dropdown) == RM_END);
1795 
1802 };
1803 
1806  static const int SETTINGTREE_LEFT_OFFSET = 5;
1807  static const int SETTINGTREE_RIGHT_OFFSET = 5;
1808  static const int SETTINGTREE_TOP_OFFSET = 5;
1809  static const int SETTINGTREE_BOTTOM_OFFSET = 5;
1810 
1812 
1818 
1824 
1825  Scrollbar *vscroll;
1826 
1827  GameSettingsWindow(WindowDesc *desc) : Window(desc), filter_editbox(50)
1828  {
1829  this->warn_missing = WHR_NONE;
1830  this->warn_lines = 0;
1832  this->filter.min_cat = RM_ALL;
1833  this->filter.type = ST_ALL;
1834  this->filter.type_hides = false;
1835  this->settings_ptr = &GetGameSettings();
1836 
1837  _circle_size = maxdim(GetSpriteSize(SPR_CIRCLE_FOLDED), GetSpriteSize(SPR_CIRCLE_UNFOLDED));
1838  GetSettingsTree().FoldAll(); // Close all sub-pages
1839 
1840  this->valuewindow_entry = NULL; // No setting entry for which a entry window is opened
1841  this->clicked_entry = NULL; // No numeric setting buttons are depressed
1842  this->last_clicked = NULL;
1843  this->valuedropdown_entry = NULL;
1844  this->closing_dropdown = false;
1845  this->manually_changed_folding = false;
1846 
1847  this->CreateNestedTree();
1848  this->vscroll = this->GetScrollbar(WID_GS_SCROLLBAR);
1850 
1851  this->querystrings[WID_GS_FILTER] = &this->filter_editbox;
1852  this->filter_editbox.cancel_button = QueryString::ACTION_CLEAR;
1854 
1855  this->InvalidateData();
1856  }
1857 
1858  virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
1859  {
1860  switch (widget) {
1861  case WID_GS_OPTIONSPANEL:
1862  resize->height = SETTING_HEIGHT = max(max<int>(_circle_size.height, SETTING_BUTTON_HEIGHT), FONT_HEIGHT_NORMAL) + 1;
1863  resize->width = 1;
1864 
1865  size->height = 5 * resize->height + SETTINGTREE_TOP_OFFSET + SETTINGTREE_BOTTOM_OFFSET;
1866  break;
1867 
1868  case WID_GS_HELP_TEXT: {
1869  static const StringID setting_types[] = {
1870  STR_CONFIG_SETTING_TYPE_CLIENT,
1871  STR_CONFIG_SETTING_TYPE_COMPANY_MENU, STR_CONFIG_SETTING_TYPE_COMPANY_INGAME,
1872  STR_CONFIG_SETTING_TYPE_GAME_MENU, STR_CONFIG_SETTING_TYPE_GAME_INGAME,
1873  };
1874  for (uint i = 0; i < lengthof(setting_types); i++) {
1875  SetDParam(0, setting_types[i]);
1876  size->width = max(size->width, GetStringBoundingBox(STR_CONFIG_SETTING_TYPE).width);
1877  }
1878  size->height = 2 * FONT_HEIGHT_NORMAL + WD_PAR_VSEP_NORMAL +
1879  max(size->height, GetSettingsTree().GetMaxHelpHeight(size->width));
1880  break;
1881  }
1882 
1884  case WID_GS_RESTRICT_TYPE:
1885  size->width = max(GetStringBoundingBox(STR_CONFIG_SETTING_RESTRICT_CATEGORY).width, GetStringBoundingBox(STR_CONFIG_SETTING_RESTRICT_TYPE).width);
1886  break;
1887 
1888  default:
1889  break;
1890  }
1891  }
1892 
1893  virtual void OnPaint()
1894  {
1895  if (this->closing_dropdown) {
1896  this->closing_dropdown = false;
1897  assert(this->valuedropdown_entry != NULL);
1898  this->valuedropdown_entry->SetButtons(0);
1899  this->valuedropdown_entry = NULL;
1900  }
1901 
1902  /* Reserve the correct number of lines for the 'some search results are hidden' notice in the central settings display panel. */
1903  const NWidgetBase *panel = this->GetWidget<NWidgetBase>(WID_GS_OPTIONSPANEL);
1904  StringID warn_str = STR_CONFIG_SETTING_CATEGORY_HIDES - 1 + this->warn_missing;
1905  int new_warn_lines;
1906  if (this->warn_missing == WHR_NONE) {
1907  new_warn_lines = 0;
1908  } else {
1909  SetDParam(0, _game_settings_restrict_dropdown[this->filter.min_cat]);
1910  new_warn_lines = GetStringLineCount(warn_str, panel->current_x);
1911  }
1912  if (this->warn_lines != new_warn_lines) {
1913  this->vscroll->SetCount(this->vscroll->GetCount() - this->warn_lines + new_warn_lines);
1914  this->warn_lines = new_warn_lines;
1915  }
1916 
1917  this->DrawWidgets();
1918 
1919  /* Draw the 'some search results are hidden' notice. */
1920  if (this->warn_missing != WHR_NONE) {
1921  const int left = panel->pos_x;
1922  const int right = left + panel->current_x - 1;
1923  const int top = panel->pos_y + WD_FRAMETEXT_TOP + (SETTING_HEIGHT - FONT_HEIGHT_NORMAL) * this->warn_lines / 2;
1924  SetDParam(0, _game_settings_restrict_dropdown[this->filter.min_cat]);
1925  if (this->warn_lines == 1) {
1926  /* If the warning fits at one line, center it. */
1927  DrawString(left + WD_FRAMETEXT_LEFT, right - WD_FRAMETEXT_RIGHT, top, warn_str, TC_FROMSTRING, SA_HOR_CENTER);
1928  } else {
1929  DrawStringMultiLine(left + WD_FRAMERECT_LEFT, right - WD_FRAMERECT_RIGHT, top, INT32_MAX, warn_str, TC_FROMSTRING, SA_HOR_CENTER);
1930  }
1931  }
1932  }
1933 
1934  virtual void SetStringParameters(int widget) const
1935  {
1936  switch (widget) {
1938  SetDParam(0, _game_settings_restrict_dropdown[this->filter.mode]);
1939  break;
1940 
1941  case WID_GS_TYPE_DROPDOWN:
1942  switch (this->filter.type) {
1943  case ST_GAME: SetDParam(0, _game_mode == GM_MENU ? STR_CONFIG_SETTING_TYPE_DROPDOWN_GAME_MENU : STR_CONFIG_SETTING_TYPE_DROPDOWN_GAME_INGAME); break;
1944  case ST_COMPANY: SetDParam(0, _game_mode == GM_MENU ? STR_CONFIG_SETTING_TYPE_DROPDOWN_COMPANY_MENU : STR_CONFIG_SETTING_TYPE_DROPDOWN_COMPANY_INGAME); break;
1945  case ST_CLIENT: SetDParam(0, STR_CONFIG_SETTING_TYPE_DROPDOWN_CLIENT); break;
1946  default: SetDParam(0, STR_CONFIG_SETTING_TYPE_DROPDOWN_ALL); break;
1947  }
1948  break;
1949  }
1950  }
1951 
1952  DropDownList *BuildDropDownList(int widget) const
1953  {
1954  DropDownList *list = NULL;
1955  switch (widget) {
1957  list = new DropDownList();
1958 
1959  for (int mode = 0; mode != RM_END; mode++) {
1960  /* If we are in adv. settings screen for the new game's settings,
1961  * we don't want to allow comparing with new game's settings. */
1962  bool disabled = mode == RM_CHANGED_AGAINST_NEW && settings_ptr == &_settings_newgame;
1963 
1964  *list->Append() = new DropDownListStringItem(_game_settings_restrict_dropdown[mode], mode, disabled);
1965  }
1966  break;
1967 
1968  case WID_GS_TYPE_DROPDOWN:
1969  list = new DropDownList();
1970  *list->Append() = new DropDownListStringItem(STR_CONFIG_SETTING_TYPE_DROPDOWN_ALL, ST_ALL, false);
1971  *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);
1972  *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);
1973  *list->Append() = new DropDownListStringItem(STR_CONFIG_SETTING_TYPE_DROPDOWN_CLIENT, ST_CLIENT, false);
1974  break;
1975  }
1976  return list;
1977  }
1978 
1979  virtual void DrawWidget(const Rect &r, int widget) const
1980  {
1981  switch (widget) {
1982  case WID_GS_OPTIONSPANEL: {
1983  int top_pos = r.top + SETTINGTREE_TOP_OFFSET + 1 + this->warn_lines * SETTING_HEIGHT;
1984  uint last_row = this->vscroll->GetPosition() + this->vscroll->GetCapacity() - this->warn_lines;
1985  int next_row = GetSettingsTree().Draw(settings_ptr, r.left + SETTINGTREE_LEFT_OFFSET, r.right - SETTINGTREE_RIGHT_OFFSET, top_pos,
1986  this->vscroll->GetPosition(), last_row, this->last_clicked);
1987  if (next_row == 0) DrawString(r.left + SETTINGTREE_LEFT_OFFSET, r.right - SETTINGTREE_RIGHT_OFFSET, top_pos, STR_CONFIG_SETTINGS_NONE);
1988  break;
1989  }
1990 
1991  case WID_GS_HELP_TEXT:
1992  if (this->last_clicked != NULL) {
1993  const SettingDesc *sd = this->last_clicked->setting;
1994 
1995  int y = r.top;
1996  switch (sd->GetType()) {
1997  case ST_COMPANY: SetDParam(0, _game_mode == GM_MENU ? STR_CONFIG_SETTING_TYPE_COMPANY_MENU : STR_CONFIG_SETTING_TYPE_COMPANY_INGAME); break;
1998  case ST_CLIENT: SetDParam(0, STR_CONFIG_SETTING_TYPE_CLIENT); break;
1999  case ST_GAME: SetDParam(0, _game_mode == GM_MENU ? STR_CONFIG_SETTING_TYPE_GAME_MENU : STR_CONFIG_SETTING_TYPE_GAME_INGAME); break;
2000  default: NOT_REACHED();
2001  }
2002  DrawString(r.left, r.right, y, STR_CONFIG_SETTING_TYPE);
2003  y += FONT_HEIGHT_NORMAL;
2004 
2005  int32 default_value = ReadValue(&sd->desc.def, sd->save.conv);
2006  this->last_clicked->SetValueDParams(0, default_value);
2007  DrawString(r.left, r.right, y, STR_CONFIG_SETTING_DEFAULT_VALUE);
2009 
2010  DrawStringMultiLine(r.left, r.right, y, r.bottom, this->last_clicked->GetHelpText(), TC_WHITE);
2011  }
2012  break;
2013 
2014  default:
2015  break;
2016  }
2017  }
2018 
2024  {
2025  if (this->last_clicked != pe) this->SetDirty();
2026  this->last_clicked = pe;
2027  }
2028 
2029  virtual void OnClick(Point pt, int widget, int click_count)
2030  {
2031  switch (widget) {
2032  case WID_GS_EXPAND_ALL:
2033  this->manually_changed_folding = true;
2035  this->InvalidateData();
2036  break;
2037 
2038  case WID_GS_COLLAPSE_ALL:
2039  this->manually_changed_folding = true;
2041  this->InvalidateData();
2042  break;
2043 
2044  case WID_GS_RESTRICT_DROPDOWN: {
2045  DropDownList *list = this->BuildDropDownList(widget);
2046  if (list != NULL) {
2047  ShowDropDownList(this, list, this->filter.mode, widget);
2048  }
2049  break;
2050  }
2051 
2052  case WID_GS_TYPE_DROPDOWN: {
2053  DropDownList *list = this->BuildDropDownList(widget);
2054  if (list != NULL) {
2055  ShowDropDownList(this, list, this->filter.type, widget);
2056  }
2057  break;
2058  }
2059  }
2060 
2061  if (widget != WID_GS_OPTIONSPANEL) return;
2062 
2063  uint btn = this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_GS_OPTIONSPANEL, SETTINGTREE_TOP_OFFSET);
2064  if (btn == INT_MAX || (int)btn < this->warn_lines) return;
2065  btn -= this->warn_lines;
2066 
2067  uint cur_row = 0;
2068  BaseSettingEntry *clicked_entry = GetSettingsTree().FindEntry(btn, &cur_row);
2069 
2070  if (clicked_entry == NULL) return; // Clicked below the last setting of the page
2071 
2072  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
2073  if (x < 0) return; // Clicked left of the entry
2074 
2075  SettingsPage *clicked_page = dynamic_cast<SettingsPage*>(clicked_entry);
2076  if (clicked_page != NULL) {
2077  this->SetDisplayedHelpText(NULL);
2078  clicked_page->folded = !clicked_page->folded; // Flip 'folded'-ness of the sub-page
2079 
2080  this->manually_changed_folding = true;
2081 
2082  this->InvalidateData();
2083  return;
2084  }
2085 
2086  SettingEntry *pe = dynamic_cast<SettingEntry*>(clicked_entry);
2087  assert(pe != NULL);
2088  const SettingDesc *sd = pe->setting;
2089 
2090  /* return if action is only active in network, or only settable by server */
2091  if (!sd->IsEditable()) {
2092  this->SetDisplayedHelpText(pe);
2093  return;
2094  }
2095 
2096  const void *var = ResolveVariableAddress(settings_ptr, sd);
2097  int32 value = (int32)ReadValue(var, sd->save.conv);
2098 
2099  /* clicked on the icon on the left side. Either scroller, bool on/off or dropdown */
2100  if (x < SETTING_BUTTON_WIDTH && (sd->desc.flags & SGF_MULTISTRING)) {
2101  const SettingDescBase *sdb = &sd->desc;
2102  this->SetDisplayedHelpText(pe);
2103 
2104  if (this->valuedropdown_entry == pe) {
2105  /* unclick the dropdown */
2106  HideDropDownMenu(this);
2107  this->closing_dropdown = false;
2108  this->valuedropdown_entry->SetButtons(0);
2109  this->valuedropdown_entry = NULL;
2110  } else {
2111  if (this->valuedropdown_entry != NULL) this->valuedropdown_entry->SetButtons(0);
2112  this->closing_dropdown = false;
2113 
2114  const NWidgetBase *wid = this->GetWidget<NWidgetBase>(WID_GS_OPTIONSPANEL);
2115  int rel_y = (pt.y - (int)wid->pos_y - SETTINGTREE_TOP_OFFSET) % wid->resize_y;
2116 
2117  Rect wi_rect;
2118  wi_rect.left = pt.x - (_current_text_dir == TD_RTL ? SETTING_BUTTON_WIDTH - 1 - x : x);
2119  wi_rect.right = wi_rect.left + SETTING_BUTTON_WIDTH - 1;
2120  wi_rect.top = pt.y - rel_y + (SETTING_HEIGHT - SETTING_BUTTON_HEIGHT) / 2;
2121  wi_rect.bottom = wi_rect.top + SETTING_BUTTON_HEIGHT - 1;
2122 
2123  /* For dropdowns we also have to check the y position thoroughly, the mouse may not above the just opening dropdown */
2124  if (pt.y >= wi_rect.top && pt.y <= wi_rect.bottom) {
2125  this->valuedropdown_entry = pe;
2126  this->valuedropdown_entry->SetButtons(SEF_LEFT_DEPRESSED);
2127 
2128  DropDownList *list = new DropDownList();
2129  for (int i = sdb->min; i <= (int)sdb->max; i++) {
2130  *list->Append() = new DropDownListStringItem(sdb->str_val + i - sdb->min, i, false);
2131  }
2132 
2133  ShowDropDownListAt(this, list, value, -1, wi_rect, COLOUR_ORANGE, true);
2134  }
2135  }
2136  this->SetDirty();
2137  } else if (x < SETTING_BUTTON_WIDTH) {
2138  this->SetDisplayedHelpText(pe);
2139  const SettingDescBase *sdb = &sd->desc;
2140  int32 oldvalue = value;
2141 
2142  switch (sdb->cmd) {
2143  case SDT_BOOLX: value ^= 1; break;
2144  case SDT_ONEOFMANY:
2145  case SDT_NUMX: {
2146  /* Add a dynamic step-size to the scroller. In a maximum of
2147  * 50-steps you should be able to get from min to max,
2148  * unless specified otherwise in the 'interval' variable
2149  * of the current setting. */
2150  uint32 step = (sdb->interval == 0) ? ((sdb->max - sdb->min) / 50) : sdb->interval;
2151  if (step == 0) step = 1;
2152 
2153  /* don't allow too fast scrolling */
2154  if ((this->flags & WF_TIMEOUT) && this->timeout_timer > 1) {
2155  _left_button_clicked = false;
2156  return;
2157  }
2158 
2159  /* Increase or decrease the value and clamp it to extremes */
2160  if (x >= SETTING_BUTTON_WIDTH / 2) {
2161  value += step;
2162  if (sdb->min < 0) {
2163  assert((int32)sdb->max >= 0);
2164  if (value > (int32)sdb->max) value = (int32)sdb->max;
2165  } else {
2166  if ((uint32)value > sdb->max) value = (int32)sdb->max;
2167  }
2168  if (value < sdb->min) value = sdb->min; // skip between "disabled" and minimum
2169  } else {
2170  value -= step;
2171  if (value < sdb->min) value = (sdb->flags & SGF_0ISDISABLED) ? 0 : sdb->min;
2172  }
2173 
2174  /* Set up scroller timeout for numeric values */
2175  if (value != oldvalue) {
2176  if (this->clicked_entry != NULL) { // Release previous buttons if any
2177  this->clicked_entry->SetButtons(0);
2178  }
2179  this->clicked_entry = pe;
2180  this->clicked_entry->SetButtons((x >= SETTING_BUTTON_WIDTH / 2) != (_current_text_dir == TD_RTL) ? SEF_RIGHT_DEPRESSED : SEF_LEFT_DEPRESSED);
2181  this->SetTimeout();
2182  _left_button_clicked = false;
2183  }
2184  break;
2185  }
2186 
2187  default: NOT_REACHED();
2188  }
2189 
2190  if (value != oldvalue) {
2191  if ((sd->desc.flags & SGF_PER_COMPANY) != 0) {
2192  SetCompanySetting(pe->index, value);
2193  } else {
2194  SetSettingValue(pe->index, value);
2195  }
2196  this->SetDirty();
2197  }
2198  } else {
2199  /* Only open editbox if clicked for the second time, and only for types where it is sensible for. */
2200  if (this->last_clicked == pe && sd->desc.cmd != SDT_BOOLX && !(sd->desc.flags & SGF_MULTISTRING)) {
2201  /* Show the correct currency-translated value */
2202  if (sd->desc.flags & SGF_CURRENCY) value *= _currency->rate;
2203 
2204  this->valuewindow_entry = pe;
2205  SetDParam(0, value);
2206  ShowQueryString(STR_JUST_INT, STR_CONFIG_SETTING_QUERY_CAPTION, 10, this, CS_NUMERAL, QSF_ENABLE_DEFAULT);
2207  }
2208  this->SetDisplayedHelpText(pe);
2209  }
2210  }
2211 
2212  virtual void OnTimeout()
2213  {
2214  if (this->clicked_entry != NULL) { // On timeout, release any depressed buttons
2215  this->clicked_entry->SetButtons(0);
2216  this->clicked_entry = NULL;
2217  this->SetDirty();
2218  }
2219  }
2220 
2221  virtual void OnQueryTextFinished(char *str)
2222  {
2223  /* The user pressed cancel */
2224  if (str == NULL) return;
2225 
2226  assert(this->valuewindow_entry != NULL);
2227  const SettingDesc *sd = this->valuewindow_entry->setting;
2228 
2229  int32 value;
2230  if (!StrEmpty(str)) {
2231  value = atoi(str);
2232 
2233  /* Save the correct currency-translated value */
2234  if (sd->desc.flags & SGF_CURRENCY) value /= _currency->rate;
2235  } else {
2236  value = (int32)(size_t)sd->desc.def;
2237  }
2238 
2239  if ((sd->desc.flags & SGF_PER_COMPANY) != 0) {
2240  SetCompanySetting(this->valuewindow_entry->index, value);
2241  } else {
2242  SetSettingValue(this->valuewindow_entry->index, value);
2243  }
2244  this->SetDirty();
2245  }
2246 
2247  virtual void OnDropdownSelect(int widget, int index)
2248  {
2249  switch (widget) {
2251  this->filter.mode = (RestrictionMode)index;
2252  if (this->filter.mode == RM_CHANGED_AGAINST_DEFAULT ||
2253  this->filter.mode == RM_CHANGED_AGAINST_NEW) {
2254 
2255  if (!this->manually_changed_folding) {
2256  /* Expand all when selecting 'changes'. Update the filter state first, in case it becomes less restrictive in some cases. */
2257  GetSettingsTree().UpdateFilterState(this->filter, false);
2259  }
2260  } else {
2261  /* Non-'changes' filter. Save as default. */
2263  }
2264  this->InvalidateData();
2265  break;
2266 
2267  case WID_GS_TYPE_DROPDOWN:
2268  this->filter.type = (SettingType)index;
2269  this->InvalidateData();
2270  break;
2271 
2272  default:
2273  if (widget < 0) {
2274  /* Deal with drop down boxes on the panel. */
2275  assert(this->valuedropdown_entry != NULL);
2276  const SettingDesc *sd = this->valuedropdown_entry->setting;
2277  assert(sd->desc.flags & SGF_MULTISTRING);
2278 
2279  if ((sd->desc.flags & SGF_PER_COMPANY) != 0) {
2280  SetCompanySetting(this->valuedropdown_entry->index, index);
2281  } else {
2282  SetSettingValue(this->valuedropdown_entry->index, index);
2283  }
2284 
2285  this->SetDirty();
2286  }
2287  break;
2288  }
2289  }
2290 
2291  virtual void OnDropdownClose(Point pt, int widget, int index, bool instant_close)
2292  {
2293  if (widget >= 0) {
2294  /* Normally the default implementation of OnDropdownClose() takes care of
2295  * a few things. We want that behaviour here too, but only for
2296  * "normal" dropdown boxes. The special dropdown boxes added for every
2297  * setting that needs one can't have this call. */
2298  Window::OnDropdownClose(pt, widget, index, instant_close);
2299  } else {
2300  /* We cannot raise the dropdown button just yet. OnClick needs some hint, whether
2301  * the same dropdown button was clicked again, and then not open the dropdown again.
2302  * So, we only remember that it was closed, and process it on the next OnPaint, which is
2303  * after OnClick. */
2304  assert(this->valuedropdown_entry != NULL);
2305  this->closing_dropdown = true;
2306  this->SetDirty();
2307  }
2308  }
2309 
2310  virtual void OnInvalidateData(int data = 0, bool gui_scope = true)
2311  {
2312  if (!gui_scope) return;
2313 
2314  /* Update which settings are to be visible. */
2315  RestrictionMode min_level = (this->filter.mode <= RM_ALL) ? this->filter.mode : RM_BASIC;
2316  this->filter.min_cat = min_level;
2317  this->filter.type_hides = false;
2318  GetSettingsTree().UpdateFilterState(this->filter, false);
2319 
2320  if (this->filter.string.IsEmpty()) {
2321  this->warn_missing = WHR_NONE;
2322  } else if (min_level < this->filter.min_cat) {
2323  this->warn_missing = this->filter.type_hides ? WHR_CATEGORY_TYPE : WHR_CATEGORY;
2324  } else {
2325  this->warn_missing = this->filter.type_hides ? WHR_TYPE : WHR_NONE;
2326  }
2327  this->vscroll->SetCount(GetSettingsTree().Length() + this->warn_lines);
2328 
2329  if (this->last_clicked != NULL && !GetSettingsTree().IsVisible(this->last_clicked)) {
2330  this->SetDisplayedHelpText(NULL);
2331  }
2332 
2333  bool all_folded = true;
2334  bool all_unfolded = true;
2335  GetSettingsTree().GetFoldingState(all_folded, all_unfolded);
2336  this->SetWidgetDisabledState(WID_GS_EXPAND_ALL, all_unfolded);
2337  this->SetWidgetDisabledState(WID_GS_COLLAPSE_ALL, all_folded);
2338  }
2339 
2340  virtual void OnEditboxChanged(int wid)
2341  {
2342  if (wid == WID_GS_FILTER) {
2343  this->filter.string.SetFilterTerm(this->filter_editbox.text.buf);
2344  if (!this->filter.string.IsEmpty() && !this->manually_changed_folding) {
2345  /* User never expanded/collapsed single pages and entered a filter term.
2346  * Expand everything, to save weird expand clicks, */
2348  }
2349  this->InvalidateData();
2350  }
2351  }
2352 
2353  virtual void OnResize()
2354  {
2355  this->vscroll->SetCapacityFromWidget(this, WID_GS_OPTIONSPANEL, SETTINGTREE_TOP_OFFSET + SETTINGTREE_BOTTOM_OFFSET);
2356  }
2357 };
2358 
2360 
2361 static const NWidgetPart _nested_settings_selection_widgets[] = {
2363  NWidget(WWT_CLOSEBOX, COLOUR_MAUVE),
2364  NWidget(WWT_CAPTION, COLOUR_MAUVE), SetDataTip(STR_CONFIG_SETTING_TREE_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
2365  NWidget(WWT_DEFSIZEBOX, COLOUR_MAUVE),
2366  EndContainer(),
2367  NWidget(WWT_PANEL, COLOUR_MAUVE),
2370  NWidget(WWT_TEXT, COLOUR_MAUVE, WID_GS_RESTRICT_CATEGORY), SetDataTip(STR_CONFIG_SETTING_RESTRICT_CATEGORY, STR_NULL),
2371  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),
2372  EndContainer(),
2374  NWidget(WWT_TEXT, COLOUR_MAUVE, WID_GS_RESTRICT_TYPE), SetDataTip(STR_CONFIG_SETTING_RESTRICT_TYPE, STR_NULL),
2375  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),
2376  EndContainer(),
2377  EndContainer(),
2380  NWidget(WWT_TEXT, COLOUR_MAUVE), SetFill(0, 1), SetDataTip(STR_CONFIG_SETTING_FILTER_TITLE, STR_NULL),
2381  NWidget(WWT_EDITBOX, COLOUR_MAUVE, WID_GS_FILTER), SetFill(1, 0), SetMinimalSize(50, 12), SetResize(1, 0),
2382  SetDataTip(STR_LIST_FILTER_OSKTITLE, STR_LIST_FILTER_TOOLTIP),
2383  EndContainer(),
2384  EndContainer(),
2387  NWidget(NWID_VSCROLLBAR, COLOUR_MAUVE, WID_GS_SCROLLBAR),
2388  EndContainer(),
2389  NWidget(WWT_PANEL, COLOUR_MAUVE), SetMinimalSize(400, 40),
2390  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_GS_HELP_TEXT), SetMinimalSize(300, 25), SetFill(1, 1), SetResize(1, 0),
2392  EndContainer(),
2394  NWidget(WWT_PUSHTXTBTN, COLOUR_MAUVE, WID_GS_EXPAND_ALL), SetDataTip(STR_CONFIG_SETTING_EXPAND_ALL, STR_NULL),
2395  NWidget(WWT_PUSHTXTBTN, COLOUR_MAUVE, WID_GS_COLLAPSE_ALL), SetDataTip(STR_CONFIG_SETTING_COLLAPSE_ALL, STR_NULL),
2396  NWidget(WWT_PANEL, COLOUR_MAUVE), SetFill(1, 0), SetResize(1, 0),
2397  EndContainer(),
2398  NWidget(WWT_RESIZEBOX, COLOUR_MAUVE),
2399  EndContainer(),
2400 };
2401 
2402 static WindowDesc _settings_selection_desc(
2403  WDP_CENTER, "settings", 510, 450,
2405  0,
2406  _nested_settings_selection_widgets, lengthof(_nested_settings_selection_widgets)
2407 );
2408 
2411 {
2413  new GameSettingsWindow(&_settings_selection_desc);
2414 }
2415 
2416 
2426 void DrawArrowButtons(int x, int y, Colours button_colour, byte state, bool clickable_left, bool clickable_right)
2427 {
2428  int colour = _colour_gradient[button_colour][2];
2429  Dimension dim = NWidgetScrollbar::GetHorizontalDimension();
2430 
2431  DrawFrameRect(x, y, x + dim.width - 1, y + dim.height - 1, button_colour, (state == 1) ? FR_LOWERED : FR_NONE);
2432  DrawFrameRect(x + dim.width, y, x + dim.width + dim.width - 1, y + dim.height - 1, button_colour, (state == 2) ? FR_LOWERED : FR_NONE);
2433  DrawSprite(SPR_ARROW_LEFT, PAL_NONE, x + WD_IMGBTN_LEFT, y + WD_IMGBTN_TOP);
2434  DrawSprite(SPR_ARROW_RIGHT, PAL_NONE, x + WD_IMGBTN_LEFT + dim.width, y + WD_IMGBTN_TOP);
2435 
2436  /* Grey out the buttons that aren't clickable */
2437  bool rtl = _current_text_dir == TD_RTL;
2438  if (rtl ? !clickable_right : !clickable_left) {
2439  GfxFillRect(x + 1, y, x + dim.width - 1, y + dim.height - 2, colour, FILLRECT_CHECKER);
2440  }
2441  if (rtl ? !clickable_left : !clickable_right) {
2442  GfxFillRect(x + dim.width + 1, y, x + dim.width + dim.width - 1, y + dim.height - 2, colour, FILLRECT_CHECKER);
2443  }
2444 }
2445 
2454 void DrawDropDownButton(int x, int y, Colours button_colour, bool state, bool clickable)
2455 {
2456  int colour = _colour_gradient[button_colour][2];
2457 
2458  DrawFrameRect(x, y, x + SETTING_BUTTON_WIDTH - 1, y + SETTING_BUTTON_HEIGHT - 1, button_colour, state ? FR_LOWERED : FR_NONE);
2459  DrawSprite(SPR_ARROW_DOWN, PAL_NONE, x + (SETTING_BUTTON_WIDTH - NWidgetScrollbar::GetVerticalDimension().width) / 2 + state, y + 2 + state);
2460 
2461  if (!clickable) {
2462  GfxFillRect(x + 1, y, x + SETTING_BUTTON_WIDTH - 1, y + SETTING_BUTTON_HEIGHT - 2, colour, FILLRECT_CHECKER);
2463  }
2464 }
2465 
2473 void DrawBoolButton(int x, int y, bool state, bool clickable)
2474 {
2475  static const Colours _bool_ctabs[2][2] = {{COLOUR_CREAM, COLOUR_RED}, {COLOUR_DARK_GREEN, COLOUR_GREEN}};
2476  DrawFrameRect(x, y, x + SETTING_BUTTON_WIDTH - 1, y + SETTING_BUTTON_HEIGHT - 1, _bool_ctabs[state][clickable], state ? FR_LOWERED : FR_NONE);
2477 }
2478 
2480  int query_widget;
2481 
2482  CustomCurrencyWindow(WindowDesc *desc) : Window(desc)
2483  {
2484  this->InitNested();
2485 
2486  SetButtonState();
2487  }
2488 
2489  void SetButtonState()
2490  {
2491  this->SetWidgetDisabledState(WID_CC_RATE_DOWN, _custom_currency.rate == 1);
2492  this->SetWidgetDisabledState(WID_CC_RATE_UP, _custom_currency.rate == UINT16_MAX);
2493  this->SetWidgetDisabledState(WID_CC_YEAR_DOWN, _custom_currency.to_euro == CF_NOEURO);
2494  this->SetWidgetDisabledState(WID_CC_YEAR_UP, _custom_currency.to_euro == MAX_YEAR);
2495  }
2496 
2497  virtual void SetStringParameters(int widget) const
2498  {
2499  switch (widget) {
2500  case WID_CC_RATE: SetDParam(0, 1); SetDParam(1, 1); break;
2501  case WID_CC_SEPARATOR: SetDParamStr(0, _custom_currency.separator); break;
2502  case WID_CC_PREFIX: SetDParamStr(0, _custom_currency.prefix); break;
2503  case WID_CC_SUFFIX: SetDParamStr(0, _custom_currency.suffix); break;
2504  case WID_CC_YEAR:
2505  SetDParam(0, (_custom_currency.to_euro != CF_NOEURO) ? STR_CURRENCY_SWITCH_TO_EURO : STR_CURRENCY_SWITCH_TO_EURO_NEVER);
2506  SetDParam(1, _custom_currency.to_euro);
2507  break;
2508 
2509  case WID_CC_PREVIEW:
2510  SetDParam(0, 10000);
2511  break;
2512  }
2513  }
2514 
2515  virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
2516  {
2517  switch (widget) {
2518  /* Set the appropriate width for the edit 'buttons' */
2519  case WID_CC_SEPARATOR_EDIT:
2520  case WID_CC_PREFIX_EDIT:
2521  case WID_CC_SUFFIX_EDIT:
2522  size->width = this->GetWidget<NWidgetBase>(WID_CC_RATE_DOWN)->smallest_x + this->GetWidget<NWidgetBase>(WID_CC_RATE_UP)->smallest_x;
2523  break;
2524 
2525  /* Make sure the window is wide enough for the widest exchange rate */
2526  case WID_CC_RATE:
2527  SetDParam(0, 1);
2528  SetDParam(1, INT32_MAX);
2529  *size = GetStringBoundingBox(STR_CURRENCY_EXCHANGE_RATE);
2530  break;
2531  }
2532  }
2533 
2534  virtual void OnClick(Point pt, int widget, int click_count)
2535  {
2536  int line = 0;
2537  int len = 0;
2538  StringID str = 0;
2539  CharSetFilter afilter = CS_ALPHANUMERAL;
2540 
2541  switch (widget) {
2542  case WID_CC_RATE_DOWN:
2543  if (_custom_currency.rate > 1) _custom_currency.rate--;
2544  if (_custom_currency.rate == 1) this->DisableWidget(WID_CC_RATE_DOWN);
2546  break;
2547 
2548  case WID_CC_RATE_UP:
2549  if (_custom_currency.rate < UINT16_MAX) _custom_currency.rate++;
2550  if (_custom_currency.rate == UINT16_MAX) this->DisableWidget(WID_CC_RATE_UP);
2552  break;
2553 
2554  case WID_CC_RATE:
2555  SetDParam(0, _custom_currency.rate);
2556  str = STR_JUST_INT;
2557  len = 5;
2558  line = WID_CC_RATE;
2559  afilter = CS_NUMERAL;
2560  break;
2561 
2562  case WID_CC_SEPARATOR_EDIT:
2563  case WID_CC_SEPARATOR:
2564  SetDParamStr(0, _custom_currency.separator);
2565  str = STR_JUST_RAW_STRING;
2566  len = 1;
2567  line = WID_CC_SEPARATOR;
2568  break;
2569 
2570  case WID_CC_PREFIX_EDIT:
2571  case WID_CC_PREFIX:
2572  SetDParamStr(0, _custom_currency.prefix);
2573  str = STR_JUST_RAW_STRING;
2574  len = 12;
2575  line = WID_CC_PREFIX;
2576  break;
2577 
2578  case WID_CC_SUFFIX_EDIT:
2579  case WID_CC_SUFFIX:
2580  SetDParamStr(0, _custom_currency.suffix);
2581  str = STR_JUST_RAW_STRING;
2582  len = 12;
2583  line = WID_CC_SUFFIX;
2584  break;
2585 
2586  case WID_CC_YEAR_DOWN:
2587  _custom_currency.to_euro = (_custom_currency.to_euro <= 2000) ? CF_NOEURO : _custom_currency.to_euro - 1;
2588  if (_custom_currency.to_euro == CF_NOEURO) this->DisableWidget(WID_CC_YEAR_DOWN);
2590  break;
2591 
2592  case WID_CC_YEAR_UP:
2593  _custom_currency.to_euro = Clamp(_custom_currency.to_euro + 1, 2000, MAX_YEAR);
2594  if (_custom_currency.to_euro == MAX_YEAR) this->DisableWidget(WID_CC_YEAR_UP);
2596  break;
2597 
2598  case WID_CC_YEAR:
2599  SetDParam(0, _custom_currency.to_euro);
2600  str = STR_JUST_INT;
2601  len = 7;
2602  line = WID_CC_YEAR;
2603  afilter = CS_NUMERAL;
2604  break;
2605  }
2606 
2607  if (len != 0) {
2608  this->query_widget = line;
2609  ShowQueryString(str, STR_CURRENCY_CHANGE_PARAMETER, len + 1, this, afilter, QSF_NONE);
2610  }
2611 
2612  this->SetTimeout();
2613  this->SetDirty();
2614  }
2615 
2616  virtual void OnQueryTextFinished(char *str)
2617  {
2618  if (str == NULL) return;
2619 
2620  switch (this->query_widget) {
2621  case WID_CC_RATE:
2622  _custom_currency.rate = Clamp(atoi(str), 1, UINT16_MAX);
2623  break;
2624 
2625  case WID_CC_SEPARATOR: // Thousands separator
2626  strecpy(_custom_currency.separator, str, lastof(_custom_currency.separator));
2627  break;
2628 
2629  case WID_CC_PREFIX:
2630  strecpy(_custom_currency.prefix, str, lastof(_custom_currency.prefix));
2631  break;
2632 
2633  case WID_CC_SUFFIX:
2634  strecpy(_custom_currency.suffix, str, lastof(_custom_currency.suffix));
2635  break;
2636 
2637  case WID_CC_YEAR: { // Year to switch to euro
2638  int val = atoi(str);
2639 
2640  _custom_currency.to_euro = (val < 2000 ? CF_NOEURO : min(val, MAX_YEAR));
2641  break;
2642  }
2643  }
2645  SetButtonState();
2646  }
2647 
2648  virtual void OnTimeout()
2649  {
2650  this->SetDirty();
2651  }
2652 };
2653 
2654 static const NWidgetPart _nested_cust_currency_widgets[] = {
2656  NWidget(WWT_CLOSEBOX, COLOUR_GREY),
2657  NWidget(WWT_CAPTION, COLOUR_GREY), SetDataTip(STR_CURRENCY_WINDOW, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
2658  EndContainer(),
2659  NWidget(WWT_PANEL, COLOUR_GREY),
2661  NWidget(NWID_HORIZONTAL), SetPIP(10, 0, 5),
2662  NWidget(WWT_PUSHARROWBTN, COLOUR_YELLOW, WID_CC_RATE_DOWN), SetDataTip(AWV_DECREASE, STR_CURRENCY_DECREASE_EXCHANGE_RATE_TOOLTIP),
2663  NWidget(WWT_PUSHARROWBTN, COLOUR_YELLOW, WID_CC_RATE_UP), SetDataTip(AWV_INCREASE, STR_CURRENCY_INCREASE_EXCHANGE_RATE_TOOLTIP),
2665  NWidget(WWT_TEXT, COLOUR_BLUE, WID_CC_RATE), SetDataTip(STR_CURRENCY_EXCHANGE_RATE, STR_CURRENCY_SET_EXCHANGE_RATE_TOOLTIP), SetFill(1, 0),
2666  EndContainer(),
2667  NWidget(NWID_HORIZONTAL), SetPIP(10, 0, 5),
2668  NWidget(WWT_PUSHBTN, COLOUR_DARK_BLUE, WID_CC_SEPARATOR_EDIT), SetDataTip(0x0, STR_CURRENCY_SET_CUSTOM_CURRENCY_SEPARATOR_TOOLTIP), SetFill(0, 1),
2670  NWidget(WWT_TEXT, COLOUR_BLUE, WID_CC_SEPARATOR), SetDataTip(STR_CURRENCY_SEPARATOR, STR_CURRENCY_SET_CUSTOM_CURRENCY_SEPARATOR_TOOLTIP), SetFill(1, 0),
2671  EndContainer(),
2672  NWidget(NWID_HORIZONTAL), SetPIP(10, 0, 5),
2673  NWidget(WWT_PUSHBTN, COLOUR_DARK_BLUE, WID_CC_PREFIX_EDIT), SetDataTip(0x0, STR_CURRENCY_SET_CUSTOM_CURRENCY_PREFIX_TOOLTIP), SetFill(0, 1),
2675  NWidget(WWT_TEXT, COLOUR_BLUE, WID_CC_PREFIX), SetDataTip(STR_CURRENCY_PREFIX, STR_CURRENCY_SET_CUSTOM_CURRENCY_PREFIX_TOOLTIP), SetFill(1, 0),
2676  EndContainer(),
2677  NWidget(NWID_HORIZONTAL), SetPIP(10, 0, 5),
2678  NWidget(WWT_PUSHBTN, COLOUR_DARK_BLUE, WID_CC_SUFFIX_EDIT), SetDataTip(0x0, STR_CURRENCY_SET_CUSTOM_CURRENCY_SUFFIX_TOOLTIP), SetFill(0, 1),
2680  NWidget(WWT_TEXT, COLOUR_BLUE, WID_CC_SUFFIX), SetDataTip(STR_CURRENCY_SUFFIX, STR_CURRENCY_SET_CUSTOM_CURRENCY_SUFFIX_TOOLTIP), SetFill(1, 0),
2681  EndContainer(),
2682  NWidget(NWID_HORIZONTAL), SetPIP(10, 0, 5),
2683  NWidget(WWT_PUSHARROWBTN, COLOUR_YELLOW, WID_CC_YEAR_DOWN), SetDataTip(AWV_DECREASE, STR_CURRENCY_DECREASE_CUSTOM_CURRENCY_TO_EURO_TOOLTIP),
2684  NWidget(WWT_PUSHARROWBTN, COLOUR_YELLOW, WID_CC_YEAR_UP), SetDataTip(AWV_INCREASE, STR_CURRENCY_INCREASE_CUSTOM_CURRENCY_TO_EURO_TOOLTIP),
2686  NWidget(WWT_TEXT, COLOUR_BLUE, WID_CC_YEAR), SetDataTip(STR_JUST_STRING, STR_CURRENCY_SET_CUSTOM_CURRENCY_TO_EURO_TOOLTIP), SetFill(1, 0),
2687  EndContainer(),
2688  EndContainer(),
2689  NWidget(WWT_LABEL, COLOUR_BLUE, WID_CC_PREVIEW),
2690  SetDataTip(STR_CURRENCY_PREVIEW, STR_CURRENCY_CUSTOM_CURRENCY_PREVIEW_TOOLTIP), SetPadding(15, 1, 18, 2),
2691  EndContainer(),
2692 };
2693 
2694 static WindowDesc _cust_currency_desc(
2695  WDP_CENTER, NULL, 0, 0,
2697  0,
2698  _nested_cust_currency_widgets, lengthof(_nested_cust_currency_widgets)
2699 );
2700 
2702 static void ShowCustCurrency()
2703 {
2705  new CustomCurrencyWindow(&_cust_currency_desc);
2706 }
RestrictionMode mode
Filter based on category.
Currency dropdown.
Functions related to OTTD&#39;s strings.
End for iteration.
VehicleSettings vehicle
options for vehicles
Empty widget, place holder to reserve space in widget array.
Definition: widget_type.h:48
Dropdown for the GUI zoom level.
virtual void OnTimeout()
Called when this window&#39;s timeout has been reached.
Definition of stuff that is very close to a company, like the company struct itself.
void CheckForMissingGlyphs(bool base_font, MissingGlyphSearcher *searcher)
Check whether the currently loaded language pack uses characters that the currently loaded font does ...
Definition: strings.cpp:2097
bool _networking
are we in networking mode?
Definition: network.cpp:56
const void * def
default value given when none is present
virtual bool IsVisible(const BaseSettingEntry *item) const
Check whether an entry is visible and not folded or filtered away.
bool IsFiltered() const
Check whether an entry is hidden due to filters.
Horizontally center the text.
Definition: gfx_func.h:99
ResizeInfo resize
Resize information.
Definition: window_gui.h:317
static NWidgetPart SetResize(int16 dx, int16 dy)
Widget part function for setting the resize step.
Definition: widget_type.h:930
Window(WindowDesc *desc)
Empty constructor, initialization has been moved to InitNested() called from the constructor of the d...
Definition: window.cpp:1849
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:387
void SetWindowDirty(WindowClass cls, WindowNumber number)
Mark window as dirty (in need of repainting)
Definition: window.cpp:3199
int warn_lines
Number of lines used for warning about missing search results.
void SetWidgetLoweredState(byte widget_index, bool lowered_stat)
Sets the lowered/raised status of a widget.
Definition: window_gui.h:448
uint GetMaxHelpHeight(int maxw)
Get the biggest height of the help texts, if the width is at least maxw.
void SetTimeout()
Set the timeout flag of the window and initiate the timer.
Definition: window_gui.h:361
Current suffix.
this setting can be different for each company (saved in company struct)
High level window description.
Definition: window_gui.h:168
Custom currency.
Definition: currency.h:58
WindowFlags flags
Window flags.
Definition: window_gui.h:305
int left
x position of left edge of the window
Definition: window_gui.h:312
All settings together for the game.
void DrawWidgets() const
Paint all widgets of a window.
Definition: widget.cpp:604
void ChangeMusicSet(int index)
Change the configured music set and reset playback.
Definition: music_gui.cpp:435
static Titem * Get(size_t index)
Returns Titem with given index.
Definition: pool_type.hpp:246
Switch to game intro menu.
Definition: openttd.h:32
virtual void UnFoldAll()
Recursively open all (filtered) folds of sub-pages.
virtual void OnClick(Point pt, int widget, int click_count)
A click with the left mouse button has been made on the window.
SettingsPage(StringID title)
Constructor for a sub-page in the &#39;advanced settings&#39; window.
Centered label.
Definition: widget_type.h:57
Scrollbar data structure.
Definition: widget_type.h:589
CurrencySpec _currency_specs[CURRENCY_END]
Array of currencies used by the system.
Definition: currency.cpp:70
Functions to handle different currencies.
virtual void Init(byte level=0)
Initialization of a setting entry.
int GetNumInvalid() const
Get the number of invalid files.
Data structure describing a single setting in a tab.
Of a numeric setting entry, the right button is depressed.
Normal amount of vertical space between two paragraphs of text.
Definition: window_gui.h:139
static T SetBit(T &x, const uint8 y)
Set a bit in a variable.
textfile; Window numbers:
Definition: window_type.h:182
Horizontal container.
Definition: widget_type.h:75
void ResetState()
Reset the matching state to process a new item.
void UnFoldAll()
Recursively open all folds of sub-pages.
void SetMediaSet(int index)
Set the base media set.
byte _colour_gradient[COLOUR_END][8]
All 16 colour gradients 8 colours per gradient from darkest (0) to lightest (7)
Definition: gfx.cpp:53
Arrow to the right or in case of RTL to the left.
Definition: widget_type.h:38
Arrow to the left or in case of RTL to the right.
Definition: widget_type.h:37
virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
Update size and resize step of a widget in the window.
Info about missing files etc.
SettingGuiFlag flags
handles how a setting would show up in the GUI (text/currency, etc.)
Open base SFX readme, changelog (+1) or license (+2).
Open base music readme, changelog (+1) or license (+2).
bool GetState() const
Get the matching state of the current item.
void ShowQueryString(StringID str, StringID caption, uint maxsize, Window *parent, CharSetFilter afilter, QueryStringFlags flags)
Show a query popup window with a textbox in it.
Definition: misc_gui.cpp:1064
Use to select a base music set.
Generic functions for replacing base data (graphics, sounds).
fluid_settings_t * settings
FluidSynth settings handle.
Definition: fluidsynth.cpp:22
Show only settings which are different compared to the user&#39;s new game setting values.
Up button.
#define SETBITS(x, y)
Sets several bits in a variable.
const LanguageMetadata * _current_language
The currently loaded language.
Definition: strings.cpp:50
Current separator.
bool closing_dropdown
True, if the dropdown list is currently closing.
static Dimension _circle_size
Dimension of the circle +/- icon. This is here as not all users are within the class of the settings ...
Separator edit button.
the number represents money, so when reading value multiply by exchange rate
DropDownList * BuildDropDownList(int widget, int *selected_index) const
Build the dropdown list for a specific widget.
Panel widget containing the option lists.
a textbox for typing
Definition: widget_type.h:71
Resize box (normally at bottom-right of a window)
Definition: widget_type.h:68
static const int ACTION_CLEAR
Clear editbox.
NewGRF changelog.
Definition: textfile_type.h:20
Filter for settings list.
int top
y position of top edge of the window
Definition: window_gui.h:313
Header of Action 0F "universal holder" structure and functions.
Type setting filtered matches away.
int64 ReadValue(const void *ptr, VarType conv)
Return a signed-long version of the value of a setting.
Definition: saveload.cpp: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:397
#define CLRBITS(x, y)
Clears several bits in a variable.
Town name dropdown.
NewGRF readme.
Definition: textfile_type.h:19
virtual void OnClick(Point pt, int widget, int click_count)
A click with the left mouse button has been made on the window.
Subdirectory for all base data (base sets, intro game)
Definition: fileio_type.h:118
static T max(const T a, const T b)
Returns the maximum of two values.
Definition: math_func.hpp:26
static StringID TownName(int town_name)
Get a town name.
virtual uint GetMaxHelpHeight(int maxw)
Get the biggest height of the help text(s), if the width is at least maxw.
the value represents a limited number of string-options (internally integer)
Common string list item.
Definition: dropdown_type.h:41
static int GetNumSets()
Count the number of available graphics sets.
int GetNumMissing() const
Get the number of missing files.
const T * End() const
Get the pointer behind the last valid item (const)
void CreateNestedTree(bool fill_nested=true)
Perform the first part of the initialization of a nested widget tree.
Definition: window.cpp:1810
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:271
void FinishInitNested(WindowNumber window_number=0)
Perform the second part of the initialization of a nested widget tree.
Definition: window.cpp:1826
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:1839
SettingEntry * last_clicked
If non-NULL, pointer to the last clicked setting.
void ShowErrorMessage(StringID summary_msg, StringID detailed_msg, WarningLevel wl, int x=0, int y=0, const GRFFile *textref_stack_grffile=NULL, uint textref_stack_size=0, const uint32 *textref_stack=NULL)
Display an error message in a window.
Definition: error_gui.cpp:378
Bottom offset of the text of the frame.
Definition: window_gui.h:75
SaveLoad save
Internal structure (going to savegame, parts to config)
virtual void OnClick(Point pt, int widget, int click_count)
A click with the left mouse button has been made on the window.
void SetDParamStr(uint n, const char *str)
This function is used to "bind" a C string to a OpenTTD dparam slot.
Definition: strings.cpp:279
enable the &#39;Default&#39; button ("\0" is returned)
Definition: textbuf_gui.h:23
bool ReadLanguagePack(const LanguageMetadata *lang)
Read a particular language.
Definition: strings.cpp:1716
Functions related to low-level strings.
Zoomed 4 times out.
Definition: zoom_type.h:26
bool type_hides
Whether the type hides filtered strings.
Only numeric ones.
Definition: string_type.h:28
Invisible widget that takes some space.
Definition: widget_type.h:79
bool UpdateFilterState(SettingFilter &filter, bool force_visible)
Update the filter state.
VarType conv
type of the variable to be saved, int
Definition: saveload.h:489
Functions related to errors.
Used in setting filter to match all types.
Default window size box (at top-right of a window, between WWT_SHADEBOX and WWT_STICKYBOX) ...
Definition: widget_type.h:65
uint Length() const
Get the number of items in the list.
int GetScrolledRowFromWidget(int clickpos, const Window *const w, int widget, int padding=0, int line_height=-1) const
Compute the row of a scrolled widget that a user clicked in.
Definition: widget.cpp:1959
display absolute value of the setting
uint pos_y
Vertical position of top-left corner of the widget in the window.
Definition: widget_type.h:178
Of a numeric setting entry, the left button is depressed.
Dropdown to say how often to autosave.
bool manually_changed_folding
Whether the user expanded/collapsed something manually.
CompanySettings company
default values for per-company settings
static GameSettings * settings_ptr
Pointer to the game settings being displayed and modified.
StringID str_help
(Translated) string with help text; gui only.
Suffix edit button.
int main(int argc, char *argv[])
Entry point.
Definition: depend.cpp:909
SettingEntry(const char *name)
Constructor for a single setting in the &#39;advanced settings&#39; window.
virtual uint Length() const
Return number of rows needed to display the (filtered) entry.
byte road_side
the side of the road vehicles drive on
void SetDisplayedHelpText(SettingEntry *pe)
Set the entry that should have its help text displayed, and mark the window dirty so it gets repainte...
SmallMap< int, QueryString * > querystrings
QueryString associated to WWT_EDITBOX widgets.
Definition: window_gui.h:323
void UpdateAllVirtCoords()
Update the viewport coordinates of all signs.
Definition: afterload.cpp:219
const char * name
Name of the setting.
#define FONT_HEIGHT_NORMAL
Height of characters in the normal (FS_NORMAL) font.
Definition: gfx_func.h:180
static NWidgetPart SetDataTip(uint32 data, StringID tip)
Widget part function for setting the data and tooltip.
Definition: widget_type.h:1014
Simple vector template class, with automatic delete.
virtual void DrawSetting(GameSettings *settings_ptr, int left, int right, int y, bool highlight) const
Function to draw setting value (button + text + current value)
Data stored about a string that can be modified in the GUI.
ClientSettings _settings_client
The current settings for this game.
Definition: settings.cpp:76
static NWidgetPart SetMinimalSize(int16 x, int16 y)
Widget part function for setting the minimal size.
Definition: widget_type.h:947
virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
Update size and resize step of a widget in the window.
Definition of base types and functions in a cross-platform compatible way.
void LoadStringWidthTable(bool monospace)
Initialize _stringwidth_table cache.
Definition: gfx.cpp: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:1157
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:966
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:1144
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:3434
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:314
The caption of the window.
Definition: misc_widget.h:50
static NWidgetPart SetFill(uint fill_x, uint fill_y)
Widget part function for setting filling.
Definition: widget_type.h:983
static bool HasBit(const T x, const uint8 y)
Checks if a bit in a value is set.
Base functions for all AIs.
Base of the town class.
static void ShowCustCurrency()
Open custom currency window.
GameCreationSettings game_creation
settings used during the creation of a game (map)
QueryString filter_editbox
Filter editbox;.
void DrawBoolButton(int x, int y, bool state, bool clickable)
Draw a toggle button.
void SetCapacityFromWidget(Window *w, int widget, int padding=0)
Set capacity of visible elements from the size and resize properties of a widget. ...
Definition: widget.cpp:1973
Client setting.
Specification of a rectangle with absolute coordinates of all edges.
Vertical scrollbar.
Definition: widget_type.h:84
int _nb_orig_names
Number of original town names.
Both category and type settings filtered matches away.
Text is written right-to-left by default.
Definition: strings_type.h:26
SettingEntry * valuewindow_entry
If non-NULL, pointer to setting for which a value-entering window has been opened.
Window functions not directly related to making/drawing windows.
SettingType
Type of settings for filtering.
const char * GetTextfile(TextfileType type, Subdirectory dir, const char *filename)
Search a textfile file next to the given content.
Information area to display help text of the selected option.
#define DECLARE_POSTFIX_INCREMENT(type)
Some enums need to have allowed incrementing (i.e.
Definition: enum_type.hpp:16
virtual void OnDropdownClose(Point pt, int widget, int index, bool instant_close)
A dropdown window associated to this window has been closed.
Definition: window.cpp: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:309
Errors (eg. saving/loading failed)
Definition: error.h:25
void GetFoldingState(bool &all_folded, bool &all_unfolded) const
Recursively accumulate the folding state of the tree.
static void QSortT(T *base, uint num, int(CDECL *comparator)(const T *, const T *), bool desc=false)
Type safe qsort()
Definition: sort_func.hpp:28
BaseSettingEntry * FindEntry(uint row, uint *cur_row)
Find the setting entry at row number row_num.
Info about corrupted files etc.
uint32 max
maximum values
Left offset of the image in the button.
Definition: window_gui.h:40
int32 interval
the interval to use between settings in the &#39;settings&#39; window. If interval is &#39;0&#39; the interval is dyn...
static NWidgetPart SetScrollbar(int index)
Attach a scrollbar to a widget.
Definition: widget_type.h:1095
Base list item class from which others are derived.
Definition: dropdown_type.h:24
byte autosave
how often should we do autosaves?
SettingDescBase desc
Settings structure (going to configuration file)
Dimensions (a width and height) of a rectangle in 2D.
Value of the NCB_EQUALSIZE flag.
Definition: widget_type.h:429
Query string window; Window numbers:
Definition: window_type.h:118
bool IsEmpty() const
Check whether any filter words were entered.
Offset at left to draw the frame rectangular area.
Definition: window_gui.h:62
static const Year MAX_YEAR
MAX_YEAR, nicely rounded value of the number of years that can be encoded in a single 32 bits date...
Definition: date_type.h:94
Factory to &#39;query&#39; all available blitters.
Game options window; Window numbers:
Definition: window_type.h:608
static const GraphicsSet * GetUsedSet()
Return the used set.
void DrawSprite(SpriteID img, PaletteID pal, int x, int y, const SubSprite *sub, ZoomLevel zoom)
Draw a sprite, not in a viewport.
Definition: gfx.cpp: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:3240
Down button.
virtual bool IsVisible(const BaseSettingEntry *item) const
Check whether an entry is visible and not folded or filtered away.
int height
Height of the window (number of pixels down in y direction)
Definition: window_gui.h:315
virtual bool UpdateFilterState(SettingFilter &filter, bool force_visible)
Update the filter state.
void EnableWidget(byte widget_index)
Sets a widget to Enabled.
Definition: window_gui.h:406
void MarkWholeScreenDirty()
This function mark the whole screen as dirty.
Definition: gfx.cpp: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:733
(Toggle) Button with text
Definition: widget_type.h:55
List all settings regardless of the default/newgame/... values.
virtual void OnTimeout()
Called when this window&#39;s timeout has been reached.
a boolean number
uint16 GetPosition() const
Gets the position of the first visible element in the list.
Definition: widget_type.h:631
byte currency
currency we currently use
static void SetDParam(uint n, uint64 v)
Set a string parameter v at index n in the global string parameter array.
Definition: strings_func.h:201
static int CDECL NatSortFunc(const DropDownListItem *const *first, const DropDownListItem *const *second)
Natural sorting comparator function for DropDownList::sort().
Definition: dropdown.cpp:54