The Battle for Wesnoth  1.15.7+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  if(times_.empty())
114  {
115  times_.push_back(time_of_day());
116  }
117 }
118 
120 {
121  static std::map<std::string, tod_attribute_getter> metadata_stuff {
122  {"image", tod_getter_image},
123  {"mask", tod_getter_mask },
124  {"sound", tod_getter_sound}
125  };
126 
127  window.add_to_tab_order(find_widget<text_box>(&window, "tod_name", false, true));
128  window.add_to_tab_order(find_widget<text_box>(&window, "tod_id", false, true));
129 
130  for(const auto& data : metadata_stuff) {
131  find_widget<text_box>(&window, "path_" + data.first, false).set_active(false);
132 
133  button& copy_w = find_widget<button>(&window, "copy_" + data.first, false);
134 
136  std::bind(&custom_tod::copy_to_clipboard_callback, this, data.second));
137 
139  copy_w.set_active(false);
140  copy_w.set_tooltip(_("Clipboard support not found, contact your packager"));
141  }
142  }
143 
145  find_widget<button>(&window, "browse_image", false),
146  std::bind(&custom_tod::select_file<tod_getter_image>, this, "data/core/images/misc"));
147 
149  find_widget<button>(&window, "browse_mask", false),
150  std::bind(&custom_tod::select_file<tod_getter_mask>, this, "data/core/images"));
151 
153  find_widget<button>(&window, "browse_sound", false),
154  std::bind(&custom_tod::select_file<tod_getter_sound>, this, "data/core/sounds/ambient"));
155 
157  find_widget<button>(&window, "next_tod", false),
158  std::bind(&custom_tod::do_next_tod, this));
159 
161  find_widget<button>(&window, "previous_tod", false),
162  std::bind(&custom_tod::do_prev_tod, this));
163 
165  find_widget<button>(&window, "new", false),
166  std::bind(&custom_tod::do_new_tod, this));
167 
169  find_widget<button>(&window, "delete", false),
170  std::bind(&custom_tod::do_delete_tod, this));
171 
173  find_widget<slider>(&window, "lawful_bonus", false),
174  std::bind(&custom_tod::update_lawful_bonus, this));
175 
178  std::bind(&custom_tod::color_slider_callback, this));
179 
182  std::bind(&custom_tod::color_slider_callback, this));
183 
186  std::bind(&custom_tod::color_slider_callback, this));
187 
189 }
190 
191 template<custom_tod::string_pair(*fptr)(const time_of_day&)>
193 {
194  const string_pair& data = (*fptr)(get_selected_tod());
195 
196  std::string fn = filesystem::base_name(data.second);
198  if(dn.empty()) {
199  dn = default_dir;
200  }
201 
203 
204  dlg.set_title(_("Choose File"))
205  .set_ok_label(_("Select"))
206  .set_path(dn)
207  .set_read_only(true);
208 
209  if(dlg.show()) {
210  dn = dlg.path();
211 
212  if(data.first == "image") {
213  times_[current_tod_].image = dn;
214  } else if(data.first == "mask") {
215  times_[current_tod_].image_mask = dn;
216  } else if(data.first == "sound") {
217  times_[current_tod_].sounds = dn;
218  }
219  }
220 
222 }
223 
225 {
226  current_tod_ = (current_tod_ + 1) % times_.size();
228 }
229 
231 {
232  current_tod_ = (current_tod_ ? current_tod_ : times_.size()) - 1;
234 }
235 
237 {
238  times_.insert(times_.begin() + current_tod_, time_of_day());
240 }
241 
243 {
244  assert(times_.begin() + current_tod_ < times_.end());
245 
246  if(times_.size() == 1) {
247  times_.emplace_back();
248  } else {
249  times_.erase(times_.begin() + current_tod_);
250 
251  if(times_.begin() + current_tod_ >= times_.end()) {
252  current_tod_ = times_.size() - 1;
253  }
254  }
255 
257 }
258 
260 {
261  try {
262  return times_.at(current_tod_);
263  } catch(const std::out_of_range&) {
264  throw std::string("Attempted to fetch a non-existant ToD!");
265  }
266 }
267 
269 {
270  time_of_day& current_tod = times_[current_tod_];
271 
272  current_tod.color.r = color_field_r_->get_widget_value(*get_window());
273  current_tod.color.g = color_field_g_->get_widget_value(*get_window());
274  current_tod.color.b = color_field_b_->get_widget_value(*get_window());
275 
277 }
278 
280 {
282  assert(disp && "Display pointer is null!");
283 
284  // Prevent a floating slice of window appearing alone over the
285  // theme UI sidebar after redrawing tiles and before we have a
286  // chance to redraw the rest of this window.
287  get_window()->undraw();
288 
289  // NOTE: We only really want to re-render the gamemap tiles here.
290  // Redrawing everything is a significantly more expensive task.
291  // At this time, tiles are the only elements on which ToD tint is
292  // meant to have a visible effect. This is very strongly tied to
293  // the image caching mechanism.
294  //
295  // If this ceases to be the case in the future, you'll need to call
296  // redraw_everything() instead.
297 
298  disp->update_tod(&get_selected_tod());
299 
300  // invalidate all tiles so they are redrawn with the new ToD tint next
301  disp->invalidate_all();
302 
303  // redraw tiles
304  disp->draw(false);
305 
306  // NOTE: revert to invalidate_layout if necessary to display the ToD mask image.
307  get_window()->set_is_dirty(true);
308 }
309 
311 {
312  times_[current_tod_].lawful_bonus = find_widget<slider>(get_window(), "lawful_bonus", false).get_value();
313 }
314 
316 {
317  const time_of_day& current_tod = get_selected_tod();
318 
319  find_widget<text_box>(get_window(), "tod_name", false).set_value(current_tod.name);
320  find_widget<text_box>(get_window(), "tod_id", false).set_value(current_tod.id);
321 
322  find_widget<text_box>(get_window(), "path_image", false).set_value(current_tod.image);
323  find_widget<text_box>(get_window(), "path_mask", false).set_value(current_tod.image_mask);
324  find_widget<text_box>(get_window(), "path_sound", false).set_value(current_tod.sounds);
325 
326  find_widget<image>(get_window(), "current_tod_image", false).set_image(current_tod.image);
327  find_widget<image>(get_window(), "current_tod_mask", false).set_image(current_tod.image_mask);
328 
329  find_widget<slider>(get_window(), "lawful_bonus", false).set_value(current_tod.lawful_bonus);
330 
334 
335  const std::string new_index_str = formatter() << (current_tod_ + 1) << "/" << times_.size();
336  find_widget<label>(get_window(), "tod_number", false).set_label(new_index_str);
337 
339 }
340 
342 {
344 }
345 
346 void custom_tod::post_show(window& /*window*/)
347 {
349 
350  if(get_retval() == retval::OK) {
351  // TODO: save ToD
352  }
353 }
354 
355 } // namespace dialogs
356 } // 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
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
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.
window * get_window() const
Returns a pointer to the dialog&#39;s window.
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:2475
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
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:100
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:186
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:259
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:171
void set_is_dirty(const bool is_dirty)
Definition: widget.cpp:465
void update_tod(const time_of_day *tod_override=nullptr)
Applies r,g,b coloring to the map.
Definition: display.cpp:454
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:3011
Various uncategorised dialogs.
styled_widget * get_widget()
Definition: field.hpp:206
field_integer * color_field_r_
Definition: custom_tod.hpp:79
void select_file(const std::string &default_dir)
Definition: custom_tod.cpp:192
virtual void post_show(window &window) override
Inherited from modal_dialog.
Definition: custom_tod.cpp:346
virtual void pre_show(window &window) override
Inherited from modal_dialog.
Definition: custom_tod.cpp:119
Declarations for File-IO.
void do_next_tod()
Callback for the next tod button.
Definition: custom_tod.cpp:224
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:782
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 copy_to_clipboard_callback(tod_attribute_getter getter)
Definition: custom_tod.cpp:341
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:62
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