The Battle for Wesnoth  1.15.3+dev
modal_dialog.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-lib"
16 
18 
19 #include "cursor.hpp"
20 #include "gui/auxiliary/field.hpp"
24 #include "video.hpp"
25 
26 namespace gui2
27 {
28 namespace dialogs
29 {
31  : window_(nullptr)
32  , retval_(retval::NONE)
33  , always_save_fields_(false)
34  , fields_()
35  , focus_()
36  , restore_(false)
37  , allow_plugin_skip_(true)
38  , show_even_without_video_(false)
39 {
40 }
41 
43 {
44 }
45 
46 namespace {
47  struct window_stack_handler {
48  window_stack_handler(std::unique_ptr<window>& win) : local_window(win) {
49  open_window_stack.push_back(local_window.get());
50  }
51  ~window_stack_handler() {
53  }
54  std::unique_ptr<window>& local_window;
55  };
56 }
57 
58 bool modal_dialog::show(const unsigned auto_close_time)
59 {
61  if(!allow_plugin_skip_) {
62  return false;
63  }
64 
66  if (pm && pm->any_running())
67  {
68  plugins_context pc("Dialog");
69  pc.set_callback("skip_dialog", [this](config) { retval_ = retval::OK; }, false);
70  pc.set_callback("quit", [](config) {}, false);
71  pc.play_slice();
72  }
73 
74  return false;
75  }
76 
77  window_.reset(build_window());
78  assert(window_.get());
79 
81 
82  window_->set_owner(this);
83 
85 
86  pre_show(*window_);
87 
88  { // Scope the window stack
90  window_stack_handler push_window_stack(window_);
91  retval_ = window_->show(restore_, auto_close_time);
92  }
93 
94  /*
95  * It can happen that when two clicks follow each other fast that the event
96  * handling code in events.cpp generates a DOUBLE_CLICK_EVENT. For some
97  * reason it can happen that this event gets pushed in the queue when the
98  * window is shown, but processed after the window is closed. This causes
99  * the next window to get this pending event.
100  *
101  * This caused a bug where double clicking in the campaign selection dialog
102  * directly selected a difficulty level and started the campaign. In order
103  * to avoid that problem, filter all pending DOUBLE_CLICK_EVENT events after
104  * the window is closed.
105  */
106  SDL_FlushEvent(DOUBLE_CLICK_EVENT);
107 
109 
110  post_show(*window_);
111 
112  // post_show may have updated the window retval. Update it here.
113  retval_ = window_->get_retval();
114 
115  // Reset window object.
116  window_.reset(nullptr);
117 
118  return retval_ == retval::OK;
119 }
120 
122  const std::string& id,
123  const bool mandatory,
124  const std::function<bool()> callback_load_value,
125  const std::function<void(bool)> callback_save_value,
126  const std::function<void(widget&)> callback_change,
127  const bool initial_fire)
128 {
129  field_bool* field = new field_bool(id,
130  mandatory,
131  callback_load_value,
132  callback_save_value,
133  callback_change,
134  initial_fire);
135 
136  fields_.emplace_back(field);
137  return field;
138 }
139 
140 field_bool*
141 modal_dialog::register_bool(const std::string& id,
142  const bool mandatory,
143  bool& linked_variable,
144  const std::function<void(widget&)> callback_change,
145  const bool initial_fire)
146 {
148  = new field_bool(id, mandatory, linked_variable, callback_change, initial_fire);
149 
150  fields_.emplace_back(field);
151  return field;
152 }
153 
155  const std::string& id,
156  const bool mandatory,
157  const std::function<int()> callback_load_value,
158  const std::function<void(const int)> callback_save_value)
159 {
161  id, mandatory, callback_load_value, callback_save_value);
162 
163  fields_.emplace_back(field);
164  return field;
165 }
166 
168  const bool mandatory,
169  int& linked_variable)
170 {
171  field_integer* field = new field_integer(id, mandatory, linked_variable);
172 
173  fields_.emplace_back(field);
174  return field;
175 }
176 
178  const std::string& id,
179  const bool mandatory,
180  const std::function<std::string()> callback_load_value,
181  const std::function<void(const std::string&)> callback_save_value,
182  const bool capture_focus)
183 {
184  field_text* field = new field_text(
185  id, mandatory, callback_load_value, callback_save_value);
186 
187  if(capture_focus) {
188  focus_ = id;
189  }
190 
191  fields_.emplace_back(field);
192  return field;
193 }
194 
196  const bool mandatory,
197  std::string& linked_variable,
198  const bool capture_focus)
199 {
200  field_text* field = new field_text(id, mandatory, linked_variable);
201 
202  if(capture_focus) {
203  focus_ = id;
204  }
205 
206  fields_.emplace_back(field);
207  return field;
208 }
209 
211  const bool mandatory,
212  const std::string& text,
213  const bool use_markup)
214 {
215  field_label* field = new field_label(id, mandatory, text, use_markup);
216 
217  fields_.emplace_back(field);
218  return field;
219 }
220 
222 {
223  return build(window_id());
224 }
225 
227 {
228  /* DO NOTHING */
229 }
230 
232 {
233  /* DO NOTHING */
234 }
235 
237 {
238  /* DO NOTHING */
239 }
240 
242 {
243  for(auto& field : fields_)
244  {
245  field->attach_to_window(window);
246  field->widget_init(window);
247  }
248 
249  if(!focus_.empty()) {
250  if(widget* widget = window.find(focus_, false)) {
251  window.keyboard_capture(widget);
252  }
253  }
254 }
255 
256 void modal_dialog::finalize_fields(window& window, const bool save_fields)
257 {
258  for(auto& field : fields_)
259  {
260  if(save_fields) {
261  field->widget_finalize(window);
262  }
264  }
265 }
266 
267 } // namespace dialogs
268 } // namespace gui2
269 
270 
271 /*WIKI
272  * @page = GUIWindowDefinitionWML
273  * @order = 1
274  *
275  * {{Autogenerated}}
276  *
277  * = Window definition =
278  *
279  * The window definition define how the windows shown in the dialog look.
280  */
281 
282 /*WIKI
283  * @page = GUIWindowDefinitionWML
284  * @order = ZZZZZZ_footer
285  *
286  * [[Category: WML Reference]]
287  * [[Category: GUI WML Reference]]
288  */
void keyboard_capture(widget *widget)
Definition: window.cpp:1281
void set_callback(const std::string &name, callback_function)
Definition: context.cpp:51
void attach_to_window(window &window)
Attaches the field to a window.
Definition: field.hpp:77
bool show_even_without_video_
Show the dialog even with –nogui? Some dialogs need to be shown even when –nogui is specified if th...
Specialized field class for boolean.
Definition: field.hpp:544
void widget_finalize(window &window)
Finalizes the widget.
Definition: field.hpp:120
virtual void post_build(window &window)
Actions to be taken directly after the window is build.
Base class for all widgets.
Definition: widget.hpp:47
virtual void finalize_fields(window &window, const bool save_fields)
When the dialog is closed with the OK status saves all fields.
bool allow_plugin_skip_
Allow plugins to skip through the dialog? Most dialogs install a plugins context to allow plugins to ...
static CVideo & get_singleton()
Definition: video.hpp:43
field_bool * register_bool(const std::string &id, const bool mandatory, const std::function< bool()> callback_load_value=nullptr, const std::function< void(bool)> callback_save_value=nullptr, const std::function< void(widget &)> callback_change=nullptr, const bool initial_fire=false)
Creates a new boolean field.
Implements some helper classes to ease adding fields to a dialog and hide the synchronization needed...
bool always_save_fields_
Always save the fields upon closing.
bool show(const unsigned auto_close_time=0)
Shows the window.
-file util.hpp
field< int, integer_selector > field_integer
Definition: field-fwd.hpp:36
void detach_from_window()
Detaches the field from a window.
Definition: field.hpp:131
Generic file dialog.
Definition: field-fwd.hpp:22
field_text * register_text(const std::string &id, const bool mandatory, const std::function< std::string()> callback_load_value=nullptr, const std::function< void(const std::string &)> callback_save_value=nullptr, const bool capture_focus=false)
Creates a new text field.
std::vector< std::unique_ptr< class field_base > > fields_
Contains the automatically managed fields.
bool restore_
Restore the screen after showing?
field_integer * register_integer(const std::string &id, const bool mandatory, const std::function< int()> callback_load_value=nullptr, const std::function< void(int)> callback_save_value=nullptr)
Creates a new integer field.
void remove_from_window_stack(window *window)
Removes a entry from the open_window_stack list.
Definition: handler.cpp:1108
static void field(LexState *ls, struct ConsControl *cc)
Definition: lparser.cpp:702
window * build_window() const
Builds the window.
Various uncategorised dialogs.
widget * find(const std::string &id, const bool must_be_active) override
See widget::find.
Definition: window.cpp:822
#define DOUBLE_CLICK_EVENT
Definition: events.hpp:23
virtual void init_fields(window &window)
Initializes all fields in the dialog and set the keyboard focus.
Default, unset return value.
Definition: retval.hpp:31
Specialized field class for a styled_widget, used for labels and images.
Definition: field.hpp:626
window * build(const builder_window::window_resolution *definition)
Builds a window.
field_label * register_label(const std::string &id, const bool mandatory, const std::string &text, const bool use_markup=false)
Registers a new styled_widget as a label.
virtual const std::string & window_id() const =0
The id of the window to build.
bool any_running()
Definition: manager.cpp:206
int retval_
Returns the window exit status, 0 means not shown.
void widget_init(window &window)
Initializes the widget.
Definition: field.hpp:101
std::unique_ptr< window > window_
The window object build for this dialog.
virtual void pre_show(window &window)
Actions to be taken before showing the window.
retval
Default window/dialog return values.
Definition: retval.hpp:28
Dialog was closed with the OK button.
Definition: retval.hpp:34
virtual void post_show(window &window)
Actions to be taken after the window has been shown.
std::string focus_
Contains the widget that should get the focus when the window is shown.
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:68
Specialized field class for text.
Definition: field.hpp:592
base class of top level items, the only item which needs to store the final canvases to draw on ...
Definition: window.hpp:62
Template class to implement the generic field implementation.
Definition: field-fwd.hpp:35
static plugins_manager * get()
Definition: manager.cpp:58
void play_slice()
Definition: context.cpp:96
std::vector< window * > open_window_stack
Keeps track of any open windows of any type (modal, non-modal, or tooltip) in the order in which they...
Definition: handler.cpp:1106