/*********************************************************************
*	Slider
*	SOURCE FILE
*	Autor:	Michal Jirouš
*	Datum: 2.7.2008
*	Soubor: slider.cpp
*	Popis: Hodnota ze zadaneho intervalu ovladana jezdcem
**********************************************************************/

#include "gfg.h"
#include <sstream>
#include <iomanip>
#include "mathematic.h"
Slider::Slider( float w, float h )
{
	m_Line = NULL;
	m_SliderButton = NULL;
	baseInit( w, h );
	setCaption( "0" );

	//vytvoreni cary
	m_Line = new ComponentLine( m_fWidth, 0 );
	m_Line->setParent( this );
	m_Line->setPosition( 0.0f, m_fHeight * 0.75f  );	//do 3/4 vysky
	
	//vytvoreni jezdce
	m_SliderButton = new Button( GFG_SLIDER_BUTTON_WIDTH, m_fHeight / 2 );	
	m_SliderButton->setParent( this );
	m_SliderButton->setPosition( m_fGlobalXpos, m_fGlobalYpos + m_fHeight / 2 );	//do druhe poloviny
	
	m_fPosition = m_fSize = m_fStartValue = m_fValue = 0.0f;
	m_bChangingPosition = false;
	m_iMoveXpos = m_iMoveYpos = 0;
	m_iNumPositionsForRounding = 0;
	
	//nastaveni vzhledu jezdce
	m_SliderButton->setTextureIdle( "GFG_SLIDER_BUTTON" );
	m_SliderButton->setTexturePushed( "GFG_SLIDER_BUTTON" );
	m_SliderButton->setColorIdle( GFG_COLOR_BUTTON_MOUSEOVER );
	m_SliderButton->setColorMouseOver( GFG_COLOR_BUTTON_CAPTION_MOUSEOVER );
	m_SliderButton->setColorPushed( GFG_COLOR_BUTTON_MOUSEOVER );
	m_SliderButton->setColorPushedMouseOver( GFG_COLOR_BUTTON_CAPTION_MOUSEOVER );
	
	m_ColorBackGround = GFG_COLOR_BUTTON_CAPTION_MOUSEOVER;
	m_iObjectType = GFG_SLIDER;
}

//zmena pozice
void Slider::onScissorBoxTranslate( float offsetX, float offsetY )
{
	if( m_Line )
		m_Line->setPositionOffset( offsetX, offsetY );
	if( m_SliderButton )
		m_SliderButton->setPositionOffset( offsetX, offsetY );
}

//pri zmene velikosti se zmeni velikost cary, ale musi se dopocitat
//nova pozice tlacitka - funkce updateByParameters
void Slider::onScissorBoxResize( float w_offset, float h_offset )
{
	if( m_Line )
	{
		m_Line->setSize( m_ScissorBox.w, 0 );
		m_Line->setPosition( m_ScissorBox.x, m_ScissorBox.y + m_ScissorBox.h * 0.75f );
	}
	if( m_SliderButton )
	{
		updateByParameters();
		m_SliderButton->setYPosition( m_fGlobalYpos + m_fHeight / 2 );
		m_SliderButton->setHeight( m_fHeight / 2 );
	}
}

void Slider::refreshValue()
{
	ostringstream buf;

	if( m_iNumPositionsForRounding > 1 )
	{
		buf << showpoint;
	}
	buf << fixed << right << setprecision(m_iNumPositionsForRounding) << m_fValue;

	setCaption( buf.str() );
	buf.clear();

}

//nastaveni hodnoty
void Slider::setValue( float value )
{ 
	m_fValue = value;
	updateByParameters();
	refreshValue();
}

//zpravy predavane i tlacitku a care
void Slider::setAlphaMultiplier( float multiplier )
{
	m_fAlphaMultiplier = multiplier;
	m_Line->setAlphaMultiplier( multiplier );
	m_SliderButton->setAlphaMultiplier( multiplier );
}

void Slider::setEnabled( bool enabled )
{
	m_bEnabled = enabled;
	m_Line->setEnabled( enabled );
	m_SliderButton->setEnabled( enabled );
}
void Slider::setTemporaryDisabled( bool disabled )
{
	m_bTemporaryDisabled = disabled;
	m_Line->setTemporaryDisabled( disabled );
	m_SliderButton->setTemporaryDisabled( disabled );
}

Slider::~Slider()
{
	delete m_Line;
	delete m_SliderButton;
}

