/*********************************************************************
*	GFG - GUI For Games
*	HEADER FILE
*	Autor:	Michal Jirouš
*	Datum: 30.6.2008
*	Soubor: gfg.h
*	Popis:	GFG realizuje uživatelské rozhraní vytvořené nad API OpenGL
*			a je vhodné pro použití ve hrách. Implementuje standardní prvky
*			jako jsou tlačítka, popisky, jednoduché textové pole, ukazatel
*			průběhu. Dále několik různých kontejnerů, do kterých lze prvky
*			umístit velice jednoduše. Rozhraní umožňuje jednoduché animace 
*			a dovoluje měnit velikost a pozici oken. Pro podrobnější popis
*			celého API si přečtěte Text projektu.
**********************************************************************/

#ifndef __GFG_H__
#define __GFG_H__

#include <iostream>
#include <list>

#include "fonts.h"
using namespace std;

#include "colors.h"
#include <time.h>

/* Předdeklarace některých tříd */
class CBaseComponent;
class CSubWindow;
class CMessageBox;
class CMainWindow;
class Button;
class Image;

//const int	TRUE	=	1;
//const int	FALSE	=	0;

/* Ovladani klavesnice */
const int	GFG_KEYBOARD_UP		=	1;
const int	GFG_KEYBOARD_DOWN	=	2;
const int	GFG_SPECIAL_KEY_UP	=	4;
const int	GFG_SPECIAL_KEY_DOWN=	8;
const int	GFG_KEYBOARD		=	GFG_KEYBOARD_UP | GFG_KEYBOARD_DOWN | GFG_SPECIAL_KEY_UP | GFG_SPECIAL_KEY_DOWN;

/* Ovladani mysi */
const int	GFG_MOUSE_BUTTON	=	16;
const int	GFG_MOUSE_MOTION	=	32;
const int	GFG_MOUSE_OVER		=	64;
const int	GFG_MOUSE			=	GFG_MOUSE_BUTTON | GFG_MOUSE_MOTION | GFG_MOUSE_OVER;


/* Ostatni ovladani od hodnoty 128 */
const int	PARENT_WAS_RESIZED_AND_RELOCATED	=	128;
const int	I_WAS_RESIZED_AND_RELOCATED			=	512 + 128;	//nepouziva se

const int	GFG_LOST_FOCUS	=	256;
const int	GFG_GOT_FOCUS	=	256 + 128;
const int	CHANGE_POSITION	= 512;

/* Velikosti */
const float	GFG_SUBWINDOW_TOP_PANEL_HEIGHT		=	24.0f;
const float	GFG_SUBWINDOW_TOP_PANEL_BUTTON_SIZE	=	12.0f;
const float	GFG_SCROLL_MIN_VALUE		=	0.0f;
const float	GFG_SCROLL_MAX_VALUE		=	1.0f;
const float	GFG_TEXT_BOX_MIN_HEIGHT		=	20.0f;
const float GFG_LISTBOX_ANIMATE_STEP	=	12.0f;
const float	GFG_LABEL_SCROLLBAR_WIDTH	=	20.0f;
const float GFG_TABS_HEIGHT				=	24;
const float GFG_TABS_MIN_WIDTH			=	32;
const float GFG_SCROLL_MAX_BUTTON_SIZE_RATIO	=	5.0f;	//určuje maximální velikost tlačítka scroll baru
const float GFG_SCROLL_INCREMENT_MULTIPLICATOR = 0.0005f;
const float GFG_OUTLINE_MULTIPLICATOR = 9.0f / 10.0f;
const float GFG_CHECK_BUTTON_ANIMATION_STEP = 2.0f;
const float GFG_STANDARD_PADDING = 5.0f;
const float GFG_SUBWINDOW_PADDING = 10.0f;
const float GFG_SUBWINDOW_PACKING_SPEED = 20.0f;
const float GFG_SUBWINDOW_TOP_PANEL_RESIZING_PADDING = 0.333f;	//multiplikator
const float GFG_SLIDER_BUTTON_WIDTH = 10.0f;
const float GFG_SLIDER_DETECT_LINE_RANGE = 5.0f;
const float GFG_PROGRESSBAR_INDICATOR_PADDING_MULTIPLICATOR = 0.11f;
const float GFG_TABS_PANEL_CAPTION_WIDTH_MULTIPLICATOR = 1.2f;
const size_t GFG_TEXTBOX_MAX_POSIBLE_LENGHT = 512;
const float GFG_SUBWINDOW_PACKING_BUTTON_OFFSET = 2.0f;

/* Casy */
const clock_t	GFG_TEXTBOX_CURSOR_FLICKER_TIME =	750;

/* Vlastnosti alfa prechodu */
const float GFG_MESSAGEBOX_MIN_ALPHA	= 0.3f;
const float GFG_MESSAGEBOX_MAX_ALPHA	= 1.0f;
const float GFG_MESSAGEBOX_ALPHA_STEP	= 0.05f;
const float GFG_GLOBAL_MIN_ALPHA		= 0.0f;
const float GFG_GLOBAL_MAX_ALPHA		= 0.7f;

const float GFG_CBASEPANEL_MIN_ALPHA	= 0.6f;
const float GFG_CBASEPANEL_ALPHA_STEP	= 0.05f;
const float GFG_SUBWINDOW_ALPHA_MULTIPLIER_STEP		=	0.1f;

/* Pojmenovani klaves */
const int GFG_KEY_ENTER	 = 13;
const int GFG_KEY_ESC	= 27;
const int GFG_KEY_TAB	= 9;
const int GFG_KEY_UP = 400;
const int GFG_KEY_DOWN = 401;
const int GFG_KEY_RIGHT = 402;
const int GFG_KEY_LEFT = 403;
const int GFG_KEY_DELETE = 127;
const int GFG_KEY_BACKSPACE = 8;


const int GFG_UP = 0;
const int GFG_DOWN = 1;


/* Typy detekování */
const int GFG_DETECT_NONE = 0;
const int GFG_DETECT_MOUSE = 1;
const int GFG_DETECT_KEYBOARD = 2;

/* Změny velikosti */
const int GFG_RESIZE_LEFT	= 1;
const int GFG_RESIZE_DOWN	= 2;
const int GFG_RESIZE_RIGHT	= 4;
const int GFG_RESIZE_UP		= 8;

const string EMPTY_STRING;

