diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/crepe/api/EventHandler.h | 80 | ||||
| -rw-r--r-- | src/crepe/api/EventManager.cpp | 21 | ||||
| -rw-r--r-- | src/crepe/api/EventManager.h | 162 | ||||
| -rw-r--r-- | src/crepe/api/IKeyListener.cpp | 20 | ||||
| -rw-r--r-- | src/crepe/api/IKeyListener.h | 8 | ||||
| -rw-r--r-- | src/makefile | 3 | 
6 files changed, 240 insertions, 54 deletions
diff --git a/src/crepe/api/EventHandler.h b/src/crepe/api/EventHandler.h index eea1c79..5b9ac0d 100644 --- a/src/crepe/api/EventHandler.h +++ b/src/crepe/api/EventHandler.h @@ -4,35 +4,109 @@  #include <typeindex>  #include "Event.h" +/** + * \brief A type alias for an event handler function. + *  + * The EventHandler is a std::function that takes an EventType reference and returns a boolean value  + * indicating whether the event was successfully handled. + *  + * \tparam EventType The type of event this handler will handle. + */  template <typename EventType>  using EventHandler = std::function<bool(const EventType & e)>; +/** + * \class IEventHandlerWrapper + * \brief An abstract base class for event handler wrappers. + *  + * This class provides the interface for handling events. Derived classes must implement the + * `call()` method to process events and the `get_type()` method to return the handler's type. + */  class IEventHandlerWrapper {  public: +    /** +     * \brief Virtual destructor for IEventHandlerWrapper. +     */      virtual ~IEventHandlerWrapper() = default; +    /** +     * \brief Executes the handler with the given event. +     *  +     * This method calls the `call()` method of the derived class, passing the event to the handler. +     *  +     * \param e The event to be processed. +     * \return A boolean value indicating whether the event is handled. +     */      bool exec(const Event & e); +    /** +     * \brief Get the type of the event handler. +     *  +     * This method returns the type of the event handler as a string. +     *  +     * \return A string representing the handler's type. +     */      virtual std::string get_type() const = 0;  private: +    /** +     * \brief The method responsible for handling the event. +     *  +     * This method is implemented by derived classes to process the event. +     *  +     * \param e The event to be processed. +     * \return A boolean value indicating whether the event is handled. +     */      virtual bool call(const Event & e) = 0;  }; +/** + * \class EventHandlerWrapper + * \brief A wrapper for event handler functions. + *  + * This class wraps an event handler function of a specific event type. It implements the  + * `call()` and `get_type()` methods to allow the handler to be executed and its type to be  + * queried. + *  + * \tparam EventType The type of event this handler will handle. + */  template <typename EventType>  class EventHandlerWrapper : public IEventHandlerWrapper {  public: +    /** +     * \brief Constructs an EventHandlerWrapper with a given handler. +     *  +     * The constructor takes an event handler function and stores it in the wrapper. +     *  +     * \param handler The event handler function. +     */      explicit EventHandlerWrapper(const EventHandler<EventType> & handler)          : m_handler(handler), m_handler_type(m_handler.target_type().name()) {      }  private: +    /** +     * \brief Calls the stored event handler with the event. +     *  +     * This method casts the event to the appropriate type and calls the handler. +     *  +     * \param e The event to be handled. +     * \return A boolean value indicating whether the event is handled. +     */      bool call(const Event & e) override {          return m_handler(static_cast<const EventType &>(e));      } +    /** +     * \brief Returns the type of the handler. +     *  +     * This method returns a string representing the type of the event handler. +     *  +     * \return The handler type as a string. +     */      std::string get_type() const override { return m_handler_type; } - -    EventHandler<EventType> m_handler; -    const std::string m_handler_type; +	//! The event handler function. +    EventHandler<EventType> m_handler;  +	//! The type name of the handler function. +    const std::string m_handler_type;   }; diff --git a/src/crepe/api/EventManager.cpp b/src/crepe/api/EventManager.cpp index 869ec74..3d8558b 100644 --- a/src/crepe/api/EventManager.cpp +++ b/src/crepe/api/EventManager.cpp @@ -7,6 +7,9 @@ void EventManager::dispatch_events() {          auto& event = std::get<0>(*event_it);          int channel = std::get<1>(*event_it);           std::type_index event_type = std::get<2>(*event_it);  + +        bool event_handled = false; +          if (channel) {              auto handlers_it = subscribers_by_event_id.find(event_type);              if (handlers_it != subscribers_by_event_id.end()) { @@ -15,25 +18,33 @@ void EventManager::dispatch_events() {                  if (handlers != handlers_map.end()) {                      auto& callbacks = handlers->second;                      for (auto& handler : callbacks) { -                        handler->exec(*event); +                        if (handler->exec(*event)) { +                            event_it = events_queue.erase(event_it); +                            event_handled = true; +                            break; +                        }                      }                  }              }          } else { +            // Handle event for all channels              auto handlers_it = subscribers.find(event_type);              if (handlers_it != subscribers.end()) {                  auto& handlers = handlers_it->second;                  for (auto& handler : handlers) { -                    handler->exec(*event); +                    if (handler->exec(*event)) { +                        event_it = events_queue.erase(event_it); +                        event_handled = true; +                        break; +                    }                  }              }          } -        if (event->handled) { -            event_it = events_queue.erase(event_it); -        } else { +        if (!event_handled) {              ++event_it;          }      }  } + diff --git a/src/crepe/api/EventManager.h b/src/crepe/api/EventManager.h index be9a947..9b69b29 100644 --- a/src/crepe/api/EventManager.h +++ b/src/crepe/api/EventManager.h @@ -10,48 +10,127 @@  #include "EventHandler.h"  //#include "keyCodes.h" +/** + * @class EventManager + * @brief The EventManager class is responsible for managing the subscription, triggering,  + * and queueing of events. It handles events and dispatches them to appropriate subscribers. + */  class EventManager {  public: -	EventManager(const EventManager &) = delete; -	const EventManager & operator=(const EventManager &) = delete; -	static EventManager & get_instance() { -		static EventManager instance; -		return instance; -	} -	template <typename EventType> -	void subscribe(EventHandler<EventType> && callback, int channel = 0); -	template <typename EventType> -	void unsubscribe(const EventHandler<EventType> &, int eventId); -	template <typename EventType> -	void trigger_event(const EventType & event, int channel); -	template <typename EventType> -	void queue_event(EventType&& event, int channel); -	void dispatch_events(); +    /** +     * \brief Deleted copy constructor to prevent copying of the EventManager instance. +     */ +    EventManager(const EventManager &) = delete; + +    /** +     * @brief Deleted copy assignment operator to prevent assignment of the EventManager instance. +     */ +    const EventManager & operator=(const EventManager &) = delete; + +    /** +     * @brief Get the singleton instance of the EventManager. +     *  +     * This method returns the unique instance of the EventManager, creating it on the first call. +     *  +     * @return Reference to the EventManager instance. +     */ +    static EventManager & get_instance() { +        static EventManager instance; +        return instance; +    } + +    /** +     * @brief Subscribe to an event. +     *  +     * This method allows the registration of a callback for a specific event type and channel. +     *  +     * @tparam EventType The type of the event to subscribe to. +     * @param callback The callback function to invoke when the event is triggered. +     * @param channel The channel number to subscribe to (default is 0). +     */ +    template <typename EventType> +    void subscribe(EventHandler<EventType> && callback, int channel = 0); + +    /** +     * @brief Unsubscribe from an event. +     *  +     * This method removes a previously registered callback from an event. +     *  +     * @tparam EventType The type of the event to unsubscribe from. +     * @param callback The callback function to remove from the subscription list. +     * @param eventId The event ID to unsubscribe from. +     */ +    template <typename EventType> +    void unsubscribe(const EventHandler<EventType> &, int eventId); + +    /** +     * @brief Trigger an event. +     *  +     * This method invokes the appropriate callback(s) for the specified event. +     *  +     * @tparam EventType The type of the event to trigger. +     * @param event The event data to pass to the callback. +     * @param channel The channel from which to trigger the event (default is 0). +     */ +    template <typename EventType> +    void trigger_event(const EventType & event, int channel); + +    /** +     * @brief Queue an event for later processing. +     *  +     * This method adds an event to the event queue, which will be processed in the  +     * dispatch_events function. +     *  +     * @tparam EventType The type of the event to queue. +     * @param event The event to queue. +     * @param channel The channel number for the event (default is 0). +     */ +    template <typename EventType> +    void queue_event(EventType&& event, int channel); + +    /** +     * @brief Dispatch all queued events. +     *  +     * This method processes all events in the event queue and triggers the corresponding  +     * callbacks for each event. +     */ +    void dispatch_events();  private: -	EventManager() = default; -	std::vector<std::tuple<std::unique_ptr<Event>, int, std::type_index>> events_queue; -	std::unordered_map<std::type_index, std::vector<std::unique_ptr<IEventHandlerWrapper>>> subscribers; -	std::unordered_map<std::type_index, std::unordered_map<int, std::vector<std::unique_ptr<IEventHandlerWrapper>>>> subscribers_by_event_id; +    /** +     * @brief Default constructor for the EventManager. +     *  +     * This constructor is private to enforce the singleton pattern. +     */ +    EventManager() = default; + +    //! The queue of events to be processed. +    std::vector<std::tuple<std::unique_ptr<Event>, int, std::type_index>> events_queue;  +	//! Registered event handlers. +    std::unordered_map<std::type_index, std::vector<std::unique_ptr<IEventHandlerWrapper>>> subscribers;  +	//! Event handlers indexed by event ID. +    std::unordered_map<std::type_index, std::unordered_map<int, std::vector<std::unique_ptr<IEventHandlerWrapper>>>> subscribers_by_event_id;   };  template <typename EventType> -void EventManager::subscribe(EventHandler<EventType> && callback, int channel){ +void EventManager::subscribe(EventHandler<EventType> && callback, int channel) {      std::type_index event_type = typeid(EventType); -    auto handler = std::make_unique<EventHandlerWrapper<EventType>>(callback); +    std::unique_ptr<EventHandlerWrapper<EventType>> handler = std::make_unique<EventHandlerWrapper<EventType>>(callback);      if (channel) { -        auto & handlers_map = subscribers_by_event_id[event_type]; -        auto handlers = handlers_map.find(channel); +        std::unordered_map<int, std::vector<std::unique_ptr<IEventHandlerWrapper>>>& handlers_map = subscribers_by_event_id[event_type]; +        std::unordered_map<int, std::vector<std::unique_ptr<IEventHandlerWrapper>>>::iterator handlers = handlers_map.find(channel);          if (handlers != handlers_map.end()) {              handlers->second.emplace_back(std::move(handler));          } else {              handlers_map[channel].emplace_back(std::move(handler));          }      } else { -        subscribers[event_type].emplace_back(std::move(handler)); +        std::vector<std::unique_ptr<IEventHandlerWrapper>>& handlers = subscribers[event_type]; +        handlers.emplace_back(std::move(handler));      }  } +  template <typename EventType>  void EventManager::queue_event(EventType&& event, int channel) {      std::type_index event_type = std::type_index(typeid(EventType)); @@ -71,10 +150,12 @@ void EventManager::trigger_event(const EventType & event, int eventId) {      std::type_index event_type = std::type_index(typeid(EventType));      if (eventId > 0) { -        auto handlers_it = subscribers_by_event_id[event_type].find(eventId); -        if (handlers_it != subscribers_by_event_id[event_type].end()) { -            auto & callbacks = handlers_it->second; -            for (auto it = callbacks.begin(); it != callbacks.end();) { +        std::unordered_map<int, std::vector<std::unique_ptr<IEventHandlerWrapper>>>& handlers_map = subscribers_by_event_id[event_type]; +        std::unordered_map<int, std::vector<std::unique_ptr<IEventHandlerWrapper>>>::iterator handlers_it = handlers_map.find(eventId); +         +        if (handlers_it != handlers_map.end()) { +            std::vector<std::unique_ptr<IEventHandlerWrapper>>& callbacks = handlers_it->second; +            for (std::vector<std::unique_ptr<IEventHandlerWrapper>>::iterator it = callbacks.begin(); it != callbacks.end();) {                  if ((*it)->exec(event)) {                      it = callbacks.erase(it);                  } else { @@ -83,25 +164,26 @@ void EventManager::trigger_event(const EventType & event, int eventId) {              }          }      } else { -        auto & handlers = subscribers[event_type]; -        for (auto & handler : handlers) { -            handler->exec(event); +        std::vector<std::unique_ptr<IEventHandlerWrapper>>& handlers = subscribers[event_type]; +        for (std::vector<std::unique_ptr<IEventHandlerWrapper>>::iterator it = handlers.begin(); it != handlers.end(); ++it) { +            (*it)->exec(event);          }      }  } +  template <typename EventType>  void EventManager::unsubscribe(const EventHandler<EventType> & callback, int channel) {      std::type_index event_type(typeid(EventType)); -    const std::string handler_name = callback.target_type().name(); +    std::string handler_name = callback.target_type().name();      if (channel) { -        auto subscriber_list = subscribers_by_event_id.find(event_type); +        std::unordered_map<std::type_index, std::unordered_map<int, std::vector<std::unique_ptr<IEventHandlerWrapper>>>>::iterator subscriber_list = subscribers_by_event_id.find(event_type);          if (subscriber_list != subscribers_by_event_id.end()) { -            auto& handlers_map = subscriber_list->second; -            auto handlers = handlers_map.find(channel); +            std::unordered_map<int, std::vector<std::unique_ptr<IEventHandlerWrapper>>>& handlers_map = subscriber_list->second; +            std::unordered_map<int, std::vector<std::unique_ptr<IEventHandlerWrapper>>>::iterator handlers = handlers_map.find(channel);              if (handlers != handlers_map.end()) { -                auto& callbacks = handlers->second; -                for (auto it = callbacks.begin(); it != callbacks.end(); ++it) { +                std::vector<std::unique_ptr<IEventHandlerWrapper>>& callbacks = handlers->second; +                for (std::vector<std::unique_ptr<IEventHandlerWrapper>>::iterator it = callbacks.begin(); it != callbacks.end(); ++it) {                      if ((*it)->get_type() == handler_name) {                          it = callbacks.erase(it);                          return; @@ -110,10 +192,10 @@ void EventManager::unsubscribe(const EventHandler<EventType> & callback, int cha              }          }      } else { -        auto handlers_it = subscribers.find(event_type); +        std::unordered_map<std::type_index, std::vector<std::unique_ptr<IEventHandlerWrapper>>>::iterator handlers_it = subscribers.find(event_type);          if (handlers_it != subscribers.end()) { -            auto& handlers = handlers_it->second; -            for (auto it = handlers.begin(); it != handlers.end(); ++it) { +            std::vector<std::unique_ptr<IEventHandlerWrapper>>& handlers = handlers_it->second; +            for (std::vector<std::unique_ptr<IEventHandlerWrapper>>::iterator it = handlers.begin(); it != handlers.end(); ++it) {                  if ((*it)->get_type() == handler_name) {                      it = handlers.erase(it);                      return; diff --git a/src/crepe/api/IKeyListener.cpp b/src/crepe/api/IKeyListener.cpp index 663dbc7..3a06f77 100644 --- a/src/crepe/api/IKeyListener.cpp +++ b/src/crepe/api/IKeyListener.cpp @@ -1,8 +1,12 @@  #include "IKeyListener.h"  #include <iostream>  IKeyListener::IKeyListener(){ -	 -	subscribe_events(0); +	this->channel = channel; +	subscribe_events(); +} +IKeyListener::IKeyListener(int channel){ +	this->channel = channel; +	subscribe_events(channel);  }  IKeyListener::~IKeyListener() {   	unsubscribe_events();  @@ -24,3 +28,15 @@ void IKeyListener::unsubscribe_events(int listenerId) {      EventManager::get_instance().unsubscribe<KeyReleaseEvent>(key_released_handler , listenerId);  	std::cout << std::endl;  } +void IKeyListener::activate_keys(int listenerId) {  +	if(this->active){ +		return; +	} +	subscribe_events(listenerId);  +} +void IKeyListener::deactivate_keys() {  +	if(!this->active){ +		return; +	} +	unsubscribe_events();  +} diff --git a/src/crepe/api/IKeyListener.h b/src/crepe/api/IKeyListener.h index fc8de16..83949bf 100644 --- a/src/crepe/api/IKeyListener.h +++ b/src/crepe/api/IKeyListener.h @@ -4,18 +4,22 @@  #include "EventManager.h"  class IKeyListener {  public: +	IKeyListener(int channel);  	IKeyListener();      virtual ~IKeyListener();      virtual bool on_key_pressed(const KeyPressEvent & event) = 0;      virtual bool on_key_released(const KeyReleaseEvent & event) = 0; +	void activate_keys(int listenerId = 0); +    void deactivate_keys();  protected:      void subscribe_events(int listenerId = 0);      void unsubscribe_events(int listenerId = 0); -    void activate(int listenerId = 0) { subscribe_events(listenerId); } -    void deactivate(int listenerId = 0) { unsubscribe_events(listenerId); } +      private: +	bool active = true; +	int channel = 0;      EventHandler<KeyPressEvent> key_pressed_handler;      EventHandler<KeyReleaseEvent> key_released_handler;  }; diff --git a/src/makefile b/src/makefile index 03a2c0e..f6907f6 100644 --- a/src/makefile +++ b/src/makefile @@ -103,10 +103,9 @@ WOUTER += crepe/api/IKeyListener.cpp  WOUTER += crepe/api/IKeyListener.h  WOUTER += crepe/api/IMouseListener.cpp  WOUTER += crepe/api/IMouseListener.h -FMT := $(WOUTER) #<<< CHANGE THIS TO YOUR NAME FOR STEP 2 +FMT := $(shell git ls-files '*.c' '*.cpp' '*.h' '*.hpp')  format: FORCE  	clang-tidy -p build/compile_commands.json --fix-errors $(FMT) -# FMT += $(shell git ls-files '*.c' '*.cpp' '*.h' '*.hpp')  # TODO: re-enable linter after all corrections  |