The Battle for Wesnoth  1.15.0-dev
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"
25 #include "hotkey/hotkey_item.hpp"
27 #include "preferences/lobby.hpp"
28 #include "preferences/general.hpp"
29 #include "preferences/display.hpp"
30 #include "utils/functional.hpp"
31 #include "utils/general.hpp"
32 #include "video.hpp"
33 
34 // Sub-dialog includes
41 
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 #if BOOST_VERSION >= 106700
67 #include <boost/integer/common_factor_rt.hpp>
68 #else
69 #include <boost/math/common_factor_rt.hpp>
70 #endif
71 
72 namespace gui2
73 {
74 namespace dialogs
75 {
76 namespace
77 {
78 // Helper function to get the main grid in each row of the advanced section
79 // listbox, which contains the value and setter widgets.
80 grid* get_advanced_row_grid(listbox& list, const int selected_row)
81 {
82  return dynamic_cast<grid*>(list.get_row_grid(selected_row)->find("pref_main_grid", false));
83 }
84 
85 template<typename W>
86 void disable_widget_on_toggle(window& window, widget& w, const std::string& id)
87 {
88  find_widget<W>(&window, id, false).set_active(dynamic_cast<selectable_item&>(w).get_value_bool());
89 }
90 
91 // Ensure the specified index is between 0 and one less than the max
92 // number of pager layers (since get_layer_count returns one-past-end).
93 int index_in_pager_range(const int first, const stacked_widget& pager)
94 {
95  return utils::clamp<int>(first, 0, pager.get_layer_count() - 1);
96 }
97 
98 // Helper to make it easier to immediately apply sound toggles immediately.
99 template<bool(*fptr)(bool)>
100 void sound_toggle_on_change(window& window, const std::string& id_to_toggle, widget& w)
101 {
102  (*fptr)(dynamic_cast<selectable_item&>(w).get_value_bool());
103 
104  // Toggle the corresponding slider.
105  disable_widget_on_toggle<slider>(window, w, id_to_toggle);
106 }
107 
108 // Helper to make it easier to immediately apply volume (music, etc) setings on change.
109 template<void(*fptr)(int)>
110 void volume_setter_on_change(widget& w)
111 {
112  (*fptr)(dynamic_cast<integer_selector&>(w).get_value());
113 }
114 
115 } // end anon namespace
116 
117 using namespace preferences;
118 
119 REGISTER_DIALOG(preferences_dialog)
120 
121 preferences_dialog::preferences_dialog(const config& game_cfg, const PREFERENCE_VIEW& initial_view)
122  : resolutions_() // should be populated by set_resolution_list before use
123  , adv_preferences_cfg_()
124  , last_selected_item_(0)
125  , accl_speeds_({0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2, 3, 4, 8, 16})
126  , visible_hotkeys_()
127  , cat_names_()
128  , initial_index_(pef_view_map[initial_view])
129 {
130  for(const config& adv : game_cfg.child_range("advanced_preference")) {
131  adv_preferences_cfg_.push_back(adv);
132  }
133 
134  std::sort(adv_preferences_cfg_.begin(), adv_preferences_cfg_.end(),
135  [](const config& lhs, const config& rhs) {
136  return lhs["name"].t_str().str() < rhs["name"].t_str().str();
137  });
138 
139  for(const auto& name : hotkey::get_category_names()) {
140  // Don't include categories with no hotkeys
141  if(!hotkey::get_hotkeys_by_category(name.first).empty()) {
142  cat_names_[name.first] = t_string(name.second, "wesnoth-lib");
143  }
144  }
145 }
146 
147 // Helper function to refresh resolution list
149 {
150  resolutions_ = video.get_available_resolutions(true);
151 
152  std::vector<config> options;
153  for(const point& res : resolutions_) {
154  config option;
155  option["label"] = formatter() << res.x << font::unicode_multiplication_sign << res.y;
156 
157 #if BOOST_VERSION >= 106700
158  const int div = boost::integer::gcd(res.x, res.y);
159 #else
160  const int div = boost::math::gcd(res.x, res.y);
161 #endif
162 
163  const int x_ratio = res.x / div;
164  const int y_ratio = res.y / div;
165 
166  if(x_ratio <= 10 || y_ratio <= 10) {
167  option["details"] = formatter() << "<span color='#777777'>(" << x_ratio << ':' << y_ratio << ")</span>";
168  }
169 
170  options.push_back(std::move(option));
171  }
172 
173  const unsigned current_res = std::distance(resolutions_.begin(), std::find(resolutions_.begin(), resolutions_.end(),
174  video.current_resolution()));
175 
176  res_list.set_values(options, current_res);
177 }
178 
179 std::map<std::string, string_map> preferences_dialog::get_friends_list_row_data(const acquaintance& entry)
180 {
181  std::map<std::string, string_map> data;
182  string_map item;
183 
184  std::string image = "friend.png";
185  std::string descriptor = _("friend");
186  std::string notes;
187 
188  if(entry.get_status() == "ignore") {
189  image = "ignore.png";
190  descriptor = _("ignored");
191  }
192 
193  if(!entry.get_notes().empty()) {
194  notes = " <small>(" + entry.get_notes() + ")</small>";
195  }
196 
197  item["use_markup"] = "true";
198 
199  item["label"] = "misc/status-" + image;
200  data.emplace("friend_icon", item);
201 
202  item["label"] = entry.get_nick() + notes;
203  data.emplace("friend_name", item);
204 
205  item["label"] = "<small>" + descriptor + "</small>";
206  data.emplace("friend_status", item);
207 
208  return data;
209 }
210 
212 {
213  const int num_friends = get_acquaintances().size();
214  const int sel = list.get_selected_row();
215 
216  if(sel < 0 || sel >= num_friends) {
217  return;
218  }
219 
220  std::map<std::string, acquaintance>::const_iterator who = get_acquaintances().begin();
221  std::advance(who, sel);
222 
223  textbox.set_value(who->second.get_nick() + " " + who->second.get_notes());
224 }
225 
227 {
228  const bool list_empty = list.get_item_count() == 0;
229 
230  if(!list_empty) {
231  list.select_row(std::min(static_cast<int>(list.get_item_count()) - 1, list.get_selected_row()));
232  }
233 
234  find_widget<button>(&window, "remove", false).set_active(!list_empty);
235 
236  find_widget<label>(&window, "no_friends_notice", false).set_visible(
238 }
239 
241 {
242  std::string username = textbox.text();
243  if(username.empty()) {
244  gui2::show_transient_message("", _("No username specified"), "", false, false);
245  return;
246  }
247 
248  std::string reason;
249 
250  std::size_t pos = username.find_first_of(' ');
251  if(pos != std::string::npos) {
252  reason = username.substr(pos + 1);
253  username = username.substr(0, pos);
254  }
255 
256  acquaintance* entry = nullptr;
257  bool added_new;
258 
259  std::tie(entry, added_new) = add_acquaintance(username, (is_friend ? "friend": "ignore"), reason);
260 
261  if(!entry) {
262  gui2::show_transient_message(_("Error"), _("Invalid username"), "", false, false);
263  return;
264  }
265 
266  textbox.clear();
267 
268  listbox& list = find_widget<listbox>(&window, "friends_list", false);
269 
270  //
271  // If this is a new entry, just add a new row. If it's not, we find the relevant
272  // row, remove it, and add a new row with the updated data. Should probably come
273  // up with a more elegant way to do this... the only reason I'm using the remove
274  // -and-replace method is to prevent any issues with the widgets' layout sizes.
275  //
276  if(added_new) {
277  list.add_row(get_friends_list_row_data(*entry));
278  } else {
279  for(unsigned i = 0; i < list.get_item_count(); ++i) {
280  grid* row_grid = list.get_row_grid(i);
281 
282  if(find_widget<label>(row_grid, "friend_name", false).get_label() == entry->get_nick()) {
283  list.remove_row(i);
284  list.add_row(get_friends_list_row_data(*entry), i);
285 
286  break;
287  }
288  }
289  }
290 
291  update_friends_list_controls(window, list);
292 }
293 
295 {
296  const int selected_row = std::max(0, friends_list.get_selected_row());
297 
298  std::map<std::string, acquaintance>::const_iterator who = get_acquaintances().begin();
299  std::advance(who, selected_row);
300 
301  const std::string to_remove = !textbox.text().empty() ? textbox.text() : who->second.get_nick();
302 
303  if(to_remove.empty()) {
304  gui2::show_transient_message("", _("No username specified"), "", false, false);
305  return;
306  }
307 
308  if(!remove_acquaintance(to_remove)) {
309  gui2::show_transient_error_message(_("Not on friends or ignore lists"));
310  return;
311  }
312 
313  textbox.clear();
314 
315  listbox& list = find_widget<listbox>(&window, "friends_list", false);
316  list.remove_row(selected_row);
317 
318  update_friends_list_controls(window, list);
319 }
320 
321 template<bool(*toggle_getter)(), bool(*toggle_setter)(bool), int(*vol_getter)(), void(*vol_setter)(int)>
322 void preferences_dialog::initialize_sound_option_group(const std::string& id_suffix)
323 {
324  const std::string toggle_widget_id = "sound_toggle_" + id_suffix;
325  const std::string volume_widget_id = "sound_volume_" + id_suffix;
326 
327  window& window = *get_window();
328 
329  // Set up the toggle. We utilize field_bool's callback-on-changed mechanism instead
330  // of manually registering the callback. Since we want the effects to apply immediately,
331  // the callback the setter callback is duplicated in the on-change callback. The field
332  // class could possibly use some reworking to make this less redundant, but for now it
333  // works well enough.
334  register_bool(toggle_widget_id, true, toggle_getter, std::bind(toggle_setter, _1),
335  std::bind(sound_toggle_on_change<toggle_setter>, std::ref(window), volume_widget_id, _1), true);
336 
337  // Set up the volume slider. integer_field doesn't have a callback-on-changed mechanism.
338  // To add one would either mean adding it to the base field class or make it a proper
339  // class of is own.
340  register_integer(volume_widget_id, true, vol_getter, vol_setter);
341 
342  // Callback to actually immediately apply the volume effect.
343  connect_signal_notify_modified(find_widget<slider>(&window, volume_widget_id, false),
344  std::bind(volume_setter_on_change<vol_setter>, _1));
345 }
346 
347 /**
348  * Sets up states and callbacks for each of the widgets
349  */
351 {
352  //
353  // GENERAL PANEL
354  //
355 
356  /* SCROLL SPEED */
357  register_integer("scroll_speed", true,
359 
360  /* ACCELERATED SPEED */
361  register_bool("turbo_toggle", true, turbo, set_turbo,
362  [&](widget& w) { disable_widget_on_toggle<slider>(window, w, "turbo_slider"); }, true);
363 
364  const auto accl_load = [this]()->int {
365  return std::distance(accl_speeds_.begin(), std::find(accl_speeds_.begin(), accl_speeds_.end(), turbo_speed()));
366  };
367 
368  const auto accl_save = [this](int i) {
369  set_turbo_speed(accl_speeds_[i]);
370  };
371 
372  register_integer("turbo_slider", true,
373  accl_load, accl_save);
374 
375  // Set the value label transform function.
376  find_widget<slider>(&window, "turbo_slider", false).set_value_labels(
377  [this](int pos, int /*max*/)->t_string { return lexical_cast<std::string>(accl_speeds_[pos]); }
378  );
379 
380  /* SKIP AI MOVES */
381  register_bool("skip_ai_moves", true,
383 
384  /* DISABLE AUTO MOVES */
385  register_bool("disable_auto_moves", true,
387 
388  /* TURN DIALOG */
389  register_bool("show_turn_dialog", true,
391 
392  /* ENABLE PLANNING MODE */
393  register_bool("whiteboard_on_start", true,
395 
396  /* HIDE ALLY PLANS */
397  register_bool("whiteboard_hide_allies", true,
399 
400  /* INTERRUPT ON SIGHTING */
401  register_bool("interrupt_move_when_ally_sighted", true,
403 
404  /* SAVE REPLAYS */
405  register_bool("save_replays", true,
407 
408  /* DELETE AUTOSAVES */
409  register_bool("delete_saves", true,
411 
412  /* MAX AUTO SAVES */
413  register_integer("max_saves_slider", true,
415 
416  /* CACHE MANAGE */
417  connect_signal_mouse_left_click(find_widget<button>(&window, "cachemg", false),
418  std::bind(&gui2::dialogs::game_cache_options::display<>));
419 
420  //
421  // DISPLAY PANEL
422  //
423 
424  /* FULLSCREEN TOGGLE */
425  toggle_button& toggle_fullscreen =
426  find_widget<toggle_button>(&window, "fullscreen", false);
427 
428  toggle_fullscreen.set_value(fullscreen());
429 
430  // We bind a special callback function, so setup_single_toggle() is not used
431  connect_signal_mouse_left_click(toggle_fullscreen, std::bind(
433  this, std::ref(window)));
434 
435  /* SET RESOLUTION */
436  menu_button& res_list = find_widget<menu_button>(&window, "resolution_set", false);
437 
438  res_list.set_use_markup(true);
439  res_list.set_active(!fullscreen());
440 
441  set_resolution_list(res_list, window.video());
442 
443  res_list.connect_click_handler(
445  this, std::ref(window)));
446 
447  /* SHOW FLOATING LABELS */
448  register_bool("show_floating_labels", true,
450 
451  /* SHOW TEAM COLORS */
452  register_bool("show_ellipses", true,
454 
455  /* SHOW GRID */
456  register_bool("show_grid", true,
458 
459  /* ANIMATE MAP */
460  register_bool("animate_terrains", true, animate_map, set_animate_map,
461  [&](widget& w) { disable_widget_on_toggle<toggle_button>(window, w, "animate_water"); }, true);
462 
463  /* ANIMATE WATER */
464  register_bool("animate_water", true,
466 
467  /* SHOW UNIT STANDING ANIMS */
468  register_bool("animate_units_standing", true,
470 
471  /* SHOW UNIT IDLE ANIMS */
472  register_bool("animate_units_idle", true, idle_anim, set_idle_anim,
473  [&](widget& w) { disable_widget_on_toggle<slider>(window, w, "idle_anim_frequency"); });
474 
475  register_integer("idle_anim_frequency", true,
477 
478  /* FONT SCALING */
479  register_integer("scaling_slider", true,
481 
482  /* SELECT THEME */
484  find_widget<button>(&window, "choose_theme", false),
485  std::bind(&show_theme_dialog));
486 
487  //
488  // SOUND PANEL
489  //
490 
491  /* SOUND FX */
492  initialize_sound_option_group<sound_on, set_sound, sound_volume, set_sound_volume>("sfx");
493 
494  /* MUSIC */
495  initialize_sound_option_group<music_on, set_music, music_volume, set_music_volume>("music");
496 
497  register_bool("sound_toggle_stop_music_in_background", true,
499 
500  /* TURN BELL */
501  initialize_sound_option_group<turn_bell, set_turn_bell, bell_volume, set_bell_volume>("bell");
502 
503  /* UI FX */
504  initialize_sound_option_group<UI_sound_on, set_UI_sound, UI_volume, set_UI_volume>("uisfx");
505 
506  //
507  // MULTIPLAYER PANEL
508  //
509 
510  /* CHAT LINES */
511  register_integer("chat_lines", true,
513 
514  /* CHAT TIMESTAMPPING */
515  register_bool("chat_timestamps", true,
517 
518  /* SAVE PASSWORD */
519  register_bool("remember_password", true,
521 
522  /* WHISPERS FROM FRIENDS ONLY */
523  register_bool("lobby_whisper_friends_only", true,
525 
526  /* LOBBY JOIN NOTIFICATIONS */
527  lobby_joins_group.add_member(find_widget<toggle_button>(&window, "lobby_joins_none", false, true), SHOW_NONE);
528  lobby_joins_group.add_member(find_widget<toggle_button>(&window, "lobby_joins_friends", false, true), SHOW_FRIENDS);
529  lobby_joins_group.add_member(find_widget<toggle_button>(&window, "lobby_joins_all", false, true), SHOW_ALL);
530 
531  lobby_joins_group.set_member_states(static_cast<LOBBY_JOINS>(lobby_joins()));
532 
533  lobby_joins_group.set_callback_on_value_change([&](widget&) {
534  _set_lobby_joins(lobby_joins_group.get_active_member_value());
535  });
536 
537  /* FRIENDS LIST */
538  listbox& friends_list = find_widget<listbox>(&window, "friends_list", false);
539 
540  friends_list.clear();
541 
542  for(const auto& entry : get_acquaintances()) {
543  friends_list.add_row(get_friends_list_row_data(entry.second));
544  }
545 
546  update_friends_list_controls(window, friends_list);
547 
548  text_box& textbox = find_widget<text_box>(&window, "friend_name_box", false);
549 
551  find_widget<button>(&window, "add_friend", false), std::bind(
553  this, true,
554  std::ref(textbox),
555  std::ref(window)));
556 
558  find_widget<button>(&window, "add_ignored", false), std::bind(
560  this, false,
561  std::ref(textbox),
562  std::ref(window)));
563 
565  find_widget<button>(&window, "remove", false), std::bind(
567  this,
568  std::ref(friends_list),
569  std::ref(textbox),
570  std::ref(window)));
571 
572  connect_signal_notify_modified(friends_list, std::bind(
574  this,
575  std::ref(friends_list),
576  std::ref(textbox)));
577 
578  /* ALERTS */
580  find_widget<button>(&window, "mp_alerts", false),
581  std::bind(&gui2::dialogs::mp_alerts_options::display<>));
582 
583  /* SET WESNOTHD PATH */
585  find_widget<button>(&window, "mp_wesnothd", false), std::bind(
587 
588 
589  //
590  // ADVANCED PANEL
591  //
592 
593  listbox& advanced = find_widget<listbox>(&window, "advanced_prefs", false);
594 
595  std::map<std::string, string_map> row_data;
596 
597  for(const config& option : adv_preferences_cfg_) {
598  // Details about the current option
599  ADVANCED_PREF_TYPE pref_type;
600  try {
601  pref_type = ADVANCED_PREF_TYPE::string_to_enum(option["type"].str());
602  } catch(const bad_enum_cast&) {
603  continue;
604  }
605 
606  const std::string& pref_name = option["field"].str();
607 
608  row_data["pref_name"]["label"] = option["name"];
609  advanced.add_row(row_data);
610 
611  const int this_row = advanced.get_item_count() - 1;
612 
613  // Get the main grid from each row
614  grid* main_grid = get_advanced_row_grid(advanced, this_row);
615  assert(main_grid);
616 
617  grid& details_grid = find_widget<grid>(main_grid, "prefs_setter_grid", false);
619 
620  // The toggle widget for toggle-type options (hidden for other types)
621  toggle_button& toggle_box = find_widget<toggle_button>(main_grid, "value_toggle", false);
623 
624  if(!option["description"].empty()) {
625  find_widget<styled_widget>(main_grid, "description", false).set_label(option["description"]);
626  }
627 
628  switch(pref_type.v) {
629  case ADVANCED_PREF_TYPE::TOGGLE: {
630  //main_grid->remove_child("setter");
631 
633  toggle_box.set_value(get(pref_name, option["default"].to_bool()));
634 
635  // We need to bind a lambda here since preferences::set is overloaded.
636  // A lambda alone would be more verbose because it'd need to specify all the parameters.
637  connect_signal_mouse_left_click(toggle_box, std::bind(
638  [&, pref_name]() { set(pref_name, toggle_box.get_value_bool()); }
639  ));
640 
641  gui2::bind_status_label<toggle_button>(
642  main_grid, "value_toggle", default_status_value_getter<toggle_button>, "value");
643 
644  break;
645  }
646 
647  case ADVANCED_PREF_TYPE::SLIDER: {
648  slider* setter_widget = build_single_widget_instance<slider>("slider", config {"definition", "minimal"});
649  setter_widget->set_id("setter");
650  // Maximum must be set first or this will assert
651  setter_widget->set_value_range(option["min"].to_int(), option["max"].to_int());
652  setter_widget->set_step_size(option["step"].to_int(1));
653 
654  details_grid.swap_child("setter", setter_widget, true);
655 
656  slider& slide = find_widget<slider>(&details_grid, "setter", false);
657 
658  slide.set_value(lexical_cast_default<int>(get(pref_name), option["default"].to_int()));
659 
660  // We need to bind a lambda here since preferences::set is overloaded.
661  // A lambda alone would be more verbose because it'd need to specify all the parameters.
662  connect_signal_notify_modified(slide, std::bind(
663  [&, pref_name]() { set(pref_name, slide.get_value()); }
664  ));
665 
666  gui2::bind_status_label<slider>(main_grid, "setter", default_status_value_getter<slider>, "value");
667 
668  break;
669  }
670 
671  case ADVANCED_PREF_TYPE::COMBO: {
672  std::vector<config> menu_data;
673  std::vector<std::string> option_ids;
674 
675  for(const config& choice : option.child_range("option")) {
676  config menu_item;
677  menu_item["label"] = choice["name"];
678  if(choice.has_attribute("description")) {
679  menu_item["details"] = std::string("<span color='#777'>") + choice["description"] + "</span>";
680  }
681  menu_data.push_back(menu_item);
682  option_ids.push_back(choice["id"]);
683  }
684 
685  // Attempt to find an initial selection
686  int selected = std::distance(option_ids.begin(), std::find(option_ids.begin(), option_ids.end(),
687  get(pref_name, option["default"].str())
688  ));
689 
690  // If the saved option value was invalid, reset selection to 0.
691  if(selected < 0 || selected >= static_cast<int>(option_ids.size())) {
692  selected = 0;
693  }
694 
695  menu_button* setter_widget = build_single_widget_instance<menu_button>("menu_button");
696  setter_widget->set_id("setter");
697 
698  details_grid.swap_child("setter", setter_widget, true);
699 
700  menu_button& menu = find_widget<menu_button>(&details_grid, "setter", false);
701 
702  menu.set_use_markup(true);
703  menu.set_values(menu_data, selected);
704 
705  // We need to bind a lambda here since preferences::set is overloaded.
706  // A lambda alone would be more verbose because it'd need to specify all the parameters.
708  std::bind([=](widget& w) { set(pref_name, option_ids[dynamic_cast<menu_button&>(w).get_value()]); }, _1));
709 
710  gui2::bind_status_label<menu_button>(main_grid, "setter", [](menu_button& m)->std::string {
711  return m.get_value_string();
712  }, "value");
713 
714  break;
715  }
716 
717  case ADVANCED_PREF_TYPE::SPECIAL: {
718  //main_grid->remove_child("setter");
719 
720  image* value_widget = build_single_widget_instance<image>("image");
721  value_widget->set_label("icons/arrows/arrows_blank_right_25.png~CROP(3,3,18,18)");
722 
723  main_grid->swap_child("value", value_widget, true);
724 
725  break;
726  }
727  }
728  }
729 
730  connect_signal_notify_modified(advanced, std::bind(
732  this,
733  std::ref(advanced)));
734 
735  on_advanced_prefs_list_select(advanced);
736 
737  //
738  // HOTKEYS PANEL
739  //
740 
741  std::vector<config> hotkey_category_entries;
742  for(const auto& name : cat_names_) {
743  hotkey_category_entries.emplace_back("label", name.second, "checkbox", false);
744  }
745 
746  multimenu_button& hotkey_menu = find_widget<multimenu_button>(&window, "hotkey_category_menu", false);
747 
748  hotkey_menu.set_values(hotkey_category_entries);
749 
750  connect_signal_notify_modified(hotkey_menu,
751  std::bind(&preferences_dialog::hotkey_type_filter_callback, this, std::ref(window)));
752 
753  listbox& hotkey_list = setup_hotkey_list(window);
754 
755  // Action column
756  hotkey_list.register_translatable_sorting_option(0, [this](const int i) { return visible_hotkeys_[i]->description.str(); });
757 
758  // Hotkey column
759  hotkey_list.register_sorting_option(1, [this](const int i) { return hotkey::get_names(visible_hotkeys_[i]->command); });
760 
761  // Scope columns
762  hotkey_list.register_sorting_option(2, [this](const int i) { return !visible_hotkeys_[i]->scope[hotkey::SCOPE_GAME]; });
763  hotkey_list.register_sorting_option(3, [this](const int i) { return !visible_hotkeys_[i]->scope[hotkey::SCOPE_EDITOR]; });
764  hotkey_list.register_sorting_option(4, [this](const int i) { return !visible_hotkeys_[i]->scope[hotkey::SCOPE_MAIN_MENU]; });
765 
766  hotkey_list.set_active_sorting_option({0, listbox::SORT_ASCENDING}, true);
767 
769  find_widget<button>(&window, "btn_add_hotkey", false), std::bind(
771  this,
772  std::ref(hotkey_list)));
773 
775  find_widget<button>(&window, "btn_clear_hotkey", false), std::bind(
777  this,
778  std::ref(hotkey_list)));
779 
781  find_widget<button>(&window, "btn_reset_hotkeys", false), std::bind(
783  this,
784  std::ref(window)));
785 }
786 
788 {
789  const std::string& default_icon = "misc/empty.png~CROP(0,0,15,15)";
790 
791  std::map<std::string, string_map> row_data;
792 
793  t_string& row_icon = row_data["img_icon"]["label"];
794  t_string& row_action = row_data["lbl_desc"]["label"];
795  t_string& row_hotkey = row_data["lbl_hotkey"]["label"];
796 
797  t_string& row_is_g = row_data["lbl_is_game"]["label"];
798  t_string& row_is_g_markup = row_data["lbl_is_game"]["use_markup"];
799  t_string& row_is_e = row_data["lbl_is_editor"]["label"];
800  t_string& row_is_e_markup = row_data["lbl_is_editor"]["use_markup"];
801  t_string& row_is_t = row_data["lbl_is_titlescreen"]["label"];
802  t_string& row_is_t_markup = row_data["lbl_is_titlescreen"]["use_markup"];
803 
804  listbox& hotkey_list = find_widget<listbox>(&window, "list_hotkeys", false);
805 
806  hotkey_list.clear();
807  visible_hotkeys_.clear();
808 
809  std::string text_feature_on = "<span color='#0f0'>" + _("&#9679;") + "</span>";
810 
811  for(const auto& hotkey_item : hotkey::get_hotkey_commands()) {
812  if(hotkey_item.hidden) {
813  continue;
814  }
815  visible_hotkeys_.push_back(&hotkey_item);
816 
817  if(filesystem::file_exists(game_config::path + "/images/icons/action/" + hotkey_item.command + "_25.png")) {
818  row_icon = "icons/action/" + hotkey_item.command + "_25.png~CROP(3,3,18,18)";
819  } else {
820  row_icon = default_icon;
821  }
822 
823  row_action = hotkey_item.description;
824  row_hotkey = hotkey::get_names(hotkey_item.command);
825 
826  row_is_g = hotkey_item.scope[hotkey::SCOPE_GAME] ? text_feature_on : "";
827  row_is_g_markup = "true";
828  row_is_e = hotkey_item.scope[hotkey::SCOPE_EDITOR] ? text_feature_on : "";
829  row_is_e_markup = "true";
830  row_is_t = hotkey_item.scope[hotkey::SCOPE_MAIN_MENU] ? text_feature_on : "";
831  row_is_t_markup = "true";
832 
833  hotkey_list.add_row(row_data);
834  }
835 
836  return hotkey_list;
837 }
838 
840 {
841  int row_number = hotkeys.get_selected_row();
842  const hotkey::hotkey_command& hotkey_item = *visible_hotkeys_[row_number];
843 
844  gui2::dialogs::hotkey_bind bind_dlg(hotkey_item.command);
845  bind_dlg.show();
846 
847  hotkey::hotkey_ptr newhk = bind_dlg.get_new_binding();
848  hotkey::hotkey_ptr oldhk;
849 
850  // only if not cancelled.
851  if(newhk.get() == nullptr) {
852  return;
853  }
854 
855  for(const hotkey::hotkey_ptr& hk : hotkey::get_hotkeys()) {
856  if(!hk->is_disabled() && newhk->bindings_equal(hk)) {
857  oldhk = hk;
858  }
859  }
860 
861  hotkey::scope_changer scope_restorer;
862  hotkey::set_active_scopes(hotkey_item.scope);
863 
864  if(oldhk && oldhk->get_command() == hotkey_item.command) {
865  return;
866  }
867 
868  if(oldhk && oldhk->get_command() != "null") {
869  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>”?", {
870  {"hotkey_sequence", oldhk->get_name()},
871  {"old_hotkey_action", hotkey::get_description(oldhk->get_command())},
872  {"new_hotkey_action", hotkey::get_description(newhk->get_command())}
873  });
874 
875  const int res = gui2::show_message(_("Reassign Hotkey"), text, gui2::dialogs::message::yes_no_buttons, true);
876  if(res != gui2::retval::OK) {
877  return;
878  }
879  }
880 
881  hotkey::add_hotkey(newhk);
882 
883  // We need to recalculate all hotkey names in because we might have removed a hotkey from another command.
884  for(std::size_t i = 0; i < hotkeys.get_item_count(); ++i) {
885  const hotkey::hotkey_command& hotkey_item_row = *visible_hotkeys_[i];
886  find_widget<label>(hotkeys.get_row_grid(i), "lbl_hotkey", false).set_label(hotkey::get_names(hotkey_item_row.command));
887  }
888 }
889 
891 {
892  gui2::show_transient_message(_("Hotkeys Reset"), _("All hotkeys have been reset to their default values."),
893  std::string(), false, false);
894 
895  clear_hotkeys();
896 
897  // Set up the list again and reselect the default sorting option.
898  listbox& hotkey_list = setup_hotkey_list(window);
899  hotkey_list.set_active_sorting_option({0, listbox::SORT_ASCENDING}, true);
900 
901  find_widget<multimenu_button>(&window, "hotkey_category_menu", false).reset_toggle_states();
902 }
903 
905 {
906  int row_number = hotkeys.get_selected_row();
907  const hotkey::hotkey_command& hotkey_item = *visible_hotkeys_[row_number];
908  hotkey::clear_hotkeys(hotkey_item.command);
909  find_widget<label>(hotkeys.get_row_grid(row_number), "lbl_hotkey", false).set_label(hotkey::get_names(hotkey_item.command));
910 }
911 
913 {
914  const multimenu_button& hotkey_menu = find_widget<const multimenu_button>(&window, "hotkey_category_menu", false);
915 
916  boost::dynamic_bitset<> toggle_states = hotkey_menu.get_toggle_states();
917  boost::dynamic_bitset<> res(visible_hotkeys_.size());
918 
919  if(!toggle_states.none()) {
920  for(std::size_t h = 0; h < visible_hotkeys_.size(); ++h) {
921  unsigned index = 0;
922 
923  for(const auto& name : cat_names_) {
924  if(visible_hotkeys_[h]->category == name.first) {
925  break;
926  } else {
927  ++index;
928  }
929  }
930 
931  if(index < toggle_states.size()) {
932  res[h] = toggle_states[index];
933  } else {
934  res[h] = false;
935  }
936  }
937  } else {
938  // Nothing selected. It means that *all* categories are shown.
939  res = ~res;
940  }
941 
942  find_widget<listbox>(&window, "list_hotkeys", false).set_row_shown(res);
943 }
944 
946 {
947  const int selected_row = list.get_selected_row();
948 
949  const ADVANCED_PREF_TYPE& selected_type = ADVANCED_PREF_TYPE::string_to_enum(
950  adv_preferences_cfg_[selected_row]["type"].str());
951 
952  const std::string& selected_field = adv_preferences_cfg_[selected_row]["field"].str();
953 
954  if(selected_type == ADVANCED_PREF_TYPE::SPECIAL) {
955  if(selected_field == "advanced_graphic_options") {
956  gui2::dialogs::advanced_graphics_options::display();
957  } else if(selected_field == "logging") {
958  gui2::dialogs::log_settings::display();
959  } else if(selected_field == "orb_color") {
960  gui2::dialogs::select_orb_colors::display();
961  } else {
962  WRN_GUI_L << "Invalid or unimplemented custom advanced prefs option: " << selected_field << "\n";
963  }
964 
965  // Add more options here as needed
966  }
967 
968  const bool has_description = !adv_preferences_cfg_[selected_row]["description"].empty();
969 
970  if(has_description || (selected_type != ADVANCED_PREF_TYPE::SPECIAL && selected_type != ADVANCED_PREF_TYPE::TOGGLE)) {
971  find_widget<widget>(get_advanced_row_grid(list, selected_row), "prefs_setter_grid", false)
972  .set_visible(widget::visibility::visible);
973  }
974 
975  if(last_selected_item_ != selected_row) {
976  find_widget<widget>(get_advanced_row_grid(list, last_selected_item_), "prefs_setter_grid", false)
977  .set_visible(widget::visibility::invisible);
978 
979  last_selected_item_ = selected_row;
980  }
981 }
982 
984 {
985  //
986  // MULTIPLAYER TABS
987  //
989  std::bind(&preferences_dialog::on_tab_select, this, std::ref(window)));
990 }
991 
993 {
994  set_always_save_fields(true);
995 
996  //
997  // Status labels
998  // These need to be set here in pre_show, once the fields are initialized. For some reason, this
999  // is not the case for those in Advanced
1000  //
1001 
1002  gui2::bind_status_label<slider>(&window, "max_saves_slider", [](slider& s)->std::string {
1003  return s.get_value() == INFINITE_AUTO_SAVES ? _("∞") : s.get_value_label().str();
1004  });
1005 
1006  gui2::bind_status_label<slider>(&window, "turbo_slider");
1007 
1008  gui2::bind_status_label<slider>(&window, "scaling_slider", [](slider& s)->std::string {
1009  return s.get_value_label() + "%";
1010  });
1011 
1012  listbox& selector = find_widget<listbox>(&window, "selector", false);
1013  stacked_widget& pager = find_widget<stacked_widget>(&window, "pager", false);
1014 
1015  pager.set_find_in_all_layers(true);
1016 
1018  std::bind(&preferences_dialog::on_page_select, this, std::ref(window)));
1019 
1020  window.keyboard_capture(&selector);
1021 
1022  VALIDATE(selector.get_item_count() == pager.get_layer_count(),
1023  "The preferences pager and its selector listbox do not have the same number of items.");
1024 
1025  const int main_index = index_in_pager_range(initial_index_.first, pager);
1026 
1027  // Loops through each pager layer and checks if it has both a tab bar
1028  // and stack. If so, it initializes the options for the former and
1029  // selects the specified layer of the latter.
1030  for(unsigned int i = 0; i < pager.get_layer_count(); ++i) {
1031  listbox* tab_selector = find_widget<listbox>(
1032  pager.get_layer_grid(i), "tab_selector", false, false);
1033 
1034  stacked_widget* tab_pager = find_widget<stacked_widget>(
1035  pager.get_layer_grid(i), "tab_pager", false, false);
1036 
1037  if(tab_pager && tab_selector) {
1038  const int ii = static_cast<int>(i);
1039  const int tab_index = index_in_pager_range(initial_index_.second, *tab_pager);
1040  const int to_select = (ii == main_index ? tab_index : 0);
1041 
1042  // Initialize tabs for this page
1043  initialize_tabs(window, *tab_selector);
1044 
1045  tab_selector->select_row(to_select);
1046  tab_pager->select_layer(to_select);
1047  }
1048  }
1049 
1050  // Finally, select the initial main page
1051  selector.select_row(main_index);
1052  pager.select_layer(main_index);
1053 }
1054 
1055 void preferences_dialog::set_visible_page(window& window, unsigned int page, const std::string& pager_id)
1056 {
1057  find_widget<stacked_widget>(&window, pager_id, false).select_layer(page);
1058 }
1059 
1060 // Special fullsceen callback
1062 {
1063  const bool ison = find_widget<toggle_button>(&window, "fullscreen", false).get_value_bool();
1064  window.video().set_fullscreen(ison);
1065 
1066  menu_button& res_list = find_widget<menu_button>(&window, "resolution_set", false);
1067 
1068  set_resolution_list(res_list, window.video());
1069  res_list.set_active(!ison);
1070 }
1071 
1073 {
1074  menu_button& res_list = find_widget<menu_button>(&window, "resolution_set", false);
1075 
1076  if(window.video().set_resolution(resolutions_[res_list.get_value()])) {
1077  set_resolution_list(res_list, window.video());
1078  }
1079 }
1080 
1082 {
1083  const int selected_row =
1084  std::max(0, find_widget<listbox>(&window, "selector", false).get_selected_row());
1085  set_visible_page(window, static_cast<unsigned int>(selected_row), "pager");
1086 }
1087 
1089 {
1090  const int selected_row =
1091  std::max(0, find_widget<listbox>(&window, "tab_selector", false).get_selected_row());
1092  set_visible_page(window, static_cast<unsigned int>(selected_row), "tab_pager");
1093 }
1094 
1096 {
1097  save_hotkeys();
1098 
1099  // Save new prefs to disk. This also happens on app close, but doing
1100  // it here too ensures nothing is lost in case of, say, a crash.
1102 }
1103 
1104 } // namespace dialogs
1105 } // namespace gui2
bool disable_auto_moves()
Definition: general.cpp:911
void initialize_tabs(window &window, listbox &selector)
Initializers.
bool show_theme_dialog()
Definition: display.cpp:116
void set_turbo(bool ison)
Definition: display.cpp:52
void on_page_select(window &window)
Callback for selection changes.
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:624
void set_hide_whiteboard(bool value)
Definition: game.cpp:444
int autosavemax()
Definition: game.cpp:809
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:150
void set_grid(bool ison)
Definition: display.cpp:70
point current_resolution()
Definition: video.cpp:416
bool remember_password()
void set_value(unsigned selected, bool fire_event=false) override
Inherited from selectable_item.
void set_show_standing_animations(bool value)
Definition: display.cpp:107
void write_preferences()
Definition: general.cpp:156
void connect_click_handler(const event::signal_function &signal)
Inherited from clickable_item.
Definition: menu_button.hpp:58
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)
static bool file_exists(const fs::path &fpath)
Definition: filesystem.cpp:300
void set_remember_password(bool remember)
void set_show_floating_labels(bool value)
Definition: game.cpp:846
int lobby_joins()
Definition: game.cpp:347
New lexcical_cast header.
void show_wesnothd_server_search()
Definition: display.cpp:150
Definition: video.hpp:36
void default_hotkey_callback(window &window)
void set_scroll_speed(const int new_speed)
Definition: general.cpp:731
void update_friends_list_controls(window &window, listbox &list)
const std::map< std::string, acquaintance > & get_acquaintances()
Definition: game.cpp:229
const int INFINITE_AUTO_SAVES
Definition: game.hpp:189
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:366
void set_show_side_colors(bool value)
Definition: game.cpp:759
int scroll_speed()
Definition: general.cpp:723
#define WRN_GUI_L
Definition: log.hpp:59
Base class for all widgets.
Definition: widget.hpp:47
bool hide_whiteboard()
Definition: game.cpp:439
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:362
void set_chat_lines(int lines)
Definition: game.cpp:918
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:913
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:616
hotkey::hotkey_ptr get_new_binding() const
Definition: hotkey_bind.hpp:33
#define h
double turbo_speed()
Definition: general.cpp:431
int get_selected_row() const
Returns the first selected row.
Definition: listbox.cpp:272
bool animate_water()
Definition: general.cpp:762
Simple push button.
std::list< HOTKEY_COMMAND > get_hotkeys_by_category(HOTKEY_CATEGORY category)
Returns a list of all the hotkeys belonging to the given category.
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:764
-file util.hpp
bool remove_acquaintance(const std::string &nick)
Definition: game.cpp:271
void set_interrupt_when_ally_sighted(bool value)
Definition: game.cpp:799
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:250
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 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
Base container class.
Definition: grid.hpp:30
const config & options()
Definition: game.cpp:569
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:424
static UNUSEDNOWARN std::string _(const char *str)
Definition: gettext.hpp:89
void set_value_range(int min_value, int max_value)
Definition: slider.cpp:254
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:179
void set_save_replays(bool value)
Definition: game.cpp:769
bool is_friend(const std::string &nick)
Definition: game.cpp:293
void set_idle_anim_rate(int rate)
Definition: display.cpp:94
#define VALIDATE(cond, message)
The macro to use for the validation of WML.
This file contains the settings handling of the widget library.
const std::string & get_nick() const
Definition: game.hpp:273
void set_values(const std::vector<::config > &values, int selected=0)
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:456
std::pair< preferences::acquaintance *, bool > add_acquaintance(const std::string &nick, const std::string &mode, const std::string &notes)
Definition: game.cpp:249
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:164
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)
Shows a transient message to the user.
bool fullscreen()
Definition: general.cpp:396
void set_enable_whiteboard_mode_on_start(bool value)
Definition: game.cpp:434
void set_turbo_speed(double speed)
Definition: display.cpp:61
void set_font_scaling(int scale)
Definition: general.cpp:447
std::string selected
const std::string unicode_multiplication_sign
Definition: constants.cpp:41
void set_idle_anim(bool ison)
Definition: display.cpp:86
std::map< std::string, string_map > get_friends_list_row_data(const preferences::acquaintance &entry)
std::string path
Definition: game_config.cpp:39
Modify, read and display user preferences.
Shows a yes and no button.
Definition: message.hpp:79
unsigned get_item_count() const
Returns the number of items in the listbox.
Definition: listbox.cpp:133
void add_hotkey(const hotkey_ptr item)
Add a hotkey to the list of hotkeys.
virtual void set_use_markup(bool use_markup)
void set_stop_music_in_background(bool ison)
Definition: general.cpp:714
bool animate_map()
Definition: general.cpp:757
void fullscreen_toggle_callback(window &window)
void hotkey_type_filter_callback(window &window) const
bool show_standing_animations()
Definition: display.cpp:102
void set_animate_map(bool value)
Definition: general.cpp:817
bool chat_timestamping()
Definition: game.cpp:905
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:909
int idle_anim_rate()
Definition: general.cpp:467
boost::dynamic_bitset get_toggle_states() const
Get the current state of the menu options.
std::size_t i
Definition: function.cpp:933
const category_name_map_t & get_category_names()
Returns the map of hotkey categories and their display names.
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:804
void handle_res_select(window &window)
Special callback functions.
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:779
void initialize_sound_option_group(const std::string &id_suffix)
void add_hotkey_callback(listbox &hotkeys)
int get_value() const override
Inherited from integer_selector.
Definition: slider.hpp:53
std::map< std::string, t_string > string_map
Definition: widget.hpp:24
Holds a 2D point.
Definition: point.hpp:23
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.
bool delete_saves()
Definition: game.cpp:784
int w
std::shared_ptr< hotkey_base > hotkey_ptr
Definition: hotkey_item.hpp:30
const std::string & get_status() const
Definition: game.hpp:274
std::size_t index(const std::string &str, const std::size_t index)
Codepoint index corresponding to the nth character in a UTF-8 string.
Definition: unicode.cpp:71
static int sort(lua_State *L)
Definition: ltablib.cpp:411
#define VGETTEXT(msgid,...)
const std::string & get_notes() const
Definition: game.hpp:275
const std::string & get_description(const std::string &command)
void set_autosavemax(int value)
Definition: game.cpp:814
bool grid()
Definition: general.cpp:507
const grid * get_row_grid(const unsigned row) const
Returns the grid of the wanted row.
Definition: listbox.cpp:237
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)
bool show_floating_labels()
Definition: game.cpp:841
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:
const std::string & text() const
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:94
bool enable_whiteboard_mode_on_start()
Definition: game.cpp:429
this module manages the cache of images.
Definition: image.cpp:102
void set_value(int value) override
Inherited from integer_selector.
Definition: slider.cpp:86
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
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.
Dialog was closed with the OK button.
Definition: retval.hpp:34
void register_sorting_option(const int col, const Func &f)
Definition: listbox.hpp:268
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:68
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:754
bool turn_dialog()
Definition: game.cpp:419
void set_animate_water(bool value)
Definition: general.cpp:822
void set_step_size(int step_size)
Definition: slider.cpp:285
void remove_hotkey_callback(listbox &hotkeys)
base class of top level items, the only item which needs to store the final canvases to draw on ...
Definition: window.hpp:63
std::vector< point > get_available_resolutions(const bool include_current=false)
Returns the list of available screen resolutions.
Definition: video.cpp:358
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:749
Class for a toggle button.
virtual void post_build(window &window) override
Inherited from modal_dialog.
void on_advanced_prefs_list_select(listbox &tree)
void set_disable_auto_moves(bool value)
Definition: general.cpp:916
bool save_replays()
Definition: game.cpp:774