/* Definice barev */
const Color4I GFG_COLOR_BUTTON_IDLE					( 246, 246, 246, 128 );
const Color4I GFG_COLOR_BUTTON_CAPTION_IDLE			( 0, 0, 0, 255 );
const Color4I GFG_COLOR_BUTTON_MOUSEOVER			( 255, 255, 255, 196 );
const Color4I GFG_COLOR_BUTTON_CAPTION_MOUSEOVER	( 196, 255, 255, 255 );
const Color4I GFG_COLOR_SKIN_START_LINE				( 72, 148, 177, 196 );
const Color4I GFG_COLOR_SKIN_END_LINE				( 72, 148, 177, 64 );
const Color4I GFG_COLOR_TEXTBOX_START_LINE_MOUSEOVER	( 72, 148, 177, 255 );
const Color4I GFG_COLOR_TEXTBOX_END_LINE_MOUSEOVER		( 72, 148, 177, 196 );
const Color4I GFG_COLOR_TEXTBOX_CURSOR			(160, 255, 255, 196 );
const Color4I GFG_COLOR_TEXTBOX_TEXT			(196, 255, 255, 255 );
const Color4I GFG_COLOR_LABEL_TEXT				(128,192,255,255 );
const Color4I GFG_COLOR_SCROLLBAR_IDLE			( 64, 196, 255, 230 );
const Color4I GFG_COLOR_SCROLLBAR_MOUSEOVER		( 196, 255, 255, 255);
//const Color4I GFG_COLOR_PANEL_SELECTED			( 72, 148, 177, 196 );
const Color4I GFG_COLOR_PANEL_SELECTED			( 160, 160, 160, 196 );
const Color4I GFG_COLOR_PANEL_MOUSEOVER				( 150, 150, 150, 196 );
const Color4I GFG_COLOR_DISABLED				( 64, 64, 64, 196 );
const Color4I GFG_COLOR_BACKGROUND				( 50, 50, 50, 10 );
const Color4I GFG_COLOR_WINDOW_TOP_AVERAGE		( 64, 196, 255, 230 );
const Color4I GFG_COLOR_WINDOW_TOP_DARK			( 64, 196, 255, 230 );
const Color4I GFG_COLOR_WINDOW_TOP_LIGHT		( 196, 255, 255, 255 );
const Color4I GFG_COLOR_WINDOW_TOP_LIGHTUNFOCUSED	( 64, 128, 255, 64 );
const Color4I GFG_COLOR_WINDOW_FIELD_LIGHTBLEND	( 0, 0, 0, 230 );
const Color4I GFG_COLOR_WINDOW_FIELD_HARDBLEND	( 0, 0, 0, 220 );
const Color4I GFG_COLOR_WINDOW_CAPTION			( 0, 0, 0, 255 );
const Color4I GFG_COLOR_IMAGE_COLOR_MODIFICATOR	( 255, 255, 255, 196 );
const Color4I GFG_COLOR_BUTTONSWITCH_TEXT_IDLE	( 72, 148, 177, 196 );
const Color4I GFG_COLOR_ACCEPT_ICON				( 10, 255, 120, 196 );
const Color4I GFG_COLOR_PROGRESSBAR_OUTLINE		( 72, 148, 177, 255 );
const Color4I GFG_COLOR_PROGRESSBAR_CAPTION		(196, 255, 255, 255 );
const Color4I GFG_COLOR_PROGRESSBAR_INDICATOR	( 72, 148, 177, 255 );
const Color4I GFG_COLOR_MESSAGEBOX_BACKGROUND	( 0, 0, 0, 220);

/* Typy objektů */
enum GFG_object_types
{
	GFG_DEFAULT = 0,
	GFG_MESSAGEBOX,
	GFG_LABEL,
	GFG_BUTTON,
	GFG_LINE,
	GFG_LISTBOX,
	GFG_PROGRESSBAR,
	GFG_IMAGE,
	GFG_SCROLL,
	GFG_SLIDER,
	GFG_WINDOW,
	GFG_TABS,
	GFG_TEXTBOX,
	GFG_CONTAINER
};

/* Ořezávací box každého ovládacího prvku */
struct ScissorBox
{
	float x, y;
	float w, h;
	ScissorBox()	: x(0), y(0), w(0), h(0) {}
	ScissorBox intersection( ScissorBox &box );		//průnik dvou boxů
	void translate( float x, float y )	{ this->x+= x; this->y += y; }
};

/* Informace o callback funkci vyvolané při nějaké události */
struct GFG_Callback
{
	void *callbackData;
	void (*callbackFunc)(CBaseComponent*,void*);
	GFG_Callback() : callbackData(NULL), callbackFunc(NULL) {}
};

/* Zjednodušení */
typedef list<CBaseComponent*>::iterator				iterComp_t;
typedef list<CBaseComponent*>::reverse_iterator		riterComp_t;

const int DELETE_MSG_BOX_EXCEPTION = 0;

const float GFG_MAINWINDOW_FADE_OUT_VALUE = 0.0f;
const float GFG_MAINWINDOW_FADE_IN_VALUE = 1.0f;
const float GFG_MAINWINDOW_ALPHA_STEP = 0.05f;

//hlavni okno, je to prostrednik mezi aplikaci a samotnym GUI
class CMainWindow
{
protected:
	float m_fAlphaMultiplier;			//messagebox animation variable
	float m_fMessageBoxAlphaMultiplier;
	ScissorBox m_ScissorBox;
	list<CBaseComponent*> m_componentList;
	float m_fWidth, m_fHeight;
	CMessageBox *m_pMessageBox;

	float m_fMyAlpha, m_fTargetAlpha;	//component alpha animation

	virtual void anim_run();
	virtual void user_run() {}
	virtual void user_draw() {}
	virtual bool user_controller( int type, float x, float y, int param1, int param2 ) { return false; }
public:
	CMainWindow();
	~CMainWindow();

	void fadein( float value = GFG_MAINWINDOW_FADE_IN_VALUE )	{ m_fTargetAlpha = value; }
	void fadeout( float value = GFG_MAINWINDOW_FADE_OUT_VALUE )	{ m_fTargetAlpha = value; }

	void setMyAlphaMultiplier( float a )	{ m_fMyAlpha = a; m_fTargetAlpha = a; setComponentAlphaMultiplier(a); }

	void setVisibleWidthFocus( CSubWindow *component );
	void addComponent( CBaseComponent *component );

	float getWidth()	{ return m_fWidth;	}
	float getHeight()	{ return m_fHeight;	}
	
	void joinMessageBox( CMessageBox *mbox );
	void removeMessageBox();
	void setComponentAlphaMultiplier( float multiplier );

	void setSize( float width, float height );
	virtual void inputController( int type, float x, float y, int param1, int param2 );
	virtual void draw();
	virtual void run();
	virtual void deleteAll();
};


/* Hlavní kořenová třída všech komponent. Definuje základní funkce a proměnné,
které ostatní komponenty dědí. Každá komponenta volá při vytváření inicializační funkci, která nastaví
hodnoty proměnných na výchozí hodnoty. Třída definuje funkce, které jsou reakcí na určité změny
a potomci této třídy si tyto funkce přepisují podle vlastních potřeb. Obsahuje též základní ovládací funkce. */
class CBaseComponent
{
protected:
	int m_iDetectionType,		//určuje typy reakcí na vstup (klávesnice, myš)
		m_iObjectType,			//typ objektu z ENUM GFG_object_types
		m_iIdentificalNumber;	//identifikační číslo objektu
	ScissorBox m_ScissorBox;	//ořezávací box
	Color4I m_ColorBackGround;	//základní barva
	float m_fAlphaMultiplier;	//násobitel alfa hodnoty aktuální barvy (používá se k animacím)
	bool m_bVisible, m_bMouseOver, m_bEnabled, m_bFocused,
		m_bTemporaryDisabled;	//znamená, že prvek je disabled kvůli nadřazenému prvku
	CBaseComponent *parent;		
	float m_fWidth, m_fHeight;
	float m_fGlobalXpos, m_fGlobalYpos;
	fontLibrary::DString m_dsCaption;
	GFG_Callback m_Callback;	//calback funkce + data

	void baseInit( float w, float h );	//základní inicializace společná pro všechny prvky

	float m_fPaddingRight, m_fPaddingLeft, m_fPaddingTop, m_fPaddingBottom;
	void setColor( const Color4I &color );		//funkce nastavuje aktuální barvu OpenGL
	
	/* Funkce testuje, zda bod x,y leží v poli prvku */
	inline bool checkMouseArea( float x, float y )
	{
		return x > m_fGlobalXpos && x < m_fGlobalXpos + m_fWidth && y > m_fGlobalYpos && y < m_fGlobalYpos + m_fHeight;
	}

	/* Funkce testuje, zda bod x,y leží v ořezávacím poli prvku  */
	inline bool checkScissorBoxArea( float x, float y )
	{
		return x > m_ScissorBox.x && x < m_ScissorBox.x + m_ScissorBox.w && y > m_ScissorBox.y && y < m_ScissorBox.y + m_ScissorBox.h;
	}

