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