The Battle for Wesnoth  1.15.9+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 
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 {
123  if(window_) {
124  window_->set_retval(retval);
125  }
126 }
127 
129  const std::string& id,
130  const bool mandatory,
131  const std::function<bool()> callback_load_value,
132  const std::function<void(bool)> callback_save_value,
133  const std::function<void(widget&)> callback_change,
134  const bool initial_fire)
135 {
136  field_bool* field = new field_bool(id,
137  mandatory,
138  callback_load_value,
139  callback_save_value,
140  callback_change,
141  initial_fire);
142 
143  fields_.emplace_back(field);
144  return field;
145 }
146 
147 field_bool*
148 modal_dialog::register_bool(const std::string& id,
149  const bool mandatory,
150  bool& linked_variable,
151  const std::function<void(widget&)> callback_change,
152  const bool initial_fire)
153 {
155  = new field_bool(id, mandatory, linked_variable, callback_change, initial_fire);
156 
157  fields_.emplace_back(field);
158  return field;
159 }
160 
162  const std::string& id,
163  const bool mandatory,
164  const std::function<int()> callback_load_value,
165  const std::function<void(const int)> callback_save_value)
166 {
168  id, mandatory, callback_load_value, callback_save_value);
169 
170  fields_.emplace_back(field);
171  return field;
172 }
173 
175  const bool mandatory,
176  int& linked_variable)
177 {
178  field_integer* field = new field_integer(id, mandatory, linked_variable);
179 
180  fields_.emplace_back(field);
181  return field;
182 }
183 
185  const std::string& id,
186  const bool mandatory,
187  const std::function<std::string()> callback_load_value,
188  const std::function<void(const std::string&)> callback_save_value,
189  const bool capture_focus)
190 {
191  field_text* field = new field_text(
192  id, mandatory, callback_load_value, callback_save_value);
193 
194  if(capture_focus) {
195  focus_ = id;
196  }
197 
198  fields_.emplace_back(field);
199  return field;
200 }
201 
203  const bool mandatory,
204  std::string& linked_variable,
205  const bool capture_focus)
206 {
207  field_text* field = new field_text(id, mandatory, linked_variable);
208 
209  if(capture_focus) {
210  focus_ = id;
211  }
212 
213  fields_.emplace_back(field);
214  return field;
215 }
216 
218  const bool mandatory,
219  const std::string& text,
220  const bool use_markup)
221 {
222  field_label* field = new field_label(id, mandatory, text, use_markup);
223 
224  fields_.emplace_back(field);
225  return field;
226 }
227 
228 std::unique_ptr<window> modal_dialog::build_window() const
229 {
230  return build(window_id());
231 }
232 
234 {
235  /* DO NOTHING */
236 }
237 
239 {
240  /* DO NOTHING */
241 }
242 
244 {
245  /* DO NOTHING */
246 }
247 
249 {
250  for(auto& field : fields_)
251  {
252  field->attach_to_window(window);
253  field->widget_init(window);
254  }
255 
256  if(!focus_.empty()) {
257  if(widget* widget = window.find(focus_, false)) {
258  window.keyboard_capture(widget);
259  }
260  }
261 }
262 
263 void modal_dialog::finalize_fields(window& window, const bool save_fields)
264 {
265  for(auto& field : fields_)
266  {
267  if(save_fields) {
268  field->widget_finalize(window);
269  }
271  }
272 }
273 
274 } // namespace dialogs
275 } // namespace gui2
void keyboard_capture(widget *widget)
Definition: window.cpp:1273
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:49
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
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:1106
static void field(LexState *ls, struct ConsControl *cc)
Definition: lparser.cpp:703
Various uncategorised dialogs.
widget * find(const std::string &id, const bool must_be_active) override
See widget::find.
Definition: window.cpp:813
#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:60
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:1104