#include"CGUISlider.h"

namespace Maid
{
	/*!
	 *	\class	CGUISlider CGUISlider.h
	 *	\brief	スライダクラス
	\n			挙動は Windows のボタンといっしょ
	\n			ボタンが動かせるだけです
	 */

enum PARTSID
{
	PARTSID_BUTTON=0,	//!<	スライダのボタン
};

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! コンストラクタ
/*!
 *
 */
IGUISlider::IGUISlider()
{
	m_MeterBegin  = 0;
	m_MeterLength = 1;
	m_NowMeter = 0;

	m_BarBegin  = 0;
	m_BarLength = 1;

	m_State = STATE_NORMAL;
}


/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! スライダリスナの設定
/*!
 *	\param	pListener	[i ]	設定するリスナ
 */
void	IGUISlider::SetListener(const SPGUISLIDERLISTENER& pListener )
{
	m_pListener = pListener;

	m_BarBegin  = pListener->GetBarBegin();
	m_BarLength = pListener->GetBarLength();

}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! スライダリスナの取得
/*!
 *	\return スライダリスナ
 */
const boost::shared_ptr<IGUISlider::Listener>&	IGUISlider::GetSliderListener() const
{
	return m_pListener;
}


/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! メモリ数の設定
/*!
 *	\param	begin	[i ]	メモリの開始値
 *	\param	len		[i ]	メモリの数
 */
void	IGUISlider::SetMeterRange( int begin, int len )
{
	MAID_ASSERT( len==0, "０は設定できません" );
	m_MeterBegin  = begin;
	m_MeterLength = len;
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! 現在の位置の設定
/*!
 *	GUIMESSAGE_SLIDER_MOVEVALUE メッセージは発行しません
 *
 *	\param	pos	[i ]	新しく設定する位置
 */
void	IGUISlider::SetMeter( int pos )
{
	if( pos < m_MeterBegin                     ){ m_NowMeter = m_MeterBegin;     }
	ef(       m_MeterBegin+m_MeterLength < pos ){ m_NowMeter = m_MeterBegin+m_MeterLength; }
	else										{ m_NowMeter = pos; }
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! 現在の位置の設定
/*!
 *	GUIMESSAGE_SLIDER_MOVEVALUE メッセージを発行します
 *
 *	\param	pos	[i ]	新しく設定する位置
 */
void	IGUISlider::SetMeterCallMessage( int pos )
{
	//	変更前と同じ値ならメッセージは要らない
	int old = m_NowMeter;
	SetMeter( pos );
	
	if( old!=m_NowMeter ) { CallBack(GUIMESSAGE_SLIDER_MOVEVALUE); }
}


/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! 現在の位置の取得
/*!
 *	\return 位置
 */
int	IGUISlider::GetMeter() const
{
	return m_NowMeter;
}


/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! フォーカスがきたときに呼ばれる
/*!
 *	引数などは IGUIParts::OnLocalFocusIn を参照すること
 */
void IGUISlider::OnLocalFocusIn()
{
	MAID_ASSERT( m_pListener.get()==NULL, "リスナの設定がされていません" );
	m_pListener->OnFocusIn();
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! フォーカスがさったときに呼ばれる
/*!
 *	引数などは IGUIParts::OnLocalFocusOut を参照すること
 */
void IGUISlider::OnLocalFocusOut()
{
	MAID_ASSERT( m_pListener.get()==NULL, "リスナの設定がされていません" );
	m_pListener->OnFocusOut();
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! ボタンのある座標の取得
/*!
 *	\return ボタンのある座標
 */
int	IGUISlider::GetButtonPos() const
{
	return m_NowMeter*m_BarLength/m_MeterLength+m_BarBegin;
}


/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! 指定した座標からメーターの値を計算する
/*!
 *	\param	pos	[i ]	座標（IGUISliderの座標系）
 *
 *	\return メーターの値
 */
int	IGUISlider::CalcMeter( int pos ) const
{
	return (pos-m_BarBegin + m_BarLength/m_MeterLength/2)*m_MeterLength/m_BarLength;
}









/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! 横スライダなのか縦スライダなのか決める
/*!
 *	\param	type	[i ]	スライダの方向
 */
void CGUISliderVH::SetSliderType( TYPE type )
{
	m_Type = type;
}



/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! このパーツ内にカーソルがあるか？
/*!
 *	引数などは IGUIParts::IsLocalCollision を参照すること
 */
bool CGUISliderVH::IsLocalCollision( const POINT2DI& pos ) const
{
	MAID_ASSERT( m_pListener.get()==NULL, "リスナの設定がされていません" );

	if( m_State==STATE_MOVE ) { return true; }

	const VECTOR2DI	offset = GetButtonOffset();

	return m_pListener->IsCollisionBar(pos) || m_pListener->IsCollisionButton(pos-offset);
}

void CGUISliderVH::OnLocalMouseIn  ( const POINT2DI& pos )
{
	MAID_ASSERT( m_pListener.get()==NULL, "リスナの設定がされていません" );
	m_pListener->OnMouseIn();
}

void CGUISliderVH::OnLocalMouseOut ( const POINT2DI& pos )
{
	MAID_ASSERT( m_pListener.get()==NULL, "リスナの設定がされていません" );
	m_pListener->OnMouseOut();
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! マウスのボタンが押された時に呼ばれる
/*!
 *	引数などは IGUIParts::OnLocalMouseDown を参照すること
 */
void CGUISliderVH::OnLocalMouseDown( const POINT2DI& pos )
{
	MAID_ASSERT( m_pListener.get()==NULL, "リスナの設定がされていません" );

	//	ボタン内でおしたらドラッグモード
	//	バー内で押したらボタンを動かす


	//	ボタンの位置はメーターの値で変わっているので
	//	その分を加える

	const VECTOR2DI	offset = GetButtonOffset();

	if( m_pListener->IsCollisionButton(pos-offset) )
	{
		m_pListener->OnButtonDown();
		m_State = STATE_MOVE;
	}
	ef( m_pListener->IsCollisionBar(pos) )
	{
		const int meter = CalcMeter(pos);
		SetMeterCallMessage(meter);
		m_pListener->OnButtonDown();
		m_State = STATE_MOVE;
	}
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! マウスのボタンが離された時に呼ばれる
/*!
 *	引数などは IGUIParts::OnLocalMouseUp を参照すること
 */
void CGUISliderVH::OnLocalMouseUp  ( const POINT2DI& pos )
{
	MAID_ASSERT( m_pListener.get()==NULL, "リスナの設定がされていません" );

	switch( m_State )
	{
	case STATE_NORMAL:
		{
		}break;
	case STATE_MOVE:
		{
			m_pListener->OnButtonUp();
			m_State = STATE_NORMAL;
		}break;
	}
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! マウスのカーソルが動いた時に呼ばれる
/*!
 *	引数などは IGUIParts::OnLocalMouseMove を参照すること
 */
void CGUISliderVH::OnLocalMouseMove( const POINT2DI& pos )
{
	MAID_ASSERT( m_pListener.get()==NULL, "リスナの設定がされていません" );
	switch( m_State )
	{
	case STATE_NORMAL:
		{

		}break;

	case STATE_MOVE:
		{
			const int meter = CalcMeter(pos);
			SetMeterCallMessage(meter);
		}break;
	}
}


/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! フレーム毎の処理
/*!
 *	引数などは IGUIParts::OnLocalMove を参照すること
 */
void CGUISliderVH::OnLocalMove()
{
	MAID_ASSERT( m_pListener.get()==NULL, "リスナの設定がされていません" );
	m_pListener->OnMove();
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! フレーム毎の描画
/*!
 *	引数などは IGUIParts::OnLocalDraw を参照すること
 */
void CGUISliderVH::OnLocalDraw( const POINT2DI& pos, CGraphic& Render )
{
	MAID_ASSERT( m_pListener.get()==NULL, "リスナの設定がされていません" );

	const VECTOR2DI	offset = GetButtonOffset();

	m_pListener->OnDraw( pos, pos+offset, Render );
}


VECTOR2DI CGUISliderVH::GetButtonOffset() const
{
	VECTOR2DI	offset(0,0);

	switch(m_Type)
	{
	case TYPE_V: { offset.y = GetButtonPos(); }break;
	case TYPE_H: { offset.x = GetButtonPos(); }break;
	}

	return offset;
}

int	CGUISliderVH::CalcMeter( const POINT2DI& pos )const
{
	int meter = 0;
	switch(m_Type)
	{
	case TYPE_V: { meter = IGUISlider::CalcMeter(pos.y); }break;
	case TYPE_H: { meter = IGUISlider::CalcMeter(pos.x); }break;
	}
	return meter;
}


void CGUISliderVH::OnLocalKeyDown( unt08 KeyCode )
{
	switch(m_Type)
	{
	case TYPE_V:
		{
			switch(KeyCode)
			{
			case CKeybord::BUTTON_UP:  { SetMeterCallMessage(m_NowMeter-1); }break;
			case CKeybord::BUTTON_DOWN:{ SetMeterCallMessage(m_NowMeter+1); }break;
			}
		}break;

	case TYPE_H:
		{
			switch(KeyCode)
			{
			case CKeybord::BUTTON_LEFT: { SetMeterCallMessage(m_NowMeter-1); }break;
			case CKeybord::BUTTON_RIGHT:{ SetMeterCallMessage(m_NowMeter+1); }break;
			}
		}break;
	}
}


}
