MyGUI  3.0.1
MyGUI_DelegateImplement.h
Go to the documentation of this file.
1 
7 /*
8  This file is part of MyGUI.
9 
10  MyGUI is free software: you can redistribute it and/or modify
11  it under the terms of the GNU Lesser General Public License as published by
12  the Free Software Foundation, either version 3 of the License, or
13  (at your option) any later version.
14 
15  MyGUI is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  GNU Lesser General Public License for more details.
19 
20  You should have received a copy of the GNU Lesser General Public License
21  along with MyGUI. If not, see <http://www.gnu.org/licenses/>.
22 */
23 
24 namespace delegates
25 {
26 
27  #define MYGUI_COMBINE(a, b) MYGUI_COMBINE1(a, b)
28  #define MYGUI_COMBINE1(a, b) a##b
29 
30  #define MYGUI_I_DELEGATE MYGUI_COMBINE(IDelegate, MYGUI_SUFFIX)
31 
32  #define MYGUI_C_STATIC_DELEGATE MYGUI_COMBINE(CStaticDelegate, MYGUI_SUFFIX)
33  #define MYGUI_C_METHOD_DELEGATE MYGUI_COMBINE(CMethodDelegate, MYGUI_SUFFIX)
34 
35  #define MYGUI_C_DELEGATE MYGUI_COMBINE(CDelegate, MYGUI_SUFFIX)
36  #define MYGUI_C_MULTI_DELEGATE MYGUI_COMBINE(CMultiDelegate, MYGUI_SUFFIX)
37 
38 
39  // базовый класс всех делегатов
42  {
43  public:
44  virtual ~MYGUI_I_DELEGATE() { }
45  virtual bool isType( const std::type_info& _type) = 0;
46  virtual void invoke( MYGUI_PARAMS ) = 0;
47  virtual bool compare( MYGUI_I_DELEGATE MYGUI_TEMPLATE_ARGS * _delegate) const = 0;
48  virtual bool compare(IDelegateUnlink * _unlink) const { return false; }
49  };
50 
51 
52  // делегат для статической функции
55  {
56  public:
57  typedef void (*Func)( MYGUI_PARAMS );
58 
59  MYGUI_C_STATIC_DELEGATE (Func _func) : mFunc(_func) { }
60 
61  virtual bool isType( const std::type_info& _type) { return typeid( MYGUI_C_STATIC_DELEGATE MYGUI_TEMPLATE_ARGS ) == _type; }
62 
63  virtual void invoke( MYGUI_PARAMS )
64  {
65  mFunc( MYGUI_ARGS );
66  }
67 
68  virtual bool compare( MYGUI_I_DELEGATE MYGUI_TEMPLATE_ARGS * _delegate) const
69  {
70  if (nullptr == _delegate || !_delegate->isType(typeid(MYGUI_C_STATIC_DELEGATE MYGUI_TEMPLATE_ARGS)) ) return false;
71  MYGUI_C_STATIC_DELEGATE MYGUI_TEMPLATE_ARGS * cast = static_cast<MYGUI_C_STATIC_DELEGATE MYGUI_TEMPLATE_ARGS *>(_delegate);
72  return cast->mFunc == mFunc;
73  }
74  virtual bool compare(IDelegateUnlink * _unlink) const { return false; }
75 
76  private:
77  Func mFunc;
78  };
79 
80 
81  // делегат для метода класса
84  {
85  public:
86  typedef void (T::*Method)( MYGUI_PARAMS );
87 
88  MYGUI_C_METHOD_DELEGATE(IDelegateUnlink * _unlink, T * _object, Method _method) : mUnlink(_unlink), mObject(_object), mMethod(_method) { }
89 
90  virtual bool isType( const std::type_info& _type) { return typeid( MYGUI_C_METHOD_DELEGATE MYGUI_T_TEMPLATE_ARGS ) == _type; }
91 
92  virtual void invoke( MYGUI_PARAMS )
93  {
94  (mObject->*mMethod)( MYGUI_ARGS );
95  }
96 
97  virtual bool compare( MYGUI_I_DELEGATE MYGUI_TEMPLATE_ARGS * _delegate) const
98  {
99  if (nullptr == _delegate || !_delegate->isType(typeid(MYGUI_C_METHOD_DELEGATE MYGUI_T_TEMPLATE_ARGS)) ) return false;
100  MYGUI_C_METHOD_DELEGATE MYGUI_T_TEMPLATE_ARGS * cast = static_cast< MYGUI_C_METHOD_DELEGATE MYGUI_T_TEMPLATE_ARGS * >(_delegate);
101  return cast->mObject == mObject && cast->mMethod == mMethod;
102  }
103 
104  virtual bool compare(IDelegateUnlink * _unlink) const
105  {
106  return mUnlink == _unlink;
107  }
108 
109  private:
110  IDelegateUnlink *mUnlink;
111  T * mObject;
112  Method mMethod;
113  };
114 
115 } // namespace delegates
116 
117 // шаблон для создания делегата статической функции
118 // параметры : указатель на функцию
119 // пример : newDelegate(funk_name);
120 // пример : newDelegate(class_name::static_method_name);
123 {
125 }
126 
127 
128 // шаблон для создания делегата метода класса
129 // параметры : указатель на объект класса и указатель на метод класса
130 // пример : newDelegate(&object_name, &class_name::method_name);
132 inline delegates::MYGUI_I_DELEGATE MYGUI_TEMPLATE_ARGS * newDelegate( T * _object, void (T::*_method)( MYGUI_PARAMS ) )
133 {
135 }
136 
137 namespace delegates
138 {
139  // шаблон класса делегата
142  {
143  public:
145 
146  MYGUI_C_DELEGATE () : mDelegate(nullptr) { }
148  {
149  // забираем себе владение
150  mDelegate = _event.mDelegate;
151  const_cast< MYGUI_C_DELEGATE MYGUI_TEMPLATE_ARGS& >(_event).mDelegate = nullptr;
152  }
153  ~MYGUI_C_DELEGATE () { clear(); }
154 
155  bool empty() const { return mDelegate == nullptr; }
156 
157  void clear()
158  {
159  if (mDelegate)
160  {
161  delete mDelegate;
162  mDelegate = nullptr;
163  }
164  }
165 
166  MYGUI_C_DELEGATE MYGUI_TEMPLATE_ARGS & operator=(IDelegate* _delegate)
167  {
168  delete mDelegate;
169  mDelegate = _delegate;
170  return *this;
171  }
172 
174  {
175  // забираем себе владение
176  delete mDelegate;
177  mDelegate = _event.mDelegate;
178  const_cast< MYGUI_C_DELEGATE MYGUI_TEMPLATE_ARGS& >(_event).mDelegate = nullptr;
179 
180  return *this;
181  }
182 
183  void operator()( MYGUI_PARAMS )
184  {
185  if (mDelegate == nullptr) return;
186  mDelegate->invoke( MYGUI_ARGS );
187  }
188 
189  private:
190  IDelegate * mDelegate;
191  };
192 
193 
194  // шаблон класса мульти делегата
197  {
198  public:
200  typedef MYGUI_TYPENAME std::list<IDelegate* /*, Allocator<IDelegate*>*/ > ListDelegate;
201  typedef MYGUI_TYPENAME ListDelegate::iterator ListDelegateIterator;
202  typedef MYGUI_TYPENAME ListDelegate::const_iterator ConstListDelegateIterator;
203 
205  ~MYGUI_C_MULTI_DELEGATE () { clear(); }
206 
207  bool empty() const
208  {
209  for (ConstListDelegateIterator iter = mListDelegates.begin(); iter!=mListDelegates.end(); ++iter)
210  {
211  if (*iter) return false;
212  }
213  return true;
214  }
215 
216  void clear()
217  {
218  for (ListDelegateIterator iter=mListDelegates.begin(); iter!=mListDelegates.end(); ++iter)
219  {
220  if (*iter)
221  {
222  delete (*iter);
223  (*iter) = nullptr;
224  }
225  }
226  }
227 
228  void clear(IDelegateUnlink * _unlink)
229  {
230  for (ListDelegateIterator iter=mListDelegates.begin(); iter!=mListDelegates.end(); ++iter)
231  {
232  if ((*iter) && (*iter)->compare(_unlink))
233  {
234  delete (*iter);
235  (*iter) = nullptr;
236  }
237  }
238  }
239 
240  MYGUI_C_MULTI_DELEGATE MYGUI_TEMPLATE_ARGS & operator+=(IDelegate* _delegate)
241  {
242  for (ListDelegateIterator iter=mListDelegates.begin(); iter!=mListDelegates.end(); ++iter)
243  {
244  if ((*iter) && (*iter)->compare(_delegate))
245  {
246  MYGUI_ASSERT(false, "dublicate delegate");
247  }
248  }
249  mListDelegates.push_back(_delegate);
250  return *this;
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  // проверяем на идентичность делегатов
260  if ((*iter) != _delegate) delete (*iter);
261  (*iter) = nullptr;
262  break;
263  }
264  }
265  delete _delegate;
266  return *this;
267  }
268 
269  void operator()( MYGUI_PARAMS )
270  {
271  ListDelegateIterator iter = mListDelegates.begin();
272  while (iter != mListDelegates.end())
273  {
274  if (nullptr == (*iter))
275  {
276  iter = mListDelegates.erase(iter);
277  }
278  else
279  {
280  (*iter)->invoke( MYGUI_ARGS );
281  ++iter;
282  }
283  }
284  }
285 
286  private:
287  // constructor and operator =, without implementation, just for private
290 
291 
292  private:
293  ListDelegate mListDelegates;
294 
295  };
296 
297 
298  #undef MYGUI_COMBINE
299  #undef MYGUI_COMBINE1
300 
301  #undef MYGUI_I_DELEGATE
302 
303  #undef MYGUI_C_STATIC_DELEGATE
304  #undef MYGUI_C_METHOD_DELEGATE
305 
306  #undef MYGUI_C_DELEGATE
307  #undef MYGUI_C_MULTI_DELEGATE
308 
309  #undef MYGUI_SUFFIX
310  #undef MYGUI_TEMPLATE
311  #undef MYGUI_TEMPLATE_PARAMS
312  #undef MYGUI_TEMPLATE_ARGS
313  #undef MYGUI_T_TEMPLATE_PARAMS
314  #undef MYGUI_T_TEMPLATE_ARGS
315  #undef MYGUI_PARAMS
316  #undef MYGUI_ARGS
317  #undef MYGUI_TYPENAME
318 
319 } // namespace delegates