Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

EventCallback.h

Go to the documentation of this file.
00001 //-*-c++-*-
00002 #ifndef INCLUDED_EventCallback_h_
00003 #define INCLUDED_EventCallback_h_
00004 
00005 #include "Events/EventListener.h"
00006 #include "Shared/string_util.h"
00007 #include "Events/EventRouter.h"
00008 #include <typeinfo>
00009 
00010 //! Listens for a specified event and then forwards to the specified callback
00011 /*! This allows you to avoid the switch-block style of processing for events */
00012 template<class EV>
00013 class EventCallbackAs : public EventListener {
00014 public:
00015   //! constructor, pass zero-argument callback function
00016   template<typename F>
00017   EventCallbackAs(const F& cb) : EventListener(), fun(new FunctorInstance<F,void>(cb)) { }
00018   
00019   //! constructor, pass the user data and single argument callback function
00020   template<typename F, typename C>
00021   EventCallbackAs(const F& cb, C& userdata) : EventListener(), fun(new FunctorInstance<F,C>(cb,userdata)) { }
00022   
00023   //! constructor, pass the user data and single argument callback function
00024   template<typename F, typename C>
00025   EventCallbackAs(const F& cb, const C& userdata) : EventListener(), fun(new FunctorInstance<F,C>(cb,userdata)) { }
00026   
00027   //! constructor, pass zero-argument callback function
00028   template<typename F>
00029   void redirect(const F& cb) { delete fun; fun = new FunctorInstance<F,void>(cb); }
00030   
00031   //! constructor, pass the user data and single argument callback function
00032   template<typename F, typename C>
00033   void redirect(const F& cb, C& userdata) { delete fun; fun=new FunctorInstance<F,C>(cb,userdata); }
00034   
00035   //! constructor, pass the user data and single argument callback function
00036   template<typename F, typename C>
00037   void redirect(const F& cb, const C& userdata) { delete fun; fun=new FunctorInstance<F,C>(cb,userdata); }
00038   
00039   //! destructor
00040   ~EventCallbackAs() { erouter->remove(this); delete fun; fun=NULL; }
00041   
00042 protected:
00043   /*! @cond INTERNAL */
00044   
00045   //! generic base case, supplies a functor interface with no arguments
00046   /*! (subclasses must store the arguments passed to EventCallback constructor) */
00047   struct FunctorAdapter {
00048     virtual ~FunctorAdapter() {}
00049     virtual void operator()(const EV& event)=0;
00050   };
00051   
00052   //! generic template instance, handles std::mem_fun_t and such class based functors
00053   template<typename F, typename C> struct FunctorInstance : public FunctorAdapter {
00054     FunctorInstance(const F& cb, const C& x) : fun(cb), data(x) {}
00055     virtual void operator()(const EV& event) { fun(data,event); }
00056     F fun;
00057     C data;
00058   private:
00059     FunctorInstance(const FunctorInstance&); //!< don't call
00060     FunctorInstance& operator=(const FunctorInstance&); //!< don't call
00061   };
00062   
00063   //! partial specialization, handles non-const member functions
00064   template<typename R, class C, class SUB, class ET> struct FunctorInstance<R (C::*)(const ET&),SUB> : public FunctorAdapter {
00065     FunctorInstance(R (C::*cb)(const EV&), SUB& x) : fun(cb), cl(x) {}
00066     virtual void operator()(const EV& event) { (cl.*fun)(event); }
00067     R (C::*fun)(const EV& event);
00068     SUB& cl;
00069   };
00070   //! partial specialization, handles const member functions
00071   template<typename R, class C, class SUB, class ET> struct FunctorInstance<R (C::*)(const ET&) const,SUB> : public FunctorAdapter {
00072     FunctorInstance(R (C::*cb)(const EV&) const, const SUB& x) : fun(cb), cl(x) {}
00073     virtual void operator()(const EV& event) { (cl.*fun)(event); }
00074     R (C::*fun)(const EV& event) const;
00075     const SUB& cl;
00076   };
00077   //! partial specialization, handles zero-argument functors
00078   template<typename R, class ET> struct FunctorInstance<R (*)(const ET&),void> : public FunctorAdapter {
00079     FunctorInstance(R (*cb)(const EV&)) : fun(cb) {}
00080     virtual void operator()(const EV& event) { fun(event); }
00081     R (*fun)(const EV& event);
00082   };
00083   
00084   //! partial specialization, handles non-const member functions
00085   template<typename R, class C, class SUB, class ET> struct FunctorInstance<R* (C::*)(const ET&),SUB> : public FunctorAdapter {
00086     FunctorInstance(R* (C::*cb)(const EV&), SUB& x) : fun(cb), cl(x) {}
00087     virtual void operator()(const EV& event) { (cl.*fun)(event); }
00088     R* (C::*fun)(const EV& event);
00089     SUB& cl;
00090   };
00091   //! partial specialization, handles const member functions
00092   template<typename R, class C, class SUB, class ET> struct FunctorInstance<R* (C::*)(const ET&) const,SUB> : public FunctorAdapter {
00093     FunctorInstance(R* (C::*cb)(const EV&) const, const SUB& x) : fun(cb), cl(x) {}
00094     virtual void operator()(const EV& event) { (cl.*fun)(event); }
00095     R* (C::*fun)(const EV& event) const;
00096     const SUB& cl;
00097   };
00098   //! partial specialization, handles zero-argument member functions
00099   template<typename R, class ET> struct FunctorInstance<R* (*)(const ET&),void> : public FunctorAdapter {
00100     FunctorInstance(R* (*cb)(const EV&)) : fun(cb) {}
00101     virtual void operator()(const EV& event) { fun(event); }
00102     R* (*fun)(const EV& event);
00103   };
00104   
00105   /*! @endcond */
00106   
00107   virtual void processEvent(const EventBase& event) {
00108     const EV* ev = dynamic_cast<const EV*>(&event);
00109     if(ev==NULL) {
00110       std::cerr << "EventCallback dropping " << event.getDescription() << ", was expected type " << string_util::demangle(typeid(EV).name()) << " not " << string_util::demangle(typeid(event).name()) << std::endl;
00111     } else {
00112       (*fun)(*ev);
00113     }
00114   }
00115   FunctorAdapter * fun;
00116   
00117 private:
00118   EventCallbackAs(const EventCallbackAs&); //!< don't call
00119   EventCallbackAs& operator=(const EventCallbackAs&); //!< don't call
00120 };
00121 
00122 typedef EventCallbackAs<EventBase> EventCallback;
00123 
00124 /*! @file
00125  * @brief EventCallback listens for a specified event and then forwards to the specified callback
00126  * @author Ethan Tira-Thompson (ejt) (Creator)
00127  */
00128 
00129 #endif

Tekkotsu v5.1CVS
Generated Mon May 9 04:58:38 2016 by Doxygen 1.6.3