00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef NEWNET_EVENT_H
00021 #define NEWNET_EVENT_H
00022
00023 #include "nnobject.h"
00024 #include "nnrefptr.h"
00025 #include <vector>
00026 #include <functional>
00027 #include <algorithm>
00028
00029 namespace NewNet
00030 {
00032
00035 template<typename T> class Event : public Object
00036 {
00037 public:
00039
00041 class Callback : public Object
00042 {
00043 public:
00045 Callback() { }
00046
00048 virtual ~Callback() { }
00049
00051
00052 virtual void operator()(T t) = 0;
00053
00054 #ifndef DOXYGEN_UNDOCUMENTED
00055
00056 void onConnected(Event * event)
00057 {
00058 m_Events.push_back(event);
00059 }
00060
00061
00062 void onDisconnected(Event * event)
00063 {
00064 m_Events.erase(std::find(m_Events.begin(), m_Events.end(), event));
00065 }
00066 #endif // DOXYGEN_UNDOCUMENTED
00067
00069
00073 void disconnect()
00074 {
00075
00076
00077 ++(this->refCounter());
00078
00079
00080 while(! m_Events.empty())
00081 m_Events.front()->disconnect(this);
00082
00083
00084 if(--(this->refCounter()))
00085 delete this;
00086 }
00087
00088 private:
00089
00090 Callback(const Callback &) { }
00091 std::vector<Event *> m_Events;
00092 };
00093
00094 private:
00095 #ifndef DOXYGEN_UNDOCUMENTED
00096
00097 template<class ObjectType, typename MethodType> class BoundCallback : public Callback
00098 {
00099 private:
00100
00101 class GuardObjectCallback : public GuardObject::Callback
00102 {
00103 public:
00104 GuardObjectCallback(BoundCallback * callback) : m_Callback(callback)
00105 {
00106 }
00107
00108
00109 void operator()(Object *)
00110 {
00111 m_Callback->onObjectDeleted();
00112 }
00113 private:
00114 BoundCallback * m_Callback;
00115 };
00116 GuardObjectCallback * m_GuardObjectCallback;
00117
00118 public:
00119 BoundCallback(ObjectType * object, MethodType method)
00120 : m_Object(object), m_Method(method)
00121 {
00122
00123 m_GuardObjectCallback = new GuardObjectCallback(this);
00124 m_Object->guardObject() += m_GuardObjectCallback;
00125 }
00126
00127 ~BoundCallback()
00128 {
00129
00130
00131 if(m_Object)
00132 m_Object->guardObject() -= m_GuardObjectCallback;
00133
00134 delete m_GuardObjectCallback;
00135 }
00136
00137 void operator()(T t)
00138 {
00139
00140
00141
00142 if(m_Object)
00143 std::bind1st(std::mem_fun(m_Method), m_Object)(t);
00144 }
00145
00146 protected:
00147
00148
00149 void onObjectDeleted()
00150 {
00151 m_Object = 0;
00152 Callback::disconnect();
00153 }
00154
00155 private:
00156
00157 BoundCallback(const BoundCallback &) { }
00158
00159 ObjectType * m_Object;
00160 MethodType m_Method;
00161 };
00162 #endif // DOXYGEN_UNDOCUMENTED
00163
00164 public:
00166
00167 Event() { }
00168
00170
00172 Event(const Event & that)
00173 {
00174 typename std::vector<RefPtr<Callback> >::const_iterator it, end;
00175 end = that.m_Callbacks.end();
00176 for(it = that.m_Callbacks.begin(); it != end; ++it)
00177 connect(*it);
00178 }
00179
00181
00182 virtual ~Event()
00183 {
00184
00185 clear();
00186 }
00187
00189
00193 void clear()
00194 {
00195 while(! m_Callbacks.empty())
00196 disconnect(m_Callbacks.front());
00197 }
00198
00200
00202 Callback * connect(Callback * callback)
00203 {
00204
00205 m_Callbacks.push_back(callback);
00206
00207
00208 callback->onConnected(this);
00209
00210 return callback;
00211 }
00212
00214
00216 template<class ObjectType, typename MethodType>
00217 static Callback * bind(ObjectType * object, MethodType method)
00218 {
00219 return new BoundCallback<ObjectType, MethodType>(object, method);
00220 }
00221
00223
00226 template<class ObjectType, typename MethodType>
00227 Callback * connect(ObjectType * object, MethodType method)
00228 {
00229 return connect(bind(object, method));
00230 }
00231
00233
00236 void disconnect(Callback * callback)
00237 {
00238
00239
00240 ++(callback->refCounter());
00241
00242
00243 m_Callbacks.erase(std::find(m_Callbacks.begin(), m_Callbacks.end(), callback));
00244
00245
00246 callback->onDisconnected(this);
00247
00248
00249
00250 if(--(callback->refCounter()))
00251 delete callback;
00252 }
00253
00255
00257 void operator()(T t)
00258 {
00259 std::vector<RefPtr<Callback> > callbacks(m_Callbacks);
00260 typename std::vector<RefPtr<Callback> >::iterator it, end = callbacks.end();
00261 for(it = callbacks.begin(); it != end; ++it)
00262 {
00263 (*(*it))(t);
00264 }
00265 }
00266
00267 private:
00268 std::vector<RefPtr<Callback> > m_Callbacks;
00269 };
00270 }
00271
00272 #endif // NEWNET_EVENT_H