Files
pip/piobject.h
2011-12-29 12:25:17 +03:00

256 lines
12 KiB
C++

/*
PIP - Platform Independent Primitives
Object, base class of some PIP classes, provide EVENT -> EVENT_HANDLER mechanism
Copyright (C) 2011 Ivan Pelipenko peri4@rambler.ru
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"
//#ifdef CC_VC
//#define HANDLER(c,s) #s,PIObject::handlerPtr<c>((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 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.remove(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 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 <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::connect: 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::connect: 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::connect: 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::connect: 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::connect: can`t find PIObject with \"" << destObject << "\" name!" << endl;
return;
}
raiseEvent<T0, T1, T2, T3>(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<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