/* * Copyright (C) 2007-2010 Xagasoft, All rights reserved. * * This file is part of the libbu++ library and is released under the * terms of the license contained in the file LICENSE. */ #ifndef BU_OBJECT_SIGNALS_H #define BU_OBJECT_SIGNALS_H #include "bu/util.h" #include "bu/exceptionbase.h" namespace Bu { subExceptionDecl( SignalException ); // // 0 Parameters // template<typename ret> class _Slot0 { public: _Slot0() { } virtual ~_Slot0() { } virtual ret operator()()=0; virtual _Slot0<ret> *clone() const=0; }; template<typename cls, typename ret> class __Slot0 : public _Slot0<ret> { public: __Slot0( cls *pCls, ret (cls::*pFnc)() ) : pCls( pCls ), pFnc( pFnc ) { } virtual ~__Slot0() { } virtual ret operator()() { return (pCls->*pFnc)(); } virtual _Slot0<ret> *clone() const { return new __Slot0<cls, ret>( pCls, pFnc ); } private: cls *pCls; ret (cls::*pFnc)(); }; template<typename ret> class __Slot0F : public _Slot0<ret> { public: __Slot0F( ret (*pFnc)() ) : pFnc( pFnc ) { } virtual ~__Slot0F() { } virtual ret operator()() { return (*pFnc)(); } virtual _Slot0<ret> *clone() const { return new __Slot0F<ret>( pFnc ); } private: ret (*pFnc)(); }; template<typename ret> class Signal0 { public: Signal0() : pCb( NULL ) { } Signal0( _Slot0<ret> *pCb ) : pCb( pCb ) { } Signal0( const Signal0<ret> &rSrc ) : pCb( (rSrc.pCb)?(rSrc.pCb->clone()):(NULL) ) { } virtual ~Signal0() { delete pCb; pCb = NULL; } ret operator()() { if( !pCb ) throw SignalException("Uninitialized signal used."); return (*pCb)(); } bool isSet() const { return pCb != NULL; } operator bool() const { return isSet(); } Signal0<ret> &operator=( const Signal0<ret> &rhs ) { pCb = rhs.pCb->clone(); return *this; } private: _Slot0<ret> *pCb; }; template<typename cls, typename ret> Signal0<ret> slot( cls *pCls, ret (cls::*pFnc)() ) { if( !pCls || !pFnc ) throw SignalException("NULL pointer in slot()."); return Signal0<ret>( new __Slot0<cls, ret>( pCls, pFnc ) ); } template<typename ret> Signal0<ret> slot( ret (*pFnc)() ) { if( !pFnc ) throw SignalException("NULL pointer in slot()."); return Signal0<ret>( new __Slot0F<ret>( pFnc ) ); } // // 1 Parameter // template<typename ret, typename p1t> class _Slot1 { public: _Slot1() { } virtual ~_Slot1() { } virtual ret operator()( p1t p1 )=0; virtual _Slot1<ret, p1t> *clone() const=0; }; template<typename cls, typename ret, typename p1t> class __Slot1 : public _Slot1<ret, p1t> { public: __Slot1( cls *pCls, ret (cls::*pFnc)( p1t ) ) : pCls( pCls ), pFnc( pFnc ) { } virtual ~__Slot1() { } virtual ret operator()( p1t p1 ) { return (pCls->*pFnc)( p1 ); } virtual _Slot1<ret, p1t> *clone() const { return new __Slot1<cls, ret, p1t>( pCls, pFnc ); } private: cls *pCls; ret (cls::*pFnc)( p1t ); }; template<typename ret, typename p1t> class __Slot1F : public _Slot1<ret, p1t> { public: __Slot1F( ret (*pFnc)( p1t ) ) : pFnc( pFnc ) { } virtual ~__Slot1F() { } virtual ret operator()( p1t p1 ) { return (*pFnc)( p1 ); } virtual _Slot1<ret, p1t> *clone() const { return new __Slot1F<ret, p1t>( pFnc ); } private: ret (*pFnc)( p1t p1 ); }; template<typename ret, typename p1t> class Signal1 { public: Signal1() : pCb( NULL ) { } Signal1( _Slot1<ret, p1t> *pCb ) : pCb( pCb ) { } Signal1( const Signal1<ret, p1t> &rSrc ) : pCb( (rSrc.pCb)?(rSrc.pCb->clone()):(NULL) ) { } virtual ~Signal1() { delete pCb; pCb = NULL; } ret operator()( p1t p1 ) { if( !pCb ) throw SignalException("Uninitialized signal used."); return (*pCb)( p1 ); } bool isSet() const { return pCb != NULL; } operator bool() const { return isSet(); } Signal1<ret, p1t> &operator=( const Signal1<ret, p1t> &rhs ) { pCb = rhs.pCb->clone(); return *this; } private: _Slot1<ret, p1t> *pCb; }; template<typename cls, typename ret, typename p1t> Signal1<ret, p1t> slot( cls *pCls, ret (cls::*pFnc)( p1t ) ) { if( !pCls || !pFnc ) throw SignalException("NULL pointer in slot()."); return Signal1<ret, p1t>( new __Slot1<cls, ret, p1t>( pCls, pFnc ) ); } template<typename ret, typename p1t> Signal1<ret, p1t> slot( ret (*pFnc)( p1t ) ) { if( !pFnc ) throw SignalException("NULL pointer in slot()."); return Signal1<ret, p1t>( new __Slot1F<ret, p1t>( pFnc ) ); } // // 2 Parameters // template<typename ret, typename p1t, typename p2t> class _Slot2 { public: _Slot2() { } virtual ~_Slot2() { } virtual ret operator()( p1t p1, p2t p2 )=0; virtual _Slot2<ret, p1t, p2t> *clone() const=0; }; template<typename cls, typename ret, typename p1t, typename p2t> class __Slot2 : public _Slot2<ret, p1t, p2t> { public: __Slot2( cls *pCls, ret (cls::*pFnc)( p1t, p2t ) ) : pCls( pCls ), pFnc( pFnc ) { } virtual ~__Slot2() { } virtual ret operator()( p1t p1, p2t p2 ) { return (pCls->*pFnc)( p1, p2 ); } virtual _Slot2<ret, p1t, p2t> *clone() const { return new __Slot2<cls, ret, p1t, p2t>( pCls, pFnc ); } private: cls *pCls; ret (cls::*pFnc)( p1t, p2t ); }; template<typename ret, typename p1t, typename p2t> class __Slot2F : public _Slot2<ret, p1t, p2t> { public: __Slot2F( ret (*pFnc)( p1t, p2t ) ) : pFnc( pFnc ) { } virtual ~__Slot2F() { } virtual ret operator()( p1t p1, p2t p2 ) { return (*pFnc)( p1, p2 ); } virtual _Slot2<ret, p1t, p2t> *clone() const { return new __Slot2F<ret, p1t, p2t>( pFnc ); } private: ret (*pFnc)( p1t, p2t ); }; template<typename ret, typename p1t, typename p2t> class Signal2 { public: Signal2() : pCb( NULL ) { } Signal2( _Slot2<ret, p1t, p2t> *pCb ) : pCb( pCb ) { } Signal2( const Signal2<ret, p1t, p2t> &rSrc ) : pCb( (rSrc.pCb)?(rSrc.pCb->clone()):(NULL) ) { } virtual ~Signal2() { delete pCb; pCb = NULL; } ret operator()( p1t p1, p2t p2 ) { if( !pCb ) throw SignalException("Uninitialized signal used."); return (*pCb)( p1, p2 ); } bool isSet() const { return pCb != NULL; } operator bool() const { return isSet(); } Signal2<ret, p1t, p2t> &operator=( const Signal2<ret, p1t, p2t> &rhs ) { pCb = rhs.pCb->clone(); return *this; } private: _Slot2<ret, p1t, p2t> *pCb; }; template<typename cls, typename ret, typename p1t, typename p2t> Signal2<ret, p1t, p2t> slot( cls *pCls, ret (cls::*pFnc)( p1t, p2t ) ) { if( !pCls || !pFnc ) throw SignalException("NULL pointer in slot()."); return Signal2<ret, p1t, p2t>( new __Slot2<cls, ret, p1t, p2t>( pCls, pFnc ) ); } template<typename ret, typename p1t, typename p2t> Signal2<ret, p1t, p2t> slot( ret (*pFnc)( p1t, p2t ) ) { if( !pFnc ) throw SignalException("NULL pointer in slot()."); return Signal2<ret, p1t, p2t>( new __Slot2F<ret, p1t, p2t>( pFnc ) ); } // // 3 Parameters // template<typename ret, typename p1t, typename p2t, typename p3t> class _Slot3 { public: _Slot3() { } virtual ~_Slot3() { } virtual ret operator()( p1t p1, p2t p2, p3t p3 )=0; virtual _Slot3<ret, p1t, p2t, p3t> *clone() const=0; }; template<typename cls, typename ret, typename p1t, typename p2t, typename p3t> class __Slot3 : public _Slot3<ret, p1t, p2t, p3t> { public: __Slot3( cls *pCls, ret (cls::*pFnc)( p1t, p2t, p3t ) ) : pCls( pCls ), pFnc( pFnc ) { } virtual ~__Slot3() { } virtual ret operator()( p1t p1, p2t p2, p3t p3 ) { return (pCls->*pFnc)( p1, p2, p3 ); } virtual _Slot3<ret, p1t, p2t, p3t> *clone() const { return new __Slot3<cls, ret, p1t, p2t, p3t>( pCls, pFnc ); } private: cls *pCls; ret (cls::*pFnc)( p1t, p2t, p3t ); }; template<typename ret, typename p1t, typename p2t, typename p3t> class __Slot3F : public _Slot3<ret, p1t, p2t, p3t> { public: __Slot3F( ret (*pFnc)( p1t, p2t, p3t ) ) : pFnc( pFnc ) { } virtual ~__Slot3F() { } virtual ret operator()( p1t p1, p2t p2, p3t p3 ) { return (*pFnc)( p1, p2, p3 ); } virtual _Slot3<ret, p1t, p2t, p3t> *clone() const { return new __Slot3F<ret, p1t, p2t, p3t>( pFnc ); } private: ret (*pFnc)( p1t, p2t, p3t ); }; template<typename ret, typename p1t, typename p2t, typename p3t> class Signal3 { public: Signal3() : pCb( NULL ) { } Signal3( _Slot3<ret, p1t, p2t, p3t> *pCb ) : pCb( pCb ) { } Signal3( const Signal3<ret, p1t, p2t, p3t> &rSrc ) : pCb( (rSrc.pCb)?(rSrc.pCb->clone()):(NULL) ) { } virtual ~Signal3() { delete pCb; pCb = NULL; } ret operator()( p1t p1, p2t p2, p3t p3 ) { if( !pCb ) throw SignalException("Uninitialized signal used."); return (*pCb)( p1, p2, p3 ); } bool isSet() const { return pCb != NULL; } operator bool() const { return isSet(); } Signal3<ret, p1t, p2t, p3t> &operator=( const Signal3<ret, p1t, p2t, p3t> &rhs ) { pCb = rhs.pCb->clone(); return *this; } private: _Slot3<ret, p1t, p2t, p3t> *pCb; }; template<typename cls, typename ret, typename p1t, typename p2t, typename p3t> Signal3<ret, p1t, p2t, p3t> slot( cls *pCls, ret (cls::*pFnc)( p1t, p2t, p3t ) ) { if( !pCls || !pFnc ) throw SignalException("NULL pointer in slot()."); return Signal3<ret, p1t, p2t, p3t>( new __Slot3<cls, ret, p1t, p2t, p3t>( pCls, pFnc ) ); } template<typename ret, typename p1t, typename p2t, typename p3t> Signal3<ret, p1t, p2t, p3t> slot( ret (*pFnc)( p1t, p2t, p3t ) ) { if( !pFnc ) throw SignalException("NULL pointer in slot()."); return Signal3<ret, p1t, p2t, p3t>( new __Slot3F<ret, p1t, p2t, p3t>( pFnc ) ); } // // 4 Parameters // template<typename ret, typename p1t, typename p2t, typename p3t, typename p4t> class _Slot4 { public: _Slot4() { } virtual ~_Slot4() { } virtual ret operator()( p1t p1, p2t p2, p3t p3, p4t p4 )=0; virtual _Slot4<ret, p1t, p2t, p3t, p4t> *clone() const=0; }; template<typename cls, typename ret, typename p1t, typename p2t, typename p3t, typename p4t> class __Slot4 : public _Slot4<ret, p1t, p2t, p3t, p4t> { public: __Slot4( cls *pCls, ret (cls::*pFnc)( p1t, p2t, p3t, p4t ) ) : pCls( pCls ), pFnc( pFnc ) { } virtual ~__Slot4() { } virtual ret operator()( p1t p1, p2t p2, p3t p3, p4t p4 ) { return (pCls->*pFnc)( p1, p2, p3, p4 ); } virtual _Slot4<ret, p1t, p2t, p3t, p4t> *clone() const { return new __Slot4<cls, ret, p1t, p2t, p3t, p4t>( pCls, pFnc ); } private: cls *pCls; ret (cls::*pFnc)( p1t, p2t, p3t, p4t ); }; template<typename ret, typename p1t, typename p2t, typename p3t, typename p4t> class __Slot4F : public _Slot4<ret, p1t, p2t, p3t, p4t> { public: __Slot4F( ret (*pFnc)( p1t, p2t, p3t, p4t ) ) : pFnc( pFnc ) { } virtual ~__Slot4F() { } virtual ret operator()( p1t p1, p2t p2, p3t p3, p4t p4 ) { return (*pFnc)( p1, p2, p3, p4 ); } virtual _Slot4<ret, p1t, p2t, p3t, p4t> *clone() const { return new __Slot4F<ret, p1t, p2t, p3t, p4t>( pFnc ); } private: ret (*pFnc)( p1t, p2t, p3t, p4t ); }; template<typename ret, typename p1t, typename p2t, typename p3t, typename p4t> class Signal4 { public: Signal4() : pCb( NULL ) { } Signal4( _Slot4<ret, p1t, p2t, p3t, p4t> *pCb ) : pCb( pCb ) { } Signal4( const Signal4<ret, p1t, p2t, p3t, p4t> &rSrc ) : pCb( (rSrc.pCb)?(rSrc.pCb->clone()):(NULL) ) { } virtual ~Signal4() { delete pCb; pCb = NULL; } ret operator()( p1t p1, p2t p2, p3t p3, p4t p4 ) { if( !pCb ) throw SignalException("Uninitialized signal used."); return (*pCb)( p1, p2, p3, p4 ); } bool isSet() const { return pCb != NULL; } operator bool() const { return isSet(); } Signal4<ret, p1t, p2t, p3t, p4t> &operator=( const Signal4<ret, p1t, p2t, p3t, p4t> &rhs ) { pCb = rhs.pCb->clone(); return *this; } private: _Slot4<ret, p1t, p2t, p3t, p4t> *pCb; }; template<typename cls, typename ret, typename p1t, typename p2t, typename p3t, typename p4t> Signal4<ret, p1t, p2t, p3t, p4t> slot( cls *pCls, ret (cls::*pFnc)( p1t, p2t, p3t, p4t ) ) { if( !pCls || !pFnc ) throw SignalException("NULL pointer in slot()."); return Signal4<ret, p1t, p2t, p3t, p4t>( new __Slot4<cls, ret, p1t, p2t, p3t, p4t>( pCls, pFnc ) ); } template<typename ret, typename p1t, typename p2t, typename p3t, typename p4t> Signal4<ret, p1t, p2t, p3t, p4t> slot( ret (*pFnc)( p1t, p2t, p3t, p4t ) ) { if( !pFnc ) throw SignalException("NULL pointer in slot()."); return Signal4<ret, p1t, p2t, p3t, p4t>( new __Slot4F<ret, p1t, p2t, p3t, p4t>( pFnc ) ); } // // 5 Parameters // template<typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t> class _Slot5 { public: _Slot5() { } virtual ~_Slot5() { } virtual ret operator()( p1t p1, p2t p2, p3t p3, p4t p4, p5t p5 )=0; virtual _Slot5<ret, p1t, p2t, p3t, p4t, p5t> *clone() const=0; }; template<typename cls, typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t> class __Slot5 : public _Slot5<ret, p1t, p2t, p3t, p4t, p5t> { public: __Slot5( cls *pCls, ret (cls::*pFnc)( p1t, p2t, p3t, p4t, p5t ) ) : pCls( pCls ), pFnc( pFnc ) { } virtual ~__Slot5() { } virtual ret operator()( p1t p1, p2t p2, p3t p3, p4t p4, p5t p5 ) { return (pCls->*pFnc)( p1, p2, p3, p4, p5 ); } virtual _Slot5<ret, p1t, p2t, p3t, p4t, p5t> *clone() const { return new __Slot5<cls, ret, p1t, p2t, p3t, p4t, p5t>( pCls, pFnc ); } private: cls *pCls; ret (cls::*pFnc)( p1t, p2t, p3t, p4t, p5t ); }; template<typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t> class __Slot5F : public _Slot5<ret, p1t, p2t, p3t, p4t, p5t> { public: __Slot5F( ret (*pFnc)( p1t, p2t, p3t, p4t, p5t ) ) : pFnc( pFnc ) { } virtual ~__Slot5F() { } virtual ret operator()( p1t p1, p2t p2, p3t p3, p4t p4, p5t p5 ) { return (*pFnc)( p1, p2, p3, p4, p5 ); } virtual _Slot5<ret, p1t, p2t, p3t, p4t, p5t> *clone() const { return new __Slot5F<ret, p1t, p2t, p3t, p4t, p5t>( pFnc ); } private: ret (*pFnc)( p1t, p2t, p3t, p4t, p5t ); }; template<typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t> class Signal5 { public: Signal5() : pCb( NULL ) { } Signal5( _Slot5<ret, p1t, p2t, p3t, p4t, p5t> *pCb ) : pCb( pCb ) { } Signal5( const Signal5<ret, p1t, p2t, p3t, p4t, p5t> &rSrc ) : pCb( (rSrc.pCb)?(rSrc.pCb->clone()):(NULL) ) { } virtual ~Signal5() { delete pCb; pCb = NULL; } ret operator()( p1t p1, p2t p2, p3t p3, p4t p4, p5t p5 ) { if( !pCb ) throw SignalException("Uninitialized signal used."); return (*pCb)( p1, p2, p3, p4, p5 ); } bool isSet() const { return pCb != NULL; } operator bool() const { return isSet(); } Signal5<ret, p1t, p2t, p3t, p4t, p5t> &operator=( const Signal5<ret, p1t, p2t, p3t, p4t, p5t> &rhs ) { pCb = rhs.pCb->clone(); return *this; } private: _Slot5<ret, p1t, p2t, p3t, p4t, p5t> *pCb; }; template<typename cls, typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t> Signal5<ret, p1t, p2t, p3t, p4t, p5t> slot( cls *pCls, ret (cls::*pFnc)( p1t, p2t, p3t, p4t, p5t ) ) { if( !pCls || !pFnc ) throw SignalException("NULL pointer in slot()."); return Signal5<ret, p1t, p2t, p3t, p4t, p5t>( new __Slot5<cls, ret, p1t, p2t, p3t, p4t, p5t>( pCls, pFnc ) ); } template<typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t> Signal5<ret, p1t, p2t, p3t, p4t, p5t> slot( ret (*pFnc)( p1t, p2t, p3t, p4t, p5t ) ) { if( !pFnc ) throw SignalException("NULL pointer in slot()."); return Signal5<ret, p1t, p2t, p3t, p4t, p5t>( new __Slot5F<ret, p1t, p2t, p3t, p4t, p5t>( pFnc ) ); } }; #endif