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 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 #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 
141  void signal_handler_sdl_wheel(const event::ui_event event,
142  bool& handled,
143  const point& coordinate);
144 
146  bool& handled,
147  const point& coordinate);
148 };
149 
150 /***** ***** ***** ***** mouse_button ***** ***** ***** ***** *****/
151 
152 /**
153  * Small helper metastruct to specialize mouse_button with and provide ui_event type
154  * aliases without needing to make mouse_button take a million template types.
155  */
156 template<
157  ui_event sdl_button_down,
158  ui_event sdl_button_up,
159  ui_event button_down,
160  ui_event button_up,
161  ui_event button_click,
162  ui_event button_double_click>
164 {
165  static const ui_event sdl_button_down_event = sdl_button_down;
166  static const ui_event sdl_button_up_event = sdl_button_up;
167  static const ui_event button_down_event = button_down;
168  static const ui_event button_up_event = button_up;
169  static const ui_event button_click_event = button_click;
170  static const ui_event button_double_click_event = button_double_click;
171 };
172 
173 template<typename T>
174 class mouse_button : public virtual mouse_motion
175 {
176 public:
177  mouse_button(const std::string& name_,
178  widget& owner,
179  const dispatcher::queue_position queue_position);
180 
181  /**
182  * Initializes the state of the button.
183  *
184  * @param is_down The initial state of the button, if true down
185  * else initialized as up.
186  */
187  void initialize_state(const bool is_down);
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  /** used for debug messages. */
205  const std::string name_;
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 /***** ***** ***** ***** distributor ***** ***** ***** ***** *****/
225 
234  >;
235 
244  >;
245 
254  >;
255 
256 
257 /** The event handler class for the widget library. */
258 class distributor :
259  public mouse_button_left,
260  public mouse_button_middle,
261  public mouse_button_right
262 {
263 public:
264  distributor(widget& owner, const dispatcher::queue_position queue_position);
265 
266  ~distributor();
267 
268  /**
269  * Initializes the state of the keyboard and mouse.
270  *
271  * Needed after initialization and reactivation.
272  */
273  void initialize_state();
274 
275  /**
276  * Captures the keyboard input.
277  *
278  * @param widget The widget which should capture the keyboard.
279  * Sending nullptr releases the capturing.
280  */
281  void keyboard_capture(widget* widget);
282 
283  /**
284  * Adds the widget to the keyboard chain.
285  *
286  * @param widget The widget to add to the chain. The widget
287  * should be valid widget, which hasn't been
288  * added to the chain yet.
289  */
290  void keyboard_add_to_chain(widget* widget);
291 
292  /**
293  * Remove the widget from the keyboard chain.
294  *
295  * @param widget The widget to be removed from the chain.
296  */
297  void keyboard_remove_from_chain(widget* widget);
298 
299  /**
300  * Return the widget currently capturing keyboard input.
301  */
302  widget* keyboard_focus() const;
303 
304 private:
305 #if 0
306  class layer : public video2::draw_layering
307  {
308  public:
309  virtual void handle_event(const SDL_Event& ) {}
310  virtual void handle_window_event(const SDL_Event& ) {}
311  layer() : video2::draw_layering(false) { }
312  };
313 
314  // make sure the appropriate things happens when we close.
315  layer layer_;
316 
317  bool hover_pending_; /**< Is there a hover event pending? */
318  unsigned hover_id_; /**< Id of the pending hover event. */
319  SDL_Rect hover_box_; /**< The area the mouse can move in,
320  * moving outside invalidates the
321  * pending hover event.
322  */
323 
324  bool had_hover_; /**< A widget only gets one hover event
325  * per enter cycle.
326  */
327 
328  /** The widget of the currently active tooltip. */
329  widget* tooltip_;
330 
331  /** The widget of the currently active help popup. */
332  widget* help_popup_;
333 #endif
334  /** The widget that holds the keyboard focus_. */
336 
337  /**
338  * Fall back keyboard focus_ items.
339  *
340  * When the focused widget didn't handle the keyboard event (or no handler
341  * for the keyboard focus_) it is send all widgets in this vector. The order
342  * is from rbegin() to rend(). If the keyboard_focus_ is in the vector it
343  * won't get the event twice. The first item added to the vector should be
344  * the window, so it will be the last handler and can dispatch the hotkeys
345  * registered.
346  */
347  std::vector<widget*> keyboard_focus_chain_;
348 
349  /**
350  * Set of functions that handle certain events and sends them to the proper
351  * widget. These functions are called by the SDL event handling functions.
352  */
353 
354  void signal_handler_sdl_key_down(const SDL_Keycode key,
355  const SDL_Keymod modifier,
356  const std::string& unicode);
357 
358  void signal_handler_sdl_text_input(const std::string& unicode, int32_t start, int32_t len);
359  void signal_handler_sdl_text_editing(const std::string& unicode, int32_t start, int32_t len);
360 
361  template<typename Fcn, typename P1, typename P2, typename P3>
362  void signal_handler_keyboard_internal(event::ui_event evt, P1&& p1, P2&& p2, P3&& p3);
363 
364  void signal_handler_notify_removal(dispatcher& widget, const ui_event event);
365 };
366 
367 } // namespace event
368 
369 } // 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?
std::vector< widget * > keyboard_focus_chain_
Fall back keyboard focus_ items.
A left mouse button down event for a widget.
Definition: handler.hpp:60
Base class for event handling.
Definition: dispatcher.hpp:281
void signal_handler_sdl_wheel(const event::ui_event event, bool &handled, const point &coordinate)
See LEFT_BUTTON_CLICK.
Definition: handler.hpp:76
An SDL left mouse button down event.
Definition: handler.hpp:58
Base class for all widgets.
Definition: widget.hpp:48
See LEFT_BUTTON_DOUBLE_CLICK.
Definition: handler.hpp:77
See LEFT_BUTTON_CLICK.
Definition: handler.hpp:69
An SDL right mouse button down event.
Definition: handler.hpp:72
See LEFT_BUTTON_DOWN.
Definition: handler.hpp:67
-file util.hpp
See LEFT_BUTTON_UP.
Definition: handler.hpp:75
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:61
widget * keyboard_focus_
The widget that holds the keyboard focus_.
An SDL middle mouse button down event.
Definition: handler.hpp:65
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:66
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:63
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.
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:455
bool mouse_captured_
Did the current widget capture the focus_?
Definition: distributor.hpp:80
An SDL left mouse button up event.
Definition: handler.hpp:59
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:74
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:73
Small helper metastruct to specialize mouse_button with and provide ui_event type aliases without nee...
See LEFT_BUTTON_DOUBLE_CLICK.
Definition: handler.hpp:70
bool is_down_
Is the button down?
A left mouse button click event for a widget.
Definition: handler.hpp:62
See LEFT_BUTTON_UP.
Definition: handler.hpp:68
ui_event
The event send to the dispatcher.
Definition: handler.hpp:47