The Battle for Wesnoth  1.17.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 "cursor.hpp"
20 #include "gui/auxiliary/field.hpp"
24 #include "video.hpp"
25 
26 namespace gui2::dialogs
27 {
29  : window_(nullptr)
30  , retval_(retval::NONE)
31  , always_save_fields_(false)
32  , fields_()
33  , focus_()
34  , restore_(false)
35  , allow_plugin_skip_(true)
36  , show_even_without_video_(false)
37 {
38 }
39 
41 {
42 }
43 
44 namespace {
45  struct window_stack_handler {
46  window_stack_handler(std::unique_ptr<window>& win) : local_window(win) {
47  open_window_stack.push_back(local_window.get());
48  }
49  ~window_stack_handler() {
51  }
52  std::unique_ptr<window>& local_window;
53  };
54 }
55 
56 bool modal_dialog::show(const unsigned auto_close_time)
57 {
59  if(!allow_plugin_skip_) {
60  return false;
61  }
62 
64  if (pm && pm->any_running())
65  {
66  plugins_context pc("Dialog");
67  pc.set_callback("skip_dialog", [this](config) { retval_ = retval::OK; }, false);
68  pc.set_callback("quit", [](config) {}, false);
69  pc.play_slice();
70  }
71 
72  return false;
73  }
74 
76  assert(window_.get());
77 
79 
80  window_->set_owner(this);
81 
83 
84  pre_show(*window_);
85 
86  { // 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 {
121  if(window_) {
122  window_->set_retval(retval);
123  }
124 }
125 
127  const std::string& id,
128  const bool mandatory,
129  const std::function<bool()> callback_load_value,
130  const std::function<void(bool)> callback_save_value,
131  const std::function<void(widget&)> callback_change,
132  const bool initial_fire)
133 {
134  field_bool* field = new field_bool(id,
135  mandatory,
136  callback_load_value,
137  callback_save_value,
138  callback_change,
139  initial_fire);
140 
141  fields_.emplace_back(field);
142  return field;
143 }
144 
145 field_bool*
146 modal_dialog::register_bool(const std::string& id,
147  const bool mandatory,
148  bool& linked_variable,
149  const std::function<void(widget&)> callback_change,
150  const bool initial_fire)
151 {
153  = new field_bool(id, mandatory, linked_variable, callback_change, initial_fire);
154 
155  fields_.emplace_back(field);
156  return field;
157 }
158 
160  const std::string& id,
161  const bool mandatory,
162  const std::function<int()> callback_load_value,
163  const std::function<void(const int)> callback_save_value)
164 {
166  id, mandatory, callback_load_value, callback_save_value);
167 
168  fields_.emplace_back(field);
169  return field;
170 }
171 
173  const bool mandatory,
174  int& linked_variable)
175 {
176  field_integer* field = new field_integer(id, mandatory, linked_variable);
177 
178  fields_.emplace_back(field);
179  return field;
180 }
181 
183  const std::string& id,
184  const bool mandatory,
185  const std::function<std::string()> callback_load_value,
186  const std::function<void(const std::string&)> callback_save_value,
187  const bool capture_focus)
188 {
189  field_text* field = new field_text(
190  id, mandatory, callback_load_value, callback_save_value);
191 
192  if(capture_focus) {
193  focus_ = id;
194  }
195 
196  fields_.emplace_back(field);
197  return field;
198 }
199 
201  const bool mandatory,
202  std::string& linked_variable,
203  const bool capture_focus)
204 {
205  field_text* field = new field_text(id, mandatory, linked_variable);
206 
207  if(capture_focus) {
208  focus_ = id;
209  }
210 
211  fields_.emplace_back(field);
212  return field;
213 }
214 
216  const bool mandatory,
217  const std::string& text,
218  const bool use_markup)
219 {
220  field_label* field = new field_label(id, mandatory, text, use_markup);
221 
222  fields_.emplace_back(field);
223  return field;
224 }
225 
226 std::unique_ptr<window> modal_dialog::build_window() const
227 {
228  return build(window_id());
229 }
230 
232 {
233  /* DO NOTHING */
234 }
235 
237 {
238  /* DO NOTHING */
239 }
240 
242 {
243  /* DO NOTHING */
244 }
245 
247 {
248  for(auto& field : fields_)
249  {
250  field->attach_to_window(window);
251  field->widget_init(window);
252  }
253 
254  if(!focus_.empty()) {
255  if(widget* widget = window.find(focus_, false)) {
256  window.keyboard_capture(widget);
257  }
258  }
259 }
260 
261 void modal_dialog::finalize_fields(window& window, const bool save_fields)
262 {
263  for(auto& field : fields_)
264  {
265  if(save_fields) {
266  field->widget_finalize(window);
267  }
269  }
270 }
271 
272 } // namespace dialogs
void keyboard_capture(widget *widget)
Definition: window.cpp:1275
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:48
static void field(LexState *ls, ConsControl *cc)
Definition: lparser.cpp:891
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:48
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.
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
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:1105
widget * find(const std::string &id, const bool must_be_active) override
See widget::find.
Definition: window.cpp:815
std::string id
Text to match against addon_info.tags()
Definition: manager.cpp:214
#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
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_
The window&#39;s exit code (return value).
void widget_init(window &window)
Initializes the widget.
Definition: field.hpp:101
std::unique_ptr< window > window_
The window object build for this dialog.
std::unique_ptr< window > build_window() const
Builds the window.
virtual void pre_show(window &window)
Actions to be taken before showing the window.
retval
Default window/dialog return values.
Definition: retval.hpp:28
std::unique_ptr< window > build(const builder_window::window_resolution &definition)
Builds a window.
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:59
Specialized field class for text.
Definition: field.hpp:592
void set_retval(int retval)
Convenience wrapper to set the window&#39;s exit code.
base class of top level items, the only item which needs to store the final canvases to draw on...
Definition: window.hpp:64
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:1103