	float getGlobalXpos()	{return m_fGlobalXpos;	}
	float getGlobalYpos() {return m_fGlobalYpos;	}
	/*float getGlobalXpos( float localX );
	float getGlobalYpos( float localY );*/
	/* Funkce přepočítá celý ořezávací box dle pole prvku a hodnot okrajů */
	virtual void updateScissorBox();

	/* Následují funkce reakcí na události */
	virtual bool onMouseOver( float x, float y)	{ return m_bMouseOver;	}
	virtual bool onMouseButtonUp( float x, float y, int button, bool isOnArea)	{ return false;	}
	virtual bool onMouseButtonDown( float x, float y, int button, bool isOnArea)	{ return isOnArea;	}
	virtual bool onKeyboardDown( int key )	{ return false;	}
	virtual bool onSpecialKeyDown( int key )	{ return false;	}

	/* Reakce na změny velikosti a pozice*/
	virtual void onComponentTranslate( float offsetX, float offsetY ) {}
	virtual void onComponentResize( float w_offset, float h_offset ) {}
	virtual void onScissorBoxTranslate( float offsetX, float offsetY ) {}
	virtual void onScissorBoxResize( float w_offset, float h_offset ) {}
public:
	
	CBaseComponent();
	CBaseComponent( float w, float h )	{ baseInit( w,h ); }
	virtual ~CBaseComponent()	{}
	ScissorBox & getScissorBox()	{ return m_ScissorBox;	}
	

	int getObjectID()	{ return m_iIdentificalNumber;	}
	void setObjectID( int ID )	{ m_iIdentificalNumber = ID;	}
	int getObjectType() { return m_iObjectType; }

	float getPadding()	{ return max( m_fPaddingRight, max( m_fPaddingLeft, max ( m_fPaddingTop, m_fPaddingBottom ) ) );	}
	float getPaddingRight()	{ return m_fPaddingRight;	}
	float getPaddingLeft()	{ return m_fPaddingLeft;	}
	float getPaddingTop()	{ return m_fPaddingTop;	}
	float getPaddingBottom()	{ return m_fPaddingBottom;	}
	
	/* Nastaví všechny hodnoty okrajů */
	virtual void setPadding( float padding )
	{ 
		m_fPaddingRight = padding;
		m_fPaddingLeft = padding;
		m_fPaddingTop = padding;
		m_fPaddingBottom = padding;
		updateScissorBox();
	}

	/* Nastavení callback funkce */
	void setCallback( GFG_Callback &callback ) { m_Callback = callback; }
	GFG_Callback * getCallback() { return &m_Callback; }

	////////////////////////////////////////////////////////////////////////////
	// Virtuální funkce, které by si měl každý potomek definovat sám,
	// nebo použít tyto standardní
	////////////////////////////////////////////////////////////////////////////

	//forward messages - funkce se volají od kořene směrem dolů
	virtual void setTemporaryDisabled( bool disabled );
	virtual bool inputController( int type, float x, float y, int param1, int param2 );
	virtual void draw( ScissorBox &scissorBox ) = 0;
	virtual void run(){};
	virtual void setAlphaMultiplier( float multiplier )	{ m_fAlphaMultiplier = multiplier;	}
	virtual void setEnabled( bool value );
	

	//backward messages - funkce se volají od potomka směrem vzhůru k rodičům
	
	/* funkce říká, jestli by měl prvek ztratit fokus po určité události. Viz Text projektu */
	virtual bool lostFocusForChilds()	{ return true;	}	
	virtual void giveMeFocus( CBaseComponent *me = NULL );	//prvek vyžaduje, aby dostal fokus

	//object use functions - funkce pro ovládání fokusu
	virtual	bool isFocusable()	{ return true;	}	//dulezite
	virtual bool shouldIlostFocus()
	{
		if( parent != NULL )
			return parent->lostFocusForChilds();
		return false;
	}

	//////////////////////////////////////////////////
	//////////////////////////////////////////////////
	//////////////////////////////////////////////////

	bool getTemporaryDisabled()	{ return m_bTemporaryDisabled;	}

	/* Funkce nastavují okraj pole prvku. Některé prvky vyžadují
		speciální nastavení, proto jsou virtual */
	virtual void setPaddingRight( float padding )	{ m_fPaddingRight = padding; updateScissorBox();	}
	virtual void setPaddingLeft( float padding )	{ m_fPaddingLeft = padding; updateScissorBox();	}
	virtual void setPaddingTop( float padding )	{ m_fPaddingTop = padding; updateScissorBox();	}
	virtual void setPaddingBottom( float padding )	{ m_fPaddingBottom = padding; updateScissorBox();	}
	
	float getAlphaMultiplier()	{ return m_fAlphaMultiplier;	}
	void setVisible( bool visibility )	{ m_bVisible = visibility; }
	bool getVisible()	{ return m_bVisible;	}

	/* Nastavení pozic a velikostí */
	void setPosition( float x, float y )	{ setPositionOffset( x- m_fGlobalXpos,  y - m_fGlobalYpos ); }
	void setYPosition( float y )	{ setPositionOffset( 0, y - m_fGlobalYpos ); }
	void setXPosition( float x )	{ setPositionOffset( x- m_fGlobalXpos, 0 ); }
	void setPositionOffset( float offsetX, float offsetY )	{ m_fGlobalXpos += offsetX; m_fGlobalYpos += offsetY; m_ScissorBox.translate(offsetX,offsetY); onComponentTranslate(offsetX,offsetY); onScissorBoxTranslate( offsetX,offsetY );	}

	void setWidth( float w )	{ setSizeOffset( w - m_fWidth, 0 ); }
	void setHeight( float h )	{ setSizeOffset( 0, h - m_fHeight ); }
	void setSize( float w, float h )	{ setSizeOffset( w - m_fWidth, h - m_fHeight );	}
	void setSizeOffset( float w_offset, float h_offset )	{ m_fWidth += w_offset; m_fHeight += h_offset; onComponentResize(w_offset, h_offset); updateScissorBox();	}

	void setPositionAndSizeOffset( float offsetX, float offsetY, float w_offset, float h_offset )	{ setPositionOffset( offsetX, offsetY ); setSizeOffset( w_offset, h_offset );   	}
	
	
	
	CBaseComponent *getParent()	{	return parent;	}
	void setParent(CBaseComponent *comp)	{	parent = comp;	}
	
	/* Funkce nastavení textu */
	virtual void setCaption( string text, int iAlign = FONT_ALIGN_CENTER );
	virtual void setCaption( string text, string font, int iAlign = FONT_ALIGN_CENTER );
	virtual void setCaption( string text, Font *font, int iAlign = FONT_ALIGN_CENTER );
	virtual void setCaption( fontLibrary::DString &str ) { m_dsCaption = str; }

	fontLibrary::DString & getCaption()	{ return m_dsCaption;	}
	

	float getWidth(  )	{ return m_fWidth; }
	float getXPosition()	{ return m_fGlobalXpos; }
	float getYPosition()	{ return  m_fGlobalYpos; }
	float getHeight( )	{ return m_fHeight; }
	
	bool getEnabled()	{ return m_bEnabled; }
	
	/* Nastavení typu */
	void setDetectionType( int type )	{ m_iDetectionType = type;	}
	int getDetectionType()	{ return m_iDetectionType;	}
	
	void setColorBackGround( Color4I &color )	{ m_ColorBackGround = color; }
};

/* Element kontejneru, obsahuje ukazatel na prvek a také ukazatele na sousedy. */
struct ContainerElement
{
	CBaseComponent *m_pComponent;
	/*ContainerElement *m_pPrevious;
	ContainerElement *m_pNext;*/
	float m_fInformation;
	ContainerElement *m_pUp;
	ContainerElement *m_pDown;
	ContainerElement() : m_pComponent( NULL ), m_pUp( NULL ), m_pDown( NULL ), m_fInformation(0)	{}
	bool operator==( const ContainerElement &b )
	{
		return ( m_pComponent == b.m_pComponent );
	}
	virtual ~ContainerElement()
	{
		delete m_pComponent;
	}

};
/* Zjednodušení */
typedef ContainerElement ContElem;

