/** * @file scim_signals.h * @brief C++ signal interface. * * Provides a set of signal class templates you can use to create signals * that can pass up to 6 arguments to signal handlers connected via the * slot interface (see scim_slot.h). The signal classes are named Signal0 * to Signal6, where 0 to 6 specifies the number of arguments that can be * passed to a slot. * * Most code of this file are came from Inti project. */ /* * Smart Common Input Method * * Copyright (c) 2002-2005 James Su * Copyright (c) 2002 The Inti Development Team. * Copyright (c) 2000 Red Hat, Inc. * Copyright 1999, Karl Einar Nelson * * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., 59 Temple Place, Suite 330, * Boston, MA 02111-1307 USA * * $Id: scim_signals.h,v 1.12 2005/01/30 13:24:13 suzhe Exp $ */ #ifndef __SCIM_SIGNALS_H #define __SCIM_SIGNALS_H namespace scim { /** * @addtogroup SignalSlot * @{ */ class Signal; //! @class SlotNode //! @brief A node class for managing slots connected to scim::Signal's. class SlotNode : public Node { friend class Signal; SlotNode(Slot *slot); ~SlotNode(); bool is_blocked; public: bool blocked() const { return is_blocked; } //!< Returns true if the slot is blocked. virtual void block(); //!< Block signal emission to the slot until unblock is called. virtual void unblock(); //!< Unblock the slot so signal emmissions can be received. virtual void disconnect(); //!< Disconnect the slot. The slot will no longer recieve signal emissions. }; // DefaultMarshal class (from marshal.h, libsigc++) template class DefaultMarshal { public: typedef R OutType; typedef R InType; private: OutType value_; public: DefaultMarshal() :value_() {} OutType& value() { return value_; } // Return true to stop emission. bool marshal(const InType & newval) { value_ = newval; return false; } }; // Marshal specialization template <> class DefaultMarshal { public: typedef bool OutType; typedef bool InType; private: OutType value_; public: DefaultMarshal() :value_(false) {} OutType& value() { return value_; } // Return true to stop emission. bool marshal(const InType & newval) { value_ = newval; return false; } }; //! @class Signal //! @brief Base class for the C++ signal interface. class Signal { Signal(const Signal&); Signal& operator=(const Signal&); protected: typedef std::vector< Pointer > ConnectionList; //!< ConnectionList type. ConnectionList connection_list; //!< A list of all the slots connected to the signal. public: Signal(); //!< Constructor. virtual ~Signal(); //!< Destructor. SlotNode* connect(Slot *slot); //!< Creates a new SlotNode for slot and adds it to the connection_list. }; //! @class Signal0 //! @brief A template for a signal passing no arguments and returning a value of type R. template > class Signal0 : public Signal { typedef Signal0 Self; static R callback(void *data) { Self *s = static_cast(data); return s->emit(); } public: typedef Slot0 SlotType; //!< Function signature for handlers connecting the signal. Connection connect(SlotType *slot) { return Signal::connect(slot); } //!< Connect a slot to the signal. //!< @param slot - a slot of type Slot0. //!< @return a connection object. //!< //!<
The returned connection object can be used alter or change the connection. SlotType* slot() { return new SignalSlot0(this, &callback); } //!< Returns a slot for this signal. //!< @return a new slot of type Slot0. //!< //!<
The returned slot can be passed to another signal allowing the //!< other signal to call this signal when it gets emitted. R emit() { Marshal m; ConnectionList::iterator i = connection_list.begin(); while (i != connection_list.end()) { if (!(*i)->blocked()) { SlotType *slot = dynamic_cast((*i)->slot()); if (slot && m.marshal(slot->call())) break; } ++i; } return m.value(); } //!< Emit the signal. //!< @return the value returned by the signal handler. //!< //!<
Calls every slot connected to this signal, in order of connection. R operator()() { return emit(); } //!< Function operator; calls emit(). }; // Signal0 partially specialized for void return template class Signal0 : public Signal { typedef Signal0 Self; static void callback(void *data) { Self *s = static_cast(data); s->emit(); } public: typedef Slot0 SlotType; Connection connect(SlotType *slot) { return Signal::connect(slot); } SlotType* slot() { return new SignalSlot0(this, &callback); } void emit() { ConnectionList::iterator i = connection_list.begin(); while (i != connection_list.end()) { if (!(*i)->blocked()) { SlotType *slot = dynamic_cast((*i)->slot()); if (slot) slot->call(); } ++i; } } void operator()() { emit(); } }; //! @class Signal1 //! @brief A template for a signal passing one argument of type P1 and returning a value of type R. template > class Signal1 : public Signal { typedef Signal1 Self; static R callback(void *data, P1 p1) { Self *s = static_cast(data); return s->emit(p1); } public: typedef Slot1 SlotType; //!< Function signature for handlers connecting to the signal. Connection connect(SlotType *slot) { return Signal::connect(slot); } //!< Connect a slot to the signal. //!< @param slot - a slot of type Slot1. //!< @return a connection object. //!< //!<
The returned connection object can be used alter or change the connection. SlotType* slot() { return new SignalSlot1(this, &callback); } //!< Returns a slot for this signal. //!< @return a new slot of type Slot1. //!< //!<
The returned slot can be passed to another signal allowing the //!< other signal to call this signal when it gets emitted. R emit(P1 p1) { Marshal m; ConnectionList::iterator i = connection_list.begin(); while (i != connection_list.end()) { if (!(*i)->blocked()) { SlotType *slot = dynamic_cast((*i)->slot()); if (slot && m.marshal(slot->call(p1))) break; } ++i; } return m.value(); } //!< Emit the signal. //!< @param p1 - passes p1 to the signal handler. //!< @return the value returned by the signal handler. //!< //!<
Calls every slot connected to this signal, in order of connection. R operator()(P1 p1) { return emit(p1); } //!< Function operator; calls emit(). }; // Signal1 partially specialized for void return template class Signal1 : public Signal { typedef Signal1 Self; static void callback(void *data, P1 p1) { Self *s = static_cast(data); s->emit(p1); } public: typedef Slot1 SlotType; Connection connect(SlotType *slot) { return Signal::connect(slot); } SlotType* slot() { return new SignalSlot1(this, &callback); } void emit(P1 p1) { ConnectionList::iterator i = connection_list.begin(); while (i != connection_list.end()) { if (!(*i)->blocked()) { SlotType *slot = dynamic_cast((*i)->slot()); if (slot) slot->call(p1); } ++i; } } void operator()(P1 p1) { emit(p1); } }; //! @class Signal2 //! @brief A template for a signal passing two arguments of type P1 and P2, //! and returning a value of type R. template > class Signal2 : public Signal { typedef Signal2 Self; static R callback(void *data, P1 p1, P2 p2) { Self *s = static_cast(data); return s->emit(p1, p2); } public: typedef Slot2 SlotType; //!< Function signature for handlers connecting to the signal. Connection connect(SlotType *slot) { return Signal::connect(slot); } //!< Connect a slot to the signal. //!< @param slot - a slot of type Slot2. //!< @return a connection object. //!< //!<
The returned connection object can be used alter or change the connection. SlotType* slot() { return new SignalSlot2(this, &callback); } //!< Returns a slot for this signal. //!< @return a new slot of type Slot2. //!< //!<
The returned slot can be passed to another signal allowing the //!< other signal to call this signal when it gets emitted. R emit(P1 p1, P2 p2) { Marshal m; ConnectionList::iterator i = connection_list.begin(); while (i != connection_list.end()) { if (!(*i)->blocked()) { SlotType *slot = dynamic_cast((*i)->slot()); if (slot && m.marshal(slot->call(p1, p2))) break; } ++i; } return m.value(); } //!< Emit the signal. //!< @param p1 - passes p1 to the signal handler. //!< @param p2 - passes p2 to the signal handler. //!< @return the value returned by the signal handler. //!< //!<
Calls every slot connected to this signal, in order of connection. R operator()(P1 p1, P2 p2) { return emit(p1, p2); } //!< Function operator; calls emit(). }; // Signal2 partially specialized for void return template class Signal2 : public Signal { typedef Signal2 Self; static void callback(void *data, P1 p1, P2 p2) { Self *s = static_cast(data); s->emit(p1, p2); } public: typedef Slot2 SlotType; Connection connect(SlotType *slot) { return Signal::connect(slot); } SlotType* slot() { return new SignalSlot2(this, &callback); } void emit(P1 p1, P2 p2) { ConnectionList::iterator i = connection_list.begin(); while (i != connection_list.end()) { if (!(*i)->blocked()) { SlotType *slot = dynamic_cast((*i)->slot()); if (slot) slot->call(p1, p2); } ++i; } } void operator()(P1 p1, P2 p2) { emit(p1, p2); } }; //! @class Signal3 //! @brief A template for a signal passing three arguments of type P1, P2 and P3, //! and returning a value of type R. template > class Signal3 : public Signal { typedef Signal3 Self; static R callback(void *data, P1 p1, P2 p2, P3 p3) { Self *s = static_cast(data); return s->emit(p1, p2, p3); } public: typedef Slot3 SlotType; //!< Function signature for handlers connecting to the signal. Connection connect(SlotType *slot) { return Signal::connect(slot); } //!< Connect a slot to the signal. //!< @param slot - a slot of type Slot3. //!< @return a connection object. //!< //!<
The returned connection object can be used alter or change the connection. SlotType* slot() { return new SignalSlot3(this, &callback); } //!< Returns a slot for this signal. //!< @return a new slot of type Slot3. //!< //!<
The returned slot can be passed to another signal allowing the //!< other signal to call this signal when it gets emitted. R emit(P1 p1, P2 p2, P3 p3) { Marshal m; ConnectionList::iterator i = connection_list.begin(); while (i != connection_list.end()) { if (!(*i)->blocked()) { SlotType *slot = dynamic_cast((*i)->slot()); if (slot && m.marshal(slot->call(p1, p2, p3))) break; } ++i; } return m.value(); } //!< Emit the signal. //!< @param p1 - passes p1 to the signal handler. //!< @param p2 - passes p2 to the signal handler. //!< @param p3 - passes p3 to the signal handler. //!< @return the value returned by the signal handler. //!< //!<
Calls every slot connected to this signal, in order of connection. R operator()(P1 p1, P2 p2, P3 p3) { return emit(p1, p2, p3); } //!< Function operator; calls emit(). }; // Signal3 partially specialized for void return template class Signal3 : public Signal { typedef Signal3 Self; static void callback(void *data, P1 p1, P2 p2, P3 p3) { Self *s = static_cast(data); s->emit(p1, p2, p3); } public: typedef Slot3 SlotType; Connection connect(SlotType *slot) { return Signal::connect(slot); } SlotType* slot() { return new SignalSlot3(this, &callback); } void emit(P1 p1, P2 p2, P3 p3) { ConnectionList::iterator i = connection_list.begin(); while (i != connection_list.end()) { if (!(*i)->blocked()) { SlotType *slot = dynamic_cast((*i)->slot()); if (slot) slot->call(p1, p2, p3); } ++i; } } void operator()(P1 p1, P2 p2, P3 p3) { emit(p1, p2, p3); } }; //! @class Signal4 //! @brief A template for a signal passing four arguments of type P1, P2, P3 and P4, //! and returning a value of type R. template > class Signal4 : public Signal { typedef Signal4 Self; static R callback(void *data, P1 p1, P2 p2, P3 p3, P4 p4) { Self *s = static_cast(data); return s->emit(p1, p2, p3, p4); } public: typedef Slot4 SlotType; //!< Function signature for handlers connecting to the signal. Connection connect(SlotType *slot) { return Signal::connect(slot); } //!< Connect a slot to the signal. //!< @param slot - a slot of type Slot4. //!< @return a connection object. //!< //!<
The returned connection object can be used alter or change the connection. SlotType* slot() { return new SignalSlot4(this, &callback); } //!< Returns a slot for this signal. //!< @return a new slot of type Slot4. //!< //!<
The returned slot can be passed to another signal allowing the //!< other signal to call this signal when it gets emitted. R emit(P1 p1, P2 p2, P3 p3, P4 p4) { Marshal m; ConnectionList::iterator i = connection_list.begin(); while (i != connection_list.end()) { if (!(*i)->blocked()) { SlotType *slot = dynamic_cast((*i)->slot()); if (slot && m.marshal(slot->call(p1, p2, p3, p4))) break; } ++i; } return m.value(); } //!< Emit the signal. //!< @param p1 - passes p1 to the signal handler. //!< @param p2 - passes p2 to the signal handler. //!< @param p3 - passes p3 to the signal handler. //!< @param p4 - passes p4 to the signal handler. //!< @return the value returned by the signal handler. //!< //!<
Calls every slot connected to this signal, in order of connection. R operator()(P1 p1, P2 p2, P3 p3, P4 p4) { return emit(p1, p2, p3, p4); } //!< Function operator; calls emit(). }; // Signal4 partially specialized for void return template class Signal4 : public Signal { typedef Signal4 Self; static void callback(void *data, P1 p1, P2 p2, P3 p3, P4 p4) { Self *s = static_cast(data); s->emit(p1, p2, p3, p4); } public: typedef Slot4 SlotType; Connection connect(SlotType *slot) { return Signal::connect(slot); } SlotType* slot() { return new SignalSlot4(this, &callback); } void emit(P1 p1, P2 p2, P3 p3, P4 p4) { ConnectionList::iterator i = connection_list.begin(); while (i != connection_list.end()) { if (!(*i)->blocked()) { SlotType *slot = dynamic_cast((*i)->slot()); if (slot) slot->call(p1, p2, p3, p4); } ++i; } } void operator()(P1 p1, P2 p2, P3 p3, P4 p4) { emit(p1, p2, p3, p4); } }; //! @class Signal5 //! @brief A template for a signal passing five arguments of type P1, P2, P3, P4 and P5, //! and returning a value of type R. template > class Signal5 : public Signal { typedef Signal5 Self; static R callback(void *data, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) { Self *s = static_cast(data); return s->emit(p1, p2, p3, p4, p5); } public: typedef Slot5 SlotType; //!< Function signature for handlers connecting to the signal. Connection connect(SlotType *slot) { return Signal::connect(slot); } //!< Connect a slot to the signal. //!< @param slot - a slot of type Slot5. //!< @return a connection object. //!< //!<
The returned connection object can be used alter or change the connection. SlotType* slot() { return new SignalSlot5(this, &callback); } //!< Returns a slot for this signal. //!< @return a new slot of type Slot5. //!< //!<
The returned slot can be passed to another signal allowing the //!< other signal to call this signal when it gets emitted. R emit(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) { Marshal m; ConnectionList::iterator i = connection_list.begin(); while (i != connection_list.end()) { if (!(*i)->blocked()) { SlotType *slot = dynamic_cast((*i)->slot()); if (slot && m.marshal(slot->call(p1, p2, p3, p4, p5))) break; } ++i; } return m.value(); } //!< Emit the signal. //!< @param p1 - passes p1 to the signal handler. //!< @param p2 - passes p2 to the signal handler. //!< @param p3 - passes p3 to the signal handler. //!< @param p4 - passes p4 to the signal handler. //!< @param p5 - passes p5 to the signal handler. //!< @return the value returned by the signal handler. //!< //!<
Calls every slot connected to this signal, in order of connection. R operator()(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) { return emit(p1, p2, p3, p4, p5); } //!< Function operator; calls emit(). }; // Signal5 partially specialized for void return template class Signal5 : public Signal { typedef Signal5 Self; static void callback(void *data, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) { Self *s = static_cast(data); s->emit(p1, p2, p3, p4, p5); } public: typedef Slot5 SlotType; Connection connect(SlotType *slot) { return Signal::connect(slot); } SlotType* slot() { return new SignalSlot5(this, &callback); } void emit(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) { ConnectionList::iterator i = connection_list.begin(); while (i != connection_list.end()) { if (!(*i)->blocked()) { SlotType *slot = dynamic_cast((*i)->slot()); if (slot) slot->call(p1, p2, p3, p4, p5); } ++i; } } void operator()(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) { emit(p1, p2, p3, p4, p5); } }; //! @class Signal6 //! @brief A template for a signal passing six arguments of type P1, P2, P3, P4, P5 and P6, //! and returning a value of type R. template > class Signal6 : public Signal { typedef Signal6 Self; static R callback(void *data, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) { Self *s = static_cast(data); return s->emit(p1, p2, p3, p4, p5, p6); } public: typedef Slot6 SlotType; //!< Function signature for handlers connecting to the signal. Connection connect(SlotType *slot) { return Signal::connect(slot); } //!< Connect a slot to the signal. //!< @param slot - a slot of type Slot6. //!< @return a connection object. //!< //!<
The returned connection object can be used alter or change the connection. SlotType* slot() { return new SignalSlot6(this, &callback); } //!< Returns a slot for this signal. //!< @return a new slot of type Slot6. //!< //!<
The returned slot can be passed to another signal allowing the //!< other signal to call this signal when it gets emitted. R emit(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) { Marshal m; ConnectionList::iterator i = connection_list.begin(); while (i != connection_list.end()) { if (!(*i)->blocked()) { SlotType *slot = dynamic_cast((*i)->slot()); if (slot && m.marshal(slot->call(p1, p2, p3, p4, p5, p6))) break; } ++i; } return m.value(); } //!< Emit the signal. //!< @param p1 - passes p1 to the signal handler. //!< @param p2 - passes p2 to the signal handler. //!< @param p3 - passes p3 to the signal handler. //!< @param p4 - passes p4 to the signal handler. //!< @param p5 - passes p5 to the signal handler. //!< @param p6 - passes p6 to the signal handler. //!< @return the value returned by the signal handler. //!< //!<
Calls every slot connected to this signal, in order of connection. R operator()(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) { return emit(p1, p2, p3, p4, p5, p6); } //!< Function operator; calls emit(). }; /* Signal6 partially specialized for void return */ template class Signal6 : public Signal { typedef Signal6 Self; static void callback(void *data, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) { Self *s = static_cast(data); s->emit(p1, p2, p3, p4, p5, p6); } public: typedef Slot6 SlotType; Connection connect(SlotType *slot) { return Signal::connect(slot); } SlotType* slot() { return new SignalSlot6(this, &callback); } void emit(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) { ConnectionList::iterator i = connection_list.begin(); while (i != connection_list.end()) { if (!(*i)->blocked()) { SlotType *slot = dynamic_cast((*i)->slot()); if (slot) slot->call(p1, p2, p3, p4, p5, p6); } ++i; } } void operator()(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) { emit(p1, p2, p3, p4, p5, p6); } }; /** @} */ } // namespace scim #endif //__SCIM_SIGNALS_H /* vi:ts=4:nowrap:ai:expandtab */