Utils/EventChain.h

Sat, 11 Apr 2015 15:07:18 +0300

author
kandemir <kandemir@airpost.net>
date
Sat, 11 Apr 2015 15:07:18 +0300
branch
3.x-stable
changeset 681
939b9d20d986
parent 355
0b7f662779ba
permissions
-rw-r--r--

Fixed fpermisive cast in EventChain

//DESCRIPTION
//	This file allows exposing event objects. Supports multiple events
//	to be registered, unregister and different function signatures
//	If C++0x feature lambda functionality is causing problems, define
//	NOLAMBDA

//REQUIRES:
//	gge::utils::Collection
//	gge::utils::Any

//LICENSE
//	This program is free software: you can redistribute it and/or modify
//	it under the terms of the Lesser 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
//	Lesser GNU General Public License for more details.
//
//	You should have received a copy of the Lesser GNU General Public License
//	along with this program. If not, see < http://www.gnu.org/licenses/ >.

//COPYRIGHT
//	Cem Kalyoncu, DarkGaze.Org (cemkalyoncu[at]gmail[dot]com)

#pragma once


#define EVENTCHAIN_EXIST



#include <string>

#ifndef NOLAMBDA
#	include <functional>
#endif


#include "Collection.h"
#include "UtilsBase.h"
#include "Any.h"
#include <stdint.h>


namespace gge { namespace utils {

	////An empty event parameter structure
	struct empty_event_params {
	};


	class Empty {
	};


	//****
	//Solution to function<> parameters, solved by Nawaz@stackoverflow
	template <typename T>
	struct function_traits : public function_traits<decltype(&T::operator())>
	{};

	template <typename C, typename R>
	struct function_traits<R(C::*)() const> { enum { arity = 0 }; };

	template <typename C, typename R, typename T0>
	struct function_traits<R(C::*)(T0) const> { enum { arity = 1 }; };

	template <typename C, typename R, typename T0, typename T1>
	struct function_traits<R(C::*)(T0,T1) const> { enum { arity = 2 }; };

	template <typename C, typename R, typename T0, typename T1, typename T2>
	struct function_traits<R(C::*)(T0,T1,T2) const> { enum { arity = 3 }; };

	template <typename C, typename R, typename T0, typename T1, typename T2, typename T3>
	struct function_traits<R(C::*)(T0,T1,T2,T3) const> { enum { arity = 4 }; };

	template <typename C, typename R, typename T0, typename T1, typename T2, typename T3, typename T4>
	struct function_traits<R(C::*)(T0,T1,T2,T3,T4) const> { enum { arity = 5 }; };

	template<typename Functor, size_t NArgs, typename Type_=void>
	struct count_arg : std::enable_if<function_traits<Functor>::arity==NArgs, Type_>
	{};
	//****


	template<class O_, class P_> class EventChain;


	namespace prvt { namespace eventchain {

		////Base of an event handler
		template <class P_, class O_>
		struct EventHandler {
			Any data;

			EventHandler(Any data) : data(data) {}

			virtual void Fire(P_ params, O_ &caller, std::string eventname) const=0;

			virtual ~EventHandler() {}
		};

		//These template functions provide pseudo inheritance for these functions
		//every handler type must implement their of specialization
		template <class F_,class P_, class O_>
		EventHandler<P_, O_> *CreateEventHandler(F_ function, Any data) {
			return NULL;
		}
		template <class F_, class R_, class P_, class O_>
		EventHandler<P_, O_> *CreateEventHandler(R_ *object, F_ function, Any data) {
			return NULL;
		}

		template <class F_,class P_, class O_>
		bool Compare(EventHandler<P_, O_> *obj, F_ function) {
			return false;
		}
		template <class F_, class R_, class P_, class O_>
		bool Compare(EventHandler<P_,O_> *obj, R_ *object, F_ function) {
			return false;
		}
		template <class F_, class R_, class P_, class O_>
		bool Compare(EventHandler<P_,O_> *obj, R_ &object, F_ function) {
			return Compare(obj, &object, function);
		}