typedef list<ContElem*>::iterator iterContElem_t;
typedef list<ContElem*>::reverse_iterator riterContElem_t;

/* Základní kontejner. Definuje základní operace s kontejnery
*	jako například ovládání fokusu mezi jednotlivými komponenty
*	a také ovládání komponent, které konterjner obsahuje */
class CBaseContainer : public CBaseComponent
{
protected:
	bool m_bDraw;	//v případě, že je tato hodnota nastave na true, tak se vykresluje rámeček i s popiskem
	list<ContElem*> m_Components;

	virtual bool changeFocusBySpecKey( int key ) = 0;
	
	virtual void gotFocus( int type ) = 0;
	void init() { m_bDraw = false; baseInit(0,0);  }
	
	/* Velice důležitá funkce - hledá objekt, který může získat fokus */
	ContainerElement *findFirstNextFocusable( ContainerElement *start, ContainerElement *next, int direction );
	virtual void onScissorBoxTranslate( float offsetX, float offsetY );
public:
	CBaseContainer() : CBaseComponent() { init(); }
	virtual void changeFocusedItem( ContainerElement *element, int type );
	virtual void setTemporaryDisabled( bool disabled );
	virtual void setEnabled( bool enabled );
	virtual bool lostFocusForChilds()
	{
		if ( m_Components.size() > 1 )
			return true;
		else if( parent != NULL )
			return parent->lostFocusForChilds();
		return false;
	}
	virtual ~CBaseContainer();
	virtual bool inputController( int type, float x, float y, int param1, int param2 );
	virtual void draw( ScissorBox &scissorBox );
	virtual void run();
	virtual void setAlphaMultiplier( float multiplier );
	void setAllowDraw( bool allowDraw )	{ m_bDraw = allowDraw; }
	bool getAllowDraw(  )	{ return m_bDraw; }
	bool empty() { return m_Components.empty(); }
	virtual void addComponent( CBaseComponent *component, float info = 1.0f ) = 0;	//tuto funkci si každý dědic definuje sám
	virtual void giveMeFocus( CBaseComponent *me = NULL );	//funkce přidělí fokus žadateli
	void clear();

	virtual bool isFocusable();	//záleží na prvních kontejneru

	/* Iterátory spojového seznamu prvků */
	iterContElem_t getComponentListBegin() { return m_Components.begin(); }
	iterContElem_t getComponentListEnd() { return m_Components.end(); }
	riterContElem_t getComponentListRBegin() { return m_Components.rbegin(); }
	riterContElem_t getComponentListREnd() { return m_Components.rend(); }

};

/* Základní implementace kontejneru */
class ContainerSimpleBase : public CBaseContainer
{
protected:
	ContainerElement *m_pFirstElement;
	ContainerElement *m_pLastElement;
	bool noFocusableTillStart();
	bool noFocusableTillEnd();
	virtual void gotFocus( int type );	//zisk fokusu klávesou 'type'
public:
	virtual bool changeFocusBySpecKey( int key );	//zavolá se po stisku klávesy 'key'
	virtual ~ContainerSimpleBase()	{}
		
	ContainerSimpleBase() : CBaseContainer() { m_pFirstElement = NULL, m_pLastElement = NULL; }
	virtual void addComponent( CBaseComponent *component, float info = 1.0f ) = 0;
};

/* Kontejner s pevnou pozicí prvků */
class ContainerFixed : public ContainerSimpleBase
{
public:	
	ContainerFixed() : ContainerSimpleBase() { }
	virtual void addComponent( CBaseComponent *component, float x_offset, float y_offset );
	virtual void addComponent( CBaseComponent *component, float info ) { addComponent( component, 0, 0 ); }
};

const bool GFG_CONTAINER_REVERSE = 1;
const bool GFG_CONTAINER_NORMAL = 0;

/* Kontejner s procentuální výškou (každý prvek má stejnou výšku) */
class ContainerRelativeUpToDown : public ContainerSimpleBase
{
protected:
	float m_fTotalPriority;
	//prázdné místo mezi objekty ( procentuální hodnoty 0 - 1 )
	float m_fHorizontalPaddingPercents, m_fVerticalPaddingPercents;	
	virtual void recalculate();	//funkce přepočítá pozice a velikosti jednotlivých prvků kontejneru
	bool m_bReverse;
public:
	ContainerRelativeUpToDown( bool reverse = GFG_CONTAINER_NORMAL ) : ContainerSimpleBase( ) { m_fHorizontalPaddingPercents = 0; m_fVerticalPaddingPercents = 0; m_bReverse = reverse; m_fTotalPriority = 0.0f; }
	virtual void addComponent( CBaseComponent *component, float priority = 1.0f );	//pridava se od shora v poradi
	virtual void onScissorBoxResize( float offsetX, float offsetY ) { recalculate(); }
	
	void setHorizontalPadding( float percent );
	void setVerticalPadding( float percent );
	float getHorizontalPadding()	{ return m_fHorizontalPaddingPercents; }
	float getVerticalPadding()	{ return m_fVerticalPaddingPercents; }
};

/* Kontejner s procentuální šířkou ( každý prvek má stejnou šířku ) */
class ContainerRelativeLeftToRight : public ContainerRelativeUpToDown
{
protected:
	virtual void recalculate();
public:
	ContainerRelativeLeftToRight( bool reverse = false ) : ContainerRelativeUpToDown( reverse ) {  }

};

/* Komponenty se přidávají vertikálně a zůstává jim jejich výška. 3ířka se přizpůsobuje kontejneru */
class ContainerSemiRelativeUpToDown : public ContainerRelativeUpToDown
{
protected:
	virtual void recalculate();
public:
	ContainerSemiRelativeUpToDown( bool reverse = false ) : ContainerRelativeUpToDown( reverse ) {  }

};

/* Komponenty se přidávají horizontálně a zůstává jim jejich šířka. Šířka se přizpůsobuje kontejneru */
class ContainerSemiRelativeLeftToRight : public ContainerRelativeUpToDown
{
protected:
	virtual void recalculate();
public:
	ContainerSemiRelativeLeftToRight( bool reverse = false ) : ContainerRelativeUpToDown( reverse ) {  }
};

const int GFG_SUBWINDOW_CLOSE = 1;
const int GFG_SUBWINDOW_PACKING = 2;

/* Okno, které může obsahovat jeden prvek, který bude mít vždy velikost okna.
*	dále obsahuje tlačítko 'zavřít okno' a tlačítko 'zabalit okno'. Okno umožňuje měnit velikost
*	a pozici sebe sama. */
class CSubWindow : public CBaseComponent
{
protected:
	int m_iButtonParm;
	float m_iPackingButtonOffset;
	int g_maskId, g_panelID;
	int m_iXstartMove, m_iYstartMove;	//pomocné proměnné pro posun okna
	bool m_bChangingPosition, m_bResizing, m_bResizable, m_bPacked;
	int m_iResizeType;	//určuje aktuální typ změny velikosti
	float	m_fPackOffset,	//vzdálenost zabalení okna
		m_iPackingStep;	//krok zabalování okna

	Button *cancelButton, *packButton;
	CMainWindow *m_pMainWindow;
	
	//zkontroluje kliknutí myši nad horním panelem a na okrajích okna
	void checkTopPanelAndResizes( float x, float y );	
	CBaseComponent* m_pComponent;
	
