Photon Editor Library 2.0.0-beta
A physically based renderer.
Loading...
Searching...
No Matches
TEventDispatcher.h
Go to the documentation of this file.
1#pragma once
2
5
6#include <Utility/TFunction.h>
7#include <Common/primitive_type.h>
8#include <Common/assertion.h>
9#include <Common/exceptions.h>
10#include <Utility/TUniquePtrVector.h>
11
12#include <limits>
13#include <type_traits>
14#include <utility>
15#include <cstddef>
16#include <vector>
17
18namespace ph::editor
19{
20
21template<typename EventType>
23{
24 static_assert(std::is_base_of_v<Event, EventType>);
25
26public:
28
29public:
31
41 void removeListener(Listener* listener);
42
48
55 template<typename DispatchFunc>
56 void dispatch(const EventType& e, DispatchFunc dispatchFunc);
57
58 void dispatch(const EventType& e);
59
60private:
61 TUniquePtrVector<Listener> m_listeners;
62 std::vector<Listener*> m_listenersToRemove;
63 bool m_isDispatching = false;
64};
65
66template<typename EventType>
68 -> Listener*
69{
70 return m_listeners.add(std::make_unique<Listener>(std::move(listener)));
71}
72
73template<typename EventType>
75{
76 if(!listener)
77 {
78 return;
79 }
80
81 // Add to the pending-to-remove queue, will actually be removed in `dispatch()`
82 m_listenersToRemove.push_back(listener);
83}
84
85template<typename EventType>
87{
88 if(!listener)
89 {
90 return;
91 }
92
93 if(m_isDispatching)
94 {
95 throw IllegalOperationException(
96 "Cannot remove listeners during dispatch. Use removeListener(1) instead.");
97 }
98
99 const auto removedListener = m_listeners.remove(listener);
100 PH_ASSERT(removedListener != nullptr);
101}
102
103template<typename EventType>
104template<typename DispatchFunc>
105inline void TEventDispatcher<EventType>::dispatch(const EventType& e, DispatchFunc dispatchFunc)
106{
107 static_assert(std::is_invocable_v<DispatchFunc, EventType, Listener>,
108 "DispatchFunc must take (EventType, Listener).");
109
110 // Only actually remove listeners before dispatch--so other listeners can be kept valid
111 // during dispatch. Also, removal is done before dispatch so calls to `removeListener()`
112 // are respected. Calling `removeListener()` during dispatch will take effect in the next dispatch.
113 for(Listener* listener : m_listenersToRemove)
114 {
115 removeListenerImmediately(listener);
116 }
117 m_listenersToRemove.clear();
118
119 // Iterate through all listeners and invoke the dispatch function on each of them. The code is
120 // aware of that listeners might get added/removed (calling `addListener()` and `removeListener()`)
121 // in the call to dispatch function. Listeners added/removed in the dispatch function will only
122 // participate in the next call to `dispatch()`.
123
124 // Record current count so newly added listeners will not get involved this time
125 const auto numListeners = m_listeners.size();
126
127 // Guard against nested dispatch call
128 PH_ASSERT(!m_isDispatching);
129
130 m_isDispatching = true;
131 for(std::size_t listenerIdx = 0; listenerIdx < numListeners; ++listenerIdx)
132 {
133 dispatchFunc(e, *m_listeners[listenerIdx]);
134 }
135 m_isDispatching = false;
136}
137
138template<typename EventType>
139inline void TEventDispatcher<EventType>::dispatch(const EventType& e)
140{
141 dispatch(
142 e,
143 [](const EventType& e, const Listener& listener)
144 {
145 listener(e);
146 });
147}
148
149}// end namespace ph
Definition TEventDispatcher.h:23
void removeListener(Listener *listener)
Remove a listener that was added to this dispatcher. The listener will not be removed immediately....
Definition TEventDispatcher.h:74
void dispatch(const EventType &e)
Definition TEventDispatcher.h:139
TEventListener< EventType > Listener
Definition TEventDispatcher.h:27
void removeListenerImmediately(Listener *listener)
Immediately remove a listener that was added to this dispatcher.
Definition TEventDispatcher.h:86
Listener * addListener(Listener listener)
Definition TEventDispatcher.h:67
void dispatch(const EventType &e, DispatchFunc dispatchFunc)
Submit an event to the listeners.
Definition TEventDispatcher.h:105
Definition ph_editor.h:10
TFunction< void(const EventType &e)> TEventListener
Definition TEventListener.h:9