/* * Dillo Widget * * Copyright 2005-2007 Sebastian Geerken * * 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 . */ #include "signal.hh" namespace lout { namespace signal { using namespace container::typed; // ------------ // Emitter // ------------ Emitter::Emitter()= default; Emitter::~Emitter () { // TODO: RAII this? for( Receiver *receiver: receivers ) { receiver->unconnectFrom( this ); } } void Emitter::intoStringBuffer(misc::StringBuffer *sb) const { sb->append ("append (">"); } void Emitter::unconnect (Receiver *receiver) { receivers.remove( 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.push_back( 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( Receiver *receiver: receivers ) { 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( Receiver *receiver: receivers ) { // 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()= default; Receiver::~Receiver() { for( Emitter *emitter: emitters ) { emitter->unconnect (this); } } void Receiver::intoStringBuffer(misc::StringBuffer *sb) const { // emitters are not listed, to prevent recursion sb->append (""); } void Receiver::connectTo(Emitter *emitter) { emitters.push_back( emitter ); } void Receiver::unconnectFrom(Emitter *emitter) { emitters.remove( emitter); } // ------------------------ // ObservedObject // ------------------------ bool ObservedObject::DeletionEmitter::emitToReceiver (Receiver *receiver, int signalNo, int argc, Object **argv) { object::TypedPointer *p = (object::TypedPointer*)argv[0]; ((DeletionReceiver*)receiver)->deleted (p->getTypedValue ()); return false; } void ObservedObject::DeletionEmitter::emitDeletion (ObservedObject *obj) { object::TypedPointer p(obj); object::Object *argv[1] = { &p }; emitVoid (0, 1, argv); } ObservedObject::~ObservedObject() { deletionEmitter.emitDeletion (this); } } // namespace signal } // namespace lout