The Battle for Wesnoth  1.15.1+dev
custom_tod.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2008 - 2018 by Mark de Wever <koraq@xs4all.nl>
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 #define GETTEXT_DOMAIN "wesnoth-editor"
16 
18 
19 #include "desktop/clipboard.hpp"
20 #include "display.hpp"
21 #include "filesystem.hpp"
22 #include "formatter.hpp"
23 #include "gettext.hpp"
24 #include "gui/auxiliary/field.hpp"
26 #include "gui/widgets/button.hpp"
27 #include "gui/widgets/image.hpp"
28 #include "gui/widgets/label.hpp"
29 #include "gui/widgets/settings.hpp"
30 #include "gui/widgets/slider.hpp"
31 #include "gui/widgets/text_box.hpp"
32 
33 #include "utils/functional.hpp"
34 
35 namespace gui2
36 {
37 namespace dialogs
38 {
39 
40 /*WIKI
41  * @page = GUIWindowDefinitionWML
42  * @order = 2_custom_tod
43  *
44  * == Custom Schedules ==
45  *
46  * This shows the dialog to modify tod schedules.
47  *
48  * @begin{table}{dialog_widgets}
49  *
50  * current_tod_name & & text_box & m &
51  * The name of the time of day(ToD). $
52  *
53  * current_tod_id & & text_box & m &
54  * The id of the time of day(ToD). $
55  *
56  * current_tod_image & & image & m &
57  * The image for the time of day(ToD). $
58  *
59  * current_tod_mask & & image & m &
60  * The image mask for the time of day(ToD). $
61  *
62  * current_tod_sonund & & label & m &
63  * The sound for the time of day(ToD). $
64  *
65  * next_tod & & button & m &
66  * Selects the next ToD. $
67  *
68  * prev_tod & & button & m &
69  * Selects the previous ToD. $
70  *
71  * lawful_bonus & & slider & m &
72  * Sets the Lawful Bonus for the current ToD. $
73  *
74  * tod_red & & slider & m &
75  * Sets the red component of the current ToD. $
76  *
77  * tod_green & & slider & m &
78  * Sets the green component of the current ToD. $
79  *
80  * tod_blue & & slider & m &
81  * Sets the blue component of the current ToD. $
82  *
83  * @end{table}
84  */
85 
87 {
88  static std::string type = "image";
89  return {type, tod.image};
90 }
91 
93 {
94  static std::string type = "mask";
95  return {type, tod.image_mask};
96 }
97 
99 {
100  static std::string type = "sound";
101  return {type, tod.sounds};
102 }
103 
105 
106 custom_tod::custom_tod(const std::vector<time_of_day>& times, int current_time)
107  : times_(times)
108  , current_tod_(current_time)
109  , color_field_r_(register_integer("tod_red", true))
110  , color_field_g_(register_integer("tod_green", true))
111  , color_field_b_(register_integer("tod_blue", true))
112 {
113  assert(!times_.empty());
114 }
115 
117 {
118  static std::map<std::string, tod_attribute_getter> metadata_stuff {
119  {"image", tod_getter_image},
120  {"mask", tod_getter_mask },
121  {"sound", tod_getter_sound}
122  };
123 
124  window.add_to_tab_order(find_widget<text_box>(&window, "tod_name", false, true));
125  window.add_to_tab_order(find_widget<text_box>(&window, "tod_id", false, true));
126 
127  for(const auto& data : metadata_stuff) {
128  find_widget<text_box>(&window, "path_" + data.first, false).set_active(false);
129 
130  button& copy_w = find_widget<button>(&window, "copy_" + data.first, false);
131 
133  std::bind(&custom_tod::copy_to_clipboard_callback, this, data.second));
134 
136  copy_w.set_active(false);
137  copy_w.set_tooltip(_("Clipboard support not found, contact your packager"));
138  }
139  }
140 
142  find_widget<button>(&window, "browse_image", false),
143  std::bind(&custom_tod::select_file<tod_getter_image>, this, std::ref(window), "data/core/images/misc"));
144 
146  find_widget<button>(&window, "browse_mask", false),
147  std::bind(&custom_tod::select_file<tod_getter_mask>, this, std::ref(window), "data/core/images"));
148 
150  find_widget<button>(&window, "browse_sound", false),
151  std::bind(&custom_tod::select_file<tod_getter_sound>, this, std::ref(window), "data/core/sounds/ambient"));
152 
154  find_widget<button>(&window, "next_tod", false),
155  std::bind(&custom_tod::do_next_tod, this, std::ref(window)));
156 
158  find_widget<button>(&window, "previous_tod", false),
159  std::bind(&custom_tod::do_prev_tod, this, std::ref(window)));
160 
162  find_widget<button>(&window, "new", false),
163  std::bind(&custom_tod::do_new_tod, this, std::ref(window)));
164 
166  find_widget<button>(&window, "delete", false),
167  std::bind(&custom_tod::do_delete_tod, this, std::ref(window)));
168 
170  find_widget<slider>(&window, "lawful_bonus", false),
171  std::bind(&custom_tod::update_lawful_bonus, this, std::ref(window)));
172 
175  std::bind(&custom_tod::color_slider_callback, this, std::ref(window)));
176 
179  std::bind(&custom_tod::color_slider_callback, this, std::ref(window)));
180 
183  std::bind(&custom_tod::color_slider_callback, this, std::ref(window)));
184 
185  update_selected_tod_info(window);
186 }
187 
188 template<custom_tod::string_pair(*fptr)(const time_of_day&)>
190 {
191  const string_pair& data = (*fptr)(get_selected_tod());
192 
193  std::string fn = filesystem::base_name(data.second);
194  std::string dn = filesystem::directory_name(fn);
195  if(dn.empty()) {
196  dn = default_dir;
197  }
198 
200 
201  dlg.set_title(_("Choose File"))
202  .set_ok_label(_("Select"))
203  .set_path(dn)
204  .set_read_only(true);
205 
206  if(dlg.show()) {
207  dn = dlg.path();
208 
209  if(data.first == "image") {
210  times_[current_tod_].image = dn;
211  } else if(data.first == "mask") {
212  times_[current_tod_].image_mask = dn;
213  } else if(data.first == "sound") {
214  times_[current_tod_].sounds = dn;
215  }
216  }
217 
218  update_selected_tod_info(window);
219 }
220 
222 {
223  current_tod_ = (current_tod_ + 1) % times_.size();
224  update_selected_tod_info(window);
225 }
226 
228 {
229  current_tod_ = (current_tod_ ? current_tod_ : times_.size()) - 1;
230  update_selected_tod_info(window);
231 }
232 
234 {
235  times_.insert(times_.begin() + current_tod_, time_of_day());
236  update_selected_tod_info(window);
237 }
238 
240 {
241  assert(times_.begin() + current_tod_ < times_.end());
242 
243  if(times_.size() == 1) {
244  times_.emplace_back();
245  } else {
246  times_.erase(times_.begin() + current_tod_);
247 
248  if(times_.begin() + current_tod_ >= times_.end()) {
249  current_tod_ = times_.size() - 1;
250  }
251  }
252 
253  update_selected_tod_info(window);
254 }
255 
257 {
258  try {
259  return times_.at(current_tod_);
260  } catch(const std::out_of_range&) {
261  throw std::string("Attempted to fetch a non-existant ToD!");
262  }
263 }
264 
266 {
267  time_of_day& current_tod = times_[current_tod_];
268 
269  current_tod.color.r = color_field_r_->get_widget_value(window);
270  current_tod.color.g = color_field_g_->get_widget_value(window);
271  current_tod.color.b = color_field_b_->get_widget_value(window);
272 
273  update_tod_display(window);
274 }
275 
277 {
279  assert(disp && "Display pointer is null!");
280 
281  // Prevent a floating slice of window appearing alone over the
282  // theme UI sidebar after redrawing tiles and before we have a
283  // chance to redraw the rest of this window.
284  window.undraw();
285 
286  // NOTE: We only really want to re-render the gamemap tiles here.
287  // Redrawing everything is a significantly more expensive task.
288  // At this time, tiles are the only elements on which ToD tint is
289  // meant to have a visible effect. This is very strongly tied to
290  // the image caching mechanism.
291  //
292  // If this ceases to be the case in the future, you'll need to call
293  // redraw_everything() instead.
294 
295  disp->update_tod(&get_selected_tod());
296 
297  // invalidate all tiles so they are redrawn with the new ToD tint next
298  disp->invalidate_all();
299 
300  // redraw tiles
301  disp->draw(false);
302 
303  // NOTE: revert to invalidate_layout if necessary to display the ToD mask image.
304  window.set_is_dirty(true);
305 }
306 
308 {
309  times_[current_tod_].lawful_bonus = find_widget<slider>(&window, "lawful_bonus", false).get_value();
310 }
311 
313 {
314  const time_of_day& current_tod = get_selected_tod();
315 
316  find_widget<text_box>(&window, "tod_name", false).set_value(current_tod.name);
317  find_widget<text_box>(&window, "tod_id", false).set_value(current_tod.id);
318 
319  find_widget<text_box>(&window, "path_image", false).set_value(current_tod.image);
320  find_widget<text_box>(&window, "path_mask", false).set_value(current_tod.image_mask);
321  find_widget<text_box>(&window, "path_sound", false).set_value(current_tod.sounds);
322 
323  find_widget<image>(&window, "current_tod_image", false).set_image(current_tod.image);
324  find_widget<image>(&window, "current_tod_mask", false).set_image(current_tod.image_mask);
325 
326  find_widget<slider>(&window, "lawful_bonus", false).set_value(current_tod.lawful_bonus);
327 
328  color_field_r_->set_widget_value(window, current_tod.color.r);
329  color_field_g_->set_widget_value(window, current_tod.color.g);
330  color_field_b_->set_widget_value(window, current_tod.color.b);
331 
332  const std::string new_index_str = formatter() << (current_tod_ + 1) << "/" << times_.size();
333  find_widget<label>(&window, "tod_number", false).set_label(new_index_str);
334 
335  update_tod_display(window);
336 }
337 
339 {
341 }
342 
344 {
345  update_tod_display(window);
346 
347  if(get_retval() == retval::OK) {
348  // TODO: save ToD
349  }
350 }
351 
352 } // namespace dialogs
353 } // namespace gui2
std::pair< std::string, std::string > string_pair
The execute function.
Definition: custom_tod.hpp:37
static display * get_singleton()
Returns the display object if a display object exists.
Definition: display.hpp:88
void do_prev_tod(window &window)
Definition: custom_tod.cpp:227
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:97
int current_tod_
Current ToD index.
Definition: custom_tod.hpp:77
std::vector< time_of_day > times_
Available time_of_days.
Definition: custom_tod.hpp:74
tod_color color
The color modifications that should be made to the game board to reflect the time of day...
bool available()
Whether wesnoth was compiled with support for a clipboard.
Definition: clipboard.cpp:56
void update_tod_display(window &window)
Definition: custom_tod.cpp:276
file_dialog & set_path(const std::string &value)
Sets the initial file selection.
file_dialog & set_ok_label(const std::string &value)
Sets the OK button label.
std::string sounds
List of "ambient" sounds associated with this time_of_day, Played at the beginning of turn...
std::string id
Definition: time_of_day.hpp:91
int lawful_bonus
The % bonus lawful units receive.
Definition: time_of_day.hpp:84
std::string image
The image to be displayed in the game status.
Definition: time_of_day.hpp:88
STL namespace.
static custom_tod::string_pair tod_getter_mask(const time_of_day &tod)
Definition: custom_tod.cpp:92
virtual void draw()
Draws invalidated items.
Definition: display.cpp:2436
T get_widget_value(window &window)
Gets the value of the field.
Definition: field.hpp:395
Implements some helper classes to ease adding fields to a dialog and hide the synchronization needed...
bool show(const unsigned auto_close_time=0)
Shows the window.
static custom_tod::string_pair tod_getter_sound(const time_of_day &tod)
Definition: custom_tod.cpp:98
void do_new_tod(window &window)
Definition: custom_tod.cpp:233
Generic file dialog.
Definition: field-fwd.hpp:22
std::string path() const
Gets the current file selection.
std::string default_dir()
Definition: editor.cpp:32
t_string name
Definition: time_of_day.hpp:89
Object which defines a time of day with associated bonuses, image, sounds etc.
Definition: time_of_day.hpp:57
static UNUSEDNOWARN std::string _(const char *str)
Definition: gettext.hpp:91
file_dialog & set_read_only(bool value)
Whether to provide user interface elements for manipulating existing objects.
void set_widget_value(window &window, CT value)
Sets the value of the field.
Definition: field.hpp:358
void set_tooltip(const t_string &tooltip)
void connect_signal_notify_modified(dispatcher &dispatcher, const signal_notification_function &signal)
Connects a signal handler for getting a notification upon modification.
Definition: dispatcher.cpp:248
std::function< string_pair(const time_of_day &)> tod_attribute_getter
Definition: custom_tod.hpp:38
const time_of_day & get_selected_tod() const
Definition: custom_tod.cpp:256
void update_lawful_bonus(window &window)
Definition: custom_tod.cpp:307
This file contains the settings handling of the widget library.
std::ostringstream wrapper.
Definition: formatter.hpp:38
void connect_signal_mouse_left_click(dispatcher &dispatcher, const signal_function &signal)
Connects a signal handler for a left mouse button click.
Definition: dispatcher.cpp:233
void set_is_dirty(const bool is_dirty)
Definition: widget.cpp:463
void update_tod(const time_of_day *tod_override=nullptr)
Applies r,g,b coloring to the map.
Definition: display.cpp:430
field_integer * color_field_g_
Definition: custom_tod.hpp:80
field_integer * color_field_b_
Definition: custom_tod.hpp:81
map_display and display: classes which take care of displaying the map and game-data on the screen...
static custom_tod::string_pair tod_getter_image(const time_of_day &tod)
Definition: custom_tod.cpp:86
void invalidate_all()
Function to invalidate all tiles.
Definition: display.cpp:2968
Various uncategorised dialogs.
styled_widget * get_widget()
Definition: field.hpp:206
field_integer * color_field_r_
Definition: custom_tod.hpp:79
void do_delete_tod(window &window)
Definition: custom_tod.cpp:239
void update_selected_tod_info(window &window)
Definition: custom_tod.cpp:312
virtual void post_show(window &window) override
Inherited from modal_dialog.
Definition: custom_tod.cpp:343
void select_file(window &window, const std::string &default_dir)
Definition: custom_tod.cpp:189
virtual void pre_show(window &window) override
Inherited from modal_dialog.
Definition: custom_tod.cpp:116
Declarations for File-IO.
std::string base_name(const std::string &file, const bool remove_extension)
Returns the base filename of a file, with directory name stripped.
void undraw()
Undraws the window.
Definition: window.cpp:783
virtual void set_active(const bool active) override
See styled_widget::set_active.
Definition: button.cpp:62
void copy_to_clipboard(const std::string &text, const bool)
Copies text to the clipboard.
Definition: clipboard.cpp:35
Simple push button.
Definition: button.hpp:35
void do_next_tod(window &window)
Callback for the next tod button.
Definition: custom_tod.cpp:221
void copy_to_clipboard_callback(tod_attribute_getter getter)
Definition: custom_tod.cpp:338
Dialog was closed with the OK button.
Definition: retval.hpp:34
void add_to_tab_order(widget *widget, int at=-1)
Add the widget to the tabbing order.
Definition: window.cpp:1300
base class of top level items, the only item which needs to store the final canvases to draw on ...
Definition: window.hpp:63
std::string directory_name(const std::string &file)
Returns the directory name of a file, with filename stripped.
file_dialog & set_title(const std::string &value)
Sets the current dialog title text.
Definition: file_dialog.hpp:56
void color_slider_callback(window &window)
Definition: custom_tod.cpp:265