		////This is private event object that is used to
		/// store function event handlers
		template<class P_, class O_>
		struct EventHandlerFunction : public EventHandler<P_, O_> {
			void(*handler)(P_, O_ &, Any Data, std::string);

			EventHandlerFunction(void(*handler)(P_, O_ &, Any Data, std::string), Any data) : EventHandler<P_, O_>(data), handler(handler) {}

			virtual void Fire(P_ params, O_ &caller, std::string eventname) const {
				(*handler)(params, caller, EventHandler<P_, O_>::data, eventname);
			}

		};
		template <class P_, class O_>
		EventHandler<P_, O_> *CreateEventHandler( void(*function)(P_, O_ &, Any Data, std::string), Any data) {
			return new EventHandlerFunction<P_, O_>(function, data);
		}

		template <class P_, class O_>
		bool Compare(EventHandler<P_, O_> *obj, void(*function)(P_, O_ &, Any Data, std::string)) {
			if(!dynamic_cast<EventHandlerFunction<P_,O_>*>(obj))
				return false;

			return function==dynamic_cast<EventHandlerFunction<P_,O_>*>(obj)->handler;
		}
		////This is private event object that is used to
		/// store function event handlers
		template<class P_, class O_>
		struct EventHandlerFunctionPlain : public EventHandler<P_, O_> {
			void(*handler)(P_, O_ &);

			EventHandlerFunctionPlain(void(*handler)(P_, O_ &)) : EventHandler<P_, O_>(NULL), handler(handler) {}

			virtual void Fire(P_ params, O_ &caller, std::string eventname) const {
				(*handler)(params, caller);
			}

			bool Compare(void(*function)(P_, O_ &), void*) {
				if(handler==function)
					return true;
			}
		};

		template <class P_, class O_>
		EventHandler<P_, O_> *CreateEventHandler( void(*function)(P_, O_ &), Any data) {
			return new EventHandlerFunctionPlain<P_, O_>(function);
		}

		template <class P_, class O_>
		bool Compare(EventHandler<P_, O_> *obj, void(*function)(P_, O_ &)) {
			if(!dynamic_cast<EventHandlerFunctionPlain<P_,O_>*>(obj))
				return false;

			return function==dynamic_cast<EventHandlerFunctionPlain<P_,O_>*>(obj)->handler;
		}

		////This is private event object that is used to
		/// store function event handlers
		template<class P_, class O_>
		struct EventHandlerFunctionEmpty : public EventHandler<P_, O_> {
			void(*handler)();

			EventHandlerFunctionEmpty(void(*handler)()) : EventHandler<P_, O_>(Any()), handler(handler) {}

			virtual void Fire(P_ params, O_ &caller, std::string eventname) const {
				(*handler)();
			}

			bool Compare(void(*function)(), void*) {
				if(handler==function)
					return true;
			}
		};


		template <class P_, class O_>
		EventHandler<P_, O_> *CreateEventHandler( void(*function)(), Any data) {
			return new EventHandlerFunctionEmpty<P_, O_>(function);
		}
		template <class P_, class O_>
		bool Compare(EventHandler<P_, O_> *obj, void(*function)()) {
			if(!dynamic_cast<EventHandlerFunctionEmpty<P_,O_>*>(obj))
				return false;

			return function==dynamic_cast<EventHandlerFunctionEmpty<P_,O_>*>(obj)->handler;
		}
		////This is private event object that is used to
		/// store function event handlers
		template<class P_, class O_>
		struct EventHandlerFunctionObjectOnly : public EventHandler<P_, O_> {
			void(*handler)(O_ &);

			EventHandlerFunctionObjectOnly(void(*handler)(O_ &)) : EventHandler<P_, O_>(Any()), handler(handler) {}

			virtual void Fire(P_ params, O_ &caller, std::string eventname) const {
				(*handler)(caller);
			}