	void subWindowInit( float x, float y, float w, float h );
	virtual void windowBasicDraw( ScissorBox &scissorBox );
	virtual void windowTopPanelDraw( ScissorBox &scissorBox );
	virtual void onCancelButtonClick();
	float m_iTopPanelHeight;
	virtual bool onKeyboardDown( int key );
	
	void resizeByMouse( int x, int y);
	virtual void onComponentTranslate( float offsetX, float offsetY );
	virtual void onComponentResize( float w_offset, float h_offset );
	virtual void onScissorBoxTranslate( float offsetX, float offsetY );
	virtual void onScissorBoxResize( float w_offset, float h_offset );
	void windowCorrection();	//upraví pozici okna tak, aby byl vidět minimálně celý horní panel
public:	
	CSubWindow();
	CSubWindow( float x, float y, float w, float h, int buttonparm = GFG_SUBWINDOW_CLOSE |GFG_SUBWINDOW_PACKING );
	virtual ~CSubWindow();
	
	

	void setResizable( bool resizable )	{ m_bResizable = resizable; }
	bool getResizable()	{ return m_bResizable;	}
	void setPacked( bool packed )	{ m_bPacked = packed; }
	bool getPacked()	{ return m_bPacked;	}

	virtual bool shouldIlostFocus()	{	return false;	}	//nikdy si sam nezahazuj focus
	virtual bool lostFocusForChilds()	{ return false;	}	//potomci si sami nezahazuji focus
	void setComponent( CBaseComponent *component );
	void setCaption( string text );
	void setCaption( string text, string font, int align = FONT_ALIGN_CENTER );
	virtual bool inputController( int type, float x, float y, int param1, int param2 );
	virtual void draw( ScissorBox &scissorBox );
	virtual void run();
	virtual void setEnabled( bool value );
	virtual void setTemporaryDisabled( bool disabled );
	virtual void setAlphaMultiplier( float multiplier );

	virtual void setPaddingTop( float padding ) { m_fPaddingTop = GFG_SUBWINDOW_TOP_PANEL_HEIGHT + padding; updateScissorBox(); }
	virtual void setPadding( float padding );

	/* Okno potřebuje znát hlavní okno, jinak nebude fungovat korekce pozice */
	void setMainWindow( CMainWindow *pMainWindow ) { m_pMainWindow = pMainWindow; windowCorrection(); }
	CMainWindow *getMainWindow() { return m_pMainWindow; }

};



/* Základní třída definující obecné vlastnosti tlačítek */
class ButtonBase : public CBaseComponent
{
protected:
	bool m_bPushed;			//indikátor stisknutí tlačítka

	/* Barvy */
	Color4I m_ColorCaptionMouseOver, m_ColorCaptionIdle;
	Color4I m_ColorMouseOver, m_ColorIdle;
	Color4I m_ColorPushed, m_ColorPushedMouseOver;

	TextureElement *m_pTexture_up, *m_pTexture_down; //textury ( klidový stav a stisknutí )

	virtual void onClick();			//funkce vyvolaná po stisku tlačítka
	virtual bool onMouseButtonDown( float x, float y, int button, bool isOnArea );
	virtual bool onMouseButtonUp( float x, float y, int button, bool isOnArea);
	virtual bool onMouseOver( float x, float y );
	virtual bool onKeyboardDown( int key );
	void buttonBaseInit( float w, float h );		//základní inicializace tlačítkových tříd


public:
	virtual void init();
	virtual ~ButtonBase();
	ButtonBase();
	ButtonBase( float w, float h );
	
	/* Nastavení barev ( používají se různá barevná provedení tlačítek */
	void setColorMouseOver( const Color4I &color )	{ m_ColorMouseOver = color; }
	void setColorIdle( const Color4I &color )	{ m_ColorIdle = color; }
	void setColorCaptionMouseOver( const Color4I &color )	{ m_ColorCaptionMouseOver = color; }
	void setColorCaptionIdle( const Color4I &color )	{ m_ColorCaptionIdle = color; }
	void setColorPushed( const Color4I &color )	{ m_ColorPushed = color; }
	void setColorPushedMouseOver( const Color4I &color ) {	m_ColorPushedMouseOver = color; }

	/* Nastavení textur */
	void setTextureIdle( string texture );
	void setTexturePushed( string texture );

	bool getPushed()	{ return m_bPushed;	}
	void setPushed( bool pushed )	{ m_bPushed = pushed;	}

	virtual void draw( ScissorBox &scissorBox ) = 0;
};

/* Třída reprezentuje základní formu tlačítka ( tlačítko lze stisknout a tím vyvolat reakci a
* implementuje základní způsob vykreslování tlačítek, po uvolnění stisknutí se tlačítko vrací do klidového stavu )
*	-Reakce se vyvolá až po uvolnění stisknutí tlačítka. Je to proto, aby nedocházelo k nechtěným událostem, protože když
*	dojde k uvolnění stisknutí myší, kde souřadnice kurzoru nebudou v ploše tlačítka, tak k reakci nedojde.
*/
class Button : public ButtonBase
{
public:
	Button()	{ buttonBaseInit(0,0); }
	~Button();
	Button( float w, float h ) : ButtonBase( w, h ) { }
	virtual void init();
	
	bool isPushed()	{ return m_bPushed;	}
	void setPushed( bool pushed )	{ m_bPushed = pushed;	}

	virtual void draw( ScissorBox &scissorBox );
};

/*	Tato třída je v základě stejná jako základní forma tlačítka, ale navíc implementuje dva
*	stavy, kde tlačítko může být stisknuté a v klidu a nevrací se do klidového stavu po uvolnění stisknutí.
*/
class SwitchedButton : public Button
{
	virtual bool onMouseButtonDown( float x, float y, int button, bool isOnArea );
	virtual bool onMouseButtonUp( float x, float y, int button, bool isOnArea)	{ return false;	}
	virtual bool onMouseOver( float x, float y )	{ return m_bMouseOver; }
public:
	virtual void init();
	SwitchedButton( float w, float h ) 	:  Button( w,h ) {}
};

/* CheckButton implementuje klasické zátržítko. Obsahuje čtverec, ve kterém se zobrazuje nebo nezobrazuje
*	obrázek v závislosti na zatržení a popisek, který zatržení popisuje. Navíc je zde implmentována rotace
*	indikujícího obrázku, který zlepšuje výsledný estetický dojem. 
*/
class CheckButton : public ButtonBase
{
protected:
	Image *m_Image;		//obrázek
	
	float m_fRotate;			//úhel otočení obrázku
	bool m_bSwitched;			//indikuje zatržení
	virtual bool onMouseButtonUp( float x, float y, int button, bool isOnArea);
	virtual void onComponentTranslate( float x, float y );
	virtual void onScissorBoxResize( float w_offset, float h_offset ) { recalculate(); }
	/* funkce přepočítává souřadnice a velikosti obrázku, když dojde ke změně celého objektu */
	void recalculate();			
	void switchBaseInit();
public:
	virtual ~CheckButton();
	CheckButton() : ButtonBase( 0, 0 ) { switchBaseInit(); }
	CheckButton( float w, float h ) : ButtonBase( w, h ) { switchBaseInit(); }
	virtual void init();
	virtual void draw( ScissorBox &scissorBox );
	
	/* Nastavení a zjištění zatržení */
	void setSwitched( bool value )	{ m_bSwitched = value;	}
	bool getSwitched()	{ return m_bSwitched;	}
	
	virtual void setCaption( string text, int iAlign = FONT_ALIGN_LEFT );
	virtual void setCaption( string text, string font, int iAlign = FONT_ALIGN_LEFT );
	virtual void setCaption( string text, Font *font, int iAlign = FONT_ALIGN_LEFT );
	virtual void setAlphaMultiplier( float multiplier );
	virtual void run();
};

