From ae353c5a46d7081d00e6625426918f973c8d51d7 Mon Sep 17 00:00:00 2001 From: Charles Dang Date: Mon, 18 Jan 2021 00:06:45 +1100 Subject: [PATCH] GUI2/Dispatcher: refactored [dis]connect_signal to use constexpr-if rather than SFINAE --- src/gui/core/event/dispatcher.hpp | 342 ++++++------------------------ 1 file changed, 65 insertions(+), 277 deletions(-) diff --git a/src/gui/core/event/dispatcher.hpp b/src/gui/core/event/dispatcher.hpp index a6d9e855586f..fc755fa4da80 100644 --- a/src/gui/core/event/dispatcher.hpp +++ b/src/gui/core/event/dispatcher.hpp @@ -483,310 +483,98 @@ class dispatcher back_post_child }; - /** - * Connect a signal for callback in set_event. - * - * The function uses some enable_if magic to avoid registering the wrong - * function, but the common way to use this function is: - * widget->connect_signal( - * std::bind(&tmy_dialog::my_member, this)); - * This allows simply adding a member of a dialog to be used as a callback - * for widget without a lot of magic. Note most widgets probably will get a - * callback like - * connect_signal_mouse_left_click(const signal_function& callback) - * which hides this function for the average use. - * - * @tparam E The event the callback needs to react to. - * @param signal The callback function. - * @param position The position to place the callback. - */ - template - std::enable_if_t - connect_signal(const signal_function& signal, const queue_position position = back_child) - { - signal_queue_.connect_signal(E, position, signal); - } - - /** - * Disconnect a signal for callback in set_event. - * - * @tparam E The event the callback was used for. - * @param signal The callback function. - * @param position The place where the function was added. - * Needed remove the event from the right - * place. (The function doesn't care whether - * was added in front or back.) - */ - template - std::enable_if_t - disconnect_signal(const signal_function& signal, const queue_position position = back_child) - { - signal_queue_.disconnect_signal(E, position, signal); - } - - /** - * Connect a signal for callback in set_event_mouse. - * - * @tparam E The event the callback needs to react to. - * @param signal The callback function. - * @param position The position to place the callback. - */ - template - std::enable_if_t - connect_signal(const signal_mouse_function& signal, const queue_position position = back_child) - { - signal_mouse_queue_.connect_signal(E, position, signal); - } +/** Helper macro to wrap the result of a macro concatnation in a string. */ +#define STR(RES) #RES - /** - * Disconnect a signal for callback in set_event_mouse. - * - * @tparam E The event the callback was used for. - * @param signal The callback function. - * @param position The place where the function was added. - * Needed remove the event from the right - * place. (The function doesn't care whether - * was added in front or back.) - */ - template - std::enable_if_t - disconnect_signal(const signal_mouse_function& signal, const queue_position position = back_child) - { - signal_mouse_queue_.disconnect_signal(E, position, signal); - } +#define VALIDATE_AND_ADD_TO_QUEUE(QUEUE) \ + static_assert(std::is_convertible_v, \ + "connect_signal: function signature does not match " STR(QUEUE##_function)); \ + QUEUE##_queue_.connect_signal(E, position, func); /** - * Connect a signal for callback in set_event_keyboard. + * Adds a callback to the appropriate queue based on event type. * * @tparam E The event the callback needs to react to. - * @param signal The callback function. - * @param position The position to place the callback. - */ - template - std::enable_if_t - connect_signal(const signal_keyboard_function& signal, const queue_position position = back_child) - { - signal_keyboard_queue_.connect_signal(E, position, signal); - } - - /** - * Disconnect a signal for callback in set_event_keyboard. - * - * @tparam E The event the callback was used for. - * @param signal The callback function. - * @param position The place where the function was added. - * Needed remove the event from the right - * place. (The function doesn't care whether - * was added in front or back.) - */ - template - std::enable_if_t - disconnect_signal(const signal_keyboard_function& signal, const queue_position position = back_child) - { - signal_keyboard_queue_.disconnect_signal(E, position, signal); - } - - /** - * Connect a signal for callback in set_event_touch_motion. + * @tparam F The event signature. This must match the + * appropriate queue's callback signature. * - * @tparam E The event the callback needs to react to. * @param signal The callback function. * @param position The position to place the callback. */ - template - std::enable_if_t - connect_signal(const signal_touch_motion_function& signal, const queue_position position = back_child) + template + void connect_signal(const F& func, const queue_position position = back_child) { - signal_touch_motion_queue_.connect_signal(E, position, signal); - } - - /** - * Disconnect a signal for callback in set_event_touch_motion. - * - * @tparam E The event the callback was used for. - * @param signal The callback function. - * @param position The place where the function was added. - * Needed remove the event from the right - * place. (The function doesn't care whether - * was added in front or back.) - */ - template - std::enable_if_t - disconnect_signal(const signal_touch_motion_function& signal, const queue_position position = back_child) - { - signal_touch_motion_queue_.disconnect_signal(E, position, signal); - } - - /** - * Connect a signal for callback in set_event_touch_gesture. - * - * @tparam E The event the callback needs to react to. - * @param signal The callback function. - * @param position The position to place the callback. - */ - template - std::enable_if_t - connect_signal(const signal_touch_gesture_function& signal, const queue_position position = back_child) - { - signal_touch_gesture_queue_.connect_signal(E, position, signal); - } - - /** - * Disconnect a signal for callback in set_event_touch_gesture. - * - * @tparam E The event the callback was used for. - * @param signal The callback function. - * @param position The place where the function was added. - * Needed remove the event from the right - * place. (The function doesn't care whether - * was added in front or back.) - */ - template - std::enable_if_t - disconnect_signal(const signal_touch_gesture_function& signal, const queue_position position = back_child) - { - signal_touch_gesture_queue_.disconnect_signal(E, position, signal); - } - - /** - * Connect a signal for callback in set_event_notification. - * - * @tparam E The event the callback needs to react to. - * @param signal The callback function. - * @param position The position to place the callback. Since - * the message is send to a widget directly - * the pre and post positions make no sense - * and shouldn't be used. - */ - template - std::enable_if_t - connect_signal(const signal_notification_function& signal, const queue_position position = back_child) - { - signal_notification_queue_.connect_signal(E, position, signal); - } - - /** - * Disconnect a signal for callback in set_event_notification. - * - * @tparam E The event the callback was used for. - * @param signal The callback function. - * @param position The place where the function was added. - * Needed remove the event from the right - * place. (The function doesn't care whether - * was added in front or back, but it needs - * to know the proper queue so it's save to - * add with front_child and remove with - * back_child. But it's not save to add with - * front_child and remove with - * front_pre_child) - */ - template - std::enable_if_t - disconnect_signal(const signal_notification_function& signal, const queue_position position = back_child) - { - signal_notification_queue_.disconnect_signal(E, position, signal); - } - - /** - * Connect a signal for callback in set_event_message. - * - * @tparam E The event the callback needs to react to. - * @param signal The callback function. - * @param position The position to place the callback. Since - * the message is send to a widget directly - * the pre and post positions make no sense - * and shouldn't be used. - */ - template - std::enable_if_t - connect_signal(const signal_message_function& signal, const queue_position position = back_child) - { - signal_message_queue_.connect_signal(E, position, signal); + if constexpr(is_general_event(E)) { + VALIDATE_AND_ADD_TO_QUEUE(signal) + } else if constexpr(is_mouse_event(E)) { + VALIDATE_AND_ADD_TO_QUEUE(signal_mouse) + } else if constexpr(is_keyboard_event(E)) { + VALIDATE_AND_ADD_TO_QUEUE(signal_keyboard) + } else if constexpr(is_touch_motion_event(E)) { + VALIDATE_AND_ADD_TO_QUEUE(signal_touch_motion) + } else if constexpr(is_touch_gesture_event(E)) { + VALIDATE_AND_ADD_TO_QUEUE(signal_touch_gesture) + } else if constexpr(is_notification_event(E)) { + VALIDATE_AND_ADD_TO_QUEUE(signal_notification) + } else if constexpr(is_message_event(E)) { + VALIDATE_AND_ADD_TO_QUEUE(signal_message) + } else if constexpr(is_raw_event_event(E)) { + VALIDATE_AND_ADD_TO_QUEUE(signal_raw_event) + } else if constexpr(is_text_input_event(E)) { + VALIDATE_AND_ADD_TO_QUEUE(signal_text_input) + } else { + static_assert(false, "No matching signal queue found for event"); + } } - /** - * Disconnect a signal for callback in set_event_message. - * - * @tparam E The event the callback was used for. - * @param signal The callback function. - * @param position The place where the function was added. - * Needed remove the event from the right - * place. (The function doesn't care whether - * was added in front or back, but it needs - * to know the proper queue so it's save to - * add with front_child and remove with - * back_child. But it's not save to add with - * front_child and remove with - * front_pre_child) - */ - template - std::enable_if_t - disconnect_signal(const signal_message_function& signal, const queue_position position = back_child) - { - signal_message_queue_.disconnect_signal(E, position, signal); - } +#define VALIDATE_AND_REMOVE_FROM_QUEUE(QUEUE) \ + static_assert(std::is_convertible_v, \ + "disconnect_signal: function signature does not match " STR(QUEUE##_function)); \ + QUEUE##_queue_.disconnect_signal(E, position, func); /** - * Connect a signal for callback in set_raw_event. + * Removes a callback from the appropriate queue based on event type. * * @tparam E The event the callback needs to react to. - * @param signal The callback function. - * @param position The position to place the callback. - */ - template - std::enable_if_t - connect_signal(const signal_raw_event_function& signal, const queue_position position = back_child) - { - signal_raw_event_queue_.connect_signal(E, position, signal); - } - - /** - * Disconnect a signal for callback in set_raw_event. + * @tparam F The event signature. This must match the + * appropriate queue's callback signature. * - * @tparam E The event the callback was used for. * @param signal The callback function. * @param position The place where the function was added. * Needed remove the event from the right * place. (The function doesn't care whether * was added in front or back.) */ - template - std::enable_if_t - disconnect_signal(const signal_raw_event_function& signal, const queue_position position = back_child) + template + void disconnect_signal(const F& func, const queue_position position = back_child) { - signal_raw_event_queue_.disconnect_signal(E, position, signal); + if constexpr(is_general_event(E)) { + VALIDATE_AND_REMOVE_FROM_QUEUE(signal) + } else if constexpr(is_mouse_event(E)) { + VALIDATE_AND_REMOVE_FROM_QUEUE(signal_mouse) + } else if constexpr(is_keyboard_event(E)) { + VALIDATE_AND_REMOVE_FROM_QUEUE(signal_keyboard) + } else if constexpr(is_touch_motion_event(E)) { + VALIDATE_AND_REMOVE_FROM_QUEUE(signal_touch_motion) + } else if constexpr(is_touch_gesture_event(E)) { + VALIDATE_AND_REMOVE_FROM_QUEUE(signal_touch_gesture) + } else if constexpr(is_notification_event(E)) { + VALIDATE_AND_REMOVE_FROM_QUEUE(signal_notification) + } else if constexpr(is_message_event(E)) { + VALIDATE_AND_REMOVE_FROM_QUEUE(signal_message) + } else if constexpr(is_raw_event_event(E)) { + VALIDATE_AND_REMOVE_FROM_QUEUE(signal_raw_event) + } else if constexpr(is_text_input_event(E)) { + VALIDATE_AND_REMOVE_FROM_QUEUE(signal_text_input) + } else { + static_assert(false, "No matching signal queue found for event"); + } } - /** - * Connect a signal for callback in set_text_input. - * - * @tparam E The event the callback needs to react to. - * @param signal The callback function. - * @param position The position to place the callback. - */ - template - std::enable_if_t - connect_signal(const signal_text_input_function& signal, const queue_position position = back_child) - { - signal_text_input_queue_.connect_signal(E, position, signal); - } +#undef VALIDATE_AND_ADD_TO_QUEUE +#undef VALIDATE_AND_REMOVE_FROM_QUEUE - /** - * Disconnect a signal for callback in set_text_input. - * - * @tparam E The event the callback was used for. - * @param signal The callback function. - * @param position The place where the function was added. - * Needed remove the event from the right - * place. (The function doesn't care whether - * was added in front or back.) - */ - template - std::enable_if_t - disconnect_signal(const signal_text_input_function& signal, const queue_position position = back_child) - { - signal_text_input_queue_.disconnect_signal(E, position, signal); - } +#undef STR /** * The behavior of the mouse events.