ClanLib  2.3.7
virtual_function_v1.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 "../System/exception.h"
35 #include "slot.h"
36 #include "signals_impl.h"
37 
38 template <typename Param1> class CL_Super_v1;
39 
42 template <class Param1>
44 {
45 public:
46  virtual void invoke(Param1 param1, CL_Super_v1<Param1> &super_func) = 0;
47 };
48 
51 template <class Param1>
52 class CL_Super_v1
53 {
54 public:
55  void invoke(Param1 param1)
56  {
57  std::vector< CL_SharedPtr<CL_SlotCallback> >::reverse_iterator it = it_super;
58  while (it != it_end)
59  {
60  CL_Super_v1<Param1> parent;
61  parent.it_super = it;
62  parent.it_end = it_end;
63  ++parent.it_super;
64 
65  if (it->get()->valid && it->get()->enabled)
66  {
67  ((CL_VirtualCallback_v1<Param1> *) it->get())->invoke(param1, parent);
68  return;
69  }
70  ++it;
71  }
72 
73  throw CL_Exception("Called non-invokable super function");
74  }
75 
76  bool is_null() const
77  {
78  std::vector< CL_SharedPtr<CL_SlotCallback> >::reverse_iterator it = it_super;
79  while (it != it_end)
80  {
81  if (it->get()->valid && it->get()->enabled)
82  return false;
83  ++it;
84  }
85  return true;
86  }
87 
88  bool is_invokable() const
89  {
90  return !is_null();
91  }
92 
93  std::vector< CL_SharedPtr<CL_SlotCallback> >::reverse_iterator it_super;
94 
95  std::vector< CL_SharedPtr<CL_SlotCallback> >::reverse_iterator it_end;
96 };
97 
100 template <class Param1>
102 {
103 public:
105  : static_func(static_func) { return; }
106  void invoke(Param1 param1, CL_Super_v1<Param1> &super_func) { static_func(param1, super_func); }
107  void (*static_func)(Param1, CL_Super_v1<Param1> &);
108 };
109 
112 template <class Param1, class UserData>
114 {
115 public:
116  CL_VirtualCallback_v1_static_user(void (*static_func)(Param1, UserData, CL_Super_v1<Param1> &), const UserData &user_data)
117  : static_func(static_func), user_data(user_data) { return; }
118  void invoke(Param1 param1, CL_Super_v1<Param1> &super_func) { static_func(param1, user_data, super_func); }
119  void (*static_func)(Param1, UserData, CL_Super_v1<Param1> &);
120  UserData user_data;
121 };
122 
125 template <class Param1, class InstanceClass>
127 {
128 public:
129  CL_VirtualCallback_v1_member(InstanceClass *instance, void (InstanceClass::*member_func)(Param1, CL_Super_v1<Param1> &))
130  : instance(instance), member_func(member_func) { return; }
131  void invoke(Param1 param1, CL_Super_v1<Param1> &super_func) { (instance->*member_func)(param1, super_func); }
132  InstanceClass *instance;
133  void (InstanceClass::*member_func)(Param1, CL_Super_v1<Param1> &);
134 };
135 
138 template <class Param1, class InstanceClass, class UserData>
140 {
141 public:
142  CL_VirtualCallback_v1_member_user(InstanceClass *instance, void (InstanceClass::*member_func)(Param1, UserData, CL_Super_v1<Param1> &), const UserData &user_data)
143  : instance(instance), member_func(member_func), user_data(user_data) { return; }
144  void invoke(Param1 param1, CL_Super_v1<Param1> &super_func) { (instance->*member_func)(param1, user_data, super_func); }
145  InstanceClass *instance;
146  void (InstanceClass::*member_func)(Param1, UserData, CL_Super_v1<Param1> &);
147  UserData user_data;
148 };
149 
152 template <class Param1, class Functor>
154 {
155 public:
157  : functor(functor) { return; }
158  void invoke(Param1 param1, CL_Super_v1<Param1> &super_func) { functor(param1, super_func); }
159  Functor functor;
160 };
161 
165 template <class Param1>
167 {
170 
171 public:
173  : impl(new CL_Signal_Impl) { return; }
174 
176  : impl(copy.impl) { return; }
177 
178 
182 
183 public:
184  CL_Slot connect(void (*function)(Param1, CL_Super_v1<Param1> &))
185  {
186  clean_up();
187  CL_SharedPtr<CL_SlotCallback> callback(
189  impl->connected_slots.push_back(callback);
190  return CL_Slot(callback);
191  }
192 
193  template<class UserData>
194  CL_Slot connect(void (*function)(Param1, UserData, CL_Super_v1<Param1> &), const UserData &user_data)
195  {
196  clean_up();
197  CL_SharedPtr<CL_SlotCallback> callback(
198  new CL_VirtualCallback_v1_static_user<Param1, UserData>(function, user_data));
199  impl->connected_slots.push_back(callback);
200  return CL_Slot(callback);
201  }
202 
203  template<class InstanceClass>
204  CL_Slot connect(InstanceClass *instance, void (InstanceClass::*function)(Param1, CL_Super_v1<Param1> &))
205  {
206  clean_up();
207  CL_SharedPtr<CL_SlotCallback> callback(
209  impl->connected_slots.push_back(callback);
210  return CL_Slot(callback);
211  }
212 
213  template<class InstanceClass, class UserData>
214  CL_Slot connect(InstanceClass *instance, void (InstanceClass::*function)(Param1, UserData, CL_Super_v1<Param1> &), const UserData &user_data)
215  {
216  clean_up();
217  CL_SharedPtr<CL_SlotCallback> callback(
218  new CL_VirtualCallback_v1_member_user<Param1, InstanceClass, UserData>(instance, function, user_data));
219  impl->connected_slots.push_back(callback);
220  return CL_Slot(callback);
221  }
222 
223  template<class Functor>
224  CL_Slot connect_functor(const Functor &functor)
225  {
226  clean_up();
227  CL_SharedPtr<CL_SlotCallback> callback(
229  impl->connected_slots.push_back(callback);
230  return CL_Slot(callback);
231  }
232 
233  void invoke(Param1 param1) const
234  {
235  std::vector< CL_SharedPtr<CL_SlotCallback> > callbacks = impl->connected_slots;
237  s.it_super = callbacks.rbegin();
238  s.it_end = callbacks.rend();
239  s.invoke(param1);
240  }
241 
242 
246 
247 private:
248  void clean_up()
249  {
250  std::vector< CL_SharedPtr<CL_SlotCallback> >::size_type i, size;
251  size = impl->connected_slots.size();
252  for (i = 0; i < size; i++)
253  {
254  if (!impl->connected_slots[i]->valid)
255  {
256  impl->connected_slots.erase(impl->connected_slots.begin()+i);
257  i--;
258  size--;
259  }
260  }
261  }
262 
263  CL_SharedPtr<CL_Signal_Impl> impl;
265 };
266 
267