The Battle for Wesnoth  1.15.0-dev
dispatcher.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2009 - 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 #pragma once
16 
19 
20 #include "utils/functional.hpp"
21 
22 #include <SDL_events.h>
23 
24 #include <boost/mpl/int.hpp>
25 
26 #include <list>
27 #include <map>
28 #include <type_traits>
29 
30 struct point;
31 
32 namespace gui2
33 {
34 class widget;
35 
36 namespace event
37 {
38 
39 template<typename K, ui_event E>
40 using has_key = boost::mpl::has_key<K, boost::mpl::int_<E>>;
41 
42 struct message;
43 
44 /**
45  * Callback function signature.
46  *
47  * There are several kinds of callback signature, this only has the parameters
48  * shared by all callbacks.
49  *
50  * This function is used for the callbacks in set_event.
51  */
52 typedef std::function<void(widget& dispatcher,
53  const ui_event event,
54  bool& handled, bool& halt)> signal_function;
55 
56 /**
57  * Callback function signature.
58  *
59  * This function is used for the callbacks in set_event_mouse.
60  */
61 typedef std::function<void(widget& dispatcher,
62  const ui_event event,
63  bool& handled,
64  bool& halt,
66 
67 /**
68  * Callback function signature.
69  *
70  * This function is used for the callbacks in set_event_keyboard.
71  */
72 typedef std::function<void(widget& dispatcher,
73  const ui_event event,
74  bool& handled,
75  bool& halt,
76  const SDL_Keycode key,
77  const SDL_Keymod modifier,
78  const std::string& unicode)> signal_keyboard_function;
79 
80 /**
81  * Callback function signature.
82  *
83  * This function is used for the callbacks in set_event_touch_motion.
84  */
85 typedef std::function<void(widget& dispatcher,
86  const ui_event event,
87  bool& handled,
88  bool& halt,
89  const point& pos,
91 
92 /**
93  * Callback function signature.
94  *
95  * This function is used for the callbacks in set_event_touch_gesture.
96  */
97 typedef std::function<void(dispatcher& dispatcher,
98  const ui_event event,
99  bool& handled,
100  bool& halt,
101  const point& center,
102  float dTheta,
103  float dDist,
104  Uint8 numFingers)> signal_touch_gesture_function;
105 
106 /**
107  * Callback function signature.
108  *
109  * This function is used for the callbacks in set_event_notification.
110  * Added the dummy void* parameter which will be nullptr to get a different
111  * signature as signal_function's callback.
112  */
113 typedef std::function<void(widget& dispatcher,
114  const ui_event event,
115  bool& handled,
116  bool& halt,
118 
119 /**
120  * Callback function signature.
121  *
122  * This function is used for the callbacks in set_event_message.
123  */
124 typedef std::function<void(widget& dispatcher,
125  const ui_event event,
126  bool& handled,
127  bool& halt,
129 
130 /**
131  * Callback function signature.
132  *
133  * This function is used for the callbacks in set_event_raw_event.
134  */
135 typedef std::function<void(widget& dispatcher,
136  const ui_event event,
137  bool& handled,
138  bool& halt,
139  const SDL_Event& sdlevent)> signal_raw_event_function;
140 
141 /**
142  * Callback function signature.
143  *
144  * This function is used for the callbacks in set_event_text_input.
145  */
146 typedef std::function<void(widget& dispatcher,
147  const ui_event event,
148  bool& handled,
149  bool& halt,
150  const std::string& text,
151  int32_t current_pos,
152  int32_t select_len)> signal_text_input_function;
153 
154 /** Hotkey function handler signature. */
155 typedef std::function<void(widget& dispatcher, hotkey::HOTKEY_COMMAND id)> hotkey_function;
156 
157 /**
158  * Base class for event handling.
159  *
160  * A dispatcher has slots for events, when an event arrives it looks for the
161  * functions that registered themselves for that event and calls their
162  * callbacks.
163  *
164  * This class is a base class for all widgets[1], what a widget does on a
165  * callback can differ greatly, an image might ignore all events a window can
166  * track the mouse location and fire MOUSE_ENTER and MOUSE_LEAVE events to the
167  * widgets involved.
168  *
169  * [1] Not really sure whether it will be a base class for a widget or
170  * styled_widget yet.
171  */
173 {
175 
176 public:
177  dispatcher();
178  virtual ~dispatcher();
179 
180  /**
181  * Connects the dispatcher to the event handler.
182  *
183  * When a dispatcher is connected to the event handler it will get the
184  * events directly from the event handler. This is wanted for top level
185  * items like windows but not for most other widgets.
186  *
187  * So a window can call connect to register itself, it will automatically
188  * disconnect upon destruction.
189  */
190  void connect();
191 
192  /**
193  * Determines whether the location is inside an active widget.
194  *
195  * This is used to see whether a mouse event is inside the widget.
196  *
197  * @param coordinate The coordinate to test whether inside the
198  * widget.
199  *
200  * @result True if inside an active widget, false
201  * otherwise.
202  */
203  virtual bool is_at(const point& coordinate) const = 0;
204 
206  pre = 1,
207  child = 2,
208  post = 4
209  };
210 
211  bool has_event(const ui_event event, const event_queue_type event_type);
212 
213  /** Fires an event which has no extra parameters. */
214  bool fire(const ui_event event, widget& target);
215 
216  /**
217  * Fires an event which takes a coordinate parameter.
218  *
219  * @param event The event to fire.
220  * @param target The widget that should receive the event.
221  * @param coordinate The mouse position for the event.
222  */
223  bool fire(const ui_event event,
224  widget& target,
225  const point& coordinate);
226 
227  /**
228  * Fires an event which takes keyboard parameters.
229  *
230  * @param event The event to fire.
231  * @param target The widget that should receive the event.
232  * @param key The SDL key code of the key pressed.
233  * @param modifier The SDL key modifiers used.
234  * @param unicode The unicode value for the key pressed.
235  */
236  bool fire(const ui_event event,
237  widget& target,
238  const SDL_Keycode key,
239  const SDL_Keymod modifier,
240  const std::string& unicode);
241 
242  /**
243  * Fires an event which takes touch-motion parameters.
244  *
245  * @param event The event to fire.
246  * @param target The widget that should receive the event.
247  * @param pos The location touched.
248  * @param distance The distance moved.
249  */
250  bool fire(const ui_event event,
251  widget& target,
252  const point& pos,
253  const point& distance);
254 
255 
256  /**
257  * Fires an event which takes touch-gesture parameters.
258  *
259  * @param event The event to fire.
260  * @param target The widget that should receive the event.
261  * @param center The location touched.
262  * @param dTheta Probably the direction moved.
263  * @param dDist The distance moved.
264  * @param numFingers Probably the number of fingers touching the screen.
265  */
266  bool fire(const ui_event event,
267  widget& target,
268  const point& center,
269  float dTheta,
270  float dDist,
271  Uint8 numFingers);
272 
273 
274  /**
275  * Fires an event which takes notification parameters.
276  *
277  * @note the void* parameter is a dummy needed for SFINAE.
278  *
279  * @param event The event to fire.
280  * @param target The widget that should receive the event.
281  */
282  bool fire(const ui_event event,
283  widget& target,
284  void*);
285 
286  /**
287  * Fires an event which takes message parameters.
288  *
289  * @param event The event to fire.
290  * @param target The widget that should receive the event.
291  * Normally this is the window holding the
292  * widget.
293  * @param msg The extra information needed for a window
294  * (or another widget in the chain) to handle
295  * the message.
296  */
297  bool fire(const ui_event event,
298  widget& target,
299  const message& msg);
300 
301  /**
302  * Fires an event that's a raw SDL event
303  * @param event The event to fire.
304  * @param target The widget that should receive the event.
305  * Normally this is the window holding the
306  * widget.
307  * @param sdlevent The raw SDL event
308  */
309  bool fire(const ui_event event,
310  widget& target,
311  const SDL_Event& sdlevent);
312 
313  /**
314  * Fires an event which takes text input parameters
315  * @param event The event to fire.
316  * @param target The widget that should receive the event.
317  * Normally this is the window holding the
318  * widget.
319  * @param text The text involved in the event
320  * @param start The start point for IME editing
321  * @param len The selection length for IME editing
322  */
323  bool fire(const ui_event event,
324  widget& target,
325  const std::string& text,
326  int32_t start,
327  int32_t len);
328 
329  /**
330  * The position where to add a new callback in the signal handler.
331  *
332  * The signal handler has three callback queues:
333  * * pre_child These callbacks are called before a container widget sends it
334  * to the child items. Widgets without children should also use this
335  * queue.
336  * * child The callbacks for the proper child widget(s) are called.
337  * * post_child The callbacks for the parent container to be called after
338  * the child.
339  *
340  * For every queue it's possible to add a new event in the front or in the
341  * back.
342  *
343  * Whether all three queues are executed depend on the whether the
344  * callbacks modify the handled and halt flag.
345  * * When the halt flag is set execution of the current queue stops, when
346  * doing so the handled flag must be set as well.
347  * * When the handled flag is set the events in that queue are executed and
348  * no more queues afterwards.
349  *
350  * Here are some use case examples.
351  * A button that plays a sound and executes an optional user callback:
352  * * The buttons internal click handler is invoked and sets the handled
353  * flag
354  * * The callback installed by the user is in the same queue and gets
355  * executed afterwards.
356  *
357  * A toggle button may or may not be toggled:
358  * * The user inserts a callback, that validates whether the action is
359  * allowed, if not allowed it sets the halt flag (and handled), else
360  * leaves the flags untouched.
361  * * The normal buttons toggle function then might get invoked and if so
362  * sets the handled flag.
363  * * Optionally there is another user callback invoked at this point.
364  */
372  };
373 
374  /**
375  * Connect a signal for callback in set_event.
376  *
377  * The function uses some enable_if magic to avoid registering the wrong
378  * function, but the common way to use this function is:
379  * widget->connect_signal<EVENT_ID>(
380  * std::bind(&tmy_dialog::my_member, this));
381  * This allows simply adding a member of a dialog to be used as a callback
382  * for widget without a lot of magic. Note most widgets probably will get a
383  * callback like
384  * connect_signal_mouse_left_click(const signal_function& callback)
385  * which hides this function for the average use.
386  *
387  * @tparam E The event the callback needs to react to.
388  * @param signal The callback function.
389  * @param position The position to place the callback.
390  */
391  template <ui_event E>
392  std::enable_if_t<has_key<set_event, E>::value>
393  connect_signal(const signal_function& signal,
394  const queue_position position = back_child)
395  {
396  signal_queue_.connect_signal(E, position, signal);
397  }
398 
399  /**
400  * Disconnect a signal for callback in set_event.
401  *
402  * @tparam E The event the callback was used for.
403  * @param signal The callback function.
404  * @param position The place where the function was added.
405  * Needed remove the event from the right
406  * place. (The function doesn't care whether
407  * was added in front or back.)
408  */
409  template <ui_event E>
410  std::enable_if_t<has_key<set_event, E>::value>
411  disconnect_signal(const signal_function& signal,
412  const queue_position position = back_child)
413  {
414  signal_queue_.disconnect_signal(E, position, signal);
415  }
416 
417  /**
418  * Connect a signal for callback in set_event_mouse.
419  *
420  * @tparam E The event the callback needs to react to.
421  * @param signal The callback function.
422  * @param position The position to place the callback.
423  */
424  template <ui_event E>
425  std::enable_if_t<has_key<set_event_mouse, E>::value>
426  connect_signal(const signal_mouse_function& signal,
427  const queue_position position = back_child)
428  {
429  signal_mouse_queue_.connect_signal(E, position, signal);
430  }
431 
432  /**
433  * Disconnect a signal for callback in set_event_mouse.
434  *
435  * @tparam E The event the callback was used for.
436  * @param signal The callback function.
437  * @param position The place where the function was added.
438  * Needed remove the event from the right
439  * place. (The function doesn't care whether
440  * was added in front or back.)
441  */
442  template <ui_event E>
443  std::enable_if_t<has_key<set_event_mouse, E>::value>
444  disconnect_signal(const signal_mouse_function& signal,
445  const queue_position position = back_child)
446  {
447  signal_mouse_queue_.disconnect_signal(E, position, signal);
448  }
449 
450  /**
451  * Connect a signal for callback in set_event_keyboard.
452  *
453  * @tparam E The event the callback needs to react to.
454  * @param signal The callback function.
455  * @param position The position to place the callback.
456  */
457  template <ui_event E>
458  std::enable_if_t<has_key<set_event_keyboard, E>::value>
459  connect_signal(const signal_keyboard_function& signal,
460  const queue_position position = back_child)
461  {
462  signal_keyboard_queue_.connect_signal(E, position, signal);
463  }
464 
465  /**
466  * Disconnect a signal for callback in set_event_keyboard.
467  *
468  * @tparam E The event the callback was used for.
469  * @param signal The callback function.
470  * @param position The place where the function was added.
471  * Needed remove the event from the right
472  * place. (The function doesn't care whether
473  * was added in front or back.)
474  */
475  template <ui_event E>
476  std::enable_if_t<has_key<set_event_keyboard, E>::value>
477  disconnect_signal(const signal_keyboard_function& signal,
478  const queue_position position = back_child)
479  {
480  signal_keyboard_queue_.disconnect_signal(E, position, signal);
481  }
482 
483  /**
484  * Connect a signal for callback in set_event_touch_motion.
485  *
486  * @tparam E The event the callback needs to react to.
487  * @param signal The callback function.
488  * @param position The position to place the callback.
489  */
490  template <ui_event E>
491  std::enable_if_t<has_key<set_event_touch_motion, E>::value>
492  connect_signal(const signal_touch_motion_function& signal,
493  const queue_position position = back_child)
494  {
495  signal_touch_motion_queue_.connect_signal(E, position, signal);
496  }
497 
498  /**
499  * Disconnect a signal for callback in set_event_touch.
500  *
501  * @tparam E The event the callback was used for.
502  * @param signal The callback function.
503  * @param position The place where the function was added.
504  * Needed remove the event from the right
505  * place. (The function doesn't care whether
506  * was added in front or back.)
507  */
508  template <ui_event E>
509  std::enable_if_t<has_key<set_event_touch_motion, E>::value>
510  disconnect_signal(const signal_touch_motion_function& signal,
511  const queue_position position = back_child)
512  {
513  signal_touch_motion_queue_.disconnect_signal(E, position, signal);
514  }
515 
516  /**
517  * Connect a signal for callback in set_event_touch_gesture.
518  *
519  * @tparam E The event the callback needs to react to.
520  * @param signal The callback function.
521  * @param position The position to place the callback.
522  */
523  template <ui_event E>
524  std::enable_if_t<has_key<set_event_touch_gesture, E>::value>
525  connect_signal(const signal_touch_gesture_function& signal,
526  const queue_position position = back_child)
527  {
528  signal_touch_gesture_queue_.connect_signal(E, position, signal);
529  }
530 
531  /**
532  * Disconnect a signal for callback in set_event_touch.
533  *
534  * @tparam E The event the callback was used for.
535  * @param signal The callback function.
536  * @param position The place where the function was added.
537  * Needed remove the event from the right
538  * place. (The function doesn't care whether
539  * was added in front or back.)
540  */
541  template <ui_event E>
542  std::enable_if_t<has_key<set_event_touch_gesture, E>::value>
543  disconnect_signal(const signal_touch_gesture_function& signal,
544  const queue_position position = back_child)
545  {
546  signal_touch_gesture_queue_.disconnect_signal(E, position, signal);
547  }
548 
549  /**
550  * Connect a signal for callback in set_event_notification.
551  *
552  * @tparam E The event the callback needs to react to.
553  * @param signal The callback function.
554  * @param position The position to place the callback. Since
555  * the message is send to a widget directly
556  * the pre and post positions make no sense
557  * and shouldn't be used.
558  */
559  template <ui_event E>
560  std::enable_if_t<has_key<set_event_notification, E>::value>
561  connect_signal(const signal_notification_function& signal,
562  const queue_position position = back_child)
563  {
564  signal_notification_queue_.connect_signal(E, position, signal);
565  }
566 
567  /**
568  * Disconnect a signal for callback in set_event_notification.
569  *
570  * @tparam E The event the callback was used for.
571  * @param signal The callback function.
572  * @param position The place where the function was added.
573  * Needed remove the event from the right
574  * place. (The function doesn't care whether
575  * was added in front or back, but it needs
576  * to know the proper queue so it's save to
577  * add with front_child and remove with
578  * back_child. But it's not save to add with
579  * front_child and remove with
580  * front_pre_child)
581  */
582  template <ui_event E>
583  std::enable_if_t<has_key<set_event_notification, E>::value>
584  disconnect_signal(const signal_notification_function& signal,
585  const queue_position position = back_child)
586  {
587  signal_notification_queue_.disconnect_signal(E, position, signal);
588  }
589 
590  /**
591  * Connect a signal for callback in set_event_message.
592  *
593  * @tparam E The event the callback needs to react to.
594  * @param signal The callback function.
595  * @param position The position to place the callback. Since
596  * the message is send to a widget directly
597  * the pre and post positions make no sense
598  * and shouldn't be used.
599  */
600  template <ui_event E>
601  std::enable_if_t<has_key<set_event_message, E>::value>
602  connect_signal(const signal_message_function& signal,
603  const queue_position position = back_child)
604  {
605  signal_message_queue_.connect_signal(E, position, signal);
606  }
607 
608  /**
609  * Disconnect a signal for callback in set_event_message.
610  *
611  * @tparam E The event the callback was used for.
612  * @param signal The callback function.
613  * @param position The place where the function was added.
614  * Needed remove the event from the right
615  * place. (The function doesn't care whether
616  * was added in front or back, but it needs
617  * to know the proper queue so it's save to
618  * add with front_child and remove with
619  * back_child. But it's not save to add with
620  * front_child and remove with
621  * front_pre_child)
622  */
623  template <ui_event E>
624  std::enable_if_t<has_key<set_event_message, E>::value>
625  disconnect_signal(const signal_message_function& signal,
626  const queue_position position = back_child)
627  {
628  signal_message_queue_.disconnect_signal(E, position, signal);
629  }
630 
631  /**
632  * Connect a signal for callback in set_raw_event.
633  *
634  * @tparam E The event the callback needs to react to.
635  * @param signal The callback function.
636  * @param position The position to place the callback.
637  */
638  template <ui_event E>
639  std::enable_if_t<has_key<set_event_raw_event, E>::value>
640  connect_signal(const signal_raw_event_function& signal,
641  const queue_position position = back_child)
642  {
643  signal_raw_event_queue_.connect_signal(E, position, signal);
644  }
645 
646  /**
647  * Disconnect a signal for callback in set_raw_event.
648  *
649  * @tparam E The event the callback was used for.
650  * @param signal The callback function.
651  * @param position The place where the function was added.
652  * Needed remove the event from the right
653  * place. (The function doesn't care whether
654  * was added in front or back.)
655  */
656  template <ui_event E>
657  std::enable_if_t<has_key<set_event_raw_event, E>::value>
658  disconnect_signal(const signal_raw_event_function& signal,
659  const queue_position position = back_child)
660  {
661  signal_raw_event_queue_.disconnect_signal(E, position, signal);
662  }
663 
664  /**
665  * Connect a signal for callback in set_text_input.
666  *
667  * @tparam E The event the callback needs to react to.
668  * @param signal The callback function.
669  * @param position The position to place the callback.
670  */
671  template <ui_event E>
672  std::enable_if_t<has_key<set_event_text_input, E>::value>
673  connect_signal(const signal_text_input_function& signal,
674  const queue_position position = back_child)
675  {
676  signal_text_input_queue_.connect_signal(E, position, signal);
677  }
678 
679  /**
680  * Disconnect a signal for callback in set_text_input.
681  *
682  * @tparam E The event the callback was used for.
683  * @param signal The callback function.
684  * @param position The place where the function was added.
685  * Needed remove the event from the right
686  * place. (The function doesn't care whether
687  * was added in front or back.)
688  */
689  template <ui_event E>
690  std::enable_if_t<has_key<set_event_text_input, E>::value>
691  disconnect_signal(const signal_text_input_function& signal,
692  const queue_position position = back_child)
693  {
694  signal_text_input_queue_.disconnect_signal(E, position, signal);
695  }
696 
697  /**
698  * The behavior of the mouse events.
699  *
700  * Normally for mouse events there's first checked whether a dispatcher has
701  * captured the mouse if so it gets the event.
702  * If not the dispatcher is searched from the back to the front in the
703  * layers and its behavior is checked.
704  * * none The event is never send to the layer and goes on the the next
705  * layer. This is used for tooltips who might cover a button but a click
706  * on the tooltips should still click the button.
707  * * all The event is always send to this layer and stops the search for a
708  * next layer.
709  * * hit If the mouse is inside the dispatcher area the event is send and
710  * no longer searched further. If not inside tests the last layer.
711  *
712  * If after these tests no dispatcher is found the event is ignored.
713  */
718  };
719 
720  /** Captures the mouse. */
722  {
724  }
725 
726  /** Releases the mouse capture. */
728  {
730  }
731 
732  /***** ***** ***** setters/getters ***** ***** *****/
733 
735  {
737  }
738 
740  {
741  return mouse_behavior_;
742  }
743 
744  void set_want_keyboard_input(const bool want_keyboard_input)
745  {
746  want_keyboard_input_ = want_keyboard_input;
747  }
748 
750  {
751  return want_keyboard_input_;
752  }
753 
754  /** Helper struct to generate the various signal types. */
755  template <class T>
756  struct signal_type
757  {
759  {
760  }
761 
762  std::list<T> pre_child;
763  std::list<T> child;
764  std::list<T> post_child;
765  };
766 
767  /** Helper struct to generate the various event queues. */
768  template <class T>
770  {
771  signal_queue() : queue()
772  {
773  }
774 
775  std::map<ui_event, signal_type<T>> queue;
776 
777  void connect_signal(const ui_event event,
778  const queue_position position,
779  const T& signal)
780  {
781  switch(position) {
782  case front_pre_child:
783  queue[event].pre_child.push_front(signal);
784  break;
785  case back_pre_child:
786  queue[event].pre_child.push_back(signal);
787  break;
788 
789  case front_child:
790  queue[event].child.push_front(signal);
791  break;
792  case back_child:
793  queue[event].child.push_back(signal);
794  break;
795 
796  case front_post_child:
797  queue[event].post_child.push_front(signal);
798  break;
799  case back_post_child:
800  queue[event].post_child.push_back(signal);
801  break;
802  }
803  }
804 
805  void disconnect_signal(const ui_event event,
806  const queue_position position,
807  const T& signal)
808  {
809  signal_type<T>& signal_queue = queue[event];
810 
811  /* The function doesn't differentiate between front and back position so fall
812  * down from front to back.
813  *
814  * NOTE: This used to only remove the first signal of matching target type.
815  * That behavior could be restored in the future if needed.
816  * - vultraz, 2017-05-02
817  */
818  switch(position) {
819  case front_pre_child:
820  case back_pre_child: {
821  signal_queue.pre_child.remove_if(
822  [&signal](T& element) { return signal.target_type() == element.target_type(); }
823  );
824  } break;
825 
826  case front_child:
827  case back_child: {
828  signal_queue.child.remove_if(
829  [&signal](T& element) { return signal.target_type() == element.target_type(); }
830  );
831  } break;
832 
833  case front_post_child:
834  case back_post_child: {
835  signal_queue.post_child.remove_if(
836  [&signal](T& element) { return signal.target_type() == element.target_type(); }
837  );
838  } break;
839  }
840  }
841  };
842 
843  /**
844  * Registers a hotkey.
845  *
846  * @todo add a static function register_global_hotkey.
847  *
848  * Once that's done execute_hotkey will first try to execute a global
849  * hotkey and if that fails tries the hotkeys in this dispatcher.
850  *
851  * @param id The hotkey to register.
852  * @param function The callback function to call.
853  */
855  const hotkey_function& function);
856 
857  /**
858  * Executes a hotkey.
859  *
860  * @param id The hotkey to execute.
861  *
862  * @returns true if the hotkey is handled, false
863  * otherwise.
864  */
865  bool execute_hotkey(const hotkey::HOTKEY_COMMAND id);
866 
867 private:
868  /** The mouse behavior for the dispatcher. */
870 
871  /**
872  * Does the dispatcher want to receive keyboard input.
873  *
874  * @todo The entire mouse and keyboard handling can use a code review to
875  * seen whether it might be combined in one flag field. At the moment the
876  * keyboard doesn't look whether a dialog has the mouse focus before
877  * sending the event, so maybe we should add an active dispatcher to keep
878  * track of it. But since at the moment there are only non-modal windows
879  * and tooltips it's not a problem.
880  */
882 
883  /** Signal queue for callbacks in set_event. */
885 
886  /** Signal queue for callbacks in set_event_mouse. */
888 
889  /** Signal queue for callbacks in set_event_keyboard. */
891 
892  /** Signal queue for callbacks in set_event_touch. */
894 
895  /** Signal queue for callbacks in set_event_touch. */
897 
898  /** Signal queue for callbacks in set_event_notification. */
900 
901  /** Signal queue for callbacks in set_event_message. */
903 
904  /** Signal queue for callbacks in set_raw_event. */
906 
907  /** Signal queue for callbacks in set_event_text_input. */
909 
910  /** Are we connected to the event handler. */
912 
913  /** The registered hotkeys for this dispatcher. */
914  std::map<hotkey::HOTKEY_COMMAND, hotkey_function> hotkeys_;
915 };
916 
917 /***** ***** ***** ***** ***** Common helpers ***** ***** ***** ***** *****/
918 
919 /*
920  * These helpers can be used to easily add callbacks to a dispatcher (widget).
921  * This is just a list of common ones all others can be used as well.
922  */
923 
924 /**
925  * Connects the signal for 'snooping' on the keypress.
926  *
927  * This callback is called before the widget itself allowing you to either
928  * snoop on the input or filter it.
929  */
930 void connect_signal_pre_key_press(dispatcher& dispatcher, const signal_keyboard_function& signal);
931 
932 /** Connects a signal handler for a left mouse button click. */
933 void connect_signal_mouse_left_click(dispatcher& dispatcher, const signal_function& signal);
934 
935 /** Disconnects a signal handler for a left mouse button click. */
936 void disconnect_signal_mouse_left_click(dispatcher& dispatcher, const signal_function& signal);
937 
938 /**
939  * Connects a signal handler for a left mouse button double click.
940  *
941  * I'm not exactly sure why this works in this queue position with toggle
942  * panels, but it does. Will revisit if it becomes an issue later (ie, if
943  * this is used with other widgets and doesn't work).
944  *
945  * - vultraz, 2017-08-23
946  */
947 void connect_signal_mouse_left_double_click(dispatcher& dispatcher, const signal_function& signal);
948 
949 /** Connects a signal handler for getting a notification upon modification. */
950 void connect_signal_notify_modified(dispatcher& dispatcher, const signal_notification_function& signal);
951 
952 /** Connects a signal handler for a callback when the widget is drawn. */
953 void connect_signal_on_draw(dispatcher& dispatcher, const signal_function& signal);
954 
955 } // namespace event
956 
957 } // namespace gui2
mouse_behavior get_mouse_behavior() const
Definition: dispatcher.hpp:739
std::enable_if_t< has_key< set_event_keyboard, E >::value > connect_signal(const signal_keyboard_function &signal, const queue_position position=back_child)
Connect a signal for callback in set_event_keyboard.
Definition: dispatcher.hpp:459
std::enable_if_t< has_key< set_event_message, E >::value > connect_signal(const signal_message_function &signal, const queue_position position=back_child)
Connect a signal for callback in set_event_message.
Definition: dispatcher.hpp:602
std::enable_if_t< has_key< set_event_raw_event, E >::value > connect_signal(const signal_raw_event_function &signal, const queue_position position=back_child)
Connect a signal for callback in set_raw_event.
Definition: dispatcher.hpp:640
std::enable_if_t< has_key< set_event_touch_motion, E >::value > connect_signal(const signal_touch_motion_function &signal, const queue_position position=back_child)
Connect a signal for callback in set_event_touch_motion.
Definition: dispatcher.hpp:492
signal_queue< signal_text_input_function > signal_text_input_queue_
Signal queue for callbacks in set_event_text_input.
Definition: dispatcher.hpp:908
Base class for event handling.
Definition: dispatcher.hpp:172
void register_hotkey(const hotkey::HOTKEY_COMMAND id, const hotkey_function &function)
Registers a hotkey.
Definition: dispatcher.cpp:203
Base class for all widgets.
Definition: widget.hpp:47
std::function< void(widget &dispatcher, const ui_event event, bool &handled, bool &halt, const SDL_Keycode key, const SDL_Keymod modifier, const std::string &unicode)> signal_keyboard_function
Callback function signature.
Definition: dispatcher.hpp:78
void capture_mouse(dispatcher *dispatcher)
Captures the mouse.
Definition: handler.cpp:926
std::function< void(widget &dispatcher, const ui_event event, bool &handled, bool &halt, const message &message)> signal_message_function
Callback function signature.
Definition: dispatcher.hpp:128
std::function< void(widget &dispatcher, const ui_event event, bool &handled, bool &halt, const point &coordinate)> signal_mouse_function
Callback function signature.
Definition: dispatcher.hpp:65
static void msg(const char *act, debug_info &i, const char *to="", const char *result="")
Definition: debugger.cpp:109
void connect_signal(const ui_event event, const queue_position position, const T &signal)
Definition: dispatcher.hpp:777
std::enable_if_t< has_key< set_event_message, E >::value > disconnect_signal(const signal_message_function &signal, const queue_position position=back_child)
Disconnect a signal for callback in set_event_message.
Definition: dispatcher.hpp:625
std::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:393
bool has_event(const ui_event event, const event_queue_type event_type)
Definition: dispatcher.cpp:57
Generic file dialog.
Definition: field-fwd.hpp:22
The message callbacks hold a reference to a message.
Definition: message.hpp:45
signal_queue< signal_touch_gesture_function > signal_touch_gesture_queue_
Signal queue for callbacks in set_event_touch.
Definition: dispatcher.hpp:896
void capture_mouse()
Captures the mouse.
Definition: dispatcher.hpp:721
bool get_want_keyboard_input() const
Definition: dispatcher.hpp:749
void connect()
Connects the dispatcher to the event handler.
Definition: dispatcher.cpp:50
signal_queue< signal_touch_motion_function > signal_touch_motion_queue_
Signal queue for callbacks in set_event_touch.
Definition: dispatcher.hpp:893
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:248
std::enable_if_t< has_key< set_event_touch_gesture, E >::value > connect_signal(const signal_touch_gesture_function &signal, const queue_position position=back_child)
Connect a signal for callback in set_event_touch_gesture.
Definition: dispatcher.hpp:525
signal_queue< signal_mouse_function > signal_mouse_queue_
Signal queue for callbacks in set_event_mouse.
Definition: dispatcher.hpp:887
virtual bool is_at(const point &coordinate) const =0
Determines whether the location is inside an active widget.
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:233
std::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:411
bool execute_hotkey(const hotkey::HOTKEY_COMMAND id)
Executes a hotkey.
Definition: dispatcher.cpp:208
std::function< void(widget &dispatcher, hotkey::HOTKEY_COMMAND id)> hotkey_function
Hotkey function handler signature.
Definition: dispatcher.hpp:155
std::enable_if_t< has_key< set_event_touch_motion, E >::value > disconnect_signal(const signal_touch_motion_function &signal, const queue_position position=back_child)
Disconnect a signal for callback in set_event_touch.
Definition: dispatcher.hpp:510
std::enable_if_t< has_key< set_event_mouse, E >::value > disconnect_signal(const signal_mouse_function &signal, const queue_position position=back_child)
Disconnect a signal for callback in set_event_mouse.
Definition: dispatcher.hpp:444
signal_queue< signal_function > signal_queue_
Signal queue for callbacks in set_event.
Definition: dispatcher.hpp:884
signal_queue< signal_message_function > signal_message_queue_
Signal queue for callbacks in set_event_message.
Definition: dispatcher.hpp:902
Helper struct to generate the various event queues.
Definition: dispatcher.hpp:769
void set_mouse_behavior(const mouse_behavior mouse_behavior)
Definition: dispatcher.hpp:734
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:243
std::enable_if_t< has_key< set_event_raw_event, E >::value > disconnect_signal(const signal_raw_event_function &signal, const queue_position position=back_child)
Disconnect a signal for callback in set_raw_event.
Definition: dispatcher.hpp:658
std::function< void(widget &dispatcher, const ui_event event, bool &handled, bool &halt, const point &pos, const point &distance)> signal_touch_motion_function
Callback function signature.
Definition: dispatcher.hpp:90
std::enable_if_t< has_key< set_event_text_input, E >::value > disconnect_signal(const signal_text_input_function &signal, const queue_position position=back_child)
Disconnect a signal for callback in set_text_input.
Definition: dispatcher.hpp:691
std::map< ui_event, signal_type< T > > queue
Definition: dispatcher.hpp:775
std::enable_if_t< has_key< set_event_touch_gesture, E >::value > disconnect_signal(const signal_touch_gesture_function &signal, const queue_position position=back_child)
Disconnect a signal for callback in set_event_touch.
Definition: dispatcher.hpp:543
std::enable_if_t< has_key< set_event_notification, E >::value > connect_signal(const signal_notification_function &signal, const queue_position position=back_child)
Connect a signal for callback in set_event_notification.
Definition: dispatcher.hpp:561
std::map< hotkey::HOTKEY_COMMAND, hotkey_function > hotkeys_
The registered hotkeys for this dispatcher.
Definition: dispatcher.hpp:914
bool want_keyboard_input_
Does the dispatcher want to receive keyboard input.
Definition: dispatcher.hpp:881
bool connected_
Are we connected to the event handler.
Definition: dispatcher.hpp:911
Holds a 2D point.
Definition: point.hpp:23
signal_queue< signal_raw_event_function > signal_raw_event_queue_
Signal queue for callbacks in set_raw_event.
Definition: dispatcher.hpp:905
std::function< void(widget &dispatcher, const ui_event event, bool &handled, bool &halt, const std::string &text, int32_t current_pos, int32_t select_len)> signal_text_input_function
Callback function signature.
Definition: dispatcher.hpp:152
std::function< void(widget &dispatcher, const ui_event event, bool &handled, bool &halt)> signal_function
Callback function signature.
Definition: dispatcher.hpp:42
queue_position
The position where to add a new callback in the signal handler.
Definition: dispatcher.hpp:365
signal_queue< signal_notification_function > signal_notification_queue_
Signal queue for callbacks in set_event_notification.
Definition: dispatcher.hpp:899
void connect_signal_pre_key_press(dispatcher &dispatcher, const signal_keyboard_function &signal)
Connects the signal for &#39;snooping&#39; on the keypress.
Definition: dispatcher.cpp:228
mouse_behavior
The behavior of the mouse events.
Definition: dispatcher.hpp:714
signal_queue< signal_keyboard_function > signal_keyboard_queue_
Signal queue for callbacks in set_event_keyboard.
Definition: dispatcher.hpp:890
Helper struct to generate the various signal types.
Definition: dispatcher.hpp:756
std::enable_if_t< has_key< set_event_notification, E >::value > disconnect_signal(const signal_notification_function &signal, const queue_position position=back_child)
Disconnect a signal for callback in set_event_notification.
Definition: dispatcher.hpp:584
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:238
void release_mouse(dispatcher *dispatcher)
Releases a captured mouse.
Definition: handler.cpp:933
std::function< void(widget &dispatcher, const ui_event event, bool &handled, bool &halt, const SDL_Event &sdlevent)> signal_raw_event_function
Callback function signature.
Definition: dispatcher.hpp:139
bool fire(const ui_event event, widget &target)
Fires an event which has no extra parameters.
Definition: dispatcher.cpp:130
EXIT_STATUS start(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
void release_mouse()
Releases the mouse capture.
Definition: dispatcher.hpp:727
map_location coordinate
Contains an x and y coordinate used for starting positions in maps.
std::function< void(dispatcher &dispatcher, const ui_event event, bool &handled, bool &halt, const point &center, float dTheta, float dDist, Uint8 numFingers)> signal_touch_gesture_function
Callback function signature.
Definition: dispatcher.hpp:104
void set_want_keyboard_input(const bool want_keyboard_input)
Definition: dispatcher.hpp:744
std::enable_if_t< has_key< set_event_text_input, E >::value > connect_signal(const signal_text_input_function &signal, const queue_position position=back_child)
Connect a signal for callback in set_text_input.
Definition: dispatcher.hpp:673
std::enable_if_t< has_key< set_event_mouse, E >::value > connect_signal(const signal_mouse_function &signal, const queue_position position=back_child)
Connect a signal for callback in set_event_mouse.
Definition: dispatcher.hpp:426
std::function< void(widget &dispatcher, const ui_event event, bool &handled, bool &halt, void *)> signal_notification_function
Callback function signature.
Definition: dispatcher.hpp:117
mouse_behavior mouse_behavior_
The mouse behavior for the dispatcher.
Definition: dispatcher.hpp:869
void disconnect_signal(const ui_event event, const queue_position position, const T &signal)
Definition: dispatcher.hpp:805
std::enable_if_t< has_key< set_event_keyboard, E >::value > disconnect_signal(const signal_keyboard_function &signal, const queue_position position=back_child)
Disconnect a signal for callback in set_event_keyboard.
Definition: dispatcher.hpp:477
ui_event
The event send to the dispatcher.
Definition: handler.hpp:55
void connect_signal_on_draw(dispatcher &dispatcher, const signal_function &signal)
Connects a signal handler for a callback when the widget is drawn.
Definition: dispatcher.cpp:253
boost::mpl::has_key< K, boost::mpl::int_< E > > has_key
Definition: dispatcher.hpp:40