/*****************************************************************************
 * $Id: gfx_event2.hh,v 1.6 2006/11/04 00:02:56 devel Exp $
 * @file
 * @author	Jim E. Brooks  http://www.jimbrooks.org
 * @brief	To be included only by gfx_event.hh.
 *//*
 * LEGAL:	COPYRIGHT (C) 2004 JIM E. BROOKS
 *          THIS SOURCE CODE IS RELEASED UNDER THE TERMS
 *          OF THE GNU GENERAL PUBLIC LICENSE (GPL).
 *****************************************************************************/


////////////////////////////////////////////////////////////////////////////////
/// @brief Event class (with/out object broadcasting, preprocessed).
/// @remarks See comments in gfx_event.hh.
GFX_EVENT_TEMPLATE_CLASS
{
public:
	typedef void (*ListenerFunc)( GFX_EVENT_T_OBJ );

	/// Constructor.
	Event( void )
	{
		mListenerCnt = 0;
		// Clearing mListeners[] isn't necessary.
	}

	/// Add or remove a listener.
	void Listen( ListenerFunc listener, bool listen )
	{
		if ( listen )
			Listen( listener );
		else
			Ignore( listener );
	}

	/// Add a listener.
	void Listen( ListenerFunc listener )
	{
		// Append to array.
		ASSERT( mListenerCnt < GFX_EVENT_MAX_LISTENERS );
		mListeners[mListenerCnt++] = listener;
	}

	/// Remove a listener.
	void Ignore( ListenerFunc listener )
	{
    if ( UX(gExitingGfx) ) return;  // in case Event object is static

		// Find and nullify listener.
		ASSERT( mListenerCnt < GFX_EVENT_MAX_LISTENERS );
		for ( uint i = 0; i < mListenerCnt; ++i )
		{
			if ( mListeners[i] == listener )
			{
				mListeners[i] = NULL;
				// continue in case of duplicates
			}
		}
	}

	/// Broadcast an object to all listeners.
	void Broadcast( GFX_EVENT_T_OBJ )
	{
    if ( UX(gExitingGfx) ) return;  // in case Event object is static

		// Short-circuit for single listener case.
		if ( EX( mListenerCnt == 1 && mListeners[0] ) )
		{
			mListeners[0]( GFX_EVENT_OBJ ); // obtuse function call
			return;
		}

		// Skip inactive listeners.
		ASSERT( mListenerCnt < GFX_EVENT_MAX_LISTENERS );
		for ( uint i = 0; i < mListenerCnt; ++i )
			if ( mListeners[i] )
				mListeners[i]( GFX_EVENT_OBJ ); // obtuse function call
	}

private:
	ListenerFunc	mListeners[GFX_EVENT_MAX_LISTENERS];	///< array of function pointers
	uint			mListenerCnt;							///< count of listeners (active or not)
};