/* Téměř stejný prvek jako zátržítko, ale s jiným obrázkem ( v tomto případě se jedná o kruh, který je
*	známý pro tento prvek, který se používá pro volbu z několika možností
*/
class RadioButton : public CheckButton
{
	
public:
	virtual void init();
	RadioButton() : CheckButton() {}
	RadioButton( float w, float h ) : CheckButton( w, h ) { init(); }

};

/* Třída reprezentuje obyčejný obrázek */
class Image : public CBaseComponent
{
	GLuint m_Picture, m_iPictureWidth, m_iPictureHeight;	//DList a vlastnosti obrázku
	
	//určuje, zda si má obrázek udržovat reálnou velikost dle vstupního souboru
	bool m_bRealSize;										
public:
	Image( float w, float h );
	~Image();
	bool loadImage( string filename );			//načtení obrázku
	void setRealSizeDraw( bool yes )	{ m_bRealSize = yes; }
	bool getRealSizeDraw()	{ return m_bRealSize; }
	
	//zjištění velikostí vlastního obrázku ( ne tohoto objektu )
	void getImageSize( int &x, int &y );
	int getImageWidth()	{ return m_iPictureWidth;	}
	int getImageHeight()	{ return m_iPictureHeight;	}
	virtual void draw( ScissorBox &scissorBox );
	bool isFocusable() { return false; }		//obrázek nemůže dostat focus
};


/* Tato třída tvoří pole prvků RadioButton. Umožňuje výběr práve jednoho prvku ze seznamu. 
*	Ve své implmentaci obsahuje ale ukazatel pouze na jeden objekt CBaseContainer. Je tedy na 
*	programátorovy, jaký typ Containeru zvolí. Container ale musí být prázdný, jinak je obsah smazán, protože
*	je třeba zaručít, aby všechny objekty byly jen typu RadioButton. Prvky RadioButton se přidávají pomocí funkce addOption
*/

class Option : public CBaseComponent
{
	CBaseComponent *m_pSelected;		//ukazatel na vybraný RadioButton
	CBaseContainer *m_pContainer;		//ukazatel na Container
	/* Při těchto změnách se musí přepočítat velikosti vnitřních objektů */
	virtual void onScissorBoxTranslate( float offsetX, float offsetY );
	virtual void onScissorBoxResize( float w_offset, float h_offset );	

public:
	Option( float w, float h ) : CBaseComponent( w, h) {}
	~Option();
	void init();
	void setContainer( CBaseContainer *pContainer );	//nastavení Containeru
	void addOption( RadioButton *button );				//vložení nového prvku RadioButton
	RadioButton *selectedOption();						//vrací aktuálně vybrané tlačítko
	
	virtual bool inputController( int type, float x, float y, int param1, int param2 );
	virtual void draw( ScissorBox &scissorBox );
	virtual void setAlphaMultiplier( float multiplier );
	virtual void run();
	virtual void setEnabled( bool enabled );
	virtual void setTemporaryDisabled( bool disabled );


};
	
/* Horizontální čára - leží vždy uprostřed výšky objektu */
class ComponentLine : public CBaseComponent
{
	virtual void onComponentResize( float w_offset, float h_offset );
public:
	ComponentLine( float w, float h );
	virtual bool isFocusable() { return false; }
	virtual void draw( ScissorBox &scissorBox );
	

};


/* Slider ( šoupátko ) - používá se k nastavení hodnoty z určítehé intervalu. Určitě je známý z přehrávačů hudby,
*	nebo video, kde určuje aktuální místo přehrávání. Hodnotu zde určuje poloha jezdce ( v omto případě tlačítka )
*/
class Slider : public CBaseComponent
{
	ComponentLine *m_Line;			//jezdící čára
	Button *m_SliderButton;			//indikující tlačítko
	
	//Vlastnosti: pozice tlačítka, velikost jezdícího pole, počáteční hodnota a velikost intervalu
	float m_fPosition, m_fSize, m_fStartValue, m_fValue;	
	void updateByParameters();			//aktualizace dle změn parametrů
	void updateByPosition();			//aktualizace dle změny pozice jezdce
	bool m_bChangingPosition;			//určuje, zda se mění pozice jezdce
	int m_iMoveXpos, m_iMoveYpos;		//pomocné proměnné pro táhnutí jezdce myší
	int m_iNumPositionsForRounding;		//určuje počet desetinných míst pro zaokrouhlení hodnoty
	
	/* Při těchto změnách musí dojít k přepočítání pozic a velikostí vnitřních prvků */
	virtual void onScissorBoxTranslate( float offsetX, float offsetY );
	virtual void onScissorBoxResize( float w_offset, float h_offset );
public:
	Slider( float w, float h );
	~Slider();
	
	virtual bool inputController( int type, float x, float y, int param1, int param2 );
	virtual void draw( ScissorBox &scissorBox );
	virtual void setAlphaMultiplier( float multiplier );
	virtual void setEnabled( bool enabled );
	virtual void setTemporaryDisabled( bool disabled );
	
	float getValue()	{ return m_fValue;	}	//vlastní hodnota slideru - udává ji poloha jezdce
	void setValue( float value );
	void refreshValue();
	void setRoundPositions( int num )	{ m_iNumPositionsForRounding = num;	}
	
	/* Nastavení rozsahu a levé krajní hodnoty */
	void setValueSize( float size );
	void setValueSize( float start, float size )	{ setStartValue( start ); setValueSize( size );	}
	void setStartValue( float start )	{ m_fStartValue = start; updateByParameters(); }
	
	bool isFocusable() { return false; }		//nemůže dostat focus


};



/* Textové pole je hlavním prvkem pro vstup z klávesnice. Pole zobrazuje Cursor, který určuje pozici psaní v textu
*	umožňuje ho posouvat kurzorovými šipkamy mazat a vkládat text. Při posunu dochází k plynulé animaci. Text smí obsahovat pouze 
*	jeden řádek.
*/
class TextBox : public CBaseComponent
{
protected:
	size_t m_iMaxLenght;
	int m_iCursorPos;		//udává vzdálenost kurzoru od počátku
	//vlastní posunutí objektu a posunutí pro animaci ( toto určuje posunutí pro vykreslení )
	float m_fTranslate, m_fAnimateTranslation;
	size_t m_iCursorIndex;	//udává pozici kurzoru v počtu znaků
	int m_iCursorFlickerTime, m_iLastFlickerTime;	//časy pro blikání
	bool m_bCursorVisible;					
	void resetCursor();
	void textCorrection( string &text );	//upraví text, který se má nastavit jako aktuální
	void update();			//aktualizuje velikosti a vlastnosti kurzoru v případě změny velikosti vlastního objektu
	virtual void onScissorBoxResize( float w_offset, float h_offset );
public:
	TextBox( float w, float h );
	virtual bool inputController( int type, float x, float y, int param1, int param2 );
	void draw( ScissorBox &scissorBox );
	string getCaption();
	virtual void run();		//v této funkci dochází k implementaci animace
	virtual void setCaption( string text );
	virtual void setCaption( string text, string font );
	virtual void setCaption( string text, Font *font );
	virtual void setCaption( fontLibrary::DString &str );
	void setTextLine( fontLibrary::DString::TextLine &line );	
	void setColorText( const Color4I &color )	{ m_ColorBackGround = color; }
	void setFont( Font *pFont );
	void setFont( string sFont ) { setFont( fontLibrary::getFont( sFont ) ); }
	void setMaxLenght( size_t lenght );
};

/*	Prvek určuje procentuální stav nějaké operace a zobrazuje ho graficky pomocí šířky pole (obdélníku) s texturou.
*
*/
class ProgressBar : public CBaseComponent
{
	float m_fValue, m_fSize;
	int m_iRoundingPositions;
	bool m_bCaptionVisible;

