// ------------------------------------------------------------------------------------ //
//																						//
//	File: Asura_GUIMenu_Widget_TextListBox.h												//
//																						//
//	Description: ListBox widget class													//
//																						//
//	Created: Steve Keen - 9/11/06														//
//																						//
//	Copyright (C) 2006 Rebellion (Derby), All Rights Reserved.							//
// ------------------------------------------------------------------------------------ //

#ifndef __ASURA_GUIMENU_WIDGET_TEXTLISTBOX_H__
#define __ASURA_GUIMENU_WIDGET_TEXTLISTBOX_H__

#ifdef ASURA_USE_PRAGMA_ONCE
#pragma once
#endif

#ifdef ASURA_USE_GUI_MENU_SYSTEM

#include "GUIMenu/Asura_GUIMenu_Widget_Base.h"
#include "GUIMenu/Asura_GUIMenu_Element_Text.h"
#include "GUIMenu/Asura_GUIMenu_CommandManager.h"

// -- Typedef -------------------------------------------------------------------------

// -- Enums ---------------------------------------------------------------------------
enum Asura_GUIMenu_TextListBox_Message
{
	ASURA_GUIMENU_TEXTLISTBOX_NONE = 0,
	ASURA_GUIMENU_TEXTLISTBOX_CLEAR,
	ASURA_GUIMENU_TEXTLISTBOX_GET_SELECTION_INDEX,
	ASURA_GUIMENU_TEXTLISTBOX_SET_SELECTION_INDEX,
	ASURA_GUIMENU_TEXTLISTBOX_ADD_TEXT,
	ASURA_GUIMENU_TEXTLISTBOX_GET_TEXT,
	ASURA_GUIMENU_TEXTLISTBOX_ADD_TEXTHASH,
	ASURA_GUIMENU_TEXTLISTBOX_GET_TEXTHASH,
	ASURA_GUIMENU_TEXTLISTBOX_SET_IMAGE,
	ASURA_GUIMENU_TEXTLISTBOX_GET_IMAGE,
	ASURA_GUIMENU_TEXTLISTBOX_END_OF_MESSAGES
};
// -- Defines -------------------------------------------------------------------------
#define ASURA_GUIMENU_MAX_LISTBOX_ENTRIES 10

#define fASURA_GUIMENU_WIDGET_TEXTLISTBOX_FLASH_TIME_DEFAULT	(0.1f)
#define fASURA_GUIMENU_WIDGET_TEXTLISTBOX_CONTROL_INITIAL_REPEAT_DELAY			( 0.5f)
#define fASURA_GUIMENU_WIDGET_TEXTLISTBOX_CONTROL_SECONDARY_REPEAT_DELAY		( 0.2f)

#define ASURA_GUIMENU_WIDGET_TEXTLISTBOX_LOCAL_FLAG_START	16

enum Asura_GUIMenu_TextListBox_Render_Flag
{
	ASURA_GUIMENU_TEXTLISTBOX_SCALE_ON_PARENT_RESIZE     = 0x00008000,
};


/*
Versions: ASURA_CHUNK_ELEMENT_LISTBOX_VERSION

0:	Initial data - SK 5.12.06
1:	Added text render flags - SK 21.2.07
2:	Added command manager - SK 26.2.07
3:	Added population function - MH 12.3.07
4:  Added hashes for Inc/Dec icons(Image elements hash ids) - SK
5:  added button press auto-repeat vars - SK
6:  added text scroll rate - RM 17.05.07
7:  added font scale - NDB 09.04.08
8:	added init value var - NY 18.07.08
9:	added scroll bar - NY 16.01.08
10:	moved size data up to root - NY 01/08/2008
*/
#define ASURA_CHUNK_WIDGET_TEXTLISTBOX_VERSION	10


// -- Structures ----------------------------------------------------------------------

// -- Class ---------------------------------------------------------------------------
class Asura_GUIMenu_Element_Base;
class Asura_GUIMenu_Element_Image;
class Asura_GUIMenu_Element_Path;

class Asura_GUIMenu_Widget_TextListBox : public Asura_GUIMenu_Widget_Base
{
	// -- Functions -----------------------------------------------------------------------
public:
	friend class Asura_Chunk_GUIMenu;			// for access to m_xCommand; until we have ReadFromChunkStream() member.
	friend class Tools_GUIMenu_Widget_TextListBox;	// for access to m_xCommand when creating tools dialog.

	enum Asura_GUIMenu_Inherit_Flag_Widget_ListBox_Type
	{
		ASURA_GUIMENU_WIDGET_TEXTLISTBOX_LOCAL_FLAG_WIDTH				 = (1<<(ASURA_GUIMENU_WIDGET_TEXTLISTBOX_LOCAL_FLAG_START+0)),
		ASURA_GUIMENU_WIDGET_TEXTLISTBOX_LOCAL_FLAG_HEIGHT				 = (1<<(ASURA_GUIMENU_WIDGET_TEXTLISTBOX_LOCAL_FLAG_START+1)),
		ASURA_GUIMENU_WIDGET_TEXTLISTBOX_LOCAL_FLAG_MAX_ALLOWED_ENTRIES = (1<<(ASURA_GUIMENU_WIDGET_TEXTLISTBOX_LOCAL_FLAG_START+2)),
		ASURA_GUIMENU_WIDGET_TEXTLISTBOX_LOCAL_FLAG_MAX_DISPLAY_ENTRIES = (1<<(ASURA_GUIMENU_WIDGET_TEXTLISTBOX_LOCAL_FLAG_START+3)),
		ASURA_GUIMENU_WIDGET_TEXTLISTBOX_LOCAL_FLAG_RENDER_FLAGS		= (1<<(ASURA_GUIMENU_WIDGET_TEXTLISTBOX_LOCAL_FLAG_START+4)),
		ASURA_GUIMENU_WIDGET_TEXTLISTBOX_LOCAL_FLAG_FLASH_DETAILS		= (1<<(ASURA_GUIMENU_WIDGET_TEXTLISTBOX_LOCAL_FLAG_START+5)),
		ASURA_GUIMENU_WIDGET_TEXTLISTBOX_LOCAL_FLAG_CONTROL_REPEAT		= (1<<(ASURA_GUIMENU_WIDGET_TEXTLISTBOX_LOCAL_FLAG_START+6)),
		ASURA_GUIMENU_WIDGET_TEXTLISTBOX_LOCAL_FLAG_FONT				= (1<<(ASURA_GUIMENU_WIDGET_TEXTLISTBOX_LOCAL_FLAG_START+7)),
		ASURA_GUIMENU_WIDGET_TEXTLISTBOX_LOCAL_FLAG_POPULATION_FUNCTION	= (1<<(ASURA_GUIMENU_WIDGET_TEXTLISTBOX_LOCAL_FLAG_START+8)),
		ASURA_GUIMENU_WIDGET_TEXTLISTBOX_LOCAL_FLAG_COMMAND_MANAGER		= (1<<(ASURA_GUIMENU_WIDGET_TEXTLISTBOX_LOCAL_FLAG_START+9)),

		//ASURA_GUIMENU_WIDGET_BUTTON_OVERIDE_MAX is here to stop another programmer adding past bit flag 31
		ASURA_GUIMENU_WIDGET_TEXTLISTBOX_INHERIT_FLAG_MAX				 = (1<<(ASURA_GUIMENU_WIDGET_TEXTLISTBOX_LOCAL_FLAG_START+15))
	};

	Asura_GUIMenu_Widget_TextListBox();
	virtual ~Asura_GUIMenu_Widget_TextListBox();

	virtual void 				Update( float fElapsedTime);
	virtual void 				Render( u_int uState);
	virtual void				Copy( const Asura_GUIMenu_Root* pxSource);

	virtual void				Resize( const Asura_Bounding_Rectangle& xBounds );

	virtual u_int				ProcessInputActivity( const Asura_GUIMenu_Input& xInput);

