/*-----------------------------------------------------------------------------
[名称]	CharPaletteDlg.cpp
[概要]	文字パレットダイアログクラスの実装
[備考]	なし
[履歴]	2003-02-26	NC		コメント付加(moralog)
-----------------------------------------------------------------------------*/


//-----------------------------------------------------------------------------
// インクルード
//-----------------------------------------------------------------------------
#include "stdafx.h"
#include "shitarabian.h"

#include "ExeCommon.h"

#include "CommandInput.h"
#include "CommandManager.h"
#include "ShitarabianDoc.h"
#include "ShitarabianView.h"
#include "MainFrm.h"
#include "Selection.h"
#include "OwnerTabCtrl.h"

#include "CharPaletteDlg.h"
#include "CharPalette.h"
#include "CharPaletteCanvasDlg.h"
#include "CharPaletteSettingDlg.h"
#include "GeneralSetting.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif


/*-----------------------------------------------------------------------------
[名称]	コンストラクタ
[機能]	インスタンスの生成。
[戻値]	なし
[備考]	なし
-----------------------------------------------------------------------------*/
CCharPaletteDlg::CCharPaletteDlg(CWnd* pParent /*=NULL*/)
:	CDialog(CCharPaletteDlg::IDD, pParent)
,	m_paCharPalettez( NULL )
,	m_ptabPalette( NULL )
,	m_aCanvas( NULL )
,	m_bFore( TRUE )
,	m_sizeButton( 30, 30 )
,	m_eScrollBarAlign( ScrollBarAlignBottom )
,	m_eTabAlign( ScrollBarAlignTop )
,	m_pMainFrame( NULL )
{
	//{{AFX_DATA_INIT(CCharPaletteDlg)
		// メモ - ClassWizard はこの位置にマッピング用のマクロを追加または削除します。
	//}}AFX_DATA_INIT
}


/*-----------------------------------------------------------------------------
[名称]	デストラクタ
[機能]	インスタンスの破棄。
[戻値]	なし
[備考]	なし
-----------------------------------------------------------------------------*/
CCharPaletteDlg::~CCharPaletteDlg()
{
	if( m_aCanvas != NULL )
	{
		delete [] m_aCanvas;
		m_aCanvas = NULL;
	}

	if( m_ptabPalette != NULL )
	{
		delete m_ptabPalette;
		m_ptabPalette = NULL;
	}
}


/*-----------------------------------------------------------------------------
[名称]	データ変換
[機能]	CDialog::DoDataExchange() のヘルプを参照。
[戻値]	なし
[備考]	なし
-----------------------------------------------------------------------------*/
void CCharPaletteDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CCharPaletteDlg)
	//}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(CCharPaletteDlg, CDialog)
	//{{AFX_MSG_MAP(CCharPaletteDlg)
	ON_WM_SIZE()
	ON_WM_SHOWWINDOW()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()


