ClanLib  2.3.7
virtual_function_1.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 RetVal, typename Param1> class CL_Super_1;
39 
42 template <typename RetVal, class Param1>
44 {
45 public:
46  virtual RetVal invoke(Param1 param1, CL_Super_1<RetVal, Param1> &super_func) = 0;
47 };
48 
51 template <typename RetVal, class Param1>
52 class CL_Super_1
53 {
54 public:
55  RetVal invoke(Param1 param1)
56  {
57  std::vector< CL_SharedPtr<CL_SlotCallback> >::reverse_iterator it = it_super;
58  while (it != it_end)
59  {
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  return ((CL_VirtualCallback_1<RetVal, Param1> *) it->get())->invoke(param1, parent);
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 
99 template <typename RetVal, class Param1>
100 class CL_VirtualCallback_1_static : public CL_VirtualCallback_1<RetVal, Param1>
101 {
102 public:
104  : static_func(static_func) { return; }
105  RetVal invoke(Param1 param1, CL_Super_1<RetVal, Param1> &super_func) { return static_func(param1, super_func); }
107 };
108 
111 template <typename RetVal, class Param1, class UserData>
113 {
114 public:
115  CL_VirtualCallback_1_static_user(RetVal (*static_func)(Param1, UserData, CL_Super_1<RetVal, Param1> &), const UserData &user_data)
116  : static_func(static_func), user_data(user_data) { return; }
117  RetVal invoke(Param1 param1, CL_Super_1<RetVal, Param1> &super_func) { return static_func(param1, user_data, super_func); }
118  RetVal (*static_func)(Param1, UserData, CL_Super_1<RetVal, Param1> &);
119  UserData user_data;
120 };
121 
124 template <typename RetVal, class Param1, class InstanceClass>
125 class CL_VirtualCallback_1_member : public CL_VirtualCallback_1<RetVal, Param1>
126 {
127 public:
128  CL_VirtualCallback_1_member(InstanceClass *instance, RetVal (InstanceClass::*member_func)(Param1, CL_Super_1<RetVal, Param1> &))
129  : instance(instance), member_func(member_func) { return; }
130  RetVal invoke(Param1 param1, CL_Super_1<RetVal, Param1> &super_func) { return (instance->*member_func)(param1, super_func); }
131  InstanceClass *instance;
132  RetVal (InstanceClass::*member_func)(Param1, CL_Super_1<RetVal, Param1> &);
133 };
134 
137 template <typename RetVal, class Param1, class InstanceClass, class UserData>
139 {
140 public:
141  CL_VirtualCallback_1_member_user(InstanceClass *instance, RetVal (InstanceClass::*member_func)(Param1, UserData, CL_Super_1<RetVal, Param1> &), const UserData &user_data)
142  : instance(instance), member_func(member_func), user_data(user_data) { return; }
143  RetVal invoke(Param1 param1, CL_Super_1<RetVal, Param1> &super_func) { return (instance->*member_func)(param1, user_data, super_func); }
144  InstanceClass *instance;
145  RetVal (InstanceClass::*member_func)(Param1, UserData, CL_Super_1<RetVal, Param1> &);
146  UserData user_data;
147 };
148 
151 template <typename RetVal, class Param1, class Functor>
153 {
154 public:
156  : functor(functor) { return; }
157  RetVal invoke(Param1 param1, CL_Super_1<RetVal, Param1> &super_func) { return functor(param1, super_func); }
158  Functor functor;
159 };
160 
164 template <typename RetVal, class Param1>
166 {
169 
170 public:
172  : impl(new CL_Signal_Impl) { return; }
173 
175  : impl(copy.impl) { return; }
176 
177 
181 
182 public:
183  CL_Slot connect(RetVal (*function)(Param1, CL_Super_1<RetVal, Param1> &))
184  {
185  clean_up();
186  CL_SharedPtr<CL_SlotCallback> callback(
188  impl->connected_slots.push_back(callback);
189  return CL_Slot(callback);
190  }
191 
192  template<class UserData>
193  CL_Slot connect(RetVal (*function)(Param1, UserData, CL_Super_1<RetVal, Param1> &), const UserData &user_data)
194  {
195  clean_up();
196  CL_SharedPtr<CL_SlotCallback> callback(
198  impl->connected_slots.push_back(callback);
199  return CL_Slot(callback);
200  }
201 
202  template<class InstanceClass>
203  CL_Slot connect(InstanceClass *instance, RetVal (InstanceClass::*function)(Param1, CL_Super_1<RetVal, Param1> &))
204  {
205  clean_up();
206  CL_SharedPtr<CL_SlotCallback> callback(
208  impl->connected_slots.push_back(callback);
209  return CL_Slot(callback);
210  }
211 
212  template<class InstanceClass, class UserData>
213  CL_Slot connect(InstanceClass *instance, RetVal (InstanceClass::*function)(Param1, UserData, CL_Super_1<RetVal, Param1> &), const UserData &user_data)
214  {
215  clean_up();
216  CL_SharedPtr<CL_SlotCallback> callback(
218  impl->connected_slots.push_back(callback);
219  return CL_Slot(callback);
220  }
221 
222  template<class Functor>
223  CL_Slot connect_functor(const Functor &functor)
224  {
225  clean_up();
226  CL_SharedPtr<CL_SlotCallback> callback(
228  impl->connected_slots.push_back(callback);
229  return CL_Slot(callback);
230  }
231 
232  RetVal invoke(Param1 param1) const
233  {
234  std::vector< CL_SharedPtr<CL_SlotCallback> > callbacks = impl->connected_slots;
236  s.it_super = callbacks.rbegin();
237  s.it_end = callbacks.rend();
238  return s.invoke(param1);
239  }
240 
241 
245 
246 private:
247  void clean_up()
248  {
249  std::vector< CL_SharedPtr<CL_SlotCallback> >::size_type i, size;
250  size = impl->connected_slots.size();
251  for (i = 0; i < size; i++)
252  {
253  if (!impl->connected_slots[i]->valid)
254  {
255  impl->connected_slots.erase(impl->connected_slots.begin()+i);
256  i--;
257  size--;
258  }
259  }
260  }
261 
262  CL_SharedPtr<CL_Signal_Impl> impl;
264 };
265 
266