1 /*
2    Copyright (C) 2007 - 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 /**
16  *  @file
17  *  This file contains the window object, this object is a top level container
18  *  which has the event management as well.
19  */
20 
21 #pragma once
22 
23 #include "formula/callable.hpp"
24 #include "formula/function.hpp"
25 #include "gui/auxiliary/typed_formula.hpp"
26 #include "gui/core/event/handler.hpp"
27 #include "gui/core/window_builder.hpp"
28 #include "gui/widgets/panel.hpp"
29 #include "gui/widgets/retval.hpp"
30 
31 #include <functional>
32 #include <map>
33 #include <memory>
34 #include <string>
35 #include <vector>
36 
37 class CVideo;
38 class surface;
39 struct point;
40 
41 namespace gui2
42 {
43 
44 class widget;
45 namespace event { struct message; }
46 
47 // ------------ WIDGET -----------{
48 
49 namespace dialogs { class modal_dialog; }
50 class debug_layout_graph;
51 class pane;
52 
53 namespace event
54 {
55 class distributor;
56 } // namespace event
57 
58 /**
59  * base class of top level items, the only item
60  * which needs to store the final canvases to draw on
61  */
62 class window : public panel
63 {
64 	friend class debug_layout_graph;
65 	friend window* build(const builder_window::window_resolution*);
66 	friend struct window_implementation;
67 	friend class invalidate_layout_blocker;
68 	friend class pane;
69 
70 public:
71 	explicit window(const builder_window::window_resolution* definition);
72 
73 	~window();
74 
75 	/**
76 	 * Returns the instance of a window.
77 	 *
78 	 * @param handle              The instance id of the window.
79 	 *
80 	 * @returns                   The window or nullptr.
81 	 */
82 	static window* window_instance(const unsigned handle);
83 
84 	/** Gets the retval for the default buttons. */
85 	static retval get_retval_by_id(const std::string& id);
86 
87 	/**
88 	 * @todo Clean up the show functions.
89 	 *
90 	 * the show functions are a bit messy and can use a proper cleanup.
91 	 */
92 
93 	/**
94 	 * Shows the window.
95 	 *
96 	 * @param restore             Restore the screenarea the window was on
97 	 *                            after closing it?
98 	 * @param auto_close_timeout  The time in ms after which the window will
99 	 *                            automatically close, if 0 it doesn't close.
100 	 *                            @note the timeout is a minimum time and
101 	 *                            there's no guarantee about how fast it closes
102 	 *                            after the minimum.
103 	 *
104 	 * @returns                   The close code of the window, predefined
105 	 *                            values are listed in retval.
106 	 */
107 	int show(const bool restore = true, const unsigned auto_close_timeout = 0);
108 
109 	/**
110 	 * Shows the window as a tooltip.
111 	 *
112 	 * A tooltip can't be interacted with and is just shown.
113 	 *
114 	 * @todo implement @p auto_close_timeout.
115 	 *
116 	 * @p     auto_close_timeout  The time in ms after which the window will
117 	 *                            automatically close, if 0 it doesn't close.
118 	 *                            @note the timeout is a minimum time and
119 	 *                            there's no guarantee about how fast it closes
120 	 *                            after the minimum.
121 	 */
122 	void show_tooltip(/*const unsigned auto_close_timeout = 0*/);
123 
124 	/**
125 	 * Shows the window non modal.
126 	 *
127 	 * A tooltip can be interacted with unlike the tooltip.
128 	 *
129 	 * @todo implement @p auto_close_timeout.
130 	 *
131 	 * @p     auto_close_timeout  The time in ms after which the window will
132 	 *                            automatically close, if 0 it doesn't close.
133 	 *                            @note the timeout is a minimum time and
134 	 *                            there's no guarantee about how fast it closes
135 	 *                            after the minimum.
136 	 */
137 	void show_non_modal(/*const unsigned auto_close_timeout = 0*/);
138 
139 	/**
140 	 * Draws the window.
141 	 *
142 	 * This routine draws the window if needed, it's called from the event
143 	 * handler. This is done by a drawing event. When a window is shown it
144 	 * manages an SDL timer which fires a drawing event every X milliseconds,
145 	 * that event calls this routine. Don't call it manually.
146 	 */
147 	void draw();
148 
149 	/**
150 	 * Undraws the window.
151 	 */
152 	void undraw();
153 
154 	/**
155 	 * Adds an item to the dirty_list_.
156 	 *
157 	 * @param call_stack          The list of widgets traversed to get to the
158 	 *                            dirty widget.
159 	 */
add_to_dirty_list(const std::vector<widget * > & call_stack)160 	void add_to_dirty_list(const std::vector<widget*>& call_stack)
161 	{
162 		dirty_list_.push_back(call_stack);
163 	}
164 
165 	/** The status of the window. */
166 	enum status {
167 		NEW,		   /**< The window is new and not yet shown. */
168 		SHOWING,	   /**< The window is being shown. */
169 		REQUEST_CLOSE, /**< The window has been requested to be
170 						*   closed but still needs to evaluate the
171 						*   request.
172 						*/
173 		CLOSED /**< The window has been closed. */
174 	};
175 
176 	/**
177 	 * Requests to close the window.
178 	 *
179 	 * At the moment the request is always honored but that might change in the
180 	 * future.
181 	 */
close()182 	void close()
183 	{
184 		status_ = REQUEST_CLOSE;
185 	}
186 
187 	/**
188 	 * Helper class to block invalidate_layout.
189 	 *
190 	 * Some widgets can handling certain layout aspects without help. For
191 	 * example a listbox can handle hiding and showing rows without help but
192 	 * setting the visibility calls invalidate_layout(). When this blocker is
193 	 * Instantiated the call to invalidate_layout() becomes a nop.
194 	 *
195 	 * @note The class can't be used recursively.
196 	 */
197 	class invalidate_layout_blocker
198 	{
199 	public:
200 		invalidate_layout_blocker(window& window);
201 		~invalidate_layout_blocker();
202 
203 	private:
204 		window& window_;
205 	};
206 
207 	/** Is invalidate_layout blocked, see invalidate_layout_blocker. */
invalidate_layout_blocked() const208 	bool invalidate_layout_blocked() const
209 	{
210 		return invalidate_layout_blocked_;
211 	}
212 
213 	/**
214 	 * Updates the size of the window.
215 	 *
216 	 * If the window has automatic placement set this function recalculates the
217 	 * window. To be used after creation and after modification or items which
218 	 * can have different sizes eg listboxes.
219 	 */
220 	void invalidate_layout();
221 
222 	/** See @ref widget::find_at. */
223 	virtual widget* find_at(const point& coordinate,
224 							 const bool must_be_active) override;
225 
226 	/** See @ref widget::find_at. */
227 	virtual const widget* find_at(const point& coordinate,
228 								   const bool must_be_active) const override;
229 
230 	/** Inherited from widget. */
dialog()231 	dialogs::modal_dialog* dialog()
232 	{
233 		return owner_;
234 	}
235 
236 	/** See @ref widget::find. */
237 	widget* find(const std::string& id, const bool must_be_active) override;
238 
239 	/** See @ref widget::find. */
240 	const widget* find(const std::string& id,
241 						const bool must_be_active) const override;
242 
243 #if 0
244 	/** @todo Implement these functions. */
245 	/**
246 	 * Register a widget that prevents easy closing.
247 	 *
248 	 * Duplicate registration are ignored. See click_dismiss_ for more info.
249 	 *
250 	 * @param id                  The id of the widget to register.
251 	 */
252 	void add_click_dismiss_blocker(const std::string& id);
253 
254 	/**
255 	 * Unregister a widget the prevents easy closing.
256 	 *
257 	 * Removing a non registered id is allowed but will do nothing. See
258 	 * click_dismiss_ for more info.
259 	 *
260 	 * @param id                  The id of the widget to register.
261 	 */
262 	void remove_click_dismiss_blocker(const std::string& id);
263 #endif
264 
265 	/**
266 	 * Does the window close easily?
267 	 *
268 	 * The behavior can change at run-time, but that might cause oddities
269 	 * with the easy close button (when one is needed).
270 	 *
271 	 * @returns                   Whether or not the window closes easily.
272 	 */
does_click_dismiss() const273 	bool does_click_dismiss() const
274 	{
275 		return click_dismiss_ && !disable_click_dismiss();
276 	}
277 
278 	/**
279 	 * Disable the enter key.
280 	 *
281 	 * This is added to block dialogs from being closed automatically.
282 	 *
283 	 * @todo this function should be merged with the hotkey support once
284 	 * that has been added.
285 	 */
set_enter_disabled(const bool enter_disabled)286 	void set_enter_disabled(const bool enter_disabled)
287 	{
288 		enter_disabled_ = enter_disabled;
289 	}
290 
291 	/**
292 	 * Disable the escape key.
293 	 *
294 	 * This is added to block dialogs from being closed automatically.
295 	 *
296 	 * @todo this function should be merged with the hotkey support once
297 	 * that has been added.
298 	 */
set_escape_disabled(const bool escape_disabled)299 	void set_escape_disabled(const bool escape_disabled)
300 	{
301 		escape_disabled_ = escape_disabled;
302 	}
303 
304 	/**
305 	 * Initializes a linked size group.
306 	 *
307 	 * Note at least one of fixed_width or fixed_height must be true.
308 	 *
309 	 * @param id                  The id of the group.
310 	 * @param fixed_width         Does the group have a fixed width?
311 	 * @param fixed_height        Does the group have a fixed height?
312 	 */
313 	void init_linked_size_group(const std::string& id,
314 								const bool fixed_width,
315 								const bool fixed_height);
316 
317 	/**
318 	 * Is the linked size group defined for this window?
319 	 *
320 	 * @param id                  The id of the group.
321 	 *
322 	 * @returns                   True if defined, false otherwise.
323 	 */
324 	bool has_linked_size_group(const std::string& id);
325 
326 	/**
327 	 * Adds a widget to a linked size group.
328 	 *
329 	 * The group needs to exist, which is done by calling
330 	 * init_linked_size_group. A widget may only be member of one group.
331 	 * @todo Untested if a new widget is added after showing the widgets.
332 	 *
333 	 * @param id                  The id of the group.
334 	 * @param widget              The widget to add to the group.
335 	 */
336 	void add_linked_widget(const std::string& id, widget* widget);
337 
338 	/**
339 	 * Removes a widget from a linked size group.
340 	 *
341 	 * The group needs to exist, which is done by calling
342 	 * init_linked_size_group. If the widget is no member of the group the
343 	 * function does nothing.
344 	 *
345 	 * @param id                  The id of the group.
346 	 * @param widget              The widget to remove from the group.
347 	 */
348 	void remove_linked_widget(const std::string& id, const widget* widget);
349 
350 	/***** ***** ***** setters / getters for members ***** ****** *****/
351 
video()352 	CVideo& video()
353 	{
354 		return video_;
355 	}
356 
357 	/**
358 	 * Sets there return value of the window.
359 	 *
360 	 * @param retval              The return value for the window.
361 	 * @param close_window        Close the window after setting the value.
362 	 */
set_retval(const int retval,const bool close_window=true)363 	void set_retval(const int retval, const bool close_window = true)
364 	{
365 		retval_ = retval;
366 		if(close_window)
367 			close();
368 	}
369 
get_retval()370 	int get_retval()
371 	{
372 		return retval_;
373 	}
374 
set_owner(dialogs::modal_dialog * owner)375 	void set_owner(dialogs::modal_dialog* owner)
376 	{
377 		owner_ = owner;
378 	}
379 
set_click_dismiss(const bool click_dismiss)380 	void set_click_dismiss(const bool click_dismiss)
381 	{
382 		click_dismiss_ = click_dismiss;
383 	}
384 
get_need_layout() const385 	bool get_need_layout() const
386 	{
387 		return need_layout_;
388 	}
389 
set_variable(const std::string & key,const wfl::variant & value)390 	void set_variable(const std::string& key, const wfl::variant& value)
391 	{
392 		variables_.add(key, value);
393 		set_is_dirty(true);
394 	}
get_linked_size(const std::string & linked_group_id) const395 	point get_linked_size(const std::string& linked_group_id) const
396 	{
397 		std::map<std::string, linked_size>::const_iterator it = linked_size_.find(linked_group_id);
398 		if(it != linked_size_.end()) {
399 			return point(it->second.width, it->second.height);
400 		}
401 
402 		return point(-1, -1);
403 	}
404 
405 	/**
406 	 * Sets the window's exit hook.
407 	 *
408 	 * A window will only close if this function returns true.
409 	 *
410 	 * @param func A function taking a window reference and returning a boolean result.
411 	 */
set_exit_hook(std::function<bool (window &)> func)412 	void set_exit_hook(std::function<bool(window&)> func)
413 	{
414 		exit_hook_ = func;
415 	}
416 
set_exit_hook_ok_only(std::function<bool (window &)> func)417 	void set_exit_hook_ok_only(std::function<bool(window&)> func)
418 	{
419 		exit_hook_ = [func](window& w)->bool { return w.get_retval() != OK || func(w); };
420 	}
421 
422 	/**
423 	 * Sets a callback that will be called after the window is drawn next time.
424 	 * The callback is automatically removed after calling it once.
425 	 * Useful if you need to do something after the window is drawn for the first time
426 	 * and it's timing-sensitive (i.e. pre_show is too early).
427 	 */
set_callback_next_draw(std::function<void ()> func)428 	void set_callback_next_draw(std::function<void()> func)
429 	{
430 		callback_next_draw_ = func;
431 	}
432 
433 	enum show_mode {
434 		none,
435 		modal,
436 		modeless,
437 		tooltip
438 	};
439 
440 private:
441 	/** Needed so we can change what's drawn on the screen. */
442 	CVideo& video_;
443 
444 	/** The status of the window. */
445 	status status_;
446 
447 	/**
448 	 * The mode in which the window is shown.
449 	 *
450 	 * This is used to determine whether or not to remove the tip.
451 	 */
452 	show_mode show_mode_;
453 
454 	// return value of the window, 0 default.
455 	int retval_;
456 
457 	/** The dialog that owns the window. */
458 	dialogs::modal_dialog* owner_;
459 
460 	/**
461 	 * When set the form needs a full layout redraw cycle.
462 	 *
463 	 * This happens when either a widget changes it's size or visibility or
464 	 * the window is resized.
465 	 */
466 	bool need_layout_;
467 
468 	/** The variables of the canvas. */
469 	wfl::map_formula_callable variables_;
470 
471 	/** Is invalidate_layout blocked, see invalidate_layout_blocker. */
472 	bool invalidate_layout_blocked_;
473 
474 	/** Avoid drawing the window.  */
475 	bool suspend_drawing_;
476 
477 	/** Whether the window should undraw the window using restorer_ */
478 	bool restore_;
479 
480 	/** Whether the window has other windows behind it */
481 	bool is_toplevel_;
482 
483 	/** When the window closes this surface is used to undraw the window. */
484 	surface restorer_;
485 
486 	/** Do we wish to place the widget automatically? */
487 	const bool automatic_placement_;
488 
489 	/**
490 	 * Sets the horizontal placement.
491 	 *
492 	 * Only used if automatic_placement_ is true.
493 	 * The value should be a grid placement flag.
494 	 */
495 	const unsigned horizontal_placement_;
496 
497 	/**
498 	 * Sets the vertical placement.
499 	 *
500 	 * Only used if automatic_placement_ is true.
501 	 * The value should be a grid placement flag.
502 	 */
503 	const unsigned vertical_placement_;
504 
505 	/** The maximum width if automatic_placement_ is true. */
506 	unsigned maximum_width_;
507 
508 	/** The maximum height if automatic_placement_ is true. */
509 	unsigned maximum_height_;
510 
511 	/** The formula to calculate the x value of the dialog. */
512 	typed_formula<unsigned> x_;
513 
514 	/** The formula to calculate the y value of the dialog. */
515 	typed_formula<unsigned> y_;
516 
517 	/** The formula to calculate the width of the dialog. */
518 	typed_formula<unsigned> w_;
519 
520 	/** The formula to calculate the height of the dialog. */
521 	typed_formula<unsigned> h_;
522 
523 	/** The formula to determine whether the size is good. */
524 	typed_formula<bool> reevaluate_best_size_;
525 
526 	/** The formula definitions available for the calculation formulas. */
527 	wfl::function_symbol_table functions_;
528 
529 	/** The settings for the tooltip. */
530 	builder_window::window_resolution::tooltip_info tooltip_;
531 
532 	/** The settings for the helptip. */
533 	builder_window::window_resolution::tooltip_info helptip_;
534 
535 	/**
536 	 * Do we want to have easy close behavior?
537 	 *
538 	 * Easy closing means that whenever a mouse click is done the dialog will
539 	 * be closed. The widgets in the window may override this behavior by
540 	 * registering themselves as blockers. This is tested by the function
541 	 * disable_click_dismiss().
542 	 *
543 	 * The handling of easy close is done in the window, in order to do so a
544 	 * window either needs a click_dismiss or an ok button. Both will be hidden
545 	 * when not needed and when needed first the ok is tried and then the
546 	 * click_dismiss button. this allows adding a click_dismiss button to the
547 	 * window definition and use the ok from the window instance.
548 	 *
549 	 * @todo After testing the click dismiss feature it should be documented in
550 	 * the wiki.
551 	 */
552 	bool click_dismiss_;
553 
554 	/** Disable the enter key see our setter for more info. */
555 	bool enter_disabled_;
556 
557 	/** Disable the escape key see our setter for more info. */
558 	bool escape_disabled_;
559 
560 	/**
561 	 * Helper struct to force widgets the have the same size.
562 	 *
563 	 * Widget which are linked will get the same width and/or height. This
564 	 * can especially be useful for listboxes, but can also be used for other
565 	 * applications.
566 	 */
567 	struct linked_size
568 	{
linked_sizegui2::window::linked_size569 		linked_size(const bool width = false, const bool height = false)
570 			: widgets(), width(width ? 0 : -1), height(height ? 0 : -1)
571 		{
572 		}
573 
574 		/** The widgets linked. */
575 		std::vector<widget*> widgets;
576 
577 		/** The current width of all widgets in the group, -1 if the width is not linked. */
578 		int width;
579 
580 		/** The current height of all widgets in the group, -1 if the height is not linked. */
581 		int height;
582 	};
583 
584 	/** List of the widgets, whose size are linked together. */
585 	std::map<std::string, linked_size> linked_size_;
586 
587 	/** List of widgets in the tabbing order. */
588 	std::vector<widget*> tab_order;
589 
590 	/**
591 	 * Layouts the window.
592 	 *
593 	 * This part does the pre and post processing for the actual layout
594 	 * algorithm.
595 	 *
596 	 * See @ref layout_algorithm for more information.
597 	 */
598 	void layout();
599 
600 	/**
601 	 * Layouts the linked widgets.
602 	 *
603 	 * See @ref layout_algorithm for more information.
604 	 */
605 	void layout_linked_widgets();
606 
607 	/**
608 	 * Handles a mouse click event for dismissing the dialog.
609 	 *
610 	 * @param mouse_button_mask   The SDL_BUTTON mask for the button used to
611 	 *                            dismiss the click. If the caller is from the
612 	 *                            keyboard code the value should be 0.
613 	 *
614 	 * @return                    Whether the event should be considered as
615 	 *                            handled.
616 	 */
617 	bool click_dismiss(const int mouse_button_mask);
618 
619 	/**
620 	 * The state of the mouse button.
621 	 *
622 	 * When click dismissing a dialog in the past the DOWN event was used.
623 	 * This lead to a bug [1]. The obvious change was to switch to the UP
624 	 * event, this lead to another bug; the dialog was directly dismissed.
625 	 * Since the game map code uses the UP and DOWN event to select a unit
626 	 * there is no simple solution.
627 	 *
628 	 * Upon entry this value stores the mouse button state at entry. When a
629 	 * button is DOWN and goes UP that button does \em not trigger a dismissal
630 	 * of the dialog, instead that button's down state is removed from this
631 	 * variable. Therefore the next UP event does dismiss the dialog.
632 	 *
633 	 * [1] https://gna.org/bugs/index.php?18970
634 	 */
635 	int mouse_button_state_;
636 
637 public:
638 	/** Static type getter that does not rely on the widget being constructed. */
639 	static const std::string& type();
640 
641 private:
642 	/** Inherited from styled_widget, implemented by REGISTER_WIDGET. */
643 	virtual const std::string& get_control_type() const override;
644 
645 	/**
646 	 * The list with dirty items in the window.
647 	 *
648 	 * When drawing only the widgets that are dirty are updated. The draw()
649 	 * function has more information about the dirty_list_.
650 	 */
651 	std::vector<std::vector<widget*>> dirty_list_;
652 
653 	/**
654 	 * In how many consecutive frames the window has changed. This is used to
655 	 * detect the situation where the title screen changes in every frame,
656 	 * forcing all other windows to redraw everything all the time.
657 	 */
658 	unsigned int consecutive_changed_frames_ = 0u;
659 
660 	/** Schedules windows on top of us (if any) to redraw. */
661 	void redraw_windows_on_top() const;
662 
663 	/**
664 	 * Finishes the initialization of the grid.
665 	 *
666 	 * @param content_grid        The new contents for the content grid.
667 	 */
668 	void finalize(const std::shared_ptr<builder_grid>& content_grid);
669 
670 #ifdef DEBUG_WINDOW_LAYOUT_GRAPHS
671 	debug_layout_graph* debug_layout_;
672 
673 public:
674 	/** wrapper for debug_layout_graph::generate_dot_file. */
675 	void generate_dot_file(const std::string& generator, const unsigned domain);
676 
677 private:
678 #else
679 	void generate_dot_file(const std::string&, const unsigned)
680 	{
681 	}
682 #endif
683 
684 	std::unique_ptr<event::distributor> event_distributor_;
685 
686 public:
687 	/** Gets a reference to the window's distributor to allow some state peeking. */
get_distributor() const688 	const event::distributor& get_distributor() const
689 	{
690 		return *event_distributor_;
691 	}
692 
693 	/** Returns the dialog mode for this window. */
mode() const694 	show_mode mode() const
695 	{
696 		return show_mode_;
697 	}
698 
699 	// mouse and keyboard_capture should be renamed and stored in the
700 	// dispatcher. Chaining probably should remain exclusive to windows.
701 	void mouse_capture(const bool capture = true);
702 	void keyboard_capture(widget* widget);
703 
704 	/**
705 	 * Adds the widget to the keyboard chain.
706 	 *
707 	 * @todo rename to keyboard_add_to_chain.
708 	 * @param widget              The widget to add to the chain. The widget
709 	 *                            should be valid widget, which hasn't been
710 	 *                            added to the chain yet.
711 	 */
712 	void add_to_keyboard_chain(widget* widget);
713 
714 	/**
715 	 * Remove the widget from the keyboard chain.
716 	 *
717 	 * @todo rename to keyboard_remove_from_chain.
718 	 *
719 	 * @param widget              The widget to be removed from the chain.
720 	 */
721 	void remove_from_keyboard_chain(widget* widget);
722 
723 	/**
724 	 * Add the widget to the tabbing order
725 	 * @param widget              The widget to be added to the tabbing order
726 	 * @param at                  A hint for where to place the widget in the tabbing order
727 	 */
728 	void add_to_tab_order(widget* widget, int at = -1);
729 
730 private:
731 	/***** ***** ***** signal handlers ***** ****** *****/
732 
733 	void signal_handler_sdl_video_resize(const event::ui_event event,
734 										 bool& handled,
735 										 const point& new_size);
736 
737 	/**
738 	 * The handler for the click dismiss mouse 'event'.
739 	 *
740 	 * @param event               See @ref event::dispatcher::fire.
741 	 * @param handled             See @ref event::dispatcher::fire.
742 	 * @param halt                See @ref event::dispatcher::fire.
743 	 * @param mouse_button_mask   Forwared to @ref click_dismiss.
744 	 */
745 	void signal_handler_click_dismiss(const event::ui_event event,
746 									  bool& handled,
747 									  bool& halt,
748 									  const int mouse_button_mask);
749 
750 	void signal_handler_sdl_key_down(const event::ui_event event,
751 									 bool& handled,
752 									 const SDL_Keycode key,
753 									 const SDL_Keymod mod,
754 									 bool handle_tab);
755 
756 	void signal_handler_message_show_tooltip(const event::ui_event event,
757 											 bool& handled,
758 											 event::message& message);
759 
760 	void signal_handler_message_show_helptip(const event::ui_event event,
761 											 bool& handled,
762 											 event::message& message);
763 
764 	void signal_handler_request_placement(const event::ui_event event,
765 										  bool& handled);
766 
767 	void signal_handler_close_window();
768 
769 	std::function<bool(window&)> exit_hook_;
770 	std::function<void()> callback_next_draw_;
771 };
772 
773 // }---------- DEFINITION ---------{
774 
775 struct window_definition : public styled_widget_definition
776 {
777 	explicit window_definition(const config& cfg);
778 
779 	struct resolution : public panel_definition::resolution
780 	{
781 		explicit resolution(const config& cfg);
782 
783 		builder_grid_ptr grid;
784 	};
785 };
786 
787 // }------------ END --------------
788 
789 } // namespace gui2
790