• Main Page
  • Namespaces
  • Classes
  • Files
  • File List

callback.h

00001 #ifndef callback_h
00002 #define callback_h
00003 
00004 /*+
00005 ________________________________________________________________________
00006 
00007  (C) dGB Beheer B.V.; (LICENSE) http://opendtect.org/OpendTect_license.txt
00008  Author:        A.H.Bril
00009  Date:          8-11-1995
00010  Contents:      Notification and Callbacks
00011  RCS:           $Id: callback.h,v 1.43 2009-07-22 16:01:13 cvsbert Exp $
00012 ________________________________________________________________________
00013 
00014 -*/
00015 
00016 #include "sets.h"
00017 #include <string>
00018 
00035 struct CallBacker { virtual ~CallBacker() {} };
00036 
00037 
00038 typedef void (CallBacker::*CallBackFunction)(CallBacker*);
00040 #define mCBFn(clss,fn) ((CallBackFunction)(&clss::fn))
00041 
00042 #define mCB(obj,clss,fn) CallBack( static_cast<clss*>(obj), mCBFn(clss,fn))
00043 
00053 mClass CallBack
00054 {
00055 public:
00056                         CallBack( CallBacker* o=0, CallBackFunction f=0 )
00057                         { obj_ = o; fn_ = f; }
00058     inline int          operator==( const CallBack& cb ) const
00059                         { return obj_ == cb.obj_ && fn_ == cb.fn_; }
00060     inline int          operator!=( const CallBack& cb ) const
00061                         { return obj_ != cb.obj_ || fn_ != cb.fn_; }
00062 
00063     inline bool         willCall() const
00064                         { return obj_ && fn_; }
00065     inline void         doCall( CallBacker* o )
00066                         { if ( obj_ && fn_ ) (obj_->*fn_)( o ); }
00067 
00068     inline CallBacker*          cbObj()                 { return obj_; }
00069     inline const CallBacker*    cbObj() const           { return obj_; }
00070     inline CallBackFunction     cbFn() const            { return fn_; }
00071 
00072 protected:
00073 
00074     CallBacker*         obj_;
00075     CallBackFunction    fn_;
00076 
00077 };
00078 
00079 
00082 mClass CallBackSet : public TypeSet<CallBack>
00083 {
00084 public:
00085 
00086     void        doCall(CallBacker*,const bool* enabledflag=0,
00087                         CallBacker* exclude=0);
00094     void        removeWith(CallBacker*);
00096 };
00097 
00098 inline void CallBackSet::doCall( CallBacker* obj,
00099                                  const bool* enabledflag,
00100                                  CallBacker* exclude )
00101 {
00102     const bool enabled_ = true;
00103     const bool& enabled = enabledflag ? *enabledflag : enabled_;
00104     if ( !enabled ) return;
00105 
00106     TypeSet<CallBack> cbscopy = *this;
00107     for ( int idx=0; idx<cbscopy.size(); idx++ )
00108     {
00109         CallBack& cb = cbscopy[idx];
00110         if ( indexOf(cb)==-1 )
00111             continue;
00112 
00113         if ( cb.cbObj() != exclude )
00114             cb.doCall( obj );
00115     }
00116 }
00117 
00118 
00119 inline void CallBackSet::removeWith( CallBacker* cbrm )
00120 {
00121     for ( int idx=0; idx<size(); idx++ )
00122     {
00123         CallBack& cb = (*this)[idx];
00124         if ( cb.cbObj() == cbrm )
00125             { remove( idx ); idx--; }
00126     }
00127 }
00128 
00129 
00141 template <class T>
00142 class CBCapsule : public CallBacker
00143 {
00144 public:
00145                         CBCapsule( T d, CallBacker* c )
00146                         : data(d), caller(c)    {}
00147 
00148     T                   data;
00149     CallBacker*         caller;
00150 };
00151 
00152 
00175 #define mCBCapsuleGet(T,var,cb) \
00176     CBCapsule<T>* var = dynamic_cast< CBCapsule<T>* >( cb );
00177 
00178 #define mCBCapsuleUnpack(T,var,cb) \
00179     mCBCapsuleGet(T,cb##caps,cb) \
00180     T var = cb##caps->data
00181 
00182 #define mCBCapsuleUnpackWithCaller(T,var,cber,cb) \
00183     mCBCapsuleGet(T,cb##caps,cb) \
00184     T var = cb##caps->data; \
00185     CallBacker* cber = cb##caps->caller
00186 
00187 
00190 mClass NotifierAccess
00191 {
00192 
00193     friend class        NotifyStopper;
00194 
00195 public:
00196 
00197                         NotifierAccess()
00198                             : enabled_(true)                    {}
00199     virtual             ~NotifierAccess()                       {}
00200 
00201     virtual void        notify(const CallBack&)                 =0;
00202     virtual void        notifyIfNotNotified(const CallBack&)    =0;
00203     virtual void        remove(const CallBack&)                 =0;
00204 
00205     bool                enable( bool newstatus=true )
00206                         { return doEnable(newstatus); }
00208     bool                disable()               { return doEnable(false); }
00210     bool                isEnabled() const       { return enabled_; }
00211 
00212 protected:
00213 
00214     bool                enabled_;
00215     inline bool         doEnable( bool newstatus=true )
00216                         { bool res=enabled_; enabled_=newstatus; return res; }
00218 };
00219 
00220 
00235 mClass NamedNotifierSet
00236 {
00237 public:
00238                                 ~NamedNotifierSet()
00239                                 { deepErase( names_ ); }
00240 
00241     void                        add(const char* nm,NotifierAccess&);
00242     NotifierAccess*             find(const char*) const;
00243 
00244 protected:
00245 
00246     ObjectSet<NotifierAccess>   notifs_;
00247     ObjectSet<std::string>      names_;
00248 
00249 };
00250 
00251 
00252 inline void NamedNotifierSet::add( const char* nm, NotifierAccess& na )
00253 {
00254     names_ += new std::string( nm );
00255     notifs_ += &na;
00256 }
00257 
00258 
00259 inline NotifierAccess* NamedNotifierSet::find( const char* nm ) const
00260 {
00261     for ( int idx=0; idx<names_.size(); idx++ )
00262         if ( *names_[idx] == nm )
00263             return const_cast<NotifierAccess*>( notifs_[idx] );
00264     return 0;
00265 }
00266 
00267 
00270 mClass i_Notifier : public NotifierAccess
00271 {
00272 public:
00273 
00274     virtual void        notify( const CallBack& cb )    { cbs_ += cb; }
00275     virtual void        notifyIfNotNotified( const CallBack& cb )
00276                         { if ( cbs_.indexOf(cb)==-1 ) notify(cb); }
00277     virtual void        remove( const CallBack& cb )    { cbs_ -= cb; }
00278     virtual void        removeWith(CallBacker*);
00279 
00280     CallBackSet         cbs_;
00281     CallBacker*         cber_;
00282 
00283                         i_Notifier()    {}
00284 };
00285 
00286 
00287 inline void i_Notifier::removeWith( CallBacker* cb )
00288 {
00289     if ( cber_ == cb )
00290         { cbs_.erase(); cber_ = 0; return; }
00291 
00292     cbs_.removeWith( cb );
00293 }
00294 
00295 
00331 template <class T>
00332 class Notifier : public i_Notifier
00333 {
00334 public:
00335 
00336     void                trigger( T& t ) { trigger(&t); }
00337 
00338 // protected: (should be used by T class only)
00339 
00340                         Notifier( T* c )                        { cber_ = c; }
00341 
00342     inline void         trigger( CallBacker* c=0, CallBacker* exclude=0 )
00343                         { cbs_.doCall(c ? c : cber_, &enabled_, exclude); }
00344 
00345 };
00346 
00347 
00364 mClass NotifyStopper 
00365 {
00366 public:
00367                         NotifyStopper( NotifierAccess& n ) 
00368                             : thenotif(n)
00369                             , oldstatus( n.doEnable(false) )
00370                         {}
00371 
00372     inline              ~NotifyStopper()
00373                         { restore(); }
00374 
00375     inline void         enable()                { thenotif.doEnable(false); }
00376     inline void         disable()               { thenotif.doEnable(true); }
00377     inline void         restore()               { thenotif.doEnable(oldstatus);}
00378 
00379 protected:
00380 
00381     NotifierAccess&     thenotif;
00382     bool                oldstatus;
00383 };
00384 
00385 
00398 template <class T,class C>
00399 class CNotifier : public i_Notifier
00400 {
00401 public:
00402 
00403     void                trigger( C c, T& t )            { trigger(c,&t); }
00404 
00405 // almost protected (as above):
00406 
00407                         CNotifier( T* cb )      { cber_ = cb; }
00408 
00409     inline void         trigger( CallBacker* cb=0 )
00410                         {
00411                             if( !enabled_ ) return; 
00412                             C c;
00413                             trigger(c,cb);
00414                         }
00415 
00416     inline void         trigger( C c, CallBacker* cb=0 )
00417                         {
00418                             if( !enabled_ ) return; 
00419                             CBCapsule<C> caps( c, cb ? cb : cber_ );
00420                             cbs_.doCall( &caps, &enabled_ );
00421                         }
00422 };
00423 
00424 
00425 
00426 #endif

Generated on Tue Nov 30 2010 for Basic by  doxygen 1.7.1