00001 #ifndef Spr_MISC_CALLBACK_H
00002 #define Spr_MISC_CALLBACK_H
00003 #if _MSC_VER >= 1000
00004 #pragma once
00005 #endif // _MSC_VER >= 1000
00006
00007 #include <vector>
00008 #include <WinBasis/WBWin.h>
00009 #include <Base/BaseDebug.h>
00010
00011 namespace Spr {
00012
00013 template <class TCaller>
00014 struct WXCallbackBase{
00015 virtual void Call(TCaller* caller)=0;
00016 virtual size_t size()const=0;
00017 bool operator ==(const WXCallbackBase& c) const{
00018 if (size() != c.size()) return false;
00019 return memcmp(this, &c, size()) == 0;
00020 }
00021 };
00022
00023 template <class TCaller, class TCallee>
00024 class WXCallback:public WXCallbackBase<TCaller>{
00025 public:
00026 typedef void (TCallee::*Func)(TCaller*);
00027 protected:
00028 TCallee* callee;
00029 Func func;
00030 public:
00031 WXCallback(TCallee* c, Func f){ callee = c; func = f;}
00032 void Call(TCaller* caller){ (callee->*func)(caller); }
00033 size_t size() const { return sizeof(*this); }
00034 };
00035
00036 template <class TCaller>
00037 class WXCallbacks:public std::vector<WXCallbackBase<TCaller>*>{
00038 public:
00039 typedef std::vector<WXCallbackBase<TCaller>*> superclass;
00040 typedef std::vector<WXCallbackBase<TCaller>*> container;
00041 ~WXCallbacks(){
00042 for(iterator it=begin(); it != end(); ++it) delete *it;
00043 }
00044 void Call(TCaller* caller){
00045 container copy(*this);
00046 for(iterator it=copy.begin(); it != copy.end(); ++it) {
00047 if (std::find(begin(), end(), *it) != end()) (*it)->Call(caller);
00048 }
00049 }
00050 superclass::iterator find(const WXCallbackBase<TCaller>& cb){
00051 iterator it;
00052 for(it = begin(); it != end(); ++it) if (**it == cb) break;
00053 return it;
00054 }
00055 bool Add(WXCallbackBase<TCaller>* cb){
00056 iterator itf = find(*cb);
00057 if (itf != end()){
00058 delete cb;
00059 return false;
00060 }
00061 push_back(cb);
00062 return true;
00063 }
00064 bool Del(const WXCallbackBase<TCaller>& cb){
00065 iterator itf = find(cb);
00066 if (itf != end()){
00067 delete *itf;
00068 erase(itf);
00069 return true;
00070 }
00071 DPF("Fail to delete.\n");
00072 return false;
00073 }
00074 };
00075
00076
00077 }
00078
00079 #endif