The Battle for Wesnoth  1.19.12+dev
units_dialog.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2016 - 2025
3  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 #pragma once
16 
18 #include "gui/sort_order.hpp"
19 #include "gui/widgets/group.hpp"
20 #include "gui/widgets/listbox.hpp"
22 #include "team.hpp"
23 #include "units/ptr.hpp"
24 #include "units/types.hpp"
25 
26 #include <string>
27 #include <vector>
28 
29 class team;
30 
31 namespace gui2::dialogs
32 {
33 
34 class units_dialog : public modal_dialog
35 {
36 public:
37  units_dialog();
38 
39  int get_selected_index() const
40  {
41  return selected_index_;
42  }
43 
44  bool is_selected() const
45  {
46  return selected_index_ != -1;
47  }
48 
50  {
52  }
53 
54  /** Gender choice from the user. */
56  {
57  return gender_;
58  }
59 
61  {
62  gender_ = gender;
63  }
64 
65  /** Variation choice from the user. */
66  std::string variation() const
67  {
68  return variation_;
69  }
70 
71  void set_variation(const std::string& variation)
72  {
74  }
75 
77  {
78  variation_.clear();
79  }
80 
81  // } --------------- BUILDER HELPERS -------------- {
82 
83  units_dialog& set_title(const std::string& title)
84  {
85  title_ = title;
86  return *this;
87  }
88 
89  units_dialog& set_ok_label(const std::string& ok_label)
90  {
91  ok_label_ = ok_label;
92  return *this;
93  }
94 
95  units_dialog& set_cancel_label(const std::string& cancel_label)
96  {
97  cancel_label_ = cancel_label;
98  return *this;
99  }
100 
102  {
103  show_rename_ = show;
104  return *this;
105  }
106 
108  {
110  return *this;
111  }
112 
114  {
116  return *this;
117  }
118 
120  {
122  return *this;
123  }
124 
125  units_dialog& set_help_topic(const std::string& topic_id)
126  {
127  topic_id_ = topic_id;
128  return *this;
129  }
130 
131  units_dialog& set_row_num(const std::size_t row_num)
132  {
133  num_rows_ = row_num;
134  return *this;
135  }
136 
137  units_dialog& set_sort_by(std::pair<std::string, sort_order::type> sort_order)
138  {
140  return *this;
141  }
142 
143  /**
144  * Registers an function which will fired on NOTIFY_MODIFIED dialog events.
145  *
146  * @param f The update function. This should return a const reference to the
147  * appropriate unit or unit type to display in the sidebar.
148  */
149  template<typename Func>
150  void on_modified(const Func& f)
151  {
152  connect_signal<event::NOTIFY_MODIFIED>([this, f](widget& w, auto&&...) {
153  w.find_widget<unit_preview_pane>("unit_details").set_display_data(f(get_selected_index()));
154  });
155  }
156 
157  template<typename Value, typename Func>
158  static auto make_index_wrapper(const std::vector<Value>& list, const Func& func)
159  {
160  return [&list, func](std::size_t index) { return func(list[index]); };
161  }
162 
163  template<typename Sorter>
164  void set_sorter(std::string_view id, const Sorter& sorter)
165  {
166  find_widget<gui2::listbox>("main_list").set_single_sorter(id, sorter);
167  }
168 
169  /** Controls the sort behavior for functions returned by @ref make_column_builder. */
170  enum class sort_type { generator, none };
171 
172  /**
173  * Creates a generator function which registers secondary generator and sorter
174  * functions for the list column associated with the given ID.
175  *
176  * @param list A list of values to associate with the generator functions.
177  * These will be used to populate the dialog's listbox.
178  *
179  * @returns A function which takes takes the following arguments:
180  * - The widget ID whose value will be generated.
181  * - The function which returns said widget's display value.
182  * - A @ref sort_type flag or a function used to order the list.
183  * If sort_type::generator is specified, the second argument
184  * will be used as the sorter.
185  */
186  template<typename Value>
187  auto make_column_builder(const std::vector<Value>& list)
188  {
189  return [this, &list](std::string_view id, const auto& generator, const auto& sorter) {
190  auto wrapper = make_index_wrapper(list, generator);
191  column_generators_.try_emplace(id, wrapper);
192 
193  if constexpr(std::is_invocable_v<decltype(sorter), const Value&>) {
194  set_sorter(id, make_index_wrapper(list, sorter));
195  } else {
196  if(sorter != sort_type::generator) return;
197  set_sorter(id, wrapper);
198  }
199  };
200  }
201 
202  /** Sets the generator function for the tooltips. */
203  template<typename Generator>
205  {
207  return *this;
208  }
209 
210  /** Sets the generator function for filter text. */
211  template<typename Generator>
213  {
215  return *this;
216  }
217 
218  // } -------------------- BUILDERS -------------------- {
219 
220  using recruit_msgs_map = std::map<const unit_type*, t_string>;
221 
222  static std::unique_ptr<units_dialog> build_create_dialog(const std::vector<const unit_type*>& types_list);
223  static std::unique_ptr<units_dialog> build_recruit_dialog(
224  const std::vector<const unit_type*>& recruit_list, recruit_msgs_map& err_msgs_map, const team& team);
225  static std::unique_ptr<units_dialog> build_recall_dialog(std::vector<unit_const_ptr>& recall_list, const team& team);
226  static std::unique_ptr<units_dialog> build_unit_list_dialog(std::vector<unit_const_ptr>& units_list);
227 
228 private:
230  std::size_t num_rows_;
231 
232  std::string title_;
233  std::string ok_label_;
234  std::string cancel_label_;
235  std::string topic_id_;
236 
241 
242  std::pair<std::string, sort_order::type> sort_order_;
243  std::map<std::string_view, std::function<std::string(std::size_t)>> column_generators_;
244  std::function<std::string(std::size_t)> tooltip_gen_;
245  std::function<std::vector<std::string>(std::size_t)> filter_gen_;
246 
248  std::string variation_;
249 
250  std::vector<std::vector<std::string>> filter_options_;
252 
254  return gender_toggle_;
255  }
256 
257  /** Callbacks */
258  void list_item_clicked();
259  void filter_text_changed(const std::string& text);
260 
261  // FIXME only thing needing team
262  void dismiss_unit(std::vector<unit_const_ptr>& unit_list, const team& team);
263  void rename_unit(std::vector<unit_const_ptr>& unit_list);
264  void toggle_favorite(std::vector<unit_const_ptr>& unit_list);
265 
266  void show_list(listbox& list);
267  void show_help() const;
268 
269  void update_gender(const unit_race::GENDER val);
270  void update_variation();
271 
272  virtual const std::string& window_id() const override;
273 
274  virtual void pre_show() override;
275  virtual void post_show() override;
276 };
277 
278 } // namespace gui2::dialogs
Abstract base class for all modal dialogs.
bool show(const unsigned auto_close_time=0)
Shows the window.
static auto make_index_wrapper(const std::vector< Value > &list, const Func &func)
units_dialog & set_tooltip_generator(const Generator &generator)
Sets the generator function for the tooltips.
void show_list(listbox &list)
units_dialog & set_show_favorite(bool show=true)
void set_selected_index(int selected)
std::pair< std::string, sort_order::type > sort_order_
std::function< std::vector< std::string >std::size_t)> filter_gen_
void set_gender(const unit_race::GENDER gender)
std::map< const unit_type *, t_string > recruit_msgs_map
units_dialog & set_ok_label(const std::string &ok_label)
std::vector< std::vector< std::string > > filter_options_
auto make_column_builder(const std::vector< Value > &list)
Creates a generator function which registers secondary generator and sorter functions for the list co...
units_dialog & set_show_dismiss(bool show=true)
std::function< std::string(std::size_t)> tooltip_gen_
virtual void post_show() override
Actions to be taken after the window has been shown.
void set_sorter(std::string_view id, const Sorter &sorter)
void rename_unit(std::vector< unit_const_ptr > &unit_list)
std::string variation() const
Variation choice from the user.
units_dialog & set_help_topic(const std::string &topic_id)
units_dialog & set_show_variations(bool show=true)
units_dialog & set_cancel_label(const std::string &cancel_label)
sort_type
Controls the sort behavior for functions returned by make_column_builder.
units_dialog & set_sort_by(std::pair< std::string, sort_order::type > sort_order)
group< unit_race::GENDER > & get_toggle()
group< unit_race::GENDER > gender_toggle_
void filter_text_changed(const std::string &text)
static std::unique_ptr< units_dialog > build_unit_list_dialog(std::vector< unit_const_ptr > &units_list)
units_dialog & set_show_rename(bool show=true)
units_dialog & set_row_num(const std::size_t row_num)
static std::unique_ptr< units_dialog > build_create_dialog(const std::vector< const unit_type * > &types_list)
void dismiss_unit(std::vector< unit_const_ptr > &unit_list, const team &team)
void toggle_favorite(std::vector< unit_const_ptr > &unit_list)
void on_modified(const Func &f)
Registers an function which will fired on NOTIFY_MODIFIED dialog events.
std::map< std::string_view, std::function< std::string(std::size_t)> > column_generators_
virtual const std::string & window_id() const override
The ID of the window to build.
units_dialog & set_filter_generator(const Generator &generator)
Sets the generator function for filter text.
virtual void pre_show() override
Actions to be taken before showing the window.
void set_variation(const std::string &variation)
void list_item_clicked()
Callbacks.
unit_race::GENDER gender() const
Gender choice from the user.
static std::unique_ptr< units_dialog > build_recruit_dialog(const std::vector< const unit_type * > &recruit_list, recruit_msgs_map &err_msgs_map, const team &team)
units_dialog & set_title(const std::string &title)
static std::unique_ptr< units_dialog > build_recall_dialog(std::vector< unit_const_ptr > &recall_list, const team &team)
void update_gender(const unit_race::GENDER val)
Basic template class to generate new items.
The listbox class.
Definition: listbox.hpp:41
Base class for all widgets.
Definition: widget.hpp:55
const std::string & id() const
Definition: widget.cpp:110
This class stores all the data for a single 'side' (in game nomenclature).
Definition: team.hpp:75
int w
std::string selected
std::size_t index(std::string_view str, const std::size_t index)
Codepoint index corresponding to the nth character in a UTF-8 string.
Definition: unicode.cpp:70
string_enums::enum_base< sort_order_defines > sort_order
Definition: sort_order.hpp:27
The base template for associating string values with enum values.
Definition: enum_base.hpp:33
#define f