			bool Compare(void(*function)(O_ &), void*) {
				if(handler==function)
					return true;
			}
		};


		template <class P_, class O_>
		EventHandler<P_, O_> *CreateEventHandler( void(*function)(O_ &), Any data) {
			return new EventHandlerFunctionObjectOnly<P_, O_>(function);
		}
		template <class P_, class O_>
		bool Compare(EventHandler<P_, O_> *obj, void(*function)(O_ &)) {
			if(!dynamic_cast<EventHandlerFunctionObjectOnly<P_,O_>*>(obj))
				return false;

			return function==dynamic_cast<EventHandlerFunctionObjectOnly<P_,O_>*>(obj)->handler;
		}
		////This is private event object that is used to
		/// store function event handlers
		template<class P_, class O_>
		struct EventHandlerFunctionParamOnly : public EventHandler<P_, O_> {
			void(*handler)(P_);

			EventHandlerFunctionParamOnly(void(*handler)(P_)) : EventHandler<P_, O_>(Any()), handler(handler) {}

			virtual void Fire(P_ params, O_ &caller, std::string eventname) const {
				(*handler)(params);
			}

			bool Compare(void(*function)(P_), void*) {
				if(handler==function)
					return true;
			}
		};
		template <class P_, class O_>
		EventHandler<P_, O_> *CreateEventHandler( void(*function)(P_), Any data) {
			return new EventHandlerFunctionParamOnly<P_, O_>(function);
		}

		template <class P_, class O_>
		bool Compare(EventHandler<P_, O_> *obj, void(*function)(P_)) {
			if(!dynamic_cast<EventHandlerFunctionParamOnly<P_,O_>*>(obj))
				return false;

			return function==dynamic_cast<EventHandlerFunctionParamOnly<P_,O_>*>(obj)->handler;
		}
		////This is private event object that is used to
		/// store function event handlers
		template<class P_, class O_>
		struct EventHandlerFunctionDataOnly : public EventHandler<P_, O_> {
			void(*handler)(Any);

			EventHandlerFunctionDataOnly(void(*handler)(Any), Any data) : EventHandler<P_, O_>(data), handler(handler) {}

			virtual void Fire(P_ params, O_ &caller, std::string eventname) const {
				(*handler)(EventHandler<P_, O_>::data);
			}

		};
		template <class P_, class O_>
		EventHandler<P_, O_> *CreateEventHandler( void(*function)(Any Data), Any data) {
			return new EventHandlerFunctionDataOnly<P_, O_>(function, data);
		}

		template <class P_, class O_>
		bool Compare(EventHandler<P_, O_> *obj, void(*function)(Any Data)) {
			if(!dynamic_cast<EventHandlerFunctionDataOnly<P_,O_>*>(obj))
				return false;

			return function==dynamic_cast<EventHandlerFunctionDataOnly<P_,O_>*>(obj)->handler;
		}

		////This is private event object that is used to
		/// store function event handlers
		template<class P_, class O_>
		struct EventHandlerFunctionObjectAndData : EventHandler<P_, O_> {
			void(*handler)(O_ &, Any);

			EventHandlerFunctionObjectAndData(void(*handler)(O_ &, Any), Any data) : EventHandler<P_, O_>(data), handler(handler) {}

			virtual void Fire(P_ params, O_ &caller, std::string eventname) const {
				(*handler)(caller,EventHandler<P_, O_>::data);
			}

			bool Compare(void(*function)(O_ &, Any), void*) {
				if(handler==function)
					return true;
			}
		};

		template <class P_, class O_>
		EventHandler<P_, O_> *CreateEventHandler( void(*function)(O_ &, Any), Any data) {
			return new EventHandlerFunctionObjectAndData<P_, O_>(function,data);
		}
		template <class P_, class O_>
		bool Compare(EventHandler<P_, O_> *obj, void(*function)(O_ &, Any)) {
			if(!dynamic_cast<EventHandlerFunctionObjectAndData<P_,O_>*>(obj))
				return false;

			return function==dynamic_cast<EventHandlerFunctionObjectAndData<P_,O_>*>(obj)->handler;
		}

