MyGUI  3.2.1
MyGUI_DelegateImplement.h
Go to the documentation of this file.
00001 /*
00002  * This source file is part of MyGUI. For the latest info, see http://mygui.info/
00003  * Distributed under the MIT License
00004  * (See accompanying file COPYING.MIT or copy at http://opensource.org/licenses/MIT)
00005  */
00006 
00007 namespace delegates
00008 {
00009 
00010     #define MYGUI_COMBINE(a, b)                                 MYGUI_COMBINE1(a, b)
00011     #define MYGUI_COMBINE1(a, b)                                a##b
00012 
00013     #define MYGUI_I_DELEGATE                                    MYGUI_COMBINE(IDelegate, MYGUI_SUFFIX)
00014 
00015     #define MYGUI_C_STATIC_DELEGATE                 MYGUI_COMBINE(CStaticDelegate, MYGUI_SUFFIX)
00016     #define MYGUI_C_METHOD_DELEGATE                 MYGUI_COMBINE(CMethodDelegate, MYGUI_SUFFIX)
00017 
00018     #define MYGUI_C_DELEGATE                                    MYGUI_COMBINE(CDelegate, MYGUI_SUFFIX)
00019     #define MYGUI_C_MULTI_DELEGATE                      MYGUI_COMBINE(CMultiDelegate, MYGUI_SUFFIX)
00020 
00021 
00022     // базовый класс всех делегатов
00023     MYGUI_TEMPLATE   MYGUI_TEMPLATE_PARAMS
00024     class MYGUI_I_DELEGATE
00025     {
00026     public:
00027         virtual ~MYGUI_I_DELEGATE() { }
00028         virtual bool isType( const std::type_info& _type) = 0;
00029         virtual void invoke( MYGUI_PARAMS ) = 0;
00030         virtual bool compare(  MYGUI_I_DELEGATE MYGUI_TEMPLATE_ARGS* _delegate) const = 0;
00031         virtual bool compare(IDelegateUnlink* _unlink) const
00032         {
00033             return false;
00034         }
00035     };
00036 
00037 
00038     // делегат для статической функции
00039     MYGUI_TEMPLATE   MYGUI_TEMPLATE_PARAMS
00040     class MYGUI_C_STATIC_DELEGATE : public  MYGUI_I_DELEGATE MYGUI_TEMPLATE_ARGS
00041     {
00042     public:
00043         typedef void (*Func)( MYGUI_PARAMS );
00044 
00045         MYGUI_C_STATIC_DELEGATE (Func _func) : mFunc(_func) { }
00046 
00047         virtual bool isType( const std::type_info& _type)
00048         {
00049             return typeid( MYGUI_C_STATIC_DELEGATE MYGUI_TEMPLATE_ARGS ) == _type;
00050         }
00051 
00052         virtual void invoke( MYGUI_PARAMS )
00053         {
00054             mFunc( MYGUI_ARGS );
00055         }
00056 
00057         virtual bool compare(  MYGUI_I_DELEGATE MYGUI_TEMPLATE_ARGS* _delegate) const
00058         {
00059             if (nullptr == _delegate || !_delegate->isType(typeid(MYGUI_C_STATIC_DELEGATE MYGUI_TEMPLATE_ARGS)) ) return false;
00060             MYGUI_C_STATIC_DELEGATE MYGUI_TEMPLATE_ARGS* cast = static_cast<MYGUI_C_STATIC_DELEGATE MYGUI_TEMPLATE_ARGS*>(_delegate);
00061             return cast->mFunc == mFunc;
00062         }
00063         virtual bool compare(IDelegateUnlink* _unlink) const
00064         {
00065             return false;
00066         }
00067 
00068     private:
00069         Func mFunc;
00070     };
00071 
00072 
00073     // делегат для метода класса
00074     template MYGUI_T_TEMPLATE_PARAMS
00075     class MYGUI_C_METHOD_DELEGATE : public  MYGUI_I_DELEGATE MYGUI_TEMPLATE_ARGS
00076     {
00077     public:
00078         typedef void (T::*Method)( MYGUI_PARAMS );
00079 
00080         MYGUI_C_METHOD_DELEGATE(IDelegateUnlink* _unlink, T* _object, Method _method) : mUnlink(_unlink), mObject(_object), mMethod(_method) { }
00081 
00082         virtual bool isType( const std::type_info& _type)
00083         {
00084             return typeid( MYGUI_C_METHOD_DELEGATE MYGUI_T_TEMPLATE_ARGS ) == _type;
00085         }
00086 
00087         virtual void invoke( MYGUI_PARAMS )
00088         {
00089             (mObject->*mMethod)( MYGUI_ARGS );
00090         }
00091 
00092         virtual bool compare(  MYGUI_I_DELEGATE MYGUI_TEMPLATE_ARGS* _delegate) const
00093         {
00094             if (nullptr == _delegate || !_delegate->isType(typeid(MYGUI_C_METHOD_DELEGATE MYGUI_T_TEMPLATE_ARGS)) ) return false;
00095             MYGUI_C_METHOD_DELEGATE MYGUI_T_TEMPLATE_ARGS* cast = static_cast<  MYGUI_C_METHOD_DELEGATE MYGUI_T_TEMPLATE_ARGS* >(_delegate);
00096             return cast->mObject == mObject && cast->mMethod == mMethod;
00097         }
00098 
00099         virtual bool compare(IDelegateUnlink* _unlink) const
00100         {
00101             return mUnlink == _unlink;
00102         }
00103 
00104     private:
00105         IDelegateUnlink* mUnlink;
00106         T* mObject;
00107         Method mMethod;
00108     };
00109 
00110 } // namespace delegates
00111 
00112 // шаблон для создания делегата статической функции
00113 // параметры : указатель на функцию
00114 // пример : newDelegate(funk_name);
00115 // пример : newDelegate(class_name::static_method_name);
00116 MYGUI_TEMPLATE   MYGUI_TEMPLATE_PARAMS
00117 inline  delegates::MYGUI_I_DELEGATE MYGUI_TEMPLATE_ARGS* newDelegate( void (*_func)( MYGUI_PARAMS ) )
00118 {
00119     return new delegates::MYGUI_C_STATIC_DELEGATE MYGUI_TEMPLATE_ARGS  (_func);
00120 }
00121 
00122 
00123 // шаблон для создания делегата метода класса
00124 // параметры : указатель на объект класса и указатель на метод класса
00125 // пример : newDelegate(&object_name, &class_name::method_name);
00126 template MYGUI_T_TEMPLATE_PARAMS
00127 inline  delegates::MYGUI_I_DELEGATE MYGUI_TEMPLATE_ARGS* newDelegate( T* _object, void (T::*_method)( MYGUI_PARAMS ) )
00128 {
00129     return new delegates::MYGUI_C_METHOD_DELEGATE  MYGUI_T_TEMPLATE_ARGS  (delegates::GetDelegateUnlink(_object), _object, _method);
00130 }
00131 
00132 namespace delegates
00133 {
00134     // шаблон класса делегата
00135     MYGUI_TEMPLATE   MYGUI_TEMPLATE_PARAMS
00136     class MYGUI_C_DELEGATE
00137     {
00138     public:
00139         typedef  MYGUI_I_DELEGATE MYGUI_TEMPLATE_ARGS  IDelegate;
00140 
00141         MYGUI_C_DELEGATE () : mDelegate(nullptr) { }
00142         MYGUI_C_DELEGATE (const MYGUI_C_DELEGATE  MYGUI_TEMPLATE_ARGS& _event) : mDelegate(nullptr)
00143         {
00144             // забираем себе владение
00145             IDelegate* del = _event.mDelegate;
00146             const_cast< MYGUI_C_DELEGATE  MYGUI_TEMPLATE_ARGS& >(_event).mDelegate = nullptr;
00147 
00148             if (mDelegate != nullptr && !mDelegate->compare(del))
00149                 delete mDelegate;
00150 
00151             mDelegate = del;
00152         }
00153         ~MYGUI_C_DELEGATE ()
00154         {
00155             clear();
00156         }
00157 
00158         bool empty() const
00159         {
00160             return mDelegate == nullptr;
00161         }
00162 
00163         void clear()
00164         {
00165             if (mDelegate)
00166             {
00167                 delete mDelegate;
00168                 mDelegate = nullptr;
00169             }
00170         }
00171 
00172         MYGUI_C_DELEGATE  MYGUI_TEMPLATE_ARGS& operator=(IDelegate* _delegate)
00173         {
00174             delete mDelegate;
00175             mDelegate = _delegate;
00176             return *this;
00177         }
00178 
00179         MYGUI_C_DELEGATE  MYGUI_TEMPLATE_ARGS& operator=(const MYGUI_C_DELEGATE  MYGUI_TEMPLATE_ARGS& _event)
00180         {
00181             // забираем себе владение
00182             IDelegate* del = _event.mDelegate;
00183             const_cast< MYGUI_C_DELEGATE  MYGUI_TEMPLATE_ARGS& >(_event).mDelegate = nullptr;
00184 
00185             if (mDelegate != nullptr && !mDelegate->compare(del))
00186                 delete mDelegate;
00187 
00188             mDelegate = del;
00189 
00190             return *this;
00191         }
00192 
00193         void operator()( MYGUI_PARAMS )
00194         {
00195             if (mDelegate == nullptr) return;
00196             mDelegate->invoke( MYGUI_ARGS );
00197         }
00198 
00199     private:
00200         IDelegate* mDelegate;
00201     };
00202 
00203 
00204     // шаблон класса мульти делегата
00205     MYGUI_TEMPLATE   MYGUI_TEMPLATE_PARAMS
00206     class MYGUI_C_MULTI_DELEGATE
00207     {
00208     public:
00209         typedef  MYGUI_I_DELEGATE MYGUI_TEMPLATE_ARGS  IDelegate;
00210         typedef MYGUI_TYPENAME std::list<IDelegate* /*, Allocator<IDelegate*>*/ > ListDelegate;
00211         typedef MYGUI_TYPENAME ListDelegate::iterator ListDelegateIterator;
00212         typedef MYGUI_TYPENAME ListDelegate::const_iterator ConstListDelegateIterator;
00213 
00214         MYGUI_C_MULTI_DELEGATE () { }
00215         ~MYGUI_C_MULTI_DELEGATE ()
00216         {
00217             clear();
00218         }
00219 
00220         bool empty() const
00221         {
00222             for (ConstListDelegateIterator iter = mListDelegates.begin(); iter != mListDelegates.end(); ++iter)
00223             {
00224                 if (*iter) return false;
00225             }
00226             return true;
00227         }
00228 
00229         void clear()
00230         {
00231             for (ListDelegateIterator iter = mListDelegates.begin(); iter != mListDelegates.end(); ++iter)
00232             {
00233                 if (*iter)
00234                 {
00235                     delete (*iter);
00236                     (*iter) = nullptr;
00237                 }
00238             }
00239         }
00240 
00241         void clear(IDelegateUnlink* _unlink)
00242         {
00243             for (ListDelegateIterator iter = mListDelegates.begin(); iter != mListDelegates.end(); ++iter)
00244             {
00245                 if ((*iter) && (*iter)->compare(_unlink))
00246                 {
00247                     delete (*iter);
00248                     (*iter) = nullptr;
00249                 }
00250             }
00251         }
00252 
00253         MYGUI_C_MULTI_DELEGATE  MYGUI_TEMPLATE_ARGS& operator+=(IDelegate* _delegate)
00254         {
00255             for (ListDelegateIterator iter = mListDelegates.begin(); iter != mListDelegates.end(); ++iter)
00256             {
00257                 if ((*iter) && (*iter)->compare(_delegate))
00258                 {
00259                     MYGUI_EXCEPT("Trying to add same delegate twice.");
00260                 }
00261             }
00262             mListDelegates.push_back(_delegate);
00263             return *this;
00264         }
00265 
00266         MYGUI_C_MULTI_DELEGATE  MYGUI_TEMPLATE_ARGS& operator-=(IDelegate* _delegate)
00267         {
00268             for (ListDelegateIterator iter = mListDelegates.begin(); iter != mListDelegates.end(); ++iter)
00269             {
00270                 if ((*iter) && (*iter)->compare(_delegate))
00271                 {
00272                     // проверяем на идентичность делегатов
00273                     if ((*iter) != _delegate) delete (*iter);
00274                     (*iter) = nullptr;
00275                     break;
00276                 }
00277             }
00278             delete _delegate;
00279             return *this;
00280         }
00281 
00282         void operator()( MYGUI_PARAMS )
00283         {
00284             ListDelegateIterator iter = mListDelegates.begin();
00285             while (iter != mListDelegates.end())
00286             {
00287                 if (nullptr == (*iter))
00288                 {
00289                     iter = mListDelegates.erase(iter);
00290                 }
00291                 else
00292                 {
00293                     (*iter)->invoke( MYGUI_ARGS );
00294                     ++iter;
00295                 }
00296             }
00297         }
00298 
00299         MYGUI_C_MULTI_DELEGATE (const MYGUI_C_MULTI_DELEGATE  MYGUI_TEMPLATE_ARGS& _event)
00300         {
00301             // забираем себе владение
00302             ListDelegate del = _event.mListDelegates;
00303             const_cast< MYGUI_C_MULTI_DELEGATE  MYGUI_TEMPLATE_ARGS& >(_event).mListDelegates.clear();
00304 
00305             safe_clear(del);
00306 
00307             mListDelegates = del;
00308         }
00309 
00310         MYGUI_C_MULTI_DELEGATE  MYGUI_TEMPLATE_ARGS& operator=(const MYGUI_C_MULTI_DELEGATE  MYGUI_TEMPLATE_ARGS& _event)
00311         {
00312             // забираем себе владение
00313             ListDelegate del = _event.mListDelegates;
00314             const_cast< MYGUI_C_MULTI_DELEGATE  MYGUI_TEMPLATE_ARGS& >(_event).mListDelegates.clear();
00315 
00316             safe_clear(del);
00317 
00318             mListDelegates = del;
00319 
00320             return *this;
00321         }
00322 
00323         MYGUI_OBSOLETE("use : operator += ")
00324         MYGUI_C_MULTI_DELEGATE  MYGUI_TEMPLATE_ARGS& operator=(IDelegate* _delegate)
00325         {
00326             clear();
00327             *this += _delegate;
00328             return *this;
00329         }
00330 
00331     private:
00332         void safe_clear(ListDelegate& _delegates)
00333         {
00334             for (ListDelegateIterator iter = mListDelegates.begin(); iter != mListDelegates.end(); ++iter)
00335             {
00336                 if (*iter)
00337                 {
00338                     IDelegate* del = (*iter);
00339                     (*iter) = nullptr;
00340                     delete_is_not_found(del, _delegates);
00341                 }
00342             }
00343         }
00344 
00345         void delete_is_not_found(IDelegate* _del, ListDelegate& _delegates)
00346         {
00347             for (ListDelegateIterator iter = _delegates.begin(); iter != _delegates.end(); ++iter)
00348             {
00349                 if ((*iter) && (*iter)->compare(_del))
00350                 {
00351                     return;
00352                 }
00353             }
00354 
00355             delete _del;
00356         }
00357 
00358     private:
00359         ListDelegate mListDelegates;
00360     };
00361 
00362 
00363     #undef MYGUI_COMBINE
00364     #undef MYGUI_COMBINE1
00365 
00366     #undef MYGUI_I_DELEGATE
00367 
00368     #undef MYGUI_C_STATIC_DELEGATE
00369     #undef MYGUI_C_METHOD_DELEGATE
00370 
00371     #undef MYGUI_C_DELEGATE
00372     #undef MYGUI_C_MULTI_DELEGATE
00373 
00374     #undef MYGUI_SUFFIX
00375     #undef MYGUI_TEMPLATE
00376     #undef MYGUI_TEMPLATE_PARAMS
00377     #undef MYGUI_TEMPLATE_ARGS
00378     #undef MYGUI_T_TEMPLATE_PARAMS
00379     #undef MYGUI_T_TEMPLATE_ARGS
00380     #undef MYGUI_PARAMS
00381     #undef MYGUI_ARGS
00382     #undef MYGUI_TYPENAME
00383 
00384 } // namespace delegates