The Battle for Wesnoth  1.19.10+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 
119  units_dialog& set_help_topic(const std::string& topic_id)
120  {
121  topic_id_ = topic_id;
122  return *this;
123  }
124 
125  units_dialog& set_row_num(const std::size_t row_num)
126  {
127  num_rows_ = row_num;
128  return *this;
129  }
130 
131  units_dialog& set_sort_by(std::pair<std::string, sort_order::type> sort_order)
132  {
134  return *this;
135  }
136 
137  /**
138  * Registers an function which will fired on NOTIFY_MODIFIED dialog events.
139  *
140  * @param f The update function. This should return a const reference to the
141  * appropriate unit or unit type to display in the sidebar.
142  */
143  template<typename Func>
144  void on_modified(const Func& f)
145  {
146  connect_signal<event::NOTIFY_MODIFIED>([this, f](widget& w, auto&&...) {
147  w.find_widget<unit_preview_pane>("unit_details").set_display_data(f(get_selected_index()));
148  });
149  }
150 
151  template<typename Value, typename Func>
152  static auto make_index_wrapper(const std::vector<Value>& list, const Func& func)
153  {
154  return [&list, func](std::size_t index) { return func(list[index]); };
155  }
156 
157  template<typename Sorter>
158  void set_sorter(std::string_view id, const Sorter& sorter)
159  {
160  find_widget<gui2::listbox>("main_list").set_single_sorter(id, sorter);
161  }
162 
163  /** Controls the sort behavior for functions returned by @ref make_column_builder. */
164  enum class sort_type { generator, none };
165 
166  /**
167  * Creates a generator function which registers secondary generator and sorter
168  * functions for the list column associated with the given ID.
169  *
170  * @param list A list of values to associate with the generator functions.
171  * These will be used to populate the dialog's listbox.
172  *
173  * @returns A function which takes takes the following arguments:
174  * - The widget ID whose value will be generated.
175  * - The function which returns said widget's display value.
176  * - A @ref sort_type flag or a function used to order the list.
177  * If sort_type::generator is specified, the second argument
178  * will be used as the sorter.
179  */
180  template<typename Value>
181  auto make_column_builder(const std::vector<Value>& list)
182  {
183  return [this, &list](std::string_view id, const auto& generator, const auto& sorter) {
184  auto wrapper = make_index_wrapper(list, generator);
185  column_generators_.try_emplace(id, wrapper);
186 
187  if constexpr(std::is_invocable_v<decltype(sorter), const Value&>) {
188  set_sorter(id, make_index_wrapper(list, sorter));
189  } else {
190  if(sorter != sort_type::generator) return;
191  set_sorter(id, wrapper);
192  }
193  };
194  }
195 
196  /** Sets the generator function for the tooltips. */
197  template<typename Generator>
199  {
201  return *this;
202  }
203 
204  /** Sets the generator function for filter text. */
205  template<typename Generator>
207  {
209  return *this;
210  }
211 
212  // } -------------------- BUILDERS -------------------- {
213 
214  using recruit_msgs_map = std::map<const unit_type*, t_string>;
215 
216  static std::unique_ptr<units_dialog> build_create_dialog(const std::vector<const unit_type*>& types_list);
217  static std::unique_ptr<units_dialog> build_recruit_dialog(
218  const std::vector<const unit_type*>& recruit_list, recruit_msgs_map& err_msgs_map, const team& team);
219  static std::unique_ptr<units_dialog> build_recall_dialog(std::vector<unit_const_ptr>& recall_list, const team& team);
220  static std::unique_ptr<units_dialog> build_unit_list_dialog(std::vector<unit_const_ptr>& units_list);
221 
222 private:
224  std::size_t num_rows_;
225 
226  std::string title_;
227  std::string ok_label_;
228  std::string cancel_label_;
229  std::string topic_id_;
230 
234 
235  std::pair<std::string, sort_order::type> sort_order_;
236  std::map<std::string_view, std::function<std::string(std::size_t)>> column_generators_;
237  std::function<std::string(std::size_t)> tooltip_gen_;
238  std::function<std::vector<std::string>(std::size_t)> filter_gen_;
239 
241  std::string variation_;
242 
243  std::vector<std::vector<std::string>> filter_options_;
245 
247  return gender_toggle_;
248  }
249 
250  /** Callbacks */
251  void list_item_clicked();
252  void filter_text_changed(const std::string& text);
253 
254  // FIXME only thing needing team
255  void dismiss_unit(std::vector<unit_const_ptr>& unit_list, const team& team);
256  void rename_unit(std::vector<unit_const_ptr>& unit_list);
257 
258  void show_list(listbox& list);
259  void show_help() const;
260 
261  void update_gender(const unit_race::GENDER val);
262  void update_variation();
263 
264  virtual const std::string& window_id() const override;
265 
266  virtual void pre_show() override;
267  virtual void post_show() override;
268 };
269 
270 } // 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)
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 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