OpenTTD
settings_gui.cpp
Go to the documentation of this file.
1 /* $Id$ */
2 
3 /*
4  * This file is part of OpenTTD.
5  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
6  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
8  */
9 
12 #include "stdafx.h"
13 #include "currency.h"
14 #include "error.h"
15 #include "settings_gui.h"
16 #include "textbuf_gui.h"
17 #include "command_func.h"
18 #include "network/network.h"
19 #include "town.h"
20 #include "settings_internal.h"
21 #include "newgrf_townname.h"
22 #include "strings_func.h"
23 #include "window_func.h"
24 #include "string_func.h"
25 #include "widgets/dropdown_type.h"
26 #include "widgets/dropdown_func.h"
27 #include "highscore.h"
28 #include "base_media_base.h"
29 #include "company_base.h"
30 #include "company_func.h"
31 #include "viewport_func.h"
32 #include "core/geometry_func.hpp"
33 #include "ai/ai.hpp"
34 #include "blitter/factory.hpp"
35 #include "language.h"
36 #include "textfile_gui.h"
37 #include "stringfilter_type.h"
38 #include "querystring_gui.h"
39 #include "fontcache.h"
40 #include "zoom_func.h"
41 
42 #include <vector>
43 
44 #include "safeguards.h"
45 
46 
47 static const StringID _driveside_dropdown[] = {
48  STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_LEFT,
49  STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_RIGHT,
51 };
52 
53 static const StringID _autosave_dropdown[] = {
54  STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_OFF,
55  STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_1_MONTH,
56  STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_3_MONTHS,
57  STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_6_MONTHS,
58  STR_GAME_OPTIONS_AUTOSAVE_DROPDOWN_EVERY_12_MONTHS,
60 };
61 
62 static const StringID _gui_zoom_dropdown[] = {
63  STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_NORMAL,
64  STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_2X_ZOOM,
65  STR_GAME_OPTIONS_GUI_ZOOM_DROPDOWN_4X_ZOOM,
67 };
68 
69 static const StringID _font_zoom_dropdown[] = {
70  STR_GAME_OPTIONS_FONT_ZOOM_DROPDOWN_NORMAL,
71  STR_GAME_OPTIONS_FONT_ZOOM_DROPDOWN_2X_ZOOM,
72  STR_GAME_OPTIONS_FONT_ZOOM_DROPDOWN_4X_ZOOM,
74 };
75 
76 int _nb_orig_names = SPECSTR_TOWNNAME_LAST - SPECSTR_TOWNNAME_START + 1;
77 static StringID *_grf_names = NULL;
78 static int _nb_grf_names = 0;
79 
81 
82 static const void *ResolveVariableAddress(const GameSettings *settings_ptr, const SettingDesc *sd);
83 
86 {
88  _grf_names = GetGRFTownNameList();
89  _nb_grf_names = 0;
90  for (StringID *s = _grf_names; *s != INVALID_STRING_ID; s++) _nb_grf_names++;
91 }
92 
98 static inline StringID TownName(int town_name)
99 {
100  if (town_name < _nb_orig_names) return STR_GAME_OPTIONS_TOWN_NAME_ORIGINAL_ENGLISH + town_name;
101  town_name -= _nb_orig_names;
102  if (town_name < _nb_grf_names) return _grf_names[town_name];
103  return STR_UNDEFINED;
104 }
105 
110 static int GetCurRes()
111 {
112  int i;
113 
114  for (i = 0; i != _num_resolutions; i++) {
115  if ((int)_resolutions[i].width == _screen.width &&
116  (int)_resolutions[i].height == _screen.height) {
117  break;
118  }
119  }
120  return i;
121 }
122 
123 static void ShowCustCurrency();
124 
125 template <class T>
126 static DropDownList *BuildSetDropDownList(int *selected_index, bool allow_selection)
127 {
128  int n = T::GetNumSets();
129  *selected_index = T::GetIndexOfUsedSet();
130 
131  DropDownList *list = new DropDownList();
132  for (int i = 0; i < n; i++) {
133  *list->Append() = new DropDownListCharStringItem(T::GetSet(i)->name, i, !allow_selection && (*selected_index != i));
134  }
135 
136  return list;
137 }
138 
139 DropDownList *BuildMusicSetDropDownList(int *selected_index)
140 {
141  return BuildSetDropDownList<BaseMusic>(selected_index, true);
142 }
143 
145 template <class TBaseSet>
147  const TBaseSet* baseset;
149 
150  BaseSetTextfileWindow(TextfileType file_type, const TBaseSet* baseset, StringID content_type) : TextfileWindow(file_type), baseset(baseset), content_type(content_type)
151  {
152  const char *textfile = this->baseset->GetTextfile(file_type);
153  this->LoadTextfile(textfile, BASESET_DIR);
154  }
155 
156  /* virtual */ void SetStringParameters(int widget) const
157  {
158  if (widget == WID_TF_CAPTION) {
159  SetDParam(0, content_type);
160  SetDParamStr(1, this->baseset->name);
161  }
162  }
163 };
164 
171 template <class TBaseSet>
173 {
174  DeleteWindowById(WC_TEXTFILE, file_type);
176 }
177 
179  GameSettings *opt;
180  bool reload;
181 
182  GameOptionsWindow(WindowDesc *desc) : Window(desc)
183  {
184  this->opt = &GetGameSettings();
185  this->reload = false;
186 
188  this->OnInvalidateData(0);
189  }
190 
192  {
195  if (this->reload) _switch_mode = SM_MENU;
196  }
197 
204  DropDownList *BuildDropDownList(int widget, int *selected_index) const
205  {
206  DropDownList *list = NULL;
207  switch (widget) {
208  case WID_GO_CURRENCY_DROPDOWN: { // Setup currencies dropdown
209  list = new DropDownList();
210  *selected_index = this->opt->locale.currency;
211  StringID *items = BuildCurrencyDropdown();
212  uint64 disabled = _game_mode == GM_MENU ? 0LL : ~GetMaskOfAllowedCurrencies();
213 
214  /* Add non-custom currencies; sorted naturally */
215  for (uint i = 0; i < CURRENCY_END; items++, i++) {
216  if (i == CURRENCY_CUSTOM) continue;
217  *list->Append() = new DropDownListStringItem(*items, i, HasBit(disabled, i));
218  }
220 
221  /* Append custom currency at the end */
222  *list->Append() = new DropDownListItem(-1, false); // separator line
223  *list->Append() = new DropDownListStringItem(STR_GAME_OPTIONS_CURRENCY_CUSTOM, CURRENCY_CUSTOM, HasBit(disabled, CURRENCY_CUSTOM));
224  break;
225  }
226 
227  case WID_GO_ROADSIDE_DROPDOWN: { // Setup road-side dropdown
228  list = new DropDownList();
229  *selected_index = this->opt->vehicle.road_side;
230  const StringID *items = _driveside_dropdown;
231  uint disabled = 0;
232 
233  /* You can only change the drive side if you are in the menu or ingame with
234  * no vehicles present. In a networking game only the server can change it */
235  extern bool RoadVehiclesAreBuilt();
236  if ((_game_mode != GM_MENU && RoadVehiclesAreBuilt()) || (_networking && !_network_server)) {
237  disabled = ~(1 << this->opt->vehicle.road_side); // disable the other value
238  }
239 
240  for (uint i = 0; *items != INVALID_STRING_ID; items++, i++) {
241  *list->Append() = new DropDownListStringItem(*items, i, HasBit(disabled, i));
242  }
243  break;
244  }
245 
246  case WID_GO_TOWNNAME_DROPDOWN: { // Setup townname dropdown
247  list = new DropDownList();
248  *selected_index = this->opt->game_creation.town_name;
249 
250  int enabled_item = (_game_mode == GM_MENU || Town::GetNumItems() == 0) ? -1 : *selected_index;
251 
252  /* Add and sort newgrf townnames generators */
253  for (int i = 0; i < _nb_grf_names; i++) {
254  int result = _nb_orig_names + i;
255  *list->Append() = new DropDownListStringItem(_grf_names[i], result, enabled_item != result && enabled_item >= 0);
256  }
258 
259  int newgrf_size = list->Length();
260  /* Insert newgrf_names at the top of the list */
261  if (newgrf_size > 0) {
262  *list->Append() = new DropDownListItem(-1, false); // separator line
263  newgrf_size++;
264  }
265 
266  /* Add and sort original townnames generators */
267  for (int i = 0; i < _nb_orig_names; i++) {
268  *list->Append() = new DropDownListStringItem(STR_GAME_OPTIONS_TOWN_NAME_ORIGINAL_ENGLISH + i, i, enabled_item != i && enabled_item >= 0);
269  }
270  QSortT(list->Begin() + newgrf_size, list->Length() - newgrf_size, DropDownListStringItem::NatSortFunc);
271  break;
272  }
273 
274  case WID_GO_AUTOSAVE_DROPDOWN: { // Setup autosave dropdown
275  list = new DropDownList();
276  *selected_index = _settings_client.gui.autosave;
277  const StringID *items = _autosave_dropdown;
278  for (uint i = 0; *items != INVALID_STRING_ID; items++, i++) {
279  *list->Append() = new DropDownListStringItem(*items, i, false);
280  }
281  break;
282  }
283 
284  case WID_GO_LANG_DROPDOWN: { // Setup interface language dropdown
285  list = new DropDownList();
286  for (uint i = 0; i < _languages.Length(); i++) {
287  if (&_languages[i] == _current_language) *selected_index = i;
288  *list->Append() = new DropDownListStringItem(SPECSTR_LANGUAGE_START + i, i, false);
289  }
291  break;
292  }
293 
294  case WID_GO_RESOLUTION_DROPDOWN: // Setup resolution dropdown
295  if (_num_resolutions == 0) break;
296 
297  list = new DropDownList();
298  *selected_index = GetCurRes();
299  for (int i = 0; i < _num_resolutions; i++) {
300  *list->Append() = new DropDownListStringItem(SPECSTR_RESOLUTION_START + i, i, false);
301  }
302  break;
303 
305  list = new DropDownList();
306  *selected_index = ZOOM_LVL_OUT_4X - _gui_zoom;
307  const StringID *items = _gui_zoom_dropdown;
308  for (int i = 0; *items != INVALID_STRING_ID; items++, i++) {
310  }
311  break;
312  }
313 
315  list = new DropDownList();
316  *selected_index = ZOOM_LVL_OUT_4X - _font_zoom;
317  const StringID *items = _font_zoom_dropdown;
318  for (int i = 0; *items != INVALID_STRING_ID; items++, i++) {
319  *list->Append() = new DropDownListStringItem(*items, i, false);
320  }
321  break;
322  }
323 
325  list = BuildSetDropDownList<BaseGraphics>(selected_index, (_game_mode == GM_MENU));
326  break;
327 
329  list = BuildSetDropDownList<BaseSounds>(selected_index, (_game_mode == GM_MENU));
330  break;
331 
333  list = BuildMusicSetDropDownList(selected_index);
334  break;
335 
336  default:
337  return NULL;
338  }
339 
340  return list;
341  }
342 
343  virtual void SetStringParameters(int widget) const
344  {
345  switch (widget) {
346  case WID_GO_CURRENCY_DROPDOWN: SetDParam(0, _currency_specs[this->opt->locale.currency].name); break;
347  case WID_GO_ROADSIDE_DROPDOWN: SetDParam(0, STR_GAME_OPTIONS_ROAD_VEHICLES_DROPDOWN_LEFT + this->opt->vehicle.road_side); break;
349  case WID_GO_AUTOSAVE_DROPDOWN: SetDParam(0, _autosave_dropdown[_settings_client.gui.autosave]); break;
351  case WID_GO_RESOLUTION_DROPDOWN: SetDParam(0, GetCurRes() == _num_resolutions ? STR_GAME_OPTIONS_RESOLUTION_OTHER : SPECSTR_RESOLUTION_START + GetCurRes()); break;
352  case WID_GO_GUI_ZOOM_DROPDOWN: SetDParam(0, _gui_zoom_dropdown[ZOOM_LVL_OUT_4X - _gui_zoom]); break;
353  case WID_GO_FONT_ZOOM_DROPDOWN: SetDParam(0, _font_zoom_dropdown[ZOOM_LVL_OUT_4X - _font_zoom]); break;
355  case WID_GO_BASE_GRF_STATUS: SetDParam(0, BaseGraphics::GetUsedSet()->GetNumInvalid()); break;
358  case WID_GO_BASE_MUSIC_STATUS: SetDParam(0, BaseMusic::GetUsedSet()->GetNumInvalid()); break;
359  }
360  }
361 
362  virtual void DrawWidget(const Rect &r, int widget) const
363  {
364  switch (widget) {
367  DrawStringMultiLine(r.left, r.right, r.top, UINT16_MAX, STR_BLACK_RAW_STRING);
368  break;
369 
372  DrawStringMultiLine(r.left, r.right, r.top, UINT16_MAX, STR_BLACK_RAW_STRING);
373  break;
374 
377  DrawStringMultiLine(r.left, r.right, r.top, UINT16_MAX, STR_BLACK_RAW_STRING);
378  break;
379  }
380  }
381 
382  virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
383  {
384  switch (widget) {
386  /* Find the biggest description for the default size. */
387  for (int i = 0; i < BaseGraphics::GetNumSets(); i++) {
389  size->height = max(size->height, (uint)GetStringHeight(STR_BLACK_RAW_STRING, size->width));
390  }
391  break;
392 
394  /* Find the biggest description for the default size. */
395  for (int i = 0; i < BaseGraphics::GetNumSets(); i++) {
396  uint invalid_files = BaseGraphics::GetSet(i)->GetNumInvalid();
397  if (invalid_files == 0) continue;
398 
399  SetDParam(0, invalid_files);
400  *size = maxdim(*size, GetStringBoundingBox(STR_GAME_OPTIONS_BASE_GRF_STATUS));
401  }
402  break;
403 
405  /* Find the biggest description for the default size. */
406  for (int i = 0; i < BaseSounds::GetNumSets(); i++) {
408  size->height = max(size->height, (uint)GetStringHeight(STR_BLACK_RAW_STRING, size->width));
409  }
410  break;
411 
413  /* Find the biggest description for the default size. */
414  for (int i = 0; i < BaseMusic::GetNumSets(); i++) {
415  SetDParamStr(0, BaseMusic::GetSet(i)->GetDescription(GetCurrentLanguageIsoCode()));
416  size->height = max(size->height, (uint)GetStringHeight(STR_BLACK_RAW_STRING, size->width));
417  }
418  break;
419 
421  /* Find the biggest description for the default size. */
422  for (int i = 0; i < BaseMusic::GetNumSets(); i++) {
423  uint invalid_files = BaseMusic::GetSet(i)->GetNumInvalid();
424  if (invalid_files == 0) continue;
425 
426  SetDParam(0, invalid_files);
427  *size = maxdim(*size, GetStringBoundingBox(STR_GAME_OPTIONS_BASE_MUSIC_STATUS));
428  }
429  break;
430 
431  default: {
432  int selected;
433  DropDownList *list = this->BuildDropDownList(widget, &selected);
434  if (list != NULL) {
435  /* Find the biggest item for the default size. */
436  for (const DropDownListItem * const *it = list->Begin(); it != list->End(); it++) {
437  Dimension string_dim;
438  int width = (*it)->Width();
439  string_dim.width = width + padding.width;
440  string_dim.height = (*it)->Height(width) + padding.height;
441  *size = maxdim(*size, string_dim);
442  }
443  delete list;
444  }
445  }
446  }
447  }
448 
449  virtual void OnClick(Point pt, int widget, int click_count)
450  {
451  if (widget >= WID_GO_BASE_GRF_TEXTFILE && widget < WID_GO_BASE_GRF_TEXTFILE + TFT_END) {
452  if (BaseGraphics::GetUsedSet() == NULL) return;
453 
454  ShowBaseSetTextfileWindow((TextfileType)(widget - WID_GO_BASE_GRF_TEXTFILE), BaseGraphics::GetUsedSet(), STR_CONTENT_TYPE_BASE_GRAPHICS);
455  return;
456  }
457  if (widget >= WID_GO_BASE_SFX_TEXTFILE && widget < WID_GO_BASE_SFX_TEXTFILE + TFT_END) {
458  if (BaseSounds::GetUsedSet() == NULL) return;
459 
460  ShowBaseSetTextfileWindow((TextfileType)(widget - WID_GO_BASE_SFX_TEXTFILE), BaseSounds::GetUsedSet(), STR_CONTENT_TYPE_BASE_SOUNDS);
461  return;
462  }
463  if (widget >= WID_GO_BASE_MUSIC_TEXTFILE && widget < WID_GO_BASE_MUSIC_TEXTFILE + TFT_END) {
464  if (BaseMusic::GetUsedSet() == NULL) return;
465 
466  ShowBaseSetTextfileWindow((TextfileType)(widget - WID_GO_BASE_MUSIC_TEXTFILE), BaseMusic::GetUsedSet(), STR_CONTENT_TYPE_BASE_MUSIC);
467  return;
468  }
469  switch (widget) {
470  case WID_GO_FULLSCREEN_BUTTON: // Click fullscreen on/off
471  /* try to toggle full-screen on/off */
472  if (!ToggleFullScreen(!_fullscreen)) {
473  ShowErrorMessage(STR_ERROR_FULLSCREEN_FAILED, INVALID_STRING_ID, WL_ERROR);
474  }
476  this->SetDirty();
477  break;
478 
479  default: {
480  int selected;
481  DropDownList *list = this->BuildDropDownList(widget, &selected);
482  if (list != NULL) {
483  ShowDropDownList(this, list, selected, widget);
484  } else {
485  if (widget == WID_GO_RESOLUTION_DROPDOWN) ShowErrorMessage(STR_ERROR_RESOLUTION_LIST_FAILED, INVALID_STRING_ID, WL_ERROR);
486  }
487  break;
488  }
489  }
490  }
491 
497  template <class T>
498  void SetMediaSet(int index)
499  {
500  if (_game_mode == GM_MENU) {
501  const char *name = T::GetSet(index)->name;
502 
503  free(T::ini_set);
504  T::ini_set = stredup(name);
505 
506  T::SetSet(name);
507  this->reload = true;
508  this->InvalidateData();
509  }
510  }
511 
512  virtual void OnDropdownSelect(int widget, int index)
513  {
514  switch (widget) {
515  case WID_GO_CURRENCY_DROPDOWN: // Currency
516  if (index == CURRENCY_CUSTOM) ShowCustCurrency();
517  this->opt->locale.currency = index;
519  break;
520 
521  case WID_GO_ROADSIDE_DROPDOWN: // Road side
522  if (this->opt->vehicle.road_side != index) { // only change if setting changed
523  uint i;
524  if (GetSettingFromName("vehicle.road_side", &i) == NULL) NOT_REACHED();
525  SetSettingValue(i, index);
527  }
528  break;
529 
530  case WID_GO_TOWNNAME_DROPDOWN: // Town names
531  if (_game_mode == GM_MENU || Town::GetNumItems() == 0) {
532  this->opt->game_creation.town_name = index;
534  }
535  break;
536 
537  case WID_GO_AUTOSAVE_DROPDOWN: // Autosave options
538  _settings_client.gui.autosave = index;
539  this->SetDirty();
540  break;
541 
542  case WID_GO_LANG_DROPDOWN: // Change interface language
543  ReadLanguagePack(&_languages[index]);
548  break;
549 
550  case WID_GO_RESOLUTION_DROPDOWN: // Change resolution
551  if (index < _num_resolutions && ChangeResInGame(_resolutions[index].width, _resolutions[index].height)) {
552  this->SetDirty();
553  }
554  break;
555 
558  _gui_zoom = (ZoomLevel)(ZOOM_LVL_OUT_4X - index);
561  FixTitleGameZoom();
563  break;
564 
567  _font_zoom = (ZoomLevel)(ZOOM_LVL_OUT_4X - index);
568  ClearFontCache();
571  break;
572 
574  this->SetMediaSet<BaseGraphics>(index);
575  break;
576 
578  this->SetMediaSet<BaseSounds>(index);
579  break;
580 
582  ChangeMusicSet(index);
583  break;
584  }
585  }
586 
592  virtual void OnInvalidateData(int data = 0, bool gui_scope = true)
593  {
594  if (!gui_scope) return;
596 
597  bool missing_files = BaseGraphics::GetUsedSet()->GetNumMissing() == 0;
598  this->GetWidget<NWidgetCore>(WID_GO_BASE_GRF_STATUS)->SetDataTip(missing_files ? STR_EMPTY : STR_GAME_OPTIONS_BASE_GRF_STATUS, STR_NULL);
599 
600  for (TextfileType tft = TFT_BEGIN; tft < TFT_END; tft++) {
604  }
605 
606  missing_files = BaseMusic::GetUsedSet()->GetNumInvalid() == 0;
607  this->GetWidget<NWidgetCore>(WID_GO_BASE_MUSIC_STATUS)->SetDataTip(missing_files ? STR_EMPTY : STR_GAME_OPTIONS_BASE_MUSIC_STATUS, STR_NULL);
608  }
609 };
610 
611 static const NWidgetPart _nested_game_options_widgets[] = {
613  NWidget(WWT_CLOSEBOX, COLOUR_GREY),
614  NWidget(WWT_CAPTION, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
615  EndContainer(),
616  NWidget(WWT_PANEL, COLOUR_GREY, WID_GO_BACKGROUND), SetPIP(6, 6, 10),
617  NWidget(NWID_HORIZONTAL), SetPIP(10, 10, 10),
618  NWidget(NWID_VERTICAL), SetPIP(0, 6, 0),
619  NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_ROAD_VEHICLES_FRAME, STR_NULL),
620  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),
621  EndContainer(),
622  NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_AUTOSAVE_FRAME, STR_NULL),
623  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),
624  EndContainer(),
625  NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_RESOLUTION, STR_NULL),
626  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),
628  NWidget(WWT_TEXT, COLOUR_GREY), SetMinimalSize(0, 12), SetFill(1, 0), SetDataTip(STR_GAME_OPTIONS_FULLSCREEN, STR_NULL),
629  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_GO_FULLSCREEN_BUTTON), SetMinimalSize(21, 9), SetDataTip(STR_EMPTY, STR_GAME_OPTIONS_FULLSCREEN_TOOLTIP),
630  EndContainer(),
631  EndContainer(),
632  NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_GUI_ZOOM_FRAME, STR_NULL),
633  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),
634  EndContainer(),
635  EndContainer(),
636 
637  NWidget(NWID_VERTICAL), SetPIP(0, 6, 0),
638  NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_TOWN_NAMES_FRAME, STR_NULL),
639  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),
640  EndContainer(),
641  NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_LANGUAGE, STR_NULL),
642  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),
643  EndContainer(),
644  NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_CURRENCY_UNITS_FRAME, STR_NULL),
645  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),
646  EndContainer(),
647  NWidget(NWID_SPACER), SetMinimalSize(0, 0), SetFill(0, 1),
648  NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_FONT_ZOOM, STR_NULL),
649  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),
650  EndContainer(),
651  EndContainer(),
652  EndContainer(),
653 
654  NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_BASE_GRF, STR_NULL), SetPadding(0, 10, 0, 10),
655  NWidget(NWID_HORIZONTAL), SetPIP(0, 30, 0),
656  NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_BASE_GRF_DROPDOWN), SetMinimalSize(150, 12), SetDataTip(STR_BLACK_RAW_STRING, STR_GAME_OPTIONS_BASE_GRF_TOOLTIP),
657  NWidget(WWT_TEXT, COLOUR_GREY, WID_GO_BASE_GRF_STATUS), SetMinimalSize(150, 12), SetDataTip(STR_EMPTY, STR_NULL), SetFill(1, 0),
658  EndContainer(),
659  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),
661  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),
662  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),
663  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),
664  EndContainer(),
665  EndContainer(),
666 
667  NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_BASE_SFX, STR_NULL), SetPadding(0, 10, 0, 10),
668  NWidget(NWID_HORIZONTAL), SetPIP(0, 30, 0),
669  NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_BASE_SFX_DROPDOWN), SetMinimalSize(150, 12), SetDataTip(STR_BLACK_RAW_STRING, STR_GAME_OPTIONS_BASE_SFX_TOOLTIP),
670  NWidget(NWID_SPACER), SetFill(1, 0),
671  EndContainer(),
672  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),
674  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),
675  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),
676  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),
677  EndContainer(),
678  EndContainer(),
679 
680  NWidget(WWT_FRAME, COLOUR_GREY), SetDataTip(STR_GAME_OPTIONS_BASE_MUSIC, STR_NULL), SetPadding(0, 10, 0, 10),
681  NWidget(NWID_HORIZONTAL), SetPIP(0, 30, 0),
682  NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_GO_BASE_MUSIC_DROPDOWN), SetMinimalSize(150, 12), SetDataTip(STR_BLACK_RAW_STRING, STR_GAME_OPTIONS_BASE_MUSIC_TOOLTIP),
683  NWidget(WWT_TEXT, COLOUR_GREY, WID_GO_BASE_MUSIC_STATUS), SetMinimalSize(150, 12), SetDataTip(STR_EMPTY, STR_NULL), SetFill(1, 0),
684  EndContainer(),
685  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),
687  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),
688  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),
689  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),
690  EndContainer(),
691  EndContainer(),
692  EndContainer(),
693 };
694 
695 static WindowDesc _game_options_desc(
696  WDP_CENTER, "settings_game", 0, 0,
698  0,
699  _nested_game_options_widgets, lengthof(_nested_game_options_widgets)
700 );
701 
704 {
706  new GameOptionsWindow(&_game_options_desc);
707 }
708 
709 static int SETTING_HEIGHT = 11;
710 static const int LEVEL_WIDTH = 15;
711 
720 
721  SEF_LAST_FIELD = 0x04,
722  SEF_FILTERED = 0x08,
723 };
724 
733 };
735 
736 
740  bool type_hides;
743 };
744 
747  byte flags;
748  byte level;
749 
750  BaseSettingEntry() : flags(0), level(0) {}
751  virtual ~BaseSettingEntry() {}
752 
753  virtual void Init(byte level = 0);
754  virtual void FoldAll() {}
755  virtual void UnFoldAll() {}
756 
761  void SetLastField(bool last_field) { if (last_field) SETBITS(this->flags, SEF_LAST_FIELD); else CLRBITS(this->flags, SEF_LAST_FIELD); }
762 
763  virtual uint Length() const = 0;
764  virtual void GetFoldingState(bool &all_folded, bool &all_unfolded) const {}
765  virtual bool IsVisible(const BaseSettingEntry *item) const;
766  virtual BaseSettingEntry *FindEntry(uint row, uint *cur_row);
767  virtual uint GetMaxHelpHeight(int maxw) { return 0; }
768 
773  bool IsFiltered() const { return (this->flags & SEF_FILTERED) != 0; }
774 
775  virtual bool UpdateFilterState(SettingFilter &filter, bool force_visible) = 0;
776 
777  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;
778 
779 protected:
780  virtual void DrawSetting(GameSettings *settings_ptr, int left, int right, int y, bool highlight) const = 0;
781 };
782 
785  const char *name;
787  uint index;
788 
789  SettingEntry(const char *name);
790 
791  virtual void Init(byte level = 0);
792  virtual uint Length() const;
793  virtual uint GetMaxHelpHeight(int maxw);
794  virtual bool UpdateFilterState(SettingFilter &filter, bool force_visible);
795 
796  void SetButtons(byte new_val);
797 
802  inline StringID GetHelpText() const
803  {
804  return this->setting->desc.str_help;
805  }
806 
807  void SetValueDParams(uint first_param, int32 value) const;
808 
809 protected:
810  virtual void DrawSetting(GameSettings *settings_ptr, int left, int right, int y, bool highlight) const;
811 
812 private:
813  bool IsVisibleByRestrictionMode(RestrictionMode mode) const;
814 };
815 
818  typedef std::vector<BaseSettingEntry*> EntryVector;
819  EntryVector entries;
820 
821  template<typename T>
822  T *Add(T *item)
823  {
824  this->entries.push_back(item);
825  return item;
826  }
827 
828  void Init(byte level = 0);
829  void FoldAll();
830  void UnFoldAll();
831 
832  uint Length() const;
833  void GetFoldingState(bool &all_folded, bool &all_unfolded) const;
834  bool IsVisible(const BaseSettingEntry *item) const;
835  BaseSettingEntry *FindEntry(uint row, uint *cur_row);
836  uint GetMaxHelpHeight(int maxw);
837 
838  bool UpdateFilterState(SettingFilter &filter, bool force_visible);
839 
840  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;
841 };
842 
846  bool folded;
847 
848  SettingsPage(StringID title);
849 
850  virtual void Init(byte level = 0);
851  virtual void FoldAll();
852  virtual void UnFoldAll();
853 
854  virtual uint Length() const;
855  virtual void GetFoldingState(bool &all_folded, bool &all_unfolded) const;
856  virtual bool IsVisible(const BaseSettingEntry *item) const;
857  virtual BaseSettingEntry *FindEntry(uint row, uint *cur_row);
858  virtual uint GetMaxHelpHeight(int maxw) { return SettingsContainer::GetMaxHelpHeight(maxw); }
859 
860  virtual bool UpdateFilterState(SettingFilter &filter, bool force_visible);
861 
862  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;
863 
864 protected:
865  virtual void DrawSetting(GameSettings *settings_ptr, int left, int right, int y, bool highlight) const;
866 };
867 
868 /* == BaseSettingEntry methods == */
869 
874 void BaseSettingEntry::Init(byte level)
875 {
876  this->level = level;
877 }
878 
886 {
887  if (this->IsFiltered()) return false;
888  if (this == item) return true;
889  return false;
890 }
891 
898 BaseSettingEntry *BaseSettingEntry::FindEntry(uint row_num, uint *cur_row)
899 {
900  if (this->IsFiltered()) return NULL;
901  if (row_num == *cur_row) return this;
902  (*cur_row)++;
903  return NULL;
904 }
905 
935 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
936 {
937  if (this->IsFiltered()) return cur_row;
938  if (cur_row >= max_row) return cur_row;
939 
940  bool rtl = _current_text_dir == TD_RTL;
941  int offset = rtl ? -4 : 4;
942  int level_width = rtl ? -LEVEL_WIDTH : LEVEL_WIDTH;
943 
944  int x = rtl ? right : left;
945  if (cur_row >= first_row) {
946  int colour = _colour_gradient[COLOUR_ORANGE][4];
947  y += (cur_row - first_row) * SETTING_HEIGHT; // Compute correct y start position
948 
949  /* Draw vertical for parent nesting levels */
950  for (uint lvl = 0; lvl < this->level; lvl++) {
951  if (!HasBit(parent_last, lvl)) GfxDrawLine(x + offset, y, x + offset, y + SETTING_HEIGHT - 1, colour);
952  x += level_width;
953  }
954  /* draw own |- prefix */
955  int halfway_y = y + SETTING_HEIGHT / 2;
956  int bottom_y = (flags & SEF_LAST_FIELD) ? halfway_y : y + SETTING_HEIGHT - 1;
957  GfxDrawLine(x + offset, y, x + offset, bottom_y, colour);
958  /* Small horizontal line from the last vertical line */
959  GfxDrawLine(x + offset, halfway_y, x + level_width - offset, halfway_y, colour);
960  x += level_width;
961 
962  this->DrawSetting(settings_ptr, rtl ? left : x, rtl ? x : right, y, this == selected);
963  }
964  cur_row++;
965 
966  return cur_row;
967 }
968 
969 /* == SettingEntry methods == */
970 
975 SettingEntry::SettingEntry(const char *name)
976 {
977  this->name = name;
978  this->setting = NULL;
979  this->index = 0;
980 }
981 
986 void SettingEntry::Init(byte level)
987 {
988  BaseSettingEntry::Init(level);
989  this->setting = GetSettingFromName(this->name, &this->index);
990  assert(this->setting != NULL);
991 }
992 
998 void SettingEntry::SetButtons(byte new_val)
999 {
1000  assert((new_val & ~SEF_BUTTONS_MASK) == 0); // Should not touch any flags outside the buttons
1001  this->flags = (this->flags & ~SEF_BUTTONS_MASK) | new_val;
1002 }
1003 
1006 {
1007  return this->IsFiltered() ? 0 : 1;
1008 }
1009 
1016 {
1017  return GetStringHeight(this->GetHelpText(), maxw);
1018 }
1019 
1026 {
1027  /* There shall not be any restriction, i.e. all settings shall be visible. */
1028  if (mode == RM_ALL) return true;
1029 
1030  GameSettings *settings_ptr = &GetGameSettings();
1031  const SettingDesc *sd = this->setting;
1032 
1033  if (mode == RM_BASIC) return (this->setting->desc.cat & SC_BASIC_LIST) != 0;
1034  if (mode == RM_ADVANCED) return (this->setting->desc.cat & SC_ADVANCED_LIST) != 0;
1035 
1036  /* Read the current value. */
1037  const void *var = ResolveVariableAddress(settings_ptr, sd);
1038  int64 current_value = ReadValue(var, sd->save.conv);
1039 
1040  int64 filter_value;
1041 
1042  if (mode == RM_CHANGED_AGAINST_DEFAULT) {
1043  /* This entry shall only be visible, if the value deviates from its default value. */
1044 
1045  /* Read the default value. */
1046  filter_value = ReadValue(&sd->desc.def, sd->save.conv);
1047  } else {
1048  assert(mode == RM_CHANGED_AGAINST_NEW);
1049  /* This entry shall only be visible, if the value deviates from
1050  * its value is used when starting a new game. */
1051 
1052  /* Make sure we're not comparing the new game settings against itself. */
1053  assert(settings_ptr != &_settings_newgame);
1054 
1055  /* Read the new game's value. */
1056  var = ResolveVariableAddress(&_settings_newgame, sd);
1057  filter_value = ReadValue(var, sd->save.conv);
1058  }
1059 
1060  return current_value != filter_value;
1061 }
1062 
1069 bool SettingEntry::UpdateFilterState(SettingFilter &filter, bool force_visible)
1070 {
1071  CLRBITS(this->flags, SEF_FILTERED);
1072 
1073  bool visible = true;
1074 
1075  const SettingDesc *sd = this->setting;
1076  if (!force_visible && !filter.string.IsEmpty()) {
1077  /* Process the search text filter for this item. */
1078  filter.string.ResetState();
1079 
1080  const SettingDescBase *sdb = &sd->desc;
1081 
1082  SetDParam(0, STR_EMPTY);
1083  filter.string.AddLine(sdb->str);
1084  filter.string.AddLine(this->GetHelpText());
1085 
1086  visible = filter.string.GetState();
1087  }
1088 
1089  if (visible) {
1090  if (filter.type != ST_ALL && sd->GetType() != filter.type) {
1091  filter.type_hides = true;
1092  visible = false;
1093  }
1094  if (!this->IsVisibleByRestrictionMode(filter.mode)) {
1095  while (filter.min_cat < RM_ALL && (filter.min_cat == filter.mode || !this->IsVisibleByRestrictionMode(filter.min_cat))) filter.min_cat++;
1096  visible = false;
1097  }
1098  }
1099 
1100  if (!visible) SETBITS(this->flags, SEF_FILTERED);
1101  return visible;
1102 }
1103 
1104 
1105 static const void *ResolveVariableAddress(const GameSettings *settings_ptr, const SettingDesc *sd)
1106 {
1107  if ((sd->desc.flags & SGF_PER_COMPANY) != 0) {
1108  if (Company::IsValidID(_local_company) && _game_mode != GM_MENU) {
1110  } else {
1112  }
1113  } else {
1114  return GetVariableAddress(settings_ptr, &sd->save);
1115  }
1116 }
1117 
1123 void SettingEntry::SetValueDParams(uint first_param, int32 value) const
1124 {
1125  const SettingDescBase *sdb = &this->setting->desc;
1126  if (sdb->cmd == SDT_BOOLX) {
1127  SetDParam(first_param++, value != 0 ? STR_CONFIG_SETTING_ON : STR_CONFIG_SETTING_OFF);
1128  } else {
1129  if ((sdb->flags & SGF_MULTISTRING) != 0) {
1130  SetDParam(first_param++, sdb->str_val - sdb->min + value);
1131  } else if ((sdb->flags & SGF_DISPLAY_ABS) != 0) {
1132  SetDParam(first_param++, sdb->str_val + ((value >= 0) ? 1 : 0));
1133  value = abs(value);
1134  } else {
1135  SetDParam(first_param++, sdb->str_val + ((value == 0 && (sdb->flags & SGF_0ISDISABLED) != 0) ? 1 : 0));
1136  }
1137  SetDParam(first_param++, value);
1138  }
1139 }
1140 
1149 void SettingEntry::DrawSetting(GameSettings *settings_ptr, int left, int right, int y, bool highlight) const
1150 {
1151  const SettingDesc *sd = this->setting;
1152  const SettingDescBase *sdb = &sd->desc;
1153  const void *var = ResolveVariableAddress(settings_ptr, sd);
1154  int state = this->flags & SEF_BUTTONS_MASK;
1155 
1156  bool rtl = _current_text_dir == TD_RTL;
1157  uint buttons_left = rtl ? right + 1 - SETTING_BUTTON_WIDTH : left;
1158  uint text_left = left + (rtl ? 0 : SETTING_BUTTON_WIDTH + 5);
1159  uint text_right = right - (rtl ? SETTING_BUTTON_WIDTH + 5 : 0);
1160  uint button_y = y + (SETTING_HEIGHT - SETTING_BUTTON_HEIGHT) / 2;
1161 
1162  /* We do not allow changes of some items when we are a client in a networkgame */
1163  bool editable = sd->IsEditable();
1164 
1165  SetDParam(0, highlight ? STR_ORANGE_STRING1_WHITE : STR_ORANGE_STRING1_LTBLUE);
1166  int32 value = (int32)ReadValue(var, sd->save.conv);
1167  if (sdb->cmd == SDT_BOOLX) {
1168  /* Draw checkbox for boolean-value either on/off */
1169  DrawBoolButton(buttons_left, button_y, value != 0, editable);
1170  } else if ((sdb->flags & SGF_MULTISTRING) != 0) {
1171  /* Draw [v] button for settings of an enum-type */
1172  DrawDropDownButton(buttons_left, button_y, COLOUR_YELLOW, state != 0, editable);
1173  } else {
1174  /* Draw [<][>] boxes for settings of an integer-type */
1175  DrawArrowButtons(buttons_left, button_y, COLOUR_YELLOW, state,
1176  editable && value != (sdb->flags & SGF_0ISDISABLED ? 0 : sdb->min), editable && (uint32)value != sdb->max);
1177  }
1178  this->SetValueDParams(1, value);
1179  DrawString(text_left, text_right, y + (SETTING_HEIGHT - FONT_HEIGHT_NORMAL) / 2, sdb->str, highlight ? TC_WHITE : TC_LIGHT_BLUE);
1180 }
1181 
1182 /* == SettingsContainer methods == */
1183 
1188 void SettingsContainer::Init(byte level)
1189 {
1190  for (EntryVector::iterator it = this->entries.begin(); it != this->entries.end(); ++it) {
1191  (*it)->Init(level);
1192  }
1193 }
1194 
1197 {
1198  for (EntryVector::iterator it = this->entries.begin(); it != this->entries.end(); ++it) {
1199  (*it)->FoldAll();
1200  }
1201 }
1202 
1205 {
1206  for (EntryVector::iterator it = this->entries.begin(); it != this->entries.end(); ++it) {
1207  (*it)->UnFoldAll();
1208  }
1209 }
1210 
1216 void SettingsContainer::GetFoldingState(bool &all_folded, bool &all_unfolded) const
1217 {
1218  for (EntryVector::const_iterator it = this->entries.begin(); it != this->entries.end(); ++it) {
1219  (*it)->GetFoldingState(all_folded, all_unfolded);
1220  }
1221 }
1222 
1229 bool SettingsContainer::UpdateFilterState(SettingFilter &filter, bool force_visible)
1230 {
1231  bool visible = false;
1232  bool first_visible = true;
1233  for (EntryVector::reverse_iterator it = this->entries.rbegin(); it != this->entries.rend(); ++it) {
1234  visible |= (*it)->UpdateFilterState(filter, force_visible);
1235  (*it)->SetLastField(first_visible);
1236  if (visible && first_visible) first_visible = false;
1237  }
1238  return visible;
1239 }
1240 
1241 
1249 {
1250  for (EntryVector::const_iterator it = this->entries.begin(); it != this->entries.end(); ++it) {
1251  if ((*it)->IsVisible(item)) return true;
1252  }
1253  return false;
1254 }
1255 
1258 {
1259  uint length = 0;
1260  for (EntryVector::const_iterator it = this->entries.begin(); it != this->entries.end(); ++it) {
1261  length += (*it)->Length();
1262  }
1263  return length;
1264 }
1265 
1272 BaseSettingEntry *SettingsContainer::FindEntry(uint row_num, uint *cur_row)
1273 {
1274  BaseSettingEntry *pe = NULL;
1275  for (EntryVector::iterator it = this->entries.begin(); it != this->entries.end(); ++it) {
1276  pe = (*it)->FindEntry(row_num, cur_row);
1277  if (pe != NULL) {
1278  break;
1279  }
1280  }
1281  return pe;
1282 }
1283 
1290 {
1291  uint biggest = 0;
1292  for (EntryVector::const_iterator it = this->entries.begin(); it != this->entries.end(); ++it) {
1293  biggest = max(biggest, (*it)->GetMaxHelpHeight(maxw));
1294  }
1295  return biggest;
1296 }
1297 
1298 
1313 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
1314 {
1315  for (EntryVector::const_iterator it = this->entries.begin(); it != this->entries.end(); ++it) {
1316  cur_row = (*it)->Draw(settings_ptr, left, right, y, first_row, max_row, selected, cur_row, parent_last);
1317  if (cur_row >= max_row) {
1318  break;
1319  }
1320  }
1321  return cur_row;
1322 }
1323 
1324 /* == SettingsPage methods == */
1325 
1331 {
1332  this->title = title;
1333  this->folded = true;
1334 }
1335 
1340 void SettingsPage::Init(byte level)
1341 {
1342  BaseSettingEntry::Init(level);
1343  SettingsContainer::Init(level + 1);
1344 }
1345 
1348 {
1349  if (this->IsFiltered()) return;
1350  this->folded = true;
1351 
1353 }
1354 
1357 {
1358  if (this->IsFiltered()) return;
1359  this->folded = false;
1360 
1362 }
1363 
1369 void SettingsPage::GetFoldingState(bool &all_folded, bool &all_unfolded) const
1370 {
1371  if (this->IsFiltered()) return;
1372 
1373  if (this->folded) {
1374  all_unfolded = false;
1375  } else {
1376  all_folded = false;
1377  }
1378 
1379  SettingsContainer::GetFoldingState(all_folded, all_unfolded);
1380 }
1381 
1388 bool SettingsPage::UpdateFilterState(SettingFilter &filter, bool force_visible)
1389 {
1390  if (!force_visible && !filter.string.IsEmpty()) {
1391  filter.string.ResetState();
1392  filter.string.AddLine(this->title);
1393  force_visible = filter.string.GetState();
1394  }
1395 
1396  bool visible = SettingsContainer::UpdateFilterState(filter, force_visible);
1397  if (visible) {
1398  CLRBITS(this->flags, SEF_FILTERED);
1399  } else {
1400  SETBITS(this->flags, SEF_FILTERED);
1401  }
1402  return visible;
1403 }
1404 
1412 {
1413  if (this->IsFiltered()) return false;
1414  if (this == item) return true;
1415  if (this->folded) return false;
1416 
1417  return SettingsContainer::IsVisible(item);
1418 }
1419 
1422 {
1423  if (this->IsFiltered()) return 0;
1424  if (this->folded) return 1; // Only displaying the title
1425 
1426  return 1 + SettingsContainer::Length();
1427 }
1428 
1435 BaseSettingEntry *SettingsPage::FindEntry(uint row_num, uint *cur_row)
1436 {
1437  if (this->IsFiltered()) return NULL;
1438  if (row_num == *cur_row) return this;
1439  (*cur_row)++;
1440  if (this->folded) return NULL;
1441 
1442  return SettingsContainer::FindEntry(row_num, cur_row);
1443 }
1444 
1459 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
1460 {
1461  if (this->IsFiltered()) return cur_row;
1462  if (cur_row >= max_row) return cur_row;
1463 
1464  cur_row = BaseSettingEntry::Draw(settings_ptr, left, right, y, first_row, max_row, selected, cur_row, parent_last);
1465 
1466  if (!this->folded) {
1467  if (this->flags & SEF_LAST_FIELD) {
1468  assert(this->level < 8 * sizeof(parent_last));
1469  SetBit(parent_last, this->level); // Add own last-field state
1470  }
1471 
1472  cur_row = SettingsContainer::Draw(settings_ptr, left, right, y, first_row, max_row, selected, cur_row, parent_last);
1473  }
1474 
1475  return cur_row;
1476 }
1477 
1486 void SettingsPage::DrawSetting(GameSettings *settings_ptr, int left, int right, int y, bool highlight) const
1487 {
1488  bool rtl = _current_text_dir == TD_RTL;
1489  DrawSprite((this->folded ? SPR_CIRCLE_FOLDED : SPR_CIRCLE_UNFOLDED), PAL_NONE, rtl ? right - _circle_size.width : left, y + (SETTING_HEIGHT - _circle_size.height) / 2);
1490  DrawString(rtl ? left : left + _circle_size.width + 2, rtl ? right - _circle_size.width - 2 : right, y + (SETTING_HEIGHT - FONT_HEIGHT_NORMAL) / 2, this->title);
1491 }
1492 
1495 {
1496  static SettingsContainer *main = NULL;
1497 
1498  if (main == NULL)
1499  {
1500  /* Build up the dynamic settings-array only once per OpenTTD session */
1501  main = new SettingsContainer();
1502 
1503  SettingsPage *localisation = main->Add(new SettingsPage(STR_CONFIG_SETTING_LOCALISATION));
1504  {
1505  localisation->Add(new SettingEntry("locale.units_velocity"));
1506  localisation->Add(new SettingEntry("locale.units_power"));
1507  localisation->Add(new SettingEntry("locale.units_weight"));
1508  localisation->Add(new SettingEntry("locale.units_volume"));
1509  localisation->Add(new SettingEntry("locale.units_force"));
1510  localisation->Add(new SettingEntry("locale.units_height"));
1511  localisation->Add(new SettingEntry("gui.date_format_in_default_names"));
1512  }
1513 
1514  SettingsPage *graphics = main->Add(new SettingsPage(STR_CONFIG_SETTING_GRAPHICS));
1515  {
1516  graphics->Add(new SettingEntry("gui.zoom_min"));
1517  graphics->Add(new SettingEntry("gui.zoom_max"));
1518  graphics->Add(new SettingEntry("gui.smallmap_land_colour"));
1519  graphics->Add(new SettingEntry("gui.graph_line_thickness"));
1520  }
1521 
1522  SettingsPage *sound = main->Add(new SettingsPage(STR_CONFIG_SETTING_SOUND));
1523  {
1524  sound->Add(new SettingEntry("sound.click_beep"));
1525  sound->Add(new SettingEntry("sound.confirm"));
1526  sound->Add(new SettingEntry("sound.news_ticker"));
1527  sound->Add(new SettingEntry("sound.news_full"));
1528  sound->Add(new SettingEntry("sound.new_year"));
1529  sound->Add(new SettingEntry("sound.disaster"));
1530  sound->Add(new SettingEntry("sound.vehicle"));
1531  sound->Add(new SettingEntry("sound.ambient"));
1532  }
1533 
1534  SettingsPage *interface = main->Add(new SettingsPage(STR_CONFIG_SETTING_INTERFACE));
1535  {
1536  SettingsPage *general = interface->Add(new SettingsPage(STR_CONFIG_SETTING_INTERFACE_GENERAL));
1537  {
1538  general->Add(new SettingEntry("gui.osk_activation"));
1539  general->Add(new SettingEntry("gui.hover_delay_ms"));
1540  general->Add(new SettingEntry("gui.errmsg_duration"));
1541  general->Add(new SettingEntry("gui.window_snap_radius"));
1542  general->Add(new SettingEntry("gui.window_soft_limit"));
1543  general->Add(new SettingEntry("gui.right_mouse_wnd_close"));
1544  }
1545 
1546  SettingsPage *viewports = interface->Add(new SettingsPage(STR_CONFIG_SETTING_INTERFACE_VIEWPORTS));
1547  {
1548  viewports->Add(new SettingEntry("gui.auto_scrolling"));
1549  viewports->Add(new SettingEntry("gui.scroll_mode"));
1550  viewports->Add(new SettingEntry("gui.smooth_scroll"));
1551  /* While the horizontal scrollwheel scrolling is written as general code, only
1552  * the cocoa (OSX) driver generates input for it.
1553  * Since it's also able to completely disable the scrollwheel will we display it on all platforms anyway */
1554  viewports->Add(new SettingEntry("gui.scrollwheel_scrolling"));
1555  viewports->Add(new SettingEntry("gui.scrollwheel_multiplier"));
1556 #ifdef __APPLE__
1557  /* We might need to emulate a right mouse button on mac */
1558  viewports->Add(new SettingEntry("gui.right_mouse_btn_emulation"));
1559 #endif
1560  viewports->Add(new SettingEntry("gui.population_in_label"));
1561  viewports->Add(new SettingEntry("gui.liveries"));
1562  viewports->Add(new SettingEntry("construction.train_signal_side"));
1563  viewports->Add(new SettingEntry("gui.measure_tooltip"));
1564  viewports->Add(new SettingEntry("gui.loading_indicators"));
1565  viewports->Add(new SettingEntry("gui.show_track_reservation"));
1566  }
1567 
1568  SettingsPage *construction = interface->Add(new SettingsPage(STR_CONFIG_SETTING_INTERFACE_CONSTRUCTION));
1569  {
1570  construction->Add(new SettingEntry("gui.link_terraform_toolbar"));
1571  construction->Add(new SettingEntry("gui.enable_signal_gui"));
1572  construction->Add(new SettingEntry("gui.persistent_buildingtools"));
1573  construction->Add(new SettingEntry("gui.quick_goto"));
1574  construction->Add(new SettingEntry("gui.default_rail_type"));
1575  construction->Add(new SettingEntry("gui.disable_unsuitable_building"));
1576  }
1577 
1578  interface->Add(new SettingEntry("gui.autosave"));
1579  interface->Add(new SettingEntry("gui.toolbar_pos"));
1580  interface->Add(new SettingEntry("gui.statusbar_pos"));
1581  interface->Add(new SettingEntry("gui.prefer_teamchat"));
1582  interface->Add(new SettingEntry("gui.advanced_vehicle_list"));
1583  interface->Add(new SettingEntry("gui.timetable_in_ticks"));
1584  interface->Add(new SettingEntry("gui.timetable_arrival_departure"));
1585  interface->Add(new SettingEntry("gui.expenses_layout"));
1586  }
1587 
1588  SettingsPage *advisors = main->Add(new SettingsPage(STR_CONFIG_SETTING_ADVISORS));
1589  {
1590  advisors->Add(new SettingEntry("gui.coloured_news_year"));
1591  advisors->Add(new SettingEntry("news_display.general"));
1592  advisors->Add(new SettingEntry("news_display.new_vehicles"));
1593  advisors->Add(new SettingEntry("news_display.accident"));
1594  advisors->Add(new SettingEntry("news_display.company_info"));
1595  advisors->Add(new SettingEntry("news_display.acceptance"));
1596  advisors->Add(new SettingEntry("news_display.arrival_player"));
1597  advisors->Add(new SettingEntry("news_display.arrival_other"));
1598  advisors->Add(new SettingEntry("news_display.advice"));
1599  advisors->Add(new SettingEntry("gui.order_review_system"));
1600  advisors->Add(new SettingEntry("gui.vehicle_income_warn"));
1601  advisors->Add(new SettingEntry("gui.lost_vehicle_warn"));
1602  advisors->Add(new SettingEntry("gui.show_finances"));
1603  advisors->Add(new SettingEntry("news_display.economy"));
1604  advisors->Add(new SettingEntry("news_display.subsidies"));
1605  advisors->Add(new SettingEntry("news_display.open"));
1606  advisors->Add(new SettingEntry("news_display.close"));
1607  advisors->Add(new SettingEntry("news_display.production_player"));
1608  advisors->Add(new SettingEntry("news_display.production_other"));
1609  advisors->Add(new SettingEntry("news_display.production_nobody"));
1610  }
1611 
1612  SettingsPage *company = main->Add(new SettingsPage(STR_CONFIG_SETTING_COMPANY));
1613  {
1614  company->Add(new SettingEntry("gui.semaphore_build_before"));
1615  company->Add(new SettingEntry("gui.default_signal_type"));
1616  company->Add(new SettingEntry("gui.cycle_signal_types"));
1617  company->Add(new SettingEntry("gui.drag_signals_fixed_distance"));
1618  company->Add(new SettingEntry("gui.new_nonstop"));
1619  company->Add(new SettingEntry("gui.stop_location"));
1620  company->Add(new SettingEntry("gui.starting_colour"));
1621  company->Add(new SettingEntry("company.engine_renew"));
1622  company->Add(new SettingEntry("company.engine_renew_months"));
1623  company->Add(new SettingEntry("company.engine_renew_money"));
1624  company->Add(new SettingEntry("vehicle.servint_ispercent"));
1625  company->Add(new SettingEntry("vehicle.servint_trains"));
1626  company->Add(new SettingEntry("vehicle.servint_roadveh"));
1627  company->Add(new SettingEntry("vehicle.servint_ships"));
1628  company->Add(new SettingEntry("vehicle.servint_aircraft"));
1629  }
1630 
1631  SettingsPage *accounting = main->Add(new SettingsPage(STR_CONFIG_SETTING_ACCOUNTING));
1632  {
1633  accounting->Add(new SettingEntry("economy.inflation"));
1634  accounting->Add(new SettingEntry("difficulty.initial_interest"));
1635  accounting->Add(new SettingEntry("difficulty.max_loan"));
1636  accounting->Add(new SettingEntry("difficulty.subsidy_multiplier"));
1637  accounting->Add(new SettingEntry("economy.feeder_payment_share"));
1638  accounting->Add(new SettingEntry("economy.infrastructure_maintenance"));
1639  accounting->Add(new SettingEntry("difficulty.vehicle_costs"));
1640  accounting->Add(new SettingEntry("difficulty.construction_cost"));
1641  }
1642 
1643  SettingsPage *vehicles = main->Add(new SettingsPage(STR_CONFIG_SETTING_VEHICLES));
1644  {
1645  SettingsPage *physics = vehicles->Add(new SettingsPage(STR_CONFIG_SETTING_VEHICLES_PHYSICS));
1646  {
1647  physics->Add(new SettingEntry("vehicle.train_acceleration_model"));
1648  physics->Add(new SettingEntry("vehicle.train_slope_steepness"));
1649  physics->Add(new SettingEntry("vehicle.wagon_speed_limits"));
1650  physics->Add(new SettingEntry("vehicle.freight_trains"));
1651  physics->Add(new SettingEntry("vehicle.roadveh_acceleration_model"));
1652  physics->Add(new SettingEntry("vehicle.roadveh_slope_steepness"));
1653  physics->Add(new SettingEntry("vehicle.smoke_amount"));
1654  physics->Add(new SettingEntry("vehicle.plane_speed"));
1655  }
1656 
1657  SettingsPage *routing = vehicles->Add(new SettingsPage(STR_CONFIG_SETTING_VEHICLES_ROUTING));
1658  {
1659  routing->Add(new SettingEntry("pf.pathfinder_for_trains"));
1660  routing->Add(new SettingEntry("difficulty.line_reverse_mode"));
1661  routing->Add(new SettingEntry("pf.reverse_at_signals"));
1662  routing->Add(new SettingEntry("pf.forbid_90_deg"));
1663  routing->Add(new SettingEntry("pf.pathfinder_for_roadvehs"));
1664  routing->Add(new SettingEntry("pf.pathfinder_for_ships"));
1665  }
1666 
1667  vehicles->Add(new SettingEntry("order.no_servicing_if_no_breakdowns"));
1668  vehicles->Add(new SettingEntry("order.serviceathelipad"));
1669  }
1670 
1671  SettingsPage *limitations = main->Add(new SettingsPage(STR_CONFIG_SETTING_LIMITATIONS));
1672  {
1673  limitations->Add(new SettingEntry("construction.command_pause_level"));
1674  limitations->Add(new SettingEntry("construction.autoslope"));
1675  limitations->Add(new SettingEntry("construction.extra_dynamite"));
1676  limitations->Add(new SettingEntry("construction.max_heightlevel"));
1677  limitations->Add(new SettingEntry("construction.max_bridge_length"));
1678  limitations->Add(new SettingEntry("construction.max_bridge_height"));
1679  limitations->Add(new SettingEntry("construction.max_tunnel_length"));
1680  limitations->Add(new SettingEntry("station.never_expire_airports"));
1681  limitations->Add(new SettingEntry("vehicle.never_expire_vehicles"));
1682  limitations->Add(new SettingEntry("vehicle.max_trains"));
1683  limitations->Add(new SettingEntry("vehicle.max_roadveh"));
1684  limitations->Add(new SettingEntry("vehicle.max_aircraft"));
1685  limitations->Add(new SettingEntry("vehicle.max_ships"));
1686  limitations->Add(new SettingEntry("vehicle.max_train_length"));
1687  limitations->Add(new SettingEntry("station.station_spread"));
1688  limitations->Add(new SettingEntry("station.distant_join_stations"));
1689  limitations->Add(new SettingEntry("construction.road_stop_on_town_road"));
1690  limitations->Add(new SettingEntry("construction.road_stop_on_competitor_road"));
1691  limitations->Add(new SettingEntry("vehicle.disable_elrails"));
1692  }
1693 
1694  SettingsPage *disasters = main->Add(new SettingsPage(STR_CONFIG_SETTING_ACCIDENTS));
1695  {
1696  disasters->Add(new SettingEntry("difficulty.disasters"));
1697  disasters->Add(new SettingEntry("difficulty.economy"));
1698  disasters->Add(new SettingEntry("difficulty.vehicle_breakdowns"));
1699  disasters->Add(new SettingEntry("vehicle.plane_crashes"));
1700  }
1701 
1702  SettingsPage *genworld = main->Add(new SettingsPage(STR_CONFIG_SETTING_GENWORLD));
1703  {
1704  genworld->Add(new SettingEntry("game_creation.landscape"));
1705  genworld->Add(new SettingEntry("game_creation.land_generator"));
1706  genworld->Add(new SettingEntry("difficulty.terrain_type"));
1707  genworld->Add(new SettingEntry("game_creation.tgen_smoothness"));
1708  genworld->Add(new SettingEntry("game_creation.variety"));
1709  genworld->Add(new SettingEntry("game_creation.snow_line_height"));
1710  genworld->Add(new SettingEntry("game_creation.amount_of_rivers"));
1711  genworld->Add(new SettingEntry("game_creation.tree_placer"));
1712  genworld->Add(new SettingEntry("vehicle.road_side"));
1713  genworld->Add(new SettingEntry("economy.larger_towns"));
1714  genworld->Add(new SettingEntry("economy.initial_city_size"));
1715  genworld->Add(new SettingEntry("economy.town_layout"));
1716  genworld->Add(new SettingEntry("difficulty.industry_density"));
1717  genworld->Add(new SettingEntry("gui.pause_on_newgame"));
1718  }
1719 
1720  SettingsPage *environment = main->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT));
1721  {
1722  SettingsPage *authorities = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_AUTHORITIES));
1723  {
1724  authorities->Add(new SettingEntry("difficulty.town_council_tolerance"));
1725  authorities->Add(new SettingEntry("economy.bribe"));
1726  authorities->Add(new SettingEntry("economy.exclusive_rights"));
1727  authorities->Add(new SettingEntry("economy.fund_roads"));
1728  authorities->Add(new SettingEntry("economy.fund_buildings"));
1729  authorities->Add(new SettingEntry("economy.station_noise_level"));
1730  }
1731 
1732  SettingsPage *towns = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_TOWNS));
1733  {
1734  towns->Add(new SettingEntry("economy.town_growth_rate"));
1735  towns->Add(new SettingEntry("economy.allow_town_roads"));
1736  towns->Add(new SettingEntry("economy.allow_town_level_crossings"));
1737  towns->Add(new SettingEntry("economy.found_town"));
1738  }
1739 
1740  SettingsPage *industries = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_INDUSTRIES));
1741  {
1742  industries->Add(new SettingEntry("construction.raw_industry_construction"));
1743  industries->Add(new SettingEntry("construction.industry_platform"));
1744  industries->Add(new SettingEntry("economy.multiple_industry_per_town"));
1745  industries->Add(new SettingEntry("game_creation.oil_refinery_limit"));
1746  industries->Add(new SettingEntry("economy.smooth_economy"));
1747  }
1748 
1749  SettingsPage *cdist = environment->Add(new SettingsPage(STR_CONFIG_SETTING_ENVIRONMENT_CARGODIST));
1750  {
1751  cdist->Add(new SettingEntry("linkgraph.recalc_time"));
1752  cdist->Add(new SettingEntry("linkgraph.recalc_interval"));
1753  cdist->Add(new SettingEntry("linkgraph.distribution_pax"));
1754  cdist->Add(new SettingEntry("linkgraph.distribution_mail"));
1755  cdist->Add(new SettingEntry("linkgraph.distribution_armoured"));
1756  cdist->Add(new SettingEntry("linkgraph.distribution_default"));
1757  cdist->Add(new SettingEntry("linkgraph.accuracy"));
1758  cdist->Add(new SettingEntry("linkgraph.demand_distance"));
1759  cdist->Add(new SettingEntry("linkgraph.demand_size"));
1760  cdist->Add(new SettingEntry("linkgraph.short_path_saturation"));
1761  }
1762 
1763  environment->Add(new SettingEntry("station.modified_catchment"));
1764  environment->Add(new SettingEntry("construction.extra_tree_placement"));
1765  }
1766 
1767  SettingsPage *ai = main->Add(new SettingsPage(STR_CONFIG_SETTING_AI));
1768  {
1769  SettingsPage *npc = ai->Add(new SettingsPage(STR_CONFIG_SETTING_AI_NPC));
1770  {
1771  npc->Add(new SettingEntry("script.settings_profile"));
1772  npc->Add(new SettingEntry("script.script_max_opcode_till_suspend"));
1773  npc->Add(new SettingEntry("difficulty.competitor_speed"));
1774  npc->Add(new SettingEntry("ai.ai_in_multiplayer"));
1775  npc->Add(new SettingEntry("ai.ai_disable_veh_train"));
1776  npc->Add(new SettingEntry("ai.ai_disable_veh_roadveh"));
1777  npc->Add(new SettingEntry("ai.ai_disable_veh_aircraft"));
1778  npc->Add(new SettingEntry("ai.ai_disable_veh_ship"));
1779  }
1780 
1781  ai->Add(new SettingEntry("economy.give_money"));
1782  ai->Add(new SettingEntry("economy.allow_shares"));
1783  }
1784 
1785  main->Init();
1786  }
1787  return *main;
1788 }
1789 
1790 static const StringID _game_settings_restrict_dropdown[] = {
1791  STR_CONFIG_SETTING_RESTRICT_BASIC, // RM_BASIC
1792  STR_CONFIG_SETTING_RESTRICT_ADVANCED, // RM_ADVANCED
1793  STR_CONFIG_SETTING_RESTRICT_ALL, // RM_ALL
1794  STR_CONFIG_SETTING_RESTRICT_CHANGED_AGAINST_DEFAULT, // RM_CHANGED_AGAINST_DEFAULT
1795  STR_CONFIG_SETTING_RESTRICT_CHANGED_AGAINST_NEW, // RM_CHANGED_AGAINST_NEW
1796 };
1797 assert_compile(lengthof(_game_settings_restrict_dropdown) == RM_END);
1798 
1805 };
1806 
1809  static const int SETTINGTREE_LEFT_OFFSET = 5;
1810  static const int SETTINGTREE_RIGHT_OFFSET = 5;
1811  static const int SETTINGTREE_TOP_OFFSET = 5;
1812  static const int SETTINGTREE_BOTTOM_OFFSET = 5;
1813 
1815 
1821 
1827 
1828  Scrollbar *vscroll;
1829 
1830  GameSettingsWindow(WindowDesc *desc) : Window(desc), filter_editbox(50)
1831  {
1832  this->warn_missing = WHR_NONE;
1833  this->warn_lines = 0;
1835  this->filter.min_cat = RM_ALL;
1836  this->filter.type = ST_ALL;
1837  this->filter.type_hides = false;
1838  this->settings_ptr = &GetGameSettings();
1839 
1840  _circle_size = maxdim(GetSpriteSize(SPR_CIRCLE_FOLDED), GetSpriteSize(SPR_CIRCLE_UNFOLDED));
1841  GetSettingsTree().FoldAll(); // Close all sub-pages
1842 
1843  this->valuewindow_entry = NULL; // No setting entry for which a entry window is opened
1844  this->clicked_entry = NULL; // No numeric setting buttons are depressed
1845  this->last_clicked = NULL;
1846  this->valuedropdown_entry = NULL;
1847  this->closing_dropdown = false;
1848  this->manually_changed_folding = false;
1849 
1850  this->CreateNestedTree();
1851  this->vscroll = this->GetScrollbar(WID_GS_SCROLLBAR);
1853 
1854  this->querystrings[WID_GS_FILTER] = &this->filter_editbox;
1855  this->filter_editbox.cancel_button = QueryString::ACTION_CLEAR;
1857 
1858  this->InvalidateData();
1859  }
1860 
1861  virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
1862  {
1863  switch (widget) {
1864  case WID_GS_OPTIONSPANEL:
1865  resize->height = SETTING_HEIGHT = max(max<int>(_circle_size.height, SETTING_BUTTON_HEIGHT), FONT_HEIGHT_NORMAL) + 1;
1866  resize->width = 1;
1867 
1868  size->height = 5 * resize->height + SETTINGTREE_TOP_OFFSET + SETTINGTREE_BOTTOM_OFFSET;
1869  break;
1870 
1871  case WID_GS_HELP_TEXT: {
1872  static const StringID setting_types[] = {
1873  STR_CONFIG_SETTING_TYPE_CLIENT,
1874  STR_CONFIG_SETTING_TYPE_COMPANY_MENU, STR_CONFIG_SETTING_TYPE_COMPANY_INGAME,
1875  STR_CONFIG_SETTING_TYPE_GAME_MENU, STR_CONFIG_SETTING_TYPE_GAME_INGAME,
1876  };
1877  for (uint i = 0; i < lengthof(setting_types); i++) {
1878  SetDParam(0, setting_types[i]);
1879  size->width = max(size->width, GetStringBoundingBox(STR_CONFIG_SETTING_TYPE).width);
1880  }
1881  size->height = 2 * FONT_HEIGHT_NORMAL + WD_PAR_VSEP_NORMAL +
1882  max(size->height, GetSettingsTree().GetMaxHelpHeight(size->width));
1883  break;
1884  }
1885 
1887  case WID_GS_RESTRICT_TYPE:
1888  size->width = max(GetStringBoundingBox(STR_CONFIG_SETTING_RESTRICT_CATEGORY).width, GetStringBoundingBox(STR_CONFIG_SETTING_RESTRICT_TYPE).width);
1889  break;
1890 
1891  default:
1892  break;
1893  }
1894  }
1895 
1896  virtual void OnPaint()
1897  {
1898  if (this->closing_dropdown) {
1899  this->closing_dropdown = false;
1900  assert(this->valuedropdown_entry != NULL);
1901  this->valuedropdown_entry->SetButtons(0);
1902  this->valuedropdown_entry = NULL;
1903  }
1904 
1905  /* Reserve the correct number of lines for the 'some search results are hidden' notice in the central settings display panel. */
1906  const NWidgetBase *panel = this->GetWidget<NWidgetBase>(WID_GS_OPTIONSPANEL);
1907  StringID warn_str = STR_CONFIG_SETTING_CATEGORY_HIDES - 1 + this->warn_missing;
1908  int new_warn_lines;
1909  if (this->warn_missing == WHR_NONE) {
1910  new_warn_lines = 0;
1911  } else {
1912  SetDParam(0, _game_settings_restrict_dropdown[this->filter.min_cat]);
1913  new_warn_lines = GetStringLineCount(warn_str, panel->current_x);
1914  }
1915  if (this->warn_lines != new_warn_lines) {
1916  this->vscroll->SetCount(this->vscroll->GetCount() - this->warn_lines + new_warn_lines);
1917  this->warn_lines = new_warn_lines;
1918  }
1919 
1920  this->DrawWidgets();
1921 
1922  /* Draw the 'some search results are hidden' notice. */
1923  if (this->warn_missing != WHR_NONE) {
1924  const int left = panel->pos_x;
1925  const int right = left + panel->current_x - 1;
1926  const int top = panel->pos_y + WD_FRAMETEXT_TOP + (SETTING_HEIGHT - FONT_HEIGHT_NORMAL) * this->warn_lines / 2;
1927  SetDParam(0, _game_settings_restrict_dropdown[this->filter.min_cat]);
1928  if (this->warn_lines == 1) {
1929  /* If the warning fits at one line, center it. */
1930  DrawString(left + WD_FRAMETEXT_LEFT, right - WD_FRAMETEXT_RIGHT, top, warn_str, TC_FROMSTRING, SA_HOR_CENTER);
1931  } else {
1932  DrawStringMultiLine(left + WD_FRAMERECT_LEFT, right - WD_FRAMERECT_RIGHT, top, INT32_MAX, warn_str, TC_FROMSTRING, SA_HOR_CENTER);
1933  }
1934  }
1935  }
1936 
1937  virtual void SetStringParameters(int widget) const
1938  {
1939  switch (widget) {
1941  SetDParam(0, _game_settings_restrict_dropdown[this->filter.mode]);
1942  break;
1943 
1944  case WID_GS_TYPE_DROPDOWN:
1945  switch (this->filter.type) {
1946  case ST_GAME: SetDParam(0, _game_mode == GM_MENU ? STR_CONFIG_SETTING_TYPE_DROPDOWN_GAME_MENU : STR_CONFIG_SETTING_TYPE_DROPDOWN_GAME_INGAME); break;
1947  case ST_COMPANY: SetDParam(0, _game_mode == GM_MENU ? STR_CONFIG_SETTING_TYPE_DROPDOWN_COMPANY_MENU : STR_CONFIG_SETTING_TYPE_DROPDOWN_COMPANY_INGAME); break;
1948  case ST_CLIENT: SetDParam(0, STR_CONFIG_SETTING_TYPE_DROPDOWN_CLIENT); break;
1949  default: SetDParam(0, STR_CONFIG_SETTING_TYPE_DROPDOWN_ALL); break;
1950  }
1951  break;
1952  }
1953  }
1954 
1955  DropDownList *BuildDropDownList(int widget) const
1956  {
1957  DropDownList *list = NULL;
1958  switch (widget) {
1960  list = new DropDownList();
1961 
1962  for (int mode = 0; mode != RM_END; mode++) {
1963  /* If we are in adv. settings screen for the new game's settings,
1964  * we don't want to allow comparing with new game's settings. */
1965  bool disabled = mode == RM_CHANGED_AGAINST_NEW && settings_ptr == &_settings_newgame;
1966 
1967  *list->Append() = new DropDownListStringItem(_game_settings_restrict_dropdown[mode], mode, disabled);
1968  }
1969  break;
1970 
1971  case WID_GS_TYPE_DROPDOWN:
1972  list = new DropDownList();
1973  *list->Append() = new DropDownListStringItem(STR_CONFIG_SETTING_TYPE_DROPDOWN_ALL, ST_ALL, false);
1974  *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);
1975  *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);
1976  *list->Append() = new DropDownListStringItem(STR_CONFIG_SETTING_TYPE_DROPDOWN_CLIENT, ST_CLIENT, false);
1977  break;
1978  }
1979  return list;
1980  }
1981 
1982  virtual void DrawWidget(const Rect &r, int widget) const
1983  {
1984  switch (widget) {
1985  case WID_GS_OPTIONSPANEL: {
1986  int top_pos = r.top + SETTINGTREE_TOP_OFFSET + 1 + this->warn_lines * SETTING_HEIGHT;
1987  uint last_row = this->vscroll->GetPosition() + this->vscroll->GetCapacity() - this->warn_lines;
1988  int next_row = GetSettingsTree().Draw(settings_ptr, r.left + SETTINGTREE_LEFT_OFFSET, r.right - SETTINGTREE_RIGHT_OFFSET, top_pos,
1989  this->vscroll->GetPosition(), last_row, this->last_clicked);
1990  if (next_row == 0) DrawString(r.left + SETTINGTREE_LEFT_OFFSET, r.right - SETTINGTREE_RIGHT_OFFSET, top_pos, STR_CONFIG_SETTINGS_NONE);
1991  break;
1992  }
1993 
1994  case WID_GS_HELP_TEXT:
1995  if (this->last_clicked != NULL) {
1996  const SettingDesc *sd = this->last_clicked->setting;
1997 
1998  int y = r.top;
1999  switch (sd->GetType()) {
2000  case ST_COMPANY: SetDParam(0, _game_mode == GM_MENU ? STR_CONFIG_SETTING_TYPE_COMPANY_MENU : STR_CONFIG_SETTING_TYPE_COMPANY_INGAME); break;
2001  case ST_CLIENT: SetDParam(0, STR_CONFIG_SETTING_TYPE_CLIENT); break;
2002  case ST_GAME: SetDParam(0, _game_mode == GM_MENU ? STR_CONFIG_SETTING_TYPE_GAME_MENU : STR_CONFIG_SETTING_TYPE_GAME_INGAME); break;
2003  default: NOT_REACHED();
2004  }
2005  DrawString(r.left, r.right, y, STR_CONFIG_SETTING_TYPE);
2006  y += FONT_HEIGHT_NORMAL;
2007 
2008  int32 default_value = ReadValue(&sd->desc.def, sd->save.conv);
2009  this->last_clicked->SetValueDParams(0, default_value);
2010  DrawString(r.left, r.right, y, STR_CONFIG_SETTING_DEFAULT_VALUE);
2012 
2013  DrawStringMultiLine(r.left, r.right, y, r.bottom, this->last_clicked->GetHelpText(), TC_WHITE);
2014  }
2015  break;
2016 
2017  default:
2018  break;
2019  }
2020  }
2021 
2027  {
2028  if (this->last_clicked != pe) this->SetDirty();
2029  this->last_clicked = pe;
2030  }
2031 
2032  virtual void OnClick(Point pt, int widget, int click_count)
2033  {
2034  switch (widget) {
2035  case WID_GS_EXPAND_ALL:
2036  this->manually_changed_folding = true;
2038  this->InvalidateData();
2039  break;
2040 
2041  case WID_GS_COLLAPSE_ALL:
2042  this->manually_changed_folding = true;
2044  this->InvalidateData();
2045  break;
2046 
2047  case WID_GS_RESTRICT_DROPDOWN: {
2048  DropDownList *list = this->BuildDropDownList(widget);
2049  if (list != NULL) {
2050  ShowDropDownList(this, list, this->filter.mode, widget);
2051  }
2052  break;
2053  }
2054 
2055  case WID_GS_TYPE_DROPDOWN: {
2056  DropDownList *list = this->BuildDropDownList(widget);
2057  if (list != NULL) {
2058  ShowDropDownList(this, list, this->filter.type, widget);
2059  }
2060  break;
2061  }
2062  }
2063 
2064  if (widget != WID_GS_OPTIONSPANEL) return;
2065 
2066  uint btn = this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_GS_OPTIONSPANEL, SETTINGTREE_TOP_OFFSET);
2067  if (btn == INT_MAX || (int)btn < this->warn_lines) return;
2068  btn -= this->warn_lines;
2069 
2070  uint cur_row = 0;
2071  BaseSettingEntry *clicked_entry = GetSettingsTree().FindEntry(btn, &cur_row);
2072 
2073  if (clicked_entry == NULL) return; // Clicked below the last setting of the page
2074 
2075  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
2076  if (x < 0) return; // Clicked left of the entry
2077 
2078  SettingsPage *clicked_page = dynamic_cast<SettingsPage*>(clicked_entry);
2079  if (clicked_page != NULL) {
2080  this->SetDisplayedHelpText(NULL);
2081  clicked_page->folded = !clicked_page->folded; // Flip 'folded'-ness of the sub-page
2082 
2083  this->manually_changed_folding = true;
2084 
2085  this->InvalidateData();
2086  return;
2087  }
2088 
2089  SettingEntry *pe = dynamic_cast<SettingEntry*>(clicked_entry);
2090  assert(pe != NULL);
2091  const SettingDesc *sd = pe->setting;
2092 
2093  /* return if action is only active in network, or only settable by server */
2094  if (!sd->IsEditable()) {
2095  this->SetDisplayedHelpText(pe);
2096  return;
2097  }
2098 
2099  const void *var = ResolveVariableAddress(settings_ptr, sd);
2100  int32 value = (int32)ReadValue(var, sd->save.conv);
2101 
2102  /* clicked on the icon on the left side. Either scroller, bool on/off or dropdown */
2103  if (x < SETTING_BUTTON_WIDTH && (sd->desc.flags & SGF_MULTISTRING)) {
2104  const SettingDescBase *sdb = &sd->desc;
2105  this->SetDisplayedHelpText(pe);
2106 
2107  if (this->valuedropdown_entry == pe) {
2108  /* unclick the dropdown */
2109  HideDropDownMenu(this);
2110  this->closing_dropdown = false;
2111  this->valuedropdown_entry->SetButtons(0);
2112  this->valuedropdown_entry = NULL;
2113  } else {
2114  if (this->valuedropdown_entry != NULL) this->valuedropdown_entry->SetButtons(0);
2115  this->closing_dropdown = false;
2116 
2117  const NWidgetBase *wid = this->GetWidget<NWidgetBase>(WID_GS_OPTIONSPANEL);
2118  int rel_y = (pt.y - (int)wid->pos_y - SETTINGTREE_TOP_OFFSET) % wid->resize_y;
2119 
2120  Rect wi_rect;
2121  wi_rect.left = pt.x - (_current_text_dir == TD_RTL ? SETTING_BUTTON_WIDTH - 1 - x : x);
2122  wi_rect.right = wi_rect.left + SETTING_BUTTON_WIDTH - 1;
2123  wi_rect.top = pt.y - rel_y + (SETTING_HEIGHT - SETTING_BUTTON_HEIGHT) / 2;
2124  wi_rect.bottom = wi_rect.top + SETTING_BUTTON_HEIGHT - 1;
2125 
2126  /* For dropdowns we also have to check the y position thoroughly, the mouse may not above the just opening dropdown */
2127  if (pt.y >= wi_rect.top && pt.y <= wi_rect.bottom) {
2128  this->valuedropdown_entry = pe;
2129  this->valuedropdown_entry->SetButtons(SEF_LEFT_DEPRESSED);
2130 
2131  DropDownList *list = new DropDownList();
2132  for (int i = sdb->min; i <= (int)sdb->max; i++) {
2133  *list->Append() = new DropDownListStringItem(sdb->str_val + i - sdb->min, i, false);
2134  }
2135 
2136  ShowDropDownListAt(this, list, value, -1, wi_rect, COLOUR_ORANGE, true);
2137  }
2138  }
2139  this->SetDirty();
2140  } else if (x < SETTING_BUTTON_WIDTH) {
2141  this->SetDisplayedHelpText(pe);
2142  const SettingDescBase *sdb = &sd->desc;
2143  int32 oldvalue = value;
2144 
2145  switch (sdb->cmd) {
2146  case SDT_BOOLX: value ^= 1; break;
2147  case SDT_ONEOFMANY:
2148  case SDT_NUMX: {
2149  /* Add a dynamic step-size to the scroller. In a maximum of
2150  * 50-steps you should be able to get from min to max,
2151  * unless specified otherwise in the 'interval' variable
2152  * of the current setting. */
2153  uint32 step = (sdb->interval == 0) ? ((sdb->max - sdb->min) / 50) : sdb->interval;
2154  if (step == 0) step = 1;
2155 
2156  /* don't allow too fast scrolling */
2157  if ((this->flags & WF_TIMEOUT) && this->timeout_timer > 1) {
2158  _left_button_clicked = false;
2159  return;
2160  }
2161 
2162  /* Increase or decrease the value and clamp it to extremes */
2163  if (x >= SETTING_BUTTON_WIDTH / 2) {
2164  value += step;
2165  if (sdb->min < 0) {
2166  assert((int32)sdb->max >= 0);
2167  if (value > (int32)sdb->max) value = (int32)sdb->max;
2168  } else {
2169  if ((uint32)value > sdb->max) value = (int32)sdb->max;
2170  }
2171  if (value < sdb->min) value = sdb->min; // skip between "disabled" and minimum
2172  } else {
2173  value -= step;
2174  if (value < sdb->min) value = (sdb->flags & SGF_0ISDISABLED) ? 0 : sdb->min;
2175  }
2176 
2177  /* Set up scroller timeout for numeric values */
2178  if (value != oldvalue) {
2179  if (this->clicked_entry != NULL) { // Release previous buttons if any
2180  this->clicked_entry->SetButtons(0);
2181  }
2182  this->clicked_entry = pe;
2183  this->clicked_entry->SetButtons((x >= SETTING_BUTTON_WIDTH / 2) != (_current_text_dir == TD_RTL) ? SEF_RIGHT_DEPRESSED : SEF_LEFT_DEPRESSED);
2184  this->SetTimeout();
2185  _left_button_clicked = false;
2186  }
2187  break;
2188  }
2189 
2190  default: NOT_REACHED();
2191  }
2192 
2193  if (value != oldvalue) {
2194  if ((sd->desc.flags & SGF_PER_COMPANY) != 0) {
2195  SetCompanySetting(pe->index, value);
2196  } else {
2197  SetSettingValue(pe->index, value);
2198  }
2199  this->SetDirty();
2200  }
2201  } else {
2202  /* Only open editbox if clicked for the second time, and only for types where it is sensible for. */
2203  if (this->last_clicked == pe && sd->desc.cmd != SDT_BOOLX && !(sd->desc.flags & SGF_MULTISTRING)) {
2204  /* Show the correct currency-translated value */
2205  if (sd->desc.flags & SGF_CURRENCY) value *= _currency->rate;
2206 
2207  this->valuewindow_entry = pe;
2208  SetDParam(0, value);
2209  ShowQueryString(STR_JUST_INT, STR_CONFIG_SETTING_QUERY_CAPTION, 10, this, CS_NUMERAL, QSF_ENABLE_DEFAULT);
2210  }
2211  this->SetDisplayedHelpText(pe);
2212  }
2213  }
2214 
2215  virtual void OnTimeout()
2216  {
2217  if (this->clicked_entry != NULL) { // On timeout, release any depressed buttons
2218  this->clicked_entry->SetButtons(0);
2219  this->clicked_entry = NULL;
2220  this->SetDirty();
2221  }
2222  }
2223 
2224  virtual void OnQueryTextFinished(char *str)
2225  {
2226  /* The user pressed cancel */
2227  if (str == NULL) return;
2228 
2229  assert(this->valuewindow_entry != NULL);
2230  const SettingDesc *sd = this->valuewindow_entry->setting;
2231 
2232  int32 value;
2233  if (!StrEmpty(str)) {
2234  value = atoi(str);
2235 
2236  /* Save the correct currency-translated value */
2237  if (sd->desc.flags & SGF_CURRENCY) value /= _currency->rate;
2238  } else {
2239  value = (int32)(size_t)sd->desc.def;
2240  }
2241 
2242  if ((sd->desc.flags & SGF_PER_COMPANY) != 0) {
2243  SetCompanySetting(this->valuewindow_entry->index, value);
2244  } else {
2245  SetSettingValue(this->valuewindow_entry->index, value);
2246  }
2247  this->SetDirty();
2248  }
2249 
2250  virtual void OnDropdownSelect(int widget, int index)
2251  {
2252  switch (widget) {
2254  this->filter.mode = (RestrictionMode)index;
2255  if (this->filter.mode == RM_CHANGED_AGAINST_DEFAULT ||
2256  this->filter.mode == RM_CHANGED_AGAINST_NEW) {
2257 
2258  if (!this->manually_changed_folding) {
2259  /* Expand all when selecting 'changes'. Update the filter state first, in case it becomes less restrictive in some cases. */
2260  GetSettingsTree().UpdateFilterState(this->filter, false);
2262  }
2263  } else {
2264  /* Non-'changes' filter. Save as default. */
2266  }
2267  this->InvalidateData();
2268  break;
2269 
2270  case WID_GS_TYPE_DROPDOWN:
2271  this->filter.type = (SettingType)index;
2272  this->InvalidateData();
2273  break;
2274 
2275  default:
2276  if (widget < 0) {
2277  /* Deal with drop down boxes on the panel. */
2278  assert(this->valuedropdown_entry != NULL);
2279  const SettingDesc *sd = this->valuedropdown_entry->setting;
2280  assert(sd->desc.flags & SGF_MULTISTRING);
2281 
2282  if ((sd->desc.flags & SGF_PER_COMPANY) != 0) {
2283  SetCompanySetting(this->valuedropdown_entry->index, index);
2284  } else {
2285  SetSettingValue(this->valuedropdown_entry->index, index);
2286  }
2287 
2288  this->SetDirty();
2289  }
2290  break;
2291  }
2292  }
2293 
2294  virtual void OnDropdownClose(Point pt, int widget, int index, bool instant_close)
2295  {
2296  if (widget >= 0) {
2297  /* Normally the default implementation of OnDropdownClose() takes care of
2298  * a few things. We want that behaviour here too, but only for
2299  * "normal" dropdown boxes. The special dropdown boxes added for every
2300  * setting that needs one can't have this call. */
2301  Window::OnDropdownClose(pt, widget, index, instant_close);
2302  } else {
2303  /* We cannot raise the dropdown button just yet. OnClick needs some hint, whether
2304  * the same dropdown button was clicked again, and then not open the dropdown again.
2305  * So, we only remember that it was closed, and process it on the next OnPaint, which is
2306  * after OnClick. */
2307  assert(this->valuedropdown_entry != NULL);
2308  this->closing_dropdown = true;
2309  this->SetDirty();
2310  }
2311  }
2312 
2313  virtual void OnInvalidateData(int data = 0, bool gui_scope = true)
2314  {
2315  if (!gui_scope) return;
2316 
2317  /* Update which settings are to be visible. */
2318  RestrictionMode min_level = (this->filter.mode <= RM_ALL) ? this->filter.mode : RM_BASIC;
2319  this->filter.min_cat = min_level;
2320  this->filter.type_hides = false;
2321  GetSettingsTree().UpdateFilterState(this->filter, false);
2322 
2323  if (this->filter.string.IsEmpty()) {
2324  this->warn_missing = WHR_NONE;
2325  } else if (min_level < this->filter.min_cat) {
2326  this->warn_missing = this->filter.type_hides ? WHR_CATEGORY_TYPE : WHR_CATEGORY;
2327  } else {
2328  this->warn_missing = this->filter.type_hides ? WHR_TYPE : WHR_NONE;
2329  }
2330  this->vscroll->SetCount(GetSettingsTree().Length() + this->warn_lines);
2331 
2332  if (this->last_clicked != NULL && !GetSettingsTree().IsVisible(this->last_clicked)) {
2333  this->SetDisplayedHelpText(NULL);
2334  }
2335 
2336  bool all_folded = true;
2337  bool all_unfolded = true;
2338  GetSettingsTree().GetFoldingState(all_folded, all_unfolded);
2339  this->SetWidgetDisabledState(WID_GS_EXPAND_ALL, all_unfolded);
2340  this->SetWidgetDisabledState(WID_GS_COLLAPSE_ALL, all_folded);
2341  }
2342 
2343  virtual void OnEditboxChanged(int wid)
2344  {
2345  if (wid == WID_GS_FILTER) {
2346  this->filter.string.SetFilterTerm(this->filter_editbox.text.buf);
2347  if (!this->filter.string.IsEmpty() && !this->manually_changed_folding) {
2348  /* User never expanded/collapsed single pages and entered a filter term.
2349  * Expand everything, to save weird expand clicks, */
2351  }
2352  this->InvalidateData();
2353  }
2354  }
2355 
2356  virtual void OnResize()
2357  {
2358  this->vscroll->SetCapacityFromWidget(this, WID_GS_OPTIONSPANEL, SETTINGTREE_TOP_OFFSET + SETTINGTREE_BOTTOM_OFFSET);
2359  }
2360 };
2361 
2363 
2364 static const NWidgetPart _nested_settings_selection_widgets[] = {
2366  NWidget(WWT_CLOSEBOX, COLOUR_MAUVE),
2367  NWidget(WWT_CAPTION, COLOUR_MAUVE), SetDataTip(STR_CONFIG_SETTING_TREE_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
2368  NWidget(WWT_DEFSIZEBOX, COLOUR_MAUVE),
2369  EndContainer(),
2370  NWidget(WWT_PANEL, COLOUR_MAUVE),
2373  NWidget(WWT_TEXT, COLOUR_MAUVE, WID_GS_RESTRICT_CATEGORY), SetDataTip(STR_CONFIG_SETTING_RESTRICT_CATEGORY, STR_NULL),
2374  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),
2375  EndContainer(),
2377  NWidget(WWT_TEXT, COLOUR_MAUVE, WID_GS_RESTRICT_TYPE), SetDataTip(STR_CONFIG_SETTING_RESTRICT_TYPE, STR_NULL),
2378  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),
2379  EndContainer(),
2380  EndContainer(),
2383  NWidget(WWT_TEXT, COLOUR_MAUVE), SetFill(0, 1), SetDataTip(STR_CONFIG_SETTING_FILTER_TITLE, STR_NULL),
2384  NWidget(WWT_EDITBOX, COLOUR_MAUVE, WID_GS_FILTER), SetFill(1, 0), SetMinimalSize(50, 12), SetResize(1, 0),
2385  SetDataTip(STR_LIST_FILTER_OSKTITLE, STR_LIST_FILTER_TOOLTIP),
2386  EndContainer(),
2387  EndContainer(),
2390  NWidget(NWID_VSCROLLBAR, COLOUR_MAUVE, WID_GS_SCROLLBAR),
2391  EndContainer(),
2392  NWidget(WWT_PANEL, COLOUR_MAUVE), SetMinimalSize(400, 40),
2393  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_GS_HELP_TEXT), SetMinimalSize(300, 25), SetFill(1, 1), SetResize(1, 0),
2395  EndContainer(),
2397  NWidget(WWT_PUSHTXTBTN, COLOUR_MAUVE, WID_GS_EXPAND_ALL), SetDataTip(STR_CONFIG_SETTING_EXPAND_ALL, STR_NULL),
2398  NWidget(WWT_PUSHTXTBTN, COLOUR_MAUVE, WID_GS_COLLAPSE_ALL), SetDataTip(STR_CONFIG_SETTING_COLLAPSE_ALL, STR_NULL),
2399  NWidget(WWT_PANEL, COLOUR_MAUVE), SetFill(1, 0), SetResize(1, 0),
2400  EndContainer(),
2401  NWidget(WWT_RESIZEBOX, COLOUR_MAUVE),
2402  EndContainer(),
2403 };
2404 
2405 static WindowDesc _settings_selection_desc(
2406  WDP_CENTER, "settings", 510, 450,
2408  0,
2409  _nested_settings_selection_widgets, lengthof(_nested_settings_selection_widgets)
2410 );
2411 
2414 {
2416  new GameSettingsWindow(&_settings_selection_desc);
2417 }
2418 
2419 
2429 void DrawArrowButtons(int x, int y, Colours button_colour, byte state, bool clickable_left, bool clickable_right)
2430 {
2431  int colour = _colour_gradient[button_colour][2];
2432  Dimension dim = NWidgetScrollbar::GetHorizontalDimension();
2433 
2434  DrawFrameRect(x, y, x + dim.width - 1, y + dim.height - 1, button_colour, (state == 1) ? FR_LOWERED : FR_NONE);
2435  DrawFrameRect(x + dim.width, y, x + dim.width + dim.width - 1, y + dim.height - 1, button_colour, (state == 2) ? FR_LOWERED : FR_NONE);
2436  DrawSprite(SPR_ARROW_LEFT, PAL_NONE, x + WD_IMGBTN_LEFT, y + WD_IMGBTN_TOP);
2437  DrawSprite(SPR_ARROW_RIGHT, PAL_NONE, x + WD_IMGBTN_LEFT + dim.width, y + WD_IMGBTN_TOP);
2438 
2439  /* Grey out the buttons that aren't clickable */
2440  bool rtl = _current_text_dir == TD_RTL;
2441  if (rtl ? !clickable_right : !clickable_left) {
2442  GfxFillRect(x + 1, y, x + dim.width - 1, y + dim.height - 2, colour, FILLRECT_CHECKER);
2443  }
2444  if (rtl ? !clickable_left : !clickable_right) {
2445  GfxFillRect(x + dim.width + 1, y, x + dim.width + dim.width - 1, y + dim.height - 2, colour, FILLRECT_CHECKER);
2446  }
2447 }
2448 
2457 void DrawDropDownButton(int x, int y, Colours button_colour, bool state, bool clickable)
2458 {
2459  int colour = _colour_gradient[button_colour][2];
2460 
2461  DrawFrameRect(x, y, x + SETTING_BUTTON_WIDTH - 1, y + SETTING_BUTTON_HEIGHT - 1, button_colour, state ? FR_LOWERED : FR_NONE);
2462  DrawSprite(SPR_ARROW_DOWN, PAL_NONE, x + (SETTING_BUTTON_WIDTH - NWidgetScrollbar::GetVerticalDimension().width) / 2 + state, y + 2 + state);
2463 
2464  if (!clickable) {
2465  GfxFillRect(x + 1, y, x + SETTING_BUTTON_WIDTH - 1, y + SETTING_BUTTON_HEIGHT - 2, colour, FILLRECT_CHECKER);
2466  }
2467 }
2468 
2476 void DrawBoolButton(int x, int y, bool state, bool clickable)
2477 {
2478  static const Colours _bool_ctabs[2][2] = {{COLOUR_CREAM, COLOUR_RED}, {COLOUR_DARK_GREEN, COLOUR_GREEN}};
2479  DrawFrameRect(x, y, x + SETTING_BUTTON_WIDTH - 1, y + SETTING_BUTTON_HEIGHT - 1, _bool_ctabs[state][clickable], state ? FR_LOWERED : FR_NONE);
2480 }
2481 
2483  int query_widget;
2484 
2485  CustomCurrencyWindow(WindowDesc *desc) : Window(desc)
2486  {
2487  this->InitNested();
2488 
2489  SetButtonState();
2490  }
2491 
2492  void SetButtonState()
2493  {
2494  this->SetWidgetDisabledState(WID_CC_RATE_DOWN, _custom_currency.rate == 1);
2495  this->SetWidgetDisabledState(WID_CC_RATE_UP, _custom_currency.rate == UINT16_MAX);
2496  this->SetWidgetDisabledState(WID_CC_YEAR_DOWN, _custom_currency.to_euro == CF_NOEURO);
2497  this->SetWidgetDisabledState(WID_CC_YEAR_UP, _custom_currency.to_euro == MAX_YEAR);
2498  }
2499 
2500  virtual void SetStringParameters(int widget) const
2501  {
2502  switch (widget) {
2503  case WID_CC_RATE: SetDParam(0, 1); SetDParam(1, 1); break;
2504  case WID_CC_SEPARATOR: SetDParamStr(0, _custom_currency.separator); break;
2505  case WID_CC_PREFIX: SetDParamStr(0, _custom_currency.prefix); break;
2506  case WID_CC_SUFFIX: SetDParamStr(0, _custom_currency.suffix); break;
2507  case WID_CC_YEAR:
2508  SetDParam(0, (_custom_currency.to_euro != CF_NOEURO) ? STR_CURRENCY_SWITCH_TO_EURO : STR_CURRENCY_SWITCH_TO_EURO_NEVER);
2509  SetDParam(1, _custom_currency.to_euro);
2510  break;
2511 
2512  case WID_CC_PREVIEW:
2513  SetDParam(0, 10000);
2514  break;
2515  }
2516  }
2517 
2518  virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
2519  {
2520  switch (widget) {
2521  /* Set the appropriate width for the edit 'buttons' */
2522  case WID_CC_SEPARATOR_EDIT:
2523  case WID_CC_PREFIX_EDIT:
2524  case WID_CC_SUFFIX_EDIT:
2525  size->width = this->GetWidget<NWidgetBase>(WID_CC_RATE_DOWN)->smallest_x + this->GetWidget<NWidgetBase>(WID_CC_RATE_UP)->smallest_x;
2526  break;
2527 
2528  /* Make sure the window is wide enough for the widest exchange rate */
2529  case WID_CC_RATE:
2530  SetDParam(0, 1);
2531  SetDParam(1, INT32_MAX);
2532  *size = GetStringBoundingBox(STR_CURRENCY_EXCHANGE_RATE);
2533  break;
2534  }
2535  }
2536 
2537  virtual void OnClick(Point pt, int widget, int click_count)
2538  {
2539  int line = 0;
2540  int len = 0;
2541  StringID str = 0;
2542  CharSetFilter afilter = CS_ALPHANUMERAL;
2543 
2544  switch (widget) {
2545  case WID_CC_RATE_DOWN:
2546  if (_custom_currency.rate > 1) _custom_currency.rate--;
2547  if (_custom_currency.rate == 1) this->DisableWidget(WID_CC_RATE_DOWN);
2549  break;
2550 
2551  case WID_CC_RATE_UP:
2552  if (_custom_currency.rate < UINT16_MAX) _custom_currency.rate++;
2553  if (_custom_currency.rate == UINT16_MAX) this->DisableWidget(WID_CC_RATE_UP);
2555  break;
2556 
2557  case WID_CC_RATE:
2558  SetDParam(0, _custom_currency.rate);
2559  str = STR_JUST_INT;
2560  len = 5;
2561  line = WID_CC_RATE;
2562  afilter = CS_NUMERAL;
2563  break;
2564 
2565  case WID_CC_SEPARATOR_EDIT:
2566  case WID_CC_SEPARATOR:
2567  SetDParamStr(0, _custom_currency.separator);
2568  str = STR_JUST_RAW_STRING;
2569  len = 1;
2570  line = WID_CC_SEPARATOR;
2571  break;
2572 
2573  case WID_CC_PREFIX_EDIT:
2574  case WID_CC_PREFIX:
2575  SetDParamStr(0, _custom_currency.prefix);
2576  str = STR_JUST_RAW_STRING;
2577  len = 12;
2578  line = WID_CC_PREFIX;
2579  break;
2580 
2581  case WID_CC_SUFFIX_EDIT:
2582  case WID_CC_SUFFIX:
2583  SetDParamStr(0, _custom_currency.suffix);
2584  str = STR_JUST_RAW_STRING;
2585  len = 12;
2586  line = WID_CC_SUFFIX;
2587  break;
2588 
2589  case WID_CC_YEAR_DOWN:
2590  _custom_currency.to_euro = (_custom_currency.to_euro <= 2000) ? CF_NOEURO : _custom_currency.to_euro - 1;
2591  if (_custom_currency.to_euro == CF_NOEURO) this->DisableWidget(WID_CC_YEAR_DOWN);
2593  break;
2594 
2595  case WID_CC_YEAR_UP:
2596  _custom_currency.to_euro = Clamp(_custom_currency.to_euro + 1, 2000, MAX_YEAR);
2597  if (_custom_currency.to_euro == MAX_YEAR) this->DisableWidget(WID_CC_YEAR_UP);
2599  break;
2600 
2601  case WID_CC_YEAR:
2602  SetDParam(0, _custom_currency.to_euro);
2603  str = STR_JUST_INT;
2604  len = 7;
2605  line = WID_CC_YEAR;
2606  afilter = CS_NUMERAL;
2607  break;
2608  }
2609 
2610  if (len != 0) {
2611  this->query_widget = line;
2612  ShowQueryString(str, STR_CURRENCY_CHANGE_PARAMETER, len + 1, this, afilter, QSF_NONE);
2613  }
2614 
2615  this->SetTimeout();
2616  this->SetDirty();
2617  }
2618 
2619  virtual void OnQueryTextFinished(char *str)
2620  {
2621  if (str == NULL) return;
2622 
2623  switch (this->query_widget) {
2624  case WID_CC_RATE:
2625  _custom_currency.rate = Clamp(atoi(str), 1, UINT16_MAX);
2626  break;
2627 
2628  case WID_CC_SEPARATOR: // Thousands separator
2629  strecpy(_custom_currency.separator, str, lastof(_custom_currency.separator));
2630  break;
2631 
2632  case WID_CC_PREFIX:
2633  strecpy(_custom_currency.prefix, str, lastof(_custom_currency.prefix));
2634  break;
2635 
2636  case WID_CC_SUFFIX:
2637  strecpy(_custom_currency.suffix, str, lastof(_custom_currency.suffix));
2638  break;
2639 
2640  case WID_CC_YEAR: { // Year to switch to euro
2641  int val = atoi(str);
2642 
2643  _custom_currency.to_euro = (val < 2000 ? CF_NOEURO : min(val, MAX_YEAR));
2644  break;
2645  }
2646  }
2648  SetButtonState();
2649  }
2650 
2651  virtual void OnTimeout()
2652  {
2653  this->SetDirty();
2654  }
2655 };
2656 
2657 static const NWidgetPart _nested_cust_currency_widgets[] = {
2659  NWidget(WWT_CLOSEBOX, COLOUR_GREY),
2660  NWidget(WWT_CAPTION, COLOUR_GREY), SetDataTip(STR_CURRENCY_WINDOW, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
2661  EndContainer(),
2662  NWidget(WWT_PANEL, COLOUR_GREY),
2664  NWidget(NWID_HORIZONTAL), SetPIP(10, 0, 5),
2665  NWidget(WWT_PUSHARROWBTN, COLOUR_YELLOW, WID_CC_RATE_DOWN), SetDataTip(AWV_DECREASE, STR_CURRENCY_DECREASE_EXCHANGE_RATE_TOOLTIP),
2666  NWidget(WWT_PUSHARROWBTN, COLOUR_YELLOW, WID_CC_RATE_UP), SetDataTip(AWV_INCREASE, STR_CURRENCY_INCREASE_EXCHANGE_RATE_TOOLTIP),
2668  NWidget(WWT_TEXT, COLOUR_BLUE, WID_CC_RATE), SetDataTip(STR_CURRENCY_EXCHANGE_RATE, STR_CURRENCY_SET_EXCHANGE_RATE_TOOLTIP), SetFill(1, 0),
2669  EndContainer(),
2670  NWidget(NWID_HORIZONTAL), SetPIP(10, 0, 5),
2671  NWidget(WWT_PUSHBTN, COLOUR_DARK_BLUE, WID_CC_SEPARATOR_EDIT), SetDataTip(0x0, STR_CURRENCY_SET_CUSTOM_CURRENCY_SEPARATOR_TOOLTIP), SetFill(0, 1),
2673  NWidget(WWT_TEXT, COLOUR_BLUE, WID_CC_SEPARATOR), SetDataTip(STR_CURRENCY_SEPARATOR, STR_CURRENCY_SET_CUSTOM_CURRENCY_SEPARATOR_TOOLTIP), SetFill(1, 0),
2674  EndContainer(),
2675  NWidget(NWID_HORIZONTAL), SetPIP(10, 0, 5),
2676  NWidget(WWT_PUSHBTN, COLOUR_DARK_BLUE, WID_CC_PREFIX_EDIT), SetDataTip(0x0, STR_CURRENCY_SET_CUSTOM_CURRENCY_PREFIX_TOOLTIP), SetFill(0, 1),
2678  NWidget(WWT_TEXT, COLOUR_BLUE, WID_CC_PREFIX), SetDataTip(STR_CURRENCY_PREFIX, STR_CURRENCY_SET_CUSTOM_CURRENCY_PREFIX_TOOLTIP), SetFill(1, 0),
2679  EndContainer(),
2680  NWidget(NWID_HORIZONTAL), SetPIP(10, 0, 5),
2681  NWidget(WWT_PUSHBTN, COLOUR_DARK_BLUE, WID_CC_SUFFIX_EDIT), SetDataTip(0x0, STR_CURRENCY_SET_CUSTOM_CURRENCY_SUFFIX_TOOLTIP), SetFill(0, 1),
2683  NWidget(WWT_TEXT, COLOUR_BLUE, WID_CC_SUFFIX), SetDataTip(STR_CURRENCY_SUFFIX, STR_CURRENCY_SET_CUSTOM_CURRENCY_SUFFIX_TOOLTIP), SetFill(1, 0),
2684  EndContainer(),
2685  NWidget(NWID_HORIZONTAL), SetPIP(10, 0, 5),
2686  NWidget(WWT_PUSHARROWBTN, COLOUR_YELLOW, WID_CC_YEAR_DOWN), SetDataTip(AWV_DECREASE, STR_CURRENCY_DECREASE_CUSTOM_CURRENCY_TO_EURO_TOOLTIP),
2687  NWidget(WWT_PUSHARROWBTN, COLOUR_YELLOW, WID_CC_YEAR_UP), SetDataTip(AWV_INCREASE, STR_CURRENCY_INCREASE_CUSTOM_CURRENCY_TO_EURO_TOOLTIP),
2689  NWidget(WWT_TEXT, COLOUR_BLUE, WID_CC_YEAR), SetDataTip(STR_JUST_STRING, STR_CURRENCY_SET_CUSTOM_CURRENCY_TO_EURO_TOOLTIP), SetFill(1, 0),
2690  EndContainer(),
2691  EndContainer(),
2692  NWidget(WWT_LABEL, COLOUR_BLUE, WID_CC_PREVIEW),
2693  SetDataTip(STR_CURRENCY_PREVIEW, STR_CURRENCY_CUSTOM_CURRENCY_PREVIEW_TOOLTIP), SetPadding(15, 1, 18, 2),
2694  EndContainer(),
2695 };
2696 
2697 static WindowDesc _cust_currency_desc(
2698  WDP_CENTER, NULL, 0, 0,
2700  0,
2701  _nested_cust_currency_widgets, lengthof(_nested_cust_currency_widgets)
2702 );
2703 
2705 static void ShowCustCurrency()
2706 {
2708  new CustomCurrencyWindow(&_cust_currency_desc);
2709 }
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:2101
bool _networking
are we in networking mode?
Definition: network.cpp:56
const void * def
default value given when none is present
virtual bool IsVisible(const BaseSettingEntry *item) const
Check whether an entry is visible and not folded or filtered away.
bool IsFiltered() const
Check whether an entry is hidden due to filters.
Horizontally center the text.
Definition: gfx_func.h:99
ResizeInfo resize
Resize information.
Definition: window_gui.h:324
static NWidgetPart SetResize(int16 dx, int16 dy)
Widget part function for setting the resize step.
Definition: widget_type.h:930
Window(WindowDesc *desc)
Empty constructor, initialization has been moved to InitNested() called from the constructor of the d...
Definition: window.cpp:1851
uint Draw(GameSettings *settings_ptr, int left, int right, int y, uint first_row, uint max_row, BaseSettingEntry *selected, uint cur_row=0, uint parent_last=0) const
Draw a row in the settings panel.
void GfxFillRect(int left, int top, int right, int bottom, int colour, FillRectMode mode)
Applies a certain FillRectMode-operation to a rectangle [left, right] x [top, bottom] on the screen...
Definition: gfx.cpp:113
Rate of currency.
void SetWidgetDisabledState(byte widget_index, bool disab_stat)
Sets the enabled/disabled status of a widget.
Definition: window_gui.h:394
void SetWindowDirty(WindowClass cls, WindowNumber number)
Mark window as dirty (in need of repainting)
Definition: window.cpp:3201
int warn_lines
Number of lines used for warning about missing search results.
void SetWidgetLoweredState(byte widget_index, bool lowered_stat)
Sets the lowered/raised status of a widget.
Definition: window_gui.h:455
uint GetMaxHelpHeight(int maxw)
Get the biggest height of the help texts, if the width is at least maxw.
void SetTimeout()
Set the timeout flag of the window and initiate the timer.
Definition: window_gui.h:368
Current suffix.
this setting can be different for each company (saved in company struct)
High level window description.
Definition: window_gui.h:168
Custom currency.
Definition: currency.h:58
WindowFlags flags
Window flags.
Definition: window_gui.h:312
int left
x position of left edge of the window
Definition: window_gui.h:319
All settings together for the game.
void DrawWidgets() const
Paint all widgets of a window.
Definition: widget.cpp:604
void ChangeMusicSet(int index)
Change the configured music set and reset playback.
Definition: music_gui.cpp:435
static Titem * Get(size_t index)
Returns Titem with given index.
Definition: pool_type.hpp:246
Switch to game intro menu.
Definition: openttd.h:32
virtual void UnFoldAll()
Recursively open all (filtered) folds of sub-pages.
virtual void OnClick(Point pt, int widget, int click_count)
A click with the left mouse button has been made on the window.
SettingsPage(StringID title)
Constructor for a sub-page in the &#39;advanced settings&#39; window.
Centered label.
Definition: widget_type.h:57
Scrollbar data structure.
Definition: widget_type.h:589
CurrencySpec _currency_specs[CURRENCY_END]
Array of currencies used by the system.
Definition: currency.cpp:70
Functions to handle different currencies.
virtual void Init(byte level=0)
Initialization of a setting entry.
int GetNumInvalid() const
Get the number of invalid files.
Data structure describing a single setting in a tab.
Of a numeric setting entry, the right button is depressed.
Normal amount of vertical space between two paragraphs of text.
Definition: window_gui.h:139
static T SetBit(T &x, const uint8 y)
Set a bit in a variable.
textfile; Window numbers:
Definition: window_type.h:182
Horizontal container.
Definition: widget_type.h:75
void ResetState()
Reset the matching state to process a new item.
void UnFoldAll()
Recursively open all folds of sub-pages.
void SetMediaSet(int index)
Set the base media set.
byte _colour_gradient[COLOUR_END][8]
All 16 colour gradients 8 colours per gradient from darkest (0) to lightest (7)
Definition: gfx.cpp:53
Arrow to the right or in case of RTL to the left.
Definition: widget_type.h:38
Arrow to the left or in case of RTL to the right.
Definition: widget_type.h:37
virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
Update size and resize step of a widget in the window.
Info about missing files etc.
SettingGuiFlag flags
handles how a setting would show up in the GUI (text/currency, etc.)
Open base SFX readme, changelog (+1) or license (+2).
Open base music readme, changelog (+1) or license (+2).
bool GetState() const
Get the matching state of the current item.
void ShowQueryString(StringID str, StringID caption, uint maxsize, Window *parent, CharSetFilter afilter, QueryStringFlags flags)
Show a query popup window with a textbox in it.
Definition: misc_gui.cpp:1064
Use to select a base music set.
Generic functions for replacing base data (graphics, sounds).
fluid_settings_t * settings
FluidSynth settings handle.
Definition: fluidsynth.cpp:22
Show only settings which are different compared to the user&#39;s new game setting values.
Up button.
#define SETBITS(x, y)
Sets several bits in a variable.
const LanguageMetadata * _current_language
The currently loaded language.
Definition: strings.cpp:50
Current separator.
bool closing_dropdown
True, if the dropdown list is currently closing.
static Dimension _circle_size
Dimension of the circle +/- icon. This is here as not all users are within the class of the settings ...
Separator edit button.
the number represents money, so when reading value multiply by exchange rate
DropDownList * BuildDropDownList(int widget, int *selected_index) const
Build the dropdown list for a specific widget.
Panel widget containing the option lists.
a textbox for typing
Definition: widget_type.h:71
Resize box (normally at bottom-right of a window)
Definition: widget_type.h:68
static const int ACTION_CLEAR
Clear editbox.
NewGRF changelog.
Definition: textfile_type.h:20
Filter for settings list.
int top
y position of top edge of the window
Definition: window_gui.h:320
Header of Action 0F "universal holder" structure and functions.
Type setting filtered matches away.
int64 ReadValue(const void *ptr, VarType conv)
Return a signed-long version of the value of a setting.
Definition: saveload.cpp:752
const T * Begin() const
Get the pointer to the first item (const)
virtual void OnDropdownClose(Point pt, int widget, int index, bool instant_close)
A dropdown window associated to this window has been closed.
WarnHiddenResult
Warnings about hidden search results.
void SetButtons(byte new_val)
Set the button-depressed flags (SEF_LEFT_DEPRESSED and SEF_RIGHT_DEPRESSED) to a specified value...
WarnHiddenResult warn_missing
Whether and how to warn about missing search results.
Normal push-button (no toggle button) with custom drawing.
Definition: widget_type.h:103
int GetStringHeight(const char *str, int maxw, FontSize fontsize)
Calculates height of string (in pixels).
Definition: gfx.cpp:548
The drop down box to choose client/game/company/all settings.
LanguageList _languages
The actual list of language meta data.
Definition: strings.cpp:49
Close box (at top-left of a window)
Definition: widget_type.h:69
Window to edit settings of the game.
Properties of config file settings.
uint Length() const
Return number of rows needed to display the whole page.
int _num_resolutions
The number of resolutions.
Definition: driver.cpp:22
Settings displayed in the list of basic settings.
Dropdown to select the road side (to set the right side ;)).
void SetLastField(bool last_field)
Set whether this is the last visible entry of the parent node.
String filter and state.
#define lastof(x)
Get the last element of an fixed size array.
Definition: depend.cpp:50
ZoomLevelByte _gui_zoom
GUI Zoom level.
Definition: gfx.cpp:60
Settings displayed in the list of advanced settings.
Show only settings which are different compared to default values.
Stuff related to the text buffer GUI.
virtual void OnInvalidateData(int data=0, bool gui_scope=true)
Some data on this window has become invalid.
const SettingDesc * setting
Setting description of the setting.
void DisableWidget(byte widget_index)
Sets a widget to disabled.
Definition: window_gui.h:404
#define CLRBITS(x, y)
Clears several bits in a variable.
Town name dropdown.
NewGRF readme.
Definition: textfile_type.h:19
virtual void OnClick(Point pt, int widget, int click_count)
A click with the left mouse button has been made on the window.
Subdirectory for all base data (base sets, intro game)
Definition: fileio_type.h:118
static T max(const T a, const T b)
Returns the maximum of two values.
Definition: math_func.hpp:26
static StringID TownName(int town_name)
Get a town name.
virtual uint GetMaxHelpHeight(int maxw)
Get the biggest height of the help text(s), if the width is at least maxw.
the value represents a limited number of string-options (internally integer)
Common string list item.
Definition: dropdown_type.h:41
static int GetNumSets()
Count the number of available graphics sets.
int GetNumMissing() const
Get the number of missing files.
const T * End() const
Get the pointer behind the last valid item (const)
void CreateNestedTree(bool fill_nested=true)
Perform the first part of the initialization of a nested widget tree.
Definition: window.cpp:1812
Pure simple text.
Definition: widget_type.h:58
virtual void Init(byte level=0)
Initialization of an entire setting page.
Background of the window.
any number-type
virtual void OnQueryTextFinished(char *str)
The query window opened from this window has closed.
static const int LEVEL_WIDTH
Indenting width of a sub-page in pixels.
bool _left_button_clicked
Is left mouse button clicked?
Definition: gfx.cpp:40
void DrawFrameRect(int left, int top, int right, int bottom, Colours colour, FrameFlags flags)
Draw frame rectangle.
Definition: widget.cpp:177
T * Append(uint to_add=1)
Append an item and return it.
void SetCount(int num)
Sets the number of elements in the list.
Definition: widget_type.h:670
CompanyByte _local_company
Company controlled by the human player at this client. Can also be COMPANY_SPECTATOR.
Definition: company_cmd.cpp:46
Partial widget specification to allow NWidgets to be written nested.
Definition: widget_type.h:910
Functions related to (drawing on) viewports.
static int GetCurRes()
Get index of the current screen resolution.
Dropdown for the font zoom level.
NewGRF license.
Definition: textfile_type.h:21
Base for the GUIs that have an edit box in them.
Data structure for an opened window.
Definition: window_gui.h:278
void FinishInitNested(WindowNumber window_number=0)
Perform the second part of the initialization of a nested widget tree.
Definition: window.cpp:1828
void SetFilterTerm(const char *str)
Set the term to filter on.
Functions to read fonts from files and cache them.
static NWidgetPart SetPadding(uint8 top, uint8 right, uint8 bottom, uint8 left)
Widget part function for setting additional space around a widget.
Definition: widget_type.h:1046
void InitNested(WindowNumber number=0)
Perform complete initialization of the Window with nested widgets, to allow use.
Definition: window.cpp:1841
SettingEntry * last_clicked
If non-NULL, pointer to the last clicked setting.
void ShowErrorMessage(StringID summary_msg, StringID detailed_msg, WarningLevel wl, int x=0, int y=0, const GRFFile *textref_stack_grffile=NULL, uint textref_stack_size=0, const uint32 *textref_stack=NULL)
Display an error message in a window.
Definition: error_gui.cpp:378
Bottom offset of the text of the frame.
Definition: window_gui.h:75
SaveLoad save
Internal structure (going to savegame, parts to config)
virtual void OnClick(Point pt, int widget, int click_count)
A click with the left mouse button has been made on the window.
void SetDParamStr(uint n, const char *str)
This function is used to "bind" a C string to a OpenTTD dparam slot.
Definition: strings.cpp:282
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:1720
Functions related to low-level strings.
Zoomed 4 times out.
Definition: zoom_type.h:26
bool type_hides
Whether the type hides filtered strings.
Only numeric ones.
Definition: string_type.h:28
Invisible widget that takes some space.
Definition: widget_type.h:79
bool UpdateFilterState(SettingFilter &filter, bool force_visible)
Update the filter state.
VarType conv
type of the variable to be saved, int
Definition: saveload.h:489
Functions related to errors.
Used in setting filter to match all types.
Default window size box (at top-right of a window, between WWT_SHADEBOX and WWT_STICKYBOX) ...
Definition: widget_type.h:65
uint Length() const
Get the number of items in the list.
int GetScrolledRowFromWidget(int clickpos, const Window *const w, int widget, int padding=0, int line_height=-1) const
Compute the row of a scrolled widget that a user clicked in.
Definition: widget.cpp:1959
display absolute value of the setting
uint pos_y
Vertical position of top-left corner of the widget in the window.
Definition: widget_type.h:178
Of a numeric setting entry, the left button is depressed.
Dropdown to say how often to autosave.
bool manually_changed_folding
Whether the user expanded/collapsed something manually.
CompanySettings company
default values for per-company settings
static GameSettings * settings_ptr
Pointer to the game settings being displayed and modified.
StringID str_help
(Translated) string with help text; gui only.
Suffix edit button.
int main(int argc, char *argv[])
Entry point.
Definition: depend.cpp:909
SettingEntry(const char *name)
Constructor for a single setting in the &#39;advanced settings&#39; window.
virtual uint Length() const
Return number of rows needed to display the (filtered) entry.
byte road_side
the side of the road vehicles drive on
void SetDisplayedHelpText(SettingEntry *pe)
Set the entry that should have its help text displayed, and mark the window dirty so it gets repainte...
SmallMap< int, QueryString * > querystrings
QueryString associated to WWT_EDITBOX widgets.
Definition: window_gui.h:330
void UpdateAllVirtCoords()
Update the viewport coordinates of all signs.
Definition: afterload.cpp:219
const char * name
Name of the setting.
#define FONT_HEIGHT_NORMAL
Height of characters in the normal (FS_NORMAL) font.
Definition: gfx_func.h:180
static NWidgetPart SetDataTip(uint32 data, StringID tip)
Widget part function for setting the data and tooltip.
Definition: widget_type.h:1014
Simple vector template class, with automatic delete.
virtual void DrawSetting(GameSettings *settings_ptr, int left, int right, int y, bool highlight) const
Function to draw setting value (button + text + current value)
Data stored about a string that can be modified in the GUI.
ClientSettings _settings_client
The current settings for this game.
Definition: settings.cpp:76
static NWidgetPart SetMinimalSize(int16 x, int16 y)
Widget part function for setting the minimal size.
Definition: widget_type.h:947
virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
Update size and resize step of a widget in the window.
Definition of base types and functions in a cross-platform compatible way.
void LoadStringWidthTable(bool monospace)
Initialize _stringwidth_table cache.
Definition: gfx.cpp:1132
static const int CF_NOEURO
Currency never switches to the Euro (as far as known).
Definition: currency.h:18
A number of safeguards to prevent using unsafe methods.
Standard setting.
Normal push-button (no toggle button) with text caption.
Definition: widget_type.h:104
static int SETTING_HEIGHT
Height of a single setting in the tree view in pixels.
Geometry functions.
GameSettings _settings_newgame
Game settings for new games (updated from the intro screen).
Definition: settings.cpp:78
byte level
Nesting level of this setting entry.
Simple depressed panel.
Definition: widget_type.h:50
StringID GetHelpText() const
Get the help text of a single setting.
Display settings associated to the "basic" list.
virtual void OnQueryTextFinished(char *str)
The query window opened from this window has closed.
bool IsVisibleByRestrictionMode(RestrictionMode mode) const
Checks whether an entry shall be made visible based on the restriction mode.
Offset at bottom to draw below the text.
Definition: window_gui.h:69
Custom currency; Window numbers:
Definition: window_type.h:614
const SettingDesc * GetSettingFromName(const char *name, uint *i)
Given a name of setting, return a setting description of it.
Definition: settings.cpp:2058
Window timeout counter.
Definition: window_gui.h:234
StringID title
Title of the sub-page.
StringID * BuildCurrencyDropdown()
Build a list of currency names StringIDs to use in a dropdown list.
Definition: currency.cpp:165
Information about languages and their files.
SettingFilter filter
Filter for the list.
const Scrollbar * GetScrollbar(uint widnum) const
Return the Scrollbar to a widget index.
Definition: window.cpp:311
char * stredup(const char *s, const char *last)
Create a duplicate of the given string.
Definition: string.cpp:138
Window for displaying the textfile of a BaseSet.
virtual void OnDropdownSelect(int widget, int index)
A dropdown option associated to this window has been selected.
Display settings associated to the "advanced" list.
virtual BaseSettingEntry * FindEntry(uint row, uint *cur_row)
Find setting entry at row row_num.
virtual void DrawWidget(const Rect &r, int widget) const
Draw the contents of a nested widget.
Collapse all button.
Frame.
Definition: widget_type.h:60
Description of selected base GRF.
void Init(byte level=0)
Initialization of an entire setting page.
static const GraphicsSet * GetSet(int index)
Get the name of the graphics set at the specified index.
Center the window.
Definition: window_gui.h:157
Label upfront to the type drop-down box to restrict the list of settings to show. ...
virtual void LoadTextfile(const char *textfile, Subdirectory dir)
Loads the textfile text from file and setup lines.
static NWidgetPart NWidget(WidgetType tp, Colours col, int16 idx=-1)
Widget part function for starting a new &#39;real&#39; widget.
Definition: widget_type.h:1114
SettingType type
Filter based on type.
Containers for BaseSettingEntry.
Prefix edit button.
Baseclass for nested widgets.
Definition: widget_type.h:126
Down button.
int DrawString(int left, int right, int top, const char *str, TextColour colour, StringAlignment align, bool underline, FontSize fontsize)
Draw string, possibly truncated to make it fit in its allocated space.
Definition: gfx.cpp:500
Language dropdown.
Entry is hidden by the string filter.
Basic functions/variables used all over the place.
Toggle fullscreen.
void SetValueDParams(uint first_param, int32 value) const
Set the DParams for drawing the value of a setting.
uint index
Index of the setting in the settings table.
RestrictionMode
How the list of advanced settings is filtered.
SettingEntryFlags
Flags for SettingEntry.
Right offset of the text of the frame.
Definition: window_gui.h:73
Current prefix.
#define lengthof(x)
Return the length of an fixed size array.
Definition: depend.cpp:42
bool RoadVehiclesAreBuilt()
Verify whether a road vehicle is available.
Definition: road_cmd.cpp:47
virtual void OnInvalidateData(int data=0, bool gui_scope=true)
Some data on this window has become invalid.
void GfxClearSpriteCache()
Remove all encoded sprites from the sprite cache without discarding sprite location information...
TextfileType
Additional text files accompanying Tar archives.
Definition: textfile_type.h:16
Dropdown for the resolution.
always the last item
Definition: currency.h:63
uint resize_y
Vertical resize step (0 means not resizable).
Definition: widget_type.h:167
static T min(const T a, const T b)
Returns the minimum of two values.
Definition: math_func.hpp:42
uint pos_x
Horizontal position of top-left corner of the widget in the window.
Definition: widget_type.h:177
bool folded
Sub-page is folded (not visible except for its title)
static StringID * _grf_names
Pointer to town names defined by NewGRFs.
virtual bool UpdateFilterState(SettingFilter &filter, bool force_visible)
Update the filter state.
Top offset of the text of the frame.
Definition: window_gui.h:74
StringFilter string
Filter string.
Left offset of the text of the frame.
Definition: window_gui.h:72
Year of introduction.
int cancel_button
Widget button of parent window to simulate when pressing CANCEL in OSK.
void DrawArrowButtons(int x, int y, Colours button_colour, byte state, bool clickable_left, bool clickable_right)
Draw [<][>] boxes.
uint32 StringID
Numeric value that represents a string, independent of the selected language.
Definition: strings_type.h:18
void DeleteWindowByClass(WindowClass cls)
Delete all windows of a given class.
Definition: window.cpp:1159
virtual uint Length() const
Return number of rows needed to display the (filtered) entry.
Data structure describing one page of settings in the settings window.
#define SETTING_BUTTON_WIDTH
Width of setting buttons.
Definition: settings_gui.h:19
CharSetFilter
Valid filter types for IsValidChar.
Definition: string_type.h:26
This entry is the last one in a (sub-)page.
void SetCompanySetting(uint index, int32 value)
Top function to save the new value of an element of the Settings struct.
Definition: settings.cpp:1970
Offset at top to draw above the text.
Definition: window_gui.h:68
Expand all button.
static T Clamp(const T a, const T min, const T max)
Clamp a value between an interval.
Definition: math_func.hpp:139
virtual void GetFoldingState(bool &all_folded, bool &all_unfolded) const
Recursively accumulate the folding state of the (filtered) tree.
bool IsVisible(const BaseSettingEntry *item) const
Check whether an entry is visible and not folded or filtered away.
void SetDirty() const
Mark entire window as dirty (in need of re-paint)
Definition: window.cpp:968
RestrictionMode min_cat
Minimum category needed to display all filtered strings (RM_BASIC, RM_ADVANCED, or RM_ALL)...
void FoldAll()
Recursively close all folds of sub-pages.
virtual void FoldAll()
Recursively close all (filtered) folds of sub-pages.
Dimension _resolutions[32]
List of resolutions.
Definition: driver.cpp:23
uint8 settings_restriction_mode
selected restriction mode in adv. settings GUI.
Dimension GetStringBoundingBox(const char *str, FontSize start_fontsize)
Return the string dimension in pixels.
Definition: gfx.cpp:700
SettingEntry * valuedropdown_entry
If non-NULL, pointer to the value for which a dropdown window is currently opened.
void AddLine(const char *str)
Pass another text line from the current item to the filter.
uint16 GetCount() const
Gets the number of elements in the list.
Definition: widget_type.h:613
const TBaseSet * baseset
View the textfile of this BaseSet.
Dimension maxdim(const Dimension &d1, const Dimension &d2)
Compute bounding box of both dimensions.
Draw only every second pixel, used for greying-out.
Definition: gfx_type.h:284
No window, redirects to WC_MAIN_WINDOW.
Definition: window_type.h:40
void DeleteWindowById(WindowClass cls, WindowNumber number, bool force)
Delete a window by its class and window number (if it is open).
Definition: window.cpp:1146
bool IsEditable(bool do_command=false) const
Check whether the setting is editable in the current gamemode.
Definition: settings.cpp:765
ZoomLevelByte zoom_min
minimum zoom out level
void InitGRFTownGeneratorNames()
Allocate memory for the NewGRF town names.
EntryVector entries
Settings on this page.
static void * GetVariableAddress(const void *object, const SaveLoad *sld)
Get the address of the variable.
Definition: saveload.h:813
StringID str_val
(Translated) first string describing the value.
ZoomLevel
All zoom levels we know.
Definition: zoom_type.h:21
Functions related to companies.
char *const buf
buffer in which text is saved
Definition: textbuf_type.h:34
const char * GetCurrentLanguageIsoCode()
Get the ISO language code of the currently loaded language.
Definition: strings.cpp:2006
Open base GRF readme, changelog (+1) or license (+2).
void ReInitAllWindows()
Re-initialize all windows.
Definition: window.cpp:3436
Use to select a base GRF.
Description of selected base SFX.
Both numeric and alphabetic and spaces and stuff.
Definition: string_type.h:27
Category setting filtered matches away.
Declaration of functions and types defined in highscore.h and highscore_gui.h.
GUISettings gui
settings related to the GUI
Bit-mask for button flags.
Window caption (window title between closebox and stickybox)
Definition: widget_type.h:61
void ShowBaseSetTextfileWindow(TextfileType file_type, const TBaseSet *baseset, StringID content_type)
Open the BaseSet version of the textfile window.
Window for displaying a textfile.
Definition: textfile_gui.h:23
If set the frame is lowered and the background colour brighter (ie. buttons when pressed) ...
Definition: window_gui.h:31
static bool StrEmpty(const char *s)
Check if a string buffer is empty.
Definition: string_func.h:59
a value of zero means the feature is disabled
void UpdateCursorSize()
Update cursor dimension.
Definition: gfx.cpp:1532
int GetStringLineCount(StringID str, int maxw)
Calculates number of lines of string.
Definition: gfx.cpp:573
static size_t GetNumItems()
Returns number of valid items in the pool.
Definition: pool_type.hpp:276
TextDirection _current_text_dir
Text direction of the currently selected language.
Definition: strings.cpp:52
virtual uint Draw(GameSettings *settings_ptr, int left, int right, int y, uint first_row, uint max_row, BaseSettingEntry *selected, uint cur_row=0, uint parent_last=0) const
Draw a row in the settings panel.
static GameSettings & GetGameSettings()
Get the settings-object applicable for the current situation: the newgame settings when we&#39;re in the ...
Searching and filtering using a stringterm.
TextfileType file_type
Type of textfile to view.
Definition: textfile_gui.h:24
Top offset of image in the button.
Definition: window_gui.h:42
bitmasked number where only ONE bit may be set
Vertical container.
Definition: widget_type.h:77
bool SetSettingValue(uint index, int32 value, bool force_newgame)
Top function to save the new value of an element of the Settings struct.
Definition: settings.cpp:1929
void ShowGameOptions()
Open the game options window.
virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
Update size and resize step of a widget in the window.
char own_name[32]
the localized name of this language
Definition: language.h:32
Label upfront to the category drop-down box to restrict the list of settings to show.
static T abs(const T a)
Returns the absolute value of (scalar) variable.
Definition: math_func.hpp:83
Functions for setting GUIs.
virtual uint Draw(GameSettings *settings_ptr, int left, int right, int y, uint first_row, uint max_row, BaseSettingEntry *selected, uint cur_row=0, uint parent_last=0) const
Draw a row in the settings panel.
static NWidgetPart EndContainer()
Widget part function for denoting the end of a container (horizontal, vertical, WWT_FRAME, WWT_INSET, or WWT_PANEL).
Definition: widget_type.h:999
Functions related to zooming.
Game setting.
Scrollbar * vscroll
Vertical scrollbar.
Definition: textfile_gui.h:25
Functions and types used internally for the settings configurations.
char * strecpy(char *dst, const char *src, const char *last)
Copies characters from one buffer to another.
Definition: depend.cpp:68
uint current_x
Current horizontal size (after resizing).
Definition: widget_type.h:174
virtual void SetStringParameters(int widget) const
Initialize string parameters for a widget.
virtual void OnResize()
Called after the window got resized.
virtual void SetStringParameters(int widget) const
Initialize string parameters for a widget.
bool SetFocusedWidget(int widget_index)
Set focus within this window to the given widget.
Definition: window.cpp:488
Up button.
SwitchMode _switch_mode
The next mainloop command.
Definition: gfx.cpp:47
void DrawDropDownButton(int x, int y, Colours button_colour, bool state, bool clickable)
Draw a dropdown button.
SettingType GetType() const
Return the type of the setting.
Definition: settings.cpp:780
SettingDescType cmd
various flags for the variable
Text filter.
LocaleSettings locale
settings related to used currency/unit system in the current game
virtual void Init(byte level=0)
Initialization of a setting entry.
static SettingsContainer & GetSettingsTree()
Construct settings tree.
void ShowGameSettings()
Open advanced settings window.
byte town_name
the town name generator used for town names
GRFTextWrapper * name
NOSAVE: GRF name (Action 0x08)
virtual BaseSettingEntry * FindEntry(uint row, uint *cur_row)
Find setting entry at row row_num.
static int _nb_grf_names
Number of town names defined by NewGRFs.
Functions related to commands.
bool _network_server
network-server is active
Definition: network.cpp:57
Coordinates of a point in 2D.
byte flags
Flags of the setting entry.
Dimension GetSpriteSize(SpriteID sprid, Point *offset, ZoomLevel zoom)
Get the size of a sprite.
Definition: gfx.cpp:769
List item containing a C char string.
Definition: dropdown_type.h:73
static bool IsValidID(size_t index)
Tests whether given index can be used to get valid (non-NULL) Titem.
Definition: pool_type.hpp:235
virtual void DrawSetting(GameSettings *settings_ptr, int left, int right, int y, bool highlight) const
Function to draw setting value (button + text + current value)
virtual void OnEditboxChanged(int wid)
The text in an editbox has been edited.
Drop down list.
Definition: widget_type.h:70
Normal push-button (no toggle button) with arrow caption.
Definition: widget_type.h:106
uint16 GetCapacity() const
Gets the number of visible elements of the scrollbar.
Definition: widget_type.h:622
SettingEntry * clicked_entry
If non-NULL, pointer to a clicked numeric setting (with a depressed left or right button)...
StringID str
(translated) string with descriptive text; gui and console
virtual void SetStringParameters(int widget) const
Initialize string parameters for a widget.
StringID content_type
STR_CONTENT_TYPE_xxx for title.
The drop down box to restrict the list of settings.
static const StringID INVALID_STRING_ID
Constant representing an invalid string (16bit in case it is used in savegames)
Definition: strings_type.h:19
ZoomLevelByte _font_zoom
Font Zoom level.
Definition: gfx.cpp:61
Company setting.
int32 min
minimum values
static void free(const void *ptr)
Version of the standard free that accepts const pointers.
Definition: depend.cpp:114
uint64 GetMaskOfAllowedCurrencies()
get a mask of the allowed currencies depending on the year
Definition: currency.cpp:118
Offset at right to draw the frame rectangular area.
Definition: window_gui.h:63
int width
width of the window (number of pixels to the right in x direction)
Definition: window_gui.h:321
The caption of the window.
Definition: misc_widget.h:50
static NWidgetPart SetFill(uint fill_x, uint fill_y)
Widget part function for setting filling.
Definition: widget_type.h:983
static bool HasBit(const T x, const uint8 y)
Checks if a bit in a value is set.
Base functions for all AIs.
Base of the town class.
static void ShowCustCurrency()
Open custom currency window.
#define DECLARE_POSTFIX_INCREMENT(enum_type)
Some enums need to have allowed incrementing (i.e.
Definition: enum_type.hpp:18
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.
virtual void OnDropdownClose(Point pt, int widget, int index, bool instant_close)
A dropdown window associated to this window has been closed.
Definition: window.cpp:284
Nothing was filtering matches away.
virtual void OnDropdownSelect(int widget, int index)
A dropdown option associated to this window has been selected.
virtual void DrawWidget(const Rect &r, int widget) const
Draw the contents of a nested widget.
void SetStringParameters(int widget) const
Initialize string parameters for a widget.
Use to select a base SFX.
#define SETTING_BUTTON_HEIGHT
Height of setting buttons.
Definition: settings_gui.h:21
uint8 timeout_timer
Timer value of the WF_TIMEOUT for flags.
Definition: window_gui.h:316
Errors (eg. saving/loading failed)
Definition: error.h:25
void GetFoldingState(bool &all_folded, bool &all_unfolded) const
Recursively accumulate the folding state of the tree.
static void QSortT(T *base, uint num, int(CDECL *comparator)(const T *, const T *), bool desc=false)
Type safe qsort()
Definition: sort_func.hpp:28
BaseSettingEntry * FindEntry(uint row, uint *cur_row)
Find the setting entry at row number row_num.
Info about corrupted files etc.
uint32 max
maximum values
Left offset of the image in the button.
Definition: window_gui.h:40
int32 interval
the interval to use between settings in the &#39;settings&#39; window. If interval is &#39;0&#39; the interval is dyn...
static NWidgetPart SetScrollbar(int index)
Attach a scrollbar to a widget.
Definition: widget_type.h:1095
Base list item class from which others are derived.
Definition: dropdown_type.h:24
byte autosave
how often should we do autosaves?
SettingDescBase desc
Settings structure (going to configuration file)
Dimensions (a width and height) of a rectangle in 2D.
Value of the NCB_EQUALSIZE flag.
Definition: widget_type.h:429
Query string window; Window numbers:
Definition: window_type.h:118
bool IsEmpty() const
Check whether any filter words were entered.
Offset at left to draw the frame rectangular area.
Definition: window_gui.h:62
static const Year MAX_YEAR
MAX_YEAR, nicely rounded value of the number of years that can be encoded in a single 32 bits date...
Definition: date_type.h:94
Factory to &#39;query&#39; all available blitters.
Game options window; Window numbers:
Definition: window_type.h:608
static const GraphicsSet * GetUsedSet()
Return the used set.
void DrawSprite(SpriteID img, PaletteID pal, int x, int y, const SubSprite *sub, ZoomLevel zoom)
Draw a sprite, not in a viewport.
Definition: gfx.cpp:834
static NWidgetPart SetPIP(uint8 pre, uint8 inter, uint8 post)
Widget part function for setting a pre/inter/post spaces.
Definition: widget_type.h:1076
virtual void OnPaint()
The window must be repainted.
Description of selected base music set.
void InvalidateData(int data=0, bool gui_scope=true)
Mark this window&#39;s data as invalid (in need of re-computing)
Definition: window.cpp:3242
Down button.
virtual bool IsVisible(const BaseSettingEntry *item) const
Check whether an entry is visible and not folded or filtered away.
int height
Height of the window (number of pixels down in y direction)
Definition: window_gui.h:322
virtual bool UpdateFilterState(SettingFilter &filter, bool force_visible)
Update the filter state.
void EnableWidget(byte widget_index)
Sets a widget to Enabled.
Definition: window_gui.h:413
void MarkWholeScreenDirty()
This function mark the whole screen as dirty.
Definition: gfx.cpp:1463
GUI functions related to textfiles.
int DrawStringMultiLine(int left, int right, int top, int bottom, const char *str, TextColour colour, StringAlignment align, bool underline, FontSize fontsize)
Draw string, possibly over multiple lines.
Definition: gfx.cpp:621
virtual void OnInvalidateData(int data=0, bool gui_scope=true)
Some data on this window has become invalid.
Definition: window_gui.h:748
(Toggle) Button with text
Definition: widget_type.h:55
List all settings regardless of the default/newgame/... values.
virtual void OnTimeout()
Called when this window&#39;s timeout has been reached.
a boolean number
uint16 GetPosition() const
Gets the position of the first visible element in the list.
Definition: widget_type.h:631
byte currency
currency we currently use
static void SetDParam(uint n, uint64 v)
Set a string parameter v at index n in the global string parameter array.
Definition: strings_func.h:201
static int CDECL NatSortFunc(const DropDownListItem *const *first, const DropDownListItem *const *second)
Natural sorting comparator function for DropDownList::sort().
Definition: dropdown.cpp:54