virtual_function_1.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 "../System/exception.h"
00035 #include "slot.h"
00036 #include "signals_impl.h"
00037 
00038 template <typename RetVal, typename Param1> class CL_Super_1;
00039 
00042 template <typename RetVal, class Param1>
00043 class CL_VirtualCallback_1 : public CL_SlotCallback
00044 {
00045 public:
00046         virtual RetVal invoke(Param1 param1, CL_Super_1<RetVal, Param1> &super_func) = 0;
00047 };
00048 
00051 template <typename RetVal, class Param1>
00052 class CL_Super_1
00053 {
00054 public:
00055         RetVal invoke(Param1 param1)
00056         {
00057                 std::vector< CL_SharedPtr<CL_SlotCallback> >::reverse_iterator it = it_super;
00058                 while (it != it_end)
00059                 {
00060                         CL_Super_1<RetVal, Param1> parent;
00061                         parent.it_super = it;
00062                         parent.it_end = it_end;
00063                         ++parent.it_super;
00064 
00065                         if (it->get()->valid && it->get()->enabled)
00066                         {
00067                                 return ((CL_VirtualCallback_1<RetVal, Param1> *) it->get())->invoke(param1, parent);
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 template <typename RetVal, class Param1>
00100 class CL_VirtualCallback_1_static : public CL_VirtualCallback_1<RetVal, Param1>
00101 {
00102 public:
00103         CL_VirtualCallback_1_static(RetVal (*static_func)(Param1, CL_Super_1<RetVal, Param1> &))
00104         : static_func(static_func) { return; }
00105         RetVal invoke(Param1 param1, CL_Super_1<RetVal, Param1> &super_func) { return static_func(param1, super_func); }
00106         RetVal (*static_func)(Param1, CL_Super_1<RetVal, Param1> &);
00107 };
00108 
00111 template <typename RetVal, class Param1, class UserData>
00112 class CL_VirtualCallback_1_static_user : public CL_VirtualCallback_1<RetVal, Param1>
00113 {
00114 public:
00115         CL_VirtualCallback_1_static_user(RetVal (*static_func)(Param1, UserData, CL_Super_1<RetVal, Param1> &), const UserData &user_data)
00116         : static_func(static_func), user_data(user_data) { return; }
00117         RetVal invoke(Param1 param1, CL_Super_1<RetVal, Param1> &super_func) { return static_func(param1, user_data, super_func); }
00118         RetVal (*static_func)(Param1, UserData, CL_Super_1<RetVal, Param1> &);
00119         UserData user_data;
00120 };
00121 
00124 template <typename RetVal, class Param1, class InstanceClass>
00125 class CL_VirtualCallback_1_member : public CL_VirtualCallback_1<RetVal, Param1>
00126 {
00127 public:
00128         CL_VirtualCallback_1_member(InstanceClass *instance, RetVal (InstanceClass::*member_func)(Param1, CL_Super_1<RetVal, Param1> &))
00129         : instance(instance), member_func(member_func) { return; }
00130         RetVal invoke(Param1 param1, CL_Super_1<RetVal, Param1> &super_func) { return (instance->*member_func)(param1, super_func); }
00131         InstanceClass *instance;
00132         RetVal (InstanceClass::*member_func)(Param1, CL_Super_1<RetVal, Param1> &);
00133 };
00134 
00137 template <typename RetVal, class Param1, class InstanceClass, class UserData>
00138 class CL_VirtualCallback_1_member_user : public CL_VirtualCallback_1<RetVal, Param1>
00139 {
00140 public:
00141         CL_VirtualCallback_1_member_user(InstanceClass *instance, RetVal (InstanceClass::*member_func)(Param1, UserData, CL_Super_1<RetVal, Param1> &), const UserData &user_data)
00142         : instance(instance), member_func(member_func), user_data(user_data) { return; }
00143         RetVal invoke(Param1 param1, CL_Super_1<RetVal, Param1> &super_func) { return (instance->*member_func)(param1, user_data, super_func); }
00144         InstanceClass *instance;
00145         RetVal (InstanceClass::*member_func)(Param1, UserData, CL_Super_1<RetVal, Param1> &);
00146         UserData user_data;
00147 };
00148 
00151 template <typename RetVal, class Param1, class Functor>
00152 class CL_VirtualCallback_1_functor : public CL_VirtualCallback_1<RetVal, Param1>
00153 {
00154 public:
00155         CL_VirtualCallback_1_functor(const Functor &functor)
00156         : functor(functor) { return; }
00157         RetVal invoke(Param1 param1, CL_Super_1<RetVal, Param1> &super_func) { return functor(param1, super_func); }
00158         Functor functor;
00159 };
00160 
00164 template <typename RetVal, class Param1>
00165 class CL_VirtualFunction_1
00166 {
00169 
00170 public:
00171         CL_VirtualFunction_1()
00172         : impl(new CL_Signal_Impl) { return; }
00173 
00174         CL_VirtualFunction_1(const CL_VirtualFunction_1<RetVal, Param1> &copy)
00175         : impl(copy.impl) { return; }
00176 
00177 
00181 
00182 public:
00183         CL_Slot connect(RetVal (*function)(Param1, CL_Super_1<RetVal, Param1> &))
00184         {
00185                 clean_up();
00186                 CL_SharedPtr<CL_SlotCallback> callback(
00187                         new CL_VirtualCallback_1_static<RetVal, Param1>(function));
00188                 impl->connected_slots.push_back(callback);
00189                 return CL_Slot(callback);
00190         }
00191 
00192         template<class UserData>
00193         CL_Slot connect(RetVal (*function)(Param1, UserData, CL_Super_1<RetVal, Param1> &), const UserData &user_data)
00194         {
00195                 clean_up();
00196                 CL_SharedPtr<CL_SlotCallback> callback(
00197                         new CL_VirtualCallback_1_static_user<RetVal, Param1, UserData>(function, user_data));
00198                 impl->connected_slots.push_back(callback);
00199                 return CL_Slot(callback);
00200         }
00201 
00202         template<class InstanceClass>
00203         CL_Slot connect(InstanceClass *instance, RetVal (InstanceClass::*function)(Param1, CL_Super_1<RetVal, Param1> &))
00204         {
00205                 clean_up();
00206                 CL_SharedPtr<CL_SlotCallback> callback(
00207                         new CL_VirtualCallback_1_member<RetVal, Param1, InstanceClass>(instance, function));
00208                 impl->connected_slots.push_back(callback);
00209                 return CL_Slot(callback);
00210         }
00211 
00212         template<class InstanceClass, class UserData>
00213         CL_Slot connect(InstanceClass *instance, RetVal (InstanceClass::*function)(Param1, UserData, CL_Super_1<RetVal, Param1> &), const UserData &user_data)
00214         {
00215                 clean_up();
00216                 CL_SharedPtr<CL_SlotCallback> callback(
00217                         new CL_VirtualCallback_1_member_user<RetVal, Param1, InstanceClass, UserData>(instance, function, user_data));
00218                 impl->connected_slots.push_back(callback);
00219                 return CL_Slot(callback);
00220         }
00221 
00222         template<class Functor>
00223         CL_Slot connect_functor(const Functor &functor)
00224         {
00225                 clean_up();
00226                 CL_SharedPtr<CL_SlotCallback> callback(
00227                         new CL_VirtualCallback_1_functor<RetVal, Param1, Functor>(functor));
00228                 impl->connected_slots.push_back(callback);
00229                 return CL_Slot(callback);
00230         }
00231 
00232         RetVal invoke(Param1 param1) const
00233         {
00234                 std::vector< CL_SharedPtr<CL_SlotCallback> > callbacks = impl->connected_slots;
00235                 CL_Super_1<RetVal, Param1> s;
00236                 s.it_super = callbacks.rbegin();
00237                 s.it_end = callbacks.rend();
00238                 return s.invoke(param1);
00239         }
00240 
00241 
00245 
00246 private:
00247         void clean_up()
00248         {
00249                 std::vector< CL_SharedPtr<CL_SlotCallback> >::size_type i, size;
00250                 size = impl->connected_slots.size();
00251                 for (i = 0; i < size; i++)
00252                 {
00253                         if (!impl->connected_slots[i]->valid)
00254                         {
00255                                 impl->connected_slots.erase(impl->connected_slots.begin()+i);
00256                                 i--;
00257                                 size--;
00258                         }
00259                 }
00260         }
00261 
00262         CL_SharedPtr<CL_Signal_Impl> impl;
00264 };
00265 
00266