		////This is private event object that is used to
		/// store function event handlers
		template<class R_, class P_, class O_>
		struct EventHandlerClass : public EventHandler<P_,O_> {
			void(R_::*handler)(P_, O_ &, Any, std::string);

			R_ *object;

			EventHandlerClass(R_ *object, void(R_::*handler)(P_, O_ &, Any, std::string), Any data) : EventHandler<P_, O_>(data), object(object), handler(handler) {}

			virtual void Fire(P_ params, O_ &caller, std::string eventname) const {
				(object->*handler)(params, caller, EventHandler<P_,O_>::data, eventname);
			}

		};

		template <class R_, class P_, class O_>
		EventHandler<P_, O_> *CreateEventHandler(R_ *object, void(R_::*function)(P_, O_ &, Any, std::string), Any data) {
			return new EventHandlerClass<R_, P_, O_>(object, function, data);
		}
		template <class R_, class P_, class O_>
		bool Compare(EventHandler<P_,O_> *obj, R_ *object, void(R_::*function)(P_, O_ &, Any, std::string)) {
			if(!dynamic_cast<EventHandlerClass<R_, P_,O_>*>(obj))
				return false;

			return object==dynamic_cast<EventHandlerClass<R_, P_,O_>*>(obj)->object && function==dynamic_cast<EventHandlerClass<R_, P_,O_>*>(obj)->handler;
		}
		////This is private event object that is used to
		/// store function event handlers
		template<class R_, class P_, class O_>
		struct EventHandlerClassPlain : public EventHandler<P_,O_> {
			void(R_::*handler)(P_, O_ &);

			R_ *object;

			EventHandlerClassPlain(R_ *object, void(R_::*handler)(P_, O_ &)) : EventHandler<P_, O_>(Any()), object(object), handler(handler) {}

			virtual void Fire(P_ params, O_ &caller, std::string eventname) const {
				(object->*handler)(params, caller);
			}

			bool Compare(void(R_::*function)(P_, O_ &), void* object) {
				if((void*)handler==function && this->object==object)
					return true;
			}
		};



		template <class R_, class P_, class O_>
		EventHandler<P_, O_> *CreateEventHandler(R_ *object, void(R_::*function)(P_, O_ &), Any data) {
			return new EventHandlerClassPlain<R_, P_, O_>(object, function);
		}
		template <class R_, class P_, class O_>
		bool Compare(EventHandler<P_,O_> *obj, R_ *object, void(R_::*function)(P_, O_ &)) {
			if(!dynamic_cast<EventHandlerClassPlain<R_, P_,O_>*>(obj))
				return false;

			return object==dynamic_cast<EventHandlerClassPlain<R_, P_,O_>*>(obj)->object && function==dynamic_cast<EventHandlerClassPlain<R_, P_,O_>*>(obj)->handler;
		}
		////This is private event object that is used to
		/// store function event handlers
		template<class R_, class P_, class O_>
		struct EventHandlerClassEmpty : public EventHandler<P_,O_> {
			void(R_::*handler)();

			R_ *object;

			EventHandlerClassEmpty(R_ *object, void(R_::*handler)()) : EventHandler<P_, O_>(Any()), object(object), handler(handler) {}

			virtual void Fire(P_ params, O_ &caller, std::string eventname) const {
				(object->*handler)();
			}

			bool Compare(void(R_::*function)(), void* object) {
				if((void*)handler==function && this->object==object)
					return true;
			}
		};

