/************************************************************************ filename: CEGUIEvent.h created: 15/10/2004 authors: Paul D Turner (High-level design) Gerald Lindsly (Coder) purpose: Defines interface for Event class *************************************************************************/ /************************************************************************* Crazy Eddie's GUI System (http://www.cegui.org.uk) Copyright (C)2004 - 2005 Paul D Turner (paul@cegui.org.uk) 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.1 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 library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *************************************************************************/ #ifndef _CEGUIEvent_h_ #define _CEGUIEvent_h_ #if defined (_MSC_VER) # pragma warning(push) # pragma warning(disable : 4786) # pragma warning(disable : 4251) # if !defined (_MSC_EXTENSIONS) # pragma warning (disable : 4224) # endif #endif #include "CEGUIBase.h" #include "CEGUIString.h" #include "CEGUIEventArgs.h" #include "CEGUIRefPtr.h" #include // Start of CEGUI namespace section namespace CEGUI { /* The base class for the various binders. This provides a consistent interface for firing functions bound to an event. */ template class SubscriberInterface { public: virtual Ret operator()(Args) const = 0; virtual ~SubscriberInterface() {} }; /* This class binds a free function. */ template class _freeBinder : public SubscriberInterface { public: virtual Ret operator()(Args args) const { return d_f(args); } typedef Ret (*SlotFunction)(Args); _freeBinder(SlotFunction f) : d_f(f) {} protected: SlotFunction d_f; }; /* This class binds a copy of a functor. */ template class _functorBinder : public SubscriberInterface { public: virtual Ret operator()(Args args) const { return d_f(args); } _functorBinder(const Functor& f) : d_f(f) {} protected: Functor d_f; }; /* This class binds a member function along with a target object. */ template class _memberBinder : public SubscriberInterface { typedef Ret (T::*F)(Args); public: virtual Ret operator()(Args args) const { return (d_t->*d_f)(args); } _memberBinder(F f, T* t) : d_f(f), d_t(t) {} protected: F d_f; T* d_t; }; /* This template describes the Subscriber class. It is a wrapper for a pointer to a SubscriberInterface with various constructors that will by implicit conversion construct the various binders. */ template class SubscriberTemplate { public: Ret operator()(Args args) const { return (*d_si)(args); // call the bound function } typedef Ret (*SlotFunction)(Args); // construct from a free function SubscriberTemplate(SlotFunction f) { d_si = new _freeBinder(f); } // construct from a member function and a pointer to the target object. template SubscriberTemplate(Ret (T::*f)(Args), T* target) { d_si = new _memberBinder(f, target); } // construct from a generalized functor by copying it template SubscriberTemplate(const Functor& f) { d_si = new _functorBinder(f); } /* construct from a preconstructed SubscriberInterface. used for SubscriberRef(). */ SubscriberTemplate(SubscriberInterface* si) : d_si(si) {} // copy constructor SubscriberTemplate(const SubscriberTemplate& copy) : d_si(copy.d_si) {} // 'less than' comparable for insertion in a map bool operator<(const SubscriberTemplate& rhs) const { return d_si < rhs.d_si; } // release the binding -- called upon disconnection void release() const { delete d_si; } protected: SubscriberInterface* d_si; }; /* This class binds a const reference to a generalized functor. Sometimes it may not be appropriate for the functor to be cloned. In which case, use SubscriberRef() (which uses this). */ template class _refBinder : public SubscriberInterface { public: virtual Ret operator()(Args args) const { return d_f(args); } _refBinder(const Functor& f) : d_f(f) {} protected: const Functor& d_f; }; /* This helper function produces a const reference binding */ template SubscriberInterface* SubscriberRef(const Functor& f) { return new _refBinder(f); } /*! \brief Defines an 'event' which can be subscribed to by interested parties. An Event can be subscribed by a function, a static member function, or a function object. Whichever option is taken, the function signature needs to be as follows \par bool function_name(const EventArgs& args); \note An Event object may not be copied. */ class CEGUIEXPORT Event { public: class ConnectionInterface : public Referenced { public: virtual bool connected() { return false; } virtual void disconnect() {} }; typedef RefPtr Connection; class ScopedConnection { public: ScopedConnection(Connection conn_) : conn(conn_) {} ~ScopedConnection() { conn->disconnect(); } Connection conn; }; typedef SubscriberTemplate Subscriber; typedef int Group; /************************************************************************* Construction and Destruction *************************************************************************/ /*! \brief Constructs a new Event object with the specified name */ Event(const String& name); /*! \brief Destructor for Event objects */ virtual ~Event(void); /*! \brief Return the name given to this Event object when it was created. \return String object containing the name of the Event object. */ const String& getName(void) const {return d_name;} /*! \brief Subscribes some function / object to the Event \param subscriber A function, static member function, or function object, with the signature void function_name(const EventArgs& args) \return A Connection pointer which can be used to disconnect (unsubscribe) from the Event, and to check the connection state. */ Connection subscribe(Subscriber subscriber) { return subscribe(0, subscriber); } /*! \brief Subscribes some function / object to the Event \param group The Event group to subscribe to, subscription groups are called in ascending order, followed by subscriptions with no group. connections to the same group may be called in any order. \param subscriber A function, static member function, or function object, with the signature void function_name(const EventArgs& args) \return A Connection which can be used to disconnect (unsubscribe) from the Event, and to check the connection state. */ Connection subscribe(Group group, Subscriber subscriber); /* \brief Fires the event. All event subscribers get called in the appropriate sequence. \param args An object derived from EventArgs to be passed to each event subscriber. \return Nothing. */ void operator()(EventArgs& args); private: /************************************************************************* Copy constructor and assignment are not allowed for events *************************************************************************/ Event(const Event& evt) {} Event& operator=(const Event& evt) {return *this;} /* \brief removes the subscriber from the event. \param subscriber A pointer to a SubscriberInterface which is to be removed from the event. \return - true, if the subscriber was registered with the event in the specified group and it was removed. - false, if not. */ bool unsubscribe(Subscriber subscriber, Group group=0); class GroupSubscriber { public: Group group; Subscriber subscriber; GroupSubscriber(Group group_, Subscriber subscriber_) : group(group_), subscriber(subscriber_) {} }; struct ltGroupSubscriber { bool operator()(const GroupSubscriber& gs1, const GroupSubscriber& gs2) const { return gs1.group < gs2.group || gs1.group == gs2.group && gs1.subscriber < gs2.subscriber; } }; typedef std::map ConnectionOrdering; /************************************************************************* Implementation Data *************************************************************************/ const String d_name; //!< Name of this event ConnectionOrdering connectionOrdering; friend class ConnectionImpl; }; } // End of CEGUI namespace section #if defined(_MSC_VER) # pragma warning(pop) #endif #endif // end of guard _CEGUIEvent_h_