MyGUI  3.2.1
MyGUI_DelegateImplement.h
Go to the documentation of this file.
1 /*
2  * This source file is part of MyGUI. For the latest info, see http://mygui.info/
3  * Distributed under the MIT License
4  * (See accompanying file COPYING.MIT or copy at http://opensource.org/licenses/MIT)
5  */
6 
7 namespace delegates
8 {
9 
10  #define MYGUI_COMBINE(a, b) MYGUI_COMBINE1(a, b)
11  #define MYGUI_COMBINE1(a, b) a##b
12 
13  #define MYGUI_I_DELEGATE MYGUI_COMBINE(IDelegate, MYGUI_SUFFIX)
14 
15  #define MYGUI_C_STATIC_DELEGATE MYGUI_COMBINE(CStaticDelegate, MYGUI_SUFFIX)
16  #define MYGUI_C_METHOD_DELEGATE MYGUI_COMBINE(CMethodDelegate, MYGUI_SUFFIX)
17 
18  #define MYGUI_C_DELEGATE MYGUI_COMBINE(CDelegate, MYGUI_SUFFIX)
19  #define MYGUI_C_MULTI_DELEGATE MYGUI_COMBINE(CMultiDelegate, MYGUI_SUFFIX)
20 
21 
22  // базовый класс всех делегатов
25  {
26  public:
27  virtual ~MYGUI_I_DELEGATE() { }
28  virtual bool isType( const std::type_info& _type) = 0;
29  virtual void invoke( MYGUI_PARAMS ) = 0;
30  virtual bool compare( MYGUI_I_DELEGATE MYGUI_TEMPLATE_ARGS* _delegate) const = 0;
31  virtual bool compare(IDelegateUnlink* _unlink) const
32  {
33  return false;
34  }
35  };
36 
37 
38  // делегат для статической функции
41  {
42  public:
43  typedef void (*Func)( MYGUI_PARAMS );
44 
45  MYGUI_C_STATIC_DELEGATE (Func _func) : mFunc(_func) { }
46 
47  virtual bool isType( const std::type_info& _type)
48  {
49  return typeid( MYGUI_C_STATIC_DELEGATE MYGUI_TEMPLATE_ARGS ) == _type;
50  }
51 
52  virtual void invoke( MYGUI_PARAMS )
53  {
54  mFunc( MYGUI_ARGS );
55  }
56 
57  virtual bool compare( MYGUI_I_DELEGATE MYGUI_TEMPLATE_ARGS* _delegate) const
58  {
59  if (nullptr == _delegate || !_delegate->isType(typeid(MYGUI_C_STATIC_DELEGATE MYGUI_TEMPLATE_ARGS)) ) return false;
60  MYGUI_C_STATIC_DELEGATE MYGUI_TEMPLATE_ARGS* cast = static_cast<MYGUI_C_STATIC_DELEGATE MYGUI_TEMPLATE_ARGS*>(_delegate);
61  return cast->mFunc == mFunc;
62  }
63  virtual bool compare(IDelegateUnlink* _unlink) const
64  {
65  return false;
66  }
67 
68  private:
69  Func mFunc;
70  };
71 
72 
73  // делегат для метода класса
76  {
77  public:
78  typedef void (T::*Method)( MYGUI_PARAMS );
79 
80  MYGUI_C_METHOD_DELEGATE(IDelegateUnlink* _unlink, T* _object, Method _method) : mUnlink(_unlink), mObject(_object), mMethod(_method) { }
81 
82  virtual bool isType( const std::type_info& _type)
83  {
84  return typeid( MYGUI_C_METHOD_DELEGATE MYGUI_T_TEMPLATE_ARGS ) == _type;
85  }
86 
87  virtual void invoke( MYGUI_PARAMS )
88  {
89  (mObject->*mMethod)( MYGUI_ARGS );
90  }
91 
92  virtual bool compare( MYGUI_I_DELEGATE MYGUI_TEMPLATE_ARGS* _delegate) const
93  {
94  if (nullptr == _delegate || !_delegate->isType(typeid(MYGUI_C_METHOD_DELEGATE MYGUI_T_TEMPLATE_ARGS)) ) return false;
95  MYGUI_C_METHOD_DELEGATE MYGUI_T_TEMPLATE_ARGS* cast = static_cast< MYGUI_C_METHOD_DELEGATE MYGUI_T_TEMPLATE_ARGS* >(_delegate);
96  return cast->mObject == mObject && cast->mMethod == mMethod;
97  }
98 
99  virtual bool compare(IDelegateUnlink* _unlink) const
100  {
101  return mUnlink == _unlink;
102  }
103 
104  private:
105  IDelegateUnlink* mUnlink;
106  T* mObject;
107  Method mMethod;
108  };
109 
110 } // namespace delegates
111 
112 // шаблон для создания делегата статической функции
113 // параметры : указатель на функцию
114 // пример : newDelegate(funk_name);
115 // пример : newDelegate(class_name::static_method_name);
118 {
120 }
121 
122 
123 // шаблон для создания делегата метода класса
124 // параметры : указатель на объект класса и указатель на метод класса
125 // пример : newDelegate(&object_name, &class_name::method_name);
127 inline delegates::MYGUI_I_DELEGATE MYGUI_TEMPLATE_ARGS* newDelegate( T* _object, void (T::*_method)( MYGUI_PARAMS ) )
128 {
130 }
131 
132 namespace delegates
133 {
134  // шаблон класса делегата
137  {
138  public:
140 
141  MYGUI_C_DELEGATE () : mDelegate(nullptr) { }
143  {
144  // забираем себе владение
145  IDelegate* del = _event.mDelegate;
146  const_cast< MYGUI_C_DELEGATE MYGUI_TEMPLATE_ARGS& >(_event).mDelegate = nullptr;
147 
148  if (mDelegate != nullptr && !mDelegate->compare(del))
149  delete mDelegate;
150 
151  mDelegate = del;
152  }
154  {
155  clear();
156  }
157 
158  bool empty() const
159  {
160  return mDelegate == nullptr;
161  }
162 
163  void clear()
164  {
165  if (mDelegate)
166  {
167  delete mDelegate;
168  mDelegate = nullptr;
169  }
170  }
171 
172  MYGUI_C_DELEGATE MYGUI_TEMPLATE_ARGS& operator=(IDelegate* _delegate)
173  {
174  delete mDelegate;
175  mDelegate = _delegate;
176  return *this;
177  }
178 
180  {
181  // забираем себе владение
182  IDelegate* del = _event.mDelegate;
183  const_cast< MYGUI_C_DELEGATE MYGUI_TEMPLATE_ARGS& >(_event).mDelegate = nullptr;
184 
185  if (mDelegate != nullptr && !mDelegate->compare(del))
186  delete mDelegate;
187 
188  mDelegate = del;
189 
190  return *this;
191  }
192 
193  void operator()( MYGUI_PARAMS )
194  {
195  if (mDelegate == nullptr) return;
196  mDelegate->invoke( MYGUI_ARGS );
197  }
198 
199  private:
200  IDelegate* mDelegate;
201  };
202 
203 
204  // шаблон класса мульти делегата
207  {
208  public:
210  typedef MYGUI_TYPENAME std::list<IDelegate* /*, Allocator<IDelegate*>*/ > ListDelegate;
211  typedef MYGUI_TYPENAME ListDelegate::iterator ListDelegateIterator;
212  typedef MYGUI_TYPENAME ListDelegate::const_iterator ConstListDelegateIterator;
213 
216  {
217  clear();
218  }
219 
220  bool empty() const
221  {
222  for (ConstListDelegateIterator iter = mListDelegates.begin(); iter != mListDelegates.end(); ++iter)
223  {
224  if (*iter) return false;
225  }
226  return true;
227  }
228 
229  void clear()
230  {
231  for (ListDelegateIterator iter = mListDelegates.begin(); iter != mListDelegates.end(); ++iter)
232  {
233  if (*iter)
234  {
235  delete (*iter);
236  (*iter) = nullptr;
237  }
238  }
239  }
240 
241  void clear(IDelegateUnlink* _unlink)
242  {
243  for (ListDelegateIterator iter = mListDelegates.begin(); iter != mListDelegates.end(); ++iter)
244  {
245  if ((*iter) && (*iter)->compare(_unlink))
246  {
247  delete (*iter);
248  (*iter) = nullptr;
249  }
250  }
251  }
252 
253  MYGUI_C_MULTI_DELEGATE MYGUI_TEMPLATE_ARGS& operator+=(IDelegate* _delegate)
254  {
255  for (ListDelegateIterator iter = mListDelegates.begin(); iter != mListDelegates.end(); ++iter)
256  {
257  if ((*iter) && (*iter)->compare(_delegate))
258  {
259  MYGUI_EXCEPT("Trying to add same delegate twice.");
260  }
261  }
262  mListDelegates.push_back(_delegate);
263  return *this;
264  }
265 
266  MYGUI_C_MULTI_DELEGATE MYGUI_TEMPLATE_ARGS& operator-=(IDelegate* _delegate)
267  {
268  for (ListDelegateIterator iter = mListDelegates.begin(); iter != mListDelegates.end(); ++iter)
269  {
270  if ((*iter) && (*iter)->compare(_delegate))
271  {
272  // проверяем на идентичность делегатов
273  if ((*iter) != _delegate) delete (*iter);
274  (*iter) = nullptr;
275  break;
276  }
277  }
278  delete _delegate;
279  return *this;
280  }
281 
282  void operator()( MYGUI_PARAMS )
283  {
284  ListDelegateIterator iter = mListDelegates.begin();
285  while (iter != mListDelegates.end())
286  {
287  if (nullptr == (*iter))
288  {
289  iter = mListDelegates.erase(iter);
290  }
291  else
292  {
293  (*iter)->invoke( MYGUI_ARGS );
294  ++iter;
295  }
296  }
297  }
298 
300  {
301  // забираем себе владение
302  ListDelegate del = _event.mListDelegates;
303  const_cast< MYGUI_C_MULTI_DELEGATE MYGUI_TEMPLATE_ARGS& >(_event).mListDelegates.clear();
304 
305  safe_clear(del);
306 
307  mListDelegates = del;
308  }
309 
311  {
312  // забираем себе владение
313  ListDelegate del = _event.mListDelegates;
314  const_cast< MYGUI_C_MULTI_DELEGATE MYGUI_TEMPLATE_ARGS& >(_event).mListDelegates.clear();
315 
316  safe_clear(del);
317 
318  mListDelegates = del;
319 
320  return *this;
321  }
322 
323  MYGUI_OBSOLETE("use : operator += ")
324  MYGUI_C_MULTI_DELEGATE MYGUI_TEMPLATE_ARGS& operator=(IDelegate* _delegate)
325  {
326  clear();
327  *this += _delegate;
328  return *this;
329  }
330 
331  private:
332  void safe_clear(ListDelegate& _delegates)
333  {
334  for (ListDelegateIterator iter = mListDelegates.begin(); iter != mListDelegates.end(); ++iter)
335  {
336  if (*iter)
337  {
338  IDelegate* del = (*iter);
339  (*iter) = nullptr;
340  delete_is_not_found(del, _delegates);
341  }
342  }
343  }
344 
345  void delete_is_not_found(IDelegate* _del, ListDelegate& _delegates)
346  {
347  for (ListDelegateIterator iter = _delegates.begin(); iter != _delegates.end(); ++iter)
348  {
349  if ((*iter) && (*iter)->compare(_del))
350  {
351  return;
352  }
353  }
354 
355  delete _del;
356  }
357 
358  private:
359  ListDelegate mListDelegates;
360  };
361 
362 
363  #undef MYGUI_COMBINE
364  #undef MYGUI_COMBINE1
365 
366  #undef MYGUI_I_DELEGATE
367 
368  #undef MYGUI_C_STATIC_DELEGATE
369  #undef MYGUI_C_METHOD_DELEGATE
370 
371  #undef MYGUI_C_DELEGATE
372  #undef MYGUI_C_MULTI_DELEGATE
373 
374  #undef MYGUI_SUFFIX
375  #undef MYGUI_TEMPLATE
376  #undef MYGUI_TEMPLATE_PARAMS
377  #undef MYGUI_TEMPLATE_ARGS
378  #undef MYGUI_T_TEMPLATE_PARAMS
379  #undef MYGUI_T_TEMPLATE_ARGS
380  #undef MYGUI_PARAMS
381  #undef MYGUI_ARGS
382  #undef MYGUI_TYPENAME
383 
384 } // namespace delegates