#ifndef _DISPATCHER_H_ #define _DISPATCHER_H_ #include #include #include #include //****************************************************************************************************/ // EventDispatcher && EventIdentDispatcher // /***************************************************************************************************/ // This handy class(es) act as very simple signals/events. // Its OOP-only, so dont even try to add static functions // or C-like methods! // // :: Return Types :: // // at the moment only callbacks for void methods with a parameter // count of one ( whos type is the primary template parameter) // // :: callback signature :: // // typedef void (T::*callback)(U); // with as template // // :: Usage Example :: // // *creating a Dispatcher // // -- EventDispatcher* nameYourDispatcher = new EventDispatcher; // simple Dispatcher // -- EventIdentDispatcher* nameYourIdentDispatcher = new EventIdentDispatcher; // ident dispatcher // // *difference between simple and ident // // a simple dispatcher features only one type of signal, so you can only call all // attached listeners at once or none at all // // an ident dispatcher uses an ident string to hold and fire more than one event type at once // but is limited to the one defined parameter type for its methods // // *subscribung to a dispatcher // // -- nameYourDispatcher->addListener(, &myClass::myMethod); // simple Dispatcher // -- nameYourIdentDispatcher->addListener(, , &myClass::myMethod); // ident dispatcher// // // you can add the same method/instance to different dispatchers oder differnt ident-distinguished dispatchers in a identdispatcher. // you can also add the same method/instance to the same dispatchers all over again, which is not recommended // // // *firing a dispatcher // // -- nameYourDispatcher->fire(Type_A Object); // simple Dispatcher // -- nameYourIdentDispatcher->fire(, Type_A Object); // ident dispatcher// // // All respective attached callbacks are called in the order they were added // // // *unsubscribing // // -- nameYourDispatcher->removeListener(, &myClass::myMethod); // simple Dispatcher // -- nameYourIdentDispatcher->removeListener(, , &myClass::myMethod); // ident dispatcher// // // just the reverse of addListener. currently no removeAll() available // // // /***************************************************************************************************/ class CallbackHandle { }; template class CallbackBase : public CallbackHandle { public: virtual void fire(U u) {}; private: }; template class Callback : public CallbackBase { public: virtual void fire(U u) { if (cbVU) (callee->*cbVU)(u); }; typedef void (T::*callbackVU)(U); Callback(T* who, callbackVU cb) { cbVU = cb; callee = who; }; T* getCallee() { return callee; }; callbackVU getCBVU() { return cbVU; }; private: callbackVU cbVU; T* callee; }; template class EventDispatcher { public: template void addListener(T *who, void (T :: *func)(U)) { Callback *tmp = new Callback(who, func); _listener.push_back(dynamic_cast*>(tmp)); }; void fire(U u) { for (typename std::list*>::iterator it = _listener.begin(); it != _listener.end(); it++) { if (*it) { (*it)->fire(u); } } }; template void removeListener(T* who, void (T :: *func)(U)) { if (_listener.size()) { for (typename std::list*>::iterator it = _listener.begin(); it != _listener.end(); it++) { CallbackBase* pro = (*it); Callback *probe = dynamic_cast*>(pro); if (probe) { if (probe->getCallee() == who && probe->getCBVU() == func ) { delete (probe); _listener.remove((*it)); return; } } } } }; private: std::list*> _listener; }; template class EventIdentDispatcher { public: template void addListener(QString ident, T* who, void (T :: *func)(U)) { Callback* tmp = new Callback(who, func); _listener.push_back(std::pair*>(ident, dynamic_cast*>(tmp))); }; void fire(QString ident, U u) { for ( typename std::list* > >::iterator it = _listener.begin(); it != _listener.end(); it++) { if ((*it).first.compare(ident) == 0 || QString("*").compare((*it).first) == 0) { if ((*it).second) { (*it).second->fire(u); } } } }; template void removeListener(QString ident, T* who, void (T :: *func)(U)) { if (_listener.size()) { for (std::list >::iterator it = _listener.begin(); it != _listener.end(); it++) { if ((*it).first.compare(ident) == 0) { CallbackBase* pro = (*it).second; Callback *probe = dynamic_cast*>(pro); if (probe) { if (probe->getCallee() == who && probe->getVoidCB == func) { delete (*it).second; _listener.remove((*it)); return; } } } } } }; private: std::list* > > _listener; }; #endif