|
@@ -77,6 +77,8 @@ protected:
|
|
|
|
|
|
void insert(DelegateLink* node, F32 order);
|
|
|
void unlink();
|
|
|
+
|
|
|
+ virtual ~DelegateLink() {}
|
|
|
};
|
|
|
|
|
|
DelegateLink mList;
|
|
@@ -92,6 +94,78 @@ protected:
|
|
|
Vector<DelegateLink*> mTriggerNext;
|
|
|
};
|
|
|
|
|
|
+template<typename Signature> class SignalBaseT;
|
|
|
+
|
|
|
+/// Class for handle automatic diconnect form Signal when destroyed
|
|
|
+template< typename Signature >
|
|
|
+class SignalSlot
|
|
|
+{
|
|
|
+public:
|
|
|
+ typedef Delegate< Signature > DelegateSig;
|
|
|
+ typedef SignalBaseT< Signature > SignalSig;
|
|
|
+
|
|
|
+ SignalSlot() : mSignal(NULL)
|
|
|
+ {
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ ~SignalSlot()
|
|
|
+ {
|
|
|
+ disconnect();
|
|
|
+ }
|
|
|
+
|
|
|
+ const DelegateSig& getDelegate() { return mDlg; }
|
|
|
+
|
|
|
+ /// setDelegate disconect form Signal old delegate and connect new delegate
|
|
|
+ template<typename X>
|
|
|
+ void setDelegate( const X &fn ) { setDelegate( DelegateSig( fn ) ); }
|
|
|
+
|
|
|
+ template<typename X, typename Y>
|
|
|
+ void setDelegate( const X &ptr, const Y &fn ) { setDelegate( DelegateSig( ptr, fn ) ); }
|
|
|
+
|
|
|
+ void setDelegate( const DelegateSig &dlg)
|
|
|
+ {
|
|
|
+ SignalSig* signal = mSignal;
|
|
|
+ if( isConnected() )
|
|
|
+ disconnect();
|
|
|
+
|
|
|
+ mDlg = dlg;
|
|
|
+ if( signal && mDlg )
|
|
|
+ signal->notify( mDlg );
|
|
|
+ }
|
|
|
+
|
|
|
+ /// is connected to Signal
|
|
|
+ bool isConnected() const { return mSignal; }
|
|
|
+
|
|
|
+ /// disconnect from Signal
|
|
|
+ void disconnect()
|
|
|
+ {
|
|
|
+ if( mSignal )
|
|
|
+ {
|
|
|
+ SignalSig *oldSignal = mSignal;
|
|
|
+ mSignal = NULL;
|
|
|
+ oldSignal->remove( mDlg );
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+protected:
|
|
|
+ friend class SignalSig;
|
|
|
+
|
|
|
+ void _setSignal(SignalSig *sig)
|
|
|
+ {
|
|
|
+ mSignal = sig;
|
|
|
+ }
|
|
|
+
|
|
|
+ SignalSig* _getSignal() const { return mSignal; }
|
|
|
+
|
|
|
+ DelegateSig mDlg;
|
|
|
+ SignalSig *mSignal;
|
|
|
+
|
|
|
+private:
|
|
|
+ SignalSlot( const SignalSlot&) {}
|
|
|
+ SignalSlot& operator=( const SignalSlot&) {}
|
|
|
+};
|
|
|
+
|
|
|
template<typename Signature> class SignalBaseT : public SignalBase
|
|
|
{
|
|
|
public:
|
|
@@ -163,6 +237,18 @@ public:
|
|
|
notify(dlg, order);
|
|
|
}
|
|
|
|
|
|
+ void notify( SignalSlot<Signature> &slot, F32 order = 0.5f)
|
|
|
+ {
|
|
|
+ if( !slot.getDelegate() )
|
|
|
+ return;
|
|
|
+
|
|
|
+ if( slot.isConnected() )
|
|
|
+ slot.disconnect();
|
|
|
+
|
|
|
+ slot._setSignal( this );
|
|
|
+ mList.insert( new SlotLinkImpl(slot), order );
|
|
|
+ }
|
|
|
+
|
|
|
template <class T,class U>
|
|
|
void remove(T obj,U func)
|
|
|
{
|
|
@@ -198,6 +284,23 @@ protected:
|
|
|
DelegateLinkImpl(DelegateSig dlg) : mDelegate(dlg) {}
|
|
|
};
|
|
|
|
|
|
+ struct SlotLinkImpl : public DelegateLinkImpl
|
|
|
+ {
|
|
|
+ SlotLinkImpl(SignalSlot<Signature>& slot) : mSlot( &slot ), DelegateLinkImpl( slot.getDelegate() )
|
|
|
+ {
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ ~SlotLinkImpl()
|
|
|
+ {
|
|
|
+ if( mSlot )
|
|
|
+ mSlot->_setSignal( NULL );
|
|
|
+ }
|
|
|
+
|
|
|
+ protected:
|
|
|
+ SignalSlot<Signature> *mSlot;
|
|
|
+ };
|
|
|
+
|
|
|
DelegateSig & getDelegate(SignalBase::DelegateLink * link)
|
|
|
{
|
|
|
return ((DelegateLinkImpl*)link)->mDelegate;
|