//aktualizace pozice tlacitka novou hodnotou
void Slider::updateByParameters()
{
	m_fPosition = (m_fValue - m_fStartValue) / m_fSize;
	m_fPosition = getFromRange( m_fPosition, 0.0f, 1.0f );
	m_SliderButton->setXPosition( m_fGlobalXpos + m_fPosition * (m_fWidth - m_SliderButton->getWidth() ) );
	
}

//aktualizace dle nove pozice jezdce
void Slider::updateByPosition()
{
	
	m_fPosition = (m_SliderButton->getXPosition() - m_fGlobalXpos) / ( m_fWidth - m_SliderButton->getWidth() );
	m_fPosition = getFromRange( m_fPosition, 0.0f, 1.0f );
	m_fValue = m_fSize * m_fPosition + m_fStartValue;
	m_fValue = round( m_fValue, m_iNumPositionsForRounding );
	
	refreshValue();
}

void Slider::draw(ScissorBox &scissorBox)
{
	if( !m_bVisible )
		return;

	glPushAttrib( GL_CURRENT_BIT | GL_ENABLE_BIT | GL_SCISSOR_BIT );
	glEnable(GL_BLEND);
	glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );

	ScissorBox intersected = m_ScissorBox.intersection( scissorBox );
	
	m_Line->draw( intersected );
	m_SliderButton->draw( intersected );
	glScissor( (GLint)intersected.x, (GLint)intersected.y, (GLint)intersected.w, (GLint)intersected.h );
	setColor( m_ColorBackGround );

	//stred sirky a stred prvni polovnyny vysky
	m_dsCaption.draw( m_fGlobalXpos + m_fWidth/2, m_fGlobalYpos + m_fHeight / 4 );	
	
	glPopAttrib();
}

bool Slider::inputController(int type, float x, float y, int param1, int param2)
{
	if( !m_bVisible || !m_bEnabled )
		return false;

	if( type == GFG_GOT_FOCUS )
		m_bFocused = true;
	else if( type == GFG_LOST_FOCUS )
		m_bFocused = false;
	else if( type & GFG_MOUSE )
	{
		if( type == GFG_MOUSE_BUTTON && param2 == GFG_DOWN)
		{
			//stisknuti jezdce
			if( m_SliderButton->inputController( type, x, y, param1, param2 ) )
			{
				m_bChangingPosition = true;
				m_iMoveXpos = (int)x;
				m_iMoveYpos = (int)y;
				return true;		
			}

			//kliknuti na caru
			if( x > m_Line->getXPosition() && x < m_Line->getXPosition() + m_Line->getWidth() &&
				y > m_Line->getYPosition() - GFG_SLIDER_DETECT_LINE_RANGE && y < m_Line->getYPosition() + GFG_SLIDER_DETECT_LINE_RANGE )
			{
				float newWPos =  getFromRange( x - m_SliderButton->getWidth() / 2.0f, m_fGlobalXpos, m_fGlobalXpos + m_fWidth - m_SliderButton->getWidth() );
				m_SliderButton->setXPosition( newWPos );
					updateByPosition();
				return true;
			}
			
			return false;

		}
		else if( type == GFG_MOUSE_OVER )
		{
			if( m_SliderButton->inputController( type, x, y, param1, param2 ))
				return true;
			return false;
		}
		else if( type == GFG_MOUSE_BUTTON && param2 == GFG_UP )
		{
			if( m_bChangingPosition )
				m_bChangingPosition = false;
		}
		else if( type == GFG_MOUSE_MOTION )
		{
			if( m_bChangingPosition )
			{
				//nova x-ova souradnice jezdce
				float newWPos = m_SliderButton->getXPosition() + x - m_iMoveXpos;
				
				//pokud je uz za hranici komponenty
				if( newWPos < m_fGlobalXpos || newWPos > m_fGlobalXpos+m_fWidth - m_SliderButton->getWidth() )
				{
					//tak musime provest korekci presne na okraj
					newWPos =  getFromRange( newWPos, m_fGlobalXpos, m_fGlobalXpos+m_fWidth - m_SliderButton->getWidth() );
					m_iMoveXpos += (int)(newWPos - m_SliderButton->getXPosition());
				}
				else
				{
					m_iMoveXpos = (int)x;	//jinak jen resetuje pomocnou promennou pohybu
				}
				
				//nastavime novou pozici a provedeme aktualizaci
				m_SliderButton->setXPosition( newWPos );
				updateByPosition();
			}
		}
	}

	return false;
}


void Slider::setValueSize( float size )
{ 
	m_fSize = fabs(size);
	updateByParameters();
}
