The Battle for Wesnoth  1.19.8+dev
preferences_dialog.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2016 - 2024
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 "display.hpp"
22 #include "events.hpp"
23 #include "filesystem.hpp"
24 #include "formatter.hpp"
25 #include "formula/string_utils.hpp"
26 #include "game_data.hpp"
27 #include "gettext.hpp"
29 #include "hotkey/hotkey_item.hpp"
30 #include "lexical_cast.hpp"
31 #include "resources.hpp"
32 #include "theme.hpp"
33 #include "video.hpp"
34 
35 // Sub-dialog includes
42 
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"
53 #include "gui/widgets/slider.hpp"
56 #include "gui/widgets/text_box.hpp"
58 #include "gui/widgets/window.hpp"
59 
60 #include "serialization/markup.hpp"
61 #include "wml_exception.hpp"
62 
63 #include <functional>
64 #include <numeric>
65 
66 namespace gui2::dialogs
67 {
68 namespace
69 {
70 template<typename W>
71 void disable_widget_on_toggle(window& window, widget& w, const std::string& id)
72 {
73  window.find_widget<W>(id).set_active(dynamic_cast<selectable_item&>(w).get_value_bool());
74 }
75 
76 template<typename W>
77 void disable_widget_on_toggle_inverted(window& window, widget& w, const std::string& id)
78 {
79  window.find_widget<W>(id).set_active(!dynamic_cast<selectable_item&>(w).get_value_bool());
80 }
81 
82 // Ensure the specified index is between 0 and one less than the max
83 // number of pager layers (since get_layer_count returns one-past-end).
84 int index_in_pager_range(const int first, const stacked_widget& pager)
85 {
86  return std::clamp<int>(first, 0, pager.get_layer_count() - 1);
87 }
88 
89 // Helper to make it easier to immediately apply sound toggles immediately.
90 template<bool(*fptr)(bool)>
91 void sound_toggle_on_change(window& window, const std::string& id_to_toggle, widget& w)
92 {
93  std::invoke(fptr, dynamic_cast<selectable_item&>(w).get_value_bool());
94 
95  // Toggle the corresponding slider.
96  disable_widget_on_toggle<slider>(window, w, id_to_toggle);
97 }
98 
99 // Helper to make it easier to immediately apply volume (music, etc) setings on change.
100 template<void(*fptr)(int)>
101 void volume_setter_on_change(widget& w)
102 {
103  std::invoke(fptr, dynamic_cast<integer_selector&>(w).get_value());
104 }
105 
106 } // end anon namespace
107 
108 REGISTER_DIALOG(preferences_dialog)
109 
111  : modal_dialog(window_id())
112  , resolutions_() // should be populated by set_resolution_list before use
113  , themes_() // populated by set_theme_list
114  , gui2_themes_() // populated by set_gui2_theme_list
115  , last_selected_item_(0)
116  , current_gui_theme_(0)
117  , is_reload_needed_(false)
118  , accl_speeds_({0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2, 3, 4, 8, 16})
119  , visible_hotkeys_()
120  , visible_categories_()
121  , initial_index_(pef_view_map[initial_view])
122 {
123  initialize_callbacks();
124 }
125 
126 // Helper function to refresh resolution list
128 {
130 
131  std::vector<config> options;
132  for(const point& res : resolutions_) {
133  config option;
134  option["label"] = formatter() << res.x << font::unicode_multiplication_sign << res.y;
135 
136  const int div = std::gcd(res.x, res.y);
137  const int x_ratio = res.x / div;
138  const int y_ratio = res.y / div;
139 
140  if(x_ratio <= 10 || y_ratio <= 10) {
141  option["details"] = markup::span_color("#777777", "(", x_ratio, ':', y_ratio, ")");
142  }
143 
144  options.push_back(std::move(option));
145  }
146 
147  const unsigned current_res = std::distance(resolutions_.begin(), std::find(
149 
150  res_list.set_values(options, current_res);
151 }
152 
154 {
156 
157  std::vector<config> options;
158  std::size_t current_theme = 0;
159  for(std::size_t i = 0; i < themes_.size(); ++i) {
160  options.emplace_back("label", themes_[i].name, "tooltip", themes_[i].description);
161  if(themes_[i].id == prefs::get().theme()) {
162  current_theme = i;
163  }
164  }
165 
166  theme_list.set_values(options, current_theme);
167 }
168 
170 {
171  std::string current_gui_theme_name = prefs::get().gui2_theme();
172 
173  std::vector<config> options;
174  bool theme_found = false;
175  unsigned i = 0;
176  for(auto& gui : guis) {
177  gui2_themes_.emplace_back(gui.first);
178  options.emplace_back("label", gui.second.description());
179  if (current_gui_theme_name == gui.first) {
181  theme_found = true;
182  }
183  if (!theme_found) {
184  i++;
185  }
186  }
187 
188  theme_list.set_values(options);
189  theme_list.set_selected(current_gui_theme_);
190 }
191 
193 {
195  widget_item item;
196 
197  std::string image = "friend.png";
198  std::string descriptor = _("friend");
199  std::string notes;
200 
201  if(entry.get_status() == "ignore") {
202  image = "ignore.png";
203  descriptor = _("ignored");
204  }
205 
206  if(!entry.get_notes().empty()) {
207  notes = " " + markup::tag("small", "(", entry.get_notes(), ")");
208  }
209 
210  item["use_markup"] = "true";
211 
212  item["label"] = "misc/status-" + image;
213  data.emplace("friend_icon", item);
214 
215  item["label"] = entry.get_nick() + notes;
216  data.emplace("friend_name", item);
217 
218  item["label"] = markup::tag("small", descriptor);
219  data.emplace("friend_status", item);
220 
221  return data;
222 }
223 
225 {
226  const int num_friends = prefs::get().get_acquaintances().size();
227  const int sel = list.get_selected_row();
228 
229  if(sel < 0 || sel >= num_friends) {
230  return;
231  }
232 
233  std::map<std::string, preferences::acquaintance>::const_iterator who = prefs::get().get_acquaintances().begin();
234  std::advance(who, sel);
235 
236  textbox.set_value(who->second.get_nick() + " " + who->second.get_notes());
237 }
238 
240 {
241  const bool list_empty = list.get_item_count() == 0;
242 
243  if(!list_empty) {
244  list.select_row(std::min(static_cast<int>(list.get_item_count()) - 1, list.get_selected_row()));
245  }
246 
247  find_widget<button>("remove").set_active(!list_empty);
248 
249  find_widget<label>("no_friends_notice").set_visible(list_empty);
250 }
251 
252 void preferences_dialog::add_friend_list_entry(const bool is_friend, text_box& textbox)
253 {
254  std::string username = textbox.text();
255  if(username.empty()) {
256  gui2::show_transient_message("", _("No username specified"));
257  return;
258  }
259 
260  std::string reason;
261 
262  std::size_t pos = username.find_first_of(' ');
263  if(pos != std::string::npos) {
264  reason = username.substr(pos + 1);
265  username = username.substr(0, pos);
266  }
267 
268  auto [entry, added_new] = prefs::get().add_acquaintance(username, (is_friend ? "friend": "ignore"), reason);
269 
270  if(!entry) {
271  gui2::show_transient_message(_("Error"), _("Invalid username"));
272  return;
273  }
274 
275  textbox.clear();
276 
277  listbox& list = find_widget<listbox>("friends_list");
278 
279  //
280  // If this is a new entry, just add a new row. If it's not, we find the relevant
281  // row, remove it, and add a new row with the updated data. Should probably come
282  // up with a more elegant way to do .. the only reason I'm using the remove
283  // -and-replace method is to prevent any issues with the widgets' layout sizes.
284  //
285  if(added_new) {
286  list.add_row(get_friends_list_row_data(*entry));
287  } else {
288  for(unsigned i = 0; i < list.get_item_count(); ++i) {
289  grid* row_grid = list.get_row_grid(i);
290 
291  if(row_grid->find_widget<label>("friend_name").get_label() == entry->get_nick()) {
292  list.remove_row(i);
293  list.add_row(get_friends_list_row_data(*entry), i);
294 
295  break;
296  }
297  }
298  }
299 
301 }
302 
304 {
305  const int selected_row = std::max(0, friends_list.get_selected_row());
306 
307  std::map<std::string, preferences::acquaintance>::const_iterator who = prefs::get().get_acquaintances().begin();
308  std::advance(who, selected_row);
309 
310  const std::string to_remove = !textbox.text().empty() ? textbox.text() : who->second.get_nick();
311 
312  if(to_remove.empty()) {
313  gui2::show_transient_message("", _("No username specified"));
314  return;
315  }
316 
317  if(!prefs::get().remove_acquaintance(to_remove)) {
318  gui2::show_transient_error_message(_("Not on friends or ignore lists"));
319  return;
320  }
321 
322  textbox.clear();
323 
324  listbox& list = find_widget<listbox>("friends_list");
325  list.remove_row(selected_row);
326 
328 }
329 
331 {
332  // Update pixel scale preference.
333  slider& ps_slider = find_widget<slider>("pixel_scale_slider");
334  prefs::get().set_pixel_scale(ps_slider.get_value());
335 
336  // Update auto pixel scale preference.
337  toggle_button& auto_ps_toggle =
338  find_widget<toggle_button>("auto_pixel_scale");
339  prefs::get().set_auto_pixel_scale(auto_ps_toggle.get_value_bool());
340 
341  // Update draw buffers, taking these into account.
343 
344  // Update game display, if active
345  if(::display* disp = display::get_singleton()) {
346  disp->queue_rerender();
347  }
348 
349  // Raise a window resize event so we can react to the change
351 }
352 
353 template<bool(*toggle_getter)(), bool(*toggle_setter)(bool), int(*vol_getter)(), void(*vol_setter)(int)>
354 void preferences_dialog::initialize_sound_option_group(const std::string& id_suffix)
355 {
356  const std::string toggle_widget_id = "sound_toggle_" + id_suffix;
357  const std::string volume_widget_id = "sound_volume_" + id_suffix;
358 
359  // Set up the toggle. We utilize field_bool's callback-on-changed mechanism instead
360  // of manually registering the callback. Since we want the effects to apply immediately,
361  // the callback the setter callback is duplicated in the on-change callback. The field
362  // class could possibly use some reworking to make this less redundant, but for now it
363  // works well enough.
364  register_bool(toggle_widget_id, true, toggle_getter, std::bind(toggle_setter, std::placeholders::_1),
365  std::bind(sound_toggle_on_change<toggle_setter>, std::ref(*this), volume_widget_id, std::placeholders::_1), true);
366 
367  // Set up the volume slider. integer_field doesn't have a callback-on-changed mechanism.
368  // To add one would either mean adding it to the base field class or make it a proper
369  // class of is own.
370  register_integer(volume_widget_id, true, vol_getter, vol_setter);
371 
372  // Callback to actually immediately apply the volume effect.
373  connect_signal_notify_modified(find_widget<slider>(volume_widget_id),
374  std::bind(volume_setter_on_change<vol_setter>, std::placeholders::_1));
375 }
376 
377 /* SOUND FX wrappers for template */
378 static bool sound(){return prefs::get().sound();}
379 static bool set_sound(bool v){return prefs::get().set_sound(v);}
380 static int sound_volume(){return prefs::get().sound_volume();}
382 
383 /* MUSIC wrappers for template */
384 static bool music_on(){return prefs::get().music_on();}
385 static bool set_music(bool v){return prefs::get().set_music(v);}
386 static int music_volume(){return prefs::get().music_volume();}
388 
389 /* TURN BELL wrappers for template */
390 static bool turn_bell(){return prefs::get().turn_bell();}
391 static bool set_turn_bell(bool v){return prefs::get().set_turn_bell(v);}
392 static int bell_volume(){return prefs::get().bell_volume();}
393 static void set_bell_volume(int v){prefs::get().set_bell_volume(v);}
394 
395 /* UI FX wrappers for template */
396 static bool ui_sound_on(){return prefs::get().ui_sound_on();}
397 static bool set_ui_sound(bool v){return prefs::get().set_ui_sound(v);}
398 static int ui_volume(){return prefs::get().ui_volume();}
399 static void set_ui_volume(int v){prefs::get().set_ui_volume(v);}
400 
401 /**
402  * Sets up states and callbacks for each of the widgets
403  */
405 {
406  //
407  // GENERAL PANEL
408  //
409 
410  /* SCROLL SPEED */
411  register_integer("scroll_speed", true,
412  []() {return prefs::get().scroll_speed();},
413  [](int v) {prefs::get().set_scroll_speed(v);});
414 
415  /* ACCELERATED SPEED */
416  register_bool("turbo_toggle", true,
417  []() {return prefs::get().turbo();},
418  [](bool v) {prefs::get().set_turbo(v);});
419 
420  const auto accl_load = [this]()->int {
421  return std::distance(accl_speeds_.begin(), std::find(accl_speeds_.begin(), accl_speeds_.end(), prefs::get().turbo_speed()));
422  };
423 
424  const auto accl_save = [this](int i) {
425  prefs::get().set_turbo_speed(accl_speeds_[i]);
426  };
427 
428  register_integer("turbo_slider", true,
429  accl_load, accl_save);
430 
431  // Set the value label transform function.
432  find_widget<slider>("turbo_slider").set_value_labels(
433  [this](int pos, int /*max*/)->t_string { return lexical_cast<std::string>(accl_speeds_[pos]); }
434  );
435 
436  /* SKIP AI MOVES */
437  register_bool("skip_ai_moves", true,
438  []() {return prefs::get().skip_ai_moves();},
439  [](bool v) {prefs::get().set_skip_ai_moves(v);});
440 
441  /* DISABLE AUTO MOVES */
442  register_bool("disable_auto_moves", true,
443  []() {return prefs::get().disable_auto_moves();},
444  [](bool v) {prefs::get().set_disable_auto_moves(v);});
445 
446  /* TURN DIALOG */
447  register_bool("show_turn_dialog", true,
448  []() {return prefs::get().turn_dialog();},
449  [](bool v) {prefs::get().set_turn_dialog(v);});
450 
451  /* ENABLE PLANNING MODE */
452  register_bool("whiteboard_on_start", true,
453  []() {return prefs::get().enable_planning_mode_on_start();},
454  [](bool v) {prefs::get().set_enable_planning_mode_on_start(v);});
455 
456  /* HIDE ALLY PLANS */
457  register_bool("whiteboard_hide_allies", true,
458  []() {return prefs::get().hide_whiteboard();},
459  [](bool v) {prefs::get().set_hide_whiteboard(v);});
460 
461  /* INTERRUPT ON SIGHTING */
462  register_bool("interrupt_move_when_ally_sighted", true,
463  []() {return prefs::get().ally_sighted_interrupts();},
464  [](bool v) {prefs::get().set_ally_sighted_interrupts(v);});
465 
466  /* SAVE REPLAYS */
467  register_bool("save_replays", true,
468  []() {return prefs::get().save_replays();},
469  [](bool v) {prefs::get().set_save_replays(v);});
470 
471  /* DELETE AUTOSAVES */
472  register_bool("delete_saves", true,
473  []() {return prefs::get().delete_saves();},
474  [](bool v) {prefs::get().set_delete_saves(v);});
475 
476  /* MAX AUTO SAVES */
477  register_integer("max_saves_slider", true,
478  []() {return prefs::get().auto_save_max();},
479  [](int v) {prefs::get().set_auto_save_max(v);});
480 
481  /* CACHE MANAGE */
482  connect_signal_mouse_left_click(find_widget<button>("cachemg"),
483  std::bind(&gui2::dialogs::game_cache_options::display<>));
484 
485  //
486  // DISPLAY PANEL
487  //
488 
489  /* FULLSCREEN TOGGLE */
491  find_widget<toggle_button>("fullscreen");
492 
493  toggle_fullscreen.set_value(prefs::get().fullscreen());
494 
495  // We bind a special callback function, so setup_single_toggle() is not used
498 
499  /* SET RESOLUTION */
500  menu_button& res_list = find_widget<menu_button>("resolution_set");
501 
502  res_list.set_use_markup(true);
503  res_list.set_active(!prefs::get().fullscreen());
504 
505  set_resolution_list(res_list);
506 
508  std::bind(&preferences_dialog::handle_res_select, this));
509 
510  connect_signal<event::SDL_VIDEO_RESIZE>(std::bind(&preferences_dialog::set_resolution_list, this, std::ref(res_list)));
511 
512  /* PIXEL SCALE */
513  register_integer("pixel_scale_slider", true,
514  []() {return prefs::get().pixel_scale();},
515  [](int v) {prefs::get().set_pixel_scale(v);});
516 
517  slider& ps_slider =
518  find_widget<slider>("pixel_scale_slider");
520  std::bind(&preferences_dialog::apply_pixel_scale, this));
521 
522  /* AUTOMATIC PIXEL SCALE */
523  register_bool("auto_pixel_scale", true,
524  []() {return prefs::get().auto_pixel_scale();},
525  [](bool v) {prefs::get().set_auto_pixel_scale(v);},
526  [&](widget& w) { disable_widget_on_toggle_inverted<slider>(*this, w, "pixel_scale_slider"); }, true);
527 
528  toggle_button& auto_ps_toggle =
529  find_widget<toggle_button>("auto_pixel_scale");
530  connect_signal_mouse_left_click(auto_ps_toggle,
531  std::bind(&preferences_dialog::apply_pixel_scale, this));
532 
533  /* SHOW TIPS PANEL ON TITLESCREEN */
534  register_bool("show_tips", true,
535  []() {return prefs::get().show_tips();},
536  [&](bool v) {
537  // if changed once: different value, reload
538  // if changed twice: double toggle, same value, don't reload
540  prefs::get().set_show_tips(v);
541  });
542 
543  /* SHOW FLOATING LABELS */
544  register_bool("show_floating_labels", true,
545  []() {return prefs::get().floating_labels();},
546  [](bool v) {prefs::get().set_floating_labels(v);});
547 
548  /* SHOW TEAM COLORS */
549  register_bool("show_ellipses", true,
550  []() {return prefs::get().show_side_colors();},
551  [](bool v) {prefs::get().set_show_side_colors(v);});
552 
553  /* SHOW GRID */
554  register_bool("show_grid", true,
555  []() {return prefs::get().grid();},
556  [](bool v) {prefs::get().set_grid(v);});
557 
558  /* ANIMATE MAP */
559  register_bool("animate_terrains", true,
560  []() {return prefs::get().animate_map();},
561  [](bool v) {prefs::get().set_animate_map(v);},
562  [&](widget& w) { disable_widget_on_toggle<toggle_button>(*this, w, "animate_water"); }, true);
563 
564  /* ANIMATE WATER */
565  register_bool("animate_water", true,
566  []() {return prefs::get().animate_water();},
567  [](bool v) {prefs::get().set_animate_water(v);});
568 
569  /* SHOW UNIT STANDING ANIMS */
570  register_bool("animate_units_standing", true,
571  []() {return prefs::get().show_standing_animations();},
572  [](bool v) {prefs::get().set_show_standing_animations(v);});
573 
574  /* SHOW UNIT IDLE ANIMS */
575  register_bool("animate_units_idle", true,
576  []() {return prefs::get().idle_anim();},
577  [](bool v) {prefs::get().set_idle_anim(v);},
578  [&](widget& w) { disable_widget_on_toggle<slider>(*this, w, "idle_anim_frequency"); }, true);
579 
580  register_integer("idle_anim_frequency", true,
581  []() {return prefs::get().idle_anim_rate();},
582  [](int v) {prefs::get().set_idle_anim_rate(v);});
583 
584  /* FONT SCALING */
585  //register_integer("scaling_slider", true,
586  // font_scaling, set_font_scaling);
587 
588  /* VSYNC */
589  register_bool("vsync", true,
590  []() {return prefs::get().vsync();},
591  [](bool v) {prefs::get().set_vsync(v);});
592 
593  /* SELECT THEME */
594  menu_button& theme_list = find_widget<menu_button>("choose_theme");
597  std::bind(&preferences_dialog::handle_theme_select, this));
598 
599  /* SELECT GUI2 THEME */
600  menu_button& gui2_theme_list = find_widget<menu_button>("choose_gui2_theme");
601  button& apply_btn = find_widget<button>("apply");
602  set_gui2_theme_list(gui2_theme_list);
603  connect_signal_notify_modified(gui2_theme_list, [&](auto&&...) { apply_btn.set_active(true); });
604  apply_btn.set_active(false);
607 
608  //
609  // SOUND PANEL
610  //
611 
612  /* SOUND FX */
613  initialize_sound_option_group<sound, set_sound, sound_volume, set_sound_volume>("sfx");
614 
615  /* MUSIC */
616  initialize_sound_option_group<music_on, set_music, music_volume, set_music_volume>("music");
617 
618  register_bool("sound_toggle_stop_music_in_background", true,
619  []() {return prefs::get().stop_music_in_background();},
620  [](bool v) {prefs::get().set_stop_music_in_background(v);});
621 
622  /* TURN BELL */
623  initialize_sound_option_group<turn_bell, set_turn_bell, bell_volume, set_bell_volume>("bell");
624 
625  /* UI FX */
626  initialize_sound_option_group<ui_sound_on, set_ui_sound, ui_volume, set_ui_volume>("uisfx");
627 
628  //
629  // MULTIPLAYER PANEL
630  //
631 
632  /* CHAT LINES */
633  register_integer("chat_lines", true,
634  []() {return prefs::get().chat_lines();},
635  [](int v) {prefs::get().set_chat_lines(v);});
636 
637  /* CHAT TIMESTAMPPING */
638  register_bool("chat_timestamps", true,
639  []() {return prefs::get().chat_timestamp();},
640  [](bool v) {prefs::get().set_chat_timestamp(v);});
641 
642  /* SAVE PASSWORD */
643  register_bool("remember_password", true,
644  []() {return prefs::get().remember_password();},
645  [](bool v) {prefs::get().set_remember_password(v);});
646 
647  /* WHISPERS FROM FRIENDS ONLY */
648  register_bool("lobby_whisper_friends_only", true,
649  []() {return prefs::get().lobby_whisper_friends_only();},
650  [](bool v) {prefs::get().set_lobby_whisper_friends_only(v);});
651 
652  /* LOBBY JOIN NOTIFICATIONS */
653  lobby_joins_group.add_member(find_widget<toggle_button>("lobby_joins_none", false, true), pref_constants::lobby_joins::show_none);
654  lobby_joins_group.add_member(find_widget<toggle_button>("lobby_joins_friends", false, true), pref_constants::lobby_joins::show_friends);
655  lobby_joins_group.add_member(find_widget<toggle_button>("lobby_joins_all", false, true), pref_constants::lobby_joins::show_all);
656 
658 
661  });
662 
663  /* FRIENDS LIST */
664  listbox& friends_list = find_widget<listbox>("friends_list");
665 
666  friends_list.clear();
667 
668  for(const auto& entry : prefs::get().get_acquaintances()) {
669  friends_list.add_row(get_friends_list_row_data(entry.second));
670  }
671 
672  update_friends_list_controls(friends_list);
673 
674  text_box& textbox = find_widget<text_box>("friend_name_box");
675 
677  find_widget<button>("add_friend"), std::bind(
679  this, true,
680  std::ref(textbox)));
681 
683  find_widget<button>("add_ignored"), std::bind(
685  this, false,
686  std::ref(textbox)));
687 
689  find_widget<button>("remove"), std::bind(
691  this,
692  std::ref(friends_list),
693  std::ref(textbox)));
694 
695  connect_signal_notify_modified(friends_list, std::bind(
697  this,
698  std::ref(friends_list),
699  std::ref(textbox)));
700 
701  /* ALERTS */
703  find_widget<button>("mp_alerts"),
704  std::bind(&gui2::dialogs::mp_alerts_options::display<>));
705 
706  /* SET WESNOTHD PATH */
708  find_widget<button>("mp_wesnothd"), [](auto&&...) { return prefs::get().show_wesnothd_server_search(); });
709 
710 
711  //
712  // ADVANCED PANEL
713  //
714 
715  listbox& advanced = find_widget<listbox>("advanced_prefs");
716 
717  widget_data row_data;
718 
719  for(const auto& option : prefs::get().get_advanced_preferences()) {
720  const std::string pref_name = option.field;
721 
722  row_data["pref_name"]["label"] = option.name;
723  grid* main_grid = &advanced.add_row(row_data);
724 
725  grid& details_grid = main_grid->find_widget<grid>("prefs_setter_grid");
727 
728  // The toggle widget for toggle-type options (hidden for other types)
729  toggle_button& toggle_box = main_grid->find_widget<toggle_button>("value_toggle");
731 
732  if(!option.description.empty()) {
733  main_grid->find_widget<styled_widget>("description").set_label(option.description);
734  }
735 
736  switch(option.type) {
738 
740  toggle_box.set_value(preferences_dialog_friend::get(pref_name, option.cfg["default"].to_bool()));
741 
742  // A lambda alone would be more verbose because it'd need to specify all the parameters.
743  connect_signal_mouse_left_click(toggle_box, std::bind(
744  [&, pref_name]() { preferences_dialog_friend::set(pref_name, toggle_box.get_value_bool()); }
745  ));
746 
747  gui2::bind_status_label<toggle_button>(
748  main_grid, "value_toggle", default_status_value_getter<toggle_button>, "value");
749 
750  break;
751  }
752 
754  auto setter_widget = build_single_widget_instance<slider>(config {"definition", "minimal"});
755  setter_widget->set_id("setter");
756  // Maximum must be set first or this will assert
757  setter_widget->set_value_range(option.cfg["min"].to_int(), option.cfg["max"].to_int());
758  setter_widget->set_step_size(option.cfg["step"].to_int(1));
759 
760  details_grid.swap_child("setter", std::move(setter_widget), true);
761 
762  slider& slide = details_grid.find_widget<slider>("setter");
763 
764  slide.set_value(preferences_dialog_friend::get(pref_name, option.cfg["default"].to_int()));
765 
766  // A lambda alone would be more verbose because it'd need to specify all the parameters.
767  connect_signal_notify_modified(slide, std::bind(
768  [&, pref_name]() { preferences_dialog_friend::set(pref_name, slide.get_value()); }
769  ));
770 
771  gui2::bind_status_label<slider>(main_grid, "setter", default_status_value_getter<slider>, "value");
772 
773  break;
774  }
775 
777  std::vector<config> menu_data;
778  std::vector<std::string> option_ids;
779 
780  for(const config& choice : option.cfg.child_range("option")) {
781  config menu_item;
782  menu_item["label"] = choice["name"];
783  if(choice.has_attribute("description")) {
784  menu_item["details"] = markup::span_color("#777", choice["description"]);
785  }
786  menu_data.push_back(menu_item);
787  option_ids.push_back(choice["id"]);
788  }
789 
790  // Attempt to find an initial selection
791  int selected = std::distance(option_ids.begin(), std::find(option_ids.begin(), option_ids.end(),
792  preferences_dialog_friend::get(pref_name, option.cfg["default"].str())
793  ));
794 
795  // If the saved option value was invalid, reset selection to 0.
796  if(selected < 0 || selected >= static_cast<int>(option_ids.size())) {
797  selected = 0;
798  }
799 
800  auto setter_widget = build_single_widget_instance<menu_button>();
801  setter_widget->set_id("setter");
802 
803  details_grid.swap_child("setter", std::move(setter_widget), true);
804 
805  menu_button& menu = details_grid.find_widget<menu_button>("setter");
806 
807  menu.set_use_markup(true);
808  menu.set_values(menu_data, selected);
809 
811  [=](widget& w, auto&&...) { preferences_dialog_friend::set(pref_name, option_ids[dynamic_cast<menu_button&>(w).get_value()]); });
812 
813  gui2::bind_status_label<menu_button>(main_grid, "setter", default_status_value_getter<menu_button>, "value");
814 
815  break;
816  }
817 
819  //main_grid->remove_child("setter");
820 
821  auto value_widget = build_single_widget_instance<image>();
822  value_widget->set_label("icons/arrows/arrows_blank_right_25.png~CROP(3,3,18,18)");
823 
824  main_grid->swap_child("value", std::move(value_widget), true);
825 
826  break;
827  }
828  }
829  }
830 
831  connect_signal_notify_modified(advanced, std::bind(
833  this,
834  std::ref(advanced)));
835 
837 
838  //
839  // HOTKEYS PANEL
840  //
841 
842  multimenu_button& hotkey_menu = find_widget<multimenu_button>("hotkey_category_menu");
843  connect_signal_notify_modified(hotkey_menu,
845 
847 
848  text_box& filter = find_widget<text_box>("filter");
849  filter.on_modified([this](const auto&) { hotkey_filter_callback(); });
850 
851  hotkey_list.set_sorters(
852  // Action column
853  [this](const std::size_t i) { return visible_hotkeys_[i]->description; },
854 
855  // Hotkey column
856  [this](const std::size_t i) { return hotkey::get_names(visible_hotkeys_[i]->id); },
857 
858  // Scope columns
859  [this](const std::size_t i) { return !visible_hotkeys_[i]->scope[hotkey::SCOPE_GAME]; },
860  [this](const std::size_t i) { return !visible_hotkeys_[i]->scope[hotkey::SCOPE_EDITOR]; },
861  [this](const std::size_t i) { return !visible_hotkeys_[i]->scope[hotkey::SCOPE_MAIN_MENU]; }
862  );
863 
864  hotkey_list.set_active_sorter("sort_0", sort_order::type::ascending, true);
865 
867  find_widget<button>("btn_add_hotkey"), std::bind(
869  this,
870  std::ref(hotkey_list)));
871 
873  find_widget<button>("btn_clear_hotkey"), std::bind(
875  this,
876  std::ref(hotkey_list)));
877 
879  find_widget<button>("btn_reset_hotkeys"), std::bind(
881  this));
882 }
883 
885 {
886  widget_data row_data;
887 
888  t_string& row_icon = row_data["img_icon"]["label"];
889  t_string& row_action = row_data["lbl_desc"]["label"];
890  t_string& row_hotkey = row_data["lbl_hotkey"]["label"];
891 
892  t_string& row_is_g = row_data["lbl_is_game"]["label"];
893  t_string& row_is_e = row_data["lbl_is_editor"]["label"];
894  t_string& row_is_m = row_data["lbl_is_mainmenu"]["label"];
895 
896  listbox& hotkey_list = find_widget<listbox>("list_hotkeys");
897 
898  hotkey_list.clear();
899  visible_hotkeys_.clear();
900  visible_categories_.clear();
901 
902  //
903  // Main hotkeys list
904  //
905 
906  // These translated initials should match those used in data/gui/window/preferences/02_hotkeys.cfg
907  const std::string gh = markup::span_color("#0f0", _("game_hotkeys^G"));
908  const std::string eh = markup::span_color("#0f0", _("editor_hotkeys^E"));
909  const std::string mh = markup::span_color("#0f0", _("mainmenu_hotkeys^M"));
910 
911  for(const auto& [id, hotkey_item] : hotkey::get_hotkey_commands()) {
912  if(hotkey_item.hidden) {
913  continue;
914  }
915 
916  visible_hotkeys_.push_back(&hotkey_item);
917  visible_categories_.insert(hotkey_item.category);
918 
919  if(filesystem::file_exists(game_config::path + "/images/icons/action/" + hotkey_item.id + "_25.png")) {
920  row_icon = "icons/action/" + hotkey_item.id + "_25.png~CROP(3,3,18,18)";
921  } else {
922  row_icon = "";
923  }
924 
925  row_action = hotkey_item.description;
926  row_hotkey = hotkey::get_names(hotkey_item.id);
927 
928  row_is_g = hotkey_item.scope[hotkey::SCOPE_GAME] ? gh : "";
929  row_is_e = hotkey_item.scope[hotkey::SCOPE_EDITOR] ? eh : "";
930  row_is_m = hotkey_item.scope[hotkey::SCOPE_MAIN_MENU] ? mh : "";
931 
932  hotkey_list.add_row(row_data);
933  }
934 
935  //
936  // Filter options
937  //
938 
939  std::vector<config> filter_ops;
940  for(const hotkey::HOTKEY_CATEGORY& cat : visible_categories_) {
941  filter_ops.emplace_back("label", hotkey::get_translatable_category_name(cat), "checkbox", false);
942  }
943 
944  find_widget<multimenu_button>("hotkey_category_menu").set_values(filter_ops);
945 
946  return hotkey_list;
947 }
948 
950 {
951  int row_number = hotkeys.get_selected_row();
952  if(row_number < 0) {
953  gui2::show_transient_message("", _("No hotkey selected"));
954  return;
955  }
956 
957  const hotkey::hotkey_command& hotkey_item = *visible_hotkeys_[row_number];
958 
959  gui2::dialogs::hotkey_bind bind_dlg(hotkey_item.id);
960  bind_dlg.show();
961 
962  hotkey::hotkey_ptr newhk = bind_dlg.get_new_binding();
963  hotkey::hotkey_ptr oldhk;
964 
965  // only if not cancelled.
966  if(newhk.get() == nullptr) {
967  return;
968  }
969 
970  for(const hotkey::hotkey_ptr& hk : hotkey::get_hotkeys()) {
971  if(!hk->is_disabled() && newhk->bindings_equal(hk)) {
972  oldhk = hk;
973  }
974  }
975 
976  if(oldhk && oldhk->get_command() == hotkey_item.id) {
977  return;
978  }
979 
980  if(oldhk && oldhk->get_command() != "null") {
981  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>”?", {
982  {"hotkey_sequence", oldhk->get_name()},
983  {"old_hotkey_action", hotkey::get_hotkey_command(oldhk->get_command()).description},
984  {"new_hotkey_action", hotkey::get_hotkey_command(newhk->get_command()).description}
985  });
986 
987  const int res = gui2::show_message(_("Reassign Hotkey"), text, gui2::dialogs::message::yes_no_buttons, true);
988  if(res != gui2::retval::OK) {
989  return;
990  }
991  }
992 
993  hotkey::add_hotkey(newhk);
994 
995  // We need to recalculate all hotkey names in because we might have removed a hotkey from another command.
996  for(std::size_t i = 0; i < hotkeys.get_item_count(); ++i) {
997  const hotkey::hotkey_command& hotkey_item_row = *visible_hotkeys_[i];
998  hotkeys.get_row_grid(i)->find_widget<label>("lbl_hotkey").set_label(hotkey::get_names(hotkey_item_row.id));
999  }
1000 }
1001 
1003 {
1004  gui2::show_transient_message(_("Hotkeys Reset"), _("All hotkeys have been reset to their default values."));
1005 
1007 
1008  // Set up the list again and reselect the default sorting option.
1010  hotkey_list.set_active_sorter("sort_0", sort_order::type::ascending, true);
1011 }
1012 
1014 {
1015  int row_number = hotkeys.get_selected_row();
1016  if(row_number < 0) {
1017  gui2::show_transient_message("", _("No hotkey selected"));
1018  return;
1019  }
1020 
1021  const hotkey::hotkey_command& hotkey_item = *visible_hotkeys_[row_number];
1022  hotkey::clear_hotkeys(hotkey_item.id);
1023  hotkeys.get_row_grid(row_number)->find_widget<label>("lbl_hotkey").set_label(hotkey::get_names(hotkey_item.id));
1024 }
1025 
1027 {
1028  const multimenu_button& hotkey_menu = find_widget<const multimenu_button>("hotkey_category_menu");
1029  const text_box& name_filter = find_widget<const text_box>("filter");
1030 
1031  boost::dynamic_bitset<> toggle_states = hotkey_menu.get_toggle_states();
1032  boost::dynamic_bitset<> res(visible_hotkeys_.size());
1033 
1034  std::string text = name_filter.get_value();
1035 
1036  // Nothing selected. It means that *all* categories are shown.
1037  if(toggle_states.none()) {
1038  toggle_states = ~toggle_states;
1039  }
1040 
1041  for(std::size_t h = 0; h < visible_hotkeys_.size(); ++h) {
1042  // Default to true if there is no filter text
1043  bool found = true;
1044 
1045  if(!text.empty()) {
1046  const std::string description = visible_hotkeys_[h]->description.str();
1047 
1048  for(const auto& word : utils::split(text, ' ')) {
1049  found = translation::ci_search(description, word);
1050 
1051  // No match, we're excluding this hotkey
1052  if(!found) {
1053  break;
1054  }
1055  }
1056  }
1057 
1058  unsigned cat_index = 0;
1059 
1060  // Filter categories
1061  for(const hotkey::HOTKEY_CATEGORY& cat : visible_categories_) {
1062  if(visible_hotkeys_[h]->category == cat) {
1063  break;
1064  } else {
1065  ++cat_index;
1066  }
1067  }
1068 
1069  if(cat_index < toggle_states.size() && found) {
1070  res[h] = toggle_states[cat_index];
1071  } else {
1072  res[h] = false;
1073  }
1074  }
1075 
1076  find_widget<listbox>("list_hotkeys").set_row_shown(res);
1077 }
1078 
1080 {
1081  const int selected_row = list.get_selected_row();
1082  const auto& pref = prefs::get().get_advanced_preferences()[selected_row];
1083 
1084  if(pref.type == preferences::option::avd_type::SPECIAL) {
1085  if(pref.field == "logging") {
1086  gui2::dialogs::log_settings::display();
1087  } else if(pref.field == "orb_color") {
1088  gui2::dialogs::select_orb_colors::display();
1089  } else {
1090  WRN_GUI_L << "Invalid or unimplemented custom advanced prefs option: " << pref.field;
1091  }
1092 
1093  // Add more options here as needed
1094  }
1095 
1096  const bool has_description = !pref.description.empty();
1097 
1098  if(has_description || (pref.type != preferences::option::avd_type::SPECIAL && pref.type != preferences::option::avd_type::TOGGLE)) {
1099  list.get_row_grid(selected_row)->find_widget<widget>("prefs_setter_grid")
1101  }
1102 
1103  if(last_selected_item_ != selected_row) {
1104  list.get_row_grid(last_selected_item_)->find_widget<widget>("prefs_setter_grid")
1106 
1107  last_selected_item_ = selected_row;
1108  }
1109 }
1110 
1112 {
1113  //
1114  // MULTIPLAYER TABS
1115  //
1117  std::bind(&preferences_dialog::on_tab_select, this));
1118 }
1119 
1121 {
1122  set_always_save_fields(true);
1123 
1124  connect_signal_mouse_left_click(find_widget<button>("about"), std::bind(&game_version::display<>));
1125 
1126  //
1127  // Status labels
1128  // These need to be set here in pre_show, once the fields are initialized. For some reason, this
1129  // is not the case for those in Advanced
1130  //
1131 
1132  gui2::bind_status_label<slider>(this, "max_saves_slider");
1133  gui2::bind_status_label<slider>(this, "turbo_slider");
1134  gui2::bind_status_label<slider>(this, "pixel_scale_slider");
1135 
1136  //gui2::bind_status_label<slider>("scaling_slider", [](slider& s)->std::string {
1137  // return s.get_value_label() + "%";
1138  //});
1139 
1140  listbox& selector = find_widget<listbox>("selector");
1141  stacked_widget& pager = find_widget<stacked_widget>("pager");
1142 
1143  pager.set_find_in_all_layers(true);
1144 
1146  std::bind(&preferences_dialog::on_page_select, this));
1147 
1148  keyboard_capture(&selector);
1149 
1150  VALIDATE(selector.get_item_count() == pager.get_layer_count(),
1151  "The preferences pager and its selector listbox do not have the same number of items.");
1152 
1153  const int main_index = index_in_pager_range(initial_index_.first, pager);
1154 
1155  // Loops through each pager layer and checks if it has both a tab bar
1156  // and stack. If so, it initializes the options for the former and
1157  // selects the specified layer of the latter.
1158  for(unsigned int i = 0; i < pager.get_layer_count(); ++i) {
1159  listbox* tab_selector = pager.get_layer_grid(i)->find_widget<listbox>("tab_selector", false, false);
1160 
1161  stacked_widget* tab_pager = pager.get_layer_grid(i)->find_widget<stacked_widget>("tab_pager", false, false);
1162 
1163  if(tab_pager && tab_selector) {
1164  const int ii = static_cast<int>(i);
1165  const int tab_index = index_in_pager_range(initial_index_.second, *tab_pager);
1166  const int to_select = (ii == main_index ? tab_index : 0);
1167 
1168  // Initialize tabs for this page
1169  initialize_tabs(*tab_selector);
1170 
1171  tab_selector->select_row(to_select);
1172  tab_pager->select_layer(to_select);
1173  }
1174  }
1175 
1176  // Finally, select the initial main page
1177  selector.select_row(main_index);
1178  pager.select_layer(main_index);
1179 }
1180 
1181 void preferences_dialog::set_visible_page(unsigned int page, const std::string& pager_id)
1182 {
1183  find_widget<stacked_widget>(pager_id).select_layer(page);
1184 }
1185 
1186 // Special fullsceen callback
1188 {
1189  const bool ison = find_widget<toggle_button>("fullscreen").get_value_bool();
1190  video::set_fullscreen(ison);
1191 
1192  menu_button& res_list = find_widget<menu_button>("resolution_set");
1193 
1194  set_resolution_list(res_list);
1195  res_list.set_active(!ison);
1196 }
1197 
1199 {
1200  menu_button& res_list = find_widget<menu_button>("resolution_set");
1201 
1202  if(video::set_resolution(resolutions_[res_list.get_value()])) {
1203  set_resolution_list(res_list);
1204  }
1205 }
1206 
1208 {
1209  menu_button& theme_list = find_widget<menu_button>("choose_theme");
1210 
1211  const auto selection = theme_list.get_value();
1212  const auto& theme = themes_.at(selection);
1213  auto* display = display::get_singleton();
1214 
1215  prefs::get().set_theme(theme.id);
1216  if(display && resources::gamedata && resources::gamedata->get_theme().empty()) {
1217  display->set_theme(theme.id);
1218  }
1219 
1220 }
1221 
1223 {
1224  menu_button& gui2_theme_list = find_widget<menu_button>("choose_gui2_theme");
1225  unsigned selected_theme = gui2_theme_list.get_value();
1226  if (selected_theme != current_gui_theme_) {
1227  current_gui_theme_ = selected_theme;
1228  prefs::get().set_gui2_theme(gui2_themes_.at(selected_theme));
1230  }
1231 }
1232 
1234 {
1235  const int selected_row =
1236  std::max(0, find_widget<listbox>("selector").get_selected_row());
1237  set_visible_page(static_cast<unsigned int>(selected_row), "pager");
1238 }
1239 
1241 {
1242  const int selected_row =
1243  std::max(0, find_widget<listbox>("tab_selector").get_selected_row());
1244  set_visible_page(static_cast<unsigned int>(selected_row), "tab_pager");
1245 }
1246 
1248 {
1250 
1251  // Save new prefs to disk. This also happens on app close, but doing
1252  // it here too ensures nothing is lost in case of, say, a crash.
1254 
1255  // Needed for applying changes to tip panel visiblity on dialog close
1256  if (is_reload_needed_) {
1258  }
1259 }
1260 
1261 } // namespace dialogs
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:158
child_itors child_range(config_key_type key)
Definition: config.cpp:268
Sort-of-Singleton that many classes, both GUI and non-GUI, use to access the game data.
Definition: display.hpp:97
void set_theme(const std::string &new_theme)
Definition: display.cpp:249
static display * get_singleton()
Returns the display object if a display object exists.
Definition: display.hpp:111
std::ostringstream wrapper.
Definition: formatter.hpp:40
Simple push button.
Definition: button.hpp:36
virtual void set_active(const bool active) override
See styled_widget::set_active.
Definition: button.cpp:64
hotkey::hotkey_ptr get_new_binding() const
Definition: hotkey_bind.hpp:31
@ yes_no_buttons
Shows a yes and no button.
Definition: message.hpp:81
Abstract base class for all modal dialogs.
field_bool * register_bool(const std::string &id, const bool mandatory, const std::function< bool()> &callback_load_value=nullptr, const std::function< void(bool)> &callback_save_value=nullptr, const std::function< void(widget &)> &callback_change=nullptr, const bool initial_fire=false)
Creates a new boolean field.
void set_always_save_fields(const bool always_save_fields)
field_integer * register_integer(const std::string &id, const bool mandatory, const std::function< int()> &callback_load_value=nullptr, const std::function< void(int)> &callback_save_value=nullptr)
Creates a new integer field.
bool show(const unsigned auto_close_time=0)
Shows the window.
void set_visible_page(unsigned int page, const std::string &pager_id)
void set_theme_list(menu_button &theme_list)
void remove_hotkey_callback(listbox &hotkeys)
const std::pair< int, int > & initial_index_
void set_resolution_list(menu_button &res_list)
void on_advanced_prefs_list_select(listbox &tree)
void on_page_select()
Callback for selection changes.
void on_friends_list_select(listbox &list, text_box &textbox)
void add_friend_list_entry(const bool is_friend, text_box &textbox)
std::vector< const hotkey::hotkey_command * > visible_hotkeys_
widget_data get_friends_list_row_data(const preferences::acquaintance &entry)
virtual void post_show() override
Actions to be taken after the window has been shown.
std::set< hotkey::HOTKEY_CATEGORY > visible_categories_
void update_friends_list_controls(listbox &list)
void handle_res_select()
Special callback functions.
std::vector< std::string > gui2_themes_
virtual void pre_show() override
Actions to be taken before showing the window.
void remove_friend_list_entry(listbox &friends_list, text_box &textbox)
void initialize_sound_option_group(const std::string &id_suffix)
void add_hotkey_callback(listbox &hotkeys)
group< pref_constants::lobby_joins > lobby_joins_group
void set_gui2_theme_list(menu_button &theme_list)
Base container class.
Definition: grid.hpp:32
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
unsigned add_row(const unsigned count=1)
Adds a row to end of the grid.
Definition: grid.cpp:60
void on_modified(const Func &func)
Sets a common callback function for all members.
Definition: group.hpp:121
void add_member(selectable_item *w, const T &value)
Adds a widget/value pair to the group map.
Definition: group.hpp:41
void set_member_states(const T &value)
Sets the toggle values for all widgets besides the one associated with the specified value to false.
Definition: group.hpp:110
The listbox class.
Definition: listbox.hpp:41
grid & add_row(const widget_item &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:92
const grid * get_row_grid(const unsigned row) const
Returns the grid of the wanted row.
Definition: listbox.cpp:267
bool select_row(const unsigned row, const bool select=true)
Selects a row.
Definition: listbox.cpp:280
void remove_row(const unsigned row, unsigned count=1)
Removes a row in the listbox.
Definition: listbox.cpp:112
void clear()
Removes all the rows in the listbox, clearing it.
Definition: listbox.cpp:153
int get_selected_row() const
Returns the first selected row.
Definition: listbox.cpp:305
unsigned get_item_count() const
Returns the number of items in the listbox.
Definition: listbox.cpp:159
void set_values(const std::vector<::config > &values, unsigned selected=0)
virtual unsigned get_value() const override
Inherited from selectable_item.
Definition: menu_button.hpp:55
virtual void set_active(const bool active) override
See styled_widget::set_active.
Definition: menu_button.cpp:74
boost::dynamic_bitset get_toggle_states() const
Get the current state of the menu options.
virtual void set_value(int value) override
Inherited from integer_selector.
Definition: slider.cpp:81
virtual int get_value() const override
Inherited from integer_selector.
Definition: slider.hpp:52
grid * get_layer_grid(unsigned int i)
Gets the grid for a specified layer.
unsigned int get_layer_count() const
Gets the total number of layers.
void set_find_in_all_layers(const bool do_find)
void select_layer(const int layer)
Selects and displays a particular layer.
const t_string & get_label() const
virtual void set_label(const t_string &text)
virtual void set_use_markup(bool use_markup)
std::string get_value() const
const std::string & text() const
virtual void set_value(const std::string &text)
The set_value is virtual for the password_box class.
A widget that allows the user to input text in single line.
Definition: text_box.hpp:125
virtual void set_value(unsigned selected, bool fire_event=false) override
Inherited from selectable_item.
Base class for all widgets.
Definition: widget.hpp:55
void set_visible(const visibility visible)
Definition: widget.cpp:479
@ visible
The user sets the widget visible, that means:
@ invisible
The user set the widget invisible, that means:
@ hidden
The user sets the widget hidden, that means:
T * find_widget(const std::string_view id, const bool must_be_active, const bool must_exist)
Gets a widget with the wanted id.
Definition: widget.hpp:747
void set_retval(const int retval, const bool close_window=true)
Sets there return value of the window.
Definition: window.hpp:395
void keyboard_capture(widget *widget)
Definition: window.cpp:1193
const std::string & get_status() const
Definition: preferences.hpp:92
const std::string & get_nick() const
Definition: preferences.hpp:91
const std::string & get_notes() const
Definition: preferences.hpp:93
void set_lobby_joins(pref_constants::lobby_joins show)
bool set_music(bool ison)
void set_sound_volume(int vol)
void set_remember_password(bool remember)
const std::map< std::string, preferences::acquaintance > & get_acquaintances()
void set_turbo(bool ison)
void save_hotkeys()
bool turn_bell()
void write_preferences()
bool set_ui_sound(bool ison)
static prefs & get()
int scroll_speed()
void set_theme(const std::string &theme)
bool sound()
void show_wesnothd_server_search()
int bell_volume()
bool set_turn_bell(bool ison)
void set_music_volume(int vol)
void set_show_standing_animations(bool value)
void set_pixel_scale(const int scale)
pref_constants::lobby_joins get_lobby_joins()
bool set_sound(bool ison)
bool music_on()
void set_scroll_speed(const int scroll)
std::pair< preferences::acquaintance *, bool > add_acquaintance(const std::string &nick, const std::string &mode, const std::string &notes)
bool ui_sound_on()
int music_volume()
int pixel_scale()
void set_ui_volume(int vol)
bool turbo()
void set_bell_volume(int vol)
const std::vector< preferences::option > & get_advanced_preferences()
bool remember_password()
int ui_volume()
int sound_volume()
void clear_hotkeys()
bool show_standing_animations()
Definition: theme.hpp:44
static std::vector< theme_info > get_basic_theme_info(bool include_hidden=false)
Returns minimal info about saved themes, optionally including hidden ones.
Definition: theme.cpp:987
map_display and display: classes which take care of displaying the map and game-data on the screen.
Declarations for File-IO.
#define VGETTEXT(msgid,...)
Handy wrappers around interpolate_variables_into_string and gettext.
std::size_t i
Definition: function.cpp:1029
int w
static std::string _(const char *str)
Definition: gettext.hpp:93
#define WRN_GUI_L
Definition: log.hpp:57
std::string id
Text to match against addon_info.tags()
Definition: manager.cpp:199
This file contains the window object, this object is a top level container which has the event manage...
New lexcical_cast header.
void raise_resize_event()
Definition: events.cpp:737
static bool file_exists(const bfs::path &fpath)
Definition: filesystem.cpp:327
const std::string unicode_multiplication_sign
Definition: constants.cpp:46
std::string selected
std::string path
Definition: filesystem.cpp:92
static void set_sound_volume(int v)
static int bell_volume()
static bool set_sound(bool v)
static bool set_music(bool v)
static bool set_ui_sound(bool v)
static bool turn_bell()
static int music_volume()
static void set_bell_volume(int v)
static void set_ui_volume(int v)
static void set_music_volume(int v)
REGISTER_DIALOG(editor_edit_unit)
static bool set_turn_bell(bool v)
static bool sound()
static int ui_volume()
static bool ui_sound_on()
static int sound_volume()
static bool music_on()
void connect_signal_mouse_left_release(dispatcher &dispatcher, const signal &signal)
Connects a signal handler for a left mouse button release.
Definition: dispatcher.cpp:187
void connect_signal_notify_modified(dispatcher &dispatcher, const signal_notification &signal)
Connects a signal handler for getting a notification upon modification.
Definition: dispatcher.cpp:203
void connect_signal_mouse_left_click(dispatcher &dispatcher, const signal &signal)
Connects a signal handler for a left mouse button click.
Definition: dispatcher.cpp:177
gui_theme_map_t guis
Map of all known GUIs.
std::map< std::string, widget_item > widget_data
Definition: widget.hpp:36
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.
std::map< std::string, t_string > widget_item
Definition: widget.hpp:33
void show_transient_message(const std::string &title, const std::string &message, const std::string &image, const bool message_use_markup, const bool title_use_markup)
Shows a transient message to the user.
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:148
@ OK
Dialog was closed with the OK button.
Definition: retval.hpp:35
General purpose widgets.
const hotkey_command & get_hotkey_command(const std::string &command)
returns the hotkey_command with the given name
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.
std::shared_ptr< class hotkey_base > hotkey_ptr
Definition: hotkey_item.hpp:27
void clear_hotkeys(const std::string &command)
Unset the command bindings for all hotkeys matching the command.
const std::map< std::string_view, hotkey::hotkey_command > & get_hotkey_commands()
returns a container that contains all currently active hotkey_commands.
std::vector< hotkey::hotkey_ptr > hotkey_list
Definition: hotkey_item.hpp:31
void add_hotkey(hotkey_ptr item)
Add a hotkey to the list of hotkeys.
t_string get_translatable_category_name(HOTKEY_CATEGORY category)
Gets the display name for a given hotkey category.
Functions to load and save images from/to disk.
std::string span_color(const color_t &color, Args &&... data)
Applies Pango markup to the input specifying its display color.
Definition: markup.hpp:87
std::string tag(std::string_view tag, Args &&... data)
Wraps the given data in the specified formatting tag.
Definition: markup.hpp:50
game_data * gamedata
Definition: resources.cpp:22
bool ci_search(const std::string &s1, const std::string &s2)
Definition: gettext.cpp:565
constexpr auto filter
Definition: ranges.hpp:38
std::vector< std::string > split(const config_attribute_value &val)
auto * find(Container &container, const Value &value)
Convenience wrapper for using find on a container without needing to comare to end()
Definition: general.hpp:140
std::vector< point > get_available_resolutions(const bool include_current)
Returns the list of available screen resolutions.
Definition: video.cpp:717
point current_resolution()
The current window size in desktop coordinates.
Definition: video.cpp:769
void set_fullscreen(bool fullscreen)
Set the fullscreen state.
Definition: video.cpp:785
bool set_resolution(const point &resolution)
Set the window resolution.
Definition: video.cpp:814
void toggle_fullscreen()
Toggle fullscreen mode.
Definition: video.cpp:809
void update_buffers(bool autoupdate)
Update buffers to match current resolution and pixel scale settings.
Definition: video.cpp:844
std::string_view data
Definition: picture.cpp:178
Stores all information related to functions that can be bound to hotkeys.
std::string id
The unique ID.
Holds a 2D point.
Definition: point.hpp:25
static bool get(const std::string &pref, bool def)
static void set(const std::string &pref, bool value)
Definitions related to theme-support.
Add a special kind of assert to validate whether the input from WML doesn't contain any problems that...
#define VALIDATE(cond, message)
The macro to use for the validation of WML.
#define h