This allow compile check event for CONNECT and use EVENT as CONNECT target, also raise event now is simple execute EVENT function.
301 lines
16 KiB
C++
301 lines
16 KiB
C++
/*
|
|
PIP - Platform Independent Primitives
|
|
Object, base class of some PIP classes, provide EVENT -> EVENT_HANDLER mechanism
|
|
Copyright (C) 2013 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 <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#ifndef PIOBJECT_H
|
|
#define PIOBJECT_H
|
|
|
|
#include "pistring.h"
|
|
|
|
/// declare event handler \"event\" inside class \"obj\" with name \"name\", ret name()
|
|
#define EVENT_HANDLER0(obj, ret, name) static ret __stat_eh_##name##__(void * o) {return ((obj*)o)->name();} ret name()
|
|
#define EVENT_HANDLER1(obj, ret, name, a0, n0) static ret __stat_eh_##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_eh_##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_eh_##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_eh_##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
|
|
|
|
/// declare virtual event handler \"event\" inside class \"obj\" with name \"name\", virtual ret name()
|
|
#define EVENT_VHANDLER0(obj, ret, name) static ret __stat_eh_##name##__(void * o) {return ((obj*)o)->name();} virtual ret name()
|
|
#define EVENT_VHANDLER1(obj, ret, name, a0, n0) static ret __stat_eh_##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_eh_##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_eh_##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_eh_##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
|
|
|
|
/// declare event \"event\" inside class \"obj\" with name \"name\", void name();
|
|
#define EVENT0(obj, name) EVENT_HANDLER0(obj, void, name) {PIObject::raiseEvent(this, #name);}
|
|
#define EVENT1(obj, name, a0, n0) EVENT_HANDLER1(obj, void, name, a0, n0) {PIObject::raiseEvent(this, #name, n0);}
|
|
#define EVENT2(obj, name, a0, n0, a1, n1) EVENT_HANDLER2(obj, void, name, a0, n0, a1, n1) {PIObject::raiseEvent(this, #name, n0, n1);}
|
|
#define EVENT3(obj, name, a0, n0, a1, n1, a2, n2) EVENT_HANDLER3(obj, void, name, a0, n0, a1, n1, a2, n2) {PIObject::raiseEvent(this, #name, n0, n1, n2);}
|
|
#define EVENT4(obj, name, a0, n0, a1, n1, a2, n2, a3, n3) EVENT_HANDLER4(obj, void, name, a0, n0, a1, n1, a2, n2, a3, n3) {PIObject::raiseEvent(this, #name, n0, n1, n2, n3);}
|
|
#define EVENT EVENT0
|
|
|
|
/// raise event \"event\" from object \"src\"
|
|
#define RAISE_EVENT0(src, event) (src)->event();
|
|
#define RAISE_EVENT1(src, event, v0) (src)->event(v0);
|
|
#define RAISE_EVENT2(src, event, v0, v1) (src)->event(v0, v1);
|
|
#define RAISE_EVENT3(src, event, v0, v1, v2) (src)->event(v0, v1, v2);
|
|
#define RAISE_EVENT4(src, event, v0, v1, v2, v3) (src)->event(v0, v1, v2, v3);
|
|
#define RAISE_EVENT RAISE_EVENT0
|
|
|
|
/// connect event \"event\" from object \"src\" to event handler \"handler\" from object \"dst\" with check of event and handler exists
|
|
#define CONNECT0(ret, src, event, dst, handler) PIObject::piConnect(src, #event, dst, (void*)(ret(*)(void*))(&(dst)->__stat_eh_##handler##__), (void*)(void(*)(void*))(&(src)->__stat_eh_##event##__));
|
|
#define CONNECT1(ret, a0, src, event, dst, handler) PIObject::piConnect(src, #event, dst, (void*)(ret(*)(void*, a0))(&(dst)->__stat_eh_##handler##__), (void*)(void(*)(void*, a0))(&(src)->__stat_eh_##event##__));
|
|
#define CONNECT2(ret, a0, a1, src, event, dst, handler) PIObject::piConnect(src, #event, dst, (void*)(ret(*)(void*, a0, a1))(&(dst)->__stat_eh_##handler##__), (void*)(void(*)(void*, a0, a1))(&(src)->__stat_eh_##event##__));
|
|
#define CONNECT3(ret, a0, a1, a2, src, event, dst, handler) PIObject::piConnect(src, #event, dst, (void*)(ret(*)(void*, a0, a1, a2))(&(dst)->__stat_eh_##handler##__), (void*)(void(*)(void*, a0, a1, a2))(&(src)->__stat_eh_##event##__));
|
|
#define CONNECT4(ret, a0, a1, a2, a3, src, event, dst, handler) PIObject::piConnect(src, #event, dst, (void*)(ret(*)(void*, a0, a1, a2, a3))(&(dst)->__stat_eh_##handler##__), (void*)(void(*)(void*, a0, a1, a2, a3))(&(src)->__stat_eh_##event##__));
|
|
#define CONNECT CONNECT0
|
|
|
|
/// connect event \"event\" from object \"src\" to event handler \"handler\" from object \"dst\" without check of event exists
|
|
#define WEAK_CONNECT0(ret, src, event, dst, handler) PIObject::piConnect(src, #event, dst, (void*)(ret(*)(void*))(&(dst)->__stat_eh_##handler##__));
|
|
#define WEAK_CONNECT1(ret, a0, src, event, dst, handler) PIObject::piConnect(src, #event, dst, (void*)(ret(*)(void*, a0))(&(dst)->__stat_eh_##handler##__));
|
|
#define WEAK_CONNECT2(ret, a0, a1, src, event, dst, handler) PIObject::piConnect(src, #event, dst, (void*)(ret(*)(void*, a0, a1))(&(dst)->__stat_eh_##handler##__));
|
|
#define WEAK_CONNECT3(ret, a0, a1, a2, src, event, dst, handler) PIObject::piConnect(src, #event, dst, (void*)(ret(*)(void*, a0, a1, a2))(&(dst)->__stat_eh_##handler##__));
|
|
#define WEAK_CONNECT4(ret, a0, a1, a2, a3, src, event, dst, handler) PIObject::piConnect(src, #event, dst, (void*)(ret(*)(void*, a0, a1, a2, a3))(&(dst)->__stat_eh_##handler##__));
|
|
#define WEAK_CONNECT WEAK_CONNECT0
|
|
|
|
/// piDisconnect event \"event\" from object \"src\" from event handler \"handler\" from object \"dst\"
|
|
#define DISCONNECT0(ret, src, event, dst, handler) PIObject::piDisconnect(src, #event, dst, (void*)(ret(*)(void*))(&(dst)->__stat_eh_##handler##__));
|
|
#define DISCONNECT1(ret, a0, src, event, dst, handler) PIObject::piDisconnect(src, #event, dst, (void*)(ret(*)(void*, a0))(&(dst)->__stat_eh_##handler##__));
|
|
#define DISCONNECT2(ret, a0, a1, src, event, dst, handler) PIObject::piDisconnect(src, #event, dst, (void*)(ret(*)(void*, a0, a1))(&(dst)->__stat_eh_##handler##__));
|
|
#define DISCONNECT3(ret, a0, a1, a2, src, event, dst, handler) PIObject::piDisconnect(src, #event, dst, (void*)(ret(*)(void*, a0, a1, a2))(&(dst)->__stat_eh_##handler##__));
|
|
#define DISCONNECT4(ret, a0, a1, a2, a3, src, event, dst, handler) PIObject::piDisconnect(src, #event, dst, (void*)(ret(*)(void*, a0, a1, a2, a3))(&(dst)->__stat_eh_##handler##__));
|
|
#define DISCONNECT DISCONNECT0
|
|
|
|
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 <typename T0>
|
|
void addEvent(const PIString & name) {
|
|
signals_.insert(NamedFunction(0, name, PIStringList(typeid(T0).name())), name);
|
|
}
|
|
template <typename T0, typename T1>
|
|
void addEvent(const PIString & name) {
|
|
signals_.insert(NamedFunction(0, name, PIStringList(typeid(T0).name(), typeid(T1).name())), name);
|
|
}
|
|
template <typename T0, typename T1, typename T2>
|
|
void addEvent(const PIString & name) {
|
|
signals_.insert(NamedFunction(0, name, PIStringList(typeid(T0).name(), typeid(T1).name(), typeid(T2).name())), name);
|
|
}
|
|
template <typename T0, typename T1, typename T2, typename T3>
|
|
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 <typename T0>
|
|
void addEventHandler(const PIString & name, void * func) {
|
|
slots_.insert(NamedFunction(func, name, PIStringList(typeid(T0).name())), name);
|
|
}
|
|
template <typename T0, typename T1>
|
|
void addEventHandler(const PIString & name, void * func) {
|
|
slots_.insert(NamedFunction(func, name, PIStringList(typeid(T0).name(), typeid(T1).name())), name);
|
|
}
|
|
template <typename T0, typename T1, typename T2>
|
|
void addEventHandler(const PIString & name, void * func) {
|
|
slots_.insert(NamedFunction(func, name, PIStringList(typeid(T0).name(), typeid(T1).name(), typeid(T2).name())), name);
|
|
}
|
|
template <typename T0, typename T1, typename T2, typename T3>
|
|
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 piConnect(PIObject * src, const PIString & sig, void * dest, void * ev_h) {src->connections << Connection(ev_h, 0, sig, dest);}
|
|
static void piConnect(PIObject * src, const PIString & sig, void * dest, void * ev_h, void * e_h) {src->connections << Connection(ev_h, e_h, sig, dest);}
|
|
static void piDisconnect(PIObject * src, const PIString & sig, void * dest, void * ev_h) {
|
|
for (int i = 0; i < src->connections.size_s(); ++i) {
|
|
Connection & cc(src->connections[i]);
|
|
if (cc.event == sig && cc.dest == dest && cc.slot == ev_h) {
|
|
src->connections.remove(i);
|
|
i--;
|
|
}
|
|
}
|
|
}
|
|
//static void piConnect(PIObject & src, const PIString & sig, PIObject * dest, void * ev_h) {src.connections << Connection(ev_h, sig, dest);}
|
|
//static void piConnect(PIObject * src, const PIString & sig, PIObject & dest, void * ev_h) {src->connections << Connection(ev_h, sig, &dest);}
|
|
//static void piConnect(PIObject & src, const PIString & sig, PIObject & dest, void * ev_h) {src.connections << Connection(ev_h, sig, &dest);}
|
|
|
|
/*/// Connect through manager
|
|
static bool piConnect(const PIString & srcObject, const PIString & event, const PIString & destObject, const PIString & handler, bool force = false) {
|
|
PIObject * src = findByName(srcObject);
|
|
if (src == 0) {
|
|
cout << "PIObject::piConnect: can`t find PIObject with \"" << srcObject << "\" name!" << endl;
|
|
return false;
|
|
}
|
|
PIObject * dest = findByName(destObject);
|
|
if (dest == 0) {
|
|
cout << "PIObject::piConnect: can`t find PIObject with \"" << destObject << "\" name!" << endl;
|
|
return false;
|
|
}
|
|
return PIObject::piConnect(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 <typename T0>
|
|
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 <typename T0, typename T1>
|
|
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 <typename T0, typename T1, typename T2>
|
|
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 <typename T0, typename T1, typename T2, typename T3>
|
|
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 <typename T0>
|
|
static void raiseEvent(PIObject * destObject, const PIString & name, const T0 & v0 = T0()) {
|
|
destObject->raiseEvent<T0>(name, v0);
|
|
}
|
|
template <typename T0, typename T1>
|
|
static void raiseEvent(PIObject * destObject, const PIString & name, const T0 & v0 = T0(), const T1 & v1 = T1()) {
|
|
destObject->raiseEvent<T0, T1>(name, v0, v1);
|
|
}
|
|
template <typename T0, typename T1, typename T2>
|
|
static void raiseEvent(PIObject * destObject, const PIString & name, const T0 & v0 = T0(), const T1 & v1 = T1(), const T2 & v2 = T2()) {
|
|
destObject->raiseEvent<T0, T1, T2>(name, v0, v1, v2);
|
|
}
|
|
template <typename T0, typename T1, typename T2, typename T3>
|
|
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<T0, T1, T2, T3>(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::piConnect: can`t find PIObject with \"" << destObject << "\" name!" << endl;
|
|
return;
|
|
}
|
|
raiseEvent(dest, name);
|
|
}
|
|
template <typename T0>
|
|
static void raiseEvent(const PIString & destObject, const PIString & name, const T0 & v0 = T0()) {
|
|
PIObject * dest = findByName(destObject);
|
|
if (dest == 0) {
|
|
cout << "PIObject::piConnect: can`t find PIObject with \"" << destObject << "\" name!" << endl;
|
|
return;
|
|
}
|
|
raiseEvent<T0>(dest, name, v0);
|
|
}
|
|
template <typename T0, typename T1>
|
|
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::piConnect: can`t find PIObject with \"" << destObject << "\" name!" << endl;
|
|
return;
|
|
}
|
|
raiseEvent<T0, T1>(dest, name, v0, v1);
|
|
}
|
|
template <typename T0, typename T1, typename T2>
|
|
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::piConnect: can`t find PIObject with \"" << destObject << "\" name!" << endl;
|
|
return;
|
|
}
|
|
raiseEvent<T0, T1, T2>(name, dest, v0, v1, v2);
|
|
}
|
|
template <typename T0, typename T1, typename T2, typename T3>
|
|
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::piConnect: can`t find PIObject with \"" << destObject << "\" name!" << endl;
|
|
return;
|
|
}
|
|
raiseEvent<T0, T1, T2, T3>(name,dest , v0, v1, v2, v3);
|
|
}
|
|
|
|
protected:
|
|
PIString name_;
|
|
|
|
private:
|
|
struct Connection {
|
|
Connection(void * sl = 0, void * si = 0, const PIString & e = PIString(), void * o = 0) {slot = sl; signal = si; event = e; dest = o;}
|
|
void * slot;
|
|
void * signal;
|
|
PIString event;
|
|
void * dest;
|
|
};
|
|
|
|
PIVector<Connection> connections;
|
|
|
|
static PIVector<PIObject * > objects;
|
|
static PIObject * findByName(const PIString & name) {
|
|
piForeach (PIObject * i, PIObject::objects) {
|
|
if (i->name_ != name) continue;
|
|
return i;
|
|
}
|
|
return 0;
|
|
};
|
|
|
|
};
|
|
|
|
#endif // PIOBJECT_H
|