Back to index

extremetuxracer  0.5beta
signal.h
Go to the documentation of this file.
00001 /* 
00002  * PPRacer 
00003  * Copyright (C) 2004-2005 Peter Reichel <peter@apps4linux.org>
00004  *                         Volker Stroebel <volker@planetpenguin.de>
00005  * This program is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU General Public License
00007  * as published by the Free Software Foundation; either version 2
00008  * of the License, or (at your option) any later version.
00009  * 
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU General Public License for more details.
00014  * 
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program; if not, write to the Free Software
00017  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00018  */
00019 
00020 
00021 #ifndef PP_SIGNAL_H
00022 #define PP_SIGNAL_H
00023 
00024 #include <stdlib.h>
00025 
00026 namespace pp{
00027 
00028 
00029 class BaseSlot;
00030 class BaseSignal;
00031 class BaseArgument;
00032 
00033 class BaseArgument {
00034 public:
00035        BaseArgument(int cnt) : mCnt(cnt){};
00036 
00037        virtual ~BaseArgument() {}
00038        int Count() const { return mCnt; }
00039 private:
00040        int mCnt;
00041 };
00042 
00043 class Argument0 : public BaseArgument {
00044 public:
00045        Argument0() : BaseArgument(0) { }
00046        ~Argument0() { }
00047 };
00048 
00049 template<class R1>
00050 class Argument1 : public BaseArgument {
00051 public:
00052        Argument1(R1 a1) : BaseArgument(1)
00053        {
00054               mArg1 = a1;
00055        }
00056        ~Argument1() { }
00057 
00058        R1 Arg1() const { return mArg1; }
00059 private:
00060        R1 mArg1;
00061 };
00062 
00063 template<class R1, class R2>
00064 class Argument2 : public BaseArgument {
00065 public:
00066        Argument2(R1 a1, R2 a2) : BaseArgument(2)
00067        {
00068               mArg1 = a1;
00069               mArg2 = a2;
00070        }
00071        ~Argument2() { }
00072 
00073        R1 Arg1() const { return mArg1; }
00074        R2 Arg2() const { return mArg2; }
00075 private:
00076        R1 mArg1;
00077        R2 mArg2;
00078 };
00079 
00080 //Slotklasse
00081 
00082 class BaseSlot {
00083 public:
00084        BaseSlot() { }
00085        virtual ~BaseSlot() { }
00086 
00087        virtual void Call(BaseArgument *arg) = 0;
00088 };
00089 
00090 template<class T>
00091 class Slot0 : public BaseSlot {
00092 public:
00093        typedef void (T::*SlotPtr_t)();
00094        Slot0(T *rcv, SlotPtr_t sl)
00095        {
00096               mRcv = rcv;
00097               mSlot = sl;
00098        }
00099        ~Slot0() { }
00100 
00101        void Call(BaseArgument *arg)
00102        {
00103               
00104               //Argumente brauchen ned ausgewertet werden => 0
00105               return (*mRcv.*mSlot)();
00106        }
00107 private:
00108        T *mRcv;
00109        SlotPtr_t mSlot;
00110 };
00111 
00112 
00113 template<class T, class R1>
00114 class Slot1 : public BaseSlot {
00115 public:
00116        typedef void (T::*SlotPtr_t)(R1);
00117        Slot1(T *rcv, SlotPtr_t sl)
00118        {
00119               mRcv = rcv;
00120               mSlot = sl;
00121        }
00122        ~Slot1() { }
00123 
00124        void Call(BaseArgument *arg)
00125        {
00126               if (arg->Count() == 1) {
00127                      Argument1<R1> *a1 = static_cast<Argument1<R1>* >(arg);
00128                      if (arg) (*mRcv.*mSlot)(a1->Arg1());
00129               }
00130 
00131               //mit RTTI
00132 //            Argument1<R1> *a1 = dynamic_cast<Argument1<R1>* >(arg);
00133 //            if (arg) (*mRcv.*mSlot)(a1->Arg1());
00134        }
00135 private:
00136        T *mRcv;
00137        SlotPtr_t mSlot;
00138 };
00139 
00140 template<class T, class R1, class R2>
00141 class Slot2 : public BaseSlot {
00142 public:
00143        typedef void (T::*SlotPtr_t)(R1,R2);
00144        Slot2(T *rcv, SlotPtr_t sl)
00145        {
00146               mRcv = rcv;
00147               mSlot = sl;
00148        }
00149        ~Slot2() { }
00150 
00151        void Call(BaseArgument *arg)
00152        {
00153               if (arg->Count() == 2) {
00154                      Argument2<R1,R2> *a1 = static_cast<Argument2<R1,R2>* >(arg);
00155                      if (arg) (*mRcv.*mSlot)(a1->Arg1(),a1->Arg2());
00156               }
00157        }
00158 private:
00159        T *mRcv;
00160        SlotPtr_t mSlot;
00161 };
00162 
00163 //Signalklasse
00164 
00165 class BaseSignal {
00166 public:
00167        BaseSignal() : mSlot(NULL)
00168        {
00169        }
00170        
00171        virtual ~BaseSignal()
00172        {
00173               Clean();
00174        }
00175        
00176        void Connect(BaseSlot *slot)
00177        {
00178               Clean();
00179               mSlot = slot;
00180        }
00181 private:
00182        //only to ensure noone tries to do this
00183        BaseSignal(const BaseSignal&);     
00184        BaseSignal operator=(const BaseSignal&);
00185 
00186        void Clean()
00187        {
00188               if (mSlot) {
00189                      delete mSlot;
00190                      mSlot = NULL;
00191               }
00192        }
00193 protected:
00194        BaseSlot *mSlot;
00195 };
00196 
00197 class Signal0 : public BaseSignal {
00198 public:
00199        Signal0() { }
00200        ~Signal0() { }
00201 
00202        void Emit()
00203        {
00204               if (mSlot) {
00205                      Argument0 arg;
00206                      mSlot->Call(&arg);
00207               }
00208        }
00209 };
00210 
00211 template<class R1>
00212 class Signal1 : public BaseSignal {
00213 public:
00214        Signal1() { }
00215        ~Signal1() { }
00216 
00217        void Emit(R1 r1)
00218        {
00219               if (mSlot) {
00220                      Argument1<R1> arg(r1);
00221                      mSlot->Call(&arg);
00222               }
00223        }
00224 };
00225 
00226 template<class R1, class R2>
00227 class Signal2 : public BaseSignal {
00228 public:
00229        Signal2() { }
00230        ~Signal2() { }
00231 
00232        void Emit(R1 r1, R2 r2)
00233        {
00234 
00235               if (mSlot) {
00236                      Argument2<R1,R2> arg(r1,r2);
00237                      mSlot->Call(&arg);
00238               }
00239        }
00240 };
00241 
00242 //Creation function
00243 
00244 template<class T>
00245 BaseSlot* CreateSlot(T* rcv, void (T::*sl)())
00246 {
00247        return new Slot0<T>(rcv,sl);
00248 }
00249 
00250 template<class T, class R1>
00251 BaseSlot* CreateSlot(T* rcv, void (T::*sl)(R1))
00252 {
00253        return new Slot1<T,R1>(rcv,sl);
00254 }
00255 
00256 template<class T, class R1, class R2>
00257 BaseSlot* CreateSlot(T* rcv, void (T::*sl)(R1,R2))
00258 {
00259        return new Slot2<T,R1,R2>(rcv,sl);
00260 }
00261 
00262 }// namepsace pp
00263 
00264 #endif // PP_SIGNAL_H