The Battle for Wesnoth  1.15.0+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 "gui/auxiliary/field.hpp"
23 #include "video.hpp"
24 
25 namespace gui2
26 {
27 namespace dialogs
28 {
30  : window_(nullptr)
31  , retval_(retval::NONE)
32  , always_save_fields_(false)
33  , fields_()
34  , focus_()
35  , restore_(false)
36  , allow_plugin_skip_(true)
37  , show_even_without_video_(false)
38 {
39 }
40 
42 {
43 }
44 
45 namespace {
46  struct window_stack_handler {
47  window_stack_handler(std::unique_ptr<window>& win) : local_window(win) {
48  open_window_stack.push_back(local_window.get());
49  }
50  ~window_stack_handler() {
52  }
53  std::unique_ptr<window>& local_window;
54  };
55 }
56 
57 bool modal_dialog::show(const unsigned auto_close_time)
58 {
60  if(!allow_plugin_skip_) {
61  return false;
62  }
63 
65  if (pm && pm->any_running())
66  {
67  plugins_context pc("Dialog");
68  pc.set_callback("skip_dialog", [this](config) { retval_ = retval::OK; }, false);
69  pc.set_callback("quit", [](config) {}, false);
70  pc.play_slice();
71  }
72 
73  return false;
74  }
75 
76  window_.reset(build_window());
77  assert(window_.get());
78 
80 
81  window_->set_owner(this);
82 
84 
85  pre_show(*window_);
86 
87  { // Scope the window stack
88  window_stack_handler push_window_stack(window_);
89  retval_ = window_->show(restore_, auto_close_time);
90  }
91 
92  /*
93  * It can happen that when two clicks follow each other fast that the event
94  * handling code in events.cpp generates a DOUBLE_CLICK_EVENT. For some
95  * reason it can happen that this event gets pushed in the queue when the
96  * window is shown, but processed after the window is closed. This causes
97  * the next window to get this pending event.
98  *
99  * This caused a bug where double clicking in the campaign selection dialog
100  * directly selected a difficulty level and started the campaign. In order
101  * to avoid that problem, filter all pending DOUBLE_CLICK_EVENT events after
102  * the window is closed.
103  */
104  SDL_FlushEvent(DOUBLE_CLICK_EVENT);
105 
107 
108  post_show(*window_);
109 
110  // post_show may have updated the window retval. Update it here.
111  retval_ = window_->get_retval();
112 
113  // Reset window object.
114  window_.reset(nullptr);
115 
116  return retval_ == retval::OK;
117 }
118 
120  const std::string& id,
121  const bool mandatory,
122  const std::function<bool()> callback_load_value,
123  const std::function<void(bool)> callback_save_value,
124  const std::function<void(widget&)> callback_change,
125  const bool initial_fire)
126 {
127  field_bool* field = new field_bool(id,
128  mandatory,
129  callback_load_value,
130  callback_save_value,
131  callback_change,
132  initial_fire);
133 
134  fields_.emplace_back(field);
135  return field;
136 }
137 
138 field_bool*
139 modal_dialog::register_bool(const std::string& id,
140  const bool mandatory,
141  bool& linked_variable,
142  const std::function<void(widget&)> callback_change,
143  const bool initial_fire)
144 {
146  = new field_bool(id, mandatory, linked_variable, callback_change, initial_fire);
147 
148  fields_.emplace_back(field);
149  return field;
150 }
151 
153  const std::string& id,
154  const bool mandatory,
155  const std::function<int()> callback_load_value,
156  const std::function<void(const int)> callback_save_value)
157 {
159  id, mandatory, callback_load_value, callback_save_value);
160 
161  fields_.emplace_back(field);
162  return field;
163 }
164 
166  const bool mandatory,
167  int& linked_variable)
168 {
169  field_integer* field = new field_integer(id, mandatory, linked_variable);
170 
171  fields_.emplace_back(field);
172  return field;
173 }
174 
176  const std::string& id,
177  const bool mandatory,
178  const std::function<std::string()> callback_load_value,
179  const std::function<void(const std::string&)> callback_save_value,
180  const bool capture_focus)
181 {
182  field_text* field = new field_text(
183  id, mandatory, callback_load_value, callback_save_value);
184 
185  if(capture_focus) {
186  focus_ = id;
187  }
188 
189  fields_.emplace_back(field);
190  return field;
191 }
192 
194  const bool mandatory,
195  std::string& linked_variable,
196  const bool capture_focus)
197 {
198  field_text* field = new field_text(id, mandatory, linked_variable);
199 
200  if(capture_focus) {
201  focus_ = id;
202  }
203 
204  fields_.emplace_back(field);
205  return field;
206 }
207 
209  const bool mandatory,
210  const std::string& text,
211  const bool use_markup)
212 {
213  field_label* field = new field_label(id, mandatory, text, use_markup);
214 
215  fields_.emplace_back(field);
216  return field;
217 }
218 
220 {
221  return build(window_id());
222 }
223 
225 {
226  /* DO NOTHING */
227 }
228 
230 {
231  /* DO NOTHING */
232 }
233 
235 {
236  /* DO NOTHING */
237 }
238 
240 {
241  for(auto& field : fields_)
242  {
243  field->attach_to_window(window);
244  field->widget_init(window);
245  }
246 
247  if(!focus_.empty()) {
248  if(widget* widget = window.find(focus_, false)) {
249  window.keyboard_capture(widget);
250  }
251  }
252 }
253 
254 void modal_dialog::finalize_fields(window& window, const bool save_fields)
255 {
256  for(auto& field : fields_)
257  {
258  if(save_fields) {
259  field->widget_finalize(window);
260  }
262  }
263 }
264 
265 } // namespace dialogs
266 } // namespace gui2
267 
268 
269 /*WIKI
270  * @page = GUIWindowDefinitionWML
271  * @order = 1
272  *
273  * {{Autogenerated}}
274  *
275  * = Window definition =
276  *
277  * The window definition define how the windows shown in the dialog look.
278  */
279 
280 /*WIKI
281  * @page = GUIWindowDefinitionWML
282  * @order = ZZZZZZ_footer
283  *
284  * [[Category: WML Reference]]
285  * [[Category: GUI WML Reference]]
286  */
void keyboard_capture(widget *widget)
Definition: window.cpp:1282
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:823
#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:92
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:63
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