MyGUI  3.4.1
MyGUI_Delegate.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 #ifndef MYGUI_DELEGATE_H_
8 #define MYGUI_DELEGATE_H_
9 
10 #include "MyGUI_Diagnostic.h"
11 #include "MyGUI_Any.h"
12 #include <list>
13 
14 #include <functional>
15 
16 namespace MyGUI
17 {
18 
19 namespace delegates
20 {
21  // base class for unsubscribing from multi delegates
23  {
24  public:
25  virtual ~IDelegateUnlink() = default;
26 
28  {
29  m_baseDelegateUnlink = this;
30  }
31  bool compare(IDelegateUnlink* _unlink) const
32  {
33  return m_baseDelegateUnlink == _unlink->m_baseDelegateUnlink;
34  }
35 
36  private:
37  IDelegateUnlink* m_baseDelegateUnlink;
38  };
39 
40  template <typename ...Args>
42  {
43  public:
44  using Function = std::function<void(Args...)>;
45 
46  // function or static class method
47  DelegateFunction(Function _function, Any _functionPointer) :
48  mFunction(_function),
49  mFunctionPointer(_functionPointer)
50  {
51  }
52 
53  // non-static class method
54  DelegateFunction(Function _function, Any _functionPointer, const IDelegateUnlink* _object) :
55  mFunction(_function),
56  mUnlink(_object),
57  mObject(_object),
58  mFunctionPointer(_functionPointer)
59  {
60  }
61 
62  // non-static class method
63  DelegateFunction(Function _function, Any _functionPointer, const void* _object) :
64  mFunction(_function),
65  mUnlink(nullptr),
66  mObject(_object),
67  mFunctionPointer(_functionPointer)
68  {
69  }
70 
71  void invoke(Args... args)
72  {
73  mFunction(args...);
74  }
75 
76  bool compare(DelegateFunction<Args...>* _delegate) const
77  {
78  if (nullptr == _delegate) return false;
79  return _delegate->mObject == mObject && _delegate->mFunctionPointer.compare(mFunctionPointer);
80  }
81 
82  bool compare(IDelegateUnlink* _unlink) const
83  {
84  return mUnlink == _unlink;
85  }
86 
87  private:
88  Function mFunction;
89 
90  const IDelegateUnlink* mUnlink = nullptr;
91  const void* mObject = nullptr;
92  Any mFunctionPointer;
93  };
94 
95 } // namespace delegates
96 
97 // Creates delegate from a function or a static class method
98 template <typename ...Args>
99 inline delegates::DelegateFunction<Args...>* newDelegate(void(*_func)(Args... args))
100 {
101  return new delegates::DelegateFunction<Args...>(_func, _func);
102 }
103 
104 // Creates delegate from a non-static class method
105 template <typename T, typename ...Args>
106 inline delegates::DelegateFunction<Args...>* newDelegate(T* _object, void (T::*_method)(Args... args))
107 {
108  return new delegates::DelegateFunction<Args...>(
109  [=](Args&&... args) { return (_object->*_method)(std::forward<decltype(args)>(args)...); },
110  _method,
111  _object);
112 }
113 template <typename T, typename ...Args>
114 inline delegates::DelegateFunction<Args...>* newDelegate(const T* _object, void (T::*_method)(Args... args) const)
115 {
116  return new delegates::DelegateFunction<Args...>(
117  [=](Args&&... args) { return (_object->*_method)(std::forward<decltype(args)>(args)...); },
118  _method,
119  _object);
120 }
121 
122 // Creates delegate from std::function
123 // Require some user-defined delegateId, that should be used if operator-= is called to remove delegate.
124 // delegateId need to be unique within single delegate.
125 template <typename ...Args>
126 inline delegates::DelegateFunction<Args...>* newDelegate(const std::function<void(Args...)>& _function, int64_t delegateId)
127 {
128  return new delegates::DelegateFunction<Args...>(_function, delegateId);
129 }
130 
131 namespace delegates
132 {
133 
134  template <typename ...Args>
135  class Delegate
136  {
137  public:
138  using IDelegate = DelegateFunction<Args...>;
139 
140  Delegate() : mDelegate(nullptr) { }
141  Delegate(const Delegate& _event) : mDelegate(nullptr)
142  {
143  // take ownership
144  mDelegate = _event.mDelegate;
145  const_cast<Delegate&>(_event).mDelegate = nullptr;
146  }
147 
149  {
150  clear();
151  }
152 
153  bool empty() const
154  {
155  return mDelegate == nullptr;
156  }
157 
158  void clear()
159  {
160  delete mDelegate;
161  mDelegate = nullptr;
162  }
163 
165  {
166  delete mDelegate;
167  mDelegate = _delegate;
168  return *this;
169  }
170 
172  {
173  if (this == &_event)
174  return *this;
175 
176  // take ownership
177  IDelegate* del = _event.mDelegate;
178  const_cast<Delegate&>(_event).mDelegate = nullptr;
179 
180  if (mDelegate != nullptr && !mDelegate->compare(del))
181  delete mDelegate;
182 
183  mDelegate = del;
184 
185  return *this;
186  }
187 
188  void operator()(Args... args) const
189  {
190  if (mDelegate == nullptr) return;
191  mDelegate->invoke(args...);
192  }
193 
194  private:
195  IDelegate* mDelegate;
196  };
197 
198  template <typename ...Args>
200  {
201  public:
202  using IDelegate = DelegateFunction<Args...>;
203  using ListDelegate = typename std::list<IDelegate*>;
204 
207  {
208  clear();
209  }
210 
211  bool empty() const
212  {
213  for (const auto& delegate : mListDelegates)
214  {
215  if (delegate) return false;
216  }
217  return true;
218  }
219 
220  void clear()
221  {
222  for (auto iter = mListDelegates.begin(); iter != mListDelegates.end(); ++iter)
223  {
224  if (*iter)
225  {
226  delete (*iter);
227  (*iter) = nullptr;
228  }
229  }
230  }
231 
232  void clear(IDelegateUnlink* _unlink)
233  {
234  for (auto iter = mListDelegates.begin(); iter != mListDelegates.end(); ++iter)
235  {
236  if ((*iter) && (*iter)->compare(_unlink))
237  {
238  delete (*iter);
239  (*iter) = nullptr;
240  }
241  }
242  }
243 
244  void operator+=(IDelegate* _delegate)
245  {
246  for (auto iter = mListDelegates.begin(); iter != mListDelegates.end(); ++iter)
247  {
248  if ((*iter) && (*iter)->compare(_delegate))
249  {
250  MYGUI_EXCEPT("Trying to add same delegate twice.");
251  }
252  }
253  mListDelegates.push_back(_delegate);
254  }
255 
256  void operator-=(IDelegate* _delegate)
257  {
258  for (auto iter = mListDelegates.begin(); iter != mListDelegates.end(); ++iter)
259  {
260  if ((*iter) && (*iter)->compare(_delegate))
261  {
262  if ((*iter) != _delegate) delete (*iter);
263  (*iter) = nullptr;
264  break;
265  }
266  }
267  delete _delegate;
268  }
269 
270  void operator()(Args... args) const
271  {
272  auto iter = mListDelegates.begin();
273  while (iter != mListDelegates.end())
274  {
275  if (nullptr == (*iter))
276  {
277  iter = mListDelegates.erase(iter);
278  }
279  else
280  {
281  (*iter)->invoke(args...);
282  ++iter;
283  }
284  }
285  }
286 
288  {
289  // take ownership
290  ListDelegate del = _event.mListDelegates;
291  const_cast<MultiDelegate&>(_event).mListDelegates.clear();
292 
293  safe_clear(del);
294 
295  mListDelegates = del;
296  }
297 
299  {
300  // take ownership
301  ListDelegate del = _event.mListDelegates;
302  const_cast<MultiDelegate&>(_event).mListDelegates.clear();
303 
304  safe_clear(del);
305 
306  mListDelegates = del;
307 
308  return *this;
309  }
310 
311  MYGUI_OBSOLETE("use : operator += ")
312  MultiDelegate& operator=(IDelegate* _delegate)
313  {
314  clear();
315  *this += _delegate;
316  return *this;
317  }
318 
319  private:
320  void safe_clear(ListDelegate& _delegates)
321  {
322  for (auto iter = mListDelegates.begin(); iter != mListDelegates.end(); ++iter)
323  {
324  if (*iter)
325  {
326  IDelegate* del = (*iter);
327  (*iter) = nullptr;
328  delete_is_not_found(del, _delegates);
329  }
330  }
331  }
332 
333  void delete_is_not_found(IDelegate* _del, ListDelegate& _delegates)
334  {
335  for (auto iter = _delegates.begin(); iter != _delegates.end(); ++iter)
336  {
337  if ((*iter) && (*iter)->compare(_del))
338  {
339  return;
340  }
341  }
342 
343  delete _del;
344  }
345 
346  private:
347  mutable ListDelegate mListDelegates;
348  };
349 
350 //#ifndef MYGUI_DONT_USE_OBSOLETE // TODO
352  template <typename ...Args>
353  using CDelegate1 = Delegate<Args...>;
354  template <typename ...Args>
355  using CDelegate2 = Delegate<Args...>;
356  template <typename ...Args>
357  using CDelegate3 = Delegate<Args...>;
358  template <typename ...Args>
359  using CDelegate4 = Delegate<Args...>;
360  template <typename ...Args>
361  using CDelegate5 = Delegate<Args...>;
362  template <typename ...Args>
363  using CDelegate6 = Delegate<Args...>;
364 
366  template <typename ...Args>
367  using CMultiDelegate1 = MultiDelegate<Args...>;
368  template <typename ...Args>
369  using CMultiDelegate2 = MultiDelegate<Args...>;
370  template <typename ...Args>
371  using CMultiDelegate3 = MultiDelegate<Args...>;
372  template <typename ...Args>
373  using CMultiDelegate4 = MultiDelegate<Args...>;
374  template <typename ...Args>
375  using CMultiDelegate5 = MultiDelegate<Args...>;
376  template <typename ...Args>
377  using CMultiDelegate6 = MultiDelegate<Args...>;
378 //#endif
379 }
380 
381 } // namespace MyGUI
382 
383 #endif // MYGUI_DELEGATE_H_
#define MYGUI_EXCEPT(dest)
#define MYGUI_OBSOLETE(text)
bool compare(const Any &other) const
Definition: MyGUI_Any.cpp:73
DelegateFunction(Function _function, Any _functionPointer, const void *_object)
DelegateFunction(Function _function, Any _functionPointer)
DelegateFunction(Function _function, Any _functionPointer, const IDelegateUnlink *_object)
std::function< void(Args...)> Function
bool compare(DelegateFunction< Args... > *_delegate) const
bool compare(IDelegateUnlink *_unlink) const
void operator()(Args... args) const
DelegateFunction< Args... > IDelegate
Delegate(const Delegate &_event)
Delegate & operator=(IDelegate *_delegate)
Delegate & operator=(const Delegate< Args... > &_event)
void operator-=(IDelegate *_delegate)
DelegateFunction< Args... > IDelegate
typename std::list< IDelegate * > ListDelegate
void operator+=(IDelegate *_delegate)
MultiDelegate(const MultiDelegate &_event)
void clear(IDelegateUnlink *_unlink)
MultiDelegate & operator=(const MultiDelegate &_event)
void operator()(Args... args) const
delegates::DelegateFunction< Args... > * newDelegate(void(*_func)(Args... args))