The Battle for Wesnoth  1.13.4+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 - 2016 by Mark de Wever <[email protected]>
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 
19 #include "gui/core/log.hpp"
20 
21 namespace gui2
22 {
23 
24 namespace event
25 {
26 
27 /***** tdispatcher class. *****/
28 
30  : mouse_behavior_(all)
31  , want_keyboard_input_(true)
32  , signal_queue_()
33  , signal_mouse_queue_()
34  , signal_keyboard_queue_()
35  , signal_notification_queue_()
36  , signal_message_queue_()
37  , connected_(false)
38  , hotkeys_()
39 {
40 }
41 
43 {
44  if(connected_) {
46  }
47 }
48 
50 {
51  assert(!connected_);
52  connected_ = true;
53  connect_dispatcher(this);
54 }
55 
56 bool tdispatcher::has_event(const tevent event, const tevent_type event_type)
57 {
58 #if 0
59  // Debug code to test whether the event is in the right queue.
60  std::cerr << "Event '" << event
61  << "' event "
62  << find<tset_event>(event, tdispatcher_implementation
63  ::thas_handler(event_type, *this))
64  << " mouse "
65  << find<tset_event_mouse>(event, tdispatcher_implementation
66  ::thas_handler(event_type, *this))
67  << " keyboard "
68  << find<tset_event_keyboard>(event, tdispatcher_implementation
69  ::thas_handler(event_type, *this))
70  << " notification "
71  << find<tset_event_notification>(event, tdispatcher_implementation
72  ::thas_handler(event_type, *this))
73  << " message "
74  << find<tset_event_message>(event, tdispatcher_implementation
75  ::thas_handler(event_type, *this))
76  << ".\n";
77 #endif
78 
79  return find<tset_event>(
80  event,
82  || find<tset_event_mouse>(event,
84  event_type, *this))
85  || find<tset_event_keyboard>(
86  event,
88  *this))
89  || find<tset_event_notification>(
90  event,
92  *this))
93  || find<tset_event_message>(event,
95  event_type, *this));
96 }
97 
98 /**
99  * Helper class to do a runtime test whether an event is in a set.
100  *
101  * The class is supposed to be used in combination with find function. This
102  * function is used in the fire functions to make sure an event is send to the
103  * proper handler. If not there will be a run-time assertion failure. This
104  * makes developing and testing the code easier, a wrong handler terminates
105  * Wesnoth instead of silently not working.
106  */
108 {
109 public:
110  /**
111  * If found we get executed to set the result.
112  *
113  * Since we need to return true if found we always return true.
114  */
115  template <class T>
116  bool oper(tevent)
117  {
118  return true;
119  }
120 };
121 
122 /**
123  * Helper struct to wrap the functor call.
124  *
125  * The template function @ref fire_event needs to call a functor with extra
126  * parameter. In order to facilitate this we send the parameter in the
127  * constructor of the class and let operator() call the functor with the
128  * default parameters and the stored parameters. This allows the core part of
129  * @ref tdispatcher::fire to be generic.
130  */
131 class ttrigger
132 {
133 public:
135  tdispatcher& dispatcher,
136  const tevent event,
137  bool& handled,
138  bool& halt)
139  {
140  functor(dispatcher, event, handled, halt);
141  }
142 };
143 
145 {
146  assert(find<tset_event>(event, tevent_in_set()));
147  switch(event) {
154  dynamic_cast<twidget*>(this), &target, ttrigger());
155 
162  dynamic_cast<twidget*>(this), &target, ttrigger());
163 
170  dynamic_cast<twidget*>(this), &target, ttrigger());
171 
172  default:
173  return fire_event<tsignal_function>(
174  event, dynamic_cast<twidget*>(this), &target, ttrigger());
175  }
176 }
177 
178 /** Helper struct to wrap the functor call. */
180 {
181 public:
182  ttrigger_mouse(const tpoint& coordinate) : coordinate_(coordinate)
183  {
184  }
185 
187  tdispatcher& dispatcher,
188  const tevent event,
189  bool& handled,
190  bool& halt)
191  {
192  functor(dispatcher, event, handled, halt, coordinate_);
193  }
194 
195 private:
197 };
198 
199 bool
200 tdispatcher::fire(const tevent event, twidget& target, const tpoint& coordinate)
201 {
202  assert(find<tset_event_mouse>(event, tevent_in_set()));
203  return fire_event<tsignal_mouse_function>(event,
204  dynamic_cast<twidget*>(this),
205  &target,
206  ttrigger_mouse(coordinate));
207 }
208 
209 /** Helper struct to wrap the functor call. */
211 {
212 public:
214  const SDLMod modifier,
215  const utf8::string& unicode)
216  : key_(key), modifier_(modifier), unicode_(unicode)
217  {
218  }
219 
221  tdispatcher& dispatcher,
222  const tevent event,
223  bool& handled,
224  bool& halt)
225  {
226  functor(dispatcher, event, handled, halt, key_, modifier_, unicode_);
227  }
228 
229 private:
233 };
234 
236  twidget& target,
237  const SDLKey key,
238  const SDLMod modifier,
239  const utf8::string& unicode)
240 {
241  assert(find<tset_event_keyboard>(event, tevent_in_set()));
242  return fire_event<tsignal_keyboard_function>(
243  event,
244  dynamic_cast<twidget*>(this),
245  &target,
246  ttrigger_keyboard(key, modifier, unicode));
247 }
248 
249 /** Helper struct to wrap the functor call. */
251 {
252 public:
254  tdispatcher& dispatcher,
255  const tevent event,
256  bool& handled,
257  bool& halt)
258  {
259  functor(dispatcher, event, handled, halt, nullptr);
260  }
261 };
262 
264 {
265  assert(find<tset_event_notification>(event, tevent_in_set()));
266  return fire_event<tsignal_notification_function>(
267  event,
268  dynamic_cast<twidget*>(this),
269  &target,
271 }
272 
273 /** Helper struct to wrap the functor call. */
275 {
276 public:
278  {
279  }
280 
282  tdispatcher& dispatcher,
283  const tevent event,
284  bool& handled,
285  bool& halt)
286  {
287  functor(dispatcher, event, handled, halt, message_);
288  }
289 
290 private:
292 };
293 
295 {
296  assert(find<tset_event_message>(event, tevent_in_set()));
297  return fire_event<tsignal_message_function>(event,
298  dynamic_cast<twidget*>(this),
299  &target,
300  ttrigger_message(message));
301 }
302 
304  const thotkey_function& function)
305 {
306  hotkeys_[id] = function;
307 }
308 
310 {
312  = hotkeys_.find(id);
313 
314  if(itor == hotkeys_.end()) {
315  return false;
316  }
317 
318  return itor->second(*this, id);
319 }
320 
321 } // namespace event
322 
323 } // namespace gui2
324 
325 /**
326  * @page event_dispatching Event dispatching.
327  *
328  * @section introduction Introduction
329  *
330  * This page describes how the new event handling system works, since the
331  * system is still work in progress it might be out of date with the actual
332  * code. It also contains some ideas that might change later on. Some parts are
333  * explained in the interface and will be integrated in this document later.
334  *
335  * Since the event handling code hasn't been cast in stone yet some scenarios
336  * for solving the problem are discussed first and then the solution that is
337  * chosen in more detail.
338  *
339  * After SDL has generated and event it needs to be turned into an event which
340  * the widgets can use.
341  *
342  * @section handling_solution The implementation solutions.
343  *
344  * For the event handling we use a few use case scenarios and show the possible
345  * solutions.
346  *
347  * @subsection sample The sample window
348  *
349  * In our samples we use this sample window with the following components:
350  * - a window W
351  * - a container C
352  * - a button B
353  *
354  * These are arranged accordingly:
355  * @code
356  *
357  * ---------------------
358  * |W |
359  * | |
360  * | ----------------- |
361  * | |C |^| |
362  * | | |-| |
363  * | | ---------- |#| |
364  * | | |B | | | |
365  * | | ---------- | | |
366  * | | |-| |
367  * | | |v| |
368  * | ----------------- |
369  * | |
370  * ---------------------
371  *
372  * @endcode
373  *
374  * @subsection scenarios Possible scenarios
375  *
376  * The scenarios are:
377  * - An event that is wanted by none.
378  * - A mouse down event that should focus C and set the pressed state in B.
379  * - A mouse wheel event, which first should be offered to B and if not handled
380  * by B should be handled by C.
381  *
382  * @subsection all_queues Pass the event through all queues
383  *
384  * In this solution the event will be passed through all possible queues and
385  * tries sees where the event sticks. This following sections describe how the
386  * events are tried for this usage scenario.
387  *
388  * @subsubsection unhandled Unhandled event
389  *
390  * - W pre child
391  * - C pre child
392  * - B pre child
393  * - W child
394  * - C child
395  * - B child
396  * - W post child
397  * - C post child
398  * - B post child
399  *
400  * @subsubsection mouse_down Mouse down
401  *
402  * - W pre child
403  * - C pre child -> set focus -> !handled
404  * - B pre child -> set pressed state -> handled
405  *
406  * @subsubsection mouse_wheel Mouse wheel
407  *
408  * - W pre child
409  * - C pre child
410  * - B pre child -> We can't scroll so ignore
411  * - W child
412  * - C child
413  * - B child
414  * - W post child
415  * - C post child -> Scroll -> handled
416  *
417  * @subsection chain Pass the events in a chain like fashion
418  *
419  * In this solution the events are send to the pre- and post queue of all but
420  * the last possible widget and to the child of the last widget. The pre queue
421  * will be send from top to bottom, the post queue from bottom to top.
422  *
423  * @subsubsection unhandled Unhandled event
424  *
425  * - W pre child
426  * - C pre child
427  * - B child
428  * - C post child
429  * - W post child
430  *
431  * @subsubsection mouse_down Mouse down
432  *
433  * - W pre child
434  * - C pre child -> set focus -> !handled
435  * - B child -> set pressed state -> handled
436  *
437  * @subsubsection mouse_wheel Mouse wheel
438  *
439  * - W pre child
440  * - C pre child
441  * - B child -> We can't scroll so ignore
442  * - C post child -> Scroll -> handled
443  *
444  * @subsection evaluation Evaluation
445  *
446  * When using the first solution it's possible to drop the child queue since
447  * everything falls in pre or post. But there is a scenario that's a bit ugly
448  * to solve with the first solution:
449  *
450  * Assume there is a listbox with toggle panels and on the panel there are a
451  * few buttons, the wanted behavior is:
452  * - if clicked on the panel it should toggle, which may or may not be allowed.
453  * - if clicked on a button in the panel, we want to make sure the panel is
454  * selected, which again may or may not be allowed.
455  *
456  * With solution 2 it's rather easy:
457  *
458  * Click on panel:
459  * - W pre child
460  * - C child -> Test whether we can toggle -> handled, halt = !toggled
461  *
462  * Click on button in panel:
463  * - W pre child
464  * - C pre child -> Test whether we can select -> handled = halt = !selected
465  * - B child -> do button stuff -> handled
466  *
467  * Since for the different clicks, different queues are triggered it's easy to
468  * add a different handler there.
469  *
470  * With solution 1:
471  *
472  * Click on panel:
473  * - W pre child
474  * - C pre child -> handler 1 -> if last in queue -> solution 2 C child
475  *
476  * Click on button in panel:
477  * - W pre child
478  * - C pre child -> handler 2 -> if !last in queue -> solution 2 C pre child
479  * - B pre child -> do button stuff -> handled
480  *
481  * Not that different from solution 2, the two handlers are installed in the C
482  * pre event. But we need to manually check whether we're really the last,
483  * which means the code to check whether there are more handlers at a lower
484  * level is needed for both solutions. In solution 1 this test needs to be done
485  * twice versus once in solution 2. Also the fact that the queues for the
486  * events are processed in reverse order on the way back sounds more
487  * initiative.
488  *
489  * @section processing_raw_events Processing the raw events.
490  *
491  * This section describes how the events generated by SDL are send as our own
492  * events to the various widgets. The first step in sending an event is to
493  * decode it and send it to a registered dispatcher.
494  *
495  * - gui2::event::thandler handles the SDL events.
496  * - gui2::event::tdispatcher has the registered dispatchers.
497  *
498  * In general a dispatcher is a window which then needs to send this event to
499  * the widgets. The dispatcher is just a simple part which fires events and
500  * finds a handler for the event. This is not to the liking of most widgets,
501  * they don't want to handle raw events but get a polished and clean event. No
502  * button up and down and then try to figure out whether it needs to act as if
503  * it was clicked upon, no simply op and down to change the appearance and a
504  * click event to do the clicking actions. And don't even try to convince a
505  * widget to determine whether this up event was a single or double click.
506  * Widgets like to sleep with nice dreams and not having nightmares where SDL
507  * events haunt them.
508  *
509  * In order to remedy that problem there's the gui2::event::tdistributor
510  * class, it's the class to do the dirty job of converting the raw event into
511  * these nice polished events. The distributor is in general linked to a window,
512  * but a widget can install it's own distributor if it needs to know more of the
513  * raw events as still left in the polished events. At the time of this writing
514  * no widget needs this feature, but the toggle panel might need it.
515  *
516  * After the distributor has polished the event and send it on its way to the
517  * widget the dispatcher needs to make sure the event is properly dispatched to
518  * the widget in question and also notify its parents by means of the previously
519  * described event chain.
520  *
521  * @subsection sdl_event Get the SDL events
522  *
523  * The first step in event handling is getting the events in the first place.
524  * Events are generated by SDL and placed in a queue. The Wesnoth code processes
525  * this queue and thus handles the events. The part which does the first
526  * handling isn't described here since it's (secretly) intended to be replaced
527  * by the @ref gui2::event::thandler class. Instead we directly jump to this
528  * class and explain what it does.
529  *
530  * The main handling function is @ref gui2::event::thandler::handle_event which
531  * as no real surprise handles the events. The function is a simple multiplexer
532  * which lets other subfunctions to the handling of specific events.
533  *
534  * @todo Describe drawing and resizing once the code is stable and working as
535  * wanted in these areas.
536  *
537  * @subsubsection thandler_mouse Mouse motion events
538  *
539  * If a dispatcher has captured the mouse it gets the event, no questions asked.
540  * If not it goes through all dispatchers and finds the first one willing to
541  * accept the mouse event.
542  *
543  * This means a mouse event is send to one dispatcher.
544  *
545  * @subsubsection thandler_mouse_button_down Mouse button down events
546  *
547  * Turning the mouse wheel on a mouse generates both an down and up event. It
548  * has been decided to handle the wheel event in the button up code so wheel
549  * events are here directly dropped on the floor and forgotten.
550  *
551  * The other buttons are handled as if they're normal mouse events but are
552  * decoded per button so instead of a button_down(id) you get button_down_id.
553  *
554  * @subsubsection thandler_mouse_button_up Mouse button up events
555  *
556  * The mouse wheel event is handled as if it's a keyboard event and like the
557  * button_down they are send as wheel_id events.
558  *
559  * The other mouse buttons are handled the same as the down buttons.
560  *
561  * @subsubsection thandler_keyboard Keyboard events
562  *
563  * There are three types of keyboard events, the already mentioned mouse wheel
564  * events, the key down and key up event. When a key is pressed for a longer
565  * time several key down events are generated and only one key up, this means
566  * the key up is rather useless. Guess what, the multiplexer already drops that
567  * event so we never get it.
568  *
569  * If the keyboard event is a mouse wheel event it's directly send to the
570  * dispachting queue; either the dispatcher that captured the keyboard or the
571  * last dispatcher in the queue.
572  *
573  * If the event is a real keyboard action it's first tried as hotkey. In order
574  * to do so the target dispatcher is first determined, either the dispatcher
575  * that captured the keyboard or the last dispatcher in the queue. Then it's
576  * tried whether a hotkey and whether the hotkey can be processed. If the
577  * hotkey isn't processed the keyboard event is send to the dispatcher as
578  * normal keyboard event.
579  *
580  * The hotkey processing will have several queues (to be implemented in 1.9):
581  * - global hotkeys that always work eg toggling fullscreen mode.
582  * - main screen hotkeys, these work when one of the dialogs is shown without
583  * other dialogs on top of them. These hotkeys are for example
584  * preferences. The main screens are:
585  * - title screen
586  * - game
587  * - editor
588  * - mp lobby
589  * - map screen hotkeys, these work when a map is shown eg toggle grid. The
590  * screens are:
591  * - game
592  * - editor
593  * - local hotkeys, these are hotkeys that only work in a specific dialog eg
594  * recruit unit only works in the game screen.
595  *
596  * The queues are processed in from bottom to top in the list above, this
597  * allows an item to use a hotkey but have another handler function. Eg
598  * preferences in the editor might open another preferences dialog.
599  *
600  * @todo The hotkeys need to be implemented like above in 1.9.
601  *
602  * @todo This might change in the near future.
603  *
604  * @subsection tdistributor Event polishing and distribution
605  *
606  * The event distributor has the job to find the widget that should receive the
607  * event and which event(s) to send from a single event. In general an event is
608  * first send to the widget as-is, sending the raw events allows other
609  * distributors to be nested between this distributor and the intended target
610  * widget. Or the intended widget might not really be the intended widget but
611  * another distributor that wants to dispatch the event internally.
612  *
613  * However in the common cases this raw event isn't handled and the distributor
614  * needs to send the polished events. In the following sections the details of
615  * the conversion from raw to polished is described, it intentionally lacks the
616  * part of sending the raw events as well since it adds no value.
617  *
618  * A widget can capture the mouse, which means all mouse events are send to this
619  * widget, regardless where the mouse is. This is normally done in a mouse down
620  * event (for a button) so all events following it are send to that widget.
621  *
622  * @subsection mouse_motion Mouse motion
623  *
624  * This section describes the conversion from a raw mouse motion to the polished
625  * events it can generate:
626  * - @ref gui2::event::MOUSE_ENTER "MOUSE_ENTER"
627  * - @ref gui2::event::MOUSE_LEAVE "MOUSE_LEAVE"
628  * - @ref gui2::event::MOUSE_MOTION "MOUSE_MOTION"
629  *
630  * When the mouse is captured that widget will only receive motion events.
631  *
632  * If not captured the code checks whether the widget underneath the mouse is
633  * the same widget as at the last motion if event. If so that widget gets a
634  * motion event.
635  * If not the widget that before was underneath the mouse pointer (if any) gets
636  * a leave event and the widget newly underneath the mouse pointer (if any) gets
637  * an enter event.
638  *
639  * @subsection mouse_button Mouse buttons
640  *
641  * The mouse button code is a bit more complex and is separated in the various
642  * events to be send.
643  *
644  * @subsubsection mouse_button_down Mouse button down
645  *
646  * Some things start simple, so does the event of pressing down a mouse button.
647  * All it does is send the event to the widget as one of the following events:
648  * - @ref gui2::event::LEFT_BUTTON_DOWN "LEFT_BUTTON_DOWN"
649  * - @ref gui2::event::MIDDLE_BUTTON_DOWN "MIDDLE_BUTTON_DOWN"
650  * - @ref gui2::event::RIGHT_BUTTON_DOWN "RIGHT_BUTTON_DOWN"
651  *
652  * @todo Validate the code it seems a down event with a captured mouse doesn't
653  * really work as wanted. (Rare case but should work properly.) In general the
654  * mouse event handling needs testing to see whether the proper events are send
655  * all the time.
656  *
657  * @subsubsection mouse_button_up Mouse button up
658  *
659  * Simplicity ends here.
660  *
661  * @todo Document further.
662  *
663  * @subsubsection mouse_click Mouse click
664  *
665  * So the button up event has asked for mouse click, now we need to test whether
666  * the click will be a click or a double click. A double click is generated when
667  * the same widget is clicked twice in a short time and causes the following
668  * events:
669  * - @ref gui2::event::LEFT_BUTTON_DOUBLE_CLICK "LEFT_BUTTON_DOUBLE_CLICK"
670  * - @ref gui2::event::MIDDLE_BUTTON_DOUBLE_CLICK "MIDDLE_BUTTON_DOUBLE_CLICK"
671  * - @ref gui2::event::RIGHT_BUTTON_DOUBLE_CLICK "RIGHT_BUTTON_DOUBLE_CLICK"
672  *
673  * Otherwise one of the following single clicks is generated:
674  * - @ref gui2::event::LEFT_BUTTON_CLICK "LEFT_BUTTON_CLICK"
675  * - @ref gui2::event::MIDDLE_BUTTON_CLICK "MIDDLE_BUTTON_CLICK"
676  * - @ref gui2::event::RIGHT_BUTTON_CLICK "RIGHT_BUTTON_CLICK"
677  *
678  * @subsubsection double_click To double click or not to double click
679  *
680  * Wait a second, a widget has a field whether or not it wants a double click
681  * for a certain mouse button and now I see that it's bluntly ignored by the
682  * distributor. Indeed the distributor doesn't care about what the widget wants,
683  * it does what it wants and leaves the sorting out what's wanted to the
684  * dispatcher.
685  *
686  * The problem is that in the chain events are send to one widget that may not
687  * be interested in a double click, but another widget in the chain is. There
688  * are several solutions to this problem:
689  * -# Sending a click followed by a double click.
690  * -# Sending a click with a tag field that it actually is a double click.
691  * -# Send a double click and turn it into a click if the double click is
692  * unwanted.
693  *
694  * The first solution has the disadvantage that a toggle panel likes a click and
695  * double click, the first click selects the second deselects and now the
696  * deselected panel gets a double click. When the panel now checks whether it's
697  * selected it's not and might take the wrong action upon it.
698  *
699  * The second option is possible but would be rather intrusive in the code,
700  * since it would generate another event signature. Adding a signature just for
701  * this special case seemed a bit too much effort vs. gain. Also the widget
702  * needs to check whether a click is a click or a double click and choose a
703  * different code path for it. This in turn would mean a signal handler
704  * secretly might handle two events and lowers the transparency of the code.
705  *
706  * The third option also adds some special case handling but the scope is
707  * limited and only one part knows about the tricks done.
708  *
709  * The last option has been chosen and the dispatcher build the event chain and
710  * while building the chain it looks whether the widget wants the double click
711  * or not. It does this test by looking at the wants double click function and
712  * not test for a handler. The double click test function is made for this
713  * purpose and depending on the handler might again do the wrong thing.
714  * (A certain toggle panel might not want to do something on a double click but
715  * also not being deselected upon a double click. The latter to keep the UI
716  * consistent, a double click on a toggle panel might execute a special function
717  * or not, but always keep the panel selected. (That is if the panel can be
718  * selected.))
719  */
Define the common log macros for the gui toolkit.
void operator()(tsignal_function functor, tdispatcher &dispatcher, const tevent event, bool &handled, bool &halt)
Definition: dispatcher.cpp:134
Helper struct to wrap the functor call.
Definition: dispatcher.cpp:274
See LEFT_BUTTON_DOUBLE_CLICK.
Definition: handler.hpp:116
#define SDLMod
Definition: compat.hpp:30
A left mouse button double click event for a widget.
Definition: handler.hpp:89
void operator()(tsignal_keyboard_function functor, tdispatcher &dispatcher, const tevent event, bool &handled, bool &halt)
Definition: dispatcher.cpp:220
itor second functor(surf, f[1])
Helper class to do a runtime test whether an event is in a set.
Definition: dispatcher.cpp:107
ttrigger_keyboard(const SDLKey key, const SDLMod modifier, const utf8::string &unicode)
Definition: dispatcher.cpp:213
void register_hotkey(const hotkey::HOTKEY_COMMAND id, const thotkey_function &function)
Registers a hotkey.
Definition: dispatcher.cpp:303
std::function< bool(tdispatcher &dispatcher, hotkey::HOTKEY_COMMAND id)> thotkey_function
Hotkey function handler signature.
Definition: dispatcher.hpp:105
Base class for event handling.
Definition: dispatcher.hpp:122
std::function< void(tdispatcher &dispatcher, const tevent event, bool &handled, bool &halt, const SDLKey key, const SDLMod modifier, const utf8::string &unicode)> tsignal_keyboard_function
Callback function signature.
Definition: dispatcher.hpp:77
bool connected_
Are we connected to the event handler.
Definition: dispatcher.hpp:683
#define SDLKey
Definition: compat.hpp:29
bool wants_mouse_middle_double_click() const
A left mouse button click event for a widget.
Definition: handler.hpp:84
std::map< hotkey::HOTKEY_COMMAND, thotkey_function > hotkeys_
The registered hotkeys for this dispatcher.
Definition: dispatcher.hpp:686
A class inherited from ttext_box that displays its input as stars.
Definition: field-fwd.hpp:23
std::function< void(tdispatcher &dispatcher, const tevent event, bool &handled, bool &halt, tmessage &message)> tsignal_message_function
Callback function signature.
Definition: dispatcher.hpp:101
void operator()(tsignal_mouse_function functor, tdispatcher &dispatcher, const tevent event, bool &handled, bool &halt)
Definition: dispatcher.cpp:186
bool wants_mouse_left_double_click() const
See LEFT_BUTTON_DOUBLE_CLICK.
Definition: handler.hpp:104
bool oper(tevent)
If found we get executed to set the result.
Definition: dispatcher.cpp:116
std::function< void(tdispatcher &dispatcher, const tevent event, bool &handled, bool &halt, const tpoint &coordinate)> tsignal_mouse_function
Callback function signature.
Definition: dispatcher.hpp:63
Helper struct to wrap the functor call.
Definition: dispatcher.cpp:250
bool fire(const tevent event, twidget &target)
Fires an event which has no extra parameters.
Definition: dispatcher.cpp:144
bool execute_hotkey(const hotkey::HOTKEY_COMMAND id)
Executes a hotkey.
Definition: dispatcher.cpp:309
void connect()
Connects the dispatcher to the event handler.
Definition: dispatcher.cpp:49
ttrigger_mouse(const tpoint &coordinate)
Definition: dispatcher.cpp:182
void operator()(tsignal_notification_function functor, tdispatcher &dispatcher, const tevent event, bool &handled, bool &halt)
Definition: dispatcher.cpp:253
std::function< void(tdispatcher &dispatcher, const tevent event, bool &handled, bool &halt)> tsignal_function
Callback function signature.
Definition: dispatcher.hpp:40
bool fire_event_double_click(twidget *dispatcher, twidget *widget, F functor)
Helper struct to wrap the functor call.
Definition: dispatcher.cpp:210
static size_t id
Ids for the timers.
Definition: timer.cpp:39
tevent
The event send to the dispatcher.
Definition: handler.hpp:54
void operator()(tsignal_message_function functor, tdispatcher &dispatcher, const tevent event, bool &handled, bool &halt)
Definition: dispatcher.cpp:281
Helper struct to wrap the functor call.
Definition: dispatcher.cpp:179
A helper class to find out whether dispatcher has an handler for a certain event. ...
std::map< std::string, tfilter >::iterator itor
Definition: filter.cpp:199
See LEFT_BUTTON_CLICK.
Definition: handler.hpp:114
void connect_dispatcher(tdispatcher *dispatcher)
Connects a dispatcher to the event handler.
Definition: handler.cpp:774
Holds a 2D point.
Definition: point.hpp:24
hotkey_list hotkeys_
Definition: hotkey_item.cpp:45
The message callbacks hold a reference to a message.
Definition: message.hpp:45
std::function< void(tdispatcher &dispatcher, const tevent event, bool &handled, bool &halt, void *)> tsignal_notification_function
Callback function signature.
Definition: dispatcher.hpp:90
ttrigger_message(tmessage &message)
Definition: dispatcher.cpp:277
See LEFT_BUTTON_CLICK.
Definition: handler.hpp:102
bool has_event(const tevent event, const tevent_type event_type)
Definition: dispatcher.cpp:56
cl_event event
Definition: glew.h:3070
Helper struct to wrap the functor call.
Definition: dispatcher.cpp:131
void disconnect_dispatcher(tdispatcher *dispatcher)
Disconnects a dispatcher to the event handler.
Definition: handler.cpp:781
Base class for all widgets.
Definition: widget.hpp:49
GLsizei GLenum GLuint GLuint GLsizei char * message
Definition: glew.h:2499
std::string::const_iterator iterator
Definition: tokenizer.hpp:21
bool wants_mouse_right_double_click() const
std::string string
GLenum target
Definition: glew.h:5190