⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 eventrouter.h

📁 设计模式模板源码
💻 H
字号:
#ifndef _XP_EVENTROUTER_H__
#define _XP_EVENTROUTER_H__

#include "..\CppIface.h"
#include "..\Events\Event.h"
#include "..\Events\EventListener.h"


///////////////////////////////////////////////////////////////////////////
// IEventRouter

//@doc IEventRouter
//@mfunc XPBool | IEventRouter | RouteEvent | Routes event objects to event listeners.
//@rdesc TRUE if at least one listener handled the event.
//@parm IEvent* | pIEvent | Pointer to event object.

//@doc IEventRouter
//@mfunc XPBool | IEventRouter | AddListener | Add an event listener to the router.
//@rdesc TRUE if successful, otherwise FALSE.
//@parm IEventListener* | pIListener | Pointer to event listener to add.

//@doc IEventRouter
//@mfunc XPBool | IEventRouter | RemoveListener | Remove an event listener from the router.
//@rdesc TRUE if successful, otherwise FALSE.
//@parm IEventListener* | pIListener | Pointer to event listener to remove.

//@class IEventRouter | Interface for routing events to event listeners.
// The RouteEvent method takes a pointer to an event and returns TRUE if
// the event was handled by one or more listeners or FALSE if the event
// was not handled.

//@base public | IRefCount
//@base public | IQueryGuid

#define XP_IEVENTROUTER_IID     \
{ 0x8a189178, 0xb5e8, 0x4c7e, { 0x97, 0xfc, 0xa2, 0x2e, 0x57, 0x7, 0xe6, 0x5f } };

class IEventRouter : public IRefCount, public IQueryGuid
{
public:
	//@cmember
	/* Routes event objects to event listeners. */
	virtual XPBool RouteEvent(IEvent* pIEvent) = 0;
	//@cmember
	/* Add an event listener to the router. */
	virtual XPBool AddListener(IEventListener* pIListener) = 0;
	//@cmember
	/* Remove an event listener from the router. */
	virtual XPBool RemoveListener(IEventListener* pIListener) = 0;

	XP_IMPL_IID(XP_IEVENTROUTER_IID)
};

///////////////////////////////////////////////////////////////////////////
//@doc IEventRouterImpl
//
//@class IEventRouterImpl | Provides a default implementation of the
// <c IEventRouter> interface. This class maintains a list of event
// listeners and implements <mf IEventRouterImpl::RouteEvent> by iterating
// over the listeners and calling <mf IEventListener::HandleEvent>.
//
//@base public | IEventRouter

class IEventRouterImpl : public IEventRouter
{
// Constructors/destructor
public:
	virtual ~IEventRouterImpl()
	{
		while (m_listeners.size() > 0)
		{
			IEventListener* pIListener = m_listeners.back();
			pIListener->Release();
			m_listeners.pop_back();
		}
	}

// Attributes
protected:
	//@cmember
	/* Array of event listeners*/
	ListenerVector m_listeners;

// Operations
public:
	//@cmember,mfunc Cast object to a pointer type given a GUID.
	//@@rdesc XP_TRUE if object is successfully cast to the new data type, otherwise XP_FALSE.
	//@@parm XPREFIID | guid | Input GUID that determines the data type to cast to.
	//@@parm void ** | ppvObj | Output parameter to receive the result of the cast.
	//@@end
	/* Cast object to a pointer type given a GUID*/
	virtual XPBool QueryGuid(XPREFIID guid, void **ppvObj)
	{
		XPBool bResult = XP_FALSE;
		*ppvObj = 0;

		if (guid == IEventRouter::IID())
		{
			*ppvObj = static_cast<IEventRouter*>(this);
			bResult = XP_TRUE;
		}

		return bResult;
	}

	//@cmember,mfunc
	// Add a reference to this object.
	//@@rdesc New reference count value.
	//@@comm This is a no-op implementation. Derived classes must
	// override in order to provide reference counting.
	//@@end
	/* Add a reference to this object*/
	XPUint32 XPSTDMETHODCALLTYPE AddRef()
	{
		return 1;
	}

	//@cmember,mfunc
	// Release a reference to this object.
	//@@rdesc New reference count value.
	//@@comm This is a no-op implementation. Derived classes must
	// override in order to provide reference counting.
	//@@end
	/* Release a reference to this object*/
	XPUint32 XPSTDMETHODCALLTYPE Release()
	{
		return 1;
	}

