The Battle for Wesnoth  1.15.0-dev
distributor.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 
17 /**
18  * @file
19  * Contains the event distributor.
20  *
21  * The event distributor exists of several classes which are combined in one
22  * templated distributor class. The classes are closely tight together.
23  *
24  * All classes have direct access to each others members since they should act
25  * as one. (Since the buttons are a templated subclass it's not possible to use
26  * private subclasses.)
27  *
28  * The mouse_motion class handles the mouse motion and holds the owner of us
29  * since all classes virtually inherit us.
30  *
31  * The mouse_button classes are templated classes per mouse button, the
32  * template parameters are used to make the difference between the mouse
33  * buttons. Although it's easily possible to add more mouse buttons in the
34  * code several places only expect a left, middle and right button.
35  *
36  * distributor is the main class to be used in the user code. This class
37  * contains the handling of the keyboard as well.
38  */
39 
42 #include "sdl/point.hpp"
43 #include "video.hpp"
44 
45 #include <string>
46 #include <vector>
47 
48 namespace gui2
49 {
50 
51 class widget;
52 
53 namespace event
54 {
55 
56 /***** ***** ***** ***** mouse_motion ***** ***** ***** ***** *****/
57 
59 {
60 public:
61  mouse_motion(widget& owner, const dispatcher::queue_position queue_position);
62 
63  ~mouse_motion();
64 
65  /**
66  * Captures the mouse input.
67  *
68  * When capturing the widget that has the mouse focus_ does the capturing.
69  *
70  * @param capture Set or release the capturing.
71  */
72  void capture_mouse( // widget* widget);
73  const bool capture = true);
74 
75 protected:
76  /** The widget that currently has the mouse focus_. */
78 
79  /** Did the current widget capture the focus_? */
81 
82  /** The widget that owns us. */
84 
85  /** The timer for the hover event. */
86  std::size_t hover_timer_;
87 
88  /** The widget which should get the hover event. */
90 
91  /** The anchor point of the hover event. */
93 
94  /**
95  * Has the hover been shown for the widget?
96  *
97  * A widget won't get a second hover event after the tooltip has been
98  * triggered. Only after (shortly) entering another widget it will be shown
99  * again for this widget.
100  */
102 
103  /**
104  * Starts the hover timer.
105  *
106  * @param widget The widget that wants the tooltip.
107  * @param coordinate The anchor coordinate.
108  */
110 
111  /** Stops the current hover timer. */
112  void stop_hover_timer();
113 
114  /**
115  * Called when the mouse enters a widget.
116  *
117  * @param mouse_over The widget that should receive the event.
118  */
119  void mouse_enter(widget* mouse_over);
120 
121  /** Called when the mouse leaves the current widget. */
122  void mouse_leave();
123 
124 private:
125  /**
126  * Called when the mouse moves over a widget.
127  *
128  * @param mouse_over The widget that should receive the event.
129  * @param coordinate The current screen coordinate of the mouse.
130  */
131  void mouse_hover(widget* mouse_over, const point& coordinate);
132 
133  /** Called when the mouse wants the widget to show its tooltip. */
134  void show_tooltip();
135 
138  bool& handled,
139  const point& coordinate);
140 
142  bool& handled,
143  const point& coordinate,
144  const point& distance);
145 
146  void signal_handler_sdl_wheel(const event::ui_event event,
147  bool& handled,
148  const point& coordinate);
149 
151  bool& handled,
152  const point& coordinate);
153 };
154 
155 /***** ***** ***** ***** mouse_button ***** ***** ***** ***** *****/
156 
157 /**
158  * Small helper metastruct to specialize mouse_button with and provide ui_event type
159  * aliases without needing to make mouse_button take a million template types.
160  */
161 template<
162  ui_event sdl_button_down,
163  ui_event sdl_button_up,
164  ui_event button_down,
165  ui_event button_up,
166  ui_event button_click,
167  ui_event button_double_click>
169 {
170  static const ui_event sdl_button_down_event = sdl_button_down;
171  static const ui_event sdl_button_up_event = sdl_button_up;
172  static const ui_event button_down_event = button_down;
173  static const ui_event button_up_event = button_up;
174  static const ui_event button_click_event = button_click;
175  static const ui_event button_double_click_event = button_double_click;
176 };
177 
178 template<typename T>
179 class mouse_button : public virtual mouse_motion
180 {
181 public:
182  mouse_button(const std::string& name_,
183  widget& owner,
184  const dispatcher::queue_position queue_position);
185 
186  /**
187  * Initializes the state of the button.
188  *
189  * @param is_down The initial state of the button, if true down
190  * else initialized as up.
191  */
192  void initialize_state(const bool is_down);
193 
194 protected:
195  /** The time of the last click used for double clicking. */
197 
198  /** The widget the last click was on, used for double clicking. */
200 
201  /**
202  * If the mouse isn't captured we need to verify the up is on the same
203  * widget as the down so we send a proper click, also needed to send the
204  * up to the right widget.
205  */
207 
208 private:
209  /** used for debug messages. */
210  const std::string name_;
211 
212  /** Is the button down? */
213  bool is_down_;
214 
216  void signal_handler_sdl_button_down(const event::ui_event event,
217  bool& handled,
218  const point& coordinate);
219 
221  void signal_handler_sdl_button_up(const event::ui_event event,
222  bool& handled,
223  const point& coordinate);
224 
225 
226  void mouse_button_click(widget* widget);
227 };
228 
229 /***** ***** ***** ***** distributor ***** ***** ***** ***** *****/
230 
239  >;
240 
249  >;
250 
259  >;
260 
261 
262 /** The event handler class for the widget library. */
263 class distributor :
264  public mouse_button_left,
265  public mouse_button_middle,
266  public mouse_button_right
267 {
268 public:
269  distributor(widget& owner, const dispatcher::queue_position queue_position);
270 
271  ~distributor();
272 
273  /**
274  * Initializes the state of the keyboard and mouse.
275  *
276  * Needed after initialization and reactivation.
277  */
278  void initialize_state();
279 
280  /**
281  * Captures the keyboard input.
282  *
283  * @param widget The widget which should capture the keyboard.
284  * Sending nullptr releases the capturing.
285  */
286  void keyboard_capture(widget* widget);
287 
288  /**
289  * Adds the widget to the keyboard chain.
290  *
291  * @param widget The widget to add to the chain. The widget
292  * should be valid widget, which hasn't been
293  * added to the chain yet.
294  */
295  void keyboard_add_to_chain(widget* widget);
296 
297  /**
298  * Remove the widget from the keyboard chain.
299  *
300  * @param widget The widget to be removed from the chain.
301  */
302  void keyboard_remove_from_chain(widget* widget);
303 
304  /**
305  * Return the widget currently capturing keyboard input.
306  */
307  widget* keyboard_focus() const;
308 
309 private:
311  {
312  public:
313  virtual void handle_event(const SDL_Event& ) {}
314  virtual void handle_window_event(const SDL_Event& ) {}
315  layer() : video2::draw_layering(false) { }
316  };
317 
318  // make sure the appropriate things happens when we close.
320 
321 #if 0
322  bool hover_pending_; /**< Is there a hover event pending? */
323  unsigned hover_id_; /**< Id of the pending hover event. */
324  SDL_Rect hover_box_; /**< The area the mouse can move in,
325  * moving outside invalidates the
326  * pending hover event.
327  */
328 
329  bool had_hover_; /**< A widget only gets one hover event
330  * per enter cycle.
331  */
332 
333  /** The widget of the currently active tooltip. */
334  widget* tooltip_;
335 
336  /** The widget of the currently active help popup. */
337  widget* help_popup_;
338 #endif
339  /** The widget that holds the keyboard focus_. */
341 
342  /**
343  * Fall back keyboard focus_ items.
344  *
345  * When the focused widget didn't handle the keyboard event (or no handler
346  * for the keyboard focus_) it is send all widgets in this vector. The order
347  * is from rbegin() to rend(). If the keyboard_focus_ is in the vector it
348  * won't get the event twice. The first item added to the vector should be
349  * the window, so it will be the last handler and can dispatch the hotkeys
350  * registered.
351  */
352  std::vector<widget*> keyboard_focus_chain_;
353 
354  /**
355  * Set of functions that handle certain events and sends them to the proper
356  * widget. These functions are called by the SDL event handling functions.
357  */
358 
359  void signal_handler_sdl_key_down(const SDL_Keycode key,
360  const SDL_Keymod modifier,
361  const std::string& unicode);
362 
363  void signal_handler_sdl_text_input(const std::string& unicode, int32_t start, int32_t len);
364  void signal_handler_sdl_text_editing(const std::string& unicode, int32_t start, int32_t len);
365 
366  template<typename Fcn, typename P1, typename P2, typename P3>
367  void signal_handler_keyboard_internal(event::ui_event evt, P1&& p1, P2&& p2, P3&& p3);
368 
369  void signal_handler_notify_removal(dispatcher& widget, const ui_event event);
370 };
371 
372 } // namespace event
373 
374 } // namespace gui2
widget * last_clicked_widget_
The widget the last click was on, used for double clicking.
bool hover_shown_
Has the hover been shown for the widget?
void signal_handler_sdl_touch_motion(const event::ui_event event, bool &handled, const point &coordinate, const point &distance)
std::vector< widget * > keyboard_focus_chain_
Fall back keyboard focus_ items.
A left mouse button down event for a widget.
Definition: handler.hpp:68
Base class for event handling.
Definition: dispatcher.hpp:172
void signal_handler_sdl_wheel(const event::ui_event event, bool &handled, const point &coordinate)
See LEFT_BUTTON_CLICK.
Definition: handler.hpp:84
An SDL left mouse button down event.
Definition: handler.hpp:66
Base class for all widgets.
Definition: widget.hpp:47
See LEFT_BUTTON_DOUBLE_CLICK.
Definition: handler.hpp:85
See LEFT_BUTTON_CLICK.
Definition: handler.hpp:77
An SDL right mouse button down event.
Definition: handler.hpp:80
See LEFT_BUTTON_DOWN.
Definition: handler.hpp:75
-file util.hpp
See LEFT_BUTTON_UP.
Definition: handler.hpp:83
widget * focus_
If the mouse isn&#39;t captured we need to verify the up is on the same widget as the down so we send a p...
void mouse_hover(widget *mouse_over, const point &coordinate)
Called when the mouse moves over a widget.
Generic file dialog.
Definition: field-fwd.hpp:22
void signal_handler_show_helptip(const event::ui_event event, bool &handled, const point &coordinate)
const std::string name_
used for debug messages.
The event handler class for the widget library.
uint32_t last_click_stamp_
The time of the last click used for double clicking.
widget & owner_
The widget that owns us.
Definition: distributor.hpp:83
A left mouse button up event for a widget.
Definition: handler.hpp:69
widget * keyboard_focus_
The widget that holds the keyboard focus_.
An SDL middle mouse button down event.
Definition: handler.hpp:73
virtual void handle_window_event(const SDL_Event &)
void start_hover_timer(widget *widget, const point &coordinate)
Starts the hover timer.
point hover_position_
The anchor point of the hover event.
Definition: distributor.hpp:92
An SDL middle mouse button up event.
Definition: handler.hpp:74
Definition: video.cpp:45
void mouse_enter(widget *mouse_over)
Called when the mouse enters a widget.
void capture_mouse(const bool capture=true)
Captures the mouse input.
widget * mouse_focus_
The widget that currently has the mouse focus_.
Definition: distributor.hpp:77
A left mouse button double click event for a widget.
Definition: handler.hpp:71
std::size_t hover_timer_
The timer for the hover event.
Definition: distributor.hpp:86
Holds a 2D point.
Definition: point.hpp:23
void mouse_leave()
Called when the mouse leaves the current widget.
virtual void handle_event(const SDL_Event &)
void signal_handler_sdl_mouse_motion(const event::ui_event event, bool &handled, const point &coordinate)
queue_position
The position where to add a new callback in the signal handler.
Definition: dispatcher.hpp:365
bool mouse_captured_
Did the current widget capture the focus_?
Definition: distributor.hpp:80
An SDL left mouse button up event.
Definition: handler.hpp:67
mouse_motion(widget &owner, const dispatcher::queue_position queue_position)
void stop_hover_timer()
Stops the current hover timer.
void show_tooltip()
Called when the mouse wants the widget to show its tooltip.
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
widget * hover_widget_
The widget which should get the hover event.
Definition: distributor.hpp:89
See LEFT_BUTTON_DOWN.
Definition: handler.hpp:82
map_location coordinate
Contains an x and y coordinate used for starting positions in maps.
An SDL right mouse button up event.
Definition: handler.hpp:81
Small helper metastruct to specialize mouse_button with and provide ui_event type aliases without nee...
See LEFT_BUTTON_DOUBLE_CLICK.
Definition: handler.hpp:78
bool is_down_
Is the button down?
A left mouse button click event for a widget.
Definition: handler.hpp:70
See LEFT_BUTTON_UP.
Definition: handler.hpp:76
ui_event
The event send to the dispatcher.
Definition: handler.hpp:55