	/* Vlastnosti indikujícího pole */
	float m_fIndicatorStartX, m_fIndicatorStartY, m_fIndicatorW, m_fIndicatorH, m_fIndicatorTexW, m_fIndicatorTexH;

	//ID textur
	int m_iTextureLeft, m_iTextureCenter, m_iTextureRight, m_iTextureIndicator;
	void update();		//přepočítání velikostí a pozic po změně vlastního objektu
public:
	ProgressBar( float w, float h);
	~ProgressBar();
	float getValue()	{ return m_fValue; }	//vrátí hodnotu postupu 0-1 (nikoliv procenta)
	void setValue( float v );
	virtual void draw( ScissorBox &scissorBox );
	void setRoundPositions( int num )	{ m_iRoundingPositions = num;	}	//nastavení počtu pozic pro zaokrouhlení
	bool setCaptionVisible( bool visibility )	{ m_bCaptionVisible = visibility;	}	
	virtual void onComponentResize( float offsetX, float offsetY );
	virtual void onComponentTranslate( float offsetX, float offsetY );
	virtual	bool isFocusable()	{ return false;	}	//nelze nastavit na tento prvek focus
};



/*	Třída implementuje záložky. Je to několik Containerů, které se přepínají pomocí tlačítek (přepínačů)
*	aktivní je vždy pouze jeden Container
*/
class Tabs : public CBaseComponent
{
	/* Definice jednoho panelu */
	struct SinglePanel
	{
		CBaseComponent* m_pComponent;	//obsahuje ukazatel na jednu komponentu
		int m_iIndex;					//identifikační číslo
		SwitchedButton *m_Button;		//přepínací tlačítko pro aktivaci
		SinglePanel() : m_pComponent(NULL), m_Button(NULL), m_iIndex(0) {}
		~SinglePanel()	{ delete m_Button;	delete m_pComponent; }
	};
	list<SinglePanel*> m_Panels;		//seznam panelů
	int m_iPanelIndex;					//první volná pozice pro nový panel
	float m_fCurrentXpos;				//vzdálenost levé hrany objektu až po pravou hranu posledního panelu
	bool thisController( int type, float x, float y, int param1, int param2 );	//ovládání vlastního objektu
	virtual void onScissorBoxTranslate( float offsetX, float offsetY );
	virtual void onScissorBoxResize( float w_offset, float h_offset );
public:
	Tabs( float w, float h );
	virtual ~Tabs();
	int addPanel( std::string caption ); 
	void setComponent( int panelID, CBaseComponent *component );	//připojí panelu componentu
	virtual bool inputController( int type, float x, float y, int param1, int param2 );
	virtual void draw( ScissorBox &scissorBox );
	virtual void setAlphaMultiplier( float multiplier );
	virtual void run();

	virtual void setPaddingTop( float padding ) { m_fPaddingTop = padding  +GFG_TABS_HEIGHT; updateScissorBox(); }
	virtual void setPadding( float padding );

	//virtual void updateScissorBox();
	virtual void setTemporaryDisabled( bool disabled );
	virtual void setEnabled( bool value );
	virtual bool lostFocusForChilds();
	virtual bool isFocusable();
};




/* Rolovací panel - použvá se v různých ovládacích prvcích pro rolování obsahu, které se nevejde svojí velikostí
*	do vlastnícího okna. Panel využívá tří tlačítek k ovládání. Při posouvání jezdce panelu se mění hodnota
*	určující posun, o který je třeba data posunout.
*
*/
class Scroll : public CBaseComponent
{
protected:
	bool m_bChangingPosition, m_bArrowButtonPushed;
	//velikost pole a velikost dat, která se do pole mají vejít
	float m_fDocumentAreaSize, m_fDocumentDataSize;

	float m_fValue;				//hodnota (0-1) udává posunutí, které je třeba provést k zobrazení správných dat
	float m_fCenterButtonPosition;	//vzdálenost dolního okraje jezdce od dolního okraje objektu
	float m_fCenterButtonSize;		//velikost jezdce
	float m_fCenterButtonMaxSize;		//výška pole, kde se může jezdec vyskytovat
	float m_fSlidingAreaSize;	//možná vzdálenost pohybu jezdce
	Button *top, *center, *bottom;	//ovládací tlačítka - prostřední je jezdec
	
	void recalculatePosition();		//přepočítání velikostí a pozice interních prvků
	void updateButtonSize();

	float getButtonHeight( float requested );	//vraci maximalni moznou velikost tlacitka

	float m_iMoveXpos, m_iMoveYpos;		//pomocné proměnné pro pohyb jezdce
	void valueUp( float value );
	void valueDown( float value );
	void onScissorBoxTranslate( float offsetX, float offsetY );
	void onScissorBoxResize( float w_offset, float h_offset );
public:
	Scroll() : CBaseComponent() {}
	~Scroll()
	{
		delete top;
		delete center;
		delete bottom;
	}
	virtual	bool isFocusable()	{ return false;	}		//nelze nastavit focus
	Scroll( float w, float h );
	virtual bool inputController( int type, float x, float y, int param1, int param2 );
	virtual void draw( ScissorBox &scissorBox );
	
	float getValue()	{ return m_fValue;	}
	void setValue( float v );
	
	float getScrollSize()	{ return m_fDocumentDataSize;	}	//velikost dat pripojenych na scroll
	void setScrollParameters( float fDataSize, float fAreaSize  );
	
	void setEnabled( bool value );
	void setAlphaMultiplier( float multiplier );
	void setTemporaryDisabled( bool disabled );

	float getScrollRailSize()	{ return m_fCenterButtonMaxSize;	}
	void setScrollRailSize( float value )	{ m_fCenterButtonMaxSize = value; }
	Button *getButtonTop()	{ return top; }
	Button *getButtonCenter()	{ return center; }
	Button *getButtonBottom()	{ return bottom; }


	void run();

	bool isArrowButtonPushed() { return m_bArrowButtonPushed; }
	bool isScrollRailChangingPosition() { return m_bChangingPosition; }
};



/* Popisek. Je to základní ovládací prvek, který vykresluje nějaký text. Navíc text zalamuje podle šířky objektu
*
*/

class Label : public CBaseComponent
{
protected:
	Color4I m_ColorText;
	int m_iAlign;
	Font *m_pFont;
	virtual void drawOutLines();						//vykreslení okolí ( okrajů )
	virtual void drawText(  ScissorBox &scissorBox );	//vykreslení textu
	virtual void drawOthers( ScissorBox &scissorBox )	{}
	void onScissorBoxResize( float w_offset, float h_offset );
public:
	virtual	bool isFocusable()	{ return false;	}
	Label();
	Label( float w, float h );
	void init();
	void setAlign( int align )	{ m_iAlign = align; }
	void setFont( Font *pFont ) { m_pFont = pFont; }
	void setFont( string sFont ) { m_pFont = fontLibrary::getFont( sFont ); }
	virtual void draw( ScissorBox &scissorBox );
	virtual void setCaption( string text );
	void setColorText( const Color4I &color ) { m_ColorText = color; }

	
};

/* Jednodušší verze popisku bez vykreslování okrajů a s textem zarovnaným na střed vertikálně */
class SimpleLabel : public Label
{
	virtual void drawOutLines()	{}
	virtual void drawText(  ScissorBox &scissorBox );
	void onScissorBoxResize( float w_offset, float h_offset ){}
public:
	SimpleLabel( float w, float h );	
	virtual void setCaption( string text );
	
};

/* Verze popisku bez vykreslování okrajů */
class LabelNoOutline : public Label
{
	virtual void drawOutLines()	{}
public:
	LabelNoOutline( float w, float h );	
};