	//@cmember,mfunc
	// Routes event objects to event listeners.
	//@@rdesc TRUE if at least one listener handled the event.
	//@@parm IEvent* | pIEvent | Pointer to event object.
	//@@end
	/* Routes event objects to event listeners*/
	virtual XPBool RouteEvent(IEvent* pIEvent)
	{
		int nHandledCount = 0;

		if (pIEvent != 0)
		{
			ListenerVector::const_iterator itListener;

			//
			// Give each event listener a chance to handle the event.
			//
			for (itListener = m_listeners.begin(); itListener != m_listeners.end(); itListener++)
			{
				if ((*itListener)->HandleEvent(pIEvent))
				{
					nHandledCount++;
				}
			}
		}

		return (nHandledCount > 0);
	}

	//@cmember,mfunc
	// Add an event listener to the router.
	//@@rdesc TRUE if successful, otherwise FALSE.
	//@@parm IEventListener* | pIListener | Pointer to event listener to add.
	//@@end
	/* Add an event listener to the router*/
	virtual XPBool AddListener(IEventListener* pIListener)
	{
		if (pIListener != 0)
		{
			pIListener->AddRef();
			m_listeners.push_back(pIListener);
			return XP_TRUE;
		}
		return XP_FALSE;
	}

	//@cmember,mfunc
	// Remove an event listener from the router.
	//@@rdesc TRUE if successful, otherwise FALSE.
	//@@parm IEventListener* | pIListener | Pointer to event listener to remove.
	//@@end
	/* Remove an event listener from the router*/
	virtual XPBool RemoveListener(IEventListener* pIListener)
	{
		ListenerVector::iterator itListener = m_listeners.begin();
		while (itListener != m_listeners.end())
		{
			if (pIListener == *itListener)
			{
				(*itListener)->Release();
				m_listeners.erase(itListener);
				return XP_TRUE;
			}
			else
			{
				itListener++;
			}
		}
		return XP_FALSE;
	}
};

///////////////////////////////////////////////////////////////////////////
//@doc CComboRouterListener
//
//@class CComboRouterListener | Implements HandleEvent method for a
// combined router and listener object.
//
//@tcarg class | base_t | Base class to override. Must be derived from both <c IEventListener>
// and <c IEventRouter>
//
//@base public | base_t

template <class base_t>
class CComboRouterListener : public base_t
{
public:
	//@cmember,mfunc
	// Receive an event and attempt to handle it.
	//@@rdesc TRUE if successful, otherwise FALSE.
	//@@parm IEvent* | pIEvent | Pointer to event to handle.
	//@@comm This function first attempts to dispatch the event onto
	// the base class, since it is an event listener. If the event
	// isn't handle, it then calls RouteEvent.
	//@@end
	/* Receive an event and attempt to handle it*/
	virtual XPBool HandleEvent(IEvent* pIEvent)
	{
		XPBool bHandled = XP_FALSE;

		if (pIEvent != 0)
		{
			bHandled = pIEvent->Dispatch(guid_cast<IEventRouter*>(this));
		}

		if (!bHandled)
			bHandled = base_t::RouteEvent(pIEvent);

		return bHandled;
	}
};

///////////////////////////////////////////////////////////////////////////
//@doc CListeningRouter
//
//@class CListeningRouter | Mixes in IEventListener into an event router
// and implements HandleEvent method.
//
//@tcarg class | base_t | Base class to override. Must be derived from <c IEventRouter>
//
//@base public | base_t
//@base public | IEventListener

template <class base_t>
class CListeningRouter : public base_t, public IEventListener
{
public:
	//@cmember,mfunc
	// Receive an event and attempt to handle it.
	//@@rdesc TRUE if successful, otherwise FALSE.
	//@@parm IEvent* | pIEvent | Pointer to event to handle.
	//@@comm This function first attempts to dispatch the event onto
	// the base class, since it is an event listener. If the event
	// isn't handle, it then calls RouteEvent.
	//@@end
	/* Receive an event and attempt to handle it*/
	virtual XPBool HandleEvent(IEvent* pIEvent)
	{
		XPBool bHandled = XP_FALSE;

		if (pIEvent != 0)
		{
			bHandled = pIEvent->Dispatch(guid_cast<IEventRouter*>(this));
		}

		if (!bHandled)
			bHandled = base_t::RouteEvent(pIEvent);

		return bHandled;
	}

	BEGIN_GUID_MAP(CListeningRouter<base_t>)
		GUID_ENTRY(IEventListener)
		GUID_CHAIN_ENTRY(base_t)
	END_GUID_MAP

	XPUint32 XPSTDMETHODCALLTYPE AddRef()
	{
		return base_t::AddRef();
	}

	XPUint32 XPSTDMETHODCALLTYPE Release()
	{
		return base_t::Release();
	}
};


#endif  // #ifndef _XP_EVENTROUTER_H__

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -