Observable.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_Observable_H
21 #define MIRTK_Observable_H
22 
23 #include "mirtk/Object.h"
24 
25 #include "mirtk/Observer.h"
26 #include "mirtk/OrderedSet.h"
27 #include "mirtk/Event.h"
28 
29 
30 namespace mirtk {
31 
32 
33 /**
34  * Base class for an observable object
35  *
36  * Any object which should be observable must derive from irtkObservable
37  * instead of irtkObject. A client which wants to observe events emitted
38  * by an observable must use an instance of irtkObservable and register
39  * callback functions at this instance for the events of interest.
40  *
41  * \attention Adding and removing observers is not thread-safe!
42  */
43 class Observable : public Object
44 {
45  mirtkAbstractMacro(Observable);
46 
47  /// Container storing pointers to observers
48  typedef OrderedSet<Observer *> ObserverSet;
49 
50  /// Iterator for registered observers
51  typedef ObserverSet::iterator ObserverIterator;
52 
53  /// Whether this object has changed and should notify observers upon request
54  mirtkPublicAttributeMacro(bool, Changed);
55 
56  /// Registered observers
57  mirtkAttributeMacro(ObserverSet, Observers);
58 
59  /// Copy attributes of this class from another instance
60  void CopyAttributes(const Observable &);
61 
62 protected:
63 
64  /// Default constructor
65  Observable();
66 
67  /// Copy constructor
68  Observable(const Observable &);
69 
70  /// Assignment operator
72 
73 public:
74 
75  /// Destructor
76  virtual ~Observable();
77 
78  /// Number of current observers
79  int NumberOfObservers() const;
80 
81  /// Add observer
82  void AddObserver(Observer &);
83 
84  /// Delete observer
85  void DeleteObserver(Observer &);
86 
87  /// Delete all observers
88  void ClearObservers();
89 
90  /// Broadcast event to observers
91  void Broadcast(Event, const void * = NULL);
92 
93  /// Notify all observers about given event if this object has changed
94  void NotifyObservers(Event, const void * = NULL);
95 
96 };
97 
98 ////////////////////////////////////////////////////////////////////////////////
99 // Auxiliary macro for broadcasting log messages
100 ////////////////////////////////////////////////////////////////////////////////
101 
102 /// Broadcast a LogEvent message
103 #define MIRTK_LOG_EVENT(msg) \
104  do { \
105  ostringstream ss; \
106  ss << msg; \
107  Broadcast(mirtk::LogEvent, ss.str().c_str()); \
108  } while(false)
109 
110 ////////////////////////////////////////////////////////////////////////////////
111 // Inline definitions
112 ////////////////////////////////////////////////////////////////////////////////
113 
114 // =============================================================================
115 // Construction/Destruction
116 // =============================================================================
117 
118 // -----------------------------------------------------------------------------
120 :
121  _Changed(false)
122 {
123 }
124 
125 // -----------------------------------------------------------------------------
126 inline void Observable::CopyAttributes(const Observable &other)
127 {
128  _Changed = other._Changed;
129  // Do not copy observers!
130 }
131 
132 // -----------------------------------------------------------------------------
133 inline Observable::Observable(const Observable &other)
134 :
135  Object(other)
136 {
137  CopyAttributes(other);
138 }
139 
140 // -----------------------------------------------------------------------------
142 {
143  if (this != &other) {
144  Object::operator =(other);
145  CopyAttributes(other);
146  Changed(true);
147  }
148  return *this;
149 }
150 
151 // -----------------------------------------------------------------------------
153 {
154  for (ObserverIterator it = _Observers.begin(); it != _Observers.end(); ++it) {
155  (*it)->StopObserving(this);
156  }
157  _Observers.clear();
158 }
159 
160 // -----------------------------------------------------------------------------
162 {
163  ClearObservers();
164 }
165 
166 // =============================================================================
167 // Add/Remove observer
168 // =============================================================================
169 
170 // -----------------------------------------------------------------------------
172 {
173  return static_cast<int>(_Observers.size());
174 }
175 
176 // -----------------------------------------------------------------------------
177 inline void Observable::AddObserver(Observer &observer)
178 {
179  _Observers.insert(&observer);
180  observer.StartObserving(this);
181 }
182 
183 // -----------------------------------------------------------------------------
184 inline void Observable::DeleteObserver(Observer &observer)
185 {
186  observer.StopObserving(this);
187  _Observers.erase(&observer);
188 }
189 
190 // =============================================================================
191 // Events
192 // =============================================================================
193 
194 // -----------------------------------------------------------------------------
195 inline void Observable::Broadcast(Event event, const void *data)
196 {
197  for (ObserverIterator it = _Observers.begin(); it != _Observers.end(); ++it) {
198  (*it)->HandleEvent(this, event, data);
199  }
200 }
201 
202 // -----------------------------------------------------------------------------
203 inline void Observable::NotifyObservers(Event event, const void *data)
204 {
205  if (_Changed) {
206  Broadcast(event, data);
207  Changed(false);
208  }
209 }
210 
211 
212 } // namespace mirtk
213 
214 #endif // MIRTK_Observable_H
void DeleteObserver(Observer &)
Delete observer.
Definition: Observable.h:184
void Broadcast(Event, const void *=NULL)
Broadcast event to observers.
Definition: Observable.h:195
void AddObserver(Observer &)
Add observer.
Definition: Observable.h:177
void NotifyObservers(Event, const void *=NULL)
Notify all observers about given event if this object has changed.
Definition: Observable.h:203
Definition: IOConfig.h:41
int NumberOfObservers() const
Number of current observers.
Definition: Observable.h:171
void ClearObservers()
Delete all observers.
Definition: Observable.h:152
Observable()
Default constructor.
Definition: Observable.h:119
Event
Events that can be observed.
Definition: Event.h:32
virtual ~Observable()
Destructor.
Definition: Observable.h:161
Observable & operator=(const Observable &)
Assignment operator.
Definition: Observable.h:141