EventDelegate.h
1 /*
2  * Medical Image Registration ToolKit (MIRTK)
3  *
4  * Copyright 2013-2015 Imperial College London
5  * Copyright 2013-2015 Andreas Schuh
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 
20 #ifndef MIRTK_EventDelegate_H
21 #define MIRTK_EventDelegate_H
22 
23 #include "mirtk/Observer.h"
24 
25 #include "mirtk/FastDelegate.h"
26 #include "mirtk/UnorderedMap.h"
27 
28 
29 namespace mirtk {
30 
31 
32 /**
33  * Invokes a callback function for observed events
34  *
35  * This class can be registered as observer of an observable object derived
36  * from Observable. It receives the event notifications from the observed
37  * object(s) and dispatches the corresponding registered callback (member)
38  * function (if any). It therefore uses instances of FastDelegate.
39  *
40  * \note Do not derive from this class. Instead add instances of it as attributes
41  * to classes which observe other objects and handle the events.
42  *
43  * \code
44  * EventDelegate delegate;
45  * // Bind non-member function to any event
46  * delegate.Bind(&function);
47  * // Bind static member function to EndEvent
48  * delegate.Bind(EndEvent, &function);
49  * // Bind non-static member function to IterationEvent
50  * delegate.Bind(IterationEvent, MakeDelegate(&obj, &method));
51  * \endcode
52  */
53 class EventDelegate : public Observer
54 {
55  mirtkObjectMacro(EventDelegate);
56 
57  // ---------------------------------------------------------------------------
58  // Types
59 
60  typedef FastDelegate0<> Delegate0;
61  typedef FastDelegate1<Event> Delegate1;
62  typedef FastDelegate2<Event, const void *> Delegate2;
63  typedef FastDelegate3<Observable *, Event, const void *> Delegate3;
64 
65  // ---------------------------------------------------------------------------
66  // Construction/Destruction
67 
68  /// Copy constructor
69  /// \note Intentionally not implemented
71 
72  /// Assignment operator
73  /// \note Intentionally not implemented
74  EventDelegate &operator =(const EventDelegate &);
75 
76 public:
77 
78  /// Default constructor
79  EventDelegate();
80 
81  /// Destructor
83 
84  // ---------------------------------------------------------------------------
85  // Bind callback functions
86 
87  /// Bind callback (member) function for any event with no arguments
88  void Bind(Delegate0);
89 
90  /// Bind callback (member) function for any event with one argument
91  void Bind(Delegate1);
92 
93  /// Bind callback (member) function for any event with two arguments
94  void Bind(Delegate2);
95 
96  /// Bind callback (member) function for any event with four arguments
97  void Bind(Delegate3);
98 
99  /// Bind callback (member) function to specified event
100  void Bind(Event, Delegate0);
101 
102  /// Bind callback (member) function to specified event
103  void Bind(Event, Delegate1);
104 
105  /// Bind callback (member) function to specified event
106  void Bind(Event, Delegate2);
107 
108  /// Bind callback (member) function to specified event
109  void Bind(Event, Delegate3);
110 
111  // ---------------------------------------------------------------------------
112  // Event forwarding
113 
114  /// Forward event notification to registered callback (member) function
115  void HandleEvent(Observable *, Event, const void * = NULL);
116 
117  // ---------------------------------------------------------------------------
118  // Attributes
119 private:
120 
121  /// Auxiliary structure to store disperse callback delegates
122  struct Callback
123  {
124  int _N;
125  DelegateMemento _Memento;
126  Callback() : _N(0), _Memento() {}
127  Callback(DelegateMemento memento, int n) : _N(n), _Memento(memento) {}
128  Callback(const Callback &o) : _N(o._N), _Memento(o._Memento) {}
129  };
130 
131  void Forward(Callback &func, Observable *obj, Event event, const void *data);
132 
133  UnorderedMap<Event, Callback> _SingleEventDelegate; ///< Event delegates
134  Callback _AnyEventDelegate; ///< AnyEvent delegate
135 };
136 
137 ////////////////////////////////////////////////////////////////////////////////
138 // Inline definitions
139 ////////////////////////////////////////////////////////////////////////////////
140 
141 // -----------------------------------------------------------------------------
143 {
144 }
145 
146 // -----------------------------------------------------------------------------
148 {
149 }
150 
151 // -----------------------------------------------------------------------------
152 inline void EventDelegate::Bind(Delegate0 delegate)
153 {
154  _AnyEventDelegate = Callback(delegate.GetMemento(), 0);
155 }
156 
157 // -----------------------------------------------------------------------------
158 inline void EventDelegate::Bind(Delegate1 delegate)
159 {
160  _AnyEventDelegate = Callback(delegate.GetMemento(), 1);
161 }
162 
163 // -----------------------------------------------------------------------------
164 inline void EventDelegate::Bind(Delegate2 delegate)
165 {
166  _AnyEventDelegate = Callback(delegate.GetMemento(), 2);
167 }
168 
169 // -----------------------------------------------------------------------------
170 inline void EventDelegate::Bind(Delegate3 delegate)
171 {
172  _AnyEventDelegate = Callback(delegate.GetMemento(), 3);
173 }
174 
175 // -----------------------------------------------------------------------------
176 inline void EventDelegate::Bind(Event event, Delegate0 delegate)
177 {
178  _SingleEventDelegate[event] = Callback(delegate.GetMemento(), 0);
179 }
180 
181 // -----------------------------------------------------------------------------
182 inline void EventDelegate::Bind(Event event, Delegate1 delegate)
183 {
184  _SingleEventDelegate[event] = Callback(delegate.GetMemento(), 1);
185 }
186 
187 // -----------------------------------------------------------------------------
188 inline void EventDelegate::Bind(Event event, Delegate2 delegate)
189 {
190  _SingleEventDelegate[event] = Callback(delegate.GetMemento(), 2);
191 }
192 
193 // -----------------------------------------------------------------------------
194 inline void EventDelegate::Bind(Event event, Delegate3 delegate)
195 {
196  _SingleEventDelegate[event] = Callback(delegate.GetMemento(), 3);
197 }
198 
199 // -----------------------------------------------------------------------------
200 inline void EventDelegate::Forward(Callback &func, Observable *obj, Event event, const void *data)
201 {
202  switch (func._N) {
203  case 0: {
204  Delegate0 delegate;
205  delegate.SetMemento(func._Memento);
206  if (delegate) delegate();
207  break;
208  }
209  case 1: {
210  Delegate1 delegate;
211  delegate.SetMemento(func._Memento);
212  if (delegate) delegate(event);
213  break;
214  }
215  case 2: {
216  Delegate2 delegate;
217  delegate.SetMemento(func._Memento);
218  if (delegate) delegate(event, data);
219  break;
220  }
221  case 3: {
222  Delegate3 delegate;
223  delegate.SetMemento(func._Memento);
224  if (delegate) delegate(obj, event, data);
225  break;
226  }
227  }
228 }
229 
230 // -----------------------------------------------------------------------------
231 inline void EventDelegate::HandleEvent(Observable *obj, Event event, const void *data)
232 {
233  Forward(_AnyEventDelegate, obj, event, data);
234  UnorderedMap<Event, Callback>::iterator it = _SingleEventDelegate.find(event);
235  if (it != _SingleEventDelegate.end()) Forward(it->second, obj, event, data);
236 }
237 
238 
239 } // namespace mirtk
240 
241 #endif // MIRTK_EventDelegate_H
void HandleEvent(Observable *, Event, const void *=NULL)
Forward event notification to registered callback (member) function.
EventDelegate()
Default constructor.
Definition: IOConfig.h:41
Event
Events that can be observed.
Definition: Event.h:32
void Bind(Delegate0)
Bind callback (member) function for any event with no arguments.
~EventDelegate()
Destructor.