The Battle for Wesnoth  1.15.0-dev
distributor.cpp
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 #define GETTEXT_DOMAIN "wesnoth-lib"
16 
18 
19 #include "events.hpp"
20 #include "gui/core/log.hpp"
21 #include "gui/core/timer.hpp"
22 #include "gui/widgets/settings.hpp"
23 #include "gui/widgets/widget.hpp"
24 #include "gui/widgets/window.hpp"
26 #include "sdl/userevent.hpp"
27 
28 #include "utils/functional.hpp"
29 
30 namespace gui2
31 {
32 
33 namespace event
34 {
35 
36 /**
37  * SDL_AddTimer() callback for the hover event.
38  *
39  * When this callback is called it pushes a new hover event in the event queue.
40  *
41  * @param interval The time parameter of SDL_AddTimer.
42  * @param param Pointer to a widget that's able to show the
43  * tooltip (will be used as a dispatcher).
44  *
45  * @returns The new timer interval, 0 to stop.
46  */
47 
48 #if 0
49 /**
50  * SDL_AddTimer() callback for the popup event.
51  *
52  * This event makes sure the popup is removed again.
53  *
54  * @param interval The time parameter of SDL_AddTimer.
55  * @param param Pointer to parameter structure.
56  *
57  * @returns The new timer interval, 0 to stop.
58  */
59 static uint32_t popup_callback(uint32_t /*interval*/, void* /*param*/)
60 {
61  DBG_GUI_E << "Pushing popup removal event in queue.\n";
62 
63  SDL_Event event;
65 
66  event.type = HOVER_REMOVE_POPUP_EVENT;
67  event.user = data;
68 
69  SDL_PushEvent(&event);
70  return 0;
71 }
72 #endif
73 
74 /**
75  * Small helper to keep a resource (boolean) locked.
76  *
77  * Some of the event handling routines can't be called recursively, this due to
78  * the fact that they are attached to the pre queue and when the forward an
79  * event the pre queue event gets triggered recursively causing infinite
80  * recursion.
81  *
82  * To prevent that those functions check the lock and exit when the lock is
83  * held otherwise grab the lock here.
84  */
86 {
87 public:
88  resource_locker(bool& locked) : locked_(locked)
89  {
90  assert(!locked_);
91  locked_ = true;
92  }
93 
95  {
96  assert(locked_);
97  locked_ = false;
98  }
99 
100 private:
101  bool& locked_;
102 };
103 
104 
105 /***** ***** ***** ***** mouse_motion ***** ***** ***** ***** *****/
106 
107 #define LOG_HEADER "distributor mouse motion [" << owner_.id() << "]: "
108 
110  const dispatcher::queue_position queue_position)
111  : mouse_focus_(nullptr)
112  , mouse_captured_(false)
113  , owner_(owner)
114  , hover_timer_(0)
115  , hover_widget_(nullptr)
116  , hover_position_(0, 0)
117  , hover_shown_(true)
118  , signal_handler_sdl_mouse_motion_entered_(false)
119 {
122  this,
123  _2,
124  _3,
125  _5),
126  queue_position);
127 
130  this,
131  _2,
132  _3,
133  _5,
134  _6),
135  queue_position);
136 
138  &mouse_motion::signal_handler_sdl_wheel, this, _2, _3, _5));
140  &mouse_motion::signal_handler_sdl_wheel, this, _2, _3, _5));
142  &mouse_motion::signal_handler_sdl_wheel, this, _2, _3, _5));
144  &mouse_motion::signal_handler_sdl_wheel, this, _2, _3, _5));
145 
148  this,
149  _2,
150  _3,
151  _5),
152  queue_position);
153 }
154 
156 {
158 }
159 
160 void mouse_motion::capture_mouse(const bool capture)
161 {
162  assert(mouse_focus_);
163  mouse_captured_ = capture;
164 }
165 
167  bool& handled,
168  const point& coordinate)
169 {
171  return;
172  }
174 
175  DBG_GUI_E << LOG_HEADER << event << ".\n";
176 
177  if(mouse_captured_) {
178  assert(mouse_focus_);
179  if(!owner_.fire(event, *mouse_focus_, coordinate)) {
180  mouse_hover(mouse_focus_, coordinate);
181  }
182  } else {
183  widget* mouse_over = owner_.find_at(coordinate, true);
184  while(mouse_over && !mouse_over->can_mouse_focus() && mouse_over->parent()) {
185  mouse_over = mouse_over->parent();
186  }
187  if(mouse_over) {
188  DBG_GUI_E << LOG_HEADER << "Firing: " << event << ".\n";
189  if(owner_.fire(event, *mouse_over, coordinate)) {
190  return;
191  }
192  }
193 
194  if(!mouse_focus_ && mouse_over) {
195  mouse_enter(mouse_over);
196  } else if(mouse_focus_ && !mouse_over) {
197  mouse_leave();
198  } else if(mouse_focus_ && mouse_focus_ == mouse_over) {
199  mouse_hover(mouse_over, coordinate);
200  } else if(mouse_focus_ && mouse_over) {
201  // moved from one widget to the next
202  mouse_leave();
203  mouse_enter(mouse_over);
204  } else {
205  assert(!mouse_focus_ && !mouse_over);
206  }
207  }
208  handled = true;
209 }
210 
212  bool& handled,
213  const point& coordinate,
214  const point& distance)
215 {
216  DBG_GUI_E << LOG_HEADER << event << ".\n";
217 
218  if(mouse_captured_) {
219  assert(mouse_focus_);
220  owner_.fire(event, *mouse_focus_, coordinate, distance);
221  } else {
222  widget* mouse_over = owner_.find_at(coordinate, true);
223  if(mouse_over) {
224  owner_.fire(event, *mouse_over, coordinate, distance);
225  }
226  }
227  handled = true;
228 }
229 
231  bool& handled,
232  const point& coordinate)
233 {
234  DBG_GUI_E << LOG_HEADER << event << ".\n";
235 
236  if(mouse_captured_) {
237  assert(mouse_focus_);
238  owner_.fire(event, *mouse_focus_, coordinate);
239  } else {
240  widget* mouse_over = owner_.find_at(coordinate, true);
241  if(mouse_over) {
242  owner_.fire(event, *mouse_over, coordinate);
243  }
244  }
245  handled = true;
246 }
247 
249  bool& handled,
250  const point& coordinate)
251 {
252  DBG_GUI_E << LOG_HEADER << event << ".\n";
253 
254  if(mouse_captured_) {
255  assert(mouse_focus_);
256  if(owner_.fire(event, *mouse_focus_, coordinate)) {
258  }
259  } else {
260  widget* mouse_over = owner_.find_at(coordinate, true);
261  if(mouse_over) {
262  DBG_GUI_E << LOG_HEADER << "Firing: " << event << ".\n";
263  if(owner_.fire(event, *mouse_over, coordinate)) {
265  }
266  }
267  }
268 
269  handled = true;
270 }
271 
273 {
274  DBG_GUI_E << LOG_HEADER << "Firing: " << event::MOUSE_ENTER << ".\n";
275 
276  assert(mouse_over);
277 
278  mouse_focus_ = mouse_over;
279  owner_.fire(event::MOUSE_ENTER, *mouse_over);
280 
281  hover_shown_ = false;
282  start_hover_timer(mouse_over, get_mouse_position());
283 }
284 
286 {
287  DBG_GUI_E << LOG_HEADER << "Firing: " << event::MOUSE_MOTION << ".\n";
288 
289  assert(mouse_over);
290 
291  owner_.fire(event::MOUSE_MOTION, *mouse_over, coordinate);
292 
293  if(hover_timer_) {
294  if((std::abs(hover_position_.x - coordinate.x) > 5)
295  || (std::abs(hover_position_.y - coordinate.y) > 5)) {
296 
298  start_hover_timer(mouse_over, coordinate);
299  }
300  }
301 }
302 
304 {
305  DBG_GUI_E << LOG_HEADER << "Firing: " << event::SHOW_TOOLTIP << ".\n";
306 
307  if(!hover_widget_) {
308  // See mouse_motion::stop_hover_timer.
309  ERR_GUI_E << LOG_HEADER << event::SHOW_TOOLTIP
310  << " bailing out, no hover widget.\n";
311  return;
312  }
313 
314  /*
315  * Ignore the result of the event, always mark the tooltip as shown. If
316  * there was no handler, there is no reason to assume there will be one
317  * next time.
318  */
320 
321  hover_shown_ = true;
322 
323  hover_timer_ = 0;
324  hover_widget_ = nullptr;
326 }
327 
329 {
330  DBG_GUI_E << LOG_HEADER << "Firing: " << event::MOUSE_LEAVE << ".\n";
331 
332  styled_widget* control = dynamic_cast<styled_widget*>(mouse_focus_);
333  if(!control || control->get_active()) {
334  owner_.fire(event::MOUSE_LEAVE, *mouse_focus_);
335  }
336 
338 
339  mouse_focus_ = nullptr;
340 
342 }
343 
345 {
346  assert(widget);
347 
348 #ifdef __IPHONEOS__
349  // Guessing a crash location in a nasty stack in gui2::execute_timer.
350  // Either this or a long-touch menu.
351  // Remove this when the crash in gui2::execute_timer() and gui2::timer_callback() is gone and try again.
352  return;
353 #endif
354 
356 
357  if(hover_shown_ || !widget->wants_mouse_hover()) {
358  return;
359  }
360 
361  DBG_GUI_E << LOG_HEADER << "Start hover timer for widget '" << widget->id()
362  << "' at address " << widget << ".\n";
363 
365  = add_timer(50, std::bind(&mouse_motion::show_tooltip, this));
366 
367  if(hover_timer_) {
368  hover_widget_ = widget;
370  } else {
371  ERR_GUI_E << LOG_HEADER << "Failed to add hover timer." << std::endl;
372  }
373 }
374 
376 {
377  if(hover_timer_) {
378  assert(hover_widget_);
379  DBG_GUI_E << LOG_HEADER << "Stop hover timer for widget '"
380  << hover_widget_->id() << "' at address " << hover_widget_
381  << ".\n";
382 
383  if(!remove_timer(hover_timer_)) {
384  ERR_GUI_E << LOG_HEADER << "Failed to remove hover timer."
385  << std::endl;
386  }
387 
388  hover_timer_ = 0;
389  hover_widget_ = nullptr;
391  }
392 }
393 
394 /***** ***** ***** ***** mouse_button ***** ***** ***** ***** *****/
395 
396 #undef LOG_HEADER
397 #define LOG_HEADER \
398  "distributor mouse button " << name_ << " [" << owner_.id() << "]: "
399 
400 template<typename T>
401 mouse_button<T>::mouse_button(const std::string& name_, widget& owner,
402  const dispatcher::queue_position queue_position)
403  : mouse_motion(owner, queue_position)
404  , last_click_stamp_(0)
405  , last_clicked_widget_(nullptr)
406  , focus_(nullptr)
407  , name_(name_)
408  , is_down_(false)
409  , signal_handler_sdl_button_down_entered_(false)
410  , signal_handler_sdl_button_up_entered_(false)
411 {
412  owner_.connect_signal<T::sdl_button_down_event>(
414  this,
415  _2,
416  _3,
417  _5),
418  queue_position);
419  owner_.connect_signal<T::sdl_button_up_event>(
421  this,
422  _2,
423  _3,
424  _5),
425  queue_position);
426 }
427 
428 template<typename T>
429 void mouse_button<T>::initialize_state(const bool is_down)
430 {
431  last_click_stamp_ = 0;
432  last_clicked_widget_ = nullptr;
433  focus_ = 0;
434  is_down_ = is_down;
435 }
436 
437 template<typename T>
439  const point& coordinate)
440 {
442  return;
443  }
445 
446  DBG_GUI_E << LOG_HEADER << event << ".\n";
447 
448  if(is_down_) {
449 #ifdef GUI2_SHOW_UNHANDLED_EVENT_WARNINGS
450  WRN_GUI_E << LOG_HEADER << event
451  << ". The mouse button is already down, "
452  << "we missed an event.\n";
453 #endif
454  return;
455  }
456  is_down_ = true;
457 
458  if(mouse_captured_) {
459  assert(mouse_focus_);
461  DBG_GUI_E << LOG_HEADER << "Firing: " << T::sdl_button_down_event << ".\n";
462  if(!owner_.fire(T::sdl_button_down_event, *focus_, coordinate)) {
463  DBG_GUI_E << LOG_HEADER << "Firing: " << T::button_down_event << ".\n";
464  owner_.fire(T::button_down_event, *mouse_focus_);
465  }
466  } else {
467  widget* mouse_over = owner_.find_at(coordinate, true);
468  if(!mouse_over) {
469  return;
470  }
471 
472  if(mouse_over != mouse_focus_) {
473 #ifdef GUI2_SHOW_UNHANDLED_EVENT_WARNINGS
474  WRN_GUI_E << LOG_HEADER << ". Mouse down on non focused widget "
475  << "and mouse not captured, we missed events.\n";
476 #endif
477  mouse_focus_ = mouse_over;
478  }
479 
480  focus_ = mouse_over;
481  DBG_GUI_E << LOG_HEADER << "Firing: " << T::sdl_button_down_event << ".\n";
482  if(!owner_.fire(T::sdl_button_down_event, *focus_, coordinate)) {
483  DBG_GUI_E << LOG_HEADER << "Firing: " << T::button_down_event << ".\n";
484  owner_.fire(T::button_down_event, *focus_);
485  }
486  }
487  handled = true;
488 }
489 
490 template<typename T>
492  const point& coordinate)
493 {
495  return;
496  }
498 
499  DBG_GUI_E << LOG_HEADER << event << ".\n";
500 
501  if(!is_down_) {
502  WRN_GUI_E << LOG_HEADER << event
503  << ". The mouse button is already up, we missed an event.\n";
504  return;
505  }
506  is_down_ = false;
507 
508  if(focus_) {
509  DBG_GUI_E << LOG_HEADER << "Firing: " << T::sdl_button_up_event << ".\n";
510  if(!owner_.fire(T::sdl_button_up_event, *focus_, coordinate)) {
511  DBG_GUI_E << LOG_HEADER << "Firing: " << T::button_up_event << ".\n";
512  owner_.fire(T::button_up_event, *focus_);
513  }
514  }
515 
516  widget* mouse_over = owner_.find_at(coordinate, true);
517  if(mouse_captured_) {
518  const unsigned mask = SDL_BUTTON_LMASK | SDL_BUTTON_MMASK
519  | SDL_BUTTON_RMASK;
520 
521  if((SDL_GetMouseState(nullptr, nullptr) & mask) == 0) {
522  mouse_captured_ = false;
523  }
524 
525  if(mouse_focus_ == mouse_over) {
527  } else if(!mouse_captured_) {
528  mouse_leave();
529 
530  if(mouse_over) {
531  mouse_enter(mouse_over);
532  }
533  }
534  } else if(focus_ && focus_ == mouse_over) {
536  }
537 
538  focus_ = nullptr;
539  handled = true;
540 }
541 
542 template<typename T>
544 {
545  uint32_t stamp = SDL_GetTicks();
547  && last_clicked_widget_ == widget) {
548 
549  DBG_GUI_E << LOG_HEADER << "Firing: " << T::button_double_click_event << ".\n";
550 
551  owner_.fire(T::button_double_click_event, *widget);
552  last_click_stamp_ = 0;
553  last_clicked_widget_ = nullptr;
554 
555  } else {
556 
557  DBG_GUI_E << LOG_HEADER << "Firing: " << T::button_click_event << ".\n";
558  owner_.fire(T::button_click_event, *widget);
559  last_click_stamp_ = stamp;
560  last_clicked_widget_ = widget;
561  }
562 }
563 
564 /***** ***** ***** ***** distributor ***** ***** ***** ***** *****/
565 
566 #undef LOG_HEADER
567 #define LOG_HEADER "distributor mouse motion [" << owner_.id() << "]: "
568 
569 /**
570  * @todo Test whether the state is properly tracked when an input blocker is
571  * used.
572  */
574  const dispatcher::queue_position queue_position)
575  : mouse_motion(owner, queue_position)
576  , mouse_button_left("left", owner, queue_position)
577  , mouse_button_middle("middle", owner, queue_position)
578  , mouse_button_right("right", owner, queue_position)
579 #if 0
580  , hover_pending_(false)
581  , hover_id_(0)
582  , hover_box_()
583  , had_hover_(false)
584  , tooltip_(nullptr)
585  , help_popup_(nullptr)
586 #endif
587  , keyboard_focus_(nullptr)
588  , keyboard_focus_chain_()
589 {
590  if(SDL_WasInit(SDL_INIT_TIMER) == 0) {
591  if(SDL_InitSubSystem(SDL_INIT_TIMER) == -1) {
592  assert(false);
593  }
594  }
595 
597  &distributor::signal_handler_sdl_key_down, this, _5, _6, _7));
598 
600  &distributor::signal_handler_sdl_text_input, this, _5, _6, _7));
601 
604 
607 
609 }
610 
612 {
614  &distributor::signal_handler_sdl_key_down, this, _5, _6, _7));
615 
617  &distributor::signal_handler_sdl_text_input, this, _5, _6, _7));
618 
621 
624 }
625 
627 {
628  const uint8_t button_state = SDL_GetMouseState(nullptr, nullptr);
629 
630  mouse_button_left::initialize_state((button_state & SDL_BUTTON(1)) != 0);
631  mouse_button_middle::initialize_state((button_state & SDL_BUTTON(2)) != 0);
632  mouse_button_right::initialize_state((button_state & SDL_BUTTON(3)) != 0);
633 
635 }
636 
638 {
639  return keyboard_focus_;
640 }
641 
643 {
644  if(keyboard_focus_) {
646  << ".\n";
647 
648  owner_.fire(event::LOSE_KEYBOARD_FOCUS, *keyboard_focus_, nullptr);
649  }
650 
651  keyboard_focus_ = widget;
652 
653  if(keyboard_focus_) {
655  << ".\n";
656 
657  owner_.fire(event::RECEIVE_KEYBOARD_FOCUS, *keyboard_focus_, nullptr);
658  }
659 }
660 
662 {
663  assert(widget);
664  assert(std::find(keyboard_focus_chain_.begin(),
665  keyboard_focus_chain_.end(),
666  widget) == keyboard_focus_chain_.end());
667 
668  keyboard_focus_chain_.push_back(widget);
669 }
670 
672 {
673  assert(w);
676 
677  if(itor != keyboard_focus_chain_.end()) {
678  keyboard_focus_chain_.erase(itor);
679  }
680 }
681 
682 template<typename Fcn, typename P1, typename P2, typename P3>
684 {
685  /** @todo Test whether recursion protection is needed. */
686 
687  DBG_GUI_E << LOG_HEADER << evt << ".\n";
688 
689  if(keyboard_focus_) {
690  // Attempt to cast to styled_widget, to avoid sending events if the
691  // widget is disabled. If the cast fails, we assume the widget
692  // is enabled and ready to receive events.
693  styled_widget* control = dynamic_cast<styled_widget*>(keyboard_focus_);
694  if(!control || control->get_active()) {
695  DBG_GUI_E << LOG_HEADER << "Firing: " << evt
696  << ".\n";
697  if(owner_.fire(evt, *keyboard_focus_, p1, p2, p3)) {
698  return;
699  }
700  }
701  if(text_box_base* tb = dynamic_cast<text_box_base*>(keyboard_focus_)) {
702  if(tb->is_composing()) {
703  return; // Skip the keyboard chain if composition is in progress.
704  }
705  }
706  }
707 
708  for(std::vector<widget*>::reverse_iterator ritor
709  = keyboard_focus_chain_.rbegin();
710  ritor != keyboard_focus_chain_.rend();
711  ++ritor) {
712 
713  if(*ritor == keyboard_focus_) {
714  continue;
715  }
716 
717  if(*ritor == &owner_) {
718  /**
719  * @todo Make sure we're not in the event chain.
720  *
721  * No idea why we're here, but needs to be fixed, otherwise we keep
722  * calling this function recursively upon unhandled events...
723  *
724  * Probably added to make sure the window can grab the events and
725  * handle + block them when needed, this is no longer needed with
726  * the chain.
727  */
728  continue;
729  }
730 
731  // Attempt to cast to styled_widget, to avoid sending events if the
732  // widget is disabled. If the cast fails, we assume the widget
733  // is enabled and ready to receive events.
734  styled_widget* control = dynamic_cast<styled_widget*>(keyboard_focus_);
735  if(control != nullptr && !control->get_active()) {
736  continue;
737  }
738 
739  DBG_GUI_E << LOG_HEADER << "Firing: " << evt << ".\n";
740  if(owner_.fire(evt, **ritor, p1, p2, p3)) {
741 
742  return;
743  }
744  }
745 }
746 
747 void distributor::signal_handler_sdl_key_down(const SDL_Keycode key, const SDL_Keymod modifier, const std::string& unicode)
748 {
749  signal_handler_keyboard_internal<signal_keyboard_function>(event::SDL_KEY_DOWN, key, modifier, unicode);
750 }
751 
752 void distributor::signal_handler_sdl_text_input(const std::string& unicode, int32_t start, int32_t end)
753 {
754  signal_handler_keyboard_internal<signal_text_input_function>(event::SDL_TEXT_INPUT, unicode, start, end);
755 }
756 
757 void distributor::signal_handler_sdl_text_editing(const std::string& unicode, int32_t start, int32_t end)
758 {
759  signal_handler_keyboard_internal<signal_text_input_function>(event::SDL_TEXT_EDITING, unicode, start, end);
760 }
761 
763  const ui_event event)
764 {
765  DBG_GUI_E << LOG_HEADER << event << ".\n";
766 
767  /**
768  * @todo Evaluate whether moving the cleanup parts in the subclasses.
769  *
770  * It might be cleaner to do it that way, but creates extra small
771  * functions...
772  */
773 
774  if(hover_widget_ == &w) {
776  }
777 
780  }
781  if(mouse_button_left::focus_ == &w) {
782  mouse_button_left::focus_ = nullptr;
783  }
784 
787  }
788  if(mouse_button_middle::focus_ == &w) {
789  mouse_button_middle::focus_ = nullptr;
790  }
791 
794  }
795  if(mouse_button_right::focus_ == &w) {
796  mouse_button_right::focus_ = nullptr;
797  }
798 
799  if(mouse_focus_ == &w) {
800  mouse_focus_ = nullptr;
801  }
802 
803  if(keyboard_focus_ == &w) {
804  keyboard_focus_ = nullptr;
805  }
808  keyboard_focus_chain_.end(),
809  &w);
810  if(itor != keyboard_focus_chain_.end()) {
811  keyboard_focus_chain_.erase(itor);
812  }
813 }
814 
815 } // namespace event
816 
817 } // namespace gui2
Define the common log macros for the gui toolkit.
#define ERR_GUI_E
Definition: log.hpp:37
Request the widget to show its hover helptip.
Definition: handler.hpp:113
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?
An SDL text editing (IME) event.
Definition: handler.hpp:93
void mouse_button_click(widget *widget)
void signal_handler_sdl_touch_motion(const event::ui_event event, bool &handled, const point &coordinate, const point &distance)
Abstract base class for text items.
std::vector< widget * > keyboard_focus_chain_
Fall back keyboard focus_ items.
Widget loses keyboard focus.
Definition: handler.hpp:108
unsigned double_click_time
Definition: settings.cpp:36
void signal_handler_sdl_button_down(const event::ui_event event, bool &handled, const point &coordinate)
An SDL wheel right event.
Definition: handler.hpp:88
Base class for event handling.
Definition: dispatcher.hpp:172
void signal_handler_sdl_wheel(const event::ui_event event, bool &handled, const point &coordinate)
virtual bool get_active() const =0
Gets the active state of the styled_widget.
void keyboard_capture(widget *widget)
Captures the keyboard input.
const std::string & id() const
Definition: widget.cpp:107
This file contains the window object, this object is a top level container which has the event manage...
An SDL key down event.
Definition: handler.hpp:91
Base class for all widgets.
Definition: widget.hpp:47
A mouse leave event for a widget.
Definition: handler.hpp:64
void signal_handler_sdl_key_down(const SDL_Keycode key, const SDL_Keymod modifier, const std::string &unicode)
Set of functions that handle certain events and sends them to the proper widget.
bool wants_mouse_hover() const
Contains the event distributor.
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
An SDL wheel down event.
Definition: handler.hpp:90
Widget gains keyboard focus.
Definition: handler.hpp:107
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...
Request the widget to show its hover tooltip.
Definition: handler.hpp:110
void mouse_hover(widget *mouse_over, const point &coordinate)
Called when the mouse moves over a widget.
int x
x coordinate.
Definition: point.hpp:44
void init_mouse_location()
Initializes the location of the mouse.
Definition: handler.cpp:913
Generic file dialog.
Definition: field-fwd.hpp:22
void signal_handler_show_helptip(const event::ui_event event, bool &handled, const point &coordinate)
void initialize_state(const bool is_down)
Initializes the state of the button.
Request the widget to remove its hover tooltip.
Definition: handler.hpp:111
void keyboard_add_to_chain(widget *widget)
Adds the widget to the keyboard chain.
mouse_button(const std::string &name_, widget &owner, const dispatcher::queue_position queue_position)
distributor(widget &owner, const dispatcher::queue_position queue_position)
SDL_AddTimer() callback for the hover event.
Definition: distributor.cpp:85
void signal_handler_keyboard_internal(event::ui_event evt, P1 &&p1, P2 &&p2, P3 &&p3)
This file contains the settings handling of 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
widget * keyboard_focus_
The widget that holds the keyboard focus_.
Sent by a widget to notify others it&#39;s being destroyed.
Definition: handler.hpp:95
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
widget * parent()
Definition: widget.cpp:157
if(win_locale=="af") win_locale
void start_hover_timer(widget *widget, const point &coordinate)
Starts the hover timer.
virtual bool can_mouse_focus() const
Whether the mouse move/click event go &#39;through&#39; this widget.
Definition: widget.hpp:326
point hover_position_
The anchor point of the hover event.
Definition: distributor.hpp:92
An SDL wheel up event.
Definition: handler.hpp:89
void signal_handler_notify_removal(dispatcher &widget, const ui_event event)
void mouse_enter(widget *mouse_over)
Called when the mouse enters a widget.
#define DBG_GUI_E
Definition: log.hpp:34
void capture_mouse(const bool capture=true)
Captures the mouse input.
An SDL wheel left event.
Definition: handler.hpp:87
widget * mouse_focus_
The widget that currently has the mouse focus_.
Definition: distributor.hpp:77
A mouse motion event for a widget.
Definition: handler.hpp:63
#define WRN_GUI_E
Definition: log.hpp:36
std::size_t hover_timer_
The timer for the hover event.
Definition: distributor.hpp:86
A mouse enter event for a widget.
Definition: handler.hpp:62
Contains the gui2 timer routines.
Holds a 2D point.
Definition: point.hpp:23
void mouse_leave()
Called when the mouse leaves the current widget.
std::size_t add_timer(const uint32_t interval, const std::function< void(std::size_t id)> &callback, const bool repeat)
Adds a new timer.
Definition: timer.cpp:126
#define HOVER_REMOVE_POPUP_EVENT
Definition: events.hpp:25
int w
Base class for all visible items.
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
void keyboard_remove_from_chain(widget *widget)
Remove the widget from the keyboard chain.
bool mouse_captured_
Did the current widget capture the focus_?
Definition: distributor.hpp:80
point get_mouse_position()
Returns the current mouse position.
Definition: helper.cpp:116
mouse_motion(widget &owner, const dispatcher::queue_position queue_position)
void stop_hover_timer()
Stops the current hover timer.
bool find(E event, F functor)
Tests whether an event handler is available.
void signal_handler_sdl_button_up(const event::ui_event event, bool &handled, const point &coordinate)
#define LOG_HEADER
void show_tooltip()
Called when the mouse wants the widget to show its tooltip.
An SDL text input (commit) event.
Definition: handler.hpp:92
widget * keyboard_focus() const
Return the widget currently capturing keyboard input.
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
widget * hover_widget_
The widget which should get the hover event.
Definition: distributor.hpp:89
virtual widget * find_at(const point &coordinate, const bool must_be_active)
Returns the widget at the wanted coordinates.
Definition: widget.cpp:570
map_location coordinate
Contains an x and y coordinate used for starting positions in maps.
void signal_handler_sdl_text_editing(const std::string &unicode, int32_t start, int32_t len)
int y
y coordinate.
Definition: point.hpp:47
bool is_down_
Is the button down?
std::string::const_iterator iterator
Definition: tokenizer.hpp:24
void initialize_state()
Initializes the state of the keyboard and mouse.
ui_event
The event send to the dispatcher.
Definition: handler.hpp:55
void signal_handler_sdl_text_input(const std::string &unicode, int32_t start, int32_t len)
bool remove_timer(const std::size_t id)
Removes a timer.
Definition: timer.cpp:167
An SDL mouse motion event.
Definition: handler.hpp:61