ClanLib  2.3.7
virtual_function_v0.h
Go to the documentation of this file.
1 /*
2 ** ClanLib SDK
3 ** Copyright (c) 1997-2011 The ClanLib Team
4 **
5 ** This software is provided 'as-is', without any express or implied
6 ** warranty. In no event will the authors be held liable for any damages
7 ** arising from the use of this software.
8 **
9 ** Permission is granted to anyone to use this software for any purpose,
10 ** including commercial applications, and to alter it and redistribute it
11 ** freely, subject to the following restrictions:
12 **
13 ** 1. The origin of this software must not be misrepresented; you must not
14 ** claim that you wrote the original software. If you use this software
15 ** in a product, an acknowledgment in the product documentation would be
16 ** appreciated but is not required.
17 ** 2. Altered source versions must be plainly marked as such, and must not be
18 ** misrepresented as being the original software.
19 ** 3. This notice may not be removed or altered from any source distribution.
20 **
21 ** Note: Some of the libraries ClanLib may link to may have additional
22 ** requirements or restrictions.
23 **
24 ** File Author(s):
25 **
26 ** Magnus Norddahl
27 */
28 
31 
32 #pragma once
33 
34 #include "../api_core.h"
35 #include "../System/exception.h"
36 #include "slot.h"
37 #include "signals_impl.h"
38 
39 class CL_Super_v0;
40 
44 {
45 public:
46  virtual void invoke(CL_Super_v0 &super_func) = 0;
47 };
48 
52 {
53 public:
54  void invoke()
55  {
56  std::vector< CL_SharedPtr<CL_SlotCallback> >::reverse_iterator it = it_super;
57  while (it != it_end)
58  {
59  CL_Super_v0 parent;
60  parent.it_super = it;
61  parent.it_end = it_end;
62  ++parent.it_super;
63 
64  if (it->get()->valid && it->get()->enabled)
65  {
66  ((CL_VirtualCallback_v0 *) it->get())->invoke(parent);
67  return;
68  }
69  ++it;
70  }
71 
72  throw CL_Exception("Called non-invokable super function");
73  }
74 
75  bool is_null() const
76  {
77  std::vector< CL_SharedPtr<CL_SlotCallback> >::reverse_iterator it = it_super;
78  while (it != it_end)
79  {
80  if (it->get()->valid && it->get()->enabled)
81  return false;
82  ++it;
83  }
84  return true;
85  }
86 
87  bool is_invokable() const
88  {
89  return !is_null();
90  }
91 
92  std::vector< CL_SharedPtr<CL_SlotCallback> >::reverse_iterator it_super;
93 
94  std::vector< CL_SharedPtr<CL_SlotCallback> >::reverse_iterator it_end;
95 };
96 
100 {
101 public:
103  : static_func(static_func) { return; }
104  void invoke(CL_Super_v0 &super_func) { static_func(super_func); }
105  void (*static_func)(CL_Super_v0 &);
106 };
107 
110 template <class UserData>
112 {
113 public:
115  : static_func(static_func), user_data(user_data) { return; }
116  void invoke(CL_Super_v0 &super_func) { static_func(user_data, super_func); }
117  void (*static_func)(UserData, CL_Super_v0 &);
118  UserData user_data;
119 };
120 
123 template <class InstanceClass>
125 {
126 public:
127  CL_VirtualCallback_v0_member(InstanceClass *instance, void (InstanceClass::*member_func)(CL_Super_v0 &))
128  : instance(instance), member_func(member_func) { return; }
129  void invoke(CL_Super_v0 &super_func) { (instance->*member_func)(super_func); }
130  InstanceClass *instance;
131  void (InstanceClass::*member_func)(CL_Super_v0 &);
132 };
133 
136 template <class InstanceClass, class UserData>
138 {
139 public:
140  CL_VirtualCallback_v0_member_user(InstanceClass *instance, void (InstanceClass::*member_func)(UserData, CL_Super_v0 &), const UserData &user_data)
141  : instance(instance), member_func(member_func), user_data(user_data) { return; }
142  void invoke(CL_Super_v0 &super_func) { (instance->*member_func)(user_data, super_func); }
143  InstanceClass *instance;
144  void (InstanceClass::*member_func)(UserData, CL_Super_v0 &);
145  UserData user_data;
146 };
147 
150 template <class Functor>
152 {
153 public:
155  : functor(functor) { return; }
156  void invoke(CL_Super_v0 &super_func) { functor(super_func); }
157  Functor functor;
158 };
159 
164 {
167 
168 public:
170  : impl(new CL_Signal_Impl) { return; }
171 
173  : impl(copy.impl) { return; }
174 
175 
179 
180 public:
181  CL_Slot connect(void (*function)(CL_Super_v0 &))
182  {
183  clean_up();
184  CL_SharedPtr<CL_SlotCallback> callback(
185  new CL_VirtualCallback_v0_static(function));
186  impl->connected_slots.push_back(callback);
187  return CL_Slot(callback);
188  }
189 
190  template<class UserData>
191  CL_Slot connect(void (*function)(CL_Super_v0 &), const UserData &user_data)
192  {
193  clean_up();
194  CL_SharedPtr<CL_SlotCallback> callback(
195  new CL_VirtualCallback_v0_static_user<UserData>(function, user_data));
196  impl->connected_slots.push_back(callback);
197  return CL_Slot(callback);
198  }
199 
200  template<class InstanceClass>
201  CL_Slot connect(InstanceClass *instance, void (InstanceClass::*function)(CL_Super_v0 &))
202  {
203  clean_up();
204  CL_SharedPtr<CL_SlotCallback> callback(
205  new CL_VirtualCallback_v0_member<InstanceClass>(instance, function));
206  impl->connected_slots.push_back(callback);
207  return CL_Slot(callback);
208  }
209 
210  template<class InstanceClass, class UserData>
211  CL_Slot connect(InstanceClass *instance, void (InstanceClass::*function)(UserData, CL_Super_v0 &), const UserData &user_data)
212  {
213  clean_up();
214  CL_SharedPtr<CL_SlotCallback> callback(
215  new CL_VirtualCallback_v0_member_user<InstanceClass, UserData>(instance, function, user_data));
216  impl->connected_slots.push_back(callback);
217  return CL_Slot(callback);
218  }
219 
220  template<class Functor>
221  CL_Slot connect_functor(const Functor &functor)
222  {
223  clean_up();
224  CL_SharedPtr<CL_SlotCallback> callback(
226  impl->connected_slots.push_back(callback);
227  return CL_Slot(callback);
228  }
229 
230  void invoke() const
231  {
232  std::vector< CL_SharedPtr<CL_SlotCallback> > callbacks = impl->connected_slots;
233  CL_Super_v0 s;
234  s.it_super = callbacks.rbegin();
235  s.it_end = callbacks.rend();
236  s.invoke();
237  }
238 
239 
243 
244 private:
245  void clean_up()
246  {
247  std::vector< CL_SharedPtr<CL_SlotCallback> >::size_type i, size;
248  size = impl->connected_slots.size();
249  for (i = 0; i < size; i++)
250  {
251  if (!impl->connected_slots[i]->valid)
252  {
253  impl->connected_slots.erase(impl->connected_slots.begin()+i);
254  i--;
255  size--;
256  }
257  }
258  }
259 
260  CL_SharedPtr<CL_Signal_Impl> impl;
262 };
263 
264