/* Tento popisek navíc umožňuje rolování pohledu a tak může zobrazovat více textu */
class ScrollLabel : public Label
{
protected:
	Scroll *verticalScroll;		//rolovací panel
	virtual void drawText( ScissorBox &scissorBox );
	virtual void drawOthers( ScissorBox &scissorBox );	//navíc vykresluje rolovací panel
	void onScissorBoxResize( float w_offset, float h_offset );
	void onScissorBoxTranslate( float offsetX, float offsetY );
public:
	bool inputController( int type, float x, float y, int param1, int param2 );
	ScrollLabel( float w, float h );
	~ScrollLabel();
	void setCaption( string text );
	void setEnabled( bool value );
	void setAlphaMultiplier( float multiplier );
	void setTemporaryDisabled( bool disabled );

	void update();
	void run();
};


/*		Třída realizuje panel prvku seznam. Panel obsahuje jednu komponentu a stará se o její ovládání
*/
class CBasePanel : public CBaseComponent
{
protected:
	
	CBaseComponent *m_pComponent;		//ukazatel na komponentu
	void onScissorBoxResize( float w_offset, float h_offset );
	void onScissorBoxTranslate( float offsetX, float offsetY );
public:
	CBasePanel();
	CBasePanel( float w, float h );

	virtual bool inputController( int type, float x, float y, int param1, int param2 );
	virtual void draw( ScissorBox &scissorBox );
	void run();
	virtual ~CBasePanel();

	void setComponent( CBaseComponent *component );
	void setEnabled( bool value );
	void setTemporaryDisabled( bool disabled );
	void setAlphaMultiplier( float multiplier );

};


/*	Seznam - obsahuje objekty třídy CBasePanel. Umožňuje vybrat jeden panel, který pak označí za aktuální
*	a komponentu, kterou panel obsahuje, pak lze ovládat. Přecházet mezi komponentami jde pomocí myši a nebo klávesnice.
*	Obsahuje rolovací panel, takže může zobrazovat více panelů
*/

class ListBox : public CBaseComponent
{
protected:
	float m_iSize;		//celková výška dat
	float m_fTranslate;				//posun prvků
	float m_fAnimatedTranslate;		//hodnota posunu pro animaci
	Scroll *verticalScroll;
	list<CBasePanel*>::iterator m_IterSelectedPanel;	
	list<CBasePanel*> m_Panels;		//seznam panelů
	float checkScrollTranslation();		//funkce zjišťuje hodnotu posunu prvků

	void changeTranslation( float value );	//posunuje panely
	void updateVisibility();				//aktualizuje cílové posunutí ( je snaha, aby aktivní panel byl vždy uprostřed )

	//funkce volané po změně velikosti vlastního objektu
	void onScrollPanelChange();
	void updateScrollSizes();
	void onScissorBoxResize( float w_offset, float h_offset );
	void onScissorBoxTranslate( float offsetX, float offsetY );
	
public:
	ListBox( float w, float h );
	CBasePanel *getSelectedPanel();
	void addPanel( CBasePanel *panel, bool pushBack = true );
	virtual bool inputController( int type, float x, float y, int param1, int param2 );
	virtual void draw( ScissorBox &scissorBox );
	void setEnabled( bool value );
	virtual void run();
	virtual void addComponentToNewPanel( CBaseComponent *component, bool pushBack = true );	//vytvoří nový panel a vloží do něj komponentu
	virtual void removePanel( CBasePanel *panel );	//nepoužívat netestováno
	void removePanel();								//nepoužívat netestováno
	void setAlphaMultiplier( float multiplier );
	void setTemporaryDisabled( bool disabled );
	list<CBasePanel*> *getPanelList()	{ return &m_Panels; }
	void setSelectedPanel( CBasePanel *panel );
	void setSelectedPanel( list<CBasePanel*>::iterator &iter );
	~ListBox();



	/* Padding je kvůli rolovacímu panelu jiné než u ostatních prvků */
	virtual void setPadding( float padding )
	{ 
		m_fPaddingRight = padding + GFG_LABEL_SCROLLBAR_WIDTH;
		m_fPaddingLeft = padding;
		m_fPaddingTop = padding;
		m_fPaddingBottom = padding;
		updateScissorBox();
	}
	virtual void setPaddingRight( float padding )	{ m_fPaddingRight = padding + GFG_LABEL_SCROLLBAR_WIDTH; updateScissorBox();	}
};

/* Třída realizuje objekt, který se vyvolává většinou kvůli dotazu na uživatele. 
*	Obsahuje ukazatel na jednu komponentu, kterou ovládá dle prijatých událostí. Prvek je pak vyvolán hlavním oknem
*/
class CMessageBox : public CBaseComponent
{
private:
	int m_iBoxId;
	CBaseComponent *m_pComponent;
	void updateComponent();
	virtual void onScissorBoxTranslate( float offsetX, float offsetY );
	virtual void onScissorBoxResize( float w_offset, float h_offset );
public:
	CMessageBox()	{ m_iObjectType = GFG_MESSAGEBOX; }
	CMessageBox( float x, float y, float w, float h );
	~CMessageBox();
	void setBoxId( int id )	{ m_iBoxId = id;	}
	int setBoxId()	{ return m_iBoxId;	}
	void setComponent( CBaseComponent *component );
	virtual void setAlphaMultiplier( float multiplier );
	virtual void setEnabled( bool value );
	virtual void setTemporaryDisabled( bool disabled );
	virtual void draw( ScissorBox &scissorBox );
	virtual bool inputController( int type, float x, float y, int param1, int param2 );
	virtual void run();
	virtual bool lostFocusForChilds()	{ return false;	}	//je kořen, takže focus neztrácí

};

enum GFG_msgBoxTypes
{
	GFG_MSGBOX_INFO = 0,
	GFG_MSGBOX_QUESTION,
	GFG_MSGBOX_ALERT,
	GFG_MSGBOX_ERROR
};

//CMainWindow *	GFG_getMainWindow();
//void			GFG_setMainWindow( CMainWindow * w);


/* Ostatní funkce vytvářející nebo nastavující */
Button *		GFG_newButton( std::string caption, int object_ID = 0, float width = 0, float height = 0 );
Button *		GFG_newButton( float width, float height = 0, std::string caption = "" );
Button *		GFG_newButton( int object_ID = 0 );

CMessageBox *GFG_MessageBox_2Buttons( CMainWindow * pMainWindow, GFG_msgBoxTypes type, std::string sQuestion, std::string leftButtonCaption, int leftButtonID,
							 std::string rightButtonCaption, int rightButtonID );
void		GFG_setVisibleWithFocus( CSubWindow *window );
void		GFG_setColorDisabled( Color4I &color );
Color4I &	GFG_getColorDisabled();
GFG_Callback GFG_newCallback( void (*func)( CBaseComponent *, void*), void * data );

void GFG_setCallback_default( GFG_Callback &callback );
GFG_Callback GFG_getCallback_default();


ContainerRelativeUpToDown *GFG_newContainerRelativeUD( bool reverse = false, float vertical_padding = 0.0f, float horizontal_padding = 0.0f );
ContainerRelativeLeftToRight *GFG_newContainerRelativeLR( bool reverse = false, float vertical_padding = 0.0f, float horizontal_padding = 0.0f );
ContainerSemiRelativeUpToDown *GFG_newContainerSemiRelativeUD( bool reverse = false, float vertical_padding = 0.0f, float horizontal_padding = 0.0f );
ContainerSemiRelativeLeftToRight *GFG_newContainerSemiRelativeLR( bool reverse = false, float vertical_padding = 0.0f, float horizontal_padding = 0.0f );
ContainerFixed *GFG_newContainerFixed();
void GFG_setContainer_draw( CBaseContainer *pContainer, bool draw, string caption = "" );

CSubWindow *GFG_newSubWindow( float x, float y, float w, float h, string caption = "", float padding = 5.0f, bool resizable = true );
bool GFG_init();

#endif
