The Battle for Wesnoth  1.17.4+dev
preferences_dialog.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2016 - 2022
3  by Charles Dang <exodia339gmail.com>
4  Copyright (C) 2011, 2015 by Iris Morelle <shadowm2006@gmail.com>
5  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
6 
7  This program is free software; you can redistribute it and/or modify
8  it under the terms of the GNU General Public License as published by
9  the Free Software Foundation; either version 2 of the License, or
10  (at your option) any later version.
11  This program is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY.
13 
14  See the COPYING file for more details.
15 */
16 
17 #define GETTEXT_DOMAIN "wesnoth-lib"
18 
20 
21 #include "filesystem.hpp"
22 #include "formatter.hpp"
23 #include "formula/string_utils.hpp"
24 #include "gettext.hpp"
25 #include "hotkey/hotkey_item.hpp"
26 #include "lexical_cast.hpp"
28 #include "preferences/display.hpp"
29 #include "preferences/game.hpp"
30 #include "preferences/general.hpp"
31 #include "preferences/lobby.hpp"
32 #include "video.hpp"
33 
34 // Sub-dialog includes
40 
43 #include "gui/dialogs/message.hpp"
45 #include "gui/widgets/button.hpp"
48 #include "gui/widgets/grid.hpp"
49 #include "gui/widgets/image.hpp"
50 #include "gui/widgets/label.hpp"
51 #include "gui/widgets/listbox.hpp"
53 #include "gui/widgets/settings.hpp"
54 #include "gui/widgets/slider.hpp"
57 #include "gui/widgets/text_box.hpp"
59 #include "gui/widgets/window.hpp"
60 
61 #include <functional>
62 #include <numeric>
63 
64 namespace gui2::dialogs
65 {
66 namespace
67 {
68 template<typename W>
69 void disable_widget_on_toggle(window& window, widget& w, const std::string& id)
70 {
71  find_widget<W>(&window, id, false).set_active(dynamic_cast<selectable_item&>(w).get_value_bool());
72 }
73 
74 template<typename W>
75 void disable_widget_on_toggle_inverted(window& window, widget& w, const std::string& id)
76 {
77  find_widget<W>(&window, id, false).set_active(!dynamic_cast<selectable_item&>(w).get_value_bool());
78 }
79 
80 // Ensure the specified index is between 0 and one less than the max
81 // number of pager layers (since get_layer_count returns one-past-end).
82 int index_in_pager_range(const int first, const stacked_widget& pager)
83 {
84  return std::clamp<int>(first, 0, pager.get_layer_count() - 1);
85 }
86 
87 // Helper to make it easier to immediately apply sound toggles immediately.
88 template<bool(*fptr)(bool)>
89 void sound_toggle_on_change(window& window, const std::string& id_to_toggle, widget& w)
90 {
91  std::invoke(fptr, dynamic_cast<selectable_item&>(w).get_value_bool());
92 
93  // Toggle the corresponding slider.
94  disable_widget_on_toggle<slider>(window, w, id_to_toggle);
95 }
96 
97 // Helper to make it easier to immediately apply volume (music, etc) setings on change.
98 template<void(*fptr)(int)>
99 void volume_setter_on_change(widget& w)
100 {
101  std::invoke(fptr, dynamic_cast<integer_selector&>(w).get_value());
102 }
103 
104 } // end anon namespace
105 
106 using namespace preferences;
108 
110 
112  : adv_preferences_(preferences::get_advanced_preferences())
113  , resolutions_() // should be populated by set_resolution_list before use
114  , last_selected_item_(0)
115  , accl_speeds_({0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2, 3, 4, 8, 16})
116  , visible_hotkeys_()
117  , cat_names_()
118  , initial_index_(pef_view_map[initial_view])
119 {
120  for(const auto& name : hotkey::get_category_names()) {
121  // Don't include categories with no hotkeys
122  if(!hotkey::get_hotkeys_by_category(name.first).empty()) {
123  cat_names_[name.first] = t_string(name.second, "wesnoth-lib");
124  }
125  }
126 }
127 
128 // Helper function to refresh resolution list
130 {
131  resolutions_ = CVideo::get_singleton().get_available_resolutions(true);
132 
133  std::vector<config> options;
134  for(const point& res : resolutions_) {
135  config option;
136  option["label"] = formatter() << res.x << font::unicode_multiplication_sign << res.y;
137 
138  const int div = std::gcd(res.x, res.y);
139  const int x_ratio = res.x / div;
140  const int y_ratio = res.y / div;
141 
142  if(x_ratio <= 10 || y_ratio <= 10) {
143  option["details"] = formatter() << "<span color='#777777'>(" << x_ratio << ':' << y_ratio << ")</span>";
144  }
145 
146  options.push_back(std::move(option));
147  }
148 
149  const unsigned current_res = std::distance(resolutions_.begin(), std::find(resolutions_.begin(), resolutions_.end(),
151 
152  res_list.set_values(options, current_res);
153 }
154 
155 std::map<std::string, string_map> preferences_dialog::get_friends_list_row_data(const acquaintance& entry)
156 {
157  std::map<std::string, string_map> data;
159 
160  std::string image = "friend.png";
161  std::string descriptor = _("friend");
162  std::string notes;
163 
164  if(entry.get_status() == "ignore") {
165  image = "ignore.png";
166  descriptor = _("ignored");
167  }
168 
169  if(!entry.get_notes().empty()) {
170  notes = " <small>(" + entry.get_notes() + ")</small>";
171  }
172 
173  item["use_markup"] = "true";
174 
175  item["label"] = "misc/status-" + image;
176  data.emplace("friend_icon", item);
177 
178  item["label"] = entry.get_nick() + notes;
179  data.emplace("friend_name", item);
180 
181  item["label"] = "<small>" + descriptor + "</small>";
182  data.emplace("friend_status", item);
183 
184  return data;
185 }
186 
188 {
189  const int num_friends = get_acquaintances().size();
190  const int sel = list.get_selected_row();
191 
192  if(sel < 0 || sel >= num_friends) {
193  return;
194  }
195 
196  std::map<std::string, acquaintance>::const_iterator who = get_acquaintances().begin();
197  std::advance(who, sel);
198 
199  textbox.set_value(who->second.get_nick() + " " + who->second.get_notes());
200 }
201 
203 {
204  const bool list_empty = list.get_item_count() == 0;
205 
206  if(!list_empty) {
207  list.select_row(std::min(static_cast<int>(list.get_item_count()) - 1, list.get_selected_row()));
208  }
209 
210  find_widget<button>(get_window(), "remove", false).set_active(!list_empty);
211 
212  find_widget<label>(get_window(), "no_friends_notice", false).set_visible(
214 }
215 
217 {
218  std::string username = textbox.text();
219  if(username.empty()) {
220  gui2::show_transient_message("", _("No username specified"), "", false, false, true);
221  return;
222  }
223 
224  std::string reason;
225 
226  std::size_t pos = username.find_first_of(' ');
227  if(pos != std::string::npos) {
228  reason = username.substr(pos + 1);
229  username = username.substr(0, pos);
230  }
231 
232  auto [entry, added_new] = add_acquaintance(username, (is_friend ? "friend": "ignore"), reason);
233 
234  if(!entry) {
235  gui2::show_transient_message(_("Error"), _("Invalid username"), "", false, false, true);
236  return;
237  }
238 
239  textbox.clear();
240 
241  listbox& list = find_widget<listbox>(get_window(), "friends_list", false);
242 
243  //
244  // If this is a new entry, just add a new row. If it's not, we find the relevant
245  // row, remove it, and add a new row with the updated data. Should probably come
246  // up with a more elegant way to do this... the only reason I'm using the remove
247  // -and-replace method is to prevent any issues with the widgets' layout sizes.
248  //
249  if(added_new) {
250  list.add_row(get_friends_list_row_data(*entry));
251  } else {
252  for(unsigned i = 0; i < list.get_item_count(); ++i) {
253  grid* row_grid = list.get_row_grid(i);
254 
255  if(find_widget<label>(row_grid, "friend_name", false).get_label() == entry->get_nick()) {
256  list.remove_row(i);
257  list.add_row(get_friends_list_row_data(*entry), i);
258 
259  break;
260  }
261  }
262  }
263 
264  update_friends_list_controls(list);
265 }
266 
268 {
269  const int selected_row = std::max(0, friends_list.get_selected_row());
270 
271  std::map<std::string, acquaintance>::const_iterator who = get_acquaintances().begin();
272  std::advance(who, selected_row);
273 
274  const std::string to_remove = !textbox.text().empty() ? textbox.text() : who->second.get_nick();
275 
276  if(to_remove.empty()) {
277  gui2::show_transient_message("", _("No username specified"), "", false, false, true);
278  return;
279  }
280 
281  if(!remove_acquaintance(to_remove)) {
282  gui2::show_transient_error_message(_("Not on friends or ignore lists"));
283  return;
284  }
285 
286  textbox.clear();
287 
288  listbox& list = find_widget<listbox>(get_window(), "friends_list", false);
289  list.remove_row(selected_row);
290 
291  update_friends_list_controls(list);
292 }
293 
294 template<bool(*toggle_getter)(), bool(*toggle_setter)(bool), int(*vol_getter)(), void(*vol_setter)(int)>
295 void preferences_dialog::initialize_sound_option_group(const std::string& id_suffix)
296 {
297  const std::string toggle_widget_id = "sound_toggle_" + id_suffix;
298  const std::string volume_widget_id = "sound_volume_" + id_suffix;
299 
300  window& window = *get_window();
301 
302  // Set up the toggle. We utilize field_bool's callback-on-changed mechanism instead
303  // of manually registering the callback. Since we want the effects to apply immediately,
304  // the callback the setter callback is duplicated in the on-change callback. The field
305  // class could possibly use some reworking to make this less redundant, but for now it
306  // works well enough.
307  register_bool(toggle_widget_id, true, toggle_getter, std::bind(toggle_setter, std::placeholders::_1),
308  std::bind(sound_toggle_on_change<toggle_setter>, std::ref(window), volume_widget_id, std::placeholders::_1), true);
309 
310  // Set up the volume slider. integer_field doesn't have a callback-on-changed mechanism.
311  // To add one would either mean adding it to the base field class or make it a proper
312  // class of is own.
313  register_integer(volume_widget_id, true, vol_getter, vol_setter);
314 
315  // Callback to actually immediately apply the volume effect.
316  connect_signal_notify_modified(find_widget<slider>(&window, volume_widget_id, false),
317  std::bind(volume_setter_on_change<vol_setter>, std::placeholders::_1));
318 }
319 
321 {
322  // Update pixel scale preference.
323  slider& ps_slider = find_widget<slider>(get_window(), "pixel_scale_slider", false);
324  set_pixel_scale(ps_slider.get_value());
325 
326  // Update auto pixel scale preference.
327  toggle_button& auto_ps_toggle =
328  find_widget<toggle_button>(get_window(), "auto_pixel_scale", false);
329  set_auto_pixel_scale(auto_ps_toggle.get_value_bool());
330 
331  // Update draw buffers, taking these into account.
333 }
334 
335 
336 /**
337  * Sets up states and callbacks for each of the widgets
338  */
340 {
341  //
342  // GENERAL PANEL
343  //
344 
345  /* SCROLL SPEED */
346  register_integer("scroll_speed", true,
348 
349  /* ACCELERATED SPEED */
350  register_bool("turbo_toggle", true, turbo, set_turbo);
351 
352  const auto accl_load = [this]()->int {
353  return std::distance(accl_speeds_.begin(), std::find(accl_speeds_.begin(), accl_speeds_.end(), turbo_speed()));
354  };
355 
356  const auto accl_save = [this](int i) {
357  set_turbo_speed(accl_speeds_[i]);
358  };
359 
360  register_integer("turbo_slider", true,
361  accl_load, accl_save);
362 
363  // Set the value label transform function.
364  find_widget<slider>(&window, "turbo_slider", false).set_value_labels(
365  [this](int pos, int /*max*/)->t_string { return lexical_cast<std::string>(accl_speeds_[pos]); }
366  );
367 
368  /* SKIP AI MOVES */
369  register_bool("skip_ai_moves", true,
371 
372  /* DISABLE AUTO MOVES */
373  register_bool("disable_auto_moves", true,
375 
376  /* TURN DIALOG */
377  register_bool("show_turn_dialog", true,
379 
380  /* ENABLE PLANNING MODE */
381  register_bool("whiteboard_on_start", true,
383 
384  /* HIDE ALLY PLANS */
385  register_bool("whiteboard_hide_allies", true,
387 
388  /* INTERRUPT ON SIGHTING */
389  register_bool("interrupt_move_when_ally_sighted", true,
391 
392  /* SAVE REPLAYS */
393  register_bool("save_replays", true,
395 
396  /* DELETE AUTOSAVES */
397  register_bool("delete_saves", true,
399 
400  /* MAX AUTO SAVES */
401  register_integer("max_saves_slider", true,
403 
404  /* CACHE MANAGE */
405  connect_signal_mouse_left_click(find_widget<button>(&window, "cachemg", false),
406  std::bind(&gui2::dialogs::game_cache_options::display<>));
407 
408  //
409  // DISPLAY PANEL
410  //
411 
412  /* FULLSCREEN TOGGLE */
413  toggle_button& toggle_fullscreen =
414  find_widget<toggle_button>(&window, "fullscreen", false);
415 
416  toggle_fullscreen.set_value(fullscreen());
417 
418  // We bind a special callback function, so setup_single_toggle() is not used
419  connect_signal_mouse_left_click(toggle_fullscreen, std::bind(
421 
422  /* SET RESOLUTION */
423  menu_button& res_list = find_widget<menu_button>(&window, "resolution_set", false);
424 
425  res_list.set_use_markup(true);
426  res_list.set_active(!fullscreen());
427 
428  set_resolution_list(res_list);
429 
431  std::bind(&preferences_dialog::handle_res_select, this));
432 
433  /* PIXEL SCALE */
434  register_integer("pixel_scale_slider", true,
436 
437  slider& ps_slider =
438  find_widget<slider>(&window, "pixel_scale_slider", false);
440  std::bind(&preferences_dialog::apply_pixel_scale, this));
441 
442  /* AUTOMATIC PIXEL SCALE */
443  register_bool("auto_pixel_scale", true,
445  [&](widget& w) { disable_widget_on_toggle_inverted<slider>(window, w, "pixel_scale_slider"); }, true);
446 
447  toggle_button& auto_ps_toggle =
448  find_widget<toggle_button>(get_window(), "auto_pixel_scale", false);
449  connect_signal_mouse_left_click(auto_ps_toggle,
450  std::bind(&preferences_dialog::apply_pixel_scale, this));
451 
452  /* SHOW FLOATING LABELS */
453  register_bool("show_floating_labels", true,
455 
456  /* SHOW TEAM COLORS */
457  register_bool("show_ellipses", true,
459 
460  /* SHOW GRID */
461  register_bool("show_grid", true,
463 
464  /* ANIMATE MAP */
465  register_bool("animate_terrains", true, animate_map, set_animate_map,
466  [&](widget& w) { disable_widget_on_toggle<toggle_button>(window, w, "animate_water"); }, true);
467 
468  /* ANIMATE WATER */
469  register_bool("animate_water", true,
471 
472  /* SHOW UNIT STANDING ANIMS */
473  register_bool("animate_units_standing", true,
475 
476  /* SHOW UNIT IDLE ANIMS */
477  register_bool("animate_units_idle", true, idle_anim, set_idle_anim,
478  [&](widget& w) { disable_widget_on_toggle<slider>(window, w, "idle_anim_frequency"); });
479 
480  register_integer("idle_anim_frequency", true,
482 
483  /* FONT SCALING */
484  //register_integer("scaling_slider", true,
485  // font_scaling, set_font_scaling);
486 
487  /* FPS LIMITER */
488  register_bool("fps_limiter", true,
489  []() { return draw_delay() != 0; }, [](bool v) { set_draw_delay(v ? -1 : 0); });
490 
491  /* VSYNC */
492  register_bool("vsync", true, vsync, set_vsync);
493  if(!CVideo::get_singleton().supports_vsync()) {
494  find_widget<widget>(&window, "vsync", false).set_visible(gui2::widget::visibility::invisible);
495  }
496 
497  /* SELECT THEME */
499  find_widget<button>(&window, "choose_theme", false),
500  std::bind(&show_theme_dialog));
501 
502  //
503  // SOUND PANEL
504  //
505 
506  /* SOUND FX */
507  initialize_sound_option_group<sound_on, set_sound, sound_volume, set_sound_volume>("sfx");
508 
509  /* MUSIC */
510  initialize_sound_option_group<music_on, set_music, music_volume, set_music_volume>("music");
511 
512  register_bool("sound_toggle_stop_music_in_background", true,
514 
515  /* TURN BELL */
516  initialize_sound_option_group<turn_bell, set_turn_bell, bell_volume, set_bell_volume>("bell");
517 
518  /* UI FX */
519  initialize_sound_option_group<UI_sound_on, set_UI_sound, UI_volume, set_UI_volume>("uisfx");
520 
521  //
522  // MULTIPLAYER PANEL
523  //
524 
525  /* CHAT LINES */
526  register_integer("chat_lines", true,
528 
529  /* CHAT TIMESTAMPPING */
530  register_bool("chat_timestamps", true,
532 
533  /* SAVE PASSWORD */
534  register_bool("remember_password", true,
536 
537  /* WHISPERS FROM FRIENDS ONLY */
538  register_bool("lobby_whisper_friends_only", true,
540 
541  /* LOBBY JOIN NOTIFICATIONS */
542  lobby_joins_group.add_member(find_widget<toggle_button>(&window, "lobby_joins_none", false, true), lobby_joins::show_none);
543  lobby_joins_group.add_member(find_widget<toggle_button>(&window, "lobby_joins_friends", false, true), lobby_joins::show_friends);
544  lobby_joins_group.add_member(find_widget<toggle_button>(&window, "lobby_joins_all", false, true), lobby_joins::show_all);
545 
546  lobby_joins_group.set_member_states(get_lobby_joins());
547 
548  lobby_joins_group.set_callback_on_value_change([&](widget&, const lobby_joins val) {
549  _set_lobby_joins(val);
550  });
551 
552  /* FRIENDS LIST */
553  listbox& friends_list = find_widget<listbox>(&window, "friends_list", false);
554 
555  friends_list.clear();
556 
557  for(const auto& entry : get_acquaintances()) {
558  friends_list.add_row(get_friends_list_row_data(entry.second));
559  }
560 
561  update_friends_list_controls(friends_list);
562 
563  text_box& textbox = find_widget<text_box>(&window, "friend_name_box", false);
564 
566  find_widget<button>(&window, "add_friend", false), std::bind(
568  this, true,
569  std::ref(textbox)));
570 
572  find_widget<button>(&window, "add_ignored", false), std::bind(
574  this, false,
575  std::ref(textbox)));
576 
578  find_widget<button>(&window, "remove", false), std::bind(
580  this,
581  std::ref(friends_list),
582  std::ref(textbox)));
583 
584  connect_signal_notify_modified(friends_list, std::bind(
586  this,
587  std::ref(friends_list),
588  std::ref(textbox)));
589 
590  /* ALERTS */
592  find_widget<button>(&window, "mp_alerts", false),
593  std::bind(&gui2::dialogs::mp_alerts_options::display<>));
594 
595  /* SET WESNOTHD PATH */
597  find_widget<button>(&window, "mp_wesnothd", false), std::bind(
599 
600 
601  //
602  // ADVANCED PANEL
603  //
604 
605  listbox& advanced = find_widget<listbox>(&window, "advanced_prefs", false);
606 
607  std::map<std::string, string_map> row_data;
608 
609  for(const auto& option : adv_preferences_) {
610  const std::string& pref_name = option.field;
611 
612  row_data["pref_name"]["label"] = option.name;
613  grid* main_grid = &advanced.add_row(row_data);
614 
615  grid& details_grid = find_widget<grid>(main_grid, "prefs_setter_grid", false);
617 
618  // The toggle widget for toggle-type options (hidden for other types)
619  toggle_button& toggle_box = find_widget<toggle_button>(main_grid, "value_toggle", false);
621 
622  if(!option.description.empty()) {
623  find_widget<styled_widget>(main_grid, "description", false).set_label(option.description);
624  }
625 
626  switch(option.type) {
627  case avp::avd_type::TOGGLE: {
628  //main_grid->remove_child("setter");
629 
631  toggle_box.set_value(get(pref_name, option.cfg["default"].to_bool()));
632 
633  // We need to bind a lambda here since preferences::set is overloaded.
634  // A lambda alone would be more verbose because it'd need to specify all the parameters.
635  connect_signal_mouse_left_click(toggle_box, std::bind(
636  [&, pref_name]() { set(pref_name, toggle_box.get_value_bool()); }
637  ));
638 
639  gui2::bind_status_label<toggle_button>(
640  main_grid, "value_toggle", default_status_value_getter<toggle_button>, "value");
641 
642  break;
643  }
644 
645  case avp::avd_type::SLIDER: {
646  auto setter_widget = build_single_widget_instance<slider>(config {"definition", "minimal"});
647  setter_widget->set_id("setter");
648  // Maximum must be set first or this will assert
649  setter_widget->set_value_range(option.cfg["min"].to_int(), option.cfg["max"].to_int());
650  setter_widget->set_step_size(option.cfg["step"].to_int(1));
651 
652  details_grid.swap_child("setter", std::move(setter_widget), true);
653 
654  slider& slide = find_widget<slider>(&details_grid, "setter", false);
655 
656  slide.set_value(lexical_cast_default<int>(get(pref_name), option.cfg["default"].to_int()));
657 
658  // We need to bind a lambda here since preferences::set is overloaded.
659  // A lambda alone would be more verbose because it'd need to specify all the parameters.
660  connect_signal_notify_modified(slide, std::bind(
661  [&, pref_name]() { set(pref_name, slide.get_value()); }
662  ));
663 
664  gui2::bind_status_label<slider>(main_grid, "setter", default_status_value_getter<slider>, "value");
665 
666  break;
667  }
668 
669  case avp::avd_type::COMBO: {
670  std::vector<config> menu_data;
671  std::vector<std::string> option_ids;
672 
673  for(const config& choice : option.cfg.child_range("option")) {
674  config menu_item;
675  menu_item["label"] = choice["name"];
676  if(choice.has_attribute("description")) {
677  menu_item["details"] = std::string("<span color='#777'>") + choice["description"] + "</span>";
678  }
679  menu_data.push_back(menu_item);
680  option_ids.push_back(choice["id"]);
681  }
682 
683  // Attempt to find an initial selection
684  int selected = std::distance(option_ids.begin(), std::find(option_ids.begin(), option_ids.end(),
685  get(pref_name, option.cfg["default"].str())
686  ));
687 
688  // If the saved option value was invalid, reset selection to 0.
689  if(selected < 0 || selected >= static_cast<int>(option_ids.size())) {
690  selected = 0;
691  }
692 
693  auto setter_widget = build_single_widget_instance<menu_button>();
694  setter_widget->set_id("setter");
695 
696  details_grid.swap_child("setter", std::move(setter_widget), true);
697 
698  menu_button& menu = find_widget<menu_button>(&details_grid, "setter", false);
699 
700  menu.set_use_markup(true);
701  menu.set_values(menu_data, selected);
702 
703  // We need to bind a lambda here since preferences::set is overloaded.
704  // A lambda alone would be more verbose because it'd need to specify all the parameters.
706  std::bind([=](widget& w) { set(pref_name, option_ids[dynamic_cast<menu_button&>(w).get_value()]); }, std::placeholders::_1));
707 
708  gui2::bind_status_label<menu_button>(main_grid, "setter", default_status_value_getter<menu_button>, "value");
709 
710  break;
711  }
712 
713  case avp::avd_type::SPECIAL: {
714  //main_grid->remove_child("setter");
715 
716  auto value_widget = build_single_widget_instance<image>();
717  value_widget->set_label("icons/arrows/arrows_blank_right_25.png~CROP(3,3,18,18)");
718 
719  main_grid->swap_child("value", std::move(value_widget), true);
720 
721  break;
722  }
723  }
724  }
725 
726  connect_signal_notify_modified(advanced, std::bind(
728  this,
729  std::ref(advanced)));
730 
731  on_advanced_prefs_list_select(advanced);
732 
733  //
734  // HOTKEYS PANEL
735  //
736 
737  std::vector<config> hotkey_category_entries;
738  for(const auto& name : cat_names_) {
739  hotkey_category_entries.emplace_back("label", name.second, "checkbox", false);
740  }
741 
742  multimenu_button& hotkey_menu = find_widget<multimenu_button>(&window, "hotkey_category_menu", false);
743 
744  hotkey_menu.set_values(hotkey_category_entries);
745 
746  connect_signal_notify_modified(hotkey_menu,
748 
749  listbox& hotkey_list = setup_hotkey_list();
750 
751  text_box& filter = find_widget<text_box>(&window, "filter", false);
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, sort_order::type::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 }
784 
786 {
787  const std::string& default_icon = "misc/empty.png~CROP(0,0,15,15)";
788 
789  std::map<std::string, string_map> row_data;
790 
791  t_string& row_icon = row_data["img_icon"]["label"];
792  t_string& row_action = row_data["lbl_desc"]["label"];
793  t_string& row_hotkey = row_data["lbl_hotkey"]["label"];
794 
795  t_string& row_is_g = row_data["lbl_is_game"]["label"];
796  t_string& row_is_g_markup = row_data["lbl_is_game"]["use_markup"];
797  t_string& row_is_e = row_data["lbl_is_editor"]["label"];
798  t_string& row_is_e_markup = row_data["lbl_is_editor"]["use_markup"];
799  t_string& row_is_m = row_data["lbl_is_mainmenu"]["label"];
800  t_string& row_is_m_markup = row_data["lbl_is_mainmenu"]["use_markup"];
801 
802  listbox& hotkey_list = find_widget<listbox>(get_window(), "list_hotkeys", false);
803 
804  hotkey_list.clear();
805  visible_hotkeys_.clear();
806 
807  // These translated initials should match those used in data/gui/window/preferences/02_hotkeys.cfg
808  std::string text_game_feature_on = "<span color='#0f0'>" + _("game_hotkeys^G") + "</span>";
809  std::string text_editor_feature_on = "<span color='#0f0'>" + _("editor_hotkeys^E") + "</span>";
810  std::string text_mainmenu_feature_on = "<span color='#0f0'>" + _("mainmenu_hotkeys^M") + "</span>";
811 
812  for(const auto& hotkey_item : hotkey::get_hotkey_commands()) {
813  if(hotkey_item.hidden) {
814  continue;
815  }
816  visible_hotkeys_.push_back(&hotkey_item);
817 
818  if(filesystem::file_exists(game_config::path + "/images/icons/action/" + hotkey_item.command + "_25.png")) {
819  row_icon = "icons/action/" + hotkey_item.command + "_25.png~CROP(3,3,18,18)";
820  } else {
821  row_icon = default_icon;
822  }
823 
824  row_action = hotkey_item.description;
825  row_hotkey = hotkey::get_names(hotkey_item.command);
826 
827  row_is_g = hotkey_item.scope[hotkey::SCOPE_GAME] ? text_game_feature_on : "";
828  row_is_g_markup = "true";
829  row_is_e = hotkey_item.scope[hotkey::SCOPE_EDITOR] ? text_editor_feature_on : "";
830  row_is_e_markup = "true";
831  row_is_m = hotkey_item.scope[hotkey::SCOPE_MAIN_MENU] ? text_mainmenu_feature_on : "";
832  row_is_m_markup = "true";
833 
834  hotkey_list.add_row(row_data);
835  }
836 
837  return hotkey_list;
838 }
839 
841 {
842  int row_number = hotkeys.get_selected_row();
843  if(row_number < 0) {
844  gui2::show_transient_message("", _("No hotkey selected"));
845  return;
846  }
847 
848  const hotkey::hotkey_command& hotkey_item = *visible_hotkeys_[row_number];
849 
850  gui2::dialogs::hotkey_bind bind_dlg(hotkey_item.command);
851  bind_dlg.show();
852 
853  hotkey::hotkey_ptr newhk = bind_dlg.get_new_binding();
854  hotkey::hotkey_ptr oldhk;
855 
856  // only if not cancelled.
857  if(newhk.get() == nullptr) {
858  return;
859  }
860 
861  for(const hotkey::hotkey_ptr& hk : hotkey::get_hotkeys()) {
862  if(!hk->is_disabled() && newhk->bindings_equal(hk)) {
863  oldhk = hk;
864  }
865  }
866 
867  hotkey::scope_changer scope_restorer;
868  hotkey::set_active_scopes(hotkey_item.scope);
869 
870  if(oldhk && oldhk->get_command() == hotkey_item.command) {
871  return;
872  }
873 
874  if(oldhk && oldhk->get_command() != "null") {
875  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>”?", {
876  {"hotkey_sequence", oldhk->get_name()},
877  {"old_hotkey_action", hotkey::get_description(oldhk->get_command())},
878  {"new_hotkey_action", hotkey::get_description(newhk->get_command())}
879  });
880 
881  const int res = gui2::show_message(_("Reassign Hotkey"), text, gui2::dialogs::message::yes_no_buttons, true);
882  if(res != gui2::retval::OK) {
883  return;
884  }
885  }
886 
887  hotkey::add_hotkey(newhk);
888 
889  // We need to recalculate all hotkey names in because we might have removed a hotkey from another command.
890  for(std::size_t i = 0; i < hotkeys.get_item_count(); ++i) {
891  const hotkey::hotkey_command& hotkey_item_row = *visible_hotkeys_[i];
892  find_widget<label>(hotkeys.get_row_grid(i), "lbl_hotkey", false).set_label(hotkey::get_names(hotkey_item_row.command));
893  }
894 }
895 
897 {
898  gui2::show_transient_message(_("Hotkeys Reset"), _("All hotkeys have been reset to their default values."),
899  std::string(), false, false, true);
900 
901  clear_hotkeys();
902 
903  // Set up the list again and reselect the default sorting option.
904  listbox& hotkey_list = setup_hotkey_list();
905  hotkey_list.set_active_sorting_option({0, sort_order::type::ascending}, true);
906 
907  find_widget<multimenu_button>(get_window(), "hotkey_category_menu", false).reset_toggle_states();
908 }
909 
911 {
912  int row_number = hotkeys.get_selected_row();
913  if(row_number < 0) {
914  gui2::show_transient_message("", _("No hotkey selected"));
915  return;
916  }
917 
918  const hotkey::hotkey_command& hotkey_item = *visible_hotkeys_[row_number];
919  hotkey::clear_hotkeys(hotkey_item.command);
920  find_widget<label>(hotkeys.get_row_grid(row_number), "lbl_hotkey", false).set_label(hotkey::get_names(hotkey_item.command));
921 }
922 
924 {
925  const multimenu_button& hotkey_menu = find_widget<const multimenu_button>(get_window(), "hotkey_category_menu", false);
926  const text_box& name_filter = find_widget<const text_box>(get_window(), "filter", false);
927 
928  boost::dynamic_bitset<> toggle_states = hotkey_menu.get_toggle_states();
929  boost::dynamic_bitset<> res(visible_hotkeys_.size());
930 
931  std::string text = name_filter.get_value();
932 
933  if(toggle_states.none()) {
934  // Nothing selected. It means that *all* categories are shown.
935  toggle_states = ~toggle_states;
936  }
937 
938  for(std::size_t h = 0; h < visible_hotkeys_.size(); ++h) {
939  unsigned index = 0;
940 
941  const std::string description = visible_hotkeys_[h]->description.str();
942 
943  // Default to true if there is no filter text
944  bool found = true;
945 
946  if(!text.empty()) {
947  for(const auto& word : utils::split(text, ' ')) {
948  found = translation::ci_search(description, word);
949  if(!found) {
950  break;
951  }
952  }
953  }
954 
955  // Filter categories
956  for(const auto& name : cat_names_) {
957  if(visible_hotkeys_[h]->category == name.first) {
958  break;
959  } else {
960  ++index;
961  }
962  }
963 
964  if(index < toggle_states.size() && found) {
965  res[h] = toggle_states[index];
966  } else {
967  res[h] = false;
968  }
969  }
970 
971  find_widget<listbox>(get_window(), "list_hotkeys", false).set_row_shown(res);
972 }
973 
975 {
976  const int selected_row = list.get_selected_row();
977  const auto& pref = adv_preferences_[selected_row];
978 
979  if(pref.type == avp::avd_type::SPECIAL) {
980  if(pref.field == "logging") {
981  gui2::dialogs::log_settings::display();
982  } else if(pref.field == "orb_color") {
983  gui2::dialogs::select_orb_colors::display();
984  } else {
985  WRN_GUI_L << "Invalid or unimplemented custom advanced prefs option: " << pref.field << "\n";
986  }
987 
988  // Add more options here as needed
989  }
990 
991  const bool has_description = !pref.description.empty();
992 
993  if(has_description || (pref.type != avp::avd_type::SPECIAL && pref.type != avp::avd_type::TOGGLE)) {
994  find_widget<widget>(list.get_row_grid(selected_row), "prefs_setter_grid", false)
995  .set_visible(widget::visibility::visible);
996  }
997 
998  if(last_selected_item_ != selected_row) {
999  find_widget<widget>(list.get_row_grid(last_selected_item_), "prefs_setter_grid", false)
1000  .set_visible(widget::visibility::invisible);
1001 
1002  last_selected_item_ = selected_row;
1003  }
1004 }
1005 
1007 {
1008  //
1009  // MULTIPLAYER TABS
1010  //
1012  std::bind(&preferences_dialog::on_tab_select, this));
1013 }
1014 
1016 {
1017  set_always_save_fields(true);
1018 
1019  connect_signal_mouse_left_click(find_widget<button>(&window, "about", false), std::bind(&game_version::display<>));
1020 
1021  //
1022  // Status labels
1023  // These need to be set here in pre_show, once the fields are initialized. For some reason, this
1024  // is not the case for those in Advanced
1025  //
1026 
1027  gui2::bind_status_label<slider>(&window, "max_saves_slider");
1028  gui2::bind_status_label<slider>(&window, "turbo_slider");
1029  gui2::bind_status_label<slider>(&window, "pixel_scale_slider");
1030 
1031  //gui2::bind_status_label<slider>(&window, "scaling_slider", [](slider& s)->std::string {
1032  // return s.get_value_label() + "%";
1033  //});
1034 
1035  listbox& selector = find_widget<listbox>(&window, "selector", false);
1036  stacked_widget& pager = find_widget<stacked_widget>(&window, "pager", false);
1037 
1038  pager.set_find_in_all_layers(true);
1039 
1041  std::bind(&preferences_dialog::on_page_select, this));
1042 
1043  window.keyboard_capture(&selector);
1044 
1045  VALIDATE(selector.get_item_count() == pager.get_layer_count(),
1046  "The preferences pager and its selector listbox do not have the same number of items.");
1047 
1048  const int main_index = index_in_pager_range(initial_index_.first, pager);
1049 
1050  // Loops through each pager layer and checks if it has both a tab bar
1051  // and stack. If so, it initializes the options for the former and
1052  // selects the specified layer of the latter.
1053  for(unsigned int i = 0; i < pager.get_layer_count(); ++i) {
1054  listbox* tab_selector = find_widget<listbox>(
1055  pager.get_layer_grid(i), "tab_selector", false, false);
1056 
1057  stacked_widget* tab_pager = find_widget<stacked_widget>(
1058  pager.get_layer_grid(i), "tab_pager", false, false);
1059 
1060  if(tab_pager && tab_selector) {
1061  const int ii = static_cast<int>(i);
1062  const int tab_index = index_in_pager_range(initial_index_.second, *tab_pager);
1063  const int to_select = (ii == main_index ? tab_index : 0);
1064 
1065  // Initialize tabs for this page
1066  initialize_tabs(*tab_selector);
1067 
1068  tab_selector->select_row(to_select);
1069  tab_pager->select_layer(to_select);
1070  }
1071  }
1072 
1073  // Finally, select the initial main page
1074  selector.select_row(main_index);
1075  pager.select_layer(main_index);
1076 }
1077 
1078 void preferences_dialog::set_visible_page(unsigned int page, const std::string& pager_id)
1079 {
1080  find_widget<stacked_widget>(get_window(), pager_id, false).select_layer(page);
1081 }
1082 
1083 // Special fullsceen callback
1085 {
1086  const bool ison = find_widget<toggle_button>(get_window(), "fullscreen", false).get_value_bool();
1088 
1089  menu_button& res_list = find_widget<menu_button>(get_window(), "resolution_set", false);
1090 
1091  set_resolution_list(res_list);
1092  res_list.set_active(!ison);
1093 }
1094 
1096 {
1097  menu_button& res_list = find_widget<menu_button>(get_window(), "resolution_set", false);
1098 
1099  if(CVideo::get_singleton().set_resolution(resolutions_[res_list.get_value()])) {
1100  set_resolution_list(res_list);
1101  }
1102 }
1103 
1105 {
1106  const int selected_row =
1107  std::max(0, find_widget<listbox>(get_window(), "selector", false).get_selected_row());
1108  set_visible_page(static_cast<unsigned int>(selected_row), "pager");
1109 }
1110 
1112 {
1113  const int selected_row =
1114  std::max(0, find_widget<listbox>(get_window(), "tab_selector", false).get_selected_row());
1115  set_visible_page(static_cast<unsigned int>(selected_row), "tab_pager");
1116 }
1117 
1119 {
1120  save_hotkeys();
1121 
1122  // Save new prefs to disk. This also happens on app close, but doing
1123  // it here too ensures nothing is lost in case of, say, a crash.
1125 }
1126 
1127 } // namespace dialogs
bool disable_auto_moves()
Definition: general.cpp:976
bool show_theme_dialog()
Definition: display.cpp:65
void set_turbo(bool ison)
Definition: general.cpp:481
void set_active_sorting_option(const order_pair &sort_by, const bool select_first=false)
Sorts the listbox by a pre-set sorting option.
Definition: listbox.cpp:642
void set_hide_whiteboard(bool value)
Definition: game.cpp:448
int autosavemax()
Definition: game.cpp:798
const advanced_pref_list & get_advanced_preferences()
Gets a list of the available advanced preferences.
Definition: advanced.cpp:77
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:153
void set_grid(bool ison)
Definition: general.cpp:567
point current_resolution()
Definition: video.cpp:612
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:56
void write_preferences()
Definition: general.cpp:141
A menu_button is a styled_widget to choose an element from a list of elements.
Definition: menu_button.hpp:61
void save_hotkeys(config &cfg)
Save the non-default hotkeys to the config.
void connect_signal_mouse_left_click(dispatcher &dispatcher, const signal &signal)
Connects a signal handler for a left mouse button click.
Definition: dispatcher.cpp:172
void set_remember_password(bool remember)
void set_show_floating_labels(bool value)
Definition: game.cpp:835
New lexcical_cast header.
void show_wesnothd_server_search()
Definition: display.cpp:99
int draw_delay()
Definition: general.cpp:902
void set_scroll_speed(const int new_speed)
Definition: general.cpp:796
static bool file_exists(const bfs::path &fpath)
Definition: filesystem.cpp:263
const std::map< std::string, acquaintance > & get_acquaintances()
Definition: game.cpp:194
void set_idle_anim_rate(const int rate)
Definition: general.cpp:527
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:344
void set_show_side_colors(bool value)
Definition: game.cpp:748
int scroll_speed()
Definition: general.cpp:788
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.
bool vsync()
Definition: general.cpp:446
#define WRN_GUI_L
Definition: log.hpp:57
Base class for all widgets.
Definition: widget.hpp:49
bool hide_whiteboard()
Definition: game.cpp:443
void clear_hotkeys(const std::string &command)
Unset the command bindings for all hotkeys matching the command.
void set_chat_lines(int lines)
Definition: game.cpp:898
bool idle_anim()
Definition: general.cpp:512
Stores all information related to functions that can be bound to hotkeys.
int chat_lines()
Definition: game.cpp:893
void register_translatable_sorting_option(const int col, translatable_sorter_func_t f)
Registers a special sorting function specifically for translatable values.
Definition: listbox.cpp:634
hotkey::hotkey_ptr get_new_binding() const
Definition: hotkey_bind.hpp:32
static CVideo & get_singleton()
Definition: video.hpp:52
#define h
double turbo_speed()
Definition: general.cpp:486
int get_selected_row() const
Returns the first selected row.
Definition: listbox.cpp:271
bool animate_water()
Definition: general.cpp:827
A multimenu_button is a styled_widget to choose an element from a list of elements.
static std::string _(const char *str)
Definition: gettext.hpp:93
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:753
bool remove_acquaintance(const std::string &nick)
Definition: game.cpp:248
void set_interrupt_when_ally_sighted(bool value)
Definition: game.cpp:788
void remove_friend_list_entry(listbox &friends_list, text_box &textbox)
void set_active_scopes(hk_scopes s)
bool whisper_friends_only()
Definition: lobby.cpp:21
bool select_row(const unsigned row, const bool select=true)
Selects a row.
Definition: listbox.cpp:246
Class for a single line text area.
Definition: text_box.hpp:141
const hotkey_list & get_hotkeys()
Returns the list of hotkeys.
bool set_resolution(const unsigned width, const unsigned height)
Definition: video.cpp:701
std::string get_names(const std::string &id)
Returns a comma-separated string of hotkey names.
The listbox class.
Definition: listbox.hpp:45
Base container class.
Definition: grid.hpp:31
const config & options()
Definition: game.cpp:562
void on_friends_list_select(listbox &list, text_box &textbox)
virtual unsigned get_value() const override
Inherited from selectable_item.
Definition: menu_button.hpp:84
void set_turn_dialog(bool ison)
Definition: game.cpp:428
void set_save_replays(bool value)
Definition: game.cpp:758
bool is_friend(const std::string &nick)
Definition: game.cpp:271
#define VALIDATE(cond, message)
The macro to use for the validation of WML.
void connect_signal_mouse_left_release(dispatcher &dispatcher, const signal &signal)
Connects a signal handler for a left mouse button release.
Definition: dispatcher.cpp:182
This file contains the settings handling of the widget library.
const std::string & get_nick() const
Definition: game.hpp:61
std::ostringstream wrapper.
Definition: formatter.hpp:39
void clear()
Removes all the rows in the listbox, clearing it.
Definition: listbox.cpp:121
void set_visible(const visibility visible)
Definition: widget.cpp:477
void _set_lobby_joins(lobby_joins show)
Definition: game.cpp:352
std::pair< preferences::acquaintance *, bool > add_acquaintance(const std::string &nick, const std::string &mode, const std::string &notes)
Definition: game.cpp:229
bool fullscreen()
Definition: general.cpp:441
void set_enable_whiteboard_mode_on_start(bool value)
Definition: game.cpp:438
std::string selected
const std::string unicode_multiplication_sign
Definition: constants.cpp:46
void set_vsync(bool ison)
Definition: general.cpp:467
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:80
unsigned get_item_count() const
Returns the number of items in the listbox.
Definition: listbox.cpp:127
void add_hotkey(const hotkey_ptr item)
Add a hotkey to the list of hotkeys.
void add_friend_list_entry(const bool is_friend, text_box &textbox)
virtual void set_use_markup(bool use_markup)
void initialize_tabs(listbox &selector)
Initializers.
void set_stop_music_in_background(bool ison)
Definition: general.cpp:779
bool animate_map()
Definition: general.cpp:822
bool show_standing_animations()
Definition: display.cpp:51
void set_idle_anim(const bool ison)
Definition: general.cpp:517
void set_animate_map(bool value)
Definition: general.cpp:882
bool chat_timestamping()
Definition: game.cpp:883
std::vector< hotkey::hotkey_ptr > hotkey_list
Definition: hotkey_item.hpp:37
int pixel_scale()
Definition: general.cpp:415
hk_scopes scope
The visibility scope of the command.
void set_chat_timestamping(bool value)
Definition: game.cpp:888
void set_draw_delay(int value)
Definition: general.cpp:907
bool ci_search(const std::string &s1, const std::string &s2)
Definition: gettext.cpp:559
void update_friends_list_controls(listbox &list)
std::string id
Text to match against addon_info.tags()
Definition: manager.cpp:215
boost::dynamic_bitset get_toggle_states() const
Get the current state of the menu options.
std::size_t i
Definition: function.cpp:967
void set_visible_page(unsigned int page, const std::string &pager_id)
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:793
double idle_anim_rate()
Definition: general.cpp:522
The user set the widget invisible, that means:
bool stop_music_in_background()
Definition: general.cpp:774
void set_delete_saves(bool value)
Definition: game.cpp:768
void initialize_sound_option_group(const std::string &id_suffix)
void add_hotkey_callback(listbox &hotkeys)
void update_buffers()
Update buffers to match current resolution and pixel scale settings.
Definition: video.cpp:730
std::map< std::string, t_string > string_map
Definition: widget.hpp:26
void set_fullscreen(bool ison)
Definition: video.cpp:672
Holds a 2D point.
Definition: point.hpp:24
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:62
void set_whisper_friends_only(bool v)
Definition: lobby.cpp:26
Declarations for File-IO.
bool delete_saves()
Definition: game.cpp:773
int w
void set_turbo_speed(const double speed)
Definition: general.cpp:491
std::shared_ptr< hotkey_base > hotkey_ptr
Definition: hotkey_item.hpp:32
const std::string & get_status() const
Definition: game.hpp:62
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:72
#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:79
const std::string & get_notes() const
Definition: game.hpp:63
const std::string & get_description(const std::string &command)
void set_autosavemax(int value)
Definition: game.cpp:803
bool grid()
Definition: general.cpp:562
const grid * get_row_grid(const unsigned row) const
Returns the grid of the wanted row.
Definition: listbox.cpp:233
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 handle_res_select()
Special callback functions.
bool show_floating_labels()
Definition: game.cpp:830
lobby_joins get_lobby_joins()
Definition: game.cpp:338
The user sets the widget visible, that means:
The user sets the widget hidden, that means:
std::vector< std::string > split(const config_attribute_value &val)
const std::string & text() const
virtual void post_show(window &) override
Actions to be taken after the window has been shown.
A slider is a control that can select a value by moving a grip on a groove.
Definition: slider.hpp:59
bool enable_whiteboard_mode_on_start()
Definition: game.cpp:433
Functions to load and save images from/to disk.
virtual void set_value(int value) override
Inherited from integer_selector.
Definition: slider.cpp:81
bool turbo()
Definition: general.cpp:472
void remove_row(const unsigned row, unsigned count=1)
Removes a row in the listbox.
Definition: listbox.cpp:82
virtual void set_active(const bool active) override
See styled_widget::set_active.
Definition: menu_button.cpp:75
void set_values(const std::vector<::config > &values)
Set the available menu options.
std::unique_ptr< widget > swap_child(const std::string &id, std::unique_ptr< widget > w, const bool recurse, widget *new_parent=nullptr)
Exchanges a child in the grid.
Definition: grid.cpp:101
Dialog was closed with the OK button.
Definition: retval.hpp:35
A stacked widget holds several widgets on top of each other.
void set_pixel_scale(const int scale)
Definition: general.cpp:421
void on_page_select()
Callback for selection changes.
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:60
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:743
bool turn_dialog()
Definition: game.cpp:423
void set_animate_water(bool value)
Definition: general.cpp:887
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:65
std::vector< point > get_available_resolutions(const bool include_current=false)
Returns the list of available screen resolutions.
Definition: video.cpp:550
void set_find_in_all_layers(const bool do_find)
bool auto_pixel_scale()
Definition: general.cpp:426
bool skip_ai_moves()
Definition: game.cpp:738
Class for a toggle button.
virtual void post_build(window &window) override
Sets up states and callbacks for each of the widgets.
void connect_signal_notify_modified(dispatcher &dispatcher, const signal_notification &signal)
Connects a signal handler for getting a notification upon modification.
Definition: dispatcher.cpp:198
std::pair< std::string, unsigned > item
Definition: help_impl.hpp:410
void set_resolution_list(menu_button &res_list)
void on_advanced_prefs_list_select(listbox &tree)
void set_auto_pixel_scale(bool choice)
Definition: general.cpp:431
void set_disable_auto_moves(bool value)
Definition: general.cpp:981
bool save_replays()
Definition: game.cpp:763