// -*- c++ -*-
dnl slot.h.m4 - slot class for sigc++
dnl
// Copyright 2000, Karl Einar Nelson
dnl
dnl This library is free software; you can redistribute it and/or
dnl modify it under the terms of the GNU Lesser General Public
dnl License as published by the Free Software Foundation; either
dnl version 2 of the License, or (at your option) any later version.
dnl
dnl This library is distributed in the hope that it will be useful,
dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
dnl Lesser General Public License for more details.
dnl
dnl You should have received a copy of the GNU Lesser General Public
dnl License along with this library; if not, write to the Free Software
dnl Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
dnl
include(template.macros.m4)
#ifndef __header__
#define __header__
/* FIXME where is the docs buddy! */
/** @defgroup Slots
* Slots are type-safe representations of callback methods and functions.
* A Slot can be constructed from any function, regardless of whether it is
* a global function, a member method, static, or virtual.
*
* Use the SigC::slot() template function to get a SigC::Slot, like so:
* @code
* SigC::Slot1<void, int> slot = SigC::slot(someobj, &SomeClass::somemethod);
* @endcode
* or
* @code
* m_Button.signal_clicked().connect( SigC::slot(*this, &MyWindow::on_button_clicked) );
* @endcode
* The compiler will complain if SomeClass::somemethod has the wrong signature.
*
* You can also pass slots as method parameters where you might normally pass a function pointer.
*/
#include <sigc++/node.h>
#include <sigc++/trait.h>
#ifdef SIGC_CXX_NAMESPACES
namespace SigC
{
#endif
// this is a dummy type which we will cast to any static function
typedef void (*FuncPtr)(void*);
// (internal) All Slot types derive from this.
class LIBSIGC_API SlotNode: public NodeBase
{
public:
virtual ~SlotNode()=0;
// node must be dynamic
virtual void add_dependency(NodeBase*);
virtual void remove_dependency(NodeBase*);
// message from child that it has died and we should start
// our shut down. If from_child is true, we do not need
// to clean up the child links.
virtual void notify(bool from_child);
SlotNode(FuncPtr proxy);
FuncPtr proxy_;
NodeBase *dep_;
};
/**************************************************************/
// These are internal classes used to represent function varients of slots
// (internal)
struct LIBSIGC_API FuncSlotNode : public SlotNode
{
FuncPtr func_;
FuncSlotNode(FuncPtr proxy,FuncPtr func);
virtual ~FuncSlotNode();
};
define([__FUNC_SLOT__],[[FuncSlot]eval(NUM($*)-1)_<LIST($*)>])dnl
dnl
dnl FUNC_SLOT(ARGS)
dnl
define([FUNC_SLOT],[dnl
template <LIST(class R,ARG_CLASS($1))>
struct FuncSlot[]NUM($1)_
{
typedef typename Trait<R>::type RType;
typedef RType (*Callback)($1);
static RType proxy(LIST(ARG_REF($1),void *s))
{
return ((Callback)(((FuncSlotNode*)s)->func_))(ARG_NAME($1));
}
};
])
// These do not derive from FuncSlot, they merely hold typedefs and
// static functions on how to deal with the proxy.
FUNC_SLOT(ARGS(P,0))
FUNC_SLOT(ARGS(P,1))
FUNC_SLOT(ARGS(P,2))
FUNC_SLOT(ARGS(P,3))
FUNC_SLOT(ARGS(P,4))
FUNC_SLOT(ARGS(P,5))
FUNC_SLOT(ARGS(P,6))
/**************************************************************/
// Slot# is a holder to a SlotNode, its type is held by type of the
// pointer and not the SlotNode itself. This reduces the
// number and size of type objects.
/// (internal) Typeless Slot base class.
class LIBSIGC_API SlotBase : public Node
{
public:
// For backwards compatiblity
bool connected() const { return valid(); }
// (internal)
SlotNode* operator->() { return static_cast<SlotNode*>(node_); }
protected:
// users don't use slots so we will protect the methods
SlotBase() : Node() {}
SlotBase(const SlotBase& s) : Node(s) {}
~SlotBase() {}
SlotBase& operator =(const SlotBase& s)
{ Node::operator=(s); return *this; }
};
dnl
dnl SLOT([P1...PN])
dnl
dnl Notes,
dnl - changed call to valid() to node_->notified to cut emission time in
dnl half
dnl
define([SLOT],[dnl
/// @ingroup Slots
template <LIST(class R,ARG_CLASS($1))>
class Slot[]NUM($1) : public SlotBase
{
public:
typedef typename Trait<R>::type RType;
typedef R (*Callback)(ARG_TYPE($1));
typedef RType (*Proxy)(LIST(ARG_REF($1),void*));
RType operator ()(ARG_REF($1))
{
if (!node_) return RType();
if (node_->notified_)
{ clear(); return RType(); }
return ((Proxy)(static_cast<SlotNode*>(node_)->proxy_))
(LIST(ARG_NAME($1),node_));
}
Slot[]NUM($1)& operator= (const Slot[]NUM($1) &s)
{
SlotBase::operator=(s);
return *this;
}
Slot[]NUM($1)()
: SlotBase() {}
Slot[]NUM($1)(const Slot[]NUM($1)& s)
: SlotBase(s)
{}
Slot[]NUM($1)(SlotNode* node)
: SlotBase()
{ assign(node); }
Slot[]NUM($1)(Callback callback)
: SlotBase()
{
typedef __FUNC_SLOT__(R,$1) Proxy_;
assign(new FuncSlotNode((FuncPtr)&Proxy_::proxy,(FuncPtr)callback));
}
~Slot[]NUM($1)() {}
};
template <LIST(class R,ARG_CLASS($1))>
__SLOT__(R,$1) slot(R (*func)(ARG_TYPE($1)))
{ return func; }
])
// these represent the callable structure of a slot with various types.
// they are fundimentally just wrappers. They have no differences other
// that the types they cast data to.
SLOT(ARGS(P,0))
SLOT(ARGS(P,1))
SLOT(ARGS(P,2))
SLOT(ARGS(P,3))
SLOT(ARGS(P,4))
SLOT(ARGS(P,5))
SLOT(ARGS(P,6))
#ifdef SIGC_CXX_NAMESPACES
}
#endif
#endif // SIGC_SLOT
syntax highlighted by Code2HTML, v. 0.9.1