#include"CGUITextBox.h"
#include"CGUIManager.h"
#include"../../Auxiliary/CString.h"

namespace Maid
{
	/*!
	 *	\class	CGUITextBox CGUITextBox.h
	 *	\brief	テキストボックスクラス
	 */


/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! コンストラクタ
/*!
 *
 */
CGUITextBox::CGUITextBox()
{
	m_CursorPos = 0;
	m_TextLengthByte= 30;
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! テキストボックスリスナの設定
/*!
 *	現在入力してあるテキスト表示につかわれるリスナ
 *	ＦＥＰで編集中のテキストは FepListener の仕事です
 *
 *	\param	pListener	[i ]	設定するリスナ
 */
void CGUITextBox::SetListener( const boost::shared_ptr<Listener>& pListener )
{
	m_pListener = pListener;
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! 新しいテキストの設定
/*!
 *	\param	text	[i ]	設定するテキスト
 */
void CGUITextBox::SetText( const mstring& text )
{
	m_InputText = text;
	m_CursorPos = 0;
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! 現在入力されているテキストの設定
/*!
 *	\param	text	[i ]	設定するテキスト
 */
const mstring& CGUITextBox::GetText() const
{
	return m_InputText;
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! 現在入力できる文字の長さの設定
/*!
 *	\param	Length	[i ]	設定する長さ（byte単位)
 */
void CGUITextBox::SetTextLengthByte( unt32 Length )
{
	m_TextLengthByte = Length;
	ClipText();
}


/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! フレーム毎の処理
/*!
 *	引数などは IGUIParts::OnLocalMove を参照すること
 */
void CGUITextBox::OnLocalMove()
{
	if( m_pListener.get()!=NULL ) { m_pListener->OnMove(); }
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! フレーム毎の描画
/*!
 *	引数などは IGUIParts::OnLocalDraw を参照すること
 */
void CGUITextBox::OnLocalDraw( const POINT2DI& pos, CGraphic& Render )
{
	if( m_pListener.get()!=NULL )
	{
		Listener::EDITINFO Info;

		Info.Text = m_InputText;
		Info.Cursor = m_CursorPos;
		Info.pIME = GetOwner()->GetIME();

		m_pListener->OnDraw( pos, Render, Info ); 
	}
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! このパーツ内にカーソルがあるか？
/*!
 *	引数などは IGUIParts::IsLocalCollision を参照すること
 */
bool CGUITextBox::IsLocalCollision( const POINT2DI& pos ) const
{
	return m_pListener->IsCollision(pos);
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! マウスが範囲内に来た時に呼ばれる
/*!
 *	引数などは IGUIParts::OnLocalMouseIn を参照すること
 */
void CGUITextBox::OnLocalMouseIn  ( const POINT2DI& pos )
{
	MAID_ASSERT( m_pListener.get()==NULL, "リスナの設定がされていません" );
	return m_pListener->OnMouseIn();
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! マウスが範囲内から離れた時に呼ばれる
/*!
 *	引数などは IGUIParts::OnLocalMouseOut を参照すること
 */
void CGUITextBox::OnLocalMouseOut ( const POINT2DI& pos )
{
	MAID_ASSERT( m_pListener.get()==NULL, "リスナの設定がされていません" );
	return m_pListener->OnMouseOut();
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! マウスのボタンが押された時に呼ばれる
/*!
 *	引数などは IGUIParts::OnLocalMouseDown を参照すること
 */
void CGUITextBox::OnLocalMouseDown( const POINT2DI& pos )
{
	//	カーソル位置の移動とかやるべきだろうね
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! マウスのボタンが離された時に呼ばれる
/*!
 *	引数などは IGUIParts::OnLocalMouseUp を参照すること
 */
void CGUITextBox::OnLocalMouseUp  ( const POINT2DI& pos )
{
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! マウスのカーソルが動いた時に呼ばれる
/*!
 *	引数などは IGUIParts::OnLocalMouseMove を参照すること
 */
void CGUITextBox::OnLocalMouseMove( const POINT2DI& pos )
{
	//	範囲選択とかやるといいと思う
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! キーボードのキーが押された時に呼ばれる
/*!
 *	引数などは IGUIParts::OnLocalKeyDown を参照すること
 */
void CGUITextBox::OnLocalKeyDown( unt08 KeyCode )
{
	//	キーボードの操作のとおりにカーソルを計算
	switch( KeyCode )
	{
	case CKeybord::BUTTON_LEFT: 
		{
			m_CursorPos = max( 0, m_CursorPos-1 );
		}break;

	case CKeybord::BUTTON_RIGHT:
		{
			int32 NewPos = min( int32(m_InputText.length()), m_CursorPos+1 );
			m_CursorPos = NewPos;
		}break;

	case CKeybord::BUTTON_DELETE:
		{
			if( !(m_CursorPos<(int)m_InputText.length()) ) { break; }
			m_InputText.erase( m_CursorPos, 1 );
			CallBack(GUIMESSAGE_TEXTBOX_CHANGETEXT);
		}break;
	}

}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! 文字コードが入力された時に呼ばれる
/*!
 *	引数などは IGUIParts::OnLocalCharCode を参照すること
 */
void CGUITextBox::OnLocalCharCode( const mstring& CharCode )
{
	if( CharCode.length()==1 )
	{
		switch(CharCode[0])
		{
		case '\b':
			{
				//	バックスペース
				const int32 DelPos = m_CursorPos-1;

				if( DelPos<0 ) { return ; }

				m_InputText.erase( DelPos, 1 );
				m_CursorPos -= 1;
				CallBack(GUIMESSAGE_TEXTBOX_CHANGETEXT);
			}break;

		case '\t':
		case '\n':
		case '\r':
		case 0x1b: { }break;

		default:
			{
				m_InputText.insert( m_CursorPos, CharCode );
				m_CursorPos += (int)CharCode.length();
				CallBack(GUIMESSAGE_TEXTBOX_CHANGETEXT);
			}break;
		}
	}else
	{
		m_InputText.insert( m_CursorPos, CharCode );
		m_CursorPos += (int)CharCode.length();

		CallBack(GUIMESSAGE_TEXTBOX_CHANGETEXT);
	}

	ClipTextNoCallBack();
}



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

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


/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! 設定されている文字の長さにクリッピングする。
/*!
 */
void	CGUITextBox::ClipText()
{
	if( CString::CountByte(m_InputText) <= (int)m_TextLengthByte ) { return ; }

	ClipTextNoCallBack();

	CallBack(GUIMESSAGE_TEXTBOX_CHANGETEXT);
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! 設定されている文字の長さにクリッピングする。コールバックはしない
/*!
 */
void	CGUITextBox::ClipTextNoCallBack()
{
	if( CString::CountByte(m_InputText) <= (int)m_TextLengthByte ) { return ; }

	{
		int byte=0;
		for( int i=0; i<(int)m_InputText.length(); ++i )
		{
			if( CString::IsHankaku(m_InputText[i]) )	{ byte += 1; }
			else							{ byte += 2; }
			if( (int)m_TextLengthByte < byte )
			{
				m_InputText.resize(i);
				break;
			}
		}
	}
/*
	m_InputText.resize(m_TextLength);
*/

	m_CursorPos = min(int(m_CursorPos),int(m_InputText.length()));
}


}