	//Does a recursive search for a selectable widget at the given location
	virtual Asura_GUIMenu_Widget_Base*  FindSelectableWidgetAtPos(const Asura_Vector_2& xPos);
	virtual Asura_GUIMenu_Root* GetResizeChild( const u_int u );
	virtual u_int GetResizeChildCount() const;

	// -- UI Message handler functions --
	virtual bool				OnInit( const Asura_Message_GUIMenu_Notify* pxMessage);
	virtual bool				OnDeInit( const Asura_Message_GUIMenu_Notify* pxMessage);
	virtual bool				OnDataChange( const Asura_Message_GUIMenu_Notify* pxMessage);
	virtual bool				OnDataRequest( const Asura_Message_GUIMenu_Notify* pxMessage);
	virtual bool				OnClicked( const Asura_Message_GUIMenu_Notify* pxMessage);
	virtual bool				OnRollIn( const Asura_Message_GUIMenu_Notify* pxMessage);
	virtual bool				OnRollOut( const Asura_Message_GUIMenu_Notify* pxMessage);
	virtual bool				OnEnable( const Asura_Message_GUIMenu_Notify* pxMessage);

	u_int						GetSelectedIndex( void) const	{	return m_uSelectedIndex; }
	u_int*						GetSelectedIndexPtr( void)		{	return &m_uSelectedIndex; }
	void						SetSelectedIndex( u_int uSelected, bool bFocus=true);

	void						SetMaxAllowedEntries( u_int uMaxEntries);
	u_int						GetMaxAllowedEntries( void) const;
    
	void						SetMaxDisplayedEntries( u_int uMaxDisplayedEntries);
	u_int						GetMaxDisplayedEntries( void) const;

	void						SetEntryHeight( float fHeight)	{	m_fEntryGapY = fHeight;	}
	float						GetEntryHeight( void)	{	return m_fEntryGapY;	}

	virtual void				FocusOnSelected();

	virtual void				SetUnscaledLocalBounds( const Asura_Bounding_Rectangle& xBounds );

	void						SetFontByName( const Asura_String& xFontName) {SetFontByName(xFontName.GetString());}
	void						SetFontByName( const char* szFontName);
	const	Asura_String		GetFontName( void) const;

	void						SetFontScale( const float fScale ) { m_fFontScale = fScale; }
	float						GetFontScale() const { return m_fFontScale; }

	bool						GetTextRenderFlag( u_int uFlag) const;
	void						SetTextRenderFlag( u_int uFlagsToSet, bool bFlagSet);
	u_int						GetTextRenderFlags( void) const;
	void						SetTextRenderFlags( u_int uFlags)	  {	m_uTextRenderFlags = uFlags; }
	float						GetTextScrollRate( void) const		  { return m_fTextScrollRate; }
	void						SetTextScrollRate( float fScrollRate) { m_fTextScrollRate = fScrollRate; }

	const Asura_GUIMenu_Element_Image* GetDecImage( void) const;
	void						SetDecImage( Asura_GUIMenu_Element_Image* pxDecImage);

	const Asura_GUIMenu_Element_Image* GetIncImage( void) const;
	void						SetIncImage( Asura_GUIMenu_Element_Image* pxDecImage);

	const Asura_GUIMenu_Element_Path* GetScrollBar( void) const;
	void						SetScrollBar( Asura_GUIMenu_Element_Path* pxScrollBar);

	const Asura_RGBA			GetFlashColour( void) const;
	void						SetFlashColour( float fRed, float fGreen, float fBlue, float fAlpha);
	void						SetFlashColour( u_int uRGBAColourValue);

	void						SetFlashTime( float fFlashTime);
	float						GetFlashTime( void) const;

	u_int						GetEntryCount( void) const {	return m_uEntryCount;	}

	void						StartDecrementFlash( void);
	void						StartIncrementFlash( void);

