00001 #ifndef GUI_UTILS___EVENT_HANDLER__HPP
00002 #define GUI_UTILS___EVENT_HANDLER__HPP
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 #include <corelib/ncbiexpt.hpp>
00041 #include <corelib/hash_map.hpp>
00042 #include <corelib/ncbimtx.hpp>
00043
00044 #include <gui/utils/event.hpp>
00045
00046
00047 BEGIN_NCBI_SCOPE
00048
00049 class CEvent;
00050
00051 typedef int TCmdID;
00052
00053
00054 typedef void (CEventHandler::*FEventHandler) (CEvent *);
00055
00056
00057 typedef void (CEventHandler::*FCommandHandler) (void);
00058
00059
00060 typedef void (CEventHandler::*FCommandRangeHandler) (CEvent::TEventID);
00061
00062
00063 typedef void (CEventHandler::*FCommandUpdateHandler) (IEventAttachment*);
00064
00065
00066
00067
00068
00069
00070 #define EVENT_MAP_TX_BEGIN \
00071 virtual void FireEvent(CEvent* evt, \
00072 EDispatch disp_how = eDispatch_Default, \
00073 int pool_name = ePool_Default) \
00074 {
00075
00076 #define EVENT_FIRE_ALL() \
00077 Dispatch(evt, disp_how, pool_name);
00078
00079 #define EVENT_MAP_TX_END \
00080 }
00081
00082
00083
00084
00085 struct SEvtMapEntry
00086 {
00087 CEvent::TEventClass evt_class;
00088 CEvent::TEventTypeInfo type_info;
00089 CEvent::TEventID id;
00090 CEvent::TEventID last_id;
00091 FEventHandler handler;
00092 };
00093
00094
00095
00096 struct SEvtMap
00097 {
00098 const SEvtMap* base_map;
00099 const SEvtMapEntry* entries;
00100 };
00101
00102
00103
00104 #define DECLARE_EVENT_MAP() \
00105 private: \
00106 static const SEvtMapEntry sm_EvtMapEntries[]; \
00107 protected: \
00108 static const SEvtMap sm_EvtMap; \
00109 virtual const SEvtMap* GetEventMap() const
00110
00111
00112 #define BEGIN_EVENT_MAP(thisClass, baseClass) \
00113 const SEvtMap* thisClass::GetEventMap() const \
00114 { return &thisClass::sm_EvtMap; } \
00115 const SEvtMap thisClass::sm_EvtMap = \
00116 { &baseClass::sm_EvtMap, &thisClass::sm_EvtMapEntries[0] }; \
00117 const SEvtMapEntry thisClass::sm_EvtMapEntries[] = \
00118 { \
00119
00120
00121 #define END_EVENT_MAP() \
00122 { CEvent::eEvent_Message, typeid(void).name(), \
00123 CEvent::eEvent_InvalidID, CEvent::eEvent_InvalidID, 0} \
00124 };
00125
00126
00127 #define ON_EVENT(type, id, handler) \
00128 ON_MESSAGE(type, id, handler)
00129
00130 #define ON_MESSAGE(type, id, handler) \
00131 { ncbi::CEvent::eEvent_Message, typeid(type).name(), id, id, (FEventHandler) handler },
00132
00133
00134 #define ON_EVENT_EX(cls, type, id, handler) \
00135 { cls, typeid(type).name(), id, id, (FEventHandler) handler },
00136
00137
00138 #define ON_CMD(type, id, handler) \
00139 { ncbi::CEvent::eEvent_Command, typeid(type).name(), id, id, (FEventHandler) ((FCommandHandler) handler) },
00140
00141
00142 #define ON_CMD_RANGE(type, id, id_last, handler) \
00143 { ncbi::CEvent::eEvent_Command, typeid(type).name(), id, id_last, (FEventHandler) ((FCommandRangeHandler) handler) },
00144
00145
00146 #define ON_CMD_UPDATE(type, id, handler) \
00147 { CEvent::eEvent_CommandUpdate, typeid(type).name(), id, id, (FEventHandler) ((FCommandUpdateHandler)handler) },
00148
00149
00150 #define ON_CMD_UPDATE_RANGE(type, id, id_last, handler) \
00151 { CEvent::eEvent_CommandUpdate, typeid(type).name(), id, id_last, (FEventHandler) ((FCommandUpdateHandler)handler) },
00152
00153
00154 #define ON_EVENT_RANGE(type, id, id_last, handler) \
00155 ON_MESSAGE_RANGE(type, id, id_last, handler)
00156
00157
00158 #define ON_MESSAGE_RANGE(type, id, id_last, handler) \
00159 { CEvent::eEvent_Message, typeid(type).name(), id, id_last, (FEventHandler) handler },
00160
00161
00162 class CEventHandler;
00163
00164 template<> struct hash<CEventHandler*>
00165 {
00166 size_t operator()(CEventHandler* x) const
00167 {
00168 return (size_t) x;
00169 }
00170 };
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198 class CEventHandler
00199 {
00200 public:
00201
00202 enum EDispatch {
00203 eDispatch_SelfOnly,
00204 eDispatch_AllHandlers,
00205 eDispatch_FirstHandler,
00206
00207 eDispatch_Default = eDispatch_AllHandlers
00208 };
00209
00210
00211
00212 enum EPoolName {
00213 ePool_Default = 0,
00214 ePool_Parent,
00215 ePool_Child,
00216 ePool_Sibling,
00217
00218 ePool_NextAvailable
00219 };
00220
00221 typedef vector<CEventHandler*> TListeners;
00222
00223 struct SPostRequest
00224 {
00225 CEventHandler* m_Target;
00226 CRef<CEvent> m_Event;
00227 EDispatch m_DispHow;
00228 int m_PoolName;
00229 };
00230
00231 typedef map<int, TListeners> TPools;
00232 typedef list< AutoPtr<SPostRequest> > TPostRequests;
00233 typedef hash_map<CEventHandler*, int> THandlerToCount;
00234 typedef void (*FOnPostCallback)();
00235
00236 CEventHandler();
00237 virtual ~CEventHandler();
00238
00239
00240
00241
00242
00243
00244
00245 virtual void AddListener(CEventHandler* listener,
00246 int pool_name = ePool_Default);
00247
00248
00249
00250 virtual void RemoveListener(CEventHandler* listener);
00251
00252 virtual void RemoveAllListeners(void);
00253
00254
00255 virtual bool HasListener(CEventHandler* listener,
00256 int pool_name = ePool_Default) const;
00257
00258
00259 virtual const TListeners* GetListeners(int pool_name = ePool_Default) const;
00260
00261
00262 virtual bool OnEvent(CEvent * evt);
00263
00264
00265
00266 virtual bool Dispatch(CEvent* evt,
00267 EDispatch disp_how = eDispatch_Default,
00268 int pool_name = ePool_Default);
00269
00270
00271
00272 virtual bool Send(CEvent* evt,
00273 EDispatch disp_how = eDispatch_Default,
00274 int pool_name = ePool_Default);
00275 virtual bool Send(CEvent* evt, int pool_name);
00276
00277
00278
00279
00280
00281 virtual void Post(CRef<CEvent> evt,
00282 EDispatch disp_how = eDispatch_Default,
00283 int pool_name = ePool_Default);
00284
00285
00286
00287 virtual void FireEvent(CEvent* evt,
00288 EDispatch disp_how = eDispatch_Default,
00289 int pool_name = ePool_Default);
00290
00291
00292
00293 virtual bool OnCommand(const TCmdID cmd);
00294
00295
00296
00297
00298
00299 static void SetPostCallback(FOnPostCallback callback);
00300
00301 static bool HandlePostRequest();
00302
00303
00304 static void ClearPostQueue();
00305 static void DestroyPostQueue();
00306
00307
00308
00309 protected:
00310 DECLARE_EVENT_MAP();
00311
00312
00313 void x_DeclareDead();
00314
00315 void x_AddListenerToPool(CEventHandler* listener, int pool_name);
00316
00317 protected:
00318 TPools m_Pools;
00319
00320 private:
00321
00322
00323 class CPostQueue : public CObject
00324 {
00325 public:
00326 friend class CEventHandler;
00327
00328 static CRef<CPostQueue> GetInstance();
00329 static void DestroyInstance();
00330
00331 ~CPostQueue();
00332
00333 void Post(SPostRequest* req);
00334 bool ExecuteFirstRequest();
00335
00336 void DeclareDead(CEventHandler* handler);
00337 void Clear();
00338
00339 private:
00340 static CRef<CPostQueue> sm_PostQueue;
00341
00342
00343
00344 THandlerToCount m_AliveTargets;
00345
00346 TPostRequests m_Queue;
00347 CMutex m_Mutex;
00348 };
00349
00350 friend class CPostQueue;
00351
00352 private:
00353 CRef<CPostQueue> m_Queue;
00354
00355 static FOnPostCallback sm_PostCallback;
00356 };
00357
00358
00359 END_NCBI_SCOPE
00360
00361
00362
00363 #endif // GUI_UTILS___EVENT_HANDLER__HPP
00364
00365