diff options
-rw-r--r-- | mwe/events/include/event.h | 2 | ||||
-rw-r--r-- | src/crepe/api/EventManager.cpp | 60 | ||||
-rw-r--r-- | src/crepe/api/EventManager.h | 19 | ||||
-rw-r--r-- | src/crepe/api/EventManager.hpp | 87 | ||||
-rw-r--r-- | src/crepe/api/IKeyListener.cpp | 8 | ||||
-rw-r--r-- | src/crepe/api/IKeyListener.h | 1 | ||||
-rw-r--r-- | src/crepe/api/IMouseListener.cpp | 3 | ||||
-rw-r--r-- | src/crepe/api/IMouseListener.h | 1 | ||||
-rw-r--r-- | src/example/events.cpp | 10 | ||||
-rw-r--r-- | src/test/EventTest.cpp | 530 |
10 files changed, 344 insertions, 377 deletions
diff --git a/mwe/events/include/event.h b/mwe/events/include/event.h index ee1bf52..e1b220b 100644 --- a/mwe/events/include/event.h +++ b/mwe/events/include/event.h @@ -148,7 +148,7 @@ private: }; class ShutDownEvent : public Event { public: - ShutDownEvent() : Event("ShutDownEvent") {}; + ShutDownEvent() : Event("ShutDownEvent"){}; REGISTER_EVENT_TYPE(ShutDownEvent) diff --git a/src/crepe/api/EventManager.cpp b/src/crepe/api/EventManager.cpp index 4f88e97..dbdb0c3 100644 --- a/src/crepe/api/EventManager.cpp +++ b/src/crepe/api/EventManager.cpp @@ -8,37 +8,39 @@ EventManager & EventManager::get_instance() { } void EventManager::dispatch_events() { - for (auto event_it = this->events_queue.begin(); event_it != this->events_queue.end();) { - std::unique_ptr<Event>& event = (*event_it).event; - int channel = (*event_it).channel; - std::type_index event_type = (*event_it).type; - - bool event_handled = false; - auto handlers_it = this->subscribers.find(event_type); - if (handlers_it != this->subscribers.end()) { - std::vector<CallbackEntry>& handlers = handlers_it->second; - - std::sort(handlers.begin(), handlers.end(), [](const CallbackEntry& a, const CallbackEntry& b) { - return a.priority > b.priority; - }); - - for (auto handler_it = handlers.begin(); handler_it != handlers.end(); ++handler_it) { - // If callback is executed and returns true, remove the event from the queue - if ((*handler_it).callback->exec(*event)) { - event_it = this->events_queue.erase(event_it); - event_handled = true; - break; - } - } - } - - if (!event_handled) { - ++event_it; - } - } + for (auto event_it = this->events_queue.begin(); event_it != this->events_queue.end();) { + std::unique_ptr<Event> & event = (*event_it).event; + int channel = (*event_it).channel; + std::type_index event_type = (*event_it).type; + + bool event_handled = false; + auto handlers_it = this->subscribers.find(event_type); + if (handlers_it != this->subscribers.end()) { + std::vector<CallbackEntry> & handlers = handlers_it->second; + + std::sort(handlers.begin(), handlers.end(), + [](const CallbackEntry & a, const CallbackEntry & b) { + return a.priority > b.priority; + }); + + for (auto handler_it = handlers.begin(); handler_it != handlers.end(); + ++handler_it) { + // If callback is executed and returns true, remove the event from the queue + if ((*handler_it).callback->exec(*event)) { + event_it = this->events_queue.erase(event_it); + event_handled = true; + break; + } + } + } + + if (!event_handled) { + ++event_it; + } + } } -void EventManager::clear(){ +void EventManager::clear() { this->subscribers.clear(); this->events_queue.clear(); } diff --git a/src/crepe/api/EventManager.h b/src/crepe/api/EventManager.h index eccb0bf..133d72d 100644 --- a/src/crepe/api/EventManager.h +++ b/src/crepe/api/EventManager.h @@ -19,7 +19,6 @@ static constexpr int CHANNEL_ALL = -1; */ class EventManager { public: - /** * \brief Get the singleton instance of the EventManager. * @@ -39,7 +38,8 @@ public: * \param channel The channel number to subscribe to (default is 0). */ template <typename EventType> - void subscribe(const EventHandler<EventType> & callback, int channel = CHANNEL_ALL, int priority = 0); + void subscribe(const EventHandler<EventType> & callback, int channel = CHANNEL_ALL, + int priority = 0); /** * \brief Unsubscribe from an event. @@ -76,7 +76,7 @@ public: * \param channel The channel number for the event (default is 0). */ template <typename EventType> - void queue_event(const EventType & event, int channel = CHANNEL_ALL,int priority = 0); + void queue_event(const EventType & event, int channel = CHANNEL_ALL, int priority = 0); /** * \brief Dispatch all queued events. @@ -90,8 +90,8 @@ public: * */ void clear(); + private: - /** * \brief Default constructor for the EventManager. * @@ -99,21 +99,20 @@ private: */ EventManager() = default; struct QueueEntry { - std::unique_ptr<Event> event; + std::unique_ptr<Event> event; int channel = CHANNEL_ALL; std::type_index type; int priority = 0; - }; + }; struct CallbackEntry { - std::unique_ptr<IEventHandlerWrapper> callback; + std::unique_ptr<IEventHandlerWrapper> callback; int channel = CHANNEL_ALL; int priority = 0; - }; + }; //! The queue of events to be processed. std::vector<QueueEntry> events_queue; //! Registered event handlers. - std::unordered_map<std::type_index,std::vector<CallbackEntry>> subscribers; - + std::unordered_map<std::type_index, std::vector<CallbackEntry>> subscribers; }; } // namespace crepe diff --git a/src/crepe/api/EventManager.hpp b/src/crepe/api/EventManager.hpp index 481017d..a04a43a 100644 --- a/src/crepe/api/EventManager.hpp +++ b/src/crepe/api/EventManager.hpp @@ -3,7 +3,8 @@ namespace crepe { template <typename EventType> -void EventManager::subscribe(const EventHandler<EventType> & callback, int channel, int priority) { +void EventManager::subscribe(const EventHandler<EventType> & callback, int channel, + int priority) { std::type_index event_type = typeid(EventType); std::unique_ptr<EventHandlerWrapper<EventType>> handler @@ -14,69 +15,65 @@ void EventManager::subscribe(const EventHandler<EventType> & callback, int chann .channel = channel, .priority = priority, }); - // Sort handlers by priority (highest first) - std::sort(handlers.begin(), handlers.end(), [](const CallbackEntry &a, const CallbackEntry &b) { - return a.priority > b.priority; - }); + // Sort handlers by priority (highest first) + std::sort(handlers.begin(), handlers.end(), + [](const CallbackEntry & a, const CallbackEntry & b) { + return a.priority > b.priority; + }); } template <typename EventType> -void EventManager::queue_event(const EventType & event, int channel,int priority) { - static_assert(std::is_base_of<Event, EventType>::value, "EventType must derive from Event"); +void EventManager::queue_event(const EventType & event, int channel, int priority) { + static_assert(std::is_base_of<Event, EventType>::value, + "EventType must derive from Event"); std::type_index event_type = typeid(EventType); auto event_ptr = std::make_unique<EventType>(event); - this->events_queue.push_back( - QueueEntry{ - .event = std::move(event_ptr), - .channel = channel, - .type = event_type, - .priority = priority - } - ); + this->events_queue.push_back(QueueEntry{.event = std::move(event_ptr), + .channel = channel, + .type = event_type, + .priority = priority}); } template <typename EventType> void EventManager::trigger_event(const EventType & event, int channel) { - std::type_index event_type = typeid(EventType); + std::type_index event_type = typeid(EventType); - auto handlers_it = this->subscribers.find(event_type); - if (handlers_it != this->subscribers.end()) { - const std::vector<CallbackEntry> &handlers = handlers_it->second; + auto handlers_it = this->subscribers.find(event_type); + if (handlers_it != this->subscribers.end()) { + const std::vector<CallbackEntry> & handlers = handlers_it->second; - for (const CallbackEntry &handler : handlers) { - if (handler.channel != channel && handler.channel != CHANNEL_ALL) { - continue; - } - if (handler.callback->exec(event)) { - break; - } - } - } + for (const CallbackEntry & handler : handlers) { + if (handler.channel != channel && handler.channel != CHANNEL_ALL) { + continue; + } + if (handler.callback->exec(event)) { + break; + } + } + } } - template <typename EventType> void EventManager::unsubscribe(const EventHandler<EventType> & callback, int channel) { - std::type_index event_type = typeid(EventType); - std::string handler_name = callback.target_type().name(); + std::type_index event_type = typeid(EventType); + std::string handler_name = callback.target_type().name(); - // Find the list of handlers for this event type - auto handlers_it = this->subscribers.find(event_type); - if (handlers_it != this->subscribers.end()) { - std::vector<CallbackEntry> & handlers = handlers_it->second; + // Find the list of handlers for this event type + auto handlers_it = this->subscribers.find(event_type); + if (handlers_it != this->subscribers.end()) { + std::vector<CallbackEntry> & handlers = handlers_it->second; - for (auto it = handlers.begin(); it != handlers.end(); ) { - // Match based on handler type and channel - if (it->callback->get_type() == handler_name && it->channel == channel) { - it = handlers.erase(it); - return; - } - ++it; - } - } + for (auto it = handlers.begin(); it != handlers.end();) { + // Match based on handler type and channel + if (it->callback->get_type() == handler_name && it->channel == channel) { + it = handlers.erase(it); + return; + } + ++it; + } + } } - } // namespace crepe diff --git a/src/crepe/api/IKeyListener.cpp b/src/crepe/api/IKeyListener.cpp index 5e7d9bb..6a522c1 100644 --- a/src/crepe/api/IKeyListener.cpp +++ b/src/crepe/api/IKeyListener.cpp @@ -2,7 +2,6 @@ using namespace crepe; - // Constructor with specified channel IKeyListener::IKeyListener(int channel) : channel(channel), @@ -21,10 +20,8 @@ void IKeyListener::subscribe_events() { key_released_handler = [this](const KeyReleaseEvent & event) { return this->on_key_released(event); }; - event_manager.subscribe<KeyPressEvent>(this->key_pressed_handler, - this->channel); - event_manager.subscribe<KeyReleaseEvent>(this->key_released_handler, - this->channel); + event_manager.subscribe<KeyPressEvent>(this->key_pressed_handler, this->channel); + event_manager.subscribe<KeyReleaseEvent>(this->key_released_handler, this->channel); } // Unsubscribe from key events @@ -32,4 +29,3 @@ void IKeyListener::unsubscribe_events() { event_manager.unsubscribe<KeyPressEvent>(this->key_pressed_handler, this->channel); event_manager.unsubscribe<KeyReleaseEvent>(this->key_released_handler, this->channel); } - diff --git a/src/crepe/api/IKeyListener.h b/src/crepe/api/IKeyListener.h index 70243b4..9402cce 100644 --- a/src/crepe/api/IKeyListener.h +++ b/src/crepe/api/IKeyListener.h @@ -36,6 +36,7 @@ public: * \return True if the event was handled, false otherwise. */ virtual bool on_key_released(const KeyReleaseEvent & event) = 0; + protected: /** * \brief Subscribes to key events. diff --git a/src/crepe/api/IMouseListener.cpp b/src/crepe/api/IMouseListener.cpp index 6fd6c4b..f3ceb84 100644 --- a/src/crepe/api/IMouseListener.cpp +++ b/src/crepe/api/IMouseListener.cpp @@ -24,8 +24,7 @@ void IMouseListener::subscribe_events() { // Subscribe event handlers (no need for std::move) event_manager.subscribe<MouseClickEvent>(mouse_click_handler, this->channel); event_manager.subscribe<MousePressEvent>(mouse_press_handler, this->channel); - event_manager.subscribe<MouseReleaseEvent>(mouse_release_handler, - this->channel); + event_manager.subscribe<MouseReleaseEvent>(mouse_release_handler, this->channel); event_manager.subscribe<MouseMoveEvent>(mouse_move_handler, this->channel); } diff --git a/src/crepe/api/IMouseListener.h b/src/crepe/api/IMouseListener.h index 1195a4e..6bc5716 100644 --- a/src/crepe/api/IMouseListener.h +++ b/src/crepe/api/IMouseListener.h @@ -55,6 +55,7 @@ public: * \return True if the event was handled, false otherwise. */ virtual bool on_mouse_moved(const MouseMoveEvent & event) = 0; + protected: /** * \brief Subscribes to mouse events on the specified channel. diff --git a/src/example/events.cpp b/src/example/events.cpp index 402a857..3dee9fa 100644 --- a/src/example/events.cpp +++ b/src/example/events.cpp @@ -63,9 +63,9 @@ public: } }; int main() { - + { - // two events to trigger + // two events to trigger KeyPressEvent key_press; key_press.key = Keycode::A; key_press.repeat = 0; @@ -106,10 +106,8 @@ int main() { EventManager::get_instance().subscribe<KeyPressEvent>(event_handler, CHANNEL_ALL); EventManager::get_instance().subscribe<KeyPressEvent>(event_handler, CHANNEL_ALL); EventManager::get_instance().subscribe<MouseClickEvent>(event_handler2, CHANNEL_ALL); - EventManager::get_instance().trigger_event<KeyPressEvent>(KeyPressEvent{ - .repeat = false, - .key = Keycode::A - }); + EventManager::get_instance().trigger_event<KeyPressEvent>( + KeyPressEvent{.repeat = false, .key = Keycode::A}); //EventManager::get_instance().unsubscribe<KeyPressEvent>(event_handler, 0); // testing trigger with testListener not in scope (unsubscribed) // EventManager::get_instance().trigger_event<KeyPressEvent>(key_press, 0); diff --git a/src/test/EventTest.cpp b/src/test/EventTest.cpp index 3a78590..9dc2360 100644 --- a/src/test/EventTest.cpp +++ b/src/test/EventTest.cpp @@ -1,334 +1,308 @@ -#include "api/EventManager.h" #include "api/Event.h" +#include "api/EventManager.h" #include "api/IKeyListener.h" #include "api/IMouseListener.h" -#include <gtest/gtest.h> -#include <gtest/gtest.h> #include <gmock/gmock.h> +#include <gtest/gtest.h> using namespace std; using namespace std::chrono_literals; using namespace crepe; - class EventManagerTest : public ::testing::Test { protected: - void SetUp() override { - // Clear any existing subscriptions or events before each test - EventManager::get_instance().clear(); - } - - void TearDown() override { - // Ensure cleanup after each test - EventManager::get_instance().clear(); - } + void SetUp() override { + // Clear any existing subscriptions or events before each test + EventManager::get_instance().clear(); + } + + void TearDown() override { + // Ensure cleanup after each test + EventManager::get_instance().clear(); + } }; class MockKeyListener : public IKeyListener { public: - MOCK_METHOD(bool, on_key_pressed, (const KeyPressEvent& event), (override)); - MOCK_METHOD(bool, on_key_released, (const KeyReleaseEvent& event), (override)); + MOCK_METHOD(bool, on_key_pressed, (const KeyPressEvent & event), (override)); + MOCK_METHOD(bool, on_key_released, (const KeyReleaseEvent & event), (override)); }; class MockMouseListener : public IMouseListener { public: - MOCK_METHOD(bool, on_mouse_clicked, (const MouseClickEvent& event), (override)); - MOCK_METHOD(bool, on_mouse_pressed, (const MousePressEvent& event), (override)); - MOCK_METHOD(bool, on_mouse_released, (const MouseReleaseEvent& event), (override)); - MOCK_METHOD(bool, on_mouse_moved, (const MouseMoveEvent& event), (override)); + MOCK_METHOD(bool, on_mouse_clicked, (const MouseClickEvent & event), (override)); + MOCK_METHOD(bool, on_mouse_pressed, (const MousePressEvent & event), (override)); + MOCK_METHOD(bool, on_mouse_released, (const MouseReleaseEvent & event), (override)); + MOCK_METHOD(bool, on_mouse_moved, (const MouseMoveEvent & event), (override)); }; TEST_F(EventManagerTest, EventSubscription) { - EventHandler<KeyPressEvent> key_handler = [](const KeyPressEvent& e) { - std::cout << "Key Event Triggered" << std::endl; - return true; - }; - - // Subscribe to KeyPressEvent - EventManager::get_instance().subscribe<KeyPressEvent>(key_handler, 1); - - // Verify subscription (not directly verifiable; test by triggering event) - - EventManager::get_instance().trigger_event<KeyPressEvent>(KeyPressEvent{ - .repeat = true, - .key = Keycode::A, - }, 1); - EventManager::get_instance().trigger_event<KeyPressEvent>(KeyPressEvent{ - .repeat = true, - .key = Keycode::A, - - }, CHANNEL_ALL); - + EventHandler<KeyPressEvent> key_handler = [](const KeyPressEvent & e) { + std::cout << "Key Event Triggered" << std::endl; + return true; + }; + + // Subscribe to KeyPressEvent + EventManager::get_instance().subscribe<KeyPressEvent>(key_handler, 1); + + // Verify subscription (not directly verifiable; test by triggering event) + + EventManager::get_instance().trigger_event<KeyPressEvent>( + KeyPressEvent{ + .repeat = true, + .key = Keycode::A, + }, + 1); + EventManager::get_instance().trigger_event<KeyPressEvent>( + KeyPressEvent{ + .repeat = true, + .key = Keycode::A, + + }, + CHANNEL_ALL); } TEST_F(EventManagerTest, EventManagerTest_trigger_all_channels) { - bool triggered = false; - - EventHandler<MouseClickEvent> mouse_handler = [&](const MouseClickEvent& e) { - triggered = true; - std::cout << "mouse handled" <<std::endl; - EXPECT_EQ(e.mouse_x, 100); - EXPECT_EQ(e.mouse_y, 200); - EXPECT_EQ(e.button, MouseButton::LEFT_MOUSE); - return false; - }; - EventManager::get_instance().subscribe<MouseClickEvent>(mouse_handler, CHANNEL_ALL); - - MouseClickEvent click_event{ - .mouse_x = 100, - .mouse_y = 200, - .button = MouseButton::LEFT_MOUSE + bool triggered = false; + + EventHandler<MouseClickEvent> mouse_handler = [&](const MouseClickEvent & e) { + triggered = true; + std::cout << "mouse handled" << std::endl; + EXPECT_EQ(e.mouse_x, 100); + EXPECT_EQ(e.mouse_y, 200); + EXPECT_EQ(e.button, MouseButton::LEFT_MOUSE); + return false; }; + EventManager::get_instance().subscribe<MouseClickEvent>(mouse_handler, CHANNEL_ALL); + + MouseClickEvent click_event{ + .mouse_x = 100, .mouse_y = 200, .button = MouseButton::LEFT_MOUSE}; EventManager::get_instance().trigger_event<MouseClickEvent>(click_event, CHANNEL_ALL); - EXPECT_TRUE(triggered); + EXPECT_TRUE(triggered); } TEST_F(EventManagerTest, EventManagerTest_priority_order) { - EventManager& event_manager = EventManager::get_instance(); - - // Vector to track call order - std::vector<int> call_order; - - // Handlers with different priorities - EventHandler<MouseClickEvent> handler_priority_3 = [&](const MouseClickEvent& e) { - call_order.push_back(3); - return false; // Allow propagation - }; - - EventHandler<MouseClickEvent> handler_priority_1 = [&](const MouseClickEvent& e) { - call_order.push_back(1); - return false; // Allow propagation - }; - - EventHandler<MouseClickEvent> handler_priority_2 = [&](const MouseClickEvent& e) { - call_order.push_back(2); - return false; // Allow propagation - }; - - // Subscribe handlers with different priorities - event_manager.subscribe<MouseClickEvent>(handler_priority_1, CHANNEL_ALL, 1); - event_manager.subscribe<MouseClickEvent>(handler_priority_3, CHANNEL_ALL, 3); - event_manager.subscribe<MouseClickEvent>(handler_priority_2, CHANNEL_ALL, 2); + EventManager & event_manager = EventManager::get_instance(); + + // Vector to track call order + std::vector<int> call_order; + + // Handlers with different priorities + EventHandler<MouseClickEvent> handler_priority_3 = [&](const MouseClickEvent & e) { + call_order.push_back(3); + return false; // Allow propagation + }; + + EventHandler<MouseClickEvent> handler_priority_1 = [&](const MouseClickEvent & e) { + call_order.push_back(1); + return false; // Allow propagation + }; - // Trigger the event - event_manager.trigger_event<MouseClickEvent>(MouseClickEvent{ - .mouse_x = 100, - .mouse_y = 200, - .button = MouseButton::LEFT_MOUSE - }, CHANNEL_ALL); + EventHandler<MouseClickEvent> handler_priority_2 = [&](const MouseClickEvent & e) { + call_order.push_back(2); + return false; // Allow propagation + }; + + // Subscribe handlers with different priorities + event_manager.subscribe<MouseClickEvent>(handler_priority_1, CHANNEL_ALL, 1); + event_manager.subscribe<MouseClickEvent>(handler_priority_3, CHANNEL_ALL, 3); + event_manager.subscribe<MouseClickEvent>(handler_priority_2, CHANNEL_ALL, 2); - // Check the call order matches the expected priority order - std::vector<int> expected_order = {3, 2, 1}; - EXPECT_EQ(call_order, expected_order); + // Trigger the event + event_manager.trigger_event<MouseClickEvent>( + MouseClickEvent{.mouse_x = 100, .mouse_y = 200, .button = MouseButton::LEFT_MOUSE}, + CHANNEL_ALL); + // Check the call order matches the expected priority order + std::vector<int> expected_order = {3, 2, 1}; + EXPECT_EQ(call_order, expected_order); } TEST_F(EventManagerTest, EventManagerTest_callback_propagation) { - EventManager& event_manager = EventManager::get_instance(); - - // Flags to track handler calls - bool triggered_true = false; - bool triggered_false = false; - - // Handlers - EventHandler<MouseClickEvent> mouse_handler_true = [&](const MouseClickEvent& e) { - triggered_true = true; - EXPECT_EQ(e.mouse_x, 100); - EXPECT_EQ(e.mouse_y, 200); - EXPECT_EQ(e.button, MouseButton::LEFT_MOUSE); - return true; // Stops propagation - }; - - EventHandler<MouseClickEvent> mouse_handler_false = [&](const MouseClickEvent& e) { - triggered_false = true; - EXPECT_EQ(e.mouse_x, 100); - EXPECT_EQ(e.mouse_y, 200); - EXPECT_EQ(e.button, MouseButton::LEFT_MOUSE); - return false; // Allows propagation - }; - - // Test event - MouseClickEvent click_event{ - .mouse_x = 100, - .mouse_y = 200, - .button = MouseButton::LEFT_MOUSE - }; - - // First Scenario: True handler has higher priority - event_manager.subscribe<MouseClickEvent>(mouse_handler_true, CHANNEL_ALL, 1); - event_manager.subscribe<MouseClickEvent>(mouse_handler_false, CHANNEL_ALL, 0); - - // Trigger event - event_manager.trigger_event<MouseClickEvent>(click_event, CHANNEL_ALL); - - // Check that only the true handler was triggered - EXPECT_TRUE(triggered_true); - EXPECT_FALSE(triggered_false); - - // Reset and clear - triggered_true = false; - triggered_false = false; - event_manager.clear(); - - // Second Scenario: False handler has higher priority - event_manager.subscribe<MouseClickEvent>(mouse_handler_true, CHANNEL_ALL, 0); - event_manager.subscribe<MouseClickEvent>(mouse_handler_false, CHANNEL_ALL, 1); - - // Trigger event again - event_manager.trigger_event<MouseClickEvent>(click_event, CHANNEL_ALL); - - // Check that both handlers were triggered - EXPECT_TRUE(triggered_true); - EXPECT_TRUE(triggered_false); + EventManager & event_manager = EventManager::get_instance(); + + // Flags to track handler calls + bool triggered_true = false; + bool triggered_false = false; + + // Handlers + EventHandler<MouseClickEvent> mouse_handler_true = [&](const MouseClickEvent & e) { + triggered_true = true; + EXPECT_EQ(e.mouse_x, 100); + EXPECT_EQ(e.mouse_y, 200); + EXPECT_EQ(e.button, MouseButton::LEFT_MOUSE); + return true; // Stops propagation + }; + + EventHandler<MouseClickEvent> mouse_handler_false = [&](const MouseClickEvent & e) { + triggered_false = true; + EXPECT_EQ(e.mouse_x, 100); + EXPECT_EQ(e.mouse_y, 200); + EXPECT_EQ(e.button, MouseButton::LEFT_MOUSE); + return false; // Allows propagation + }; + + // Test event + MouseClickEvent click_event{ + .mouse_x = 100, .mouse_y = 200, .button = MouseButton::LEFT_MOUSE}; + + // First Scenario: True handler has higher priority + event_manager.subscribe<MouseClickEvent>(mouse_handler_true, CHANNEL_ALL, 1); + event_manager.subscribe<MouseClickEvent>(mouse_handler_false, CHANNEL_ALL, 0); + + // Trigger event + event_manager.trigger_event<MouseClickEvent>(click_event, CHANNEL_ALL); + + // Check that only the true handler was triggered + EXPECT_TRUE(triggered_true); + EXPECT_FALSE(triggered_false); + + // Reset and clear + triggered_true = false; + triggered_false = false; + event_manager.clear(); + + // Second Scenario: False handler has higher priority + event_manager.subscribe<MouseClickEvent>(mouse_handler_true, CHANNEL_ALL, 0); + event_manager.subscribe<MouseClickEvent>(mouse_handler_false, CHANNEL_ALL, 1); + + // Trigger event again + event_manager.trigger_event<MouseClickEvent>(click_event, CHANNEL_ALL); + + // Check that both handlers were triggered + EXPECT_TRUE(triggered_true); + EXPECT_TRUE(triggered_false); } TEST_F(EventManagerTest, EventManagerTest_queue_dispatch) { - EventManager& event_manager = EventManager::get_instance(); + EventManager & event_manager = EventManager::get_instance(); bool triggered1 = false; bool triggered2 = false; int test_channel = 1; - EventHandler<MouseClickEvent> mouse_handler1 = [&](const MouseClickEvent& e) { - triggered1 = true; - EXPECT_EQ(e.mouse_x, 100); - EXPECT_EQ(e.mouse_y, 200); - EXPECT_EQ(e.button, MouseButton::LEFT_MOUSE); - return false; // Allows propagation - }; - EventHandler<MouseClickEvent> mouse_handler2 = [&](const MouseClickEvent& e) { - triggered2 = true; - EXPECT_EQ(e.mouse_x, 100); - EXPECT_EQ(e.mouse_y, 200); - EXPECT_EQ(e.button, MouseButton::LEFT_MOUSE); - return false; // Allows propagation - }; + EventHandler<MouseClickEvent> mouse_handler1 = [&](const MouseClickEvent & e) { + triggered1 = true; + EXPECT_EQ(e.mouse_x, 100); + EXPECT_EQ(e.mouse_y, 200); + EXPECT_EQ(e.button, MouseButton::LEFT_MOUSE); + return false; // Allows propagation + }; + EventHandler<MouseClickEvent> mouse_handler2 = [&](const MouseClickEvent & e) { + triggered2 = true; + EXPECT_EQ(e.mouse_x, 100); + EXPECT_EQ(e.mouse_y, 200); + EXPECT_EQ(e.button, MouseButton::LEFT_MOUSE); + return false; // Allows propagation + }; event_manager.subscribe<MouseClickEvent>(mouse_handler1); - event_manager.subscribe<MouseClickEvent>(mouse_handler2,test_channel); - - event_manager.queue_event<MouseClickEvent>(MouseClickEvent{ - .mouse_x = 100, - .mouse_y = 200, - .button = MouseButton::LEFT_MOUSE - }); - event_manager.queue_event<MouseClickEvent>(MouseClickEvent{ - .mouse_x = 100, - .mouse_y = 200, - .button = MouseButton::LEFT_MOUSE - },test_channel); + event_manager.subscribe<MouseClickEvent>(mouse_handler2, test_channel); + + event_manager.queue_event<MouseClickEvent>( + MouseClickEvent{.mouse_x = 100, .mouse_y = 200, .button = MouseButton::LEFT_MOUSE}); + event_manager.queue_event<MouseClickEvent>( + MouseClickEvent{.mouse_x = 100, .mouse_y = 200, .button = MouseButton::LEFT_MOUSE}, + test_channel); event_manager.dispatch_events(); EXPECT_TRUE(triggered1); EXPECT_TRUE(triggered2); } TEST_F(EventManagerTest, EventManagerTest_dispatch_priority) { - EventManager& event_manager = EventManager::get_instance(); + EventManager & event_manager = EventManager::get_instance(); std::vector<int> call_order; int test_channel = 1; - EventHandler<MouseClickEvent> mouse_handler1 = [&](const MouseClickEvent& e) { + EventHandler<MouseClickEvent> mouse_handler1 = [&](const MouseClickEvent & e) { call_order.push_back(1); - EXPECT_EQ(e.mouse_x, 100); - EXPECT_EQ(e.mouse_y, 200); - EXPECT_EQ(e.button, MouseButton::LEFT_MOUSE); - return false; // Allows propagation - }; - EventHandler<MouseClickEvent> mouse_handler2 = [&](const MouseClickEvent& e) { - call_order.push_back(2); - EXPECT_EQ(e.mouse_x, 100); - EXPECT_EQ(e.mouse_y, 200); - EXPECT_EQ(e.button, MouseButton::LEFT_MOUSE); - return false; // Allows propagation - }; - EventHandler<MouseClickEvent> mouse_handler3 = [&](const MouseClickEvent& e) { - call_order.push_back(3); - EXPECT_EQ(e.mouse_x, 100); - EXPECT_EQ(e.mouse_y, 200); - EXPECT_EQ(e.button, MouseButton::LEFT_MOUSE); - return false; // Allows propagation - }; - event_manager.subscribe<MouseClickEvent>(mouse_handler2,CHANNEL_ALL,2); - event_manager.subscribe<MouseClickEvent>(mouse_handler1,CHANNEL_ALL,1); - event_manager.subscribe<MouseClickEvent>(mouse_handler3,CHANNEL_ALL,3); - event_manager.queue_event<MouseClickEvent>(MouseClickEvent{ - .mouse_x = 100, - .mouse_y = 200, - .button = MouseButton::LEFT_MOUSE - }); + EXPECT_EQ(e.mouse_x, 100); + EXPECT_EQ(e.mouse_y, 200); + EXPECT_EQ(e.button, MouseButton::LEFT_MOUSE); + return false; // Allows propagation + }; + EventHandler<MouseClickEvent> mouse_handler2 = [&](const MouseClickEvent & e) { + call_order.push_back(2); + EXPECT_EQ(e.mouse_x, 100); + EXPECT_EQ(e.mouse_y, 200); + EXPECT_EQ(e.button, MouseButton::LEFT_MOUSE); + return false; // Allows propagation + }; + EventHandler<MouseClickEvent> mouse_handler3 = [&](const MouseClickEvent & e) { + call_order.push_back(3); + EXPECT_EQ(e.mouse_x, 100); + EXPECT_EQ(e.mouse_y, 200); + EXPECT_EQ(e.button, MouseButton::LEFT_MOUSE); + return false; // Allows propagation + }; + event_manager.subscribe<MouseClickEvent>(mouse_handler2, CHANNEL_ALL, 2); + event_manager.subscribe<MouseClickEvent>(mouse_handler1, CHANNEL_ALL, 1); + event_manager.subscribe<MouseClickEvent>(mouse_handler3, CHANNEL_ALL, 3); + event_manager.queue_event<MouseClickEvent>( + MouseClickEvent{.mouse_x = 100, .mouse_y = 200, .button = MouseButton::LEFT_MOUSE}); event_manager.dispatch_events(); std::vector<int> expected_order = {3, 2, 1}; - EXPECT_EQ(call_order, expected_order); + EXPECT_EQ(call_order, expected_order); } TEST_F(EventManagerTest, EventManagerTest_unsubscribe) { - EventManager& event_manager = EventManager::get_instance(); - - // Flags to track if handlers are triggered - bool triggered1 = false; - bool triggered2 = false; - - // Define EventHandlers - EventHandler<MouseClickEvent> mouse_handler1 = [&](const MouseClickEvent& e) { - triggered1 = true; - EXPECT_EQ(e.mouse_x, 100); - EXPECT_EQ(e.mouse_y, 200); - EXPECT_EQ(e.button, MouseButton::LEFT_MOUSE); - return false; // Allows propagation - }; - - EventHandler<MouseClickEvent> mouse_handler2 = [&](const MouseClickEvent& e) { - triggered2 = true; - EXPECT_EQ(e.mouse_x, 100); - EXPECT_EQ(e.mouse_y, 200); - EXPECT_EQ(e.button, MouseButton::LEFT_MOUSE); - return false; // Allows propagation - }; - // Subscribe handlers - event_manager.subscribe<MouseClickEvent>(mouse_handler1); - event_manager.subscribe<MouseClickEvent>(mouse_handler2); - - // Queue events - event_manager.queue_event<MouseClickEvent>(MouseClickEvent{ - .mouse_x = 100, - .mouse_y = 200, - .button = MouseButton::LEFT_MOUSE - }); - - // Dispatch events - both handlers should be triggered - event_manager.dispatch_events(); - EXPECT_TRUE(triggered1); // Handler 1 should be triggered - EXPECT_TRUE(triggered2); // Handler 2 should be triggered - - // Reset flags - triggered1 = false; - triggered2 = false; - - // Unsubscribe handler1 - event_manager.unsubscribe<MouseClickEvent>(mouse_handler1); - - // Queue the same event again - event_manager.queue_event<MouseClickEvent>(MouseClickEvent{ - .mouse_x = 100, - .mouse_y = 200, - .button = MouseButton::LEFT_MOUSE - }); - - // Dispatch events - only handler 2 should be triggered, handler 1 should NOT - event_manager.dispatch_events(); - EXPECT_FALSE(triggered1); // Handler 1 should NOT be triggered - EXPECT_TRUE(triggered2); // Handler 2 should be triggered - - // Reset flags - triggered2 = false; - - // Unsubscribe handler2 - event_manager.unsubscribe<MouseClickEvent>(mouse_handler2); - - // Queue the event again - event_manager.queue_event<MouseClickEvent>(MouseClickEvent{ - .mouse_x = 100, - .mouse_y = 200, - .button = MouseButton::LEFT_MOUSE - }); - - // Dispatch events - no handler should be triggered - event_manager.dispatch_events(); - EXPECT_FALSE(triggered1); // Handler 1 should NOT be triggered - EXPECT_FALSE(triggered2); // Handler 2 should NOT be triggered -} + EventManager & event_manager = EventManager::get_instance(); + + // Flags to track if handlers are triggered + bool triggered1 = false; + bool triggered2 = false; + + // Define EventHandlers + EventHandler<MouseClickEvent> mouse_handler1 = [&](const MouseClickEvent & e) { + triggered1 = true; + EXPECT_EQ(e.mouse_x, 100); + EXPECT_EQ(e.mouse_y, 200); + EXPECT_EQ(e.button, MouseButton::LEFT_MOUSE); + return false; // Allows propagation + }; + EventHandler<MouseClickEvent> mouse_handler2 = [&](const MouseClickEvent & e) { + triggered2 = true; + EXPECT_EQ(e.mouse_x, 100); + EXPECT_EQ(e.mouse_y, 200); + EXPECT_EQ(e.button, MouseButton::LEFT_MOUSE); + return false; // Allows propagation + }; + // Subscribe handlers + event_manager.subscribe<MouseClickEvent>(mouse_handler1); + event_manager.subscribe<MouseClickEvent>(mouse_handler2); + + // Queue events + event_manager.queue_event<MouseClickEvent>( + MouseClickEvent{.mouse_x = 100, .mouse_y = 200, .button = MouseButton::LEFT_MOUSE}); + + // Dispatch events - both handlers should be triggered + event_manager.dispatch_events(); + EXPECT_TRUE(triggered1); // Handler 1 should be triggered + EXPECT_TRUE(triggered2); // Handler 2 should be triggered + + // Reset flags + triggered1 = false; + triggered2 = false; + + // Unsubscribe handler1 + event_manager.unsubscribe<MouseClickEvent>(mouse_handler1); + + // Queue the same event again + event_manager.queue_event<MouseClickEvent>( + MouseClickEvent{.mouse_x = 100, .mouse_y = 200, .button = MouseButton::LEFT_MOUSE}); + + // Dispatch events - only handler 2 should be triggered, handler 1 should NOT + event_manager.dispatch_events(); + EXPECT_FALSE(triggered1); // Handler 1 should NOT be triggered + EXPECT_TRUE(triggered2); // Handler 2 should be triggered + + // Reset flags + triggered2 = false; + + // Unsubscribe handler2 + event_manager.unsubscribe<MouseClickEvent>(mouse_handler2); + + // Queue the event again + event_manager.queue_event<MouseClickEvent>( + MouseClickEvent{.mouse_x = 100, .mouse_y = 200, .button = MouseButton::LEFT_MOUSE}); + + // Dispatch events - no handler should be triggered + event_manager.dispatch_events(); + EXPECT_FALSE(triggered1); // Handler 1 should NOT be triggered + EXPECT_FALSE(triggered2); // Handler 2 should NOT be triggered +} |