The Battle for Wesnoth  1.15.1+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 
145 {
146  hotkey_filter_callback(*textbox->get_window());
147 }
148 
149 // Helper function to refresh resolution list
151 {
152  resolutions_ = video.get_available_resolutions(true);
153 
154  std::vector<config> options;
155  for(const point& res : resolutions_) {
156  config option;
157  option["label"] = formatter() << res.x << font::unicode_multiplication_sign << res.y;
158 
159 #if BOOST_VERSION >= 106700
160  const int div = boost::integer::gcd(res.x, res.y);
161 #else
162  const int div = boost::math::gcd(res.x, res.y);
163 #endif
164 
165  const int x_ratio = res.x / div;
166  const int y_ratio = res.y / div;
167 
168  if(x_ratio <= 10 || y_ratio <= 10) {
169  option["details"] = formatter() << "<span color='#777777'>(" << x_ratio << ':' << y_ratio << ")</span>";
170  }
171 
172  options.push_back(std::move(option));
173  }
174 
175  const unsigned current_res = std::distance(resolutions_.begin(), std::find(resolutions_.begin(), resolutions_.end(),
176  video.current_resolution()));
177 
178  res_list.set_values(options, current_res);
179 }
180 
181 std::map<std::string, string_map> preferences_dialog::get_friends_list_row_data(const acquaintance& entry)
182 {
183  std::map<std::string, string_map> data;
185 
186  std::string image = "friend.png";
187  std::string descriptor = _("friend");
188  std::string notes;
189 
190  if(entry.get_status() == "ignore") {
191  image = "ignore.png";
192  descriptor = _("ignored");
193  }
194 
195  if(!entry.get_notes().empty()) {
196  notes = " <small>(" + entry.get_notes() + ")</small>";
197  }
198 
199  item["use_markup"] = "true";
200 
201  item["label"] = "misc/status-" + image;
202  data.emplace("friend_icon", item);
203 
204  item["label"] = entry.get_nick() + notes;
205  data.emplace("friend_name", item);
206 
207  item["label"] = "<small>" + descriptor + "</small>";
208  data.emplace("friend_status", item);
209 
210  return data;
211 }
212 
214 {
215  const int num_friends = get_acquaintances().size();
216  const int sel = list.get_selected_row();
217 
218  if(sel < 0 || sel >= num_friends) {
219  return;
220  }
221 
222  std::map<std::string, acquaintance>::const_iterator who = get_acquaintances().begin();
223  std::advance(who, sel);
224 
225  textbox.set_value(who->second.get_nick() + " " + who->second.get_notes());
226 }
227 
229 {
230  const bool list_empty = list.get_item_count() == 0;
231 
232  if(!list_empty) {
233  list.select_row(std::min(static_cast<int>(list.get_item_count()) - 1, list.get_selected_row()));
234  }
235 
236  find_widget<button>(&window, "remove", false).set_active(!list_empty);
237 
238  find_widget<label>(&window, "no_friends_notice", false).set_visible(
240 }
241 
243 {
244  std::string username = textbox.text();
245  if(username.empty()) {
246  gui2::show_transient_message("", _("No username specified"), "", false, false, true);
247  return;
248  }
249 
250  std::string reason;
251 
252  std::size_t pos = username.find_first_of(' ');
253  if(pos != std::string::npos) {
254  reason = username.substr(pos + 1);
255  username = username.substr(0, pos);
256  }
257 
258  acquaintance* entry = nullptr;
259  bool added_new;
260 
261  std::tie(entry, added_new) = add_acquaintance(username, (is_friend ? "friend": "ignore"), reason);
262 
263  if(!entry) {
264  gui2::show_transient_message(_("Error"), _("Invalid username"), "", false, false, true);
265  return;
266  }
267 
268  textbox.clear();
269 
270  listbox& list = find_widget<listbox>(&window, "friends_list", false);
271 
272  //
273  // If this is a new entry, just add a new row. If it's not, we find the relevant
274  // row, remove it, and add a new row with the updated data. Should probably come
275  // up with a more elegant way to do this... the only reason I'm using the remove
276  // -and-replace method is to prevent any issues with the widgets' layout sizes.
277  //
278  if(added_new) {
279  list.add_row(get_friends_list_row_data(*entry));
280  } else {
281  for(unsigned i = 0; i < list.get_item_count(); ++i) {
282  grid* row_grid = list.get_row_grid(i);
283 
284  if(find_widget<label>(row_grid, "friend_name", false).get_label() == entry->get_nick()) {
285  list.remove_row(i);
286  list.add_row(get_friends_list_row_data(*entry), i);
287 
288  break;
289  }
290  }
291  }
292 
293  update_friends_list_controls(window, list);
294 }
295 
297 {
298  const int selected_row = std::max(0, friends_list.get_selected_row());
299 
300  std::map<std::string, acquaintance>::const_iterator who = get_acquaintances().begin();
301  std::advance(who, selected_row);
302 
303  const std::string to_remove = !textbox.text().empty() ? textbox.text() : who->second.get_nick();
304 
305  if(to_remove.empty()) {
306  gui2::show_transient_message("", _("No username specified"), "", false, false, true);
307  return;
308  }
309 
310  if(!remove_acquaintance(to_remove)) {
311  gui2::show_transient_error_message(_("Not on friends or ignore lists"));
312  return;
313  }
314 
315  textbox.clear();
316 
317  listbox& list = find_widget<listbox>(&window, "friends_list", false);
318  list.remove_row(selected_row);
319 
320  update_friends_list_controls(window, list);
321 }
322 
323 template<bool(*toggle_getter)(), bool(*toggle_setter)(bool), int(*vol_getter)(), void(*vol_setter)(int)>
324 void preferences_dialog::initialize_sound_option_group(const std::string& id_suffix)
325 {
326  const std::string toggle_widget_id = "sound_toggle_" + id_suffix;
327  const std::string volume_widget_id = "sound_volume_" + id_suffix;
328 
329  window& window = *get_window();
330 
331  // Set up the toggle. We utilize field_bool's callback-on-changed mechanism instead
332  // of manually registering the callback. Since we want the effects to apply immediately,
333  // the callback the setter callback is duplicated in the on-change callback. The field
334  // class could possibly use some reworking to make this less redundant, but for now it
335  // works well enough.
336  register_bool(toggle_widget_id, true, toggle_getter, std::bind(toggle_setter, _1),
337  std::bind(sound_toggle_on_change<toggle_setter>, std::ref(window), volume_widget_id, _1), true);
338 
339  // Set up the volume slider. integer_field doesn't have a callback-on-changed mechanism.
340  // To add one would either mean adding it to the base field class or make it a proper
341  // class of is own.
342  register_integer(volume_widget_id, true, vol_getter, vol_setter);
343 
344  // Callback to actually immediately apply the volume effect.
345  connect_signal_notify_modified(find_widget<slider>(&window, volume_widget_id, false),
346  std::bind(volume_setter_on_change<vol_setter>, _1));
347 }
348 
349 /**
350  * Sets up states and callbacks for each of the widgets
351  */
353 {
354  //
355  // GENERAL PANEL
356  //
357 
358  /* SCROLL SPEED */
359  register_integer("scroll_speed", true,
361 
362  /* ACCELERATED SPEED */
363  register_bool("turbo_toggle", true, turbo, set_turbo);
364 
365  const auto accl_load = [this]()->int {
366  return std::distance(accl_speeds_.begin(), std::find(accl_speeds_.begin(), accl_speeds_.end(), turbo_speed()));
367  };
368 
369  const auto accl_save = [this](int i) {
370  set_turbo_speed(accl_speeds_[i]);
371  };
372 
373  register_integer("turbo_slider", true,
374  accl_load, accl_save);
375 
376  // Set the value label transform function.
377  find_widget<slider>(&window, "turbo_slider", false).set_value_labels(
378  [this](int pos, int /*max*/)->t_string { return lexical_cast<std::string>(accl_speeds_[pos]); }
379  );
380 
381  /* SKIP AI MOVES */
382  register_bool("skip_ai_moves", true,
384 
385  /* DISABLE AUTO MOVES */
386  register_bool("disable_auto_moves", true,
388 
389  /* TURN DIALOG */
390  register_bool("show_turn_dialog", true,
392 
393  /* ENABLE PLANNING MODE */
394  register_bool("whiteboard_on_start", true,
396 
397  /* HIDE ALLY PLANS */
398  register_bool("whiteboard_hide_allies", true,
400 
401  /* INTERRUPT ON SIGHTING */
402  register_bool("interrupt_move_when_ally_sighted", true,
404 
405  /* SAVE REPLAYS */
406  register_bool("save_replays", true,
408 
409  /* DELETE AUTOSAVES */
410  register_bool("delete_saves", true,
412 
413  /* MAX AUTO SAVES */
414  register_integer("max_saves_slider", true,
416 
417  /* CACHE MANAGE */
418  connect_signal_mouse_left_click(find_widget<button>(&window, "cachemg", false),
419  std::bind(&gui2::dialogs::game_cache_options::display<>));
420 
421  //
422  // DISPLAY PANEL
423  //
424 
425  /* FULLSCREEN TOGGLE */
426  toggle_button& toggle_fullscreen =
427  find_widget<toggle_button>(&window, "fullscreen", false);
428 
429  toggle_fullscreen.set_value(fullscreen());
430 
431  // We bind a special callback function, so setup_single_toggle() is not used
432  connect_signal_mouse_left_click(toggle_fullscreen, std::bind(
434  this, std::ref(window)));
435 
436  /* SET RESOLUTION */
437  menu_button& res_list = find_widget<menu_button>(&window, "resolution_set", false);
438 
439  res_list.set_use_markup(true);
440  res_list.set_active(!fullscreen());
441 
442  set_resolution_list(res_list, window.video());
443 
445  std::bind(&preferences_dialog::handle_res_select, 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  /* FPS LIMITER */
483  register_bool("fps_limiter", true,
484  []() { return draw_delay() != 0; }, [](bool v) { set_draw_delay(v ? -1 : 0); });
485 
486  /* SELECT THEME */
488  find_widget<button>(&window, "choose_theme", false),
489  std::bind(&show_theme_dialog));
490 
491  //
492  // SOUND PANEL
493  //
494 
495  /* SOUND FX */
496  initialize_sound_option_group<sound_on, set_sound, sound_volume, set_sound_volume>("sfx");
497 
498  /* MUSIC */
499  initialize_sound_option_group<music_on, set_music, music_volume, set_music_volume>("music");
500 
501  register_bool("sound_toggle_stop_music_in_background", true,
503 
504  /* TURN BELL */
505  initialize_sound_option_group<turn_bell, set_turn_bell, bell_volume, set_bell_volume>("bell");
506 
507  /* UI FX */
508  initialize_sound_option_group<UI_sound_on, set_UI_sound, UI_volume, set_UI_volume>("uisfx");
509 
510  //
511  // MULTIPLAYER PANEL
512  //
513 
514  /* CHAT LINES */
515  register_integer("chat_lines", true,
517 
518  /* CHAT TIMESTAMPPING */
519  register_bool("chat_timestamps", true,
521 
522  /* SAVE PASSWORD */
523  register_bool("remember_password", true,
525 
526  /* WHISPERS FROM FRIENDS ONLY */
527  register_bool("lobby_whisper_friends_only", true,
529 
530  /* LOBBY JOIN NOTIFICATIONS */
531  lobby_joins_group.add_member(find_widget<toggle_button>(&window, "lobby_joins_none", false, true), SHOW_NONE);
532  lobby_joins_group.add_member(find_widget<toggle_button>(&window, "lobby_joins_friends", false, true), SHOW_FRIENDS);
533  lobby_joins_group.add_member(find_widget<toggle_button>(&window, "lobby_joins_all", false, true), SHOW_ALL);
534 
535  lobby_joins_group.set_member_states(static_cast<LOBBY_JOINS>(lobby_joins()));
536 
537  lobby_joins_group.set_callback_on_value_change([&](widget&) {
538  _set_lobby_joins(lobby_joins_group.get_active_member_value());
539  });
540 
541  /* FRIENDS LIST */
542  listbox& friends_list = find_widget<listbox>(&window, "friends_list", false);
543 
544  friends_list.clear();
545 
546  for(const auto& entry : get_acquaintances()) {
547  friends_list.add_row(get_friends_list_row_data(entry.second));
548  }
549 
550  update_friends_list_controls(window, friends_list);
551 
552  text_box& textbox = find_widget<text_box>(&window, "friend_name_box", false);
553 
555  find_widget<button>(&window, "add_friend", false), std::bind(
557  this, true,
558  std::ref(textbox),
559  std::ref(window)));
560 
562  find_widget<button>(&window, "add_ignored", false), std::bind(
564  this, false,
565  std::ref(textbox),
566  std::ref(window)));
567 
569  find_widget<button>(&window, "remove", false), std::bind(
571  this,
572  std::ref(friends_list),
573  std::ref(textbox),
574  std::ref(window)));
575 
576  connect_signal_notify_modified(friends_list, std::bind(
578  this,
579  std::ref(friends_list),
580  std::ref(textbox)));
581 
582  /* ALERTS */
584  find_widget<button>(&window, "mp_alerts", false),
585  std::bind(&gui2::dialogs::mp_alerts_options::display<>));
586 
587  /* SET WESNOTHD PATH */
589  find_widget<button>(&window, "mp_wesnothd", false), std::bind(
591 
592 
593  //
594  // ADVANCED PANEL
595  //
596 
597  listbox& advanced = find_widget<listbox>(&window, "advanced_prefs", false);
598 
599  std::map<std::string, string_map> row_data;
600 
601  for(const config& option : adv_preferences_cfg_) {
602  // Details about the current option
603  ADVANCED_PREF_TYPE pref_type;
604  try {
605  pref_type = ADVANCED_PREF_TYPE::string_to_enum(option["type"].str());
606  } catch(const bad_enum_cast&) {
607  continue;
608  }
609 
610  const std::string& pref_name = option["field"].str();
611 
612  row_data["pref_name"]["label"] = option["name"];
613  advanced.add_row(row_data);
614 
615  const int this_row = advanced.get_item_count() - 1;
616 
617  // Get the main grid from each row
618  grid* main_grid = get_advanced_row_grid(advanced, this_row);
619  assert(main_grid);
620 
621  grid& details_grid = find_widget<grid>(main_grid, "prefs_setter_grid", false);
623 
624  // The toggle widget for toggle-type options (hidden for other types)
625  toggle_button& toggle_box = find_widget<toggle_button>(main_grid, "value_toggle", false);
627 
628  if(!option["description"].empty()) {
629  find_widget<styled_widget>(main_grid, "description", false).set_label(option["description"]);
630  }
631 
632  switch(pref_type.v) {
633  case ADVANCED_PREF_TYPE::TOGGLE: {
634  //main_grid->remove_child("setter");
635 
637  toggle_box.set_value(get(pref_name, option["default"].to_bool()));
638 
639  // We need to bind a lambda here since preferences::set is overloaded.
640  // A lambda alone would be more verbose because it'd need to specify all the parameters.
641  connect_signal_mouse_left_click(toggle_box, std::bind(
642  [&, pref_name]() { set(pref_name, toggle_box.get_value_bool()); }
643  ));
644 
645  gui2::bind_status_label<toggle_button>(
646  main_grid, "value_toggle", default_status_value_getter<toggle_button>, "value");
647 
648  break;
649  }
650 
651  case ADVANCED_PREF_TYPE::SLIDER: {
652  slider* setter_widget = build_single_widget_instance<slider>(config {"definition", "minimal"});
653  setter_widget->set_id("setter");
654  // Maximum must be set first or this will assert
655  setter_widget->set_value_range(option["min"].to_int(), option["max"].to_int());
656  setter_widget->set_step_size(option["step"].to_int(1));
657 
658  details_grid.swap_child("setter", setter_widget, true);
659 
660  slider& slide = find_widget<slider>(&details_grid, "setter", false);
661 
662  slide.set_value(lexical_cast_default<int>(get(pref_name), option["default"].to_int()));
663 
664  // We need to bind a lambda here since preferences::set is overloaded.
665  // A lambda alone would be more verbose because it'd need to specify all the parameters.
666  connect_signal_notify_modified(slide, std::bind(
667  [&, pref_name]() { set(pref_name, slide.get_value()); }
668  ));
669 
670  gui2::bind_status_label<slider>(main_grid, "setter", default_status_value_getter<slider>, "value");
671 
672  break;
673  }
674 
675  case ADVANCED_PREF_TYPE::COMBO: {
676  std::vector<config> menu_data;
677  std::vector<std::string> option_ids;
678 
679  for(const config& choice : option.child_range("option")) {
680  config menu_item;
681  menu_item["label"] = choice["name"];
682  if(choice.has_attribute("description")) {
683  menu_item["details"] = std::string("<span color='#777'>") + choice["description"] + "</span>";
684  }
685  menu_data.push_back(menu_item);
686  option_ids.push_back(choice["id"]);
687  }
688 
689  // Attempt to find an initial selection
690  int selected = std::distance(option_ids.begin(), std::find(option_ids.begin(), option_ids.end(),
691  get(pref_name, option["default"].str())
692  ));
693 
694  // If the saved option value was invalid, reset selection to 0.
695  if(selected < 0 || selected >= static_cast<int>(option_ids.size())) {
696  selected = 0;
697  }
698 
699  menu_button* setter_widget = build_single_widget_instance<menu_button>();
700  setter_widget->set_id("setter");
701 
702  details_grid.swap_child("setter", setter_widget, true);
703 
704  menu_button& menu = find_widget<menu_button>(&details_grid, "setter", false);
705 
706  menu.set_use_markup(true);
707  menu.set_values(menu_data, selected);
708 
709  // We need to bind a lambda here since preferences::set is overloaded.
710  // A lambda alone would be more verbose because it'd need to specify all the parameters.
712  std::bind([=](widget& w) { set(pref_name, option_ids[dynamic_cast<menu_button&>(w).get_value()]); }, _1));
713 
714  gui2::bind_status_label<menu_button>(main_grid, "setter", [](menu_button& m)->std::string {
715  return m.get_value_string();
716  }, "value");
717 
718  break;
719  }
720 
721  case ADVANCED_PREF_TYPE::SPECIAL: {
722  //main_grid->remove_child("setter");
723 
724  image* value_widget = build_single_widget_instance<image>();
725  value_widget->set_label("icons/arrows/arrows_blank_right_25.png~CROP(3,3,18,18)");
726 
727  main_grid->swap_child("value", value_widget, true);
728 
729  break;
730  }
731  }
732  }
733 
734  connect_signal_notify_modified(advanced, std::bind(
736  this,
737  std::ref(advanced)));
738 
739  on_advanced_prefs_list_select(advanced);
740 
741  //
742  // HOTKEYS PANEL
743  //
744 
745  std::vector<config> hotkey_category_entries;
746  for(const auto& name : cat_names_) {
747  hotkey_category_entries.emplace_back("label", name.second, "checkbox", false);
748  }
749 
750  multimenu_button& hotkey_menu = find_widget<multimenu_button>(&window, "hotkey_category_menu", false);
751 
752  hotkey_menu.set_values(hotkey_category_entries);
753 
754  connect_signal_notify_modified(hotkey_menu,
755  std::bind(&preferences_dialog::hotkey_filter_callback, this, std::ref(window)));
756 
757  listbox& hotkey_list = setup_hotkey_list(window);
758 
759  text_box& filter = find_widget<text_box>(&window, "filter", false);
761 
762  // Action column
763  hotkey_list.register_translatable_sorting_option(0, [this](const int i) { return visible_hotkeys_[i]->description.str(); });
764 
765  // Hotkey column
766  hotkey_list.register_sorting_option(1, [this](const int i) { return hotkey::get_names(visible_hotkeys_[i]->command); });
767 
768  // Scope columns
769  hotkey_list.register_sorting_option(2, [this](const int i) { return !visible_hotkeys_[i]->scope[hotkey::SCOPE_GAME]; });
770  hotkey_list.register_sorting_option(3, [this](const int i) { return !visible_hotkeys_[i]->scope[hotkey::SCOPE_EDITOR]; });
771  hotkey_list.register_sorting_option(4, [this](const int i) { return !visible_hotkeys_[i]->scope[hotkey::SCOPE_MAIN_MENU]; });
772 
773  hotkey_list.set_active_sorting_option({0, listbox::SORT_ASCENDING}, true);
774 
776  find_widget<button>(&window, "btn_add_hotkey", false), std::bind(
778  this,
779  std::ref(hotkey_list)));
780 
782  find_widget<button>(&window, "btn_clear_hotkey", false), std::bind(
784  this,
785  std::ref(hotkey_list)));
786 
788  find_widget<button>(&window, "btn_reset_hotkeys", false), std::bind(
790  this,
791  std::ref(window)));
792 }
793 
795 {
796  const std::string& default_icon = "misc/empty.png~CROP(0,0,15,15)";
797 
798  std::map<std::string, string_map> row_data;
799 
800  t_string& row_icon = row_data["img_icon"]["label"];
801  t_string& row_action = row_data["lbl_desc"]["label"];
802  t_string& row_hotkey = row_data["lbl_hotkey"]["label"];
803 
804  t_string& row_is_g = row_data["lbl_is_game"]["label"];
805  t_string& row_is_g_markup = row_data["lbl_is_game"]["use_markup"];
806  t_string& row_is_e = row_data["lbl_is_editor"]["label"];
807  t_string& row_is_e_markup = row_data["lbl_is_editor"]["use_markup"];
808  t_string& row_is_t = row_data["lbl_is_titlescreen"]["label"];
809  t_string& row_is_t_markup = row_data["lbl_is_titlescreen"]["use_markup"];
810 
811  listbox& hotkey_list = find_widget<listbox>(&window, "list_hotkeys", false);
812 
813  hotkey_list.clear();
814  visible_hotkeys_.clear();
815 
816  std::string text_feature_on = "<span color='#0f0'>" + _("&#9679;") + "</span>";
817 
818  for(const auto& hotkey_item : hotkey::get_hotkey_commands()) {
819  if(hotkey_item.hidden) {
820  continue;
821  }
822  visible_hotkeys_.push_back(&hotkey_item);
823 
824  if(filesystem::file_exists(game_config::path + "/images/icons/action/" + hotkey_item.command + "_25.png")) {
825  row_icon = "icons/action/" + hotkey_item.command + "_25.png~CROP(3,3,18,18)";
826  } else {
827  row_icon = default_icon;
828  }
829 
830  row_action = hotkey_item.description;
831  row_hotkey = hotkey::get_names(hotkey_item.command);
832 
833  row_is_g = hotkey_item.scope[hotkey::SCOPE_GAME] ? text_feature_on : "";
834  row_is_g_markup = "true";
835  row_is_e = hotkey_item.scope[hotkey::SCOPE_EDITOR] ? text_feature_on : "";
836  row_is_e_markup = "true";
837  row_is_t = hotkey_item.scope[hotkey::SCOPE_MAIN_MENU] ? text_feature_on : "";
838  row_is_t_markup = "true";
839 
840  hotkey_list.add_row(row_data);
841  }
842 
843  return hotkey_list;
844 }
845 
847 {
848  int row_number = hotkeys.get_selected_row();
849  if(row_number < 0) {
850  gui2::show_transient_message("", _("No hotkey selected"));
851  return;
852  }
853 
854  const hotkey::hotkey_command& hotkey_item = *visible_hotkeys_[row_number];
855 
856  gui2::dialogs::hotkey_bind bind_dlg(hotkey_item.command);
857  bind_dlg.show();
858 
859  hotkey::hotkey_ptr newhk = bind_dlg.get_new_binding();
860  hotkey::hotkey_ptr oldhk;
861 
862  // only if not cancelled.
863  if(newhk.get() == nullptr) {
864  return;
865  }
866 
867  for(const hotkey::hotkey_ptr& hk : hotkey::get_hotkeys()) {
868  if(!hk->is_disabled() && newhk->bindings_equal(hk)) {
869  oldhk = hk;
870  }
871  }
872 
873  hotkey::scope_changer scope_restorer;
874  hotkey::set_active_scopes(hotkey_item.scope);
875 
876  if(oldhk && oldhk->get_command() == hotkey_item.command) {
877  return;
878  }
879 
880  if(oldhk && oldhk->get_command() != "null") {
881  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>”?", {
882  {"hotkey_sequence", oldhk->get_name()},
883  {"old_hotkey_action", hotkey::get_description(oldhk->get_command())},
884  {"new_hotkey_action", hotkey::get_description(newhk->get_command())}
885  });
886 
887  const int res = gui2::show_message(_("Reassign Hotkey"), text, gui2::dialogs::message::yes_no_buttons, true);
888  if(res != gui2::retval::OK) {
889  return;
890  }
891  }
892 
893  hotkey::add_hotkey(newhk);
894 
895  // We need to recalculate all hotkey names in because we might have removed a hotkey from another command.
896  for(std::size_t i = 0; i < hotkeys.get_item_count(); ++i) {
897  const hotkey::hotkey_command& hotkey_item_row = *visible_hotkeys_[i];
898  find_widget<label>(hotkeys.get_row_grid(i), "lbl_hotkey", false).set_label(hotkey::get_names(hotkey_item_row.command));
899  }
900 }
901 
903 {
904  gui2::show_transient_message(_("Hotkeys Reset"), _("All hotkeys have been reset to their default values."),
905  std::string(), false, false, true);
906 
907  clear_hotkeys();
908 
909  // Set up the list again and reselect the default sorting option.
910  listbox& hotkey_list = setup_hotkey_list(window);
911  hotkey_list.set_active_sorting_option({0, listbox::SORT_ASCENDING}, true);
912 
913  find_widget<multimenu_button>(&window, "hotkey_category_menu", false).reset_toggle_states();
914 }
915 
917 {
918  int row_number = hotkeys.get_selected_row();
919  if(row_number < 0) {
920  gui2::show_transient_message("", _("No hotkey selected"));
921  return;
922  }
923 
924  const hotkey::hotkey_command& hotkey_item = *visible_hotkeys_[row_number];
925  hotkey::clear_hotkeys(hotkey_item.command);
926  find_widget<label>(hotkeys.get_row_grid(row_number), "lbl_hotkey", false).set_label(hotkey::get_names(hotkey_item.command));
927 }
928 
930 {
931  const multimenu_button& hotkey_menu = find_widget<const multimenu_button>(&window, "hotkey_category_menu", false);
932  const text_box& name_filter = find_widget<const text_box>(&window, "filter", false);
933 
934  boost::dynamic_bitset<> toggle_states = hotkey_menu.get_toggle_states();
935  boost::dynamic_bitset<> res(visible_hotkeys_.size());
936 
937  std::string text = name_filter.get_value();
938 
939  if(toggle_states.none()) {
940  // Nothing selected. It means that *all* categories are shown.
941  toggle_states = ~toggle_states;
942  }
943 
944  for(std::size_t h = 0; h < visible_hotkeys_.size(); ++h) {
945  unsigned index = 0;
946 
947  const std::string description = visible_hotkeys_[h]->description.str();
948 
949  // Default to true if there is no filter text
950  bool found = true;
951 
952  if(!text.empty()) {
953  for(const auto& word : utils::split(text, ' ')) {
954  found = translation::ci_search(description, word);
955  if(!found) {
956  break;
957  }
958  }
959  }
960 
961  // Filter categories
962  for(const auto& name : cat_names_) {
963  if(visible_hotkeys_[h]->category == name.first) {
964  break;
965  } else {
966  ++index;
967  }
968  }
969 
970  if(index < toggle_states.size() && found) {
971  res[h] = toggle_states[index];
972  } else {
973  res[h] = false;
974  }
975  }
976 
977  find_widget<listbox>(&window, "list_hotkeys", false).set_row_shown(res);
978 }
979 
981 {
982  const int selected_row = list.get_selected_row();
983 
984  const ADVANCED_PREF_TYPE& selected_type = ADVANCED_PREF_TYPE::string_to_enum(
985  adv_preferences_cfg_[selected_row]["type"].str());
986 
987  const std::string& selected_field = adv_preferences_cfg_[selected_row]["field"].str();
988 
989  if(selected_type == ADVANCED_PREF_TYPE::SPECIAL) {
990  if(selected_field == "advanced_graphic_options") {
991  gui2::dialogs::advanced_graphics_options::display();
992  } else if(selected_field == "logging") {
993  gui2::dialogs::log_settings::display();
994  } else if(selected_field == "orb_color") {
995  gui2::dialogs::select_orb_colors::display();
996  } else {
997  WRN_GUI_L << "Invalid or unimplemented custom advanced prefs option: " << selected_field << "\n";
998  }
999 
1000  // Add more options here as needed
1001  }
1002 
1003  const bool has_description = !adv_preferences_cfg_[selected_row]["description"].empty();
1004 
1005  if(has_description || (selected_type != ADVANCED_PREF_TYPE::SPECIAL && selected_type != ADVANCED_PREF_TYPE::TOGGLE)) {
1006  find_widget<widget>(get_advanced_row_grid(list, selected_row), "prefs_setter_grid", false)
1007  .set_visible(widget::visibility::visible);
1008  }
1009 
1010  if(last_selected_item_ != selected_row) {
1011  find_widget<widget>(get_advanced_row_grid(list, last_selected_item_), "prefs_setter_grid", false)
1012  .set_visible(widget::visibility::invisible);
1013 
1014  last_selected_item_ = selected_row;
1015  }
1016 }
1017 
1019 {
1020  //
1021  // MULTIPLAYER TABS
1022  //
1024  std::bind(&preferences_dialog::on_tab_select, this, std::ref(window)));
1025 }
1026 
1028 {
1029  set_always_save_fields(true);
1030 
1031  connect_signal_mouse_left_click(find_widget<button>(&window, "about", false), std::bind(&game_version::display<>));
1032 
1033  //
1034  // Status labels
1035  // These need to be set here in pre_show, once the fields are initialized. For some reason, this
1036  // is not the case for those in Advanced
1037  //
1038 
1039  gui2::bind_status_label<slider>(&window, "max_saves_slider", [](slider& s)->std::string {
1040  return s.get_value() == INFINITE_AUTO_SAVES ? _("∞") : s.get_value_label().str();
1041  });
1042 
1043  gui2::bind_status_label<slider>(&window, "turbo_slider");
1044 
1045  gui2::bind_status_label<slider>(&window, "scaling_slider", [](slider& s)->std::string {
1046  return s.get_value_label() + "%";
1047  });
1048 
1049  listbox& selector = find_widget<listbox>(&window, "selector", false);
1050  stacked_widget& pager = find_widget<stacked_widget>(&window, "pager", false);
1051 
1052  pager.set_find_in_all_layers(true);
1053 
1055  std::bind(&preferences_dialog::on_page_select, this, std::ref(window)));
1056 
1057  window.keyboard_capture(&selector);
1058 
1059  VALIDATE(selector.get_item_count() == pager.get_layer_count(),
1060  "The preferences pager and its selector listbox do not have the same number of items.");
1061 
1062  const int main_index = index_in_pager_range(initial_index_.first, pager);
1063 
1064  // Loops through each pager layer and checks if it has both a tab bar
1065  // and stack. If so, it initializes the options for the former and
1066  // selects the specified layer of the latter.
1067  for(unsigned int i = 0; i < pager.get_layer_count(); ++i) {
1068  listbox* tab_selector = find_widget<listbox>(
1069  pager.get_layer_grid(i), "tab_selector", false, false);
1070 
1071  stacked_widget* tab_pager = find_widget<stacked_widget>(
1072  pager.get_layer_grid(i), "tab_pager", false, false);
1073 
1074  if(tab_pager && tab_selector) {
1075  const int ii = static_cast<int>(i);
1076  const int tab_index = index_in_pager_range(initial_index_.second, *tab_pager);
1077  const int to_select = (ii == main_index ? tab_index : 0);
1078 
1079  // Initialize tabs for this page
1080  initialize_tabs(window, *tab_selector);
1081 
1082  tab_selector->select_row(to_select);
1083  tab_pager->select_layer(to_select);
1084  }
1085  }
1086 
1087  // Finally, select the initial main page
1088  selector.select_row(main_index);
1089  pager.select_layer(main_index);
1090 }
1091 
1092 void preferences_dialog::set_visible_page(window& window, unsigned int page, const std::string& pager_id)
1093 {
1094  find_widget<stacked_widget>(&window, pager_id, false).select_layer(page);
1095 }
1096 
1097 // Special fullsceen callback
1099 {
1100  const bool ison = find_widget<toggle_button>(&window, "fullscreen", false).get_value_bool();
1101  window.video().set_fullscreen(ison);
1102 
1103  menu_button& res_list = find_widget<menu_button>(&window, "resolution_set", false);
1104 
1105  set_resolution_list(res_list, window.video());
1106  res_list.set_active(!ison);
1107 }
1108 
1110 {
1111  menu_button& res_list = find_widget<menu_button>(&window, "resolution_set", false);
1112 
1113  if(window.video().set_resolution(resolutions_[res_list.get_value()])) {
1114  set_resolution_list(res_list, window.video());
1115  }
1116 }
1117 
1119 {
1120  const int selected_row =
1121  std::max(0, find_widget<listbox>(&window, "selector", false).get_selected_row());
1122  set_visible_page(window, static_cast<unsigned int>(selected_row), "pager");
1123 }
1124 
1126 {
1127  const int selected_row =
1128  std::max(0, find_widget<listbox>(&window, "tab_selector", false).get_selected_row());
1129  set_visible_page(window, static_cast<unsigned int>(selected_row), "tab_pager");
1130 }
1131 
1133 {
1134  save_hotkeys();
1135 
1136  // Save new prefs to disk. This also happens on app close, but doing
1137  // it here too ensures nothing is lost in case of, say, a crash.
1139 }
1140 
1141 } // namespace dialogs
1142 } // 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:457
int autosavemax()
Definition: game.cpp:822
void set_text_changed_callback(std::function< void(text_box_base *textbox, const std::string text)> cb)
Set the text_changed callback.
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:464
bool remember_password()
virtual void set_value(unsigned selected, bool fire_event=false) override
Inherited from selectable_item.
Abstract base class for text items.
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 hotkey_filter_callback(window &window) const
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:859
int lobby_joins()
Definition: game.cpp:360
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:282
const std::map< std::string, acquaintance > & get_acquaintances()
Definition: game.cpp:228
const int INFINITE_AUTO_SAVES
Definition: game.hpp:190
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:362
void set_show_side_colors(bool value)
Definition: game.cpp:772
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:452
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:375
void set_chat_lines(int lines)
Definition: game.cpp:931
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:926
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:777
const config * game_cfg
Definition: help_impl.cpp:65
-file util.hpp
bool remove_acquaintance(const std::string &nick)
Definition: game.cpp:284
void set_interrupt_when_ally_sighted(bool value)
Definition: game.cpp:812
std::vector< std::string > split(const std::string &val, const char c, const int flags)
Splits a (comma-)separated string into a vector of pieces.
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:582
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:437
static UNUSEDNOWARN std::string _(const char *str)
Definition: gettext.hpp:91
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:782
bool is_friend(const std::string &nick)
Definition: game.cpp:306
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:274
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:262
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:447
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)
bool show_standing_animations()
Definition: display.cpp:102
void set_animate_map(bool value)
Definition: general.cpp:953
bool chat_timestamping()
Definition: game.cpp:918
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:922
void set_draw_delay(int value)
Definition: general.cpp:978
int idle_anim_rate()
Definition: general.cpp:465
bool ci_search(const std::string &s1, const std::string &s2)
Definition: gettext.cpp:518
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:817
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
window * get_window()
Get the parent window.
Definition: widget.cpp:114
static map_location::DIRECTION s
void set_delete_saves(bool value)
Definition: game.cpp:792
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:797
int w
std::shared_ptr< hotkey_base > hotkey_ptr
Definition: hotkey_item.hpp:30
const std::string & get_status() const
Definition: game.hpp:275
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:276
const std::string & get_description(const std::string &command)
void set_autosavemax(int value)
Definition: game.cpp:827
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:854
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.
void on_filtertext_changed(text_box_base *textbox)
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:442
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:767
bool turn_dialog()
Definition: game.cpp:432
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:401
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:762
Class for a toggle button.
virtual void post_build(window &window) override
Inherited from modal_dialog.
std::pair< std::string, unsigned > item
Definition: help_impl.hpp:371
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:787