aboutsummaryrefslogtreecommitdiff
path: root/lout/signal.cc
diff options
context:
space:
mode:
authorjcid <devnull@localhost>2008-09-24 18:44:40 +0200
committerjcid <devnull@localhost>2008-09-24 18:44:40 +0200
commitc377e06400f138325a9a9d43d91a9272691867a1 (patch)
tree49f3ca1c46af11a058a68714899d4137ec717618 /lout/signal.cc
parent642f9b3e747859a7256ea12fab9f9ed50aa9253a (diff)
- Moved the dw2 tree into dillo2's tree.
Diffstat (limited to 'lout/signal.cc')
-rw-r--r--lout/signal.cc171
1 files changed, 171 insertions, 0 deletions
diff --git a/lout/signal.cc b/lout/signal.cc
new file mode 100644
index 00000000..46aae626
--- /dev/null
+++ b/lout/signal.cc
@@ -0,0 +1,171 @@
+/*
+ * 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, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+
+#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