/* PIP - Platform Independent Primitives Object, base class of some PIP classes, provide EVENT -> EVENT_HANDLER mechanism Copyright (C) 2012 Ivan Pelipenko peri4ko@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef PIOBJECT_H #define PIOBJECT_H #include "pistring.h" //#ifdef CC_VC //#define HANDLER(c,s) #s,PIObject::handlerPtr((void(c::*)())&c::s) //#else //#define HANDLER(c,s) #s,(void*)&c::s //#endif //#define EVENT_HANDLER0(obj, name) static void __stat_##name##__(obj * o) {o->name();} void name() //#define EVENT_HANDLER1(obj, name, a0, n0) static void __stat_##name##__(obj * o, a0 n0) {o->name(n0);} void name(a0 n0) //#define EVENT_HANDLER2(obj, name, a0, n0, a1, n1) static void __stat_##name##__(obj * o, a0 n0, a1 n1) {o->name(n0, n1);} void name(a0 n0, a1 n1) #define EVENT_HANDLER0(obj, ret, name) static ret __stat_##name##__(void * o) {return ((obj*)o)->name();} ret name() #define EVENT_HANDLER1(obj, ret, name, a0, n0) static ret __stat_##name##__(void * o, a0 n0) {return ((obj*)o)->name(n0);} ret name(a0 n0) #define EVENT_HANDLER2(obj, ret, name, a0, n0, a1, n1) static ret __stat_##name##__(void * o, a0 n0, a1 n1) {return ((obj*)o)->name(n0, n1);} ret name(a0 n0, a1 n1) #define EVENT_HANDLER3(obj, ret, name, a0, n0, a1, n1, a2, n2) static ret __stat_##name##__(void * o, a0 n0, a1 n1, a2 n2) {return ((obj*)o)->name(n0, n1, n2);} ret name(a0 n0, a1 n1, a2 n2) #define EVENT_HANDLER4(obj, ret, name, a0, n0, a1, n1, a2, n2, a3, n3) static ret __stat_##name##__(void * o, a0 n0, a1 n1, a2 n2, a3 n3) {return ((obj*)o)->name(n0, n1, n2, n3);} ret name(a0 n0, a1 n1, a2 n2, a3 n3) #define EVENT_HANDLER EVENT_HANDLER0 #define EVENT_VHANDLER0(obj, ret, name) static ret __stat_##name##__(void * o) {return ((obj*)o)->name();} virtual ret name() #define EVENT_VHANDLER1(obj, ret, name, a0, n0) static ret __stat_##name##__(void * o, a0 n0) {return ((obj*)o)->name(n0);} virtual ret name(a0 n0) #define EVENT_VHANDLER2(obj, ret, name, a0, n0, a1, n1) static ret __stat_##name##__(void * o, a0 n0, a1 n1) {return ((obj*)o)->name(n0, n1);} virtual ret name(a0 n0, a1 n1) #define EVENT_VHANDLER3(obj, ret, name, a0, n0, a1, n1, a2, n2) static ret __stat_##name##__(void * o, a0 n0, a1 n1, a2 n2) {return ((obj*)o)->name(n0, n1, n2);} virtual ret name(a0 n0, a1 n1, a2 n2) #define EVENT_VHANDLER4(obj, ret, name, a0, n0, a1, n1, a2, n2, a3, n3) static ret __stat_##name##__(void * o, a0 n0, a1 n1, a2 n2, a3 n3) {return ((obj*)o)->name(n0, n1, n2, n3);} virtual ret name(a0 n0, a1 n1, a2 n2, a3 n3) #define EVENT_VHANDLER EVENT_VHANDLER0 #define CONNECT0(ret, src, event, dst, handler) PIObject::connect(src, #event, dst, (void*)(ret(*)(void*))(&(dst)->__stat_##handler##__)); #define CONNECT1(ret, a0, src, event, dst, handler) PIObject::connect(src, #event, dst, (void*)(ret(*)(void*, a0))(&(dst)->__stat_##handler##__)); #define CONNECT2(ret, a0, a1, src, event, dst, handler) PIObject::connect(src, #event, dst, (void*)(ret(*)(void*, a0, a1))(&(dst)->__stat_##handler##__)); #define CONNECT3(ret, a0, a1, a2, src, event, dst, handler) PIObject::connect(src, #event, dst, (void*)(ret(*)(void*, a0, a1, a2))(&(dst)->__stat_##handler##__)); #define CONNECT4(ret, a0, a1, a2, a3, src, event, dst, handler) PIObject::connect(src, #event, dst, (void*)(ret(*)(void*, a0, a1, a2, a3))(&(dst)->__stat_##handler##__)); #define CONNECT CONNECT0 class PIObject { friend class PIObjectManager; public: PIObject(const PIString & name = PIString()) {piMonitor.objects++; setName(name); objects << this;} ~PIObject() {piMonitor.objects--; objects.removeAll(this);} const PIString & name() const {return name_;} void setName(const PIString & name) {name_ = name;} /* PIStringList events(); PIStringList eventHandlers(); /// Events void addEvent(const PIString & name) { signals_.insert(NamedFunction(0, name, PIStringList()), name); } template void addEvent(const PIString & name) { signals_.insert(NamedFunction(0, name, PIStringList(typeid(T0).name())), name); } template void addEvent(const PIString & name) { signals_.insert(NamedFunction(0, name, PIStringList(typeid(T0).name(), typeid(T1).name())), name); } template void addEvent(const PIString & name) { signals_.insert(NamedFunction(0, name, PIStringList(typeid(T0).name(), typeid(T1).name(), typeid(T2).name())), name); } template void addEvent(const PIString & name) { signals_.insert(NamedFunction(0, name, PIStringList(typeid(T0).name(), typeid(T1).name(), typeid(T2).name(), typeid(T3).name())), name); } /// Event handlers void addEventHandler(const PIString & name, void * func) { slots_.insert(NamedFunction(func, name, PIStringList()), name); } template void addEventHandler(const PIString & name, void * func) { slots_.insert(NamedFunction(func, name, PIStringList(typeid(T0).name())), name); } template void addEventHandler(const PIString & name, void * func) { slots_.insert(NamedFunction(func, name, PIStringList(typeid(T0).name(), typeid(T1).name())), name); } template void addEventHandler(const PIString & name, void * func) { slots_.insert(NamedFunction(func, name, PIStringList(typeid(T0).name(), typeid(T1).name(), typeid(T2).name())), name); } template void addEventHandler(const PIString & name, void * func) { slots_.insert(NamedFunction(func, name, PIStringList(typeid(T0).name(), typeid(T1).name(), typeid(T2).name(), typeid(T3).name())), name); } */ /// Direct connect static void connect(PIObject * src, const PIString & sig, void * dest, void * ev_h) {src->connections << Connection(ev_h, sig, dest);} //static void connect(PIObject & src, const PIString & sig, PIObject * dest, void * ev_h) {src.connections << Connection(ev_h, sig, dest);} //static void connect(PIObject * src, const PIString & sig, PIObject & dest, void * ev_h) {src->connections << Connection(ev_h, sig, &dest);} //static void connect(PIObject & src, const PIString & sig, PIObject & dest, void * ev_h) {src.connections << Connection(ev_h, sig, &dest);} /*/// Connect through manager static bool connect(const PIString & srcObject, const PIString & event, const PIString & destObject, const PIString & handler, bool force = false) { PIObject * src = findByName(srcObject); if (src == 0) { cout << "PIObject::connect: can`t find PIObject with \"" << srcObject << "\" name!" << endl; return false; } PIObject * dest = findByName(destObject); if (dest == 0) { cout << "PIObject::connect: can`t find PIObject with \"" << destObject << "\" name!" << endl; return false; } return PIObject::connect(src, event, dest, handler, force); }*/ /// Raise events static void raiseEvent(PIObject * sender, const PIString & event) { for (int j = 0; j < sender->connections.size_s(); ++j) { Connection & i(sender->connections[j]); if (i.event != event) continue; ((void(*)(void * ))i.slot)(i.dest); } } template static void raiseEvent(PIObject * sender, const PIString & event, const T0 & v0 = T0()) { for (int j = 0; j < sender->connections.size_s(); ++j) { Connection & i(sender->connections[j]); if (i.event != event) continue; ((void(*)(void * , T0))i.slot)(i.dest, v0); } } template static void raiseEvent(PIObject * sender, const PIString & event, const T0 & v0 = T0(), const T1 & v1 = T1()) { for (int j = 0; j < sender->connections.size_s(); ++j) { Connection & i(sender->connections[j]); if (i.event != event) continue; ((void(*)(void * , T0, T1))i.slot)(i.dest, v0, v1); } } template static void raiseEvent(PIObject * sender, const PIString & event, const T0 & v0 = T0(), const T1 & v1 = T1(), const T2 & v2 = T2()) { for (int j = 0; j < sender->connections.size_s(); ++j) { Connection & i(sender->connections[j]); if (i.event != event) continue; ((void(*)(void * , T0, T1, T2))i.slot)(i.dest, v0, v1, v2); } } template static void raiseEvent(PIObject * sender, const PIString & event, const T0 & v0 = T0(), const T1 & v1 = T1(), const T2 & v2 = T2(), const T3 & v3 = T3()) { for (int j = 0; j < sender->connections.size_s(); ++j) { Connection & i(sender->connections[j]); if (i.event != event) continue; ((void(*)(void * , T0, T1, T2, T3))i.slot)(i.dest, v0, v1, v2, v3); } } /* /// Raise events (static) static void raiseEvent(PIObject * destObject, const PIString & name) { destObject->raiseEvent(name); } template static void raiseEvent(PIObject * destObject, const PIString & name, const T0 & v0 = T0()) { destObject->raiseEvent(name, v0); } template static void raiseEvent(PIObject * destObject, const PIString & name, const T0 & v0 = T0(), const T1 & v1 = T1()) { destObject->raiseEvent(name, v0, v1); } template static void raiseEvent(PIObject * destObject, const PIString & name, const T0 & v0 = T0(), const T1 & v1 = T1(), const T2 & v2 = T2()) { destObject->raiseEvent(name, v0, v1, v2); } template static void raiseEvent(PIObject * destObject, const PIString & name, const T0 & v0 = T0(), const T1 & v1 = T1(), const T2 & v2 = T2(), const T3 & v3 = T3()) { destObject->raiseEvent(name, v0, v1, v2, v3); } */ /// Raise events through manager static void raiseEvent(const PIString & destObject, const PIString & name) { PIObject * dest = findByName(destObject); if (dest == 0) { cout << "PIObject::connect: can`t find PIObject with \"" << destObject << "\" name!" << endl; return; } raiseEvent(dest, name); } template static void raiseEvent(const PIString & destObject, const PIString & name, const T0 & v0 = T0()) { PIObject * dest = findByName(destObject); if (dest == 0) { cout << "PIObject::connect: can`t find PIObject with \"" << destObject << "\" name!" << endl; return; } raiseEvent(dest, name, v0); } template static void raiseEvent(const PIString & destObject, const PIString & name, const T0 & v0 = T0(), const T1 & v1 = T1()) { PIObject * dest = findByName(destObject); if (dest == 0) { cout << "PIObject::connect: can`t find PIObject with \"" << destObject << "\" name!" << endl; return; } raiseEvent(dest, name, v0, v1); } template static void raiseEvent(const PIString & destObject, const PIString & name, const T0 & v0 = T0(), const T1 & v1 = T1(), const T2 & v2 = T2()) { PIObject * dest = findByName(destObject); if (dest == 0) { cout << "PIObject::connect: can`t find PIObject with \"" << destObject << "\" name!" << endl; return; } raiseEvent(name, dest, v0, v1, v2); } template static void raiseEvent(const PIString & destObject, const PIString & name, const T0 & v0 = T0(), const T1 & v1 = T1(), const T2 & v2 = T2(), const T3 & v3 = T3()) { PIObject * dest = findByName(destObject); if (dest == 0) { cout << "PIObject::connect: can`t find PIObject with \"" << destObject << "\" name!" << endl; return; } raiseEvent(name,dest , v0, v1, v2, v3); } private: struct Connection { Connection(void * s = 0, const PIString & e = PIString(), void * o = 0) {slot = s; event = e; dest = o;} void * slot; PIString event; void * dest; }; PIString name_; PIVector connections; static PIVector objects; static PIObject * findByName(const PIString & name) { piForeach (PIObject * i, PIObject::objects) { if (i->name_ != name) continue; return i; } return 0; }; }; #endif // PIOBJECT_H