1 #ifndef __eventhandler_h__
2 #define __eventhandler_h__
7 template <typename T
> class Observable
;
9 ///Thing that listens to events - parameterized by the type of event.
10 template <typename T
> class Observer
{
12 virtual ~Observer() = default;
13 ///Called to indicate an event has occurred! Subclasses must implement.
14 virtual void HandleEvent(T evt
)=0;
17 ///An Event handler for a single type of event: maintains a list of listeners,
18 /// allows listeners to (un/)register, and allows dispatching of events to all
20 template <typename T
> class Observable
{
23 void Register(Observer
<T
> *pLstnr
);
24 void Unregister(Observer
<T
> *pLstnr
);
25 void DispatchEvent(T t
);
27 typedef typename
std::list
< Observer
<T
>* > ListenerList
;
28 typedef typename
ListenerList::iterator L_it
;
29 ListenerList m_vListeners
;
30 ListenerList m_vListenersToAdd
;
34 template <typename T
> Observable
<T
>::Observable()
39 ///Utility class for Observers which register with an Observable at construction
40 /// and deregister at destruction. (I.e. which are strictly shorter-lived, than the
41 /// Observable they listen to!)
42 template <typename T
> class TransientObserver
: public Observer
<T
> {
44 TransientObserver(Observable
<T
> *pObservable
) : m_pEventHandler(pObservable
) {
45 m_pEventHandler
->Register(this);
47 virtual ~TransientObserver() {
48 m_pEventHandler
->Unregister(this);
51 Observable
<T
> *m_pEventHandler
;
54 template <typename T
> void Observable
<T
>::Register(Observer
<T
> *pListener
) {
55 if (m_iInHandler
== 0)
56 m_vListeners
.push_back(pListener
);
58 m_vListenersToAdd
.push_back(pListener
);
61 template <typename T
> void Observable
<T
>::Unregister(Observer
<T
> *pListener
) {
62 if (m_iInHandler
== 0)
63 m_vListeners
.remove(pListener
);
65 L_it it
= std::find(m_vListeners
.begin(), m_vListeners
.end(), pListener
);
66 if (it
!= m_vListeners
.end())
71 template <typename T
> void Observable
<T
>::DispatchEvent(T evt
) {
73 // Speed up start-up before any listeners are registered
74 if (m_vListeners
.empty()) return;
76 // Just in case the same event handler was registered twice.
77 if (m_iInHandler
== 0)
78 m_vListeners
.unique();
80 // We may end up here recursively, so keep track of how far down we
81 // are, and only permit new handlers to be registered after all
82 // messages are processed.
84 // An alternative approach would be a message queue - this might actually be a bit more sensible
87 // Loop through components and notify them of the event
88 for(L_it I
=m_vListeners
.begin(), E
=m_vListeners
.end(); I
!=E
; I
++) {
89 if (*I
!= NULL
) { // Listener not removed during iteration
90 (*I
)->HandleEvent(evt
);
96 if (m_iInHandler
== 0) {
97 m_vListeners
.remove(NULL
);
98 m_vListeners
.splice(m_vListeners
.end(), m_vListenersToAdd
);