/*-----------------------------------------------------------------------------
[名称]	確定（ボタン押下ハンドラ）
[機能]	対応する文字列をメインウィンドウにペースト。
[戻値]	なし。
[備考]	なし
-----------------------------------------------------------------------------*/
void CCharPaletteDlg::ConfirmChar(
	CString&	strChar
) 
{
	CShitarabianDoc*	pDoc = ::GetDocument();

	// 履歴に追加
	CString	strHistoryTab = CGeneralSetting::GetInstance()->GetCharPaletteManager()->HistoryTabName();
	UINT	nMaxChar	= CGeneralSetting::GetInstance()->GetCharPaletteManager()->m_uiHistoryCount;
	{
		// タブ"[ 履歴 ]"を探す
		for ( int idxTab=0 ; idxTab<m_paCharPalettez->GetSize() ; idxTab++ )
		{
			if( (*m_paCharPalettez)[idxTab].GetName() == strHistoryTab )
			{
				break;
			}
		}

		// 履歴タブがなければ追加する
		if ( idxTab == m_paCharPalettez->GetSize() )
		{
			CCharPalette	CharPalette;
			CharPalette.SetName( strHistoryTab );
			m_paCharPalettez->Add( CharPalette );

			RebuildTab( m_eTabAlign );
		}

		// 開いているタブが履歴の時はソートしたくない可能性がある
		BOOL	bSort	= CGeneralSetting::GetInstance()->GetCharPaletteManager()->m_bHistorySort;
		bSort |= ( m_ptabPalette->GetCurFocus() != idxTab );

		// ソートを伴う文字列の追加
		CStringArray*	pastrCharz = (*m_paCharPalettez)[idxTab].GetCharz();
		if ( bSort )
		{
			// パレット内に同じ文字列があるかを検査
			for ( int idxChar=0 ; idxChar<pastrCharz->GetSize() ; idxChar++ )
			{
				if( (*pastrCharz)[idxChar] == strChar )
				{
					// あれば該当セルを削除
					pastrCharz->RemoveAt( idxChar );
					break;
				}
			}

			// 先頭に確定文字列を追加
			pastrCharz->InsertAt( 0, strChar );
		}

		// 多すぎれば削る
// ▼ (ワーニング回避) BGN 2003.12.29 (moralog) warning C4018
		if( pastrCharz->GetSize() > (long)nMaxChar )
// ▽ original BGN
//		if( pastrCharz->GetSize() > nMaxChar )
// △ original END
// ▲ (ワーニング回避) END
		{
			pastrCharz->SetSize( nMaxChar );
		}

		// 再描画
		m_ptabPalette->ReflectPagez();
		m_aCanvas[idxTab].RePositionControl();
	}

	// 文字挿入　please! 上書きシチュエーションが考慮されていない。
					// 文字挿入は共通関数化すべき？ExeCommandManをつかうべきのような！
	{

		CCommandInput	cmdInput;
		int idxRow = pDoc->GetCaretRow();
		int idxColumn = pDoc->GetCaretColumn();
		cmdInput.SetAttribute( strChar, idxRow, idxColumn );
		cmdInput.Execute( pDoc );

		CCommandManager*	pCmd = CCommandManager::GetInstance();
		pCmd->Add( cmdInput );

		pDoc->GetSelection()->SetSelectedNutral();
	}
	ToMainWindow();
}


/*-----------------------------------------------------------------------------
[名称]	メインへ復帰
[機能]	フォーカスをビューに移す。
[戻値]	なし
[備考]	なし
-----------------------------------------------------------------------------*/
void CCharPaletteDlg::ToMainWindow()
{
	CShitarabianDoc*	pDoc = ::GetDocument();
	// フォーカスをビューに移す
	CWnd*	pwndView = pDoc->GetMainView();
	if ( pwndView != NULL )
	{
		pwndView->SetFocus();
	}

	// 表示更新
	pDoc->ReDraw();
}


/*-----------------------------------------------------------------------------
[名称]	メッセージハンドラ
[機能]	キー入力を処理。
[戻値]	CDialog::PreTranslateMessage() のヘルプを参照。
[備考]	なし
-----------------------------------------------------------------------------*/
BOOL CCharPaletteDlg::PreTranslateMessage(MSG* pMsg) 
{
	switch( pMsg->message )
	{
	case WM_KEYDOWN:
		{
// ▼ (ワーニング回避) BGN 2003.12.29 (moralog) warning C4189
// ▽ original BGN
//			BOOL	bMove = FALSE;
// △ original END
// ▲ (ワーニング回避) END
			switch( pMsg->wParam )
			{
			// 取り消し
			case VK_ESCAPE:
				// メインウィンドウをアクティブにする
				ToMainWindow();
				break;

			// タブキーでタブ移動
			case VK_TAB:
				if ( ::GetAsyncKeyState( VK_SHIFT ) &0x8000 )
				{
					int		idxTab = m_ptabPalette->GetCurFocus();
					if( idxTab > 0 )
					{
						m_ptabPalette->SetCurFocus( idxTab - 1 );
					}
					else
					{
						m_ptabPalette->SetCurFocus( m_ptabPalette->GetItemCount()-1 );
					}
				}
				else
				{
					int		idxTab = m_ptabPalette->GetCurFocus();
					if( idxTab < m_ptabPalette->GetItemCount()-1 )
					{
						m_ptabPalette->SetCurFocus( idxTab + 1 );
					}
					else
					{
						m_ptabPalette->SetCurFocus( 0 );
					}
				}
				break;

			default:
				break;
			}
		}
		return( TRUE );
		break;

	default:
		break;
	}

	// キー入力以外のイベント処理
	return CDialog::PreTranslateMessage(pMsg);
}


/*-----------------------------------------------------------------------------
[名称]	初期化ハンドラ
[機能]	ボタン位置の初期化。
[戻値]	CDialog::OnInitDialog() のヘルプを参照。
[備考]	なし
-----------------------------------------------------------------------------*/
BOOL CCharPaletteDlg::OnInitDialog() 
{
	CDialog::OnInitDialog();

	RebuildTab( m_eTabAlign );

	return TRUE;  // コントロールにフォーカスを設定しないとき、戻り値は TRUE となります
	              // 例外: OCX プロパティ ページの戻り値は FALSE となります
}


/*-----------------------------------------------------------------------------
[名称]	パレット情報のアタッチ
[機能]	パレット情報化からページを生成する。
[戻値]	なし
[備考]	なし
-----------------------------------------------------------------------------*/
void CCharPaletteDlg::Attach(
	CArray< CCharPalette, CCharPalette& >* paCharPalettez	// I  :文字パレット情報群 [-] (-) :-
)
{
	m_paCharPalettez = paCharPalettez;

	// タブページの設定
	if ( m_ptabPalette != NULL )
	if ( m_paCharPalettez != NULL )
	{
		// ページの破棄
		if( m_aCanvas != NULL )
		{
			delete [] m_aCanvas;
		}
		if ( m_paCharPalettez->GetSize() > 0 )
		{
			m_aCanvas = new CCharPaletteCanvasDlg[ m_paCharPalettez->GetSize() ];
		}
		m_ptabPalette->DeleteAllItems();

		for ( int idxTab = 0 ; idxTab < m_paCharPalettez->GetSize() ; idxTab++ )
		{
			// タブの中のページを作成
			m_aCanvas[idxTab].Create( IDD_CHARPALETTE_CANVAS, m_ptabPalette );

			// ページの設定
			m_aCanvas[idxTab].SetScrollBarAlign( m_eScrollBarAlign );
			m_aCanvas[idxTab].Attach( this );
			m_aCanvas[idxTab].Attach( idxTab );
			m_aCanvas[idxTab].SetButtonSize( m_sizeButton );

			// タブに追加
			m_ptabPalette->InsertItem(
				TCIF_TEXT|TCIF_PARAM,
				idxTab,
				m_paCharPalettez->GetAt(idxTab).GetName(),
				0,
				(LPARAM)&(m_aCanvas[idxTab])
			);
		}
	}
}


/*-----------------------------------------------------------------------------
[名称]	サイズ変更ハンドラ
[機能]	ダイアログサイズ変更に伴うコントロールの再配置処理。
[戻値]	なし
[備考]	なし
-----------------------------------------------------------------------------*/
void CCharPaletteDlg::OnSize(UINT nType, int cx, int cy) 
{
	CDialog::OnSize(nType, cx, cy);
	
	if ( m_ptabPalette != NULL )
	if( ::IsWindow(m_ptabPalette->m_hWnd) )
	{
		m_ptabPalette->SetWindowPos(
			NULL,
			0, 0,
			cx, cy,
			SWP_NOMOVE|SWP_NOOWNERZORDER
		);

		if ( ::IsWindow(m_ptabPalette->m_hWnd))
		{
			m_ptabPalette->ReflectPagez();
		}
	}
}