		template <class R_, class P_, class O_>
		EventHandler<P_, O_> *CreateEventHandler(R_ *object, void(R_::*function)(), Any data) {
			return new EventHandlerClassEmpty<R_, P_, O_>(object, function);
		}
		template <class R_, class P_, class O_>
		bool Compare(EventHandler<P_,O_> *obj, R_ *object, void(R_::*function)()) {
			if(!dynamic_cast<EventHandlerClassEmpty<R_, P_,O_>*>(obj))
				return false;

			return object==dynamic_cast<EventHandlerClassEmpty<R_, P_,O_>*>(obj)->object && function==dynamic_cast<EventHandlerClassEmpty<R_, P_,O_>*>(obj)->handler;
		}
		////This is private event object that is used to
		/// store function event handlers
		template<class R_, class P_, class O_>
		struct EventHandlerClassObjectOnly : public EventHandler<P_,O_> {
			void(R_::*handler)(O_ &);

			R_ *object;

			EventHandlerClassObjectOnly(R_ *object, void(R_::*handler)(O_ &)) : EventHandler<P_, O_>(Any()), object(object), handler(handler) {}

			virtual void Fire(P_ params, O_ &caller, std::string eventname) const {
				(object->*handler)(caller);
			}

			bool Compare(void(R_::*function)(O_ &), void* object) {
				if((void*)handler==function && this->object==object)
					return true;
			}
		};

		template <class R_, class P_, class O_>
		EventHandler<P_, O_> *CreateEventHandler(R_ *object, void(R_::*function)(O_ &), Any data) {
			return new EventHandlerClassObjectOnly<R_, P_, O_>(object, function);
		}

		template <class R_, class P_, class O_>
		bool Compare(EventHandler<P_,O_> *obj, R_ *object, void(R_::*function)(O_ &)) {
			if(!dynamic_cast<EventHandlerClassObjectOnly<R_, P_,O_>*>(obj))
				return false;

			return object==dynamic_cast<EventHandlerClassObjectOnly<R_, P_,O_>*>(obj)->object && function==dynamic_cast<EventHandlerClassObjectOnly<R_, P_,O_>*>(obj)->handler;
		}
		////This is private event object that is used to
		/// store function event handlers
		template<class R_, class P_, class O_>
		struct EventHandlerClassParamOnly : public EventHandler<P_,O_> {
			void(R_::*handler)(P_);

			R_ *object;

			EventHandlerClassParamOnly(R_ *object, void(R_::*handler)(P_ )) : EventHandler<P_, O_>(Any()), object(object), handler(handler) {}

			virtual void Fire(P_ params, O_ &caller, std::string eventname) const {
				(object->*handler)(params);
			}

			bool Compare(void(R_::*function)(P_), void* object) {
				if((void*)handler==function && this->object==object)
					return true;
			}
		};


		template <class R_, class P_, class O_>
		EventHandler<P_, O_> *CreateEventHandler(R_ *object, void(R_::*function)(P_), Any data) {
			return new EventHandlerClassParamOnly<R_, P_, O_>(object, function);
		}
		template <class R_, class P_, class O_>
		bool Compare(EventHandler<P_,O_> *obj, R_ *object, void(R_::*function)(P_)) {
			if(!dynamic_cast<EventHandlerClassParamOnly<R_, P_,O_>*>(obj))
				return false;

			return object==dynamic_cast<EventHandlerClassParamOnly<R_, P_,O_>*>(obj)->object && function==dynamic_cast<EventHandlerClassParamOnly<R_, P_,O_>*>(obj)->handler;
		}
		////This is private event object that is used to
		/// store function event handlers
		template<class R_, class P_, class O_>
		struct EventHandlerClassDataOnly : public EventHandler<P_,O_> {
			void(R_::*handler)(Any);

			R_ *object;

			EventHandlerClassDataOnly(R_ *object, void(R_::*handler)(Any), Any data) : EventHandler<P_, O_>(data), object(object), handler(handler) {}

			virtual void Fire(P_ params, O_ &caller, std::string eventname) const {
				(object->*handler)(EventHandler<P_, O_>::data);
			}

			bool Compare(void(R_::*function)(Any), void* object) {
				if((void*)handler==function && this->object==object)
					return true;
			}
		};


