The Battle for Wesnoth  1.13.11+dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
preferences_dialog.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2011, 2015 by Iris Morelle <shadowm2006@gmail.com>
3  Copyright (C) 2016 - 2018 by Charles Dang <exodia339gmail.com>
4  Part of the Battle for Wesnoth Project http://www.wesnoth.org/
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY.
12 
13  See the COPYING file for more details.
14 */
15 
16 #define GETTEXT_DOMAIN "wesnoth-lib"
17 
19 
20 #include "gettext.hpp"
21 #include "filesystem.hpp"
22 #include "formatter.hpp"
23 #include "formula/string_utils.hpp"
24 #include "preferences/game.hpp"
26 #include "hotkey/hotkey_item.hpp"
28 #include "preferences/lobby.hpp"
29 #include "preferences/general.hpp"
30 #include "preferences/display.hpp"
31 #include "video.hpp"
32 
33 // Sub-dialog includes
40 
42 #include "gui/dialogs/helper.hpp"
43 #include "gui/dialogs/message.hpp"
45 #include "gui/widgets/button.hpp"
48 #include "gui/widgets/grid.hpp"
49 #include "gui/widgets/image.hpp"
50 #include "gui/widgets/label.hpp"
51 #ifdef GUI2_EXPERIMENTAL_LISTBOX
52 #include "gui/widgets/list.hpp"
53 #else
54 #include "gui/widgets/listbox.hpp"
55 #endif
57 #include "gui/widgets/settings.hpp"
58 #include "gui/widgets/slider.hpp"
61 #include "gui/widgets/text_box.hpp"
63 #include "gui/widgets/window.hpp"
64 #include "lexical_cast.hpp"
65 
66 #include "utils/functional.hpp"
67 #include <boost/math/common_factor_rt.hpp>
68 
69 namespace gui2
70 {
71 namespace dialogs
72 {
73 
74 using namespace preferences;
75 
76 REGISTER_DIALOG(preferences_dialog)
77 
79  : resolutions_() // should be populated by set_resolution_list before use
80  , adv_preferences_cfg_()
81  , last_selected_item_(0)
82  , accl_speeds_({0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2, 3, 4, 8, 16})
83  , visible_hotkeys_()
84  , cat_names_()
85  , initial_index_(pef_view_map[initial_view])
86 {
87  for(const config& adv : game_cfg.child_range("advanced_preference")) {
88  adv_preferences_cfg_.push_back(adv);
89  }
90 
91  std::sort(adv_preferences_cfg_.begin(), adv_preferences_cfg_.end(),
92  [](const config& lhs, const config& rhs) {
93  return lhs["name"].t_str().str() < rhs["name"].t_str().str();
94  });
95 
96  cat_names_ = {
97  // TODO: This list needs to be synchronized with the hotkey::HOTKEY_CATEGORY enum
98  // Find some way to do that automatically
99  _("General"),
100  _("Saved Games"),
101  _("Map Commands"),
102  _("Unit Commands"),
103  _("Player Chat"),
104  _("Replay Control"),
105  _("Planning Mode"),
106  _("Scenario Editor"),
107  _("Editor Palettes"),
108  _("Editor Tools"),
109  _("Editor Clipboard"),
110  _("Debug Commands"),
111  _("Custom WML Commands"),
112  // HKCAT_PLACEHOLDER intentionally excluded (it shouldn't have any anyway)
113  };
114 }
115 
116 // Helper function to refresh resolution list
118 {
119  resolutions_ = video.get_available_resolutions(true);
120 
121  std::vector<config> options;
122  for(const point& res : resolutions_) {
123  config option;
124  option["label"] = formatter() << res.x << font::unicode_multiplication_sign << res.y;
125 
126  const int div = boost::math::gcd(res.x, res.y);
127 
128  const int x_ratio = res.x / div;
129  const int y_ratio = res.y / div;
130 
131  if(x_ratio <= 10 || y_ratio <= 10) {
132  option["details"] = formatter() << "<span color='#777777'>(" << x_ratio << ':' << y_ratio << ")</span>";
133  }
134 
135  options.push_back(std::move(option));
136  }
137 
138  const unsigned current_res = std::distance(resolutions_.begin(), std::find(resolutions_.begin(), resolutions_.end(),
139  video.current_resolution()));
140 
141  res_list.set_values(options, current_res);
142 }
143 
144 std::map<std::string, string_map> preferences_dialog::get_friends_list_row_data(const acquaintance& entry)
145 {
146  std::map<std::string, string_map> data;
147  string_map item;
148 
149  std::string image = "friend.png";
150  std::string descriptor = _("friend");
151  std::string notes;
152 
153  if(entry.get_status() == "ignore") {
154  image = "ignore.png";
155  descriptor = _("ignored");
156  }
157 
158  if(!entry.get_notes().empty()) {
159  notes = " <small>(" + entry.get_notes() + ")</small>";
160  }
161 
162  item["use_markup"] = "true";
163 
164  item["label"] = "misc/status-" + image;
165  data.emplace("friend_icon", item);
166 
167  item["label"] = entry.get_nick() + notes;
168  data.emplace("friend_name", item);
169 
170  item["label"] = "<small>" + descriptor + "</small>";
171  data.emplace("friend_status", item);
172 
173  return data;
174 }
175 
177 {
178  const int num_friends = get_acquaintances().size();
179  const int sel = list.get_selected_row();
180 
181  if(sel < 0 || sel >= num_friends) {
182  return;
183  }
184 
185  std::map<std::string, acquaintance>::const_iterator who = get_acquaintances().begin();
186  std::advance(who, sel);
187 
188  textbox.set_value(who->second.get_nick() + " " + who->second.get_notes());
189 }
190 
192 {
193  const bool list_empty = list.get_item_count() == 0;
194 
195  if(!list_empty) {
196  list.select_row(std::min(static_cast<int>(list.get_item_count()) - 1, list.get_selected_row()));
197  }
198 
199  find_widget<button>(&window, "remove", false).set_active(!list_empty);
200 
201  find_widget<label>(&window, "no_friends_notice", false).set_visible(
203 }
204 
206 {
207  std::string username = textbox.text();
208  if(username.empty()) {
209  gui2::show_transient_message("", _("No username specified"), "", false, false, true);
210  return;
211  }
212 
213  std::string reason;
214 
215  size_t pos = username.find_first_of(' ');
216  if(pos != std::string::npos) {
217  reason = username.substr(pos + 1);
218  username = username.substr(0, pos);
219  }
220 
221  acquaintance* entry = nullptr;
222  bool added_new;
223 
224  std::tie(entry, added_new) = add_acquaintance(username, (is_friend ? "friend": "ignore"), reason);
225 
226  if(!entry) {
227  gui2::show_transient_message(_("Error"), _("Invalid username"), "", false, false, true);
228  return;
229  }
230 
231  textbox.clear();
232 
233  listbox& list = find_widget<listbox>(&window, "friends_list", false);
234 
235  //
236  // If this is a new entry, just add a new row. If it's not, we find the relevant
237  // row, remove it, and add a new row with the updated data. Should probably come
238  // up with a more elegant way to do this... the only reason I'm using the remove
239  // -and-replace method is to prevent any issues with the widgets' layout sizes.
240  //
241  if(added_new) {
242  list.add_row(get_friends_list_row_data(*entry));
243  } else {
244  for(unsigned i = 0; i < list.get_item_count(); ++i) {
245  grid* row_grid = list.get_row_grid(i);
246 
247  if(find_widget<label>(row_grid, "friend_name", false).get_label() == entry->get_nick()) {
248  list.remove_row(i);
249  list.add_row(get_friends_list_row_data(*entry), i);
250 
251  break;
252  }
253  }
254  }
255 
256  update_friends_list_controls(window, list);
257 }
258 
260 {
261  const int selected_row = std::max(0, friends_list.get_selected_row());
262 
263  std::map<std::string, acquaintance>::const_iterator who = get_acquaintances().begin();
264  std::advance(who, selected_row);
265 
266  const std::string to_remove = !textbox.text().empty() ? textbox.text() : who->second.get_nick();
267 
268  if(to_remove.empty()) {
269  gui2::show_transient_message("", _("No username specified"), "", false, false, true);
270  return;
271  }
272 
273  if(!remove_acquaintance(to_remove)) {
274  gui2::show_transient_error_message(_("Not on friends or ignore lists"));
275  return;
276  }
277 
278  textbox.clear();
279 
280  listbox& list = find_widget<listbox>(&window, "friends_list", false);
281  list.remove_row(selected_row);
282 
283  update_friends_list_controls(window, list);
284 }
285 
286 // Helper function to get the main grid in each row of the advanced section
287 // lisbox, which contains the value and setter widgets.
288 static grid* get_advanced_row_grid(listbox& list, const int selected_row)
289 {
290  return dynamic_cast<grid*>(list.get_row_grid(selected_row)->find("pref_main_grid", false));
291 }
292 
293 template<typename W>
295 {
296  find_widget<W>(&window, id, false).set_active(dynamic_cast<selectable_item&>(w).get_value_bool());
297 }
298 
299 /**
300  * Sets up states and callbacks for each of the widgets
301  */
303 {
304  //
305  // GENERAL PANEL
306  //
307 
308  /* SCROLL SPEED */
309  register_integer("scroll_speed", true,
311 
312  /* ACCELERATED SPEED */
313  register_bool("turbo_toggle", true, turbo, set_turbo,
314  [&](widget& w) { disable_widget_on_toggle<slider>(window, w, "turbo_slider"); }, true);
315 
316  const auto accl_load = [this]()->int {
317  return std::distance(accl_speeds_.begin() + 1, std::find(accl_speeds_.begin(), accl_speeds_.end(), turbo_speed()));
318  };
319 
320  const auto accl_save = [this](int i) {
321  set_turbo_speed(accl_speeds_[i - 1]);
322  };
323 
324  register_integer("turbo_slider", true,
325  accl_load, accl_save);
326 
327  // Set the value label transform function.
328  find_widget<slider>(&window, "turbo_slider", false).set_value_labels(
329  [this](int pos, int /*max*/)->t_string { return lexical_cast<std::string>(accl_speeds_[pos]); }
330  );
331 
332  /* SKIP AI MOVES */
333  register_bool("skip_ai_moves", true,
335 
336  /* DISABLE AUTO MOVES */
337  register_bool("disable_auto_moves", true,
339 
340  /* TURN DIALOG */
341  register_bool("show_turn_dialog", true,
343 
344  /* ENABLE PLANNING MODE */
345  register_bool("whiteboard_on_start", true,
347 
348  /* HIDE ALLY PLANS */
349  register_bool("whiteboard_hide_allies", true,
351 
352  /* INTERRUPT ON SIGHTING */
353  register_bool("interrupt_move_when_ally_sighted", true,
355 
356  /* SAVE REPLAYS */
357  register_bool("save_replays", true,
359 
360  /* DELETE AUTOSAVES */
361  register_bool("delete_saves", true,
363 
364  /* MAX AUTO SAVES */
365  register_integer("max_saves_slider", true,
367 
368  /* CACHE MANAGE */
369  connect_signal_mouse_left_click(find_widget<button>(&window, "cachemg", false),
370  std::bind(&gui2::dialogs::game_cache_options::display<>));
371 
372  //
373  // DISPLAY PANEL
374  //
375 
376  /* FULLSCREEN TOGGLE */
377  toggle_button& toggle_fullscreen =
378  find_widget<toggle_button>(&window, "fullscreen", false);
379 
380  toggle_fullscreen.set_value(fullscreen());
381 
382  // We bind a special callback function, so setup_single_toggle() is not used
383  connect_signal_mouse_left_click(toggle_fullscreen, std::bind(
385  this, std::ref(window)));
386 
387  /* SET RESOLUTION */
388  menu_button& res_list = find_widget<menu_button>(&window, "resolution_set", false);
389 
390  res_list.set_use_markup(true);
391  res_list.set_active(!fullscreen());
392 
393  set_resolution_list(res_list, window.video());
394 
395  res_list.connect_click_handler(
397  this, std::ref(window)));
398 
399  /* SHOW FLOATING LABELS */
400  register_bool("show_floating_labels", true,
402 
403  /* SHOW TEAM COLORS */
404  register_bool("show_ellipses", true,
406 
407  /* SHOW GRID */
408  register_bool("show_grid", true,
410 
411  /* ANIMATE MAP */
412  register_bool("animate_terrains", true, animate_map, set_animate_map,
413  [&](widget& w) { disable_widget_on_toggle<toggle_button>(window, w, "animate_water"); }, true);
414 
415  /* ANIMATE WATER */
416  register_bool("animate_water", true,
418 
419  /* SHOW UNIT STANDING ANIMS */
420  register_bool("animate_units_standing", true,
422 
423  /* SHOW UNIT IDLE ANIMS */
424  register_bool("animate_units_idle", true, idle_anim, set_idle_anim,
425  [&](widget& w) { disable_widget_on_toggle<slider>(window, w, "idle_anim_frequency"); });
426 
427  register_integer("idle_anim_frequency", true,
429 
430  /* FONT SCALING */
431  register_integer("scaling_slider", true,
433 
434  /* SELECT THEME */
436  find_widget<button>(&window, "choose_theme", false),
438 
439 
440  //
441  // SOUND PANEL
442  //
443 
444  /* SOUND FX */
445  register_bool("sound_toggle_sfx", true, sound_on, bind_void(set_sound, _1),
446  [&](widget& w) { disable_widget_on_toggle<slider>(window, w, "sound_volume_sfx"); }, true);
447 
448  register_integer("sound_volume_sfx", true,
450 
451  /* MUSIC */
452  register_bool("sound_toggle_music", true, music_on, bind_void(set_music, _1),
453  [&](widget& w) { disable_widget_on_toggle<slider>(window, w, "sound_volume_music"); }, true);
454 
455  register_integer("sound_volume_music", true,
457 
458  register_bool("sound_toggle_stop_music_in_background", true,
460 
461  /* TURN BELL */
462  register_bool("sound_toggle_bell", true, turn_bell, bind_void(set_turn_bell, _1),
463  [&](widget& w) { disable_widget_on_toggle<slider>(window, w, "sound_volume_bell"); }, true);
464 
465  register_integer("sound_volume_bell", true,
467 
468  /* UI FX */
469  register_bool("sound_toggle_uisfx", true, UI_sound_on, bind_void(set_UI_sound, _1),
470  [&](widget& w) { disable_widget_on_toggle<slider>(window, w, "sound_volume_uisfx"); }, true);
471 
472  register_integer("sound_volume_uisfx", true,
474 
475 
476  //
477  // MULTIPLAYER PANEL
478  //
479 
480  /* CHAT LINES */
481  register_integer("chat_lines", true,
483 
484  /* CHAT TIMESTAMPPING */
485  register_bool("chat_timestamps", true,
487 
488  /* SAVE PASSWORD */
489  register_bool("remember_password", true,
491 
492  /* WHISPERS FROM FRIENDS ONLY */
493  register_bool("lobby_whisper_friends_only", true,
495 
496  /* LOBBY JOIN NOTIFICATIONS */
497  lobby_joins_group.add_member(find_widget<toggle_button>(&window, "lobby_joins_none", false, true), SHOW_NONE);
498  lobby_joins_group.add_member(find_widget<toggle_button>(&window, "lobby_joins_friends", false, true), SHOW_FRIENDS);
499  lobby_joins_group.add_member(find_widget<toggle_button>(&window, "lobby_joins_all", false, true), SHOW_ALL);
500 
501  lobby_joins_group.set_member_states(static_cast<LOBBY_JOINS>(lobby_joins()));
502 
503  lobby_joins_group.set_callback_on_value_change([&](widget&) {
504  _set_lobby_joins(lobby_joins_group.get_active_member_value());
505  });
506 
507  /* FRIENDS LIST */
508  listbox& friends_list = find_widget<listbox>(&window, "friends_list", false);
509 
510  friends_list.clear();
511 
512  for(const auto& entry : get_acquaintances()) {
513  friends_list.add_row(get_friends_list_row_data(entry.second));
514  }
515 
516  update_friends_list_controls(window, friends_list);
517 
518  text_box& textbox = find_widget<text_box>(&window, "friend_name_box", false);
519 
521  find_widget<button>(&window, "add_friend", false), std::bind(
523  this, true,
524  std::ref(textbox),
525  std::ref(window)));
526 
528  find_widget<button>(&window, "add_ignored", false), std::bind(
530  this, false,
531  std::ref(textbox),
532  std::ref(window)));
533 
535  find_widget<button>(&window, "remove", false), std::bind(
537  this,
538  std::ref(friends_list),
539  std::ref(textbox),
540  std::ref(window)));
541 
542  connect_signal_notify_modified(friends_list, std::bind(
544  this,
545  std::ref(friends_list),
546  std::ref(textbox)));
547 
548  /* ALERTS */
550  find_widget<button>(&window, "mp_alerts", false),
551  std::bind(&gui2::dialogs::mp_alerts_options::display<>));
552 
553  /* SET WESNOTHD PATH */
555  find_widget<button>(&window, "mp_wesnothd", false), std::bind(
557 
558 
559  //
560  // ADVANCED PANEL
561  //
562 
563  listbox& advanced = find_widget<listbox>(&window, "advanced_prefs", false);
564 
565  std::map<std::string, string_map> row_data;
566 
567  for(const config& option : adv_preferences_cfg_) {
568  // Details about the current option
569  ADVANCED_PREF_TYPE pref_type;
570  try {
571  pref_type = ADVANCED_PREF_TYPE::string_to_enum(option["type"].str());
572  } catch(bad_enum_cast&) {
573  continue;
574  }
575 
576  const std::string& pref_name = option["field"].str();
577 
578  row_data["pref_name"]["label"] = option["name"];
579  advanced.add_row(row_data);
580 
581  const int this_row = advanced.get_item_count() - 1;
582 
583  // Get the main grid from each row
584  grid* main_grid = get_advanced_row_grid(advanced, this_row);
585  assert(main_grid);
586 
587  grid& details_grid = find_widget<grid>(main_grid, "prefs_setter_grid", false);
589 
590  // The toggle widget for toggle-type options (hidden for other types)
591  toggle_button& toggle_box = find_widget<toggle_button>(main_grid, "value_toggle", false);
593 
594  if(!option["description"].empty()) {
595  find_widget<styled_widget>(main_grid, "description", false).set_label(option["description"]);
596  }
597 
598  switch(pref_type.v) {
599  case ADVANCED_PREF_TYPE::TOGGLE: {
600  //main_grid->remove_child("setter");
601 
603  toggle_box.set_value(get(pref_name, option["default"].to_bool()));
604 
605  // We need to bind a lambda here since preferences::set is overloaded.
606  // A lambda alone would be more verbose because it'd need to specify all the parameters.
607  connect_signal_mouse_left_click(toggle_box, std::bind(
608  [&, pref_name]() { set(pref_name, toggle_box.get_value_bool()); }
609  ));
610 
611  gui2::bind_status_label<toggle_button>(
612  main_grid, "value_toggle", default_status_value_getter<toggle_button>, "value");
613 
614  break;
615  }
616 
617  case ADVANCED_PREF_TYPE::SLIDER: {
618  slider* setter_widget = build_single_widget_instance<slider>("slider", config {"definition", "minimal"});
619  setter_widget->set_id("setter");
620  // Maximum must be set first or this will assert
621  setter_widget->set_value_range(option["min"].to_int(), option["max"].to_int());
622  setter_widget->set_step_size(option["step"].to_int(1));
623 
624  details_grid.swap_child("setter", setter_widget, true);
625 
626  slider& slide = find_widget<slider>(&details_grid, "setter", false);
627 
628  slide.set_value(lexical_cast_default<int>(get(pref_name), option["default"].to_int()));
629 
630  // We need to bind a lambda here since preferences::set is overloaded.
631  // A lambda alone would be more verbose because it'd need to specify all the parameters.
632  connect_signal_notify_modified(slide, std::bind(
633  [&, pref_name]() { set(pref_name, slide.get_value()); }
634  ));
635 
636  gui2::bind_status_label<slider>(main_grid, "setter", default_status_value_getter<slider>, "value");
637 
638  break;
639  }
640 
641  case ADVANCED_PREF_TYPE::COMBO: {
642  std::vector<config> menu_data;
643  std::vector<std::string> option_ids;
644 
645  for(const config& choice : option.child_range("option")) {
646  config menu_item;
647  menu_item["label"] = choice["name"];
648  if(choice.has_attribute("description")) {
649  menu_item["details"] = std::string("<span color='#777'>") + choice["description"] + "</span>";
650  }
651  menu_data.push_back(menu_item);
652  option_ids.push_back(choice["id"]);
653  }
654 
655  const unsigned selected = std::distance(option_ids.begin(), std::find(option_ids.begin(), option_ids.end(),
656  get(pref_name, option["default"].str())));
657 
658  menu_button* setter_widget = build_single_widget_instance<menu_button>("menu_button");
659  setter_widget->set_id("setter");
660 
661  details_grid.swap_child("setter", setter_widget, true);
662 
663  menu_button& menu = find_widget<menu_button>(&details_grid, "setter", false);
664 
665  menu.set_use_markup(true);
666  menu.set_values(menu_data, selected);
667 
668  // We need to bind a lambda here since preferences::set is overloaded.
669  // A lambda alone would be more verbose because it'd need to specify all the parameters.
671  std::bind([=](widget& w) { set(pref_name, option_ids[dynamic_cast<menu_button&>(w).get_value()]); }, _1));
672 
673  gui2::bind_status_label<menu_button>(main_grid, "setter", [](menu_button& m)->std::string {
674  return m.get_value_string();
675  }, "value");
676 
677  break;
678  }
679 
680  case ADVANCED_PREF_TYPE::SPECIAL: {
681  //main_grid->remove_child("setter");
682 
683  image* value_widget = build_single_widget_instance<image>("image");
684  value_widget->set_label("icons/arrows/arrows_blank_right_25.png~CROP(3,3,18,18)");
685 
686  main_grid->swap_child("value", value_widget, true);
687 
688  break;
689  }
690  }
691  }
692 
693  connect_signal_notify_modified(advanced, std::bind(
695  this,
696  std::ref(advanced)));
697 
698  on_advanced_prefs_list_select(advanced);
699 
700  //
701  // HOTKEYS PANEL
702  //
703 
704  std::vector<config> hotkey_category_entries;
705  for(const auto& name : cat_names_) {
706  hotkey_category_entries.emplace_back(config {"label", name, "checkbox", false});
707  }
708 
709  multimenu_button& hotkey_menu = find_widget<multimenu_button>(&window, "hotkey_category_menu", false);
710 
711  hotkey_menu.set_values(hotkey_category_entries);
712 
713  connect_signal_notify_modified(hotkey_menu,
714  std::bind(&preferences_dialog::hotkey_type_filter_callback, this, std::ref(window)));
715 
716  listbox& hotkey_list = setup_hotkey_list(window);
717 
718  // Action column
719  hotkey_list.register_translatable_sorting_option(0, [this](const int i) { return visible_hotkeys_[i]->description.str(); });
720 
721  // Hotkey column
722  hotkey_list.register_sorting_option(1, [this](const int i) { return hotkey::get_names(visible_hotkeys_[i]->command); });
723 
724  // Scope columns
725  hotkey_list.register_sorting_option(2, [this](const int i) { return !visible_hotkeys_[i]->scope[hotkey::SCOPE_GAME]; });
726  hotkey_list.register_sorting_option(3, [this](const int i) { return !visible_hotkeys_[i]->scope[hotkey::SCOPE_EDITOR]; });
727  hotkey_list.register_sorting_option(4, [this](const int i) { return !visible_hotkeys_[i]->scope[hotkey::SCOPE_MAIN_MENU]; });
728 
729  hotkey_list.set_active_sorting_option({0, listbox::SORT_ASCENDING}, true);
730 
732  find_widget<button>(&window, "btn_add_hotkey", false), std::bind(
734  this,
735  std::ref(hotkey_list)));
736 
738  find_widget<button>(&window, "btn_clear_hotkey", false), std::bind(
740  this,
741  std::ref(hotkey_list)));
742 
744  find_widget<button>(&window, "btn_reset_hotkeys", false), std::bind(
746  this,
747  std::ref(window)));
748 }
749 
751 {
752  const std::string& default_icon = "misc/empty.png~CROP(0,0,15,15)";
753 
754  std::map<std::string, string_map> row_data;
755 
756  t_string& row_icon = row_data["img_icon"]["label"];
757  t_string& row_action = row_data["lbl_desc"]["label"];
758  t_string& row_hotkey = row_data["lbl_hotkey"]["label"];
759 
760  t_string& row_is_g = row_data["lbl_is_game"]["label"];
761  t_string& row_is_g_markup = row_data["lbl_is_game"]["use_markup"];
762  t_string& row_is_e = row_data["lbl_is_editor"]["label"];
763  t_string& row_is_e_markup = row_data["lbl_is_editor"]["use_markup"];
764  t_string& row_is_t = row_data["lbl_is_titlescreen"]["label"];
765  t_string& row_is_t_markup = row_data["lbl_is_titlescreen"]["use_markup"];
766 
767  listbox& hotkey_list = find_widget<listbox>(&window, "list_hotkeys", false);
768 
769  hotkey_list.clear();
770  visible_hotkeys_.clear();
771 
772  std::string text_feature_on = "<span color='#0f0'>" + _("&#9679;") + "</span>";
773 
774  for(const auto& hotkey_item : hotkey::get_hotkey_commands()) {
775  if(hotkey_item.hidden) {
776  continue;
777  }
778  visible_hotkeys_.push_back(&hotkey_item);
779 
780  if(filesystem::file_exists(game_config::path + "/images/icons/action/" + hotkey_item.command + "_25.png")) {
781  row_icon = "icons/action/" + hotkey_item.command + "_25.png~CROP(3,3,18,18)";
782  } else {
783  row_icon = default_icon;
784  }
785 
786  row_action = hotkey_item.description;
787  row_hotkey = hotkey::get_names(hotkey_item.command);
788 
789  row_is_g = hotkey_item.scope[hotkey::SCOPE_GAME] ? text_feature_on : "";
790  row_is_g_markup = "true";
791  row_is_e = hotkey_item.scope[hotkey::SCOPE_EDITOR] ? text_feature_on : "";
792  row_is_e_markup = "true";
793  row_is_t = hotkey_item.scope[hotkey::SCOPE_MAIN_MENU] ? text_feature_on : "";
794  row_is_t_markup = "true";
795 
796  hotkey_list.add_row(row_data);
797  }
798 
799  return hotkey_list;
800 }
801 
803 {
804  int row_number = hotkeys.get_selected_row();
805  const hotkey::hotkey_command& hotkey_item = *visible_hotkeys_[row_number];
806 
807  gui2::dialogs::hotkey_bind bind_dlg(hotkey_item.command);
808  bind_dlg.show();
809 
810  hotkey::hotkey_ptr newhk = bind_dlg.get_new_binding();
811  hotkey::hotkey_ptr oldhk;
812 
813  // only if not cancelled.
814  if(newhk.get() == nullptr) {
815  return;
816  }
817 
818  for(const hotkey::hotkey_ptr& hk : hotkey::get_hotkeys()) {
819  if(!hk->is_disabled() && newhk->bindings_equal(hk)) {
820  oldhk = hk;
821  }
822  }
823 
824  hotkey::scope_changer scope_restorer;
825  hotkey::set_active_scopes(hotkey_item.scope);
826 
827  if(oldhk && oldhk->get_command() == hotkey_item.command) {
828  return;
829  }
830 
831  if(oldhk && oldhk->get_command() != "null") {
832  const std::string text = vgettext("“<b>$hotkey_sequence|</b>” is in use by “<b>$old_hotkey_action|</b>”.\nDo you wish to reassign it to “<b>$new_hotkey_action|</b>”?", {
833  {"hotkey_sequence", oldhk->get_name()},
834  {"old_hotkey_action", hotkey::get_description(oldhk->get_command())},
835  {"new_hotkey_action", hotkey::get_description(newhk->get_command())}
836  });
837 
838  const int res = gui2::show_message(_("Reassign Hotkey"), text, gui2::dialogs::message::yes_no_buttons, true);
839  if(res != gui2::window::OK) {
840  return;
841  }
842  }
843 
844  hotkey::add_hotkey(newhk);
845 
846  // We need to recalculate all hotkey names in because we might have removed a hotkey from another command.
847  for(size_t i = 0; i < hotkeys.get_item_count(); ++i) {
848  const hotkey::hotkey_command& hotkey_item_row = *visible_hotkeys_[i];
849  find_widget<label>(hotkeys.get_row_grid(i), "lbl_hotkey", false).set_label(hotkey::get_names(hotkey_item_row.command));
850  }
851 }
852 
854 {
855  gui2::show_transient_message(_("Hotkeys Reset"), _("All hotkeys have been reset to their default values."),
856  std::string(), false, false, true);
857 
858  clear_hotkeys();
859 
860  // Set up the list again and reselect the default sorting option.
861  listbox& hotkey_list = setup_hotkey_list(window);
862  hotkey_list.set_active_sorting_option({0, listbox::SORT_ASCENDING}, true);
863 
864  find_widget<multimenu_button>(&window, "hotkey_category_menu", false).reset_toggle_states();
865 }
866 
868 {
869  int row_number = hotkeys.get_selected_row();
870  const hotkey::hotkey_command& hotkey_item = *visible_hotkeys_[row_number];
871  hotkey::clear_hotkeys(hotkey_item.command);
872  find_widget<label>(hotkeys.get_row_grid(row_number), "lbl_hotkey", false).set_label(hotkey::get_names(hotkey_item.command));
873 }
874 
876 {
877  const multimenu_button& hotkey_menu = find_widget<const multimenu_button>(&window, "hotkey_category_menu", false);
878 
879  boost::dynamic_bitset<> toggle_states = hotkey_menu.get_toggle_states();
880  boost::dynamic_bitset<> res(visible_hotkeys_.size());
881 
882  if(!toggle_states.none()) {
883  for(size_t h = 0; h < visible_hotkeys_.size(); ++h) {
884  int index = 0;
885 
886  for(size_t i = 0; i < cat_names_.size(); ++i) {
888 
889  if(visible_hotkeys_[h]->category == cat) {
890  index = i;
891  break;
892  }
893  }
894 
895  res[h] = toggle_states[index];
896  }
897  } else {
898  // Nothing selected. It means that *all* categories are shown.
899  res = ~res;
900  }
901 
902  find_widget<listbox>(&window, "list_hotkeys", false).set_row_shown(res);
903 }
904 
906 {
907  const int selected_row = list.get_selected_row();
908 
909  const ADVANCED_PREF_TYPE& selected_type = ADVANCED_PREF_TYPE::string_to_enum(
910  adv_preferences_cfg_[selected_row]["type"].str());
911 
912  const std::string& selected_field = adv_preferences_cfg_[selected_row]["field"].str();
913 
914  if(selected_type == ADVANCED_PREF_TYPE::SPECIAL) {
915  if(selected_field == "advanced_graphic_options") {
916  gui2::dialogs::advanced_graphics_options::display();
917  } else if(selected_field == "logging") {
918  gui2::dialogs::log_settings::display();
919  } else if(selected_field == "orb_color") {
920  gui2::dialogs::select_orb_colors::display();
921  } else {
922  WRN_GUI_L << "Invalid or unimplemented custom advanced prefs option: " << selected_field << "\n";
923  }
924 
925  // Add more options here as needed
926  }
927 
928  const bool has_description = !adv_preferences_cfg_[selected_row]["description"].empty();
929 
930  if(has_description || (selected_type != ADVANCED_PREF_TYPE::SPECIAL && selected_type != ADVANCED_PREF_TYPE::TOGGLE)) {
931  find_widget<widget>(get_advanced_row_grid(list, selected_row), "prefs_setter_grid", false)
932  .set_visible(widget::visibility::visible);
933  }
934 
935  if(last_selected_item_ != selected_row) {
936  find_widget<widget>(get_advanced_row_grid(list, last_selected_item_), "prefs_setter_grid", false)
937  .set_visible(widget::visibility::invisible);
938 
939  last_selected_item_ = selected_row;
940  }
941 }
942 
944 {
945  //
946  // MULTIPLAYER TABS
947  //
949  std::bind(&preferences_dialog::on_tab_select, this, std::ref(window)));
950 }
951 
952 static int index_in_pager_range(const int& first, const stacked_widget& pager)
953 {
954  // Ensure the specified index is between 0 and one less than the max
955  // number of pager layers (since get_layer_count returns one-past-end).
956  return std::min<int>(std::max(0, first), pager.get_layer_count() - 1);
957 }
958 
960 {
961  set_always_save_fields(true);
962 
963  //
964  // Status labels
965  // These need to be set here in pre_show, once the fields are initialized. For some reason, this
966  // is not the case for those in Advanced
967  //
968 
969  gui2::bind_status_label<slider>(&window, "max_saves_slider", [](slider& s)->std::string {
970  return s.get_value() == INFINITE_AUTO_SAVES ? _("∞") : s.get_value_label().str();
971  });
972 
973  gui2::bind_status_label<slider>(&window, "turbo_slider");
974 
975  gui2::bind_status_label<slider>(&window, "scaling_slider", [](slider& s)->std::string {
976  return s.get_value_label() + "%";
977  });
978 
979  listbox& selector = find_widget<listbox>(&window, "selector", false);
980  stacked_widget& pager = find_widget<stacked_widget>(&window, "pager", false);
981 
982  pager.set_find_in_all_layers(true);
983 
985  std::bind(&preferences_dialog::on_page_select, this, std::ref(window)));
986 
987  window.keyboard_capture(&selector);
988 
989  VALIDATE(selector.get_item_count() == pager.get_layer_count(),
990  "The preferences pager and its selector listbox do not have the same number of items.");
991 
992  const int main_index = index_in_pager_range(initial_index_.first, pager);
993 
994  // Loops through each pager layer and checks if it has both a tab bar
995  // and stack. If so, it initializes the options for the former and
996  // selects the specified layer of the latter.
997  for(unsigned int i = 0; i < pager.get_layer_count(); ++i) {
998  listbox* tab_selector = find_widget<listbox>(
999  pager.get_layer_grid(i), "tab_selector", false, false);
1000 
1001  stacked_widget* tab_pager = find_widget<stacked_widget>(
1002  pager.get_layer_grid(i), "tab_pager", false, false);
1003 
1004  if(tab_pager && tab_selector) {
1005  const int ii = static_cast<int>(i);
1006  const int tab_index = index_in_pager_range(initial_index_.second, *tab_pager);
1007  const int to_select = (ii == main_index ? tab_index : 0);
1008 
1009  // Initialize tabs for this page
1010  initialize_tabs(window, *tab_selector);
1011 
1012  tab_selector->select_row(to_select);
1013  tab_pager->select_layer(to_select);
1014  }
1015  }
1016 
1017  // Finally, select the initial main page
1018  selector.select_row(main_index);
1019  pager.select_layer(main_index);
1020 }
1021 
1022 void preferences_dialog::set_visible_page(window& window, unsigned int page, const std::string& pager_id)
1023 {
1024  find_widget<stacked_widget>(&window, pager_id, false).select_layer(page);
1025 }
1026 
1027 // Special fullsceen callback
1029 {
1030  const bool ison = find_widget<toggle_button>(&window, "fullscreen", false).get_value_bool();
1031  window.video().set_fullscreen(ison);
1032 
1033  menu_button& res_list = find_widget<menu_button>(&window, "resolution_set", false);
1034 
1035  set_resolution_list(res_list, window.video());
1036  res_list.set_active(!ison);
1037 }
1038 
1040 {
1041  menu_button& res_list = find_widget<menu_button>(&window, "resolution_set", false);
1042 
1043  if(window.video().set_resolution(resolutions_[res_list.get_value()])) {
1044  set_resolution_list(res_list, window.video());
1045  }
1046 }
1047 
1049 {
1050  const int selected_row =
1051  std::max(0, find_widget<listbox>(&window, "selector", false).get_selected_row());
1052  set_visible_page(window, static_cast<unsigned int>(selected_row), "pager");
1053 }
1054 
1056 {
1057  const int selected_row =
1058  std::max(0, find_widget<listbox>(&window, "tab_selector", false).get_selected_row());
1059  set_visible_page(window, static_cast<unsigned int>(selected_row), "tab_pager");
1060 }
1061 
1063 {
1064  save_hotkeys();
1065 }
1066 
1067 } // namespace dialogs
1068 } // namespace gui2
bool disable_auto_moves()
Definition: general.cpp:1049
void initialize_tabs(window &window, listbox &selector)
Initializers.
bool show_theme_dialog()
Definition: display.cpp:118
void set_turbo(bool ison)
Definition: display.cpp:54
void on_page_select(window &window)
Callback for selection changes.
bool set_sound(bool ison)
Definition: general.cpp:665
void set_active_sorting_option(const order_pair &sort_by, const bool select_first=false)
Sorts the listbox by a pre-set sorting option.
Definition: listbox.cpp:642
boost::dynamic_bitset get_toggle_states() const
Get the current state of the menu options.
void set_hide_whiteboard(bool value)
Definition: game.cpp:445
int autosavemax()
Definition: game.cpp:810
void show_message(const std::string &title, const std::string &msg, const std::string &button_caption, const bool auto_close, const bool message_use_markup, const bool title_use_markup)
Shows a message to the user.
Definition: message.cpp:152
void set_grid(bool ison)
Definition: display.cpp:72
int bell_volume()
Definition: general.cpp:577
Dialog is closed with ok button.
Definition: window.hpp:101
std::vector< char_t > string
point current_resolution()
Definition: video.cpp:473
bool remember_password()
size_t index(const utf8::string &str, const size_t index)
Codepoint index corresponding to the nth character in a UTF-8 string.
Definition: unicode.cpp:71
void set_value(unsigned selected, bool fire_event=false) override
Inherited from selectable_item.
void set_show_standing_animations(bool value)
Definition: display.cpp:109
void connect_click_handler(const event::signal_function &signal)
Inherited from clickable_item.
Definition: menu_button.hpp:58
void set(CURSOR_TYPE type)
Use the default parameter to reset cursors.
Definition: cursor.cpp:154
Simple push button.
Definition: menu_button.hpp:41
void save_hotkeys(config &cfg)
Save the non-default hotkeys to the config.
void add_friend_list_entry(const bool is_friend, text_box &textbox, window &window)
void set_visible_page(window &window, unsigned int page, const std::string &pager_id)
void set_remember_password(bool remember)
void set_show_floating_labels(bool value)
Definition: game.cpp:847
int lobby_joins()
Definition: game.cpp:343
New lexcical_cast header.
void show_wesnothd_server_search()
Definition: display.cpp:152
Definition: video.hpp:31
void default_hotkey_callback(window &window)
void set_scroll_speed(const int new_speed)
Definition: general.cpp:869
void update_friends_list_controls(window &window, listbox &list)
const std::map< std::string, acquaintance > & get_acquaintances()
Definition: game.cpp:225
const int INFINITE_AUTO_SAVES
Definition: game.hpp:191
This file contains the window object, this object is a top level container which has the event manage...
child_itors child_range(config_key_type key)
Definition: config.cpp:360
void set_show_side_colors(bool value)
Definition: game.cpp:760
int scroll_speed()
Definition: general.cpp:861
void show_transient_message(const std::string &title, const std::string &message, const std::string &image, const bool message_use_markup, const bool title_use_markup, const bool restore_background)
Shows a transient message to the user.
#define WRN_GUI_L
Definition: log.hpp:59
Base class for all widgets.
Definition: widget.hpp:48
bool hide_whiteboard()
Definition: game.cpp:440
void clear_hotkeys(const std::string &command)
Unset the command bindings for all hotkeys matching the command.
void _set_lobby_joins(int show)
Definition: game.cpp:358
void set_chat_lines(int lines)
Definition: game.cpp:919
bool idle_anim()
Definition: general.cpp:457
Stores all information related to functions that can be bound to hotkeys.
int chat_lines()
Definition: game.cpp:914
void register_translatable_sorting_option(const int col, translatable_sorter_func_t f)
Registers a special sorting function specifically for translatable values.
Definition: listbox.cpp:634
#define h
double turbo_speed()
Definition: general.cpp:431
bool animate_water()
Definition: general.cpp:900
void set_sound_volume(int vol)
Definition: general.cpp:567
Simple push button.
To lexical_cast(From value)
Lexical cast converts one type to another.
bool show(const unsigned auto_close_time=0)
Shows the window.
bool show_side_colors()
Definition: game.cpp:765
const config * game_cfg
Definition: help_impl.cpp:65
-file util.hpp
bool remove_acquaintance(const std::string &nick)
Definition: game.cpp:267
void set_interrupt_when_ally_sighted(bool value)
Definition: game.cpp:800
static grid * get_advanced_row_grid(listbox &list, const int selected_row)
bool sound_on()
Definition: general.cpp:660
void set_active_scopes(hk_scopes s)
bool whisper_friends_only()
Definition: lobby.cpp:20
bool select_row(const unsigned row, const bool select=true)
Selects a row.
Definition: listbox.cpp:252
Class for a single line text area.
Definition: text_box.hpp:121
Generic file dialog.
Definition: field-fwd.hpp:22
listbox & setup_hotkey_list(window &window)
const hotkey_list & get_hotkeys()
Returns the list of hotkeys.
std::string turn_bell
std::string get_names(const std::string &id)
Returns a comma-separated string of hotkey names.
virtual void set_label(const t_string &label)
The listbox class.
Definition: listbox.hpp:42
int get_selected_row() const
Returns the first selected row.
Definition: listbox.cpp:274
Base container class.
Definition: grid.hpp:30
const config & options()
Definition: game.cpp:570
void on_friends_list_select(listbox &list, text_box &textbox)
virtual unsigned get_value() const override
Inherited from selectable_item.
Definition: menu_button.hpp:81
void set_turn_dialog(bool ison)
Definition: game.cpp:425
static UNUSEDNOWARN std::string _(const char *str)
Definition: gettext.hpp:89
void set_value_range(int min_value, int max_value)
Definition: slider.cpp:250
void connect_signal_notify_modified(dispatcher &dispatcher, const signal_notification_function &signal)
Connects a signal handler for getting a notification upon modification.
Definition: dispatcher.cpp:233
void set_save_replays(bool value)
Definition: game.cpp:770
bool is_friend(const std::string &nick)
Definition: game.cpp:289
void set_idle_anim_rate(int rate)
Definition: display.cpp:96
#define VALIDATE(cond, message)
The macro to use for the validation of WML.
This file contains the settings handling of the widget library.
void set_values(const std::vector<::config > &values, int selected=0)
const std::string & text() const
std::ostringstream wrapper.
Definition: formatter.hpp:38
void clear()
Removes all the rows in the listbox, clearing it.
Definition: listbox.cpp:127
void set_visible(const visibility visible)
Definition: widget.cpp:479
std::pair< preferences::acquaintance *, bool > add_acquaintance(const std::string &nick, const std::string &mode, const std::string &notes)
Definition: game.cpp:245
void connect_signal_mouse_left_click(dispatcher &dispatcher, const signal_function &signal)
Connects a signal handler for a left mouse button click.
Definition: dispatcher.cpp:218
bool fullscreen()
Definition: general.cpp:396
void set_enable_whiteboard_mode_on_start(bool value)
Definition: game.cpp:435
unsigned int get_layer_count() const
Gets the total number of layers.
void set_turbo_speed(double speed)
Definition: display.cpp:63
void set_font_scaling(int scale)
Definition: general.cpp:447
std::string selected
void set_music_volume(int vol)
Definition: general.cpp:552
const std::string unicode_multiplication_sign
Definition: constants.cpp:41
void set_idle_anim(bool ison)
Definition: display.cpp:88
void hotkey_type_filter_callback(window &window) const
const std::string & get_status() const
Definition: game.hpp:276
std::map< std::string, string_map > get_friends_list_row_data(const preferences::acquaintance &entry)
widget * find(const std::string &id, const bool must_be_active) override
See widget::find.
Definition: grid.cpp:655
std::string path
Definition: game_config.cpp:56
Modify, read and display user preferences.
Shows a yes and no button.
Definition: message.hpp:79
void add_hotkey(const hotkey_ptr item)
Add a hotkey to the list of hotkeys.
virtual void set_use_markup(bool use_markup)
bool UI_sound_on()
Definition: general.cpp:631
void set_bell_volume(int vol)
Definition: general.cpp:582
void set_stop_music_in_background(bool ison)
Definition: general.cpp:714
bool animate_map()
Definition: general.cpp:895
void fullscreen_toggle_callback(window &window)
bool show_standing_animations()
Definition: display.cpp:104
void set_animate_map(bool value)
Definition: general.cpp:955
bool chat_timestamping()
Definition: game.cpp:906
std::vector< hotkey::hotkey_ptr > hotkey_list
Definition: hotkey_item.hpp:35
hk_scopes scope
The visibility scope of the command.
Various uncategorised dialogs.
void set_chat_timestamping(bool value)
Definition: game.cpp:910
int idle_anim_rate()
Definition: general.cpp:467
void set_UI_volume(int vol)
Definition: general.cpp:597
const std::string & get_notes() const
Definition: game.hpp:277
auto bind_void(F fcn, P...bindings) -> decltype(std::bind(detail::make_apply(std::function< typename detail::function_base< F >::type >(fcn)), bindings...))
Definition: functional.hpp:94
const std::vector< hotkey_command > & get_hotkey_commands()
returns a container that contains all currently active hotkey_commands.
std::string command
The command is unique.
bool interrupt_when_ally_sighted()
Definition: game.cpp:805
void handle_res_select(window &window)
Special callback functions.
hotkey::hotkey_ptr get_new_binding() const
Definition: hotkey_bind.hpp:33
The user set the widget invisible, that means:
bool stop_music_in_background()
Definition: general.cpp:709
static map_location::DIRECTION s
void set_delete_saves(bool value)
Definition: game.cpp:780
bool music_on()
Definition: general.cpp:683
void add_hotkey_callback(listbox &hotkeys)
int get_value() const override
Inherited from integer_selector.
Definition: slider.hpp:53
size_t i
Definition: function.cpp:933
std::map< std::string, t_string > string_map
Definition: widget.hpp:24
Holds a 2D point.
Definition: point.hpp:23
bool set_UI_sound(bool ison)
Definition: general.cpp:636
grid & add_row(const string_map &item, const int index=-1)
When an item in the list is selected by the user we need to update the state.
Definition: listbox.cpp:68
void set_whisper_friends_only(bool v)
Definition: lobby.cpp:25
Declarations for File-IO.
const grid * get_row_grid(const unsigned row) const
Returns the grid of the wanted row.
Definition: listbox.cpp:239
bool delete_saves()
Definition: game.cpp:785
int w
std::shared_ptr< hotkey_base > hotkey_ptr
Definition: hotkey_item.hpp:30
static int sort(lua_State *L)
Definition: ltablib.cpp:411
const std::string & get_nick() const
Definition: game.hpp:275
const std::string & get_description(const std::string &command)
std::string vgettext(const char *msgid, const utils::string_map &symbols)
void set_autosavemax(int value)
Definition: game.cpp:815
bool grid()
Definition: general.cpp:507
static std::map< PREFERENCE_VIEW, std::pair< int, int > > pef_view_map
Map containing page mappings that can be used to set the initially displayed page of the dialog...
virtual void set_value(const std::string &text)
The set_value is virtual for the password_box class.
void show_transient_error_message(const std::string &message, const std::string &image, const bool message_use_markup)
Shows a transient error message to the user.
void set_resolution_list(menu_button &res_list, CVideo &video)
int sound_volume()
Definition: general.cpp:562
bool show_floating_labels()
Definition: game.cpp:842
bool get_value_bool() const
int font_scaling()
Definition: general.cpp:441
The user sets the widget visible, that means:
std::unique_ptr< widget > swap_child(const std::string &id, widget *w, const bool recurse, widget *new_parent=nullptr)
Exchanges a child in the grid.
Definition: grid.cpp:98
The user sets the widget hidden, that means:
bool find(E event, F functor)
Tests whether an event handler is available.
virtual void post_show(window &) override
Actions to be taken after the window has been shown.
A slider.
Definition: slider.hpp:33
void set_id(const std::string &id)
Definition: widget.cpp:95
bool enable_whiteboard_mode_on_start()
Definition: game.cpp:430
this module manages the cache of images.
Definition: image.cpp:103
bool set_music(bool ison)
Definition: general.cpp:688
void set_value(int value) override
Inherited from integer_selector.
Definition: slider.cpp:82
bool set_turn_bell(bool ison)
Definition: general.cpp:612
bool turbo()
Definition: general.cpp:417
void remove_row(const unsigned row, unsigned count=1)
Removes a row in the listbox.
Definition: listbox.cpp:88
unsigned get_item_count() const
Returns the number of items in the listbox.
Definition: listbox.cpp:133
static const char * name(const std::vector< SDL_Joystick * > &joysticks, const size_t index)
Definition: joystick.cpp:48
virtual void set_active(const bool active) override
See styled_widget::set_active.
Definition: menu_button.cpp:64
void set_values(const std::vector<::config > &values)
Set the available menu options.
int UI_volume()
Definition: general.cpp:592
void register_sorting_option(const int col, const Func &f)
Definition: listbox.hpp:261
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:93
virtual void pre_show(window &window) override
Actions to be taken before showing the window.
void set_skip_ai_moves(bool value)
Definition: game.cpp:755
bool turn_dialog()
Definition: game.cpp:420
void set_animate_water(bool value)
Definition: general.cpp:960
void set_step_size(int step_size)
Definition: slider.cpp:276
void remove_hotkey_callback(listbox &hotkeys)
bool file_exists(const std::string &name)
Returns true if a file or directory with such name already exists.
base class of top level items, the only item which needs to store the final canvases to draw on ...
Definition: window.hpp:62
std::vector< point > get_available_resolutions(const bool include_current=false)
Returns the list of available screen resolutions.
Definition: video.cpp:410
void set_find_in_all_layers(const bool do_find)
void remove_friend_list_entry(listbox &friends_list, text_box &textbox, window &window)
bool skip_ai_moves()
Definition: game.cpp:750
Class for a toggle button.
int music_volume()
Definition: general.cpp:547
static void disable_widget_on_toggle(window &window, widget &w, const std::string &id)
virtual void post_build(window &window) override
Inherited from modal_dialog.
static int index_in_pager_range(const int &first, const stacked_widget &pager)
void on_advanced_prefs_list_select(listbox &tree)
void set_disable_auto_moves(bool value)
Definition: general.cpp:1054
bool save_replays()
Definition: game.cpp:775