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