//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "MultiSwitchProgFormUnit.h"
#include "GlobalUnit.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "PNGButton"
#pragma link "GeneralDialogPanel"
#pragma link "TextButton"
#pragma resource "*.dfm"
TMultiSwitchProgForm *MultiSwitchProgForm;
//---------------------------------------------------------------------------
__fastcall TMultiSwitchProgForm::TMultiSwitchProgForm(TComponent* Owner, TCommonItem *pItem)
	: TForm(Owner)
{
	m_pItem = pItem;

	mData = new TList();
	ItemChange = new TList();
	mCurrentItem = NULL;

	if( pItem->iType==SEGTYPE_STYLE || pItem->iType==SEGTYPE_TRACK ){
		InitProgListPanel();
		InitInsTypePanel();
		InitInsPanel();

		if( pItem->iType==SEGTYPE_TRACK ){
			GeneralDialogPanel->Caption = L"更换音色/乐器";
		}
	}

	SetTransparent( this );
}
//---------------------------------------------------------------------------
__fastcall TMultiSwitchProgForm::~TMultiSwitchProgForm()
{
	if(mData) {
		mData->Clear();
		delete mData;
		mData = NULL;
	}

	if(ItemChange) {
		ItemChange->Clear();
		delete ItemChange;
		ItemChange = NULL;
    }
}
//---------------------------------------------------------------------------
void __fastcall TMultiSwitchProgForm::InitProgListPanel()
{
	if( m_pItem->iType==SEGTYPE_STYLE ){
		for(int i = 0; i < m_pItem->aItems->Count; i++) {
			TSegmentItem *SegItem = (TSegmentItem *)m_pItem->aItems->Items[i];

			for(int c = 0; c < SegItem->aItems->Count; c++) {
				TTrackItem *TrackItem = (TTrackItem *) SegItem->aItems->Items[c];
				char prog = TrackItem->pTrack->iProg,// >progCurr,
					chan = TrackItem->pTrack->iChanNo;

				ProgListData *progData = CheckData( chan, prog );

				if(!progData) {
					String strInst = chan==9 ? "GM鼓" : GM_INSTRUMENT[prog];
					progData = new ProgListData( strInst, prog, chan );
					if( progData->Channel==9 )
						mData->Insert( 0, progData );
					else
						mData->Add(progData);
				}

				String strText = g_strSegment[SegItem->iType];
				strText += String("-") + (int)(SegItem->iInd+1);

				if( SegItem->iSegType>=SEGTYPE_INTRO ){
					if( SegItem->iSegNo<4 )
						strText += " 大调" ;
					else
						strText += " 小调" ;
				}

				progData->List->Add(new ProgItemData( strText, TrackItem));
			}
		}
	}
	else{
		TTrackItem *TrackItem = (TTrackItem *) m_pItem;
		TSegmentItem *SegItem = (TSegmentItem *)m_pItem->up;

		char prog = TrackItem->pTrack->iProg,// >progCurr,
			chan = TrackItem->pTrack->iChanNo;

		ProgListData *progData = CheckData( chan, prog );

		if(!progData) {
			String strInst = chan==9 ? "GM鼓" : GM_INSTRUMENT[prog];
			progData = new ProgListData( strInst, prog, chan );
			if( progData->Channel==9 )
				mData->Insert( 0, progData );
			else
				mData->Add(progData);
		}

		String strText = g_strSegment[SegItem->iType];
		strText += String("-") + (int)(SegItem->iInd+1);

		if( SegItem->iSegType>=SEGTYPE_INTRO ){
			if( SegItem->iSegNo<4 )
				strText += " 大调" ;
			else
				strText += " 小调" ;
		}

		progData->List->Add(new ProgItemData( strText, TrackItem));
    }

	mProgListPanel = new TProgHandlePanel(this);
	mProgListPanel->Width = 160;
	mProgListPanel->Height = 225;
	mProgListPanel->Top = m_ShapeCur->Top+m_ShapeCur->Height-1;
	mProgListPanel->Left = 15;
	mProgListPanel->Parent = this;
	mProgListPanel->OnSelectedItem = DoProListSelect;
	mProgListPanel->SetTextFont(g_strTxtFontName, g_szFont9);

	m_ShapeCur->Left = mProgListPanel->Left;
	m_ShapeCur->Width = mProgListPanel->Width;
	m_lbCurProg->Left = m_ShapeCur->Left+(m_ShapeCur->Width-m_lbCurProg->Width)/2;
	m_lbCurProg->Top = m_ShapeCur->Top+(m_ShapeCur->Height-m_lbCurProg->Height)/2;

	for(int i = 0; i < mData->Count; i++) {
		ProgListData *data = (ProgListData *)mData->Items[i];

		TProgHandleItem *Item = new TProgHandleItem(mProgListPanel, data->Caption);
		Item->IsUnfold = false;
		Item->Data = data;

		for(int di = 0; di < data->List->Count; di++) {
			ProgItemData *it = (ProgItemData *)data->List->Items[di];

			bool itemExist = false;

			for(int dci = 0; dci < Item->ChildCount; dci++) {
				if(Item->Child(dci)->Caption == it->Caption)
					itemExist = true;
			}

			if(!itemExist)
				new TProgHandleItem(Item, it->Caption)->Data = it;
		}
	}
}
//---------------------------------------------------------------------------
void __fastcall TMultiSwitchProgForm::InitInsTypePanel()
{
	mInsTypePanel = new TListPanel(this);
	mInsTypePanel->Left = 190;
	mInsTypePanel->Top = m_ShapType->Top+m_ShapType->Height-1;
	mInsTypePanel->Height = 225;
	mInsTypePanel->Width = 120;
	mInsTypePanel->Parent = this;
	mInsTypePanel->SetTextFont(g_strTxtFontName, g_szFont9);

	m_ShapType->Left = mInsTypePanel->Left;
	m_ShapType->Width = mInsTypePanel->Width;
	m_lbType->Left = m_ShapType->Left+(m_ShapType->Width-m_lbType->Width)/2;
	m_lbType->Top = m_ShapType->Top+(m_ShapType->Height-m_lbType->Height)/2;
}
//---------------------------------------------------------------------------
void __fastcall TMultiSwitchProgForm::InitInsPanel()
{
	mInsPanel = new TListPanel(this);
	mInsPanel->Left = 325;
	mInsPanel->Top = m_ShapeProg->Top+m_ShapeProg->Height-1;
	mInsPanel->Height = 225;
	mInsPanel->Width = 120;
	mInsPanel->Parent = this;
	mInsPanel->SetTextFont(g_strTxtFontName, g_szFont9);

	m_ShapeProg->Left  = mInsPanel->Left;
	m_ShapeProg->Width = mInsPanel->Width;
	m_lbProg->Left = m_ShapeProg->Left+(m_ShapeProg->Width-m_lbProg->Width)/2;
	m_lbProg->Top = m_ShapeProg->Top+(m_ShapeProg->Height-m_lbProg->Height)/2;
}
//---------------------------------------------------------------------------
ProgListData *TMultiSwitchProgForm::CheckData( char chan, char prog )
{
	for(int i = 0; i < mData->Count; i++) {
		ProgListData *d = (ProgListData *) mData->Items[i];

		if( prog==d->Prog && ( chan==9 && d->Channel==9
							|| chan!=9 && d->Channel!=9 ) ){
			return d;
		}
	}

	return NULL;
}
//---------------------------------------------------------------------------
void __fastcall TMultiSwitchProgForm::DoProListSelect(TObject *Sender)
{
	TProgHandleItem *Item = (TProgHandleItem *)Sender;
	TProgHandleItem *CurrentItem = mCurrentItem;

	if( Item && Item->Parent )
		Item = Item->Parent;

	if( CurrentItem==Item )
		return;
	else
		mCurrentItem = Item;

	if( Item==NULL ){
		mProgListPanel->DoSelectedItem( NULL );
		mInsTypePanel->Clear();
		mInsTypePanel->ResetScroll();
		mInsPanel->Clear();
		mInsPanel->ResetScroll();

		return;
	}

	ProgListData *data = (ProgListData *)Item->Data,
		*dataOld = CurrentItem ? (ProgListData*)CurrentItem->Data : NULL;

	int groupNew = data->Channel==9 ? 0 : ( data->Prog >> 3 ),
		groupOld = dataOld ? ( dataOld->Channel==9 ? 0 : ( dataOld->Prog >> 3 )) : -1;

	if( dataOld==NULL || data->Channel==9 && dataOld->Channel!=9
						|| data->Channel!=9 && dataOld->Channel==9 ){
		if( dataOld ){
			mInsTypePanel->Clear();
			groupOld = -1;
		}

		if( data->Channel==9 ){
			m_lbProg->Caption = "鼓组";
			mInsTypePanel->AddItem(new TListPanelItem("预设鼓组", DoInsTypeClick));
		}
		else{
			m_lbProg->Caption = "乐器";
			for(int i = 0; i < 16; i++) {
				mInsTypePanel->AddItem(new TListPanelItem(GM_GROUP[i], DoInsTypeClick));
			}
		}

		mInsTypePanel->ResetScroll();
	}

	mInsTypePanel->SelectedItemIndex = groupNew;

	int iIndex = data->Channel==9 ? mInsPanel->SelectedItemIndex : data->Prog & 0x07;

	if( groupOld!=groupNew ){
		mInsPanel->Clear();

		if( data->Channel==9 ){
			FONTINFO *pFont = g_lstFonts[g_idFont];
			iIndex = -1;

			for( int i = 0; i < pFont->nDrumCount; i++ ){
				FONTPRESET& set = pFont->aDrums[i];
				mInsPanel->AddItem( new TListPanelItem( set.text, DoInsClick ));

				if( set.id==data->Prog ){
					iIndex = i;
				}
			}
		}
		else{
			int base = groupNew<<3;
			for(int i = 0; i < 8; i++) {
				mInsPanel->AddItem(new TListPanelItem(GM_INSTRUMENT[base + i], DoInsClick));
			}
		}

		mInsPanel->ResetScroll();
	}

	mInsPanel->SelectedItemIndex = iIndex;
}
//---------------------------------------------------------------------------
void __fastcall TMultiSwitchProgForm::DoInsTypeClick(TListPanel *Sender, int Index)
{
	if( mCurrentItem == NULL || mInsPanel->SelectedItemIndex==Index )
		return;

	mInsPanel->Clear();

	ProgListData *data = (ProgListData *) mCurrentItem->Data;
	int base = Index << 3;

	for( int i = 0; i < 8; i++ ){
		mInsPanel->AddItem(new TListPanelItem(GM_INSTRUMENT[base + i], DoInsClick));
	}

	mInsPanel->ResetScroll();

	if( Index==(data->Prog >> 3) )
		mInsPanel->SelectedItemIndex = data->Prog & 0x07;
}
//---------------------------------------------------------------------------
void __fastcall TMultiSwitchProgForm::DoInsClick(TListPanel *Sender, int Index)
{
	if( mCurrentItem == NULL )
		return;

	ProgListData *data = (ProgListData *) mCurrentItem->Data;
	TProgHandleItem *CurrentItem = mCurrentItem;

	if( data->Channel==9 ){
		data->Prog = g_lstFonts[g_idFont]->aDrums[Index].id;
		CurrentItem->Caption = data->Caption + L"*";
	}
	else{
		int type = mInsTypePanel->SelectedItemIndex;
		int ins = Index;
		data->Prog = ( type << 3 ) + ins;

		if( data->ProgBak == data->Prog )
			CurrentItem->Caption = String(GM_INSTRUMENT[data->Prog]);
		else
			CurrentItem->Caption = String(GM_INSTRUMENT[data->Prog]) + L"*";
    }
}
//---------------------------------------------------------------------------
void __fastcall TMultiSwitchProgForm::DoReset(TObject *Sender)
{
	for( int i = 0; i < mProgListPanel->TopLevelItemCount; i++ ){
		TProgHandleItem *Item = mProgListPanel->GetTopLevelItem(i);
		ProgListData *data = (ProgListData *)Item->Data;

		if( data->Prog != data->ProgBak ){
			data->Prog = data->ProgBak;

			Item->Caption = data->Channel==9 ? data->Caption : String( GM_INSTRUMENT[data->Prog] );
		}
	}

	DoProListSelect( NULL );
}
//---------------------------------------------------------------------------
void __fastcall TMultiSwitchProgForm::DoOkClick(TObject *Sender)
{
	for(int pIndex = 0; pIndex < this->mProgListPanel->TopLevelItemCount; pIndex++) {
		TProgHandleItem *pItem = mProgListPanel->GetTopLevelItem(pIndex);

		ProgListData *pData = (ProgListData *)pItem->Data;

		for(int cIndex = 0; cIndex < pItem->ChildCount; cIndex++) {
			TProgHandleItem *cItem = pItem->Child(cIndex);

			ProgItemData *cData = (ProgItemData *)cItem->Data;

			//TTrackItem *TrackItem = (TTrackItem *)cData->Item;

			if(cItem->IsChecked) {
				for(int dIndex = 0; dIndex < pData->List->Count; dIndex++) {
					ProgItemData *itemData = (ProgItemData *)pData->List->Items[dIndex];
					if(itemData->Caption == cData->Caption) {
						TTrackItem *pTrack = (TTrackItem *)itemData->Item;
						if( pTrack->pTrack->iProg !=pData->Prog ){
							pTrack->pTrack->iProg = pData->Prog;
							ItemChange->Add(pTrack);
						}
                    }
				}
			}
        }
	}

	ModalResult = mrOk;
}
//---------------------------------------------------------------------------

void __fastcall TMultiSwitchProgForm::FormShow(TObject *Sender)
{
	if( mProgListPanel->TopLevelItemCount>0 ){
		TProgHandleItem *pItem = mProgListPanel->GetTopLevelItem( 0 );
		mProgListPanel->DoSelectedItem( pItem );
		pItem->IsSelected = true;
	}
	else{
		mOKButton->Enabled = false;
        mResetButton->Enabled = false;
    }
}
//---------------------------------------------------------------------------

void __fastcall TMultiSwitchProgForm::FormCreate(TObject *Sender)
{
	GeneralDialogPanel->Font->Name = g_strTxtFontName;
	GeneralDialogPanel->Font->Size = g_szFont9;

//	mResetButton->FontName = g_strTxtFontName;
	mResetButton->FontSize = g_szFont9;
//	mCancelButton->FontName = g_strTxtFontName;
	mCancelButton->FontSize = g_szFont9;
//	mOKButton->FontName = g_strTxtFontName;
	mOKButton->FontSize = g_szFont9;
}
//---------------------------------------------------------------------------

