MyGUI  3.4.0
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, 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, 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  IDelegateUnlink* mUnlink = nullptr;
91  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 
114 namespace delegates
115 {
116 
117  template <typename ...Args>
118  class Delegate
119  {
120  public:
121  using IDelegate = DelegateFunction<Args...>;
122 
123  Delegate() : mDelegate(nullptr) { }
124  Delegate(const Delegate& _event) : mDelegate(nullptr)
125  {
126  // take ownership
127  mDelegate = _event.mDelegate;
128  const_cast<Delegate&>(_event).mDelegate = nullptr;
129  }
130 
132  {
133  clear();
134  }
135 
136  bool empty() const
137  {
138  return mDelegate == nullptr;
139  }
140 
141  void clear()
142  {
143  delete mDelegate;
144  mDelegate = nullptr;
145  }
146 
148  {
149  delete mDelegate;
150  mDelegate = _delegate;
151  return *this;
152  }
153 
155  {
156  if (this == &_event)
157  return *this;
158 
159  // take ownership
160  IDelegate* del = _event.mDelegate;
161  const_cast<Delegate&>(_event).mDelegate = nullptr;
162 
163  if (mDelegate != nullptr && !mDelegate->compare(del))
164  delete mDelegate;
165 
166  mDelegate = del;
167 
168  return *this;
169  }
170 
171  void operator()(Args... args)
172  {
173  if (mDelegate == nullptr) return;
174  mDelegate->invoke(args...);
175  }
176 
177  private:
178  IDelegate* mDelegate;
179  };
180 
181  template <typename ...Args>
183  {
184  public:
185  using IDelegate = DelegateFunction<Args...>;
186  using ListDelegate = typename std::list<IDelegate*>;
187 
190  {
191  clear();
192  }
193 
194  bool empty() const
195  {
196  for (const auto& delegate : mListDelegates)
197  {
198  if (delegate) return false;
199  }
200  return true;
201  }
202 
203  void clear()
204  {
205  for (auto iter = mListDelegates.begin(); iter != mListDelegates.end(); ++iter)
206  {
207  if (*iter)
208  {
209  delete (*iter);
210  (*iter) = nullptr;
211  }
212  }
213  }
214 
215  void clear(IDelegateUnlink* _unlink)
216  {
217  for (auto iter = mListDelegates.begin(); iter != mListDelegates.end(); ++iter)
218  {
219  if ((*iter) && (*iter)->compare(_unlink))
220  {
221  delete (*iter);
222  (*iter) = nullptr;
223  }
224  }
225  }
226 
227  void operator+=(IDelegate* _delegate)
228  {
229  for (auto iter = mListDelegates.begin(); iter != mListDelegates.end(); ++iter)
230  {
231  if ((*iter) && (*iter)->compare(_delegate))
232  {
233  MYGUI_EXCEPT("Trying to add same delegate twice.");
234  }
235  }
236  mListDelegates.push_back(_delegate);
237  }
238 
239  void operator-=(IDelegate* _delegate)
240  {
241  for (auto iter = mListDelegates.begin(); iter != mListDelegates.end(); ++iter)
242  {
243  if ((*iter) && (*iter)->compare(_delegate))
244  {
245  if ((*iter) != _delegate) delete (*iter);
246  (*iter) = nullptr;
247  break;
248  }
249  }
250  delete _delegate;
251  }
252 
253  void operator()(Args... args)
254  {
255  auto iter = mListDelegates.begin();
256  while (iter != mListDelegates.end())
257  {
258  if (nullptr == (*iter))
259  {
260  iter = mListDelegates.erase(iter);
261  }
262  else
263  {
264  (*iter)->invoke(args...);
265  ++iter;
266  }
267  }
268  }
269 
271  {
272  // take ownership
273  ListDelegate del = _event.mListDelegates;
274  const_cast<MultiDelegate&>(_event).mListDelegates.clear();
275 
276  safe_clear(del);
277 
278  mListDelegates = del;
279  }
280 
282  {
283  // take ownership
284  ListDelegate del = _event.mListDelegates;
285  const_cast<MultiDelegate&>(_event).mListDelegates.clear();
286 
287  safe_clear(del);
288 
289  mListDelegates = del;
290 
291  return *this;
292  }
293 
294  MYGUI_OBSOLETE("use : operator += ")
295  MultiDelegate& operator=(IDelegate* _delegate)
296  {
297  clear();
298  *this += _delegate;
299  return *this;
300  }
301 
302  private:
303  void safe_clear(ListDelegate& _delegates)
304  {
305  for (auto iter = mListDelegates.begin(); iter != mListDelegates.end(); ++iter)
306  {
307  if (*iter)
308  {
309  IDelegate* del = (*iter);
310  (*iter) = nullptr;
311  delete_is_not_found(del, _delegates);
312  }
313  }
314  }
315 
316  void delete_is_not_found(IDelegate* _del, ListDelegate& _delegates)
317  {
318  for (auto iter = _delegates.begin(); iter != _delegates.end(); ++iter)
319  {
320  if ((*iter) && (*iter)->compare(_del))
321  {
322  return;
323  }
324  }
325 
326  delete _del;
327  }
328 
329  private:
330  ListDelegate mListDelegates;
331  };
332 
333 //#ifndef MYGUI_DONT_USE_OBSOLETE // TODO
335  template <typename ...Args>
336  using CDelegate1 = Delegate<Args...>;
337  template <typename ...Args>
338  using CDelegate2 = Delegate<Args...>;
339  template <typename ...Args>
340  using CDelegate3 = Delegate<Args...>;
341  template <typename ...Args>
342  using CDelegate4 = Delegate<Args...>;
343  template <typename ...Args>
344  using CDelegate5 = Delegate<Args...>;
345  template <typename ...Args>
346  using CDelegate6 = Delegate<Args...>;
347 
349  template <typename ...Args>
350  using CMultiDelegate1 = MultiDelegate<Args...>;
351  template <typename ...Args>
352  using CMultiDelegate2 = MultiDelegate<Args...>;
353  template <typename ...Args>
354  using CMultiDelegate3 = MultiDelegate<Args...>;
355  template <typename ...Args>
356  using CMultiDelegate4 = MultiDelegate<Args...>;
357  template <typename ...Args>
358  using CMultiDelegate5 = MultiDelegate<Args...>;
359  template <typename ...Args>
360  using CMultiDelegate6 = MultiDelegate<Args...>;
361 //#endif
362 }
363 
364 } // namespace MyGUI
365 
366 #endif // MYGUI_DELEGATE_H_
MyGUI::delegates::MultiDelegate::~MultiDelegate
~MultiDelegate()
Definition: MyGUI_Delegate.h:189
MyGUI::delegates::Delegate::IDelegate
DelegateFunction< Args... > IDelegate
Definition: MyGUI_Delegate.h:121
MyGUI_Diagnostic.h
MyGUI::delegates::MultiDelegate::IDelegate
DelegateFunction< Args... > IDelegate
Definition: MyGUI_Delegate.h:185
MyGUI::delegates::MultiDelegate::operator+=
void operator+=(IDelegate *_delegate)
Definition: MyGUI_Delegate.h:227
MyGUI::delegates::DelegateFunction::DelegateFunction
DelegateFunction(Function _function, Any _functionPointer, void *_object)
Definition: MyGUI_Delegate.h:63
MyGUI::delegates::Delegate::operator=
Delegate & operator=(const Delegate< Args... > &_event)
Definition: MyGUI_Delegate.h:154
MyGUI::delegates::Delegate::operator=
Delegate & operator=(IDelegate *_delegate)
Definition: MyGUI_Delegate.h:147
MyGUI::delegates::DelegateFunction
Definition: MyGUI_Delegate.h:42
MyGUI::delegates::DelegateFunction::invoke
void invoke(Args... args)
Definition: MyGUI_Delegate.h:71
MyGUI::delegates::Delegate::Delegate
Delegate()
Definition: MyGUI_Delegate.h:123
MyGUI::delegates::MultiDelegate
Definition: MyGUI_Delegate.h:183
MyGUI::delegates::DelegateFunction::compare
bool compare(DelegateFunction< Args... > *_delegate) const
Definition: MyGUI_Delegate.h:76
MyGUI::Any
Definition: MyGUI_Any.h:64
MyGUI::delegates::DelegateFunction::Function
std::function< void(Args...)> Function
Definition: MyGUI_Delegate.h:44
MyGUI::delegates::MultiDelegate::clear
void clear(IDelegateUnlink *_unlink)
Definition: MyGUI_Delegate.h:215
MyGUI::delegates::MultiDelegate::empty
bool empty() const
Definition: MyGUI_Delegate.h:194
MyGUI::newDelegate
delegates::DelegateFunction< Args... > * newDelegate(void(*_func)(Args... args))
Definition: MyGUI_Delegate.h:99
MyGUI::delegates::Delegate::operator()
void operator()(Args... args)
Definition: MyGUI_Delegate.h:171
MyGUI::delegates::Delegate::empty
bool empty() const
Definition: MyGUI_Delegate.h:136
MyGUI::delegates::DelegateFunction::DelegateFunction
DelegateFunction(Function _function, Any _functionPointer)
Definition: MyGUI_Delegate.h:47
MyGUI::delegates::Delegate
Definition: MyGUI_Delegate.h:119
MyGUI::delegates::MultiDelegate::MultiDelegate
MultiDelegate(const MultiDelegate &_event)
Definition: MyGUI_Delegate.h:270
MYGUI_EXCEPT
#define MYGUI_EXCEPT(dest)
Definition: MyGUI_Diagnostic.h:26
MyGUI::delegates::DelegateFunction::DelegateFunction
DelegateFunction(Function _function, Any _functionPointer, IDelegateUnlink *_object)
Definition: MyGUI_Delegate.h:54
MyGUI::delegates::MultiDelegate::operator-=
void operator-=(IDelegate *_delegate)
Definition: MyGUI_Delegate.h:239
MyGUI::delegates::Delegate::Delegate
Delegate(const Delegate &_event)
Definition: MyGUI_Delegate.h:124
MyGUI::delegates::MultiDelegate::clear
void clear()
Definition: MyGUI_Delegate.h:203
MyGUI::delegates::DelegateFunction::compare
bool compare(IDelegateUnlink *_unlink) const
Definition: MyGUI_Delegate.h:82
MyGUI::delegates::MultiDelegate< Widget *, ControllerItem * >::ListDelegate
typename std::list< IDelegate * > ListDelegate
Definition: MyGUI_Delegate.h:186
MyGUI::delegates::Delegate::~Delegate
~Delegate()
Definition: MyGUI_Delegate.h:131
MyGUI::delegates::MultiDelegate::operator=
MultiDelegate & operator=(const MultiDelegate &_event)
Definition: MyGUI_Delegate.h:281
MyGUI
Definition: MyGUI_ActionController.h:15
MyGUI::delegates::Delegate::clear
void clear()
Definition: MyGUI_Delegate.h:141
MyGUI_Any.h
MyGUI::delegates::MultiDelegate::MultiDelegate
MultiDelegate()
Definition: MyGUI_Delegate.h:188
MYGUI_OBSOLETE
#define MYGUI_OBSOLETE(text)
Definition: MyGUI_Diagnostic.h:86
MyGUI::delegates::MultiDelegate::operator()
void operator()(Args... args)
Definition: MyGUI_Delegate.h:253