aboutsummaryrefslogtreecommitdiff
path: root/include/cru
diff options
context:
space:
mode:
Diffstat (limited to 'include/cru')
-rw-r--r--include/cru/common/event.hpp127
-rw-r--r--include/cru/ui/window.hpp2
2 files changed, 87 insertions, 42 deletions
diff --git a/include/cru/common/event.hpp b/include/cru/common/event.hpp
index 6228d867..987bcdd6 100644
--- a/include/cru/common/event.hpp
+++ b/include/cru/common/event.hpp
@@ -2,73 +2,102 @@
#include "base.hpp"
#include <functional>
+#include <list>
#include <map>
#include <memory>
#include <utility>
namespace cru {
-using EventHandlerRevoker = std::function<void()>;
+class EventRevoker;
+
+namespace details {
+class EventBase {
+ friend EventRevoker;
+
+ protected:
+ using EventHandlerToken = long;
+
+ EventBase() : resolve_ptr_(new std::reference_wrapper(*this)) {}
+
+ EventBase(const EventBase& other) = delete;
+ EventBase(EventBase&& other) = delete;
+ EventBase& operator=(const EventBase& other) = delete;
+ EventBase& operator=(EventBase&& other) = delete;
+ virtual ~EventBase() = default;
+
+ virtual void RemoveHandler(EventHandlerToken token) = 0;
+
+ inline EventRevoker CreateRevoker(EventHandlerToken token);
+
+ private:
+ std::shared_ptr<std::reference_wrapper<EventBase>> resolve_ptr_;
+};
+} // namespace details
+
+class EventRevoker {
+ friend class ::cru::details::EventBase;
-// A non-copyable non-movable Event class.
-// It stores a list of event handlers.
-template <typename... TArgs>
-class Event {
private:
- using EventResolver = std::function<Event*()>;
- class EventHandlerRevokerImpl {
- public:
- EventHandlerRevokerImpl(const std::shared_ptr<EventResolver>& resolver,
- long token)
- : resolver_(resolver), token_(token) {}
- EventHandlerRevokerImpl(const EventHandlerRevokerImpl& other) = default;
- EventHandlerRevokerImpl(EventHandlerRevokerImpl&& other) = default;
- EventHandlerRevokerImpl& operator=(const EventHandlerRevokerImpl& other) =
- default;
- EventHandlerRevokerImpl& operator=(EventHandlerRevokerImpl&& other) =
- default;
- ~EventHandlerRevokerImpl() = default;
-
- void operator()() {
- const auto true_resolver = resolver_.lock();
- if (true_resolver) {
- (*true_resolver)()->RemoveHandler(token_);
- }
+ EventRevoker(const std::shared_ptr<
+ std::reference_wrapper<details::EventBase>>& resolve_ptr,
+ details::EventBase::EventHandlerToken token)
+ : weak_ptr_(resolve_ptr), token_(token) {}
+
+ public:
+ EventRevoker(const EventRevoker& other) = default;
+ EventRevoker(EventRevoker&& other) = default;
+ EventRevoker& operator=(const EventRevoker& other) = default;
+ EventRevoker& operator=(EventRevoker&& other) = default;
+ ~EventRevoker() = default;
+
+ void operator()() const {
+ const auto true_resolver = weak_ptr_.lock();
+ if (true_resolver) {
+ (*true_resolver).get().RemoveHandler(token_);
}
+ }
+
+ private:
+ std::weak_ptr<std::reference_wrapper<details::EventBase>> weak_ptr_;
+ details::EventBase::EventHandlerToken token_;
+};
- private:
- std::weak_ptr<EventResolver> resolver_;
- long token_;
- };
+inline EventRevoker details::EventBase::CreateRevoker(EventHandlerToken token) {
+ return EventRevoker(resolve_ptr_, token);
+}
+// A non-copyable non-movable Event class.
+// It stores a list of event handlers.
+template <typename... TArgs>
+class Event : public details::EventBase {
public:
using EventHandler = std::function<void(TArgs...)>;
- Event()
- : event_resolver_(new std::function<Event*()>([this] { return this; })) {}
+ Event() = default;
Event(const Event&) = delete;
Event& operator=(const Event&) = delete;
Event(Event&&) = delete;
Event& operator=(Event&&) = delete;
~Event() = default;
- EventHandlerRevoker AddHandler(const EventHandler& handler) {
+ EventRevoker AddHandler(const EventHandler& handler) {
const auto token = current_token_++;
handlers_.emplace(token, handler);
- return EventHandlerRevoker(EventHandlerRevokerImpl(event_resolver_, token));
+ return CreateRevoker(token);
}
- EventHandlerRevoker AddHandler(EventHandler&& handler) {
+ EventRevoker AddHandler(EventHandler&& handler) {
const auto token = current_token_++;
handlers_.emplace(token, std::move(handler));
- return EventHandlerRevoker(EventHandlerRevokerImpl(event_resolver_, token));
+ return CreateRevoker(token);
}
template <typename Arg>
- EventHandlerRevoker AddHandler(Arg&& handler) {
+ EventRevoker AddHandler(Arg&& handler) {
static_assert(std::is_invocable_v<Arg, TArgs...>, "Handler not invocable.");
const auto token = current_token_++;
handlers_.emplace(token, EventHandler(std::forward<Arg>(handler)));
- return EventHandlerRevoker(EventHandlerRevokerImpl(event_resolver_, token));
+ return CreateRevoker(token);
}
template <typename... Args>
@@ -77,15 +106,31 @@ class Event {
(handler.second)(std::forward<Args>(args)...);
}
- private:
- void RemoveHandler(const long token) {
+ protected:
+ void RemoveHandler(EventHandlerToken token) override {
auto find_result = handlers_.find(token);
if (find_result != handlers_.cend()) handlers_.erase(find_result);
}
private:
- std::map<long, EventHandler> handlers_{};
- long current_token_ = 0;
- std::shared_ptr<EventResolver> event_resolver_;
+ std::map<EventHandlerToken, EventHandler> handlers_{};
+ EventHandlerToken current_token_ = 0;
+};
+
+class EventRevokerGuard {
+ public:
+ EventRevokerGuard() = default;
+ EventRevokerGuard(const EventRevokerGuard& other) = delete;
+ EventRevokerGuard(EventRevokerGuard&& other) = delete;
+ EventRevokerGuard& operator=(const EventRevokerGuard& other) = delete;
+ EventRevokerGuard& operator=(EventRevokerGuard&& other) = delete;
+ ~EventRevokerGuard() {
+ for (const auto revoker : revokers_) revoker();
+ }
+
+ void Add(EventRevoker revoker) { revokers_.push_back(std::move(revoker)); }
+
+ private:
+ std::list<EventRevoker> revokers_;
};
} // namespace cru
diff --git a/include/cru/ui/window.hpp b/include/cru/ui/window.hpp
index 991ebf70..9a76f30f 100644
--- a/include/cru/ui/window.hpp
+++ b/include/cru/ui/window.hpp
@@ -81,7 +81,7 @@ class Window final : public ContentControl {
private:
platform::NativeWindow* native_window_;
- std::vector<EventHandlerRevoker> event_revokers_;
+ EventRevokerGuard event_revoker_guard_;
std::shared_ptr<render::WindowRenderObject> render_object_;