		template <class R_, class P_, class O_>
		EventHandler<P_, O_> *CreateEventHandler(R_ *object, void(R_::*function)(Any), Any data) {
			return new EventHandlerClassDataOnly<R_, P_, O_>(object, function, data);
		}
		template <class R_, class P_, class O_>
		bool Compare(EventHandler<P_,O_> *obj, R_ *object, void(R_::*function)(Any)) {
			if(!dynamic_cast<EventHandlerClassDataOnly<R_, P_,O_>*>(obj))
				return false;

			return object==dynamic_cast<EventHandlerClassDataOnly<R_, P_,O_>*>(obj)->object && function==dynamic_cast<EventHandlerClassDataOnly<R_, P_,O_>*>(obj)->handler;
		}


#ifndef NOLAMBDA
		////This is private event object that is used to
		/// store function event handlers
		template<class P_, class O_>
		struct EventHandlerLambdaEmpty : public EventHandler<P_, O_> {
			std::function<void()> handler;

			EventHandlerLambdaEmpty(std::function<void()> handler) : EventHandler<P_, O_>(Any()), handler(handler) {}

			virtual void Fire(P_ params, O_ &caller, std::string eventname) const {
				(handler)();
			}

			bool Compare(std::function<void()> function, void*) {
				return false;
			}
		};


		template <class P_, class O_>
		EventHandler<P_, O_> *CreateEventHandler( std::function<void()> function, Any data) {
			return new EventHandlerLambdaEmpty<P_, O_>(function);
		}
		template <class P_, class O_>
		bool Compare(EventHandler<P_, O_> *obj, std::function<void()> function) {
			return false;
		}


		////This is private event object that is used to
		/// store function event handlers
		template<class P_, class O_>
		struct EventHandlerLambdaParamOnly : public EventHandler<P_, O_> {
			std::function<void(P_)> handler;

			EventHandlerLambdaParamOnly(std::function<void(P_)> handler) : EventHandler<P_, O_>(Any()), handler(handler) {}

			virtual void Fire(P_ params, O_ &caller, std::string eventname) const {
				(handler)(params);
			}

			bool Compare(std::function<void(P_)> function, void*) {
				return false;
			}
		};


		template <class P_, class O_>
		EventHandler<P_, O_> *CreateEventHandler( std::function<void(P_)> function, Any data) {
			return new EventHandlerLambdaParamOnly<P_, O_>(function);
		}
		template <class P_, class O_>
		bool Compare(EventHandler<P_, O_> *obj, std::function<void(P_)> function) {
			return false;
		}
#endif

	} }


	////EventChain class is used to create event objects
	/// that can be multi-handled. It is a template
	/// so an event definer can define parameters
	/// that can be used. Every event has an object
	/// that is the source of the event and a name
	/// for the event. This information is given
	/// in constructor.
	template<class O_=Empty, class P_=empty_event_params>
	class EventChain {
		template<class O2_, class P2_> friend class EventChain;
	public:

		typedef intptr_t Token;

		////Constructor
		///@Name	: Name of the event
		///@Object	: Source of the event
		EventChain(std::string Name,O_ *Object=NULL) :
		eventname(Name), object(Object)
		{ }

		////Constructor
		///@Name	: Name of the event
		///@Object	: Source of the event
		EventChain(O_ *Object=NULL) :
		eventname(""), object(Object)
		{ }

		////Constructor
		///@Name	: Name of the event
		///@Object	: Source of the event
		EventChain(std::string Name,O_ &Object) :
		eventname(Name), object(&Object)
		{ }

		////Constructor
		///@Name	: Name of the event
		///@Object	: Source of the event
		EventChain(O_ &Object) :
		eventname(""), object(&Object)
		{ }

