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