virtual_function_v0.h

Go to the documentation of this file.
00001 /*
00002 **  ClanLib SDK
00003 **  Copyright (c) 1997-2011 The ClanLib Team
00004 **
00005 **  This software is provided 'as-is', without any express or implied
00006 **  warranty.  In no event will the authors be held liable for any damages
00007 **  arising from the use of this software.
00008 **
00009 **  Permission is granted to anyone to use this software for any purpose,
00010 **  including commercial applications, and to alter it and redistribute it
00011 **  freely, subject to the following restrictions:
00012 **
00013 **  1. The origin of this software must not be misrepresented; you must not
00014 **     claim that you wrote the original software. If you use this software
00015 **     in a product, an acknowledgment in the product documentation would be
00016 **     appreciated but is not required.
00017 **  2. Altered source versions must be plainly marked as such, and must not be
00018 **     misrepresented as being the original software.
00019 **  3. This notice may not be removed or altered from any source distribution.
00020 **
00021 **  Note: Some of the libraries ClanLib may link to may have additional
00022 **  requirements or restrictions.
00023 **
00024 **  File Author(s):
00025 **
00026 **    Magnus Norddahl
00027 */
00028 
00031 
00032 #pragma once
00033 
00034 #include "../api_core.h"
00035 #include "../System/exception.h"
00036 #include "slot.h"
00037 #include "signals_impl.h"
00038 
00039 class CL_Super_v0;
00040 
00043 class CL_API_CORE CL_VirtualCallback_v0 : public CL_SlotCallback
00044 {
00045 public:
00046         virtual void invoke(CL_Super_v0 &super_func) = 0;
00047 };
00048 
00051 class CL_API_CORE CL_Super_v0
00052 {
00053 public:
00054         void invoke()
00055         {
00056                 std::vector< CL_SharedPtr<CL_SlotCallback> >::reverse_iterator it = it_super;
00057                 while (it != it_end)
00058                 {
00059                         CL_Super_v0 parent;
00060                         parent.it_super = it;
00061                         parent.it_end = it_end;
00062                         ++parent.it_super;
00063 
00064                         if (it->get()->valid && it->get()->enabled)
00065                         {
00066                                 ((CL_VirtualCallback_v0 *) it->get())->invoke(parent);
00067                                 return;
00068                         }
00069                         ++it;
00070                 }
00071 
00072                 throw CL_Exception("Called non-invokable super function");
00073         }
00074 
00075         bool is_null() const
00076         {
00077                 std::vector< CL_SharedPtr<CL_SlotCallback> >::reverse_iterator it = it_super;
00078                 while (it != it_end)
00079                 {
00080                         if (it->get()->valid && it->get()->enabled)
00081                                 return false;
00082                         ++it;
00083                 }
00084                 return true;
00085         }
00086 
00087         bool is_invokable() const
00088         {
00089                 return !is_null();
00090         }
00091 
00092         std::vector< CL_SharedPtr<CL_SlotCallback> >::reverse_iterator it_super;
00093 
00094         std::vector< CL_SharedPtr<CL_SlotCallback> >::reverse_iterator it_end;
00095 };
00096 
00099 class CL_API_CORE CL_VirtualCallback_v0_static : public CL_VirtualCallback_v0
00100 {
00101 public:
00102         CL_VirtualCallback_v0_static(void (*static_func)(CL_Super_v0 &))
00103         : static_func(static_func) { return; }
00104         void invoke(CL_Super_v0 &super_func) { static_func(super_func); }
00105         void (*static_func)(CL_Super_v0 &);
00106 };
00107 
00110 template <class UserData>
00111 class CL_VirtualCallback_v0_static_user : public CL_VirtualCallback_v0
00112 {
00113 public:
00114         CL_VirtualCallback_v0_static_user(void (*static_func)(UserData, CL_Super_v0 &), const UserData &user_data)
00115         : static_func(static_func), user_data(user_data) { return; }
00116         void invoke(CL_Super_v0 &super_func) { static_func(user_data, super_func); }
00117         void (*static_func)(UserData, CL_Super_v0 &);
00118         UserData user_data;
00119 };
00120 
00123 template <class InstanceClass>
00124 class CL_VirtualCallback_v0_member : public CL_VirtualCallback_v0
00125 {
00126 public:
00127         CL_VirtualCallback_v0_member(InstanceClass *instance, void (InstanceClass::*member_func)(CL_Super_v0 &))
00128         : instance(instance), member_func(member_func) { return; }
00129         void invoke(CL_Super_v0 &super_func) { (instance->*member_func)(super_func); }
00130         InstanceClass *instance;
00131         void (InstanceClass::*member_func)(CL_Super_v0 &);
00132 };
00133 
00136 template <class InstanceClass, class UserData>
00137 class CL_VirtualCallback_v0_member_user : public CL_VirtualCallback_v0
00138 {
00139 public:
00140         CL_VirtualCallback_v0_member_user(InstanceClass *instance, void (InstanceClass::*member_func)(UserData, CL_Super_v0 &), const UserData &user_data)
00141         : instance(instance), member_func(member_func), user_data(user_data) { return; }
00142         void invoke(CL_Super_v0 &super_func) { (instance->*member_func)(user_data, super_func); }
00143         InstanceClass *instance;
00144         void (InstanceClass::*member_func)(UserData, CL_Super_v0 &);
00145         UserData user_data;
00146 };
00147 
00150 template <class Functor>
00151 class CL_VirtualCallback_v0_functor : public CL_VirtualCallback_v0
00152 {
00153 public:
00154         CL_VirtualCallback_v0_functor(const Functor &functor)
00155         : functor(functor) { return; }
00156         void invoke(CL_Super_v0 &super_func) { functor(super_func); }
00157         Functor functor;
00158 };
00159 
00163 class CL_API_CORE CL_VirtualFunction_v0
00164 {
00167 
00168 public:
00169         CL_VirtualFunction_v0()
00170         : impl(new CL_Signal_Impl) { return; }
00171 
00172         CL_VirtualFunction_v0(const CL_VirtualFunction_v0 &copy)
00173         : impl(copy.impl) { return; }
00174 
00175 
00179 
00180 public:
00181         CL_Slot connect(void (*function)(CL_Super_v0 &))
00182         {
00183                 clean_up();
00184                 CL_SharedPtr<CL_SlotCallback> callback(
00185                         new CL_VirtualCallback_v0_static(function));
00186                 impl->connected_slots.push_back(callback);
00187                 return CL_Slot(callback);
00188         }
00189 
00190         template<class UserData>
00191         CL_Slot connect(void (*function)(CL_Super_v0 &), const UserData &user_data)
00192         {
00193                 clean_up();
00194                 CL_SharedPtr<CL_SlotCallback> callback(
00195                         new CL_VirtualCallback_v0_static_user<UserData>(function, user_data));
00196                 impl->connected_slots.push_back(callback);
00197                 return CL_Slot(callback);
00198         }
00199 
00200         template<class InstanceClass>
00201         CL_Slot connect(InstanceClass *instance, void (InstanceClass::*function)(CL_Super_v0 &))
00202         {
00203                 clean_up();
00204                 CL_SharedPtr<CL_SlotCallback> callback(
00205                         new CL_VirtualCallback_v0_member<InstanceClass>(instance, function));
00206                 impl->connected_slots.push_back(callback);
00207                 return CL_Slot(callback);
00208         }
00209 
00210         template<class InstanceClass, class UserData>
00211         CL_Slot connect(InstanceClass *instance, void (InstanceClass::*function)(UserData, CL_Super_v0 &), const UserData &user_data)
00212         {
00213                 clean_up();
00214                 CL_SharedPtr<CL_SlotCallback> callback(
00215                         new CL_VirtualCallback_v0_member_user<InstanceClass, UserData>(instance, function, user_data));
00216                 impl->connected_slots.push_back(callback);
00217                 return CL_Slot(callback);
00218         }
00219 
00220         template<class Functor>
00221         CL_Slot connect_functor(const Functor &functor)
00222         {
00223                 clean_up();
00224                 CL_SharedPtr<CL_SlotCallback> callback(
00225                         new CL_VirtualCallback_v0_functor<Functor>(functor));
00226                 impl->connected_slots.push_back(callback);
00227                 return CL_Slot(callback);
00228         }
00229 
00230         void invoke() const
00231         {
00232                 std::vector< CL_SharedPtr<CL_SlotCallback> > callbacks = impl->connected_slots;
00233                 CL_Super_v0 s;
00234                 s.it_super = callbacks.rbegin();
00235                 s.it_end = callbacks.rend();
00236                 s.invoke();
00237         }
00238 
00239 
00243 
00244 private:
00245         void clean_up()
00246         {
00247                 std::vector< CL_SharedPtr<CL_SlotCallback> >::size_type i, size;
00248                 size = impl->connected_slots.size();
00249                 for (i = 0; i < size; i++)
00250                 {
00251                         if (!impl->connected_slots[i]->valid)
00252                         {
00253                                 impl->connected_slots.erase(impl->connected_slots.begin()+i);
00254                                 i--;
00255                                 size--;
00256                         }
00257                 }
00258         }
00259 
00260         CL_SharedPtr<CL_Signal_Impl> impl;
00262 };
00263 
00264