/*-----------------------------------------------------------------------------
[名称]	タブコントロール再構築
[機能]	アライメント変更などを受けてタブコントロールを再構築する。
[戻値]	なし
[備考]	なし
-----------------------------------------------------------------------------*/
void CCharPaletteDlg::RebuildTab(
	EScrollBarAlign	eAlign		// I  : 配置情報 [-] (-) :-
)
{
	LONG	lFlag = 0;
	switch( eAlign )
	{
	case ScrollBarAlignTop:
		lFlag = 0;
		break;
	case ScrollBarAlignBottom:
		lFlag = TCS_BOTTOM;
		break;
	case ScrollBarAlignLeft:
		lFlag = TCS_VERTICAL;
		break;
	case ScrollBarAlignRight:
		lFlag = TCS_VERTICAL | TCS_BOTTOM;
		break;
	default:
		break;
	}

	if( m_ptabPalette != NULL )
	{
		delete m_ptabPalette;
	}

	CRect	rcClient;
	GetClientRect( &rcClient );
	m_ptabPalette = new COwnerTabCtrl;
	m_ptabPalette->Create(
		lFlag | TCS_MULTILINE,
		rcClient,
		this,
		IDC_CHARPALETTETAB
	);
	m_ptabPalette->SetFont( GetFont(), FALSE );
	m_ptabPalette->ShowWindow( SW_SHOW );

	Attach( m_paCharPalettez );
	m_ptabPalette->ReflectPagez();
}


/*-----------------------------------------------------------------------------
[名称]	スクロールバー配置
[機能]	パレットページのスクロールバー位置を設定する。
[戻値]	なし
[備考]	なし
-----------------------------------------------------------------------------*/
void CCharPaletteDlg::SetScrollBarAlign(
	EScrollBarAlign eAlign
)
{
	m_eScrollBarAlign = eAlign;
	for ( int idxTab = 0 ; idxTab < m_paCharPalettez->GetSize() ; idxTab++ )
	{
		m_aCanvas[idxTab].SetScrollBarAlign( m_eScrollBarAlign );
		m_aCanvas[idxTab].RePositionControl();
	}
}


/*-----------------------------------------------------------------------------
[名称]	タブ配置
[機能]	タブの位置を設定してタブを再構築する。
[戻値]	なし
[備考]	なし
-----------------------------------------------------------------------------*/
void CCharPaletteDlg::SetTabAlign(
	EScrollBarAlign eAlign
)
{
	m_eTabAlign = eAlign;
	RebuildTab( m_eTabAlign );
}


/*-----------------------------------------------------------------------------
[名称]	ボタンサイズ変更
[機能]	パレットページのボタンサイズを変更する。
[戻値]	なし
[備考]	なし
-----------------------------------------------------------------------------*/
void CCharPaletteDlg::SetButtonSize(
	CSize	sizeButton
)
{
	m_sizeButton = sizeButton;
	for ( int idxTab = 0 ; idxTab < m_paCharPalettez->GetSize() ; idxTab++ )
	{
		m_aCanvas[idxTab].SetButtonSize( sizeButton );
		m_aCanvas[idxTab].RePositionControl();
	}
}


/*-----------------------------------------------------------------------------
[名称]	ウィンドウ表示ハンドラ
[機能]	パレットページの構築。
[戻値]	なし
[備考]	CDialog::OnShowWindow() のヘルプを参照。
-----------------------------------------------------------------------------*/
void CCharPaletteDlg::OnShowWindow(BOOL bShow, UINT nStatus) 
{
	CDialog::OnShowWindow(bShow, nStatus);
	
	m_ptabPalette->ReflectPagez();
}


/*-----------------------------------------------------------------------------
[名称]	タブにフォーカスを当てる
[機能]	タブにフォーカスを当てる。
[戻値]	なし
[備考]	なし
-----------------------------------------------------------------------------*/
void CCharPaletteDlg::SetTabFocus()
{
	m_ptabPalette->SetFocus();
}

