The Battle for Wesnoth  1.13.10+dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
dispatcher.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2009 - 2017 by Mark de Wever <koraq@xs4all.nl>
3  Part of the Battle for Wesnoth Project http://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 
20 #include "gui/core/log.hpp"
21 
22 namespace gui2
23 {
24 namespace event
25 {
26 /***** dispatcher class. *****/
27 
29  : mouse_behavior_(all)
30  , want_keyboard_input_(true)
31  , signal_queue_()
32  , signal_mouse_queue_()
33  , signal_keyboard_queue_()
34  , signal_notification_queue_()
35  , signal_message_queue_()
36  , connected_(false)
37  , hotkeys_()
38 {
39 }
40 
42 {
43  if(connected_) {
45  }
46 }
47 
49 {
50  assert(!connected_);
51  connected_ = true;
52  connect_dispatcher(this);
53 }
54 
55 bool dispatcher::has_event(const ui_event event, const event_queue_type event_type)
56 {
57 #if 0
58  // Debug code to test whether the event is in the right queue.
59  std::cerr << "Event '" << event
60  << "' event "
61  << find<set_event>(event, dispatcher_implementation
62  ::has_handler(event_type, *this))
63  << " mouse "
64  << find<set_event_mouse>(event, dispatcher_implementation
65  ::has_handler(event_type, *this))
66  << " keyboard "
67  << find<set_event_keyboard>(event, dispatcher_implementation
68  ::has_handler(event_type, *this))
69  << " notification "
70  << find<set_event_notification>(event, dispatcher_implementation
71  ::has_handler(event_type, *this))
72  << " message "
73  << find<set_event_message>(event, dispatcher_implementation
74  ::has_handler(event_type, *this))
75  << ".\n";
76 #endif
77 
78  return find<set_event>(
79  event, dispatcher_implementation::has_handler(event_type, *this))
80  || find<set_event_mouse>(
81  event, dispatcher_implementation::has_handler(event_type, *this))
82  || find<set_event_keyboard>(
83  event, dispatcher_implementation::has_handler(event_type, *this))
84  || find<set_event_text_input>(
85  event, dispatcher_implementation::has_handler(event_type, *this))
86  || find<set_event_touch>(
87  event, dispatcher_implementation::has_handler(event_type, *this))
88  || find<set_event_notification>(
89  event, dispatcher_implementation::has_handler(event_type, *this))
90  || find<set_event_message>(
91  event, dispatcher_implementation::has_handler(event_type, *this))
92  || find<set_event_raw_event>(
93  event, dispatcher_implementation::has_handler(event_type, *this));
94 }
95 
96 /**
97  * Helper class to do a runtime test whether an event is in a set.
98  *
99  * The class is supposed to be used in combination with find function. This
100  * function is used in the fire functions to make sure an event is send to the
101  * proper handler. If not there will be a run-time assertion failure. This
102  * makes developing and testing the code easier, a wrong handler terminates
103  * Wesnoth instead of silently not working.
104  */
106 {
107 public:
108  /**
109  * If found we get executed to set the result.
110  *
111  * Since we need to return true if found we always return true.
112  */
113  template <class T>
115  {
116  return true;
117  }
118 };
119 
120 bool dispatcher::fire(const ui_event event, widget& target)
121 {
122  assert(find<set_event>(event, event_in_set()));
123  switch(event) {
127 
130  &event_executor::wants_mouse_middle_double_click, signal_function>(this, &target);
131 
134  &event_executor::wants_mouse_right_double_click, signal_function>(this, &target);
135 
136  default:
137  return fire_event<signal_function>(event, this, &target);
138  }
139 }
140 
141 bool dispatcher::fire(const ui_event event, widget& target, const point& coordinate)
142 {
143  assert(find<set_event_mouse>(event, event_in_set()));
144  return fire_event<signal_mouse_function>(event, this, &target, coordinate);
145 }
146 
147 bool dispatcher::fire(const ui_event event,
148  widget& target,
149  const SDL_Keycode key,
150  const SDL_Keymod modifier,
151  const utf8::string& unicode)
152 {
153  assert(find<set_event_keyboard>(event, event_in_set()));
154  return fire_event<signal_keyboard_function>(event, this, &target, key, modifier, unicode);
155 }
156 
157 bool dispatcher::fire(const ui_event event, widget& target, const SDL_Event& sdlevent)
158 {
159  assert(find<set_event_raw_event>(event, event_in_set()));
160  return fire_event<signal_raw_event_function>(event, this, &target, sdlevent);
161 }
162 
163 bool dispatcher::fire(const ui_event event, widget& target, const std::string& text, int32_t start, int32_t len)
164 {
165  assert(find<set_event_text_input>(event, event_in_set()));
166  return fire_event<signal_text_input_function>(event, this, &target, text, start, len);
167 }
168 
169 bool dispatcher::fire(const ui_event event, widget& target, const point& pos, const point& distance)
170 {
171  assert(find<set_event_touch>(event, event_in_set()));
172  return fire_event<signal_touch_function>(event, this, &target, pos, distance);
173 }
174 
175 bool dispatcher::fire(const ui_event event, widget& target, void*)
176 {
177  assert(find<set_event_notification>(event, event_in_set()));
178  return fire_event<signal_notification_function>(event, this, &target, nullptr);
179 }
180 
181 // TODO: is there any reason msg isn't a const reference?
182 bool dispatcher::fire(const ui_event event, widget& target, message& msg)
183 {
184  assert(find<set_event_message>(event, event_in_set()));
185  return fire_event<signal_message_function>(event, this, &target, msg);
186 }
187 
189 {
190  hotkeys_[id] = function;
191 }
192 
194 {
196 
197  if(itor == hotkeys_.end()) {
198  return false;
199  }
200 
201  return itor->second(dynamic_cast<widget&>(*this), id);
202 }
203 
205 {
207 }
208 
210 {
211  dispatcher.connect_signal<LEFT_BUTTON_CLICK>(signal);
212 }
213 
215 {
216  dispatcher.disconnect_signal<LEFT_BUTTON_CLICK>(signal);
217 }
218 
220 {
222 }
223 
225 {
226  dispatcher.connect_signal<NOTIFY_MODIFIED>(signal);
227 }
228 
229 } // namespace event
230 
231 } // namespace gui2
232 
233 /**
234  * @page event_dispatching Event dispatching.
235  *
236  * @section introduction Introduction
237  *
238  * This page describes how the new event handling system works, since the
239  * system is still work in progress it might be out of date with the actual
240  * code. It also contains some ideas that might change later on. Some parts are
241  * explained in the interface and will be integrated in this document later.
242  *
243  * Since the event handling code hasn't been cast in stone yet some scenarios
244  * for solving the problem are discussed first and then the solution that is
245  * chosen in more detail.
246  *
247  * After SDL has generated and event it needs to be turned into an event which
248  * the widgets can use.
249  *
250  * @section handling_solution The implementation solutions.
251  *
252  * For the event handling we use a few use case scenarios and show the possible
253  * solutions.
254  *
255  * @subsection sample The sample window
256  *
257  * In our samples we use this sample window with the following components:
258  * - a window W
259  * - a container C
260  * - a button B
261  *
262  * These are arranged accordingly:
263  * @code
264  *
265  * ---------------------
266  * |W |
267  * | |
268  * | ----------------- |
269  * | |C |^| |
270  * | | |-| |
271  * | | ---------- |#| |
272  * | | |B | | | |
273  * | | ---------- | | |
274  * | | |-| |
275  * | | |v| |
276  * | ----------------- |
277  * | |
278  * ---------------------
279  *
280  * @endcode
281  *
282  * @subsection scenarios Possible scenarios
283  *
284  * The scenarios are:
285  * - An event that is wanted by none.
286  * - A mouse down event that should focus C and set the pressed state in B.
287  * - A mouse wheel event, which first should be offered to B and if not handled
288  * by B should be handled by C.
289  *
290  * @subsection all_queues Pass the event through all queues
291  *
292  * In this solution the event will be passed through all possible queues and
293  * tries sees where the event sticks. This following sections describe how the
294  * events are tried for this usage scenario.
295  *
296  * @subsubsection unhandled Unhandled event
297  *
298  * - W pre child
299  * - C pre child
300  * - B pre child
301  * - W child
302  * - C child
303  * - B child
304  * - W post child
305  * - C post child
306  * - B post child
307  *
308  * @subsubsection mouse_down Mouse down
309  *
310  * - W pre child
311  * - C pre child -> set focus -> !handled
312  * - B pre child -> set pressed state -> handled
313  *
314  * @subsubsection mouse_wheel Mouse wheel
315  *
316  * - W pre child
317  * - C pre child
318  * - B pre child -> We can't scroll so ignore
319  * - W child
320  * - C child
321  * - B child
322  * - W post child
323  * - C post child -> Scroll -> handled
324  *
325  * @subsection chain Pass the events in a chain like fashion
326  *
327  * In this solution the events are send to the pre- and post queue of all but
328  * the last possible widget and to the child of the last widget. The pre queue
329  * will be send from top to bottom, the post queue from bottom to top.
330  *
331  * @subsubsection unhandled Unhandled event
332  *
333  * - W pre child
334  * - C pre child
335  * - B child
336  * - C post child
337  * - W post child
338  *
339  * @subsubsection mouse_down Mouse down
340  *
341  * - W pre child
342  * - C pre child -> set focus -> !handled
343  * - B child -> set pressed state -> handled
344  *
345  * @subsubsection mouse_wheel Mouse wheel
346  *
347  * - W pre child
348  * - C pre child
349  * - B child -> We can't scroll so ignore
350  * - C post child -> Scroll -> handled
351  *
352  * @subsection evaluation Evaluation
353  *
354  * When using the first solution it's possible to drop the child queue since
355  * everything falls in pre or post. But there is a scenario that's a bit ugly
356  * to solve with the first solution:
357  *
358  * Assume there is a listbox with toggle panels and on the panel there are a
359  * few buttons, the wanted behavior is:
360  * - if clicked on the panel it should toggle, which may or may not be allowed.
361  * - if clicked on a button in the panel, we want to make sure the panel is
362  * selected, which again may or may not be allowed.
363  *
364  * With solution 2 it's rather easy:
365  *
366  * Click on panel:
367  * - W pre child
368  * - C child -> Test whether we can toggle -> handled, halt = !toggled
369  *
370  * Click on button in panel:
371  * - W pre child
372  * - C pre child -> Test whether we can select -> handled = halt = !selected
373  * - B child -> do button stuff -> handled
374  *
375  * Since for the different clicks, different queues are triggered it's easy to
376  * add a different handler there.
377  *
378  * With solution 1:
379  *
380  * Click on panel:
381  * - W pre child
382  * - C pre child -> handler 1 -> if last in queue -> solution 2 C child
383  *
384  * Click on button in panel:
385  * - W pre child
386  * - C pre child -> handler 2 -> if !last in queue -> solution 2 C pre child
387  * - B pre child -> do button stuff -> handled
388  *
389  * Not that different from solution 2, the two handlers are installed in the C
390  * pre event. But we need to manually check whether we're really the last,
391  * which means the code to check whether there are more handlers at a lower
392  * level is needed for both solutions. In solution 1 this test needs to be done
393  * twice versus once in solution 2. Also the fact that the queues for the
394  * events are processed in reverse order on the way back sounds more
395  * initiative.
396  *
397  * @section processing_raw_events Processing the raw events.
398  *
399  * This section describes how the events generated by SDL are send as our own
400  * events to the various widgets. The first step in sending an event is to
401  * decode it and send it to a registered dispatcher.
402  *
403  * - gui2::event::sdl_event_handler handles the SDL events.
404  * - gui2::event::dispatcher has the registered dispatchers.
405  *
406  * In general a dispatcher is a window which then needs to send this event to
407  * the widgets. The dispatcher is just a simple part which fires events and
408  * finds a handler for the event. This is not to the liking of most widgets,
409  * they don't want to handle raw events but get a polished and clean event. No
410  * button up and down and then try to figure out whether it needs to act as if
411  * it was clicked upon, no simply op and down to change the appearance and a
412  * click event to do the clicking actions. And don't even try to convince a
413  * widget to determine whether this up event was a single or double click.
414  * Widgets like to sleep with nice dreams and not having nightmares where SDL
415  * events haunt them.
416  *
417  * In order to remedy that problem there's the gui2::event::distributor
418  * class, it's the class to do the dirty job of converting the raw event into
419  * these nice polished events. The distributor is in general linked to a window,
420  * but a widget can install it's own distributor if it needs to know more of the
421  * raw events as still left in the polished events. At the time of this writing
422  * no widget needs this feature, but the toggle panel might need it.
423  *
424  * After the distributor has polished the event and send it on its way to the
425  * widget the dispatcher needs to make sure the event is properly dispatched to
426  * the widget in question and also notify its parents by means of the previously
427  * described event chain.
428  *
429  * @subsection sdl_event Get the SDL events
430  *
431  * The first step in event handling is getting the events in the first place.
432  * Events are generated by SDL and placed in a queue. The Wesnoth code processes
433  * this queue and thus handles the events. The part which does the first
434  * handling isn't described here since it's (secretly) intended to be replaced
435  * by the @ref gui2::event::sdl_event_handler class. Instead we directly jump to this
436  * class and explain what it does.
437  *
438  * The main handling function is @ref gui2::event::sdl_event_handler::handle_event which
439  * as no real surprise handles the events. The function is a simple multiplexer
440  * which lets other subfunctions to the handling of specific events.
441  *
442  * @todo Describe drawing and resizing once the code is stable and working as
443  * wanted in these areas.
444  *
445  * @subsubsection handler_mouse Mouse motion events
446  *
447  * If a dispatcher has captured the mouse it gets the event, no questions asked.
448  * If not it goes through all dispatchers and finds the first one willing to
449  * accept the mouse event.
450  *
451  * This means a mouse event is send to one dispatcher.
452  *
453  * @subsubsection handler_mouse_button_down Mouse button down events
454  *
455  * Turning the mouse wheel on a mouse generates both an down and up event. It
456  * has been decided to handle the wheel event in the button up code so wheel
457  * events are here directly dropped on the floor and forgotten.
458  *
459  * The other buttons are handled as if they're normal mouse events but are
460  * decoded per button so instead of a button_down(id) you get button_down_id.
461  *
462  * @subsubsection handler_mouse_button_up Mouse button up events
463  *
464  * The mouse wheel event is handled as if it's a keyboard event and like the
465  * button_down they are send as wheel_id events.
466  *
467  * The other mouse buttons are handled the same as the down buttons.
468  *
469  * @subsubsection handler_keyboard Keyboard events
470  *
471  * There are three types of keyboard events, the already mentioned mouse wheel
472  * events, the key down and key up event. When a key is pressed for a longer
473  * time several key down events are generated and only one key up, this means
474  * the key up is rather useless. Guess what, the multiplexer already drops that
475  * event so we never get it.
476  *
477  * If the keyboard event is a mouse wheel event it's directly send to the
478  * dispachting queue; either the dispatcher that captured the keyboard or the
479  * last dispatcher in the queue.
480  *
481  * If the event is a real keyboard action it's first tried as hotkey. In order
482  * to do so the target dispatcher is first determined, either the dispatcher
483  * that captured the keyboard or the last dispatcher in the queue. Then it's
484  * tried whether a hotkey and whether the hotkey can be processed. If the
485  * hotkey isn't processed the keyboard event is send to the dispatcher as
486  * normal keyboard event.
487  *
488  * The hotkey processing will have several queues (to be implemented in 1.9):
489  * - global hotkeys that always work eg toggling fullscreen mode.
490  * - main screen hotkeys, these work when one of the dialogs is shown without
491  * other dialogs on top of them. These hotkeys are for example
492  * preferences. The main screens are:
493  * - title screen
494  * - game
495  * - editor
496  * - mp lobby
497  * - map screen hotkeys, these work when a map is shown eg toggle grid. The
498  * screens are:
499  * - game
500  * - editor
501  * - local hotkeys, these are hotkeys that only work in a specific dialog eg
502  * recruit unit only works in the game screen.
503  *
504  * The queues are processed in from bottom to top in the list above, this
505  * allows an item to use a hotkey but have another handler function. Eg
506  * preferences in the editor might open another preferences dialog.
507  *
508  * @todo The hotkeys need to be implemented like above in 1.9.
509  *
510  * @todo This might change in the near future.
511  *
512  * @subsection distributor Event polishing and distribution
513  *
514  * The event distributor has the job to find the widget that should receive the
515  * event and which event(s) to send from a single event. In general an event is
516  * first send to the widget as-is, sending the raw events allows other
517  * distributors to be nested between this distributor and the intended target
518  * widget. Or the intended widget might not really be the intended widget but
519  * another distributor that wants to dispatch the event internally.
520  *
521  * However in the common cases this raw event isn't handled and the distributor
522  * needs to send the polished events. In the following sections the details of
523  * the conversion from raw to polished is described, it intentionally lacks the
524  * part of sending the raw events as well since it adds no value.
525  *
526  * A widget can capture the mouse, which means all mouse events are send to this
527  * widget, regardless where the mouse is. This is normally done in a mouse down
528  * event (for a button) so all events following it are send to that widget.
529  *
530  * @subsection mouse_motion Mouse motion
531  *
532  * This section describes the conversion from a raw mouse motion to the polished
533  * events it can generate:
534  * - @ref gui2::event::MOUSE_ENTER "MOUSE_ENTER"
535  * - @ref gui2::event::MOUSE_LEAVE "MOUSE_LEAVE"
536  * - @ref gui2::event::MOUSE_MOTION "MOUSE_MOTION"
537  *
538  * When the mouse is captured that widget will only receive motion events.
539  *
540  * If not captured the code checks whether the widget underneath the mouse is
541  * the same widget as at the last motion if event. If so that widget gets a
542  * motion event.
543  * If not the widget that before was underneath the mouse pointer (if any) gets
544  * a leave event and the widget newly underneath the mouse pointer (if any) gets
545  * an enter event.
546  *
547  * @subsection mouse_button Mouse buttons
548  *
549  * The mouse button code is a bit more complex and is separated in the various
550  * events to be send.
551  *
552  * @subsubsection mouse_button_down Mouse button down
553  *
554  * Some things start simple, so does the event of pressing down a mouse button.
555  * All it does is send the event to the widget as one of the following events:
556  * - @ref gui2::event::LEFT_BUTTON_DOWN "LEFT_BUTTON_DOWN"
557  * - @ref gui2::event::MIDDLE_BUTTON_DOWN "MIDDLE_BUTTON_DOWN"
558  * - @ref gui2::event::RIGHT_BUTTON_DOWN "RIGHT_BUTTON_DOWN"
559  *
560  * @todo Validate the code it seems a down event with a captured mouse doesn't
561  * really work as wanted. (Rare case but should work properly.) In general the
562  * mouse event handling needs testing to see whether the proper events are send
563  * all the time.
564  *
565  * @subsubsection mouse_button_up Mouse button up
566  *
567  * Simplicity ends here.
568  *
569  * @todo Document further.
570  *
571  * @subsubsection mouse_click Mouse click
572  *
573  * So the button up event has asked for mouse click, now we need to test whether
574  * the click will be a click or a double click. A double click is generated when
575  * the same widget is clicked twice in a short time and causes the following
576  * events:
577  * - @ref gui2::event::LEFT_BUTTON_DOUBLE_CLICK "LEFT_BUTTON_DOUBLE_CLICK"
578  * - @ref gui2::event::MIDDLE_BUTTON_DOUBLE_CLICK "MIDDLE_BUTTON_DOUBLE_CLICK"
579  * - @ref gui2::event::RIGHT_BUTTON_DOUBLE_CLICK "RIGHT_BUTTON_DOUBLE_CLICK"
580  *
581  * Otherwise one of the following single clicks is generated:
582  * - @ref gui2::event::LEFT_BUTTON_CLICK "LEFT_BUTTON_CLICK"
583  * - @ref gui2::event::MIDDLE_BUTTON_CLICK "MIDDLE_BUTTON_CLICK"
584  * - @ref gui2::event::RIGHT_BUTTON_CLICK "RIGHT_BUTTON_CLICK"
585  *
586  * @subsubsection double_click To double click or not to double click
587  *
588  * Wait a second, a widget has a field whether or not it wants a double click
589  * for a certain mouse button and now I see that it's bluntly ignored by the
590  * distributor. Indeed the distributor doesn't care about what the widget wants,
591  * it does what it wants and leaves the sorting out what's wanted to the
592  * dispatcher.
593  *
594  * The problem is that in the chain events are send to one widget that may not
595  * be interested in a double click, but another widget in the chain is. There
596  * are several solutions to this problem:
597  * -# Sending a click followed by a double click.
598  * -# Sending a click with a tag field that it actually is a double click.
599  * -# Send a double click and turn it into a click if the double click is
600  * unwanted.
601  *
602  * The first solution has the disadvantage that a toggle panel likes a click and
603  * double click, the first click selects the second deselects and now the
604  * deselected panel gets a double click. When the panel now checks whether it's
605  * selected it's not and might take the wrong action upon it.
606  *
607  * The second option is possible but would be rather intrusive in the code,
608  * since it would generate another event signature. Adding a signature just for
609  * this special case seemed a bit too much effort vs. gain. Also the widget
610  * needs to check whether a click is a click or a double click and choose a
611  * different code path for it. This in turn would mean a signal handler
612  * secretly might handle two events and lowers the transparency of the code.
613  *
614  * The third option also adds some special case handling but the scope is
615  * limited and only one part knows about the tricks done.
616  *
617  * The last option has been chosen and the dispatcher build the event chain and
618  * while building the chain it looks whether the widget wants the double click
619  * or not. It does this test by looking at the wants double click function and
620  * not test for a handler. The double click test function is made for this
621  * purpose and depending on the handler might again do the wrong thing.
622  * (A certain toggle panel might not want to do something on a double click but
623  * also not being deselected upon a double click. The latter to keep the UI
624  * consistent, a double click on a toggle panel might execute a special function
625  * or not, but always keep the panel selected. (That is if the panel can be
626  * selected.))
627  */
Define the common log macros for the gui toolkit.
bool oper(ui_event)
If found we get executed to set the result.
Definition: dispatcher.cpp:114
std::vector< char_t > string
Base class for event handling.
Definition: dispatcher.hpp:161
void register_hotkey(const hotkey::HOTKEY_COMMAND id, const hotkey_function &function)
Registers a hotkey.
Definition: dispatcher.cpp:188
See LEFT_BUTTON_CLICK.
Definition: handler.hpp:84
std::function< bool(widget &dispatcher, hotkey::HOTKEY_COMMAND id)> hotkey_function
Hotkey function handler signature.
Definition: dispatcher.hpp:144
An SDL key down event.
Definition: handler.hpp:91
Base class for all widgets.
Definition: widget.hpp:48
Holds a 2D point.
Definition: point.hpp:23
See LEFT_BUTTON_DOUBLE_CLICK.
Definition: handler.hpp:85
See LEFT_BUTTON_CLICK.
Definition: handler.hpp:77
static void msg(const char *act, debug_info &i, const char *to="", const char *result="")
Definition: debugger.cpp:110
Helper class to do a runtime test whether an event is in a set.
Definition: dispatcher.cpp:105
bool has_event(const ui_event event, const event_queue_type event_type)
Definition: dispatcher.cpp:55
Generic file dialog.
Definition: text.hpp:37
Sent by a widget to notify others its contents or state are modified.
Definition: handler.hpp:96
The message callbacks hold a reference to a message.
Definition: message.hpp:46
bool wants_mouse_middle_double_click() const
std::function< void(widget &dispatcher, const ui_event event, bool &handled, bool &halt, const SDL_Keycode key, const SDL_Keymod modifier, const utf8::string &unicode)> signal_keyboard_function
Callback function signature.
Definition: dispatcher.hpp:80
void connect()
Connects the dispatcher to the event handler.
Definition: dispatcher.cpp:48
void connect_signal_notify_modified(dispatcher &dispatcher, const signal_notification_function &signal)
Connects a signal handler for getting a notification upon modification.
Definition: dispatcher.cpp:224
bool wants_mouse_left_double_click() const
void connect_signal_mouse_left_click(dispatcher &dispatcher, const signal_function &signal)
Connects a signal handler for a left mouse button click.
Definition: dispatcher.cpp:209
bool execute_hotkey(const hotkey::HOTKEY_COMMAND id)
Executes a hotkey.
Definition: dispatcher.cpp:193
void disconnect_dispatcher(dispatcher *dispatcher)
Disconnects a dispatcher to the event handler.
Definition: handler.cpp:830
This file contains the defintions for the gui2::event::message class.
bool fire_event_double_click(dispatcher *dsp, widget *wgt, F &&...params)
bool wants_mouse_right_double_click() const
void connect_dispatcher(dispatcher *dispatcher)
Connects a dispatcher to the event handler.
Definition: handler.cpp:823
void connect_signal_mouse_left_double_click(dispatcher &dispatcher, const signal_function &signal)
Connects a signal handler for a left mouse button double click.
Definition: dispatcher.cpp:219
std::map< hotkey::HOTKEY_COMMAND, hotkey_function > hotkeys_
The registered hotkeys for this dispatcher.
Definition: dispatcher.hpp:848
bool connected_
Are we connected to the event handler.
Definition: dispatcher.hpp:845
A left mouse button double click event for a widget.
Definition: handler.hpp:71
hotkey_list hotkeys_
Definition: hotkey_item.cpp:40
std::function< void(widget &dispatcher, const ui_event event, bool &handled, bool &halt)> signal_function
Callback function signature.
Definition: dispatcher.hpp:44
A helper class to find out whether dispatcher has an handler for a certain event. ...
utils::enable_if_t< has_key< set_event, E >::value > disconnect_signal(const signal_function &signal, const queue_position position=back_child)
Disconnect a signal for callback in set_event.
Definition: dispatcher.hpp:381
void connect_signal_pre_key_press(dispatcher &dispatcher, const signal_keyboard_function &signal)
Connects the signal for 'snooping' on the keypress.
Definition: dispatcher.cpp:204
utils::enable_if_t< has_key< set_event, E >::value > connect_signal(const signal_function &signal, const queue_position position=back_child)
Connect a signal for callback in set_event.
Definition: dispatcher.hpp:363
void disconnect_signal_mouse_left_click(dispatcher &dispatcher, const signal_function &signal)
Disconnects a signal handler for a left mouse button click.
Definition: dispatcher.cpp:214
bool fire(const ui_event event, widget &target)
Fires an event which has no extra parameters.
Definition: dispatcher.cpp:120
map_location coordinate
Contains an x and y coordinate used for starting positions in maps.
std::function< void(widget &dispatcher, const ui_event event, bool &handled, bool &halt, void *)> signal_notification_function
Callback function signature.
Definition: dispatcher.hpp:105
See LEFT_BUTTON_DOUBLE_CLICK.
Definition: handler.hpp:78
A left mouse button click event for a widget.
Definition: handler.hpp:70
std::string::const_iterator iterator
Definition: tokenizer.hpp:24
ui_event
The event send to the dispatcher.
Definition: handler.hpp:55
std::string string
EXIT_STATUS start(const config &game_conf, CVideo &video, const std::string &filename, bool take_screenshot, const std::string &screenshot_filename)
Main interface for launching the editor from the title screen.
Definition: editor_main.cpp:28