The Battle for Wesnoth  1.19.0-dev
custom_tod.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2008 - 2024
3  by Mark de Wever <koraq@xs4all.nl>
4  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY.
12 
13  See the COPYING file for more details.
14 */
15 
16 #define GETTEXT_DOMAIN "wesnoth-editor"
17 
19 
20 #include "desktop/clipboard.hpp"
21 #include "display.hpp"
22 #include "filesystem.hpp"
23 #include "formatter.hpp"
24 #include "gettext.hpp"
25 #include "gui/auxiliary/field.hpp"
27 #include "gui/widgets/button.hpp"
28 #include "gui/widgets/image.hpp"
29 #include "gui/widgets/label.hpp"
30 #include "gui/widgets/slider.hpp"
31 #include "gui/widgets/text_box.hpp"
32 
33 #include <functional>
34 
35 namespace gui2::dialogs
36 {
37 
39 {
40  static std::string type = "image";
41  return {type, tod.image};
42 }
43 
45 {
46  static std::string type = "mask";
47  return {type, tod.image_mask};
48 }
49 
51 {
52  static std::string type = "sound";
53  return {type, tod.sounds};
54 }
55 
57 
58 custom_tod::custom_tod(const std::vector<time_of_day>& times, int current_time)
59  : modal_dialog(window_id())
60  , times_(times)
61  , current_tod_(current_time)
62  , color_field_r_(register_integer("tod_red", true))
63  , color_field_g_(register_integer("tod_green", true))
64  , color_field_b_(register_integer("tod_blue", true))
65 {
66  if(times_.empty())
67  {
68  times_.push_back(time_of_day());
69  }
70 }
71 
73 {
74  static std::map<std::string, tod_attribute_getter> metadata_stuff {
75  {"image", tod_getter_image},
76  {"mask", tod_getter_mask },
77  {"sound", tod_getter_sound}
78  };
79 
80  window.add_to_tab_order(find_widget<text_box>(&window, "tod_name", false, true));
81  window.add_to_tab_order(find_widget<text_box>(&window, "tod_desc", false, true));
82  window.add_to_tab_order(find_widget<text_box>(&window, "tod_id", false, true));
83 
84  for(const auto& data : metadata_stuff) {
85  find_widget<text_box>(&window, "path_" + data.first, false).set_active(false);
86 
87  button& copy_w = find_widget<button>(&window, "copy_" + data.first, false);
88 
90  std::bind(&custom_tod::copy_to_clipboard_callback, this, data.second));
91 
93  copy_w.set_active(false);
94  copy_w.set_tooltip(_("Clipboard support not found, contact your packager"));
95  }
96  }
97 
99  find_widget<button>(&window, "browse_image", false),
100  std::bind(&custom_tod::select_file<tod_getter_image>, this, "data/core/images/misc"));
101 
103  find_widget<button>(&window, "browse_mask", false),
104  std::bind(&custom_tod::select_file<tod_getter_mask>, this, "data/core/images"));
105 
107  find_widget<button>(&window, "browse_sound", false),
108  std::bind(&custom_tod::select_file<tod_getter_sound>, this, "data/core/sounds/ambient"));
109 
111  find_widget<button>(&window, "next_tod", false),
112  std::bind(&custom_tod::do_next_tod, this));
113 
115  find_widget<button>(&window, "previous_tod", false),
116  std::bind(&custom_tod::do_prev_tod, this));
117 
119  find_widget<button>(&window, "new", false),
120  std::bind(&custom_tod::do_new_tod, this));
121 
123  find_widget<button>(&window, "delete", false),
124  std::bind(&custom_tod::do_delete_tod, this));
125 
127  find_widget<button>(&window, "preview", false),
128  std::bind(&custom_tod::preview_schedule, this));
129 
131  find_widget<slider>(&window, "lawful_bonus", false),
132  std::bind(&custom_tod::update_lawful_bonus, this));
133 
136  std::bind(&custom_tod::color_slider_callback, this, COLOR_R));
137 
140  std::bind(&custom_tod::color_slider_callback, this, COLOR_G));
141 
144  std::bind(&custom_tod::color_slider_callback, this, COLOR_B));
145 
147 }
148 
149 template<custom_tod::string_pair(*fptr)(const time_of_day&)>
150 void custom_tod::select_file(const std::string& default_dir)
151 {
152  const string_pair& data = (*fptr)(get_selected_tod());
153 
154  std::string fn = filesystem::base_name(data.second);
155  std::string dn = filesystem::directory_name(fn);
156  if(dn.empty()) {
157  dn = default_dir;
158  }
159 
161 
162  dlg.set_title(_("Choose File"))
163  .set_ok_label(_("Select"))
164  .set_path(dn)
165  .set_read_only(true);
166 
167  if(dlg.show()) {
168  dn = dlg.path();
169 
170  if(data.first == "image") {
171  times_[current_tod_].image = dn;
172  } else if(data.first == "mask") {
173  times_[current_tod_].image_mask = dn;
174  } else if(data.first == "sound") {
175  times_[current_tod_].sounds = dn;
176  }
177  }
178 
180 }
181 
183 {
184  current_tod_ = (current_tod_ + 1) % times_.size();
186 }
187 
189 {
190  current_tod_ = (current_tod_ ? current_tod_ : times_.size()) - 1;
192 }
193 
195 {
196  times_.insert(times_.begin() + current_tod_, time_of_day());
198 }
199 
201 {
202  assert(times_.begin() + current_tod_ < times_.end());
203 
204  if(times_.size() == 1) {
205  times_.emplace_back();
206  } else {
207  times_.erase(times_.begin() + current_tod_);
208 
209  if(times_.begin() + current_tod_ >= times_.end()) {
210  current_tod_ = times_.size() - 1;
211  }
212  }
213 
215 }
216 
218 {
219  try {
220  return times_.at(current_tod_);
221  } catch(const std::out_of_range&) {
222  throw std::string("Attempted to fetch a non-existant ToD!");
223  }
224 }
225 
227 {
228  time_of_day& current_tod = times_[current_tod_];
229 
230  switch(type)
231  {
232  case COLOR_R:
233  current_tod.color.r = color_field_r_->get_widget_value();
234  break;
235  case COLOR_G :
236  current_tod.color.g = color_field_g_->get_widget_value();
237  break;
238  case COLOR_B :
239  current_tod.color.b = color_field_b_->get_widget_value();
240  break;
241  }
242 
244 }
245 
247 {
249  assert(disp && "Display pointer is null!");
250 
251  // The display handles invaliding whatever tiles need invalidating.
252  disp->update_tod(&get_selected_tod());
253 
254  // NOTE: revert to invalidate_layout if necessary to display the ToD mask image.
256 }
257 
259 {
260  times_[current_tod_].lawful_bonus = find_widget<slider>(get_window(), "lawful_bonus", false).get_value();
261 }
262 
264 {
265  const time_of_day& current_tod = get_selected_tod();
266 
267  find_widget<text_box>(get_window(), "tod_name", false).set_value(current_tod.name);
268  find_widget<text_box>(get_window(), "tod_desc", false).set_value(current_tod.description);
269  find_widget<text_box>(get_window(), "tod_id", false).set_value(current_tod.id);
270 
271  find_widget<text_box>(get_window(), "path_image", false).set_value(current_tod.image);
272  find_widget<text_box>(get_window(), "path_mask", false).set_value(current_tod.image_mask);
273  find_widget<text_box>(get_window(), "path_sound", false).set_value(current_tod.sounds);
274 
275  find_widget<image>(get_window(), "current_tod_image", false).set_image(current_tod.image);
276  find_widget<image>(get_window(), "current_tod_mask", false).set_image(current_tod.image_mask);
277 
278  find_widget<slider>(get_window(), "lawful_bonus", false).set_value(current_tod.lawful_bonus);
279 
280  color_field_r_->set_widget_value(current_tod.color.r);
281  color_field_g_->set_widget_value(current_tod.color.g);
282  color_field_b_->set_widget_value(current_tod.color.b);
283 
284  const std::string new_index_str = formatter() << (current_tod_ + 1) << "/" << times_.size();
285  find_widget<label>(get_window(), "tod_number", false).set_label(new_index_str);
286 
288 }
289 
291 {
293 }
294 
295 /** Quickly preview the schedule changes and color */
297 {
299 }
300 
302 {
303  /* Update times_ with values from the dialog */
304  times_[current_tod_].name = find_widget<text_box>(get_window(), "tod_name", false).get_value();
305  times_[current_tod_].description = find_widget<text_box>(get_window(), "tod_desc", false).get_value();
306  times_[current_tod_].id = find_widget<text_box>(get_window(), "tod_id", false).get_value();
307 
308  times_[current_tod_].image = find_widget<text_box>(get_window(), "path_image", false).get_value();
309  times_[current_tod_].image_mask = find_widget<text_box>(get_window(), "path_mask", false).get_value();
310  times_[current_tod_].sounds = find_widget<text_box>(get_window(), "path_sound", false).get_value();
311 
312  times_[current_tod_].lawful_bonus = find_widget<slider>(get_window(), "lawful_bonus", false).get_value();
313 
317 }
318 
319 const std::vector<time_of_day> custom_tod::get_schedule()
320 {
321  update_schedule();
322  return times_;
323 }
324 
325 void custom_tod::register_callback(std::function<void(std::vector<time_of_day>)> update_func)
326 {
327  update_map_and_schedule_ = update_func;
328 }
329 
330 void custom_tod::post_show(window& /*window*/)
331 {
333 }
334 
335 } // namespace dialogs
Sort-of-Singleton that many classes, both GUI and non-GUI, use to access the game data.
Definition: display.hpp:88
void update_tod(const time_of_day *tod_override=nullptr)
Applies r,g,b coloring to the map.
Definition: display.cpp:405
static display * get_singleton()
Returns the display object if a display object exists.
Definition: display.hpp:102
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:63
This shows the dialog to modify tod schedules.
Definition: custom_tod.hpp:49
void update_schedule()
Update current TOD with values from the GUI.
Definition: custom_tod.cpp:301
std::pair< std::string, std::string > string_pair
The execute function.
Definition: custom_tod.hpp:56
field_integer * color_field_g_
Definition: custom_tod.hpp:115
std::function< string_pair(const time_of_day &)> tod_attribute_getter
Definition: custom_tod.hpp:57
void color_slider_callback(COLOR_TYPE type)
Definition: custom_tod.cpp:226
void select_file(const std::string &default_dir)
Definition: custom_tod.cpp:150
virtual void pre_show(window &window) override
Actions to be taken before showing the window.
Definition: custom_tod.cpp:72
void preview_schedule()
Callback for preview button.
Definition: custom_tod.cpp:296
std::vector< time_of_day > times_
Available time_of_days.
Definition: custom_tod.hpp:109
COLOR_TYPE
enum used in identifying sliders
Definition: custom_tod.hpp:66
void copy_to_clipboard_callback(tod_attribute_getter getter)
Definition: custom_tod.cpp:290
const time_of_day & get_selected_tod() const
Definition: custom_tod.cpp:217
void do_next_tod()
Callback for the next tod button.
Definition: custom_tod.cpp:182
field_integer * color_field_b_
Definition: custom_tod.hpp:116
field_integer * color_field_r_
Definition: custom_tod.hpp:114
const std::vector< time_of_day > get_schedule()
Return current schedule.
Definition: custom_tod.cpp:319
int current_tod_
Current ToD index.
Definition: custom_tod.hpp:112
void register_callback(std::function< void(std::vector< time_of_day >)>)
Register callback for update.
Definition: custom_tod.cpp:325
std::function< void(std::vector< time_of_day >)> update_map_and_schedule_
Definition: custom_tod.hpp:92
virtual void post_show(window &window) override
Actions to be taken after the window has been shown.
Definition: custom_tod.cpp:330
file_dialog & set_ok_label(const std::string &value)
Sets the OK button label.
file_dialog & set_path(const std::string &value)
Sets the initial file selection.
file_dialog & set_title(const std::string &value)
Sets the current dialog title text.
Definition: file_dialog.hpp:59
file_dialog & set_read_only(bool value)
Whether to provide user interface elements for manipulating existing objects.
std::string path() const
Gets the current file selection.
Abstract base class for all modal dialogs.
bool show(const unsigned auto_close_time=0)
Shows the window.
window * get_window()
Returns a pointer to the dialog's window.
styled_widget * get_widget()
Definition: field.hpp:193
void set_widget_value(CT value)
Sets the value of the field.
Definition: field.hpp:344
T get_widget_value()
Gets the value of the field.
Definition: field.hpp:379
void set_tooltip(const t_string &tooltip)
void queue_redraw()
Indicates that this widget should be redrawn.
Definition: widget.cpp:455
base class of top level items, the only item which needs to store the final canvases to draw on.
Definition: window.hpp:63
static const std::string & type()
Static type getter that does not rely on the widget being constructed.
void add_to_tab_order(widget *widget, int at=-1)
Add the widget to the tabbing order.
Definition: window.cpp:1239
Implements some helper classes to ease adding fields to a dialog and hide the synchronization needed.
Declarations for File-IO.
static std::string _(const char *str)
Definition: gettext.hpp:93
void copy_to_clipboard(const std::string &text, const bool)
Copies text to the clipboard.
Definition: clipboard.cpp:32
bool available()
Whether wesnoth was compiled with support for a clipboard.
Definition: clipboard.cpp:53
std::string base_name(const std::string &file, const bool remove_extension)
Returns the base filename of a file, with directory name stripped.
std::string directory_name(const std::string &file)
Returns the directory name of a file, with filename stripped.
static custom_tod::string_pair tod_getter_mask(const time_of_day &tod)
Definition: custom_tod.cpp:44
REGISTER_DIALOG(editor_edit_unit)
static custom_tod::string_pair tod_getter_image(const time_of_day &tod)
Definition: custom_tod.cpp:38
static custom_tod::string_pair tod_getter_sound(const time_of_day &tod)
Definition: custom_tod.cpp:50
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
std::string default_dir()
Definition: editor.cpp:33
std::string_view data
Definition: picture.cpp:194
Object which defines a time of day with associated bonuses, image, sounds etc.
Definition: time_of_day.hpp:57
std::string id
Definition: time_of_day.hpp:90
tod_color color
The color modifications that should be made to the game board to reflect the time of day.
int lawful_bonus
The % bonus lawful units receive.
Definition: time_of_day.hpp:83
t_string description
Definition: time_of_day.hpp:89
t_string name
Definition: time_of_day.hpp:88
std::string image
The image to be displayed in the game status.
Definition: time_of_day.hpp:87
std::string sounds
List of "ambient" sounds associated with this time_of_day, Played at the beginning of turn.
std::string image_mask
The image that is to be laid over all images while this time of day lasts.
Definition: time_of_day.hpp:96