		////Registers an event handler. Every event handler
		/// can specify EventHandler<P_, O_>::data to be passed to handler
		/// that can be used to identify who is registered
		/// the event. This function returns event token
		/// that can be used to remove this handler. The
		/// token is not an id or sequential number
		/// therefore, it should not be altered to find other
		/// handlers. Handler function template is
		/// void Handler(Parameters params, CallerObject* object, any EventHandler<P_, O_>::data, std::string eventname)
		///@handler	: handler function
		///@data	: data to be passed to handler
		template<class F_>
		Token Register(F_ *handler, Any data=Any()) {
			return AddHandler(
				prvt::eventchain::CreateEventHandler<P_, O_>(handler, data)
				);
		}


		////Registers a class event handler. This handler
		/// should be a non static function of
		/// the given object. Event handler
		/// can specify EventHandler<P_, O_>::data to be passed to handler
		/// that can be used to identify who is registered
		/// the event. This function returns event token
		/// that can be used to remove this handler. The
		/// token is not an id or sequential number
		/// therefore, it should not be altered to find other
		/// handlers. Handler function full template is
		/// void Handler(Parameters params, CallerObject* object, any EventHandler<P_, O_>::data, std::string eventname)
		/// EventParams parameters)
		///@receiver: handler object
		///@handler	: handler function
		///@data	: data to be passed to handler
		template<class R_, class F_>
		Token Register(R_ *receiver, F_ handler, Any data=Any()) {
			return AddHandler(
				prvt::eventchain::CreateEventHandler<R_, P_, O_>(receiver, handler, data)
				);
		}

		////Registers a class event handler. This handler
		/// should be a non static function of
		/// the given object. Event handler
		/// can specify data to be passed to handler
		/// that can be used to identify who is registered
		/// the event. This function returns event token
		/// that can be used to remove this handler. The
		/// token is not an id or sequential number
		/// therefore, it should not be altered to find other
		/// handlers. Handler function full template is
		/// void Handler(Parameters params, CallerObject* object, any data, std::string eventname)
		/// EventParams parameters)
		///@receiver: handler object
		///@handler	: handler function
		///@data	: EventHandler<P_, O_>::data to be passed to handler
		template<class R_, class F_>
		Token Register(R_ &receiver, F_ handler, Any data=Any()) {
			return Register(&receiver, handler, data);
		}

		template<class R_, class F_>
		Token RegisterClass(R_ *receiver, F_ handler, Any data=Any()) {
			return AddHandler(
				prvt::eventchain::CreateEventHandler<R_, P_, O_>(receiver, handler, data)
				);
		}

		template<class R_, class F_>
		Token RegisterClass(R_ &receiver, F_ handler, Any data=Any()) {
			return RegisterClass(receiver, handler, data);
		}

#ifndef NOLAMBDA
		template <class F_>
		typename count_arg<F_, 0, Token>::type RegisterLambda(F_ handler) {
			return AddHandler(
				prvt::eventchain::CreateEventHandler<P_, O_>(std::function<void()>(handler), Any())
				);
		}
		template <class F_>
		typename count_arg<F_, 1, Token>::type RegisterLambda(F_ handler) {
			return AddHandler(
				prvt::eventchain::CreateEventHandler<P_, O_>(std::function<void(P_)>(handler), Any())
				);
		}
#endif

		template<class R_>
		Token LinkTo(EventChain<R_, P_> &target) {
			return AddHandler(
				prvt::eventchain::CreateEventHandler<EventChain<R_, P_>, P_, O_>(
				&target,
				(void(EventChain<R_,P_>::*)(P_))&EventChain<R_, P_>::firethis,
				Any()
				)
				);
		}

		template<class R_>
		Token DoubleLink(EventChain<R_, P_> &target) {
			typedef void(EventChain<O_,P_>::*MyFire		)(P_) ;
			typedef void(EventChain<R_,P_>::*TargetFire )(P_);
			typedef EventChain<R_, P_> targettype;

			target.RegisterClass< EventChain<O_, P_>, MyFire >(
				this,
				(MyFire) &EventChain<O_, P_>::linkedfire<R_>,
				Any()
			);

			return AddHandler(
				prvt::eventchain::CreateEventHandler<EventChain<R_, P_>, P_, O_>(
					&target,
					(TargetFire)&targettype::template linkedfire<O_>,
					Any()
				)
			);
		}

