The Battle for Wesnoth  1.19.9+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 
49  /** Gender choice from the user. */
51  {
52  return gender_;
53  }
54 
55  /** Variation choice from the user. */
56  std::string variation() const
57  {
58  return variation_;
59  }
60 
62  {
63  variation_.clear();
64  }
65 
66  // } --------------- BUILDER HELPERS -------------- {
67 
68  units_dialog& set_title(const std::string& title)
69  {
70  title_ = title;
71  return *this;
72  }
73 
74  units_dialog& set_ok_label(const std::string& ok_label)
75  {
76  ok_label_ = ok_label;
77  return *this;
78  }
79 
80  units_dialog& set_cancel_label(const std::string& cancel_label)
81  {
82  cancel_label_ = cancel_label;
83  return *this;
84  }
85 
87  {
89  return *this;
90  }
91 
93  {
95  return *this;
96  }
97 
99  {
101  return *this;
102  }
103 
104  units_dialog& set_help_topic(const std::string& topic_id)
105  {
106  topic_id_ = topic_id;
107  return *this;
108  }
109 
110  units_dialog& set_row_num(const std::size_t row_num)
111  {
112  num_rows_ = row_num;
113  return *this;
114  }
115 
116  units_dialog& set_sort_by(std::pair<std::string, sort_order::type> sort_order)
117  {
119  return *this;
120  }
121 
122  /**
123  * Registers an function which will fired on NOTIFY_MODIFIED dialog events.
124  *
125  * @param f The update function. This should return a const reference to the
126  * appropriate unit or unit type to display in the sidebar.
127  */
128  template<typename Func>
129  void on_modified(const Func& f)
130  {
131  connect_signal<event::NOTIFY_MODIFIED>([this, f](widget& w, auto&&...) {
132  w.find_widget<unit_preview_pane>("unit_details").set_display_data(f(get_selected_index()));
133  });
134  }
135 
136  template<typename Value, typename Func>
137  static auto make_index_wrapper(const std::vector<Value>& list, const Func& func)
138  {
139  return [&list, func](std::size_t index) { return func(list[index]); };
140  }
141 
142  template<typename Sorter>
143  void set_sorter(std::string_view id, const Sorter& sorter)
144  {
145  find_widget<gui2::listbox>("main_list").set_single_sorter(id, sorter);
146  }
147 
148  /** Controls the sort behavior for functions returned by @ref make_column_builder. */
149  enum class sort_type { generator, none };
150 
151  /**
152  * Creates a generator function which registers secondary generator and sorter
153  * functions for the list column associated with the given ID.
154  *
155  * @param list A list of values to associate with the generator functions.
156  * These will be used to populate the dialog's listbox.
157  *
158  * @returns A function which takes takes the following arguments:
159  * - The widget ID whose value will be generated.
160  * - The function which returns said widget's display value.
161  * - A @ref sort_type flag or a function used to order the list.
162  * If sort_type::generator is specified, the second argument
163  * will be used as the sorter.
164  */
165  template<typename Value>
166  auto make_column_builder(const std::vector<Value>& list)
167  {
168  return [this, &list](std::string_view id, const auto& generator, const auto& sorter) {
169  auto wrapper = make_index_wrapper(list, generator);
170  column_generators_.try_emplace(id, wrapper);
171 
172  if constexpr(std::is_invocable_v<decltype(sorter), const Value&>) {
173  set_sorter(id, make_index_wrapper(list, sorter));
174  } else {
175  if(sorter != sort_type::generator) return;
176  set_sorter(id, wrapper);
177  }
178  };
179  }
180 
181  /** Sets the generator function for the tooltips. */
182  template<typename Generator>
184  {
186  return *this;
187  }
188 
189  /** Sets the generator function for filter text. */
190  template<typename Generator>
192  {
194  return *this;
195  }
196 
197  // } -------------------- BUILDERS -------------------- {
198 
199  using recruit_msgs_map = std::map<const unit_type*, t_string>;
200 
201  static std::unique_ptr<units_dialog> build_create_dialog(const std::vector<const unit_type*>& types_list);
202  static std::unique_ptr<units_dialog> build_recruit_dialog(
203  const std::vector<const unit_type*>& recruit_list, recruit_msgs_map& err_msgs_map, const team& team);
204  static std::unique_ptr<units_dialog> build_recall_dialog(std::vector<unit_const_ptr>& recall_list, const team& team);
205  static std::unique_ptr<units_dialog> build_unit_list_dialog(std::vector<unit_const_ptr>& units_list);
206 
207 private:
209  std::size_t num_rows_;
210 
211  std::string title_;
212  std::string ok_label_;
213  std::string cancel_label_;
214  std::string topic_id_;
215 
219 
220  std::pair<std::string, sort_order::type> sort_order_;
221  std::map<std::string_view, std::function<std::string(std::size_t)>> column_generators_;
222  std::function<std::string(std::size_t)> tooltip_gen_;
223  std::function<std::vector<std::string>(std::size_t)> filter_gen_;
224 
226  std::string variation_;
227 
228  std::vector<std::vector<std::string>> filter_options_;
230 
232  return gender_toggle_;
233  }
234 
235  /** Callbacks */
236  void list_item_clicked();
237  void filter_text_changed(const std::string& text);
238 
239  // FIXME only thing needing team
240  void dismiss_unit(std::vector<unit_const_ptr>& unit_list, const team& team);
241  void rename_unit(std::vector<unit_const_ptr>& unit_list);
242 
243  void show_list(listbox& list);
244  void show_help() const;
245 
246  void update_gender(const unit_race::GENDER val);
247  void update_variation();
248 
249  virtual const std::string& window_id() const override;
250 
251  virtual void pre_show() override;
252  virtual void post_show() override;
253 };
254 
255 } // 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)
std::pair< std::string, sort_order::type > sort_order_
std::function< std::vector< std::string >std::size_t)> filter_gen_
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 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::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