MyGUI  3.2.0
MyGUI_DelegateImplement.h
Go to the documentation of this file.
1 
6 /*
7  This file is part of MyGUI.
8 
9  MyGUI is free software: you can redistribute it and/or modify
10  it under the terms of the GNU Lesser General Public License as published by
11  the Free Software Foundation, either version 3 of the License, or
12  (at your option) any later version.
13 
14  MyGUI is distributed in the hope that it will be useful,
15  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  GNU Lesser General Public License for more details.
18 
19  You should have received a copy of the GNU Lesser General Public License
20  along with MyGUI. If not, see <http://www.gnu.org/licenses/>.
21 */
22 
23 namespace delegates
24 {
25 
26  #define MYGUI_COMBINE(a, b) MYGUI_COMBINE1(a, b)
27  #define MYGUI_COMBINE1(a, b) a##b
28 
29  #define MYGUI_I_DELEGATE MYGUI_COMBINE(IDelegate, MYGUI_SUFFIX)
30 
31  #define MYGUI_C_STATIC_DELEGATE MYGUI_COMBINE(CStaticDelegate, MYGUI_SUFFIX)
32  #define MYGUI_C_METHOD_DELEGATE MYGUI_COMBINE(CMethodDelegate, MYGUI_SUFFIX)
33 
34  #define MYGUI_C_DELEGATE MYGUI_COMBINE(CDelegate, MYGUI_SUFFIX)
35  #define MYGUI_C_MULTI_DELEGATE MYGUI_COMBINE(CMultiDelegate, MYGUI_SUFFIX)
36 
37 
38  // базовый класс всех делегатов
41  {
42  public:
43  virtual ~MYGUI_I_DELEGATE() { }
44 #ifndef MYGUI_RTTI_DISABLE_TYPE_INFO
45  virtual bool isType( const std::type_info& _type) = 0;
46 #endif
47  virtual void invoke( MYGUI_PARAMS ) = 0;
48  virtual bool compare( MYGUI_I_DELEGATE MYGUI_TEMPLATE_ARGS* _delegate) const = 0;
49  virtual bool compare(IDelegateUnlink* _unlink) const
50  {
51  return false;
52  }
53  };
54 
55 
56  // делегат для статической функции
59  {
60  public:
61  typedef void (*Func)( MYGUI_PARAMS );
62 
63  MYGUI_C_STATIC_DELEGATE (Func _func) : mFunc(_func) { }
64 
65 #ifndef MYGUI_RTTI_DISABLE_TYPE_INFO
66  virtual bool isType( const std::type_info& _type)
67  {
68  return typeid( MYGUI_C_STATIC_DELEGATE MYGUI_TEMPLATE_ARGS ) == _type;
69  }
70 #endif
71 
72  virtual void invoke( MYGUI_PARAMS )
73  {
74  mFunc( MYGUI_ARGS );
75  }
76 
77  virtual bool compare( MYGUI_I_DELEGATE MYGUI_TEMPLATE_ARGS* _delegate) const
78  {
79 #ifndef MYGUI_RTTI_DISABLE_TYPE_INFO
80  if (nullptr == _delegate || !_delegate->isType(typeid(MYGUI_C_STATIC_DELEGATE MYGUI_TEMPLATE_ARGS)) ) return false;
81  MYGUI_C_STATIC_DELEGATE MYGUI_TEMPLATE_ARGS* cast = static_cast<MYGUI_C_STATIC_DELEGATE MYGUI_TEMPLATE_ARGS*>(_delegate);
82 #else
83  MYGUI_C_STATIC_DELEGATE MYGUI_TEMPLATE_ARGS* cast = dynamic_cast<MYGUI_C_STATIC_DELEGATE MYGUI_TEMPLATE_ARGS*>(_delegate);
84  if (nullptr == cast) return false;
85 #endif
86  return cast->mFunc == mFunc;
87  }
88  virtual bool compare(IDelegateUnlink* _unlink) const
89  {
90  return false;
91  }
92 
93  private:
94  Func mFunc;
95  };
96 
97 
98  // делегат для метода класса
101  {
102  public:
103  typedef void (T::*Method)( MYGUI_PARAMS );
104 
105  MYGUI_C_METHOD_DELEGATE(IDelegateUnlink* _unlink, T* _object, Method _method) : mUnlink(_unlink), mObject(_object), mMethod(_method) { }
106 
107 #ifndef MYGUI_RTTI_DISABLE_TYPE_INFO
108  virtual bool isType( const std::type_info& _type)
109  {
110  return typeid( MYGUI_C_METHOD_DELEGATE MYGUI_T_TEMPLATE_ARGS ) == _type;
111  }
112 #endif
113 
114  virtual void invoke( MYGUI_PARAMS )
115  {
116  (mObject->*mMethod)( MYGUI_ARGS );
117  }
118 
119  virtual bool compare( MYGUI_I_DELEGATE MYGUI_TEMPLATE_ARGS* _delegate) const
120  {
121 #ifndef MYGUI_RTTI_DISABLE_TYPE_INFO
122  if (nullptr == _delegate || !_delegate->isType(typeid(MYGUI_C_METHOD_DELEGATE MYGUI_T_TEMPLATE_ARGS)) ) return false;
123  MYGUI_C_METHOD_DELEGATE MYGUI_T_TEMPLATE_ARGS* cast = static_cast< MYGUI_C_METHOD_DELEGATE MYGUI_T_TEMPLATE_ARGS* >(_delegate);
124 #else
125  MYGUI_C_METHOD_DELEGATE MYGUI_T_TEMPLATE_ARGS* cast = dynamic_cast< MYGUI_C_METHOD_DELEGATE MYGUI_T_TEMPLATE_ARGS* >(_delegate);
126  if (nullptr == cast) return false;
127 #endif
128  return cast->mObject == mObject && cast->mMethod == mMethod;
129  }
130 
131  virtual bool compare(IDelegateUnlink* _unlink) const
132  {
133  return mUnlink == _unlink;
134  }
135 
136  private:
137  IDelegateUnlink* mUnlink;
138  T* mObject;
139  Method mMethod;
140  };
141 
142 } // namespace delegates
143 
144 // шаблон для создания делегата статической функции
145 // параметры : указатель на функцию
146 // пример : newDelegate(funk_name);
147 // пример : newDelegate(class_name::static_method_name);
150 {
152 }
153 
154 
155 // шаблон для создания делегата метода класса
156 // параметры : указатель на объект класса и указатель на метод класса
157 // пример : newDelegate(&object_name, &class_name::method_name);
159 inline delegates::MYGUI_I_DELEGATE MYGUI_TEMPLATE_ARGS* newDelegate( T* _object, void (T::*_method)( MYGUI_PARAMS ) )
160 {
162 }
163 
164 namespace delegates
165 {
166  // шаблон класса делегата
169  {
170  public:
172 
173  MYGUI_C_DELEGATE () : mDelegate(nullptr) { }
175  {
176  // забираем себе владение
177  IDelegate* del = _event.mDelegate;
178  const_cast< MYGUI_C_DELEGATE MYGUI_TEMPLATE_ARGS& >(_event).mDelegate = nullptr;
179 
180  if (mDelegate != nullptr && !mDelegate->compare(del))
181  delete mDelegate;
182 
183  mDelegate = del;
184  }
186  {
187  clear();
188  }
189 
190  bool empty() const
191  {
192  return mDelegate == nullptr;
193  }
194 
195  void clear()
196  {
197  if (mDelegate)
198  {
199  delete mDelegate;
200  mDelegate = nullptr;
201  }
202  }
203 
204  MYGUI_C_DELEGATE MYGUI_TEMPLATE_ARGS& operator=(IDelegate* _delegate)
205  {
206  delete mDelegate;
207  mDelegate = _delegate;
208  return *this;
209  }
210 
212  {
213  // забираем себе владение
214  IDelegate* del = _event.mDelegate;
215  const_cast< MYGUI_C_DELEGATE MYGUI_TEMPLATE_ARGS& >(_event).mDelegate = nullptr;
216 
217  if (mDelegate != nullptr && !mDelegate->compare(del))
218  delete mDelegate;
219 
220  mDelegate = del;
221 
222  return *this;
223  }
224 
225  void operator()( MYGUI_PARAMS )
226  {
227  if (mDelegate == nullptr) return;
228  mDelegate->invoke( MYGUI_ARGS );
229  }
230 
231  private:
232  IDelegate* mDelegate;
233  };
234 
235 
236  // шаблон класса мульти делегата
239  {
240  public:
242  typedef MYGUI_TYPENAME std::list<IDelegate* /*, Allocator<IDelegate*>*/ > ListDelegate;
243  typedef MYGUI_TYPENAME ListDelegate::iterator ListDelegateIterator;
244  typedef MYGUI_TYPENAME ListDelegate::const_iterator ConstListDelegateIterator;
245 
248  {
249  clear();
250  }
251 
252  bool empty() const
253  {
254  for (ConstListDelegateIterator iter = mListDelegates.begin(); iter != mListDelegates.end(); ++iter)
255  {
256  if (*iter) return false;
257  }
258  return true;
259  }
260 
261  void clear()
262  {
263  for (ListDelegateIterator iter = mListDelegates.begin(); iter != mListDelegates.end(); ++iter)
264  {
265  if (*iter)
266  {
267  delete (*iter);
268  (*iter) = nullptr;
269  }
270  }
271  }
272 
273  void clear(IDelegateUnlink* _unlink)
274  {
275  for (ListDelegateIterator iter = mListDelegates.begin(); iter != mListDelegates.end(); ++iter)
276  {
277  if ((*iter) && (*iter)->compare(_unlink))
278  {
279  delete (*iter);
280  (*iter) = nullptr;
281  }
282  }
283  }
284 
285  MYGUI_C_MULTI_DELEGATE MYGUI_TEMPLATE_ARGS& operator+=(IDelegate* _delegate)
286  {
287  for (ListDelegateIterator iter = mListDelegates.begin(); iter != mListDelegates.end(); ++iter)
288  {
289  if ((*iter) && (*iter)->compare(_delegate))
290  {
291  MYGUI_EXCEPT("Trying to add same delegate twice.");
292  }
293  }
294  mListDelegates.push_back(_delegate);
295  return *this;
296  }
297 
298  MYGUI_C_MULTI_DELEGATE MYGUI_TEMPLATE_ARGS& operator-=(IDelegate* _delegate)
299  {
300  for (ListDelegateIterator iter = mListDelegates.begin(); iter != mListDelegates.end(); ++iter)
301  {
302  if ((*iter) && (*iter)->compare(_delegate))
303  {
304  // проверяем на идентичность делегатов
305  if ((*iter) != _delegate) delete (*iter);
306  (*iter) = nullptr;
307  break;
308  }
309  }
310  delete _delegate;
311  return *this;
312  }
313 
314  void operator()( MYGUI_PARAMS )
315  {
316  ListDelegateIterator iter = mListDelegates.begin();
317  while (iter != mListDelegates.end())
318  {
319  if (nullptr == (*iter))
320  {
321  iter = mListDelegates.erase(iter);
322  }
323  else
324  {
325  (*iter)->invoke( MYGUI_ARGS );
326  ++iter;
327  }
328  }
329  }
330 
332  {
333  // забираем себе владение
334  ListDelegate del = _event.mListDelegates;
335  const_cast< MYGUI_C_MULTI_DELEGATE MYGUI_TEMPLATE_ARGS& >(_event).mListDelegates.clear();
336 
337  safe_clear(del);
338 
339  mListDelegates = del;
340  }
341 
343  {
344  // забираем себе владение
345  ListDelegate del = _event.mListDelegates;
346  const_cast< MYGUI_C_MULTI_DELEGATE MYGUI_TEMPLATE_ARGS& >(_event).mListDelegates.clear();
347 
348  safe_clear(del);
349 
350  mListDelegates = del;
351 
352  return *this;
353  }
354 
355  MYGUI_OBSOLETE("use : operator += ")
356  MYGUI_C_MULTI_DELEGATE MYGUI_TEMPLATE_ARGS& operator=(IDelegate* _delegate)
357  {
358  clear();
359  *this += _delegate;
360  return *this;
361  }
362 
363  private:
364  void safe_clear(ListDelegate& _delegates)
365  {
366  for (ListDelegateIterator iter = mListDelegates.begin(); iter != mListDelegates.end(); ++iter)
367  {
368  if (*iter)
369  {
370  IDelegate* del = (*iter);
371  (*iter) = nullptr;
372  delete_is_not_found(del, _delegates);
373  }
374  }
375  }
376 
377  void delete_is_not_found(IDelegate* _del, ListDelegate& _delegates)
378  {
379  for (ListDelegateIterator iter = _delegates.begin(); iter != _delegates.end(); ++iter)
380  {
381  if ((*iter) && (*iter)->compare(_del))
382  {
383  return;
384  }
385  }
386 
387  delete _del;
388  }
389 
390  private:
391  ListDelegate mListDelegates;
392  };
393 
394 
395  #undef MYGUI_COMBINE
396  #undef MYGUI_COMBINE1
397 
398  #undef MYGUI_I_DELEGATE
399 
400  #undef MYGUI_C_STATIC_DELEGATE
401  #undef MYGUI_C_METHOD_DELEGATE
402 
403  #undef MYGUI_C_DELEGATE
404  #undef MYGUI_C_MULTI_DELEGATE
405 
406  #undef MYGUI_SUFFIX
407  #undef MYGUI_TEMPLATE
408  #undef MYGUI_TEMPLATE_PARAMS
409  #undef MYGUI_TEMPLATE_ARGS
410  #undef MYGUI_T_TEMPLATE_PARAMS
411  #undef MYGUI_T_TEMPLATE_ARGS
412  #undef MYGUI_PARAMS
413  #undef MYGUI_ARGS
414  #undef MYGUI_TYPENAME
415 
416 } // namespace delegates