Updated German translation
[dasher.git] / Src / DasherCore / Observable.h
blob5ddb3a0451fefe83f4ccc294b100f4252b0d9678
1 #ifndef __eventhandler_h__
2 #define __eventhandler_h__
4 #include <list>
5 #include <algorithm>
7 template <typename T> class Observable;
9 ///Thing that listens to events - parameterized by the type of event.
10 template <typename T> class Observer {
11 public:
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
19 /// listeners.
20 template <typename T> class Observable {
21 public:
22 Observable();
23 void Register(Observer<T> *pLstnr);
24 void Unregister(Observer<T> *pLstnr);
25 void DispatchEvent(T t);
26 private:
27 typedef typename std::list< Observer<T>* > ListenerList;
28 typedef typename ListenerList::iterator L_it;
29 ListenerList m_vListeners;
30 ListenerList m_vListenersToAdd;
31 int m_iInHandler;
34 template <typename T> Observable<T>::Observable()
36 m_iInHandler = 0;
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> {
43 public:
44 TransientObserver(Observable<T> *pObservable) : m_pEventHandler(pObservable) {
45 m_pEventHandler->Register(this);
47 virtual ~TransientObserver() {
48 m_pEventHandler->Unregister(this);
50 protected:
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);
57 else
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);
64 else {
65 L_it it = std::find(m_vListeners.begin(), m_vListeners.end(), pListener);
66 if (it != m_vListeners.end())
67 *it = NULL;
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
85 ++m_iInHandler;
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);
94 --m_iInHandler;
96 if (m_iInHandler == 0) {
97 m_vListeners.remove(NULL);
98 m_vListeners.splice(m_vListeners.end(), m_vListenersToAdd);
101 #endif