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
16namespace MyGUI
17{
18
19namespace 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
98template <typename ...Args>
99inline 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
105template <typename T, typename ...Args>
106inline 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}
113template <typename T, typename ...Args>
114inline 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.
125template <typename ...Args>
126inline delegates::DelegateFunction<Args...>* newDelegate(const std::function<void(Args...)>& _function, int64_t delegateId)
127{
128 return new delegates::DelegateFunction<Args...>(_function, delegateId);
129}
130
131namespace delegates
132{
133
134 template <typename ...Args>
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>
368 template <typename ...Args>
370 template <typename ...Args>
372 template <typename ...Args>
374 template <typename ...Args>
376 template <typename ...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=(const Delegate< Args... > &_event)
Delegate & operator=(IDelegate *_delegate)
MultiDelegate & operator=(const MultiDelegate &_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)
void operator()(Args... args) const
delegates::DelegateFunction< Args... > * newDelegate(void(*_func)(Args... args))