klayout/src/tl/tlEventsVar.h

337 lines
9.8 KiB
C++

/*
KLayout Layout Viewer
Copyright (C) 2006-2017 Matthias Koefferlein
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 2 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, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
// Included by tlEvents for variable template arguments
#undef _JOIN
#if _COUNT == 0
# define _JOIN(A,B) A
#else
# define _JOIN(A,B) A,B
#endif
template <_TMPLARGS>
class event_function_base<_TMPLARGLISTP>
: public tl::Object
{
public:
event_function_base () : tl::Object () { }
virtual ~event_function_base () { }
virtual void call (_JOIN(tl::Object *object, _CALLARGLIST)) = 0;
virtual bool equals (const event_function_base<_TMPLARGLISTP> &other) = 0;
};
template <_JOIN(class T, _TMPLARGS)>
class event_function<T, _TMPLARGLISTP>
: public event_function_base<_TMPLARGLIST>
{
public:
event_function (void (T::*m) (_TMPLARGLIST))
: m_m (m)
{
// .. nothing yet ..
}
virtual void call (_JOIN(tl::Object *object, _CALLARGLIST))
{
T *t = dynamic_cast<T *> (object);
if (t) {
(t->*m_m) (_CALLARGS);
}
}
virtual bool equals (const event_function_base<_TMPLARGLISTP> &other)
{
const event_function<_JOIN(T, _TMPLARGLIST)> *o = dynamic_cast<const event_function<_JOIN(T, _TMPLARGLIST)> *> (&other);
return o && o->m_m == m_m;
}
private:
void (T::*m_m) (_TMPLARGLIST);
};
template <class T, _JOIN(class D, _TMPLARGS)>
class event_function_with_data<T, D, _TMPLARGLISTP>
: public event_function_base<_TMPLARGLIST>
{
public:
event_function_with_data (void (T::*m) (_JOIN(D, _TMPLARGLIST)), D d)
: m_m (m), m_d (d)
{
// .. nothing yet ..
}
virtual void call (_JOIN(tl::Object *object, _CALLARGLIST))
{
T *t = dynamic_cast<T *> (object);
if (t) {
(t->*m_m) (_JOIN(m_d, _CALLARGS));
}
}
virtual bool equals (const event_function_base<_TMPLARGLISTP> &other)
{
const event_function_with_data<T, _JOIN(D, _TMPLARGLIST)> *o = dynamic_cast<const event_function_with_data<T, _JOIN(D, _TMPLARGLIST)> *> (&other);
return o && o->m_m == m_m && o->m_d == m_d;
}
private:
void (T::*m_m) (_JOIN(D, _TMPLARGLIST));
D m_d;
};
template <_JOIN(class T, _TMPLARGS)>
class generic_event_function<T, _TMPLARGLISTP>
: public event_function_base<_TMPLARGLIST>
{
public:
generic_event_function (void (T::*m) (int, void **))
: m_m (m)
{
// .. nothing yet ..
}
virtual void call (_JOIN(tl::Object *object, _CALLARGLIST))
{
T *t = dynamic_cast<T *> (object);
if (t) {
void *(argv[]) = { _CALLARGPTRS };
(t->*m_m) (_COUNT, &(argv[0]));
}
}
virtual bool equals (const event_function_base<_TMPLARGLISTP> &other)
{
const generic_event_function<_JOIN(T, _TMPLARGLIST)> *o = dynamic_cast<const generic_event_function<_JOIN(T, _TMPLARGLIST)> *> (&other);
return o && o->m_m == m_m;
}
private:
void (T::*m_m) (int, void **);
};
template <class T, _JOIN(class D, _TMPLARGS)>
class generic_event_function_with_data<T, D, _TMPLARGLISTP>
: public event_function_base<_TMPLARGLIST>
{
public:
generic_event_function_with_data (void (T::*m) (D, int, void **), D d)
: m_m (m), m_d (d)
{
// .. nothing yet ..
}
virtual void call (_JOIN(tl::Object *object, _CALLARGLIST))
{
T *t = dynamic_cast<T *> (object);
if (t) {
void *(argv[]) = { _CALLARGPTRS };
(t->*m_m) (m_d, _COUNT, &(argv[0]));
}
}
virtual bool equals (const event_function_base<_TMPLARGLISTP> &other)
{
const generic_event_function_with_data<T, _JOIN(D, _TMPLARGLIST)> *o = dynamic_cast<const generic_event_function_with_data<T, _JOIN(D, _TMPLARGLIST)> *> (&other);
return o && o->m_m == m_m && o->m_d == m_d;
}
private:
void (T::*m_m) (D, int, void **);
D m_d;
};
template <_TMPLARGS>
class event<_TMPLARGLISTP>
{
public:
typedef event_function_base<_TMPLARGLISTP> func;
typedef std::vector<std::pair<tl::weak_ptr<tl::Object>, tl::shared_ptr<func> > > receivers;
#if _COUNT == 0
// NOTE: for gcc 4.4.7 (and may others), event is not a template in this case and
// typename must not be given.
typedef receivers::iterator receivers_iterator;
#else
typedef typename receivers::iterator receivers_iterator;
#endif
void operator() (_CALLARGLIST)
{
// Issue the events. Because inside the call, other receivers might be added, we make a copy
// first. This way added events won't be called now.
receivers tmp_receivers = m_receivers;
for (receivers_iterator r = tmp_receivers.begin (); r != tmp_receivers.end (); ++r) {
if (r->first.get ()) {
try {
r->second->call (_JOIN(r->first.get (), _CALLARGS));
} catch (tl::Exception &ex) {
handle_event_exception (ex);
} catch (std::exception &ex) {
handle_event_exception (ex);
} catch (...) {
// Unknown exceptions are ignored
}
}
}
// Clean up expired entries afterwards (the call may have expired them)
receivers_iterator w = m_receivers.begin ();
for (receivers_iterator r = m_receivers.begin (); r != m_receivers.end (); ++r) {
if (r->first.get ()) {
if (w != r) {
*w = *r;
}
++w;
}
}
if (w != m_receivers.end ()) {
m_receivers.erase (w, m_receivers.end ());
}
}
void clear ()
{
m_receivers.clear ();
}
template <class T>
T *find_receiver ()
{
for (receivers_iterator r = m_receivers.begin (); r != m_receivers.end (); ++r) {
T *t = dynamic_cast<T *> (r->first.get ());
if (t) {
return t;
}
}
return 0;
}
template <class T>
void add (T *obj, void (T::*m) (_TMPLARGLIST))
{
event_function<T, _TMPLARGLISTP> f (m);
for (receivers_iterator r = m_receivers.begin (); r != m_receivers.end (); ++r) {
if (r->first.get () == obj && r->second->equals (f)) {
// this receiver is already registered
return;
}
}
m_receivers.push_back (typename receivers::value_type (tl::weak_ptr<tl::Object> (obj, true /*is an event*/), new event_function<T, _TMPLARGLISTP> (f)));
}
template <class T>
void remove (T *obj, void (T::*m) (_TMPLARGLIST))
{
event_function<T, _TMPLARGLISTP> f (m);
for (receivers_iterator r = m_receivers.begin (); r != m_receivers.end (); ++r) {
if (r->first.get () == obj && r->second->equals (f)) {
// this receiver is already registered
m_receivers.erase (r);
return;
}
}
}
template <class T, class D>
void add (T *obj, void (T::*m) (_JOIN(D, _TMPLARGLIST)), D d)
{
event_function_with_data<T, D, _TMPLARGLISTP> f (m, d);
for (receivers_iterator r = m_receivers.begin (); r != m_receivers.end (); ++r) {
if (r->first.get () == obj && r->second->equals (f)) {
// this receiver is already registered
return;
}
}
m_receivers.push_back (typename receivers::value_type (tl::weak_ptr<tl::Object> (obj, true /*is an event*/), new event_function_with_data<T, D, _TMPLARGLISTP> (f)));
}
template <class T, class D>
void remove (T *obj, void (T::*m) (_JOIN(D, _TMPLARGLIST)), D d)
{
event_function_with_data<T, _JOIN(D, _TMPLARGLIST)> f (m, d);
for (receivers_iterator r = m_receivers.begin (); r != m_receivers.end (); ++r) {
if (r->first.get () == obj && r->second->equals (f)) {
// this receiver is already registered
m_receivers.erase (r);
return;
}
}
}
template <class T>
void add (T *obj, void (T::*m) (int, void **))
{
generic_event_function<T, _TMPLARGLISTP> f (m);
for (receivers_iterator r = m_receivers.begin (); r != m_receivers.end (); ++r) {
if (r->first.get () == obj && r->second->equals (f)) {
// this receiver is already registered
return;
}
}
m_receivers.push_back (typename receivers::value_type (tl::weak_ptr<tl::Object> (obj, true /*is an event*/), new generic_event_function<T, _TMPLARGLISTP> (f)));
}
template <class T>
void remove (T *obj, void (T::*m) (int, void **))
{
generic_event_function<T, _TMPLARGLISTP> f (m);
for (receivers_iterator r = m_receivers.begin (); r != m_receivers.end (); ++r) {
if (r->first.get () == obj && r->second->equals (f)) {
// this receiver is already registered
m_receivers.erase (r);
return;
}
}
}
template <class T, class D>
void add (T *obj, void (T::*m) (D, int, void **), D d)
{
generic_event_function_with_data<T, _JOIN(D, _TMPLARGLIST)> f (m, d);
for (receivers_iterator r = m_receivers.begin (); r != m_receivers.end (); ++r) {
if (r->first.get () == obj && r->second->equals (f)) {
// this receiver is already registered
return;
}
}
m_receivers.push_back (typename receivers::value_type (tl::weak_ptr<tl::Object> (obj, true /*is an event*/), new generic_event_function_with_data<T, D, _TMPLARGLISTP> (f)));
}
template <class T, class D>
void remove (T *obj, void (T::*m) (D, int, void **), D d)
{
generic_event_function_with_data<T, _JOIN(D, _TMPLARGLIST)> f (m, d);
for (receivers_iterator r = m_receivers.begin (); r != m_receivers.end (); ++r) {
if (r->first.get () == obj && r->second->equals (f)) {
// this receiver is already registered
m_receivers.erase (r);
return;
}
}
}
private:
receivers m_receivers;
};