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