GUI2: refactor dispatcher to remove need for helper structs in fire()
This commit is contained in:
parent
d405ec1c9d
commit
f095ada2f5
2 changed files with 40 additions and 178 deletions
|
@ -16,6 +16,7 @@
|
|||
|
||||
#include "gui/core/event/dispatcher_private.hpp"
|
||||
|
||||
#include "gui/core/event/message.hpp"
|
||||
#include "gui/core/log.hpp"
|
||||
|
||||
namespace gui2
|
||||
|
@ -114,98 +115,33 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper struct to wrap the functor call.
|
||||
*
|
||||
* The template function @ref fire_event needs to call a functor with extra
|
||||
* parameter. In order to facilitate this we send the parameter in the
|
||||
* constructor of the class and let operator() call the functor with the
|
||||
* default parameters and the stored parameters. This allows the core part of
|
||||
* @ref dispatcher::fire to be generic.
|
||||
*/
|
||||
class trigger
|
||||
{
|
||||
public:
|
||||
void operator()(signal_function functor, dispatcher& dispatcher,
|
||||
const ui_event event, bool& handled, bool& halt) const
|
||||
{
|
||||
functor(dispatcher, event, handled, halt);
|
||||
}
|
||||
};
|
||||
|
||||
bool dispatcher::fire(const ui_event event, widget& target)
|
||||
{
|
||||
assert(find<set_event>(event, event_in_set()));
|
||||
switch(event) {
|
||||
case LEFT_BUTTON_DOUBLE_CLICK:
|
||||
return fire_event_double_click<LEFT_BUTTON_CLICK, LEFT_BUTTON_DOUBLE_CLICK,
|
||||
&event_executor::wants_mouse_left_double_click, signal_function>(
|
||||
dynamic_cast<widget*>(this), &target, trigger());
|
||||
&event_executor::wants_mouse_left_double_click, signal_function>(this, &target);
|
||||
|
||||
case MIDDLE_BUTTON_DOUBLE_CLICK:
|
||||
return fire_event_double_click<MIDDLE_BUTTON_CLICK, MIDDLE_BUTTON_DOUBLE_CLICK,
|
||||
&event_executor::wants_mouse_middle_double_click, signal_function>(
|
||||
dynamic_cast<widget*>(this), &target, trigger());
|
||||
&event_executor::wants_mouse_middle_double_click, signal_function>(this, &target);
|
||||
|
||||
case RIGHT_BUTTON_DOUBLE_CLICK:
|
||||
return fire_event_double_click<RIGHT_BUTTON_CLICK, RIGHT_BUTTON_DOUBLE_CLICK,
|
||||
&event_executor::wants_mouse_right_double_click, signal_function>(
|
||||
dynamic_cast<widget*>(this), &target, trigger());
|
||||
&event_executor::wants_mouse_right_double_click, signal_function>(this, &target);
|
||||
|
||||
default:
|
||||
return fire_event<signal_function>(event, dynamic_cast<widget*>(this), &target, trigger());
|
||||
return fire_event<signal_function>(event, this, &target);
|
||||
}
|
||||
}
|
||||
|
||||
/** Helper struct to wrap the functor call. */
|
||||
class trigger_mouse
|
||||
{
|
||||
public:
|
||||
explicit trigger_mouse(const point& coordinate)
|
||||
: coordinate_(coordinate)
|
||||
{
|
||||
}
|
||||
|
||||
void operator()(signal_mouse_function functor, dispatcher& dispatcher,
|
||||
const ui_event event, bool& handled, bool& halt)
|
||||
{
|
||||
functor(dispatcher, event, handled, halt, coordinate_);
|
||||
}
|
||||
|
||||
private:
|
||||
point coordinate_;
|
||||
};
|
||||
|
||||
bool dispatcher::fire(const ui_event event, widget& target, const point& coordinate)
|
||||
{
|
||||
assert(find<set_event_mouse>(event, event_in_set()));
|
||||
return fire_event<signal_mouse_function>(
|
||||
event, dynamic_cast<widget*>(this), &target, trigger_mouse(coordinate));
|
||||
return fire_event<signal_mouse_function>(event, this, &target, coordinate);
|
||||
}
|
||||
|
||||
/** Helper struct to wrap the functor call. */
|
||||
class trigger_keyboard
|
||||
{
|
||||
public:
|
||||
trigger_keyboard(const SDL_Keycode key, const SDL_Keymod modifier, const utf8::string& unicode)
|
||||
: key_(key)
|
||||
, modifier_(modifier)
|
||||
, unicode_(unicode)
|
||||
{
|
||||
}
|
||||
|
||||
void operator()(signal_keyboard_function functor, dispatcher& dispatcher,
|
||||
const ui_event event, bool& handled, bool& halt)
|
||||
{
|
||||
functor(dispatcher, event, handled, halt, key_, modifier_, unicode_);
|
||||
}
|
||||
|
||||
private:
|
||||
SDL_Keycode key_;
|
||||
SDL_Keymod modifier_;
|
||||
utf8::string unicode_;
|
||||
};
|
||||
|
||||
bool dispatcher::fire(const ui_event event,
|
||||
widget& target,
|
||||
const SDL_Keycode key,
|
||||
|
@ -213,109 +149,33 @@ bool dispatcher::fire(const ui_event event,
|
|||
const utf8::string& unicode)
|
||||
{
|
||||
assert(find<set_event_keyboard>(event, event_in_set()));
|
||||
return fire_event<signal_keyboard_function>(
|
||||
event, dynamic_cast<widget*>(this), &target, trigger_keyboard(key, modifier, unicode));
|
||||
return fire_event<signal_keyboard_function>(event, this, &target, key, modifier, unicode);
|
||||
}
|
||||
|
||||
/** Helper struct to wrap the functor call. */
|
||||
class trigger_raw_event
|
||||
{
|
||||
public:
|
||||
trigger_raw_event(const SDL_Event& sdlevent)
|
||||
: sdl_event_(sdlevent)
|
||||
{
|
||||
}
|
||||
|
||||
void operator()(signal_raw_event_function functor, dispatcher& dispatcher,
|
||||
const ui_event event, bool& handled, bool& halt)
|
||||
{
|
||||
functor(dispatcher, event, handled, halt, sdl_event_);
|
||||
}
|
||||
|
||||
private:
|
||||
const SDL_Event& sdl_event_;
|
||||
};
|
||||
|
||||
bool dispatcher::fire(const ui_event event, widget& target, const SDL_Event& sdlevent)
|
||||
{
|
||||
assert(find<set_event_raw_event>(event, event_in_set()));
|
||||
return fire_event<signal_raw_event_function>(
|
||||
event, dynamic_cast<widget*>(this), &target, trigger_raw_event(sdlevent));
|
||||
return fire_event<signal_raw_event_function>(event, this, &target, sdlevent);
|
||||
}
|
||||
|
||||
/** Helper struct to wrap the functor call. */
|
||||
class trigger_touch
|
||||
{
|
||||
public:
|
||||
trigger_touch(const point& pos, const point& distance)
|
||||
: pos_(pos)
|
||||
, distance_(distance)
|
||||
{
|
||||
}
|
||||
|
||||
void operator()(signal_touch_function functor, dispatcher& dispatcher,
|
||||
const ui_event event, bool& handled, bool& halt)
|
||||
{
|
||||
functor(dispatcher, event, handled, halt, pos_, distance_);
|
||||
}
|
||||
|
||||
private:
|
||||
point pos_;
|
||||
point distance_;
|
||||
};
|
||||
|
||||
bool dispatcher::fire(const ui_event event, widget& target, const point& pos, const point& distance)
|
||||
{
|
||||
assert(find<set_event_touch>(event, event_in_set()));
|
||||
return fire_event<signal_touch_function>(
|
||||
event, dynamic_cast<widget*>(this), &target, trigger_touch(pos, distance));
|
||||
return fire_event<signal_touch_function>(event, this, &target, pos, distance);
|
||||
}
|
||||
|
||||
/** Helper struct to wrap the functor call. */
|
||||
class trigger_notification
|
||||
{
|
||||
public:
|
||||
void operator()(signal_notification_function functor,
|
||||
dispatcher& dispatcher,
|
||||
const ui_event event,
|
||||
bool& handled,
|
||||
bool& halt) const
|
||||
{
|
||||
functor(dispatcher, event, handled, halt, nullptr);
|
||||
}
|
||||
};
|
||||
|
||||
bool dispatcher::fire(const ui_event event, widget& target, void*)
|
||||
{
|
||||
assert(find<set_event_notification>(event, event_in_set()));
|
||||
return fire_event<signal_notification_function>(
|
||||
event, dynamic_cast<widget*>(this), &target, trigger_notification());
|
||||
return fire_event<signal_notification_function>(event, this, &target, nullptr);
|
||||
}
|
||||
|
||||
/** Helper struct to wrap the functor call. */
|
||||
class trigger_message
|
||||
{
|
||||
public:
|
||||
explicit trigger_message(message& msg)
|
||||
: message_(msg)
|
||||
{
|
||||
}
|
||||
|
||||
void operator()(signal_message_function functor, dispatcher& dispatcher,
|
||||
const ui_event event, bool& handled, bool& halt)
|
||||
{
|
||||
functor(dispatcher, event, handled, halt, message_);
|
||||
}
|
||||
|
||||
private:
|
||||
message& message_;
|
||||
};
|
||||
|
||||
// TODO: is there any reason msg isn't a const reference?
|
||||
bool dispatcher::fire(const ui_event event, widget& target, message& msg)
|
||||
{
|
||||
assert(find<set_event_message>(event, event_in_set()));
|
||||
return fire_event<signal_message_function>(
|
||||
event, dynamic_cast<widget*>(this), &target, trigger_message(msg));
|
||||
// NOTE: std::ref() needed here to prevent reference decay.
|
||||
return fire_event<signal_message_function>(event, this, &target, std::ref(msg));
|
||||
}
|
||||
|
||||
void dispatcher::register_hotkey(const hotkey::HOTKEY_COMMAND id, const thotkey_function& function)
|
||||
|
|
|
@ -402,12 +402,12 @@ build_event_chain<signal_message_function>(const ui_event event,
|
|||
* This is called with the same parameters as fire_event except for the
|
||||
* event_chain, which contains the widgets with the events to call for them.
|
||||
*/
|
||||
template <class T, class F>
|
||||
template <class T, class... F>
|
||||
inline bool fire_event(const ui_event event,
|
||||
std::vector<std::pair<widget*, ui_event> >& event_chain,
|
||||
widget* dispatcher,
|
||||
widget* w,
|
||||
F functor)
|
||||
F&&... params)
|
||||
{
|
||||
bool handled = false;
|
||||
bool halt = false;
|
||||
|
@ -426,7 +426,7 @@ inline bool fire_event(const ui_event event,
|
|||
itor != signal.pre_child.end();
|
||||
++itor) {
|
||||
|
||||
functor(*itor, *dispatcher, ritor_widget->second, handled, halt);
|
||||
(*itor)(*dispatcher, ritor_widget->second, handled, halt, std::forward<F>(params)...);
|
||||
if(halt) {
|
||||
assert(handled);
|
||||
break;
|
||||
|
@ -448,7 +448,7 @@ inline bool fire_event(const ui_event event,
|
|||
itor != signal.child.end();
|
||||
++itor) {
|
||||
|
||||
functor(*itor, *dispatcher, event, handled, halt);
|
||||
(*itor)(*dispatcher, event, handled, halt, std::forward<F>(params)...);
|
||||
|
||||
if(halt) {
|
||||
assert(handled);
|
||||
|
@ -475,7 +475,7 @@ inline bool fire_event(const ui_event event,
|
|||
itor != signal.post_child.end();
|
||||
++itor) {
|
||||
|
||||
functor(*itor, *dispatcher, itor_widget->second, handled, halt);
|
||||
(*itor)(*dispatcher, itor_widget->second, handled, halt, std::forward<F>(params)...);
|
||||
if(halt) {
|
||||
assert(handled);
|
||||
break;
|
||||
|
@ -500,51 +500,53 @@ inline bool fire_event(const ui_event event,
|
|||
* A helper to allow the common event firing code to be shared between the
|
||||
* different signal function types.
|
||||
*
|
||||
* @pre dispatcher != nullptr
|
||||
* @pre widget != nullptr
|
||||
* @pre d != nullptr
|
||||
* @pre w != nullptr
|
||||
*
|
||||
* @tparam T The signal type of the event to handle.
|
||||
* @tparam F The type of the functor.
|
||||
* @tparam F The paramater pack type.
|
||||
*
|
||||
*
|
||||
* @param event The event to fire.
|
||||
* @param dispatcher The dispatcher that handles the event.
|
||||
* @param widget The widget that should receive the event.
|
||||
* @param functor The functor to execute the actual event.
|
||||
* Since some functions need different
|
||||
* parameters this functor stores them before
|
||||
* firing the event.
|
||||
* @param d The dispatcher that handles the event.
|
||||
* @param w The widget that should receive the event.
|
||||
* @param params Zero or more additional arguments to pass
|
||||
* to the signal function when it's executed.
|
||||
*
|
||||
* @returns Whether or not the event was handled.
|
||||
*/
|
||||
template <class T, class F>
|
||||
template <class T, class... F>
|
||||
inline bool
|
||||
fire_event(const ui_event event, widget* dispatcher, widget* w, F functor)
|
||||
fire_event(const ui_event event, dispatcher* d, widget* w, F&&... params)
|
||||
{
|
||||
assert(dispatcher);
|
||||
assert(d);
|
||||
assert(w);
|
||||
|
||||
widget* dispatcher_w = dynamic_cast<widget*>(d);
|
||||
|
||||
std::vector<std::pair<widget*, ui_event> > event_chain
|
||||
= implementation::build_event_chain<T>(event, dispatcher, w);
|
||||
= implementation::build_event_chain<T>(event, dispatcher_w, w);
|
||||
|
||||
return implementation::fire_event<T>(
|
||||
event, event_chain, dispatcher, w, functor);
|
||||
event, event_chain, dispatcher_w, w, std::forward<F>(params)...);
|
||||
}
|
||||
|
||||
template <ui_event click,
|
||||
ui_event double_click,
|
||||
bool (event_executor::*wants_double_click)() const,
|
||||
class T,
|
||||
class F>
|
||||
class... F>
|
||||
inline bool
|
||||
fire_event_double_click(widget* dispatcher, widget* wgt, F functor)
|
||||
fire_event_double_click(dispatcher* dsp, widget* wgt, F&&... params)
|
||||
{
|
||||
assert(dispatcher);
|
||||
assert(dsp);
|
||||
assert(wgt);
|
||||
|
||||
std::vector<std::pair<widget*, ui_event> > event_chain;
|
||||
widget* w = wgt;
|
||||
while(w != dispatcher) {
|
||||
widget* d = dynamic_cast<widget*>(dsp);
|
||||
|
||||
while(w != d) {
|
||||
w = w->parent();
|
||||
assert(w);
|
||||
|
||||
|
@ -568,10 +570,10 @@ fire_event_double_click(widget* dispatcher, widget* wgt, F functor)
|
|||
|
||||
if((wgt->*wants_double_click)()) {
|
||||
return implementation::fire_event<T>(
|
||||
double_click, event_chain, dispatcher, wgt, functor);
|
||||
double_click, event_chain, d, wgt, std::forward<F>(params)...);
|
||||
} else {
|
||||
return implementation::fire_event<T>(
|
||||
click, event_chain, dispatcher, wgt, functor);
|
||||
click, event_chain, d, wgt, std::forward<F>(params)...);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue