include/gui/utils/event_handler.hpp

Go to the documentation of this file.
00001 #ifndef GUI_UTILS___EVENT_HANDLER__HPP
00002 #define GUI_UTILS___EVENT_HANDLER__HPP
00003 
00004 /*  $Id: event_handler.hpp 18500 2008-12-12 02:25:35Z dicuccio $
00005  * ===========================================================================
00006  *
00007  *                            PUBLIC DOMAIN NOTICE
00008  *               National Center for Biotechnology Information
00009  *
00010  *  This software/database is a "United States Government Work" under the
00011  *  terms of the United States Copyright Act.  It was written as part of
00012  *  the author's official duties as a United States Government employee and
00013  *  thus cannot be copyrighted.  This software/database is freely available
00014  *  to the public for use. The National Library of Medicine and the U.S.
00015  *  Government have not placed any restriction on its use or reproduction.
00016  *
00017  *  Although all reasonable efforts have been taken to ensure the accuracy
00018  *  and reliability of the software and data, the NLM and the U.S.
00019  *  Government do not and cannot warrant the performance or results that
00020  *  may be obtained by using this software or data. The NLM and the U.S.
00021  *  Government disclaim all warranties, express or implied, including
00022  *  warranties of performance, merchantability or fitness for any particular
00023  *  purpose.
00024  *
00025  *  Please cite the author in any work or product based on this material.
00026  *
00027  * ===========================================================================
00028  *
00029  * Authors:  Vladimir Tereshkov, Andrey Yazhuk
00030  *
00031  * File Description:
00032  *    Endpoint or target for public event.
00033  */
00034 
00035 /** @addtogroup GUI_UTILS
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 /// event handler
00054 typedef     void (CEventHandler::*FEventHandler)   (CEvent *);
00055 
00056 /// command handler
00057 typedef     void (CEventHandler::*FCommandHandler) (void);
00058 
00059 /// command range handler
00060 typedef     void (CEventHandler::*FCommandRangeHandler) (CEvent::TEventID);
00061 
00062 /// update command handler
00063 typedef     void (CEventHandler::*FCommandUpdateHandler) (IEventAttachment*);
00064 
00065 
00066 
00067 ///////////////////////////////////////////////////////////////////////////////
00068 /// Event Dispatcher macros
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 /// Command map entry.
00085 struct SEvtMapEntry
00086 {
00087     CEvent::TEventClass     evt_class; /// message or command or update
00088     CEvent::TEventTypeInfo  type_info; /// Type Information
00089     CEvent::TEventID        id;        /// Event ID (or ID range start)
00090     CEvent::TEventID        last_id;   /// Envent ID range end
00091     FEventHandler           handler;   /// pointer to command handler mapped to the Command ID
00092 };
00093 
00094 
00095 /// Command Map.
00096 struct SEvtMap
00097 {
00098     const SEvtMap*        base_map; /// pointer to command map of the base class
00099     const SEvtMapEntry*   entries;  /// pointer to array of map entries
00100 };
00101 
00102 
00103 // MACRO for declaring and defining command maps
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 /// Begins definition of Command Map for CEventHandler-derived class.
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 /// Ends definition of Command Map.
00121 #define END_EVENT_MAP() \
00122     { CEvent::eEvent_Message, typeid(void).name(), \
00123       CEvent::eEvent_InvalidID, CEvent::eEvent_InvalidID, 0} \
00124     };
00125 
00126 /// Adds a Message as Command Map entry
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 /// Adds a Command Map entry mapping given command id to given command handler.
00134 #define ON_EVENT_EX(cls, type, id, handler) \
00135 { cls, typeid(type).name(), id, id, (FEventHandler) handler },
00136 
00137 /// Adds a Command as Command Map entry
00138 #define ON_CMD(type, id, handler) \
00139 { ncbi::CEvent::eEvent_Command, typeid(type).name(), id, id, (FEventHandler) ((FCommandHandler) handler) },
00140 
00141 /// Adds a Command Range as Command Map entry
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 /// Adds a Update Command as Command Map entry
00146 #define ON_CMD_UPDATE(type, id, handler) \
00147 { CEvent::eEvent_CommandUpdate, typeid(type).name(), id, id, (FEventHandler) ((FCommandUpdateHandler)handler) },
00148 
00149 /// Adds a Update Command Range as Command Map entry
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 /// Adds a Command Map entry mapping given command range to given command handler.
00154 #define ON_EVENT_RANGE(type, id, id_last, handler) \
00155     ON_MESSAGE_RANGE(type, id, id_last, handler)
00156 
00157 /// Adds a Command Map entry mapping given message range to given command handler.
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 /// CEventHandler
00175 ///
00176 /// CEventHandler provides basic support for event handling. Event handling
00177 /// includes processing events and dispatching events.
00178 /// Processing involves recognizing an event of the particular type and invoking
00179 /// a corresponding callback. CEventHandler provide support for mapping events
00180 /// to callback by means of Event Maps (see macros in this file). A class can
00181 /// define its own Event Map that can be inherited from the Event map of the
00182 /// base class.
00183 /// Dispatching is a process of forwarding an event to other CEventHandler-s
00184 /// subscribed as listeners to the current handler. Dispatching algorithm can be
00185 /// controlled by specifying a strategy (EDispatch enumeration).
00186 /// All events are dispatched within pools. Pools are isolated networks of
00187 /// listeners subscribed to each other. An event sent to a pool will reach only
00188 /// listeners added to this particular pool, all other listeners will be ignored.
00189 /// CEventHandler has several entry points:
00190 ///   OnEvent() – processes an event, locates a callback corresponding to it
00191 ///               and executes the callback.
00192 ///   Dispatch() – dispatches an event to listeners.
00193 ///   Send() – synchronously handles events by calling OnEvent() and Dispatch().
00194 ///   Post() – posts an event to the event queue. Events are retrieved from the
00195 ///            queue by HandlePostRequest() and then sent to the handler.
00196 
00197 
00198 class  CEventHandler
00199 {
00200 public:
00201     /// enum controlling dispatching strategies
00202     enum EDispatch {
00203         eDispatch_SelfOnly,      /// handle and do not dispatch to listeners
00204         eDispatch_AllHandlers,   /// dispatch to all handlers
00205         eDispatch_FirstHandler,  /// dispatch until handled at least by one handler
00206 
00207         eDispatch_Default = eDispatch_AllHandlers
00208     };
00209 
00210     /// Identifiers for standard pools. Set of pools is extandable, programmers can
00211     /// define their own pools but need to make sure that pool identifiers are unique.
00212     enum EPoolName {
00213         ePool_Default = 0,
00214         ePool_Parent,
00215         ePool_Child,
00216         ePool_Sibling,
00217 
00218         ePool_NextAvailable /// this needs to be last!
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     /// @name Event Dispatching Interface
00240     /// @{
00241 
00242     /// Add a listener.  The listener will always be added to the default pool;
00243     /// the 'name' parameter may be used to indicate an additional pool to which
00244     // the listener is subscribed.
00245     virtual void AddListener(CEventHandler* listener,
00246                              int pool_name = ePool_Default);
00247 
00248     /// Remove a listener. This will remove the listener from all pools in which
00249     /// it exists.
00250     virtual void RemoveListener(CEventHandler* listener);
00251 
00252     virtual void RemoveAllListeners(void);
00253 
00254     /// returns "true" if the given listener belongs to the specified pool
00255     virtual bool HasListener(CEventHandler* listener,
00256                              int pool_name = ePool_Default) const;
00257 
00258     /// returns a set of listeners fro the specified pool
00259     virtual const TListeners*   GetListeners(int pool_name = ePool_Default) const;
00260 
00261     /// Processes en event. Returns "true" if event has been processed.
00262     virtual bool OnEvent(CEvent * evt);
00263 
00264     /// Dispatches an event to the listeners (but does not handle it). Returns
00265     /// "true" if event has been dispatched and handled by a listener.
00266     virtual bool Dispatch(CEvent* evt,
00267                           EDispatch disp_how = eDispatch_Default,
00268                           int pool_name = ePool_Default);
00269 
00270     /// Sends an event synchronously. Returns "true" if event has been handled.
00271     /// An event that is provided as the argument can be created on heap or stack.
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     /// Handles an event asynchronously (process and/or dispatch). The event
00278     /// will be posted to the event queue and then Post() will return, the event
00279     /// will be processed at indefenite point in time after Post() returns.
00280     /// The event must be created on heap and managed by CRef.
00281     virtual void    Post(CRef<CEvent> evt,
00282                          EDispatch disp_how = eDispatch_Default,
00283                          int pool_name = ePool_Default);
00284     /// @}
00285 
00286     /// FireEvent - depricated, TODO - remove
00287     virtual void    FireEvent(CEvent* evt,
00288                               EDispatch disp_how = eDispatch_Default,
00289                               int pool_name = ePool_Default);
00290 
00291 
00292     /// moved from CCommandTarget
00293     virtual bool    OnCommand(const TCmdID cmd);
00294 
00295     /// @name Static API
00296     /// @{
00297     /// extracts the next request from the Post Queue and sends it to the target
00298     /// returns true if the Queue is empty
00299     static void SetPostCallback(FOnPostCallback callback);
00300 
00301     static bool HandlePostRequest();
00302 
00303     /// erases all events from the queue
00304     static void ClearPostQueue();
00305     static void DestroyPostQueue();
00306 
00307     /// @}
00308 
00309 protected:
00310     DECLARE_EVENT_MAP();
00311 
00312     /// Removes itself unavailable for async event delivery.
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     /// CPostQueue - singleton queue for asynchronous events
00322     /// all methods are synchronized
00323     class CPostQueue : public CObject
00324     {
00325     public:
00326         friend class CEventHandler;
00327 
00328         static CRef<CPostQueue>    GetInstance(); /// returns Singleton
00329         static void     DestroyInstance(); /// destroys singleton
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; /// the only instance
00341 
00342         /// contains pointer to "alive" event targets and number of events for every target.
00343         /// When target is destroyed it must remove itself from this map.
00344         THandlerToCount m_AliveTargets;
00345 
00346         TPostRequests   m_Queue; /// queue of Events for async sending
00347         CMutex          m_Mutex; /// mutex guarding the sm_PostQueue and sm
00348     };
00349 
00350     friend class CPostQueue;
00351 
00352 private:
00353     CRef<CPostQueue>    m_Queue; /// a reference to the singleton (to make sure that
00354     /// the queue will not be destroyed until the Last handler is destroyed
00355     static FOnPostCallback  sm_PostCallback;
00356 };
00357 
00358 
00359 END_NCBI_SCOPE
00360 
00361 /* @} */
00362 
00363 #endif  // GUI_UTILS___EVENT_HANDLER__HPP
00364 
00365 

Generated on Wed Dec 9 03:13:25 2009 for NCBI C++ ToolKit by  doxygen 1.4.6
Modified on Wed Dec 09 08:17:30 2009 by modify_doxy.py rev. 173732