MyGUI  3.0.1
MyGUI_DelegateImplement.h
Go to the documentation of this file.
00001 
00007 /*
00008     This file is part of MyGUI.
00009 
00010     MyGUI is free software: you can redistribute it and/or modify
00011     it under the terms of the GNU Lesser General Public License as published by
00012     the Free Software Foundation, either version 3 of the License, or
00013     (at your option) any later version.
00014 
00015     MyGUI is distributed in the hope that it will be useful,
00016     but WITHOUT ANY WARRANTY; without even the implied warranty of
00017     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018     GNU Lesser General Public License for more details.
00019 
00020     You should have received a copy of the GNU Lesser General Public License
00021     along with MyGUI.  If not, see <http://www.gnu.org/licenses/>.
00022 */
00023 
00024 namespace delegates
00025 {
00026 
00027     #define MYGUI_COMBINE(a, b)                                 MYGUI_COMBINE1(a, b)
00028     #define MYGUI_COMBINE1(a, b)                                a##b
00029 
00030     #define MYGUI_I_DELEGATE                                    MYGUI_COMBINE(IDelegate, MYGUI_SUFFIX)
00031 
00032     #define MYGUI_C_STATIC_DELEGATE                 MYGUI_COMBINE(CStaticDelegate, MYGUI_SUFFIX)
00033     #define MYGUI_C_METHOD_DELEGATE                 MYGUI_COMBINE(CMethodDelegate, MYGUI_SUFFIX)
00034 
00035     #define MYGUI_C_DELEGATE                                    MYGUI_COMBINE(CDelegate, MYGUI_SUFFIX)
00036     #define MYGUI_C_MULTI_DELEGATE                      MYGUI_COMBINE(CMultiDelegate, MYGUI_SUFFIX)
00037 
00038 
00039     // базовый класс всех делегатов
00040     MYGUI_TEMPLATE   MYGUI_TEMPLATE_PARAMS
00041     class MYGUI_I_DELEGATE
00042     {
00043     public:
00044         virtual ~MYGUI_I_DELEGATE() { }
00045         virtual bool isType( const std::type_info& _type) = 0;
00046         virtual void invoke( MYGUI_PARAMS ) = 0;
00047         virtual bool compare(  MYGUI_I_DELEGATE MYGUI_TEMPLATE_ARGS  * _delegate) const = 0;
00048         virtual bool compare(IDelegateUnlink * _unlink) const { return false; }
00049     };
00050 
00051 
00052     // делегат для статической функции
00053     MYGUI_TEMPLATE   MYGUI_TEMPLATE_PARAMS
00054     class MYGUI_C_STATIC_DELEGATE : public  MYGUI_I_DELEGATE MYGUI_TEMPLATE_ARGS
00055     {
00056     public:
00057         typedef void (*Func)( MYGUI_PARAMS );
00058 
00059         MYGUI_C_STATIC_DELEGATE (Func _func) : mFunc(_func) { }
00060 
00061         virtual bool isType( const std::type_info& _type) { return typeid( MYGUI_C_STATIC_DELEGATE MYGUI_TEMPLATE_ARGS ) == _type; }
00062 
00063         virtual void invoke( MYGUI_PARAMS )
00064         {
00065             mFunc( MYGUI_ARGS );
00066         }
00067 
00068         virtual bool compare(  MYGUI_I_DELEGATE MYGUI_TEMPLATE_ARGS  * _delegate) const
00069         {
00070             if (nullptr == _delegate || !_delegate->isType(typeid(MYGUI_C_STATIC_DELEGATE MYGUI_TEMPLATE_ARGS)) ) return false;
00071             MYGUI_C_STATIC_DELEGATE MYGUI_TEMPLATE_ARGS * cast = static_cast<MYGUI_C_STATIC_DELEGATE MYGUI_TEMPLATE_ARGS *>(_delegate);
00072             return cast->mFunc == mFunc;
00073         }
00074         virtual bool compare(IDelegateUnlink * _unlink) const { return false; }
00075 
00076     private:
00077         Func mFunc;
00078     };
00079 
00080 
00081     // делегат для метода класса
00082     template MYGUI_T_TEMPLATE_PARAMS
00083     class MYGUI_C_METHOD_DELEGATE : public  MYGUI_I_DELEGATE MYGUI_TEMPLATE_ARGS
00084     {
00085     public:
00086         typedef void (T::*Method)( MYGUI_PARAMS );
00087 
00088         MYGUI_C_METHOD_DELEGATE(IDelegateUnlink * _unlink, T * _object, Method _method) : mUnlink(_unlink), mObject(_object), mMethod(_method) { }
00089 
00090         virtual bool isType( const std::type_info& _type) { return typeid( MYGUI_C_METHOD_DELEGATE MYGUI_T_TEMPLATE_ARGS ) == _type; }
00091 
00092         virtual void invoke( MYGUI_PARAMS )
00093         {
00094             (mObject->*mMethod)( MYGUI_ARGS );
00095         }
00096 
00097         virtual bool compare(  MYGUI_I_DELEGATE MYGUI_TEMPLATE_ARGS  * _delegate) const
00098         {
00099             if (nullptr == _delegate || !_delegate->isType(typeid(MYGUI_C_METHOD_DELEGATE MYGUI_T_TEMPLATE_ARGS)) ) return false;
00100             MYGUI_C_METHOD_DELEGATE MYGUI_T_TEMPLATE_ARGS  * cast = static_cast<  MYGUI_C_METHOD_DELEGATE MYGUI_T_TEMPLATE_ARGS  * >(_delegate);
00101             return cast->mObject == mObject && cast->mMethod == mMethod;
00102         }
00103 
00104         virtual bool compare(IDelegateUnlink * _unlink) const
00105         {
00106             return mUnlink == _unlink;
00107         }
00108 
00109     private:
00110         IDelegateUnlink *mUnlink;
00111         T * mObject;
00112         Method mMethod;
00113     };
00114 
00115 } // namespace delegates
00116 
00117 // шаблон для создания делегата статической функции
00118 // параметры : указатель на функцию
00119 // пример : newDelegate(funk_name);
00120 // пример : newDelegate(class_name::static_method_name);
00121 MYGUI_TEMPLATE   MYGUI_TEMPLATE_PARAMS
00122 inline  delegates::MYGUI_I_DELEGATE MYGUI_TEMPLATE_ARGS  * newDelegate( void (*_func)( MYGUI_PARAMS ) )
00123 {
00124     return new delegates::MYGUI_C_STATIC_DELEGATE MYGUI_TEMPLATE_ARGS  (_func);
00125 }
00126 
00127 
00128 // шаблон для создания делегата метода класса
00129 // параметры : указатель на объект класса и указатель на метод класса
00130 // пример : newDelegate(&object_name, &class_name::method_name);
00131 template MYGUI_T_TEMPLATE_PARAMS
00132 inline  delegates::MYGUI_I_DELEGATE MYGUI_TEMPLATE_ARGS  * newDelegate( T * _object, void (T::*_method)( MYGUI_PARAMS ) )
00133 {
00134     return new delegates::MYGUI_C_METHOD_DELEGATE  MYGUI_T_TEMPLATE_ARGS  (delegates::GetDelegateUnlink(_object), _object, _method);
00135 }
00136 
00137 namespace delegates
00138 {
00139     // шаблон класса делегата
00140     MYGUI_TEMPLATE   MYGUI_TEMPLATE_PARAMS
00141     class MYGUI_C_DELEGATE
00142     {
00143     public:
00144         typedef  MYGUI_I_DELEGATE MYGUI_TEMPLATE_ARGS  IDelegate;
00145 
00146         MYGUI_C_DELEGATE () : mDelegate(nullptr) { }
00147         MYGUI_C_DELEGATE (const MYGUI_C_DELEGATE  MYGUI_TEMPLATE_ARGS& _event)
00148         {
00149             // забираем себе владение
00150             mDelegate = _event.mDelegate;
00151             const_cast< MYGUI_C_DELEGATE  MYGUI_TEMPLATE_ARGS& >(_event).mDelegate = nullptr;
00152         }
00153         ~MYGUI_C_DELEGATE () { clear(); }
00154 
00155         bool empty() const { return mDelegate == nullptr; }
00156 
00157         void clear()
00158         {
00159             if (mDelegate)
00160             {
00161                 delete mDelegate;
00162                 mDelegate = nullptr;
00163             }
00164         }
00165 
00166         MYGUI_C_DELEGATE  MYGUI_TEMPLATE_ARGS & operator=(IDelegate* _delegate)
00167         {
00168             delete mDelegate;
00169             mDelegate = _delegate;
00170             return *this;
00171         }
00172 
00173         MYGUI_C_DELEGATE  MYGUI_TEMPLATE_ARGS & operator=(const MYGUI_C_DELEGATE  MYGUI_TEMPLATE_ARGS& _event)
00174         {
00175             // забираем себе владение
00176             delete mDelegate;
00177             mDelegate = _event.mDelegate;
00178             const_cast< MYGUI_C_DELEGATE  MYGUI_TEMPLATE_ARGS& >(_event).mDelegate = nullptr;
00179 
00180             return *this;
00181         }
00182 
00183         void operator()( MYGUI_PARAMS )
00184         {
00185             if (mDelegate == nullptr) return;
00186             mDelegate->invoke( MYGUI_ARGS );
00187         }
00188 
00189     private:
00190         IDelegate * mDelegate;
00191     };
00192 
00193 
00194     // шаблон класса мульти делегата
00195     MYGUI_TEMPLATE   MYGUI_TEMPLATE_PARAMS
00196     class MYGUI_C_MULTI_DELEGATE
00197     {
00198     public:
00199         typedef  MYGUI_I_DELEGATE MYGUI_TEMPLATE_ARGS  IDelegate;
00200         typedef MYGUI_TYPENAME std::list<IDelegate* /*, Allocator<IDelegate*>*/ > ListDelegate;
00201         typedef MYGUI_TYPENAME ListDelegate::iterator ListDelegateIterator;
00202         typedef MYGUI_TYPENAME ListDelegate::const_iterator ConstListDelegateIterator;
00203 
00204         MYGUI_C_MULTI_DELEGATE () { }
00205         ~MYGUI_C_MULTI_DELEGATE () { clear(); }
00206 
00207         bool empty() const
00208         {
00209           for (ConstListDelegateIterator iter = mListDelegates.begin(); iter!=mListDelegates.end(); ++iter)
00210             {
00211                 if (*iter) return false;
00212             }
00213             return true;
00214         }
00215 
00216         void clear()
00217         {
00218             for (ListDelegateIterator iter=mListDelegates.begin(); iter!=mListDelegates.end(); ++iter)
00219             {
00220                 if (*iter)
00221                 {
00222                     delete (*iter);
00223                     (*iter) = nullptr;
00224                 }
00225             }
00226         }
00227 
00228         void clear(IDelegateUnlink * _unlink)
00229         {
00230             for (ListDelegateIterator iter=mListDelegates.begin(); iter!=mListDelegates.end(); ++iter)
00231             {
00232                 if ((*iter) && (*iter)->compare(_unlink))
00233                 {
00234                     delete (*iter);
00235                     (*iter) = nullptr;
00236                 }
00237             }
00238         }
00239 
00240         MYGUI_C_MULTI_DELEGATE  MYGUI_TEMPLATE_ARGS & operator+=(IDelegate* _delegate)
00241         {
00242             for (ListDelegateIterator iter=mListDelegates.begin(); iter!=mListDelegates.end(); ++iter)
00243             {
00244                 if ((*iter) && (*iter)->compare(_delegate))
00245                 {
00246                     MYGUI_ASSERT(false, "dublicate delegate");
00247                 }
00248             }
00249             mListDelegates.push_back(_delegate);
00250             return *this;
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                     // проверяем на идентичность делегатов
00260                     if ((*iter) != _delegate) delete (*iter);
00261                     (*iter) = nullptr;
00262                     break;
00263                 }
00264             }
00265             delete _delegate;
00266             return *this;
00267         }
00268 
00269         void operator()( MYGUI_PARAMS )
00270         {
00271             ListDelegateIterator iter = mListDelegates.begin();
00272             while (iter != mListDelegates.end())
00273             {
00274                 if (nullptr == (*iter))
00275                 {
00276                     iter = mListDelegates.erase(iter);
00277                 }
00278                 else
00279                 {
00280                     (*iter)->invoke( MYGUI_ARGS );
00281                     ++iter;
00282                 }
00283             }
00284         }
00285 
00286     private:
00287         // constructor and operator =, without implementation, just for private
00288         MYGUI_C_MULTI_DELEGATE (const MYGUI_C_MULTI_DELEGATE  MYGUI_TEMPLATE_ARGS & _event);
00289         MYGUI_C_MULTI_DELEGATE  MYGUI_TEMPLATE_ARGS & operator=(const MYGUI_C_MULTI_DELEGATE  MYGUI_TEMPLATE_ARGS & _event);
00290 
00291 
00292     private:
00293         ListDelegate mListDelegates;
00294 
00295     };
00296 
00297 
00298     #undef MYGUI_COMBINE
00299     #undef MYGUI_COMBINE1
00300 
00301     #undef MYGUI_I_DELEGATE
00302 
00303     #undef MYGUI_C_STATIC_DELEGATE
00304     #undef MYGUI_C_METHOD_DELEGATE
00305 
00306     #undef MYGUI_C_DELEGATE
00307     #undef MYGUI_C_MULTI_DELEGATE
00308 
00309     #undef MYGUI_SUFFIX
00310     #undef MYGUI_TEMPLATE
00311     #undef MYGUI_TEMPLATE_PARAMS
00312     #undef MYGUI_TEMPLATE_ARGS
00313     #undef MYGUI_T_TEMPLATE_PARAMS
00314     #undef MYGUI_T_TEMPLATE_ARGS
00315     #undef MYGUI_PARAMS
00316     #undef MYGUI_ARGS
00317     #undef MYGUI_TYPENAME
00318 
00319 } // namespace delegates