Initial import of Dillo
This commit is contained in:
170
lout/signal.cc
Normal file
170
lout/signal.cc
Normal file
@ -0,0 +1,170 @@
|
||||
/*
|
||||
* Dillo Widget
|
||||
*
|
||||
* Copyright 2005-2007 Sebastian Geerken <sgeerken@dillo.org>
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "signal.hh"
|
||||
|
||||
namespace lout {
|
||||
namespace signal {
|
||||
|
||||
using namespace container::typed;
|
||||
|
||||
// ------------
|
||||
// Emitter
|
||||
// ------------
|
||||
|
||||
Emitter::Emitter ()
|
||||
{
|
||||
receivers = new List <Receiver> (false);
|
||||
}
|
||||
|
||||
Emitter::~Emitter ()
|
||||
{
|
||||
for (Iterator<Receiver> it = receivers->iterator (); it.hasNext (); ) {
|
||||
Receiver *receiver = it.getNext ();
|
||||
receiver->unconnectFrom (this);
|
||||
}
|
||||
delete receivers;
|
||||
}
|
||||
|
||||
void Emitter::intoStringBuffer(misc::StringBuffer *sb)
|
||||
{
|
||||
sb->append ("<emitter: ");
|
||||
receivers->intoStringBuffer (sb);
|
||||
sb->append (">");
|
||||
}
|
||||
|
||||
void Emitter::unconnect (Receiver *receiver)
|
||||
{
|
||||
receivers->removeRef (receiver);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Connect a receiver to the emitter.
|
||||
*
|
||||
* This is protected, a sub class should define a wrapper, with the respective
|
||||
* receiver as an argument, to gain type safety.
|
||||
*/
|
||||
void Emitter::connect (Receiver *receiver)
|
||||
{
|
||||
receivers->append (receiver);
|
||||
receiver->connectTo (this);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Emit a void signal.
|
||||
*
|
||||
* This method should be called by a wrapper (return value void), which
|
||||
* \em folds the signal, and delegates the emission to here.
|
||||
*/
|
||||
void Emitter::emitVoid (int signalNo, int argc, Object **argv)
|
||||
{
|
||||
for (Iterator <Receiver> it = receivers->iterator (); it.hasNext (); ) {
|
||||
Receiver *receiver = it.getNext();
|
||||
emitToReceiver (receiver, signalNo, argc, argv);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Emit a boolean signal.
|
||||
*
|
||||
* This method should be called by a wrapper, which \em folds the signal,
|
||||
* delegates the emission to here, and returns the same boolean value.
|
||||
*/
|
||||
bool Emitter::emitBool (int signalNo, int argc, Object **argv)
|
||||
{
|
||||
bool b = false, bt;
|
||||
|
||||
for (Iterator <Receiver> it = receivers->iterator (); it.hasNext (); ) {
|
||||
Receiver *receiver = it.getNext();
|
||||
// Note: All receivers are called, even if one returns true.
|
||||
// Therefore, something like
|
||||
// b = b || emitToReceiver (receiver, signalNo, argc, argv);
|
||||
// does not work.
|
||||
bt = emitToReceiver (receiver, signalNo, argc, argv);
|
||||
b = b || bt;
|
||||
}
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
|
||||
// --------------
|
||||
// Receiver
|
||||
// --------------
|
||||
|
||||
Receiver::Receiver()
|
||||
{
|
||||
emitters = new List <Emitter> (false);
|
||||
}
|
||||
|
||||
Receiver::~Receiver()
|
||||
{
|
||||
for (Iterator<Emitter> it = emitters->iterator(); it.hasNext(); ) {
|
||||
Emitter *emitter = it.getNext();
|
||||
emitter->unconnect (this);
|
||||
}
|
||||
delete emitters;
|
||||
}
|
||||
|
||||
void Receiver::intoStringBuffer(misc::StringBuffer *sb)
|
||||
{
|
||||
// emitters are not listed, to prevent recursion
|
||||
sb->append ("<receiver>");
|
||||
}
|
||||
|
||||
void Receiver::connectTo(Emitter *emitter)
|
||||
{
|
||||
emitters->append (emitter);
|
||||
}
|
||||
|
||||
void Receiver::unconnectFrom(Emitter *emitter)
|
||||
{
|
||||
emitters->removeRef (emitter);
|
||||
}
|
||||
|
||||
// ------------------------
|
||||
// ObservedObject
|
||||
// ------------------------
|
||||
|
||||
bool ObservedObject::DeletionEmitter::emitToReceiver (Receiver *receiver,
|
||||
int signalNo,
|
||||
int argc, Object **argv)
|
||||
{
|
||||
object::TypedPointer <ObservedObject> *p =
|
||||
(object::TypedPointer<ObservedObject>*)argv[0];
|
||||
((DeletionReceiver*)receiver)->deleted (p->getTypedValue ());
|
||||
return false;
|
||||
}
|
||||
|
||||
void ObservedObject::DeletionEmitter::emitDeletion (ObservedObject *obj)
|
||||
{
|
||||
object::TypedPointer <ObservedObject> p(obj);
|
||||
object::Object *argv[1] = { &p };
|
||||
emitVoid (0, 1, argv);
|
||||
}
|
||||
|
||||
ObservedObject::~ObservedObject()
|
||||
{
|
||||
deletionEmitter.emitDeletion (this);
|
||||
}
|
||||
|
||||
} // namespace signal
|
||||
} // namespace lout
|
||||
Reference in New Issue
Block a user