		////Unregisters the given event handler using handler function
		template<class F_>
		void Unregister(F_ handler) {
			for(auto it = events.First();
				it.IsValid();it.Next()) {
				if(prvt::eventchain::Compare(&(*it), handler)) {
					it.Delete();
				}
			}
		}

		////Unregisters the given handler referenced by the object and function
		template<class R_, class F_>
		void Unregister(R_ *obj, F_ handler) {
			for(auto it = events.First();
				it.IsValid();it.Next()) {
					if(prvt::eventchain::Compare<R_, P_, O_>(&(*it), obj, handler)) {
						it.Delete();
					}
			}
		}

		template<class R_, class F_>
		void UnregisterClass(R_ &obj, F_ handler) {
			Unregister(&obj, handler);
		}

		////Unregisters the given handler referenced by the object and function
		template<class R_, class F_>
		void UnregisterClass(R_ *obj, F_ handler) {
			Unregister<R_, F_>(obj,handler);
		}

		////Unregisters the given handler referenced by the object and function
		template<class R_, class F_>
		void Unregister(R_ &obj, F_ handler) {
			Unregister(&obj, handler);
		}

		////Unregisters a given handler token
		void Unregister(Token token) {
			events.Delete(reinterpret_cast< prvt::eventchain::EventHandler<P_,O_>* >(token));
		}

		////This function triggers the event causing all
		/// handlers to be called
		void operator()(P_ params) const {
			Fire(params);
		}

		////This function triggers the event causing all
		/// handlers to be called
		void operator()() const {
			Fire();
		}

		////This function triggers the event causing all
		/// handlers to be called
		void firethis(P_ params) const {
			for(auto it = events.First();
				it.IsValid();it.Next()) {
				it->Fire(params, *this->object, eventname);
			}
		}

		////This function triggers the event causing all
		/// handlers to be called
		void Fire(P_ params) const {
			for(auto it = events.First();
				it.IsValid();it.Next()) {
				it->Fire(params, *this->object, eventname);
			}
		}

		////This function triggers the event causing all
		/// handlers to be called
		void Fire() const {
			Fire(P_());
		}

		void Clear() {
			events.Destroy();
		}

		const std::string &GetName() const { return eventname; }

		~EventChain() {
			events.Destroy();
		}

	protected:
		////Name of the event
		std::string eventname;
		////Source of the events
		O_ *object;
		////Collection of event handlers
		Collection<prvt::eventchain::EventHandler<P_,O_>, 5 > events;

		Token AddHandler(prvt::eventchain::EventHandler<P_, O_> *object) {
			events.Add(object);

			return reinterpret_cast<Token>(object);

		}


	private:
		//copy constructor is disabled
		EventChain(const EventChain<O_, P_> &);

		//assignment operator is disabled
		EventChain<O_,P_> operator =(const EventChain<O_, P_> &);

		template<class R_>
		bool checklinkedfire(prvt::eventchain::EventHandler<P_, O_> *object) {
			prvt::eventchain::EventHandlerClassParamOnly<EventChain<R_, P_>, P_, O_> *obj=dynamic_cast<prvt::eventchain::EventHandlerClassParamOnly<EventChain<R_, P_>, P_, O_> *>(object);

			if(obj!=NULL) {
				if(typeid(obj->object)==typeid(EventChain<R_>*) && obj->handler == &EventChain<R_>::template linkedfire<O_>)
					return true;
			}

			return false;
		}

		template<class R_>
		void linkedfire(P_ params) {
			for(auto it = events.First();
				it.IsValid();it.Next()) {
				if(!checklinkedfire<R_>(it.CurrentPtr()))
					it->Fire(params, *this->object, eventname);
			}
		}

	};
} }

mercurial