MyGUI
3.2.0
|
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