	float						GetInitialControlRepeatDelay( void) const	{	return m_fInitialRepeatDelay;	}
	void						SetInitialControlRepeatDelay( float fDelay)	{	m_fInitialRepeatDelay = fDelay;	}
	float						GetSecondaryControlRepeatDelay( void) const {	return m_fSecondaryRepeatDelay;	}
	void						SetSecondaryControlRepeatDelay( float fDelay)	{	m_fSecondaryRepeatDelay = fDelay;	}

#ifdef ASURA_TOOLS
	virtual void				UpdateLocalDataFromStyle( void);
	virtual void				WriteToChunkStream( Asura_Chunk_Stream& xStream) const;
	virtual void				ExportToXML(Tools_GUIMenu_XMLExporter* pxExporter) const;
	
	void						ClearTextRenderFlags( void);

#endif // ASURA_TOOLS

	virtual void				ReadFromChunkStream( Asura_Chunk_Stream& xStream, Asura_GUIMenu_Root* pxParentObject, u_int uChunkVersion);

	virtual bool				RemoveFromThisContainer( Asura_GUIMenu_Root* pxObject);

protected:
	void						SetupDefaultElements( void);

	void						AddTextElement( const Asura_UnicodeChar* pszTextString );
	static void					AddTextElementCallback( const Asura_UnicodeChar* pszTextString );

	void						ClearAllEntries( void);

	void						UpdateEntryObjectBounds( void);
	void						CheckAndClipObjectBounds( const Asura_Bounding_Rectangle& xParentBounds, Asura_Bounding_Rectangle& xChildBounds);


private:

	void						AllocateEntryList( u_int uNewListSize, u_int uOldListSize);
	void 						DeAllocateEntryList( void);

	void						UpdateIcons( void);
	void						UpdateFlashingElements( void);

	bool						HandleInputAutoRepeat( bool bHeldValue);

	// -- Variables -----------------------------------------------------------------------
public:

protected:

private:

	// member data
	float							m_fElapsedTime;

	u_int							m_uButtonRepeatPhase;
	float							m_fCurrentRepeatDelay;
	float							m_fInitialRepeatDelay;
	float							m_fSecondaryRepeatDelay;

	Asura_GUIMenu_Element_Text*		m_pxEntries;
	Asura_Bounding_Rectangle*		m_pxBoundingRects;

	Asura_GUIMenu_Element_Image*	m_pxDecImage;
	Asura_GUIMenu_Element_Image*	m_pxIncImage;
	Asura_GUIMenu_Element_Path*		m_pxScrollBar;
	bool							m_bDragging;

	Asura_RGBA						m_xFlashColour;
	float							m_fDecFlashTimerCountdown;
	float							m_fIncFlashTimerCountdown;
	float							m_fFlashTimerStartVal;

	u_int							m_uEntryCount;

	u_int							m_uSelectedIndex;
	u_int							m_uOldSelectedIndex;
	float							m_fDisplayListOffsetY;
	float							m_fDisplayTargetOffsetY;
	float							m_fMoveDir;

	u_int							m_uMaxAllowedEntries;
	u_int							m_uMaxDisplayedEntries;
	float							m_fEntryGapY;

	Asura_String					m_xFontName;
	float							m_fFontScale;
	float							m_fTextScrollRate;
	u_int							m_uTextRenderFlags;

	bool							m_bDirtyRect;

	bool							m_bFadeUp;
	float							m_fFadeAmount;
	Asura_GUIMenu_ConsoleVar		m_xInitValueVar;

	Asura_GUIMenu_CommandManager	m_xCommandManager;		// commands executed on accept button presses
	Asura_GUIMenu_ConsoleCmd		m_xPopulationFunction;	// command to execute to get text for each item. should return false when index >= num items.

	// static class data
	static Asura_GUIMenu_Widget_TextListBox* s_pxThis;			// for callback function

	typedef Asura_GUIMenu_Widget_Base PARENT;
};
#endif // ASURA_USE_GUI_MENU_SYSTEM
#endif // __ASURA_GUIMENU_WIDGET_TEXTLISTBOX_H__
