The Battle for Wesnoth  1.15.12+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 configure instances of mouse_button.
159  */
161 {
168  /** Bitmask corresponding to this button's bit in SDL_GetMouseState's return value */
169  int32_t mask;
170  /** used for debug messages. */
171  std::string name;
172 };
173 
174 class mouse_button : public virtual mouse_motion
175 {
176 public:
178  widget& owner,
179  const dispatcher::queue_position queue_position);
180 
181  /**
182  * Initializes the state of the button.
183  *
184  * @param button_state The initial state of all buttons, in which the bit corresponding to
185  mouse_button_event_types.mask will be set if the button is down, or unset if it is up.
186  */
187  void initialize_state(int32_t button_state);
188 
189 protected:
190  /** The time of the last click used for double clicking. */
192 
193  /** The widget the last click was on, used for double clicking. */
195 
196  /**
197  * If the mouse isn't captured we need to verify the up is on the same
198  * widget as the down so we send a proper click, also needed to send the
199  * up to the right widget.
200  */
202 
203 private:
204  /** Which set of SDL events correspond to this button. */
206 
207  /** Is the button down? */
208  bool is_down_;
209 
211  void signal_handler_sdl_button_down(const event::ui_event event,
212  bool& handled,
213  const point& coordinate);
214 
216  void signal_handler_sdl_button_up(const event::ui_event event,
217  bool& handled,
218  const point& coordinate);
219 
220 
221  void mouse_button_click(widget* widget);
222 };
223 
224 /**
225  * Three subclasses of mouse_button, so that the distributor class can inherit from them;
226  * C++ doesn't allow multiple inheritance to directly use more than one instance of a
227  * superclass.
228  *
229  * It's a diamond inheritance, as all of these have virtual base class mouse_motion;
230  * refactoring that would allow these multiple classes to be replaced with a simple
231  * (distributor has-a std::array<mouse_button, 3>) relationship.
232  */
234 {
236  widget& owner,
237  const dispatcher::queue_position queue_position)
238  : mouse_motion(owner, queue_position)
239  , mouse_button(events, owner, queue_position)
240  {
241  }
242 };
244 {
246  widget& owner,
247  const dispatcher::queue_position queue_position)
248  : mouse_motion(owner, queue_position)
249  , mouse_button(events, owner, queue_position)
250  {
251  }
252 };
254 {
256  widget& owner,
257  const dispatcher::queue_position queue_position)
258  : mouse_motion(owner, queue_position)
259  , mouse_button(events, owner, queue_position)
260  {
261  }
262 };
263 
264 /***** ***** ***** ***** distributor ***** ***** ***** ***** *****/
265 
266 
267 /** The event handler class for the widget library. */
268 class distributor :
269  public mouse_button_left,
270  public mouse_button_middle,
271  public mouse_button_right
272 {
273 public:
274  distributor(widget& owner, const dispatcher::queue_position queue_position);
275 
276  ~distributor();
277 
278  /**
279  * Initializes the state of the keyboard and mouse.
280  *
281  * Needed after initialization and reactivation.
282  */
283  void initialize_state();
284 
285  /**
286  * Captures the keyboard input.
287  *
288  * @param widget The widget which should capture the keyboard.
289  * Sending nullptr releases the capturing.
290  */
291  void keyboard_capture(widget* widget);
292 
293  /**
294  * Adds the widget to the keyboard chain.
295  *
296  * @param widget The widget to add to the chain. The widget
297  * should be valid widget, which hasn't been
298  * added to the chain yet.
299  */
300  void keyboard_add_to_chain(widget* widget);
301 
302  /**
303  * Remove the widget from the keyboard chain.
304  *
305  * @param widget The widget to be removed from the chain.
306  */
307  void keyboard_remove_from_chain(widget* widget);
308 
309  /**
310  * Return the widget currently capturing keyboard input.
311  */
312  widget* keyboard_focus() const;
313 
314 private:
316  {
317  public:
318  virtual void handle_event(const SDL_Event& ) {}
319  virtual void handle_window_event(const SDL_Event& ) {}
320  layer() : video2::draw_layering(false) { }
321  };
322 
323  // make sure the appropriate things happens when we close.
325 
326  /** The widget that holds the keyboard focus_. */
328 
329  /**
330  * Fall back keyboard focus_ items.
331  *
332  * When the focused widget didn't handle the keyboard event (or no handler
333  * for the keyboard focus_) it is send all widgets in this vector. The order
334  * is from rbegin() to rend(). If the keyboard_focus_ is in the vector it
335  * won't get the event twice. The first item added to the vector should be
336  * the window, so it will be the last handler and can dispatch the hotkeys
337  * registered.
338  */
339  std::vector<widget*> keyboard_focus_chain_;
340 
341  /**
342  * Set of functions that handle certain events and sends them to the proper
343  * widget. These functions are called by the SDL event handling functions.
344  */
345 
346  void signal_handler_sdl_key_down(const SDL_Keycode key,
347  const SDL_Keymod modifier,
348  const std::string& unicode);
349 
350  void signal_handler_sdl_text_input(const std::string& unicode, int32_t start, int32_t len);
351  void signal_handler_sdl_text_editing(const std::string& unicode, int32_t start, int32_t len);
352 
353  template<typename Fcn, typename P1, typename P2, typename P3>
354  void signal_handler_keyboard_internal(event::ui_event evt, P1&& p1, P2&& p2, P3&& p3);
355 
356  void signal_handler_notify_removal(dispatcher& widget, const ui_event event);
357 };
358 
359 } // namespace event
360 
361 } // namespace gui2
uint32_t last_click_stamp_
The time of the last click used for double clicking.
bool hover_shown_
Has the hover been shown for the widget?
mouse_button_middle(const mouse_button_event_types &events, widget &owner, const dispatcher::queue_position queue_position)
Three subclasses of mouse_button, so that the distributor class can inherit from them; C++ doesn&#39;t al...
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.
Base class for event handling.
Definition: dispatcher.hpp:306
void signal_handler_sdl_wheel(const event::ui_event event, bool &handled, const point &coordinate)
Base class for all widgets.
Definition: widget.hpp:49
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...
mouse_button_left(const mouse_button_event_types &events, widget &owner, const dispatcher::queue_position queue_position)
mouse_button_right(const mouse_button_event_types &events, widget &owner, const dispatcher::queue_position queue_position)
widget * last_clicked_widget_
The widget the last click was on, used for double clicking.
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)
The event handler class for the widget library.
bool is_down_
Is the button down?
int32_t mask
Bitmask corresponding to this button&#39;s bit in SDL_GetMouseState&#39;s return value.
widget & owner_
The widget that owns us.
Definition: distributor.hpp:83
widget * keyboard_focus_
The widget that holds the keyboard focus_.
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
const mouse_button_event_types events_
Which set of SDL events correspond to this button.
Definition: video.cpp:50
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
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:477
Handling of system events.
Definition: manager.hpp:42
bool mouse_captured_
Did the current widget capture the focus_?
Definition: distributor.hpp:80
mouse_motion(widget &owner, const dispatcher::queue_position queue_position)
Definition: distributor.cpp:71
void stop_hover_timer()
Stops the current hover timer.
void show_tooltip()
Called when the mouse wants the widget to show its tooltip.
Small helper metastruct to configure instances of mouse_button.
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
map_location coordinate
Contains an x and y coordinate used for starting positions in maps.
std::string name
used for debug messages.
ui_event
The event send to the dispatcher.
Definition: handler.hpp:47