/*
sigslot.h
Copyright (C) 2007 Acekard, www.acekard.com
Copyright (C) 2007-2009 somebody
Copyright (C) 2009 yellow wood goblin
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 .
*/
// __________________________________________________________________________________________________
// The original version of this code was written and placed in the public domain by Sarah Thompson
// See http://sigslot.sourceforge.net/
// __________________________________________________________________________________________________
#ifndef SIGSLOT__H
#define SIGSLOT__H
#include
#include
namespace akui {
class SlotHolder;
class BasicConnection0
{
public:
virtual ~BasicConnection0() {}
virtual SlotHolder* targetSlotHolder() const = 0;
virtual void emit() = 0;
virtual BasicConnection0* clone() = 0;
virtual BasicConnection0* duplicate(SlotHolder* newTarget) = 0;
};
template
class BasicConnection1
{
public:
virtual ~BasicConnection1() {}
virtual SlotHolder* targetSlotHolder() const = 0;
virtual void emit(Type1) = 0;
virtual BasicConnection1* clone() = 0;
virtual BasicConnection1* duplicate(SlotHolder* newTarget) = 0;
};
class BasicSignal
{
public:
virtual ~BasicSignal() {}
virtual void disconnectSlot(SlotHolder* slot) = 0;
virtual void duplicateSlot(const SlotHolder* oldSlot, SlotHolder* newSlot) = 0;
};
class SlotHolder
{
private:
typedef std::set SenderSet;
typedef SenderSet::const_iterator const_iterator;
public:
SlotHolder() {}
SlotHolder(const SlotHolder& holder)
{
const_iterator it = holder.senders_.begin();
const_iterator itEnd = holder.senders_.end();
while(it != itEnd)
{
(*it)->duplicateSlot(&holder, this);
senders_.insert(*it);
++it;
}
}
void connectTo(BasicSignal* sender)
{
senders_.insert(sender);
}
void disconnectFrom(BasicSignal* sender)
{
senders_.erase(sender);
}
virtual ~SlotHolder()
{
disconnectAll();
}
void disconnectAll()
{
const_iterator it = senders_.begin();
const_iterator itEnd = senders_.end();
while(it != itEnd)
{
(*it)->disconnectSlot(this);
++it;
}
senders_.erase(senders_.begin(), senders_.end());
}
protected:
SenderSet senders_;
};
class BasicSignal0 : public BasicSignal
{
public:
typedef std::list ConnectionList;
BasicSignal0() {}
BasicSignal0(const BasicSignal0& s) : BasicSignal(s)
{
ConnectionList::const_iterator it = s.connectedSlots_.begin();
ConnectionList::const_iterator itEnd = s.connectedSlots_.end();
while(it != itEnd)
{
(*it)->targetSlotHolder()->connectTo(this);
connectedSlots_.push_back((*it)->clone());
++it;
}
}
~BasicSignal0()
{
disconnectAll();
}
void disconnectAll()
{
ConnectionList::const_iterator it = connectedSlots_.begin();
ConnectionList::const_iterator itEnd = connectedSlots_.end();
while(it != itEnd)
{
(*it)->targetSlotHolder()->disconnectFrom(this);
delete *it;
++it;
}
connectedSlots_.erase(connectedSlots_.begin(), connectedSlots_.end());
}
void disconnect(SlotHolder* slotHolder)
{
ConnectionList::iterator it = connectedSlots_.begin();
ConnectionList::iterator itEnd = connectedSlots_.end();
while(it != itEnd)
{
if((*it)->targetSlotHolder() == slotHolder)
{
delete *it;
connectedSlots_.erase(it);
slotHolder->disconnectFrom(this);
return;
}
++it;
}
}
void disconnectSlot(SlotHolder* slot)
{
ConnectionList::iterator it = connectedSlots_.begin();
ConnectionList::iterator itEnd = connectedSlots_.end();
while(it != itEnd)
{
ConnectionList::iterator itNext = it;
++itNext;
if((*it)->targetSlotHolder() == slot)
{
delete *it;
connectedSlots_.erase(it);
}
it = itNext;
}
}
void duplicateSlot(const SlotHolder* oldTarget, SlotHolder* newTarget)
{
ConnectionList::iterator it = connectedSlots_.begin();
ConnectionList::iterator itEnd = connectedSlots_.end();
while(it != itEnd)
{
if((*it)->targetSlotHolder() == oldTarget)
{
connectedSlots_.push_back((*it)->duplicate(newTarget));
}
++it;
}
}
protected:
ConnectionList connectedSlots_;
};
template
class BasicSignal1 : public BasicSignal
{
public:
typedef typename std::list *> ConnectionList;
BasicSignal1() {}
BasicSignal1(const BasicSignal1& s) : BasicSignal(s)
{
typename ConnectionList::const_iterator it = s.connectedSlots_.begin();
typename ConnectionList::const_iterator itEnd = s.connectedSlots_.end();
while(it != itEnd)
{
(*it)->targetSlotHolder()->connectTo(this);
connectedSlots_.push_back((*it)->clone());
++it;
}
}
void duplicateSlot(const SlotHolder* oldTarget, SlotHolder* newTarget)
{
typename ConnectionList::iterator it = connectedSlots_.begin();
typename ConnectionList::iterator itEnd = connectedSlots_.end();
while(it != itEnd)
{
if((*it)->targetSlotHolder() == oldTarget)
{
connectedSlots_.push_back((*it)->duplicate(newTarget));
}
++it;
}
}
~BasicSignal1()
{
disconnectAll();
}
void disconnectAll()
{
typename ConnectionList::const_iterator it = connectedSlots_.begin();
typename ConnectionList::const_iterator itEnd = connectedSlots_.end();
while(it != itEnd)
{
(*it)->targetSlotHolder()->disconnectFrom(this);
delete *it;
++it;
}
connectedSlots_.erase(connectedSlots_.begin(), connectedSlots_.end());
}
void disconnect(SlotHolder* slotHolder)
{
typename ConnectionList::iterator it = connectedSlots_.begin();
typename ConnectionList::iterator itEnd = connectedSlots_.end();
while(it != itEnd)
{
if((*it)->targetSlotHolder() == slotHolder)
{
delete *it;
connectedSlots_.erase(it);
slotHolder->disconnectFrom(this);
return;
}
++it;
}
}
void disconnectSlot(SlotHolder* slot)
{
typename ConnectionList::iterator it = connectedSlots_.begin();
typename ConnectionList::iterator itEnd = connectedSlots_.end();
while(it != itEnd)
{
typename ConnectionList::iterator itNext = it;
++itNext;
if((*it)->targetSlotHolder() == slot)
{
delete *it;
connectedSlots_.erase(it);
}
it = itNext;
}
}
protected:
ConnectionList connectedSlots_;
};
template
class Connection0 : public BasicConnection0
{
public:
Connection0()
{
object_ = 0;
memberFunction_ = 0;
voidMemberFunction_ = 0;
}
Connection0(TargetType* anObject, void (TargetType::*aMemberFunction)())
{
object_ = anObject;
memberFunction_ = 0;
voidMemberFunction_ = aMemberFunction;
}
Connection0(TargetType* anObject, TargetType& (TargetType::*aMemberFunction)())
{
object_ = anObject;
memberFunction_ = aMemberFunction;
}
virtual BasicConnection0* clone()
{
return new Connection0(*this);
}
virtual BasicConnection0* duplicate(SlotHolder* newTarget)
{
return new Connection0((TargetType *)newTarget, memberFunction_);
}
virtual void emit()
{
if(memberFunction_ != 0)
(object_->*memberFunction_)();
else
(object_->*voidMemberFunction_)();
}
virtual SlotHolder* targetSlotHolder() const
{
return object_;
}
private:
TargetType* object_;
TargetType& (TargetType::* memberFunction_)();
void (TargetType::* voidMemberFunction_)();
};
template
class Connection1 : public BasicConnection1
{
public:
Connection1()
{
object_ = 0;
memberFunction_ = 0;
voidMemberFunction_ = 0;
}
Connection1(TargetType* anObject, void (TargetType::*aMemberFunction)(Type1))
{
object_ = anObject;
memberFunction_ = 0;
voidMemberFunction_ = aMemberFunction;
}
Connection1(TargetType* anObject, TargetType& (TargetType::*aMemberFunction)(Type1))
{
object_ = anObject;
voidMemberFunction_ = 0;
memberFunction_ = aMemberFunction;
}
virtual BasicConnection1* clone()
{
return new Connection1(*this);
}
virtual BasicConnection1* duplicate(SlotHolder* newTarget)
{
return new Connection1((TargetType *)newTarget, memberFunction_);
}
virtual void emit(Type1 a1)
{
if(memberFunction_ != 0)
(object_->*memberFunction_)(a1);
else
(object_->*voidMemberFunction_)(a1);
}
virtual SlotHolder* targetSlotHolder() const
{
return object_;
}
private:
TargetType* object_;
void (TargetType::* voidMemberFunction_)(Type1);
TargetType& (TargetType::* memberFunction_)(Type1);
};
class Signal0 : public BasicSignal0
{
public:
typedef BasicSignal0::ConnectionList ConnectionList;
public:
Signal0() {}
Signal0(const Signal0& s) : BasicSignal0(s) {}
template
void connect(TargetType* slotHolder, void (TargetType::*aMemberFunction)())
{
Connection0* conn =
new Connection0(slotHolder, aMemberFunction);
connectedSlots_.push_back(conn);
slotHolder->connectTo(this);
}
template
void connect(TargetType* slotHolder, TargetType& (TargetType::*aMemberFunction)())
{
Connection0* conn =
new Connection0(slotHolder, aMemberFunction);
connectedSlots_.push_back(conn);
slotHolder->connectTo(this);
}
void emit()
{
ConnectionList::const_iterator itNext, it = connectedSlots_.begin();
ConnectionList::const_iterator itEnd = connectedSlots_.end();
while(it != itEnd)
{
itNext = it;
++itNext;
(*it)->emit();
it = itNext;
}
}
void operator()()
{
ConnectionList::const_iterator itNext, it = connectedSlots_.begin();
ConnectionList::const_iterator itEnd = connectedSlots_.end();
while(it != itEnd)
{
itNext = it;
++itNext;
(*it)->emit();
it = itNext;
}
}
size_t size(void)
{
return connectedSlots_.size();
}
};
template
class Signal1 : public BasicSignal1
{
public:
typedef typename BasicSignal1::ConnectionList ConnectionList;
public:
Signal1() {}
Signal1(const Signal1& s) : BasicSignal1(s) {}
template
void connect(TargetType* slotHolder, void (TargetType::*aMemberFunction)(Type1))
{
Connection1* conn =
new Connection1(slotHolder, aMemberFunction);
BasicSignal1::connectedSlots_.push_back(conn);
slotHolder->connectTo(this);
}
template
void connect(TargetType* slotHolder, TargetType& (TargetType::*aMemberFunction)(Type1))
{
Connection1* conn =
new Connection1(slotHolder, aMemberFunction);
BasicSignal1::connectedSlots_.push_back(conn);
slotHolder->connectTo(this);
}
void emit(Type1 a1)
{
typename ConnectionList::const_iterator itNext, it = BasicSignal1::connectedSlots_.begin();
typename ConnectionList::const_iterator itEnd = BasicSignal1::connectedSlots_.end();
while(it != itEnd)
{
itNext = it;
++itNext;
(*it)->emit(a1);
it = itNext;
}
}
void operator()(Type1 a1)
{
typename ConnectionList::const_iterator itNext, it = BasicSignal1::connectedSlots_.begin();
typename ConnectionList::const_iterator itEnd = BasicSignal1::connectedSlots_.end();
while(it != itEnd)
{
itNext = it;
++itNext;
(*it)->emit(a1);
it = itNext;
}
}
size_t size(void)
{
return BasicSignal1::connectedSlots_.size();
}
};
}
#endif // SIGSLOT__H