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

#pragma hdrstop

#include "ListPanel.h"
#include "GlobalUnit.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)

#define LP_ITEM_OVER		RGB(67, 73, 80)
#define LP_ITEM_SELECTED	RGB(29, 31, 35)
#define LP_ITEM_DEF			RGB(47, 50, 57)

#define IS_OVER			1
#define IS_SELECTED		2
#define IS_UNSELECTED	3
//---------------------------------------------------------------------------
__fastcall TListPanelItem::TListPanelItem(String Caption, TListPanelItemClick OnItemClick)
{
    FCaption = Caption;
	FOnItemClick = OnItemClick;
	Tag = 0;
}
//---------------------------------------------------------------------------
void __fastcall TListPanelItem::DrawItem(TCanvas *Canvas, TRect Rect, int flag)
{
	switch (flag) {
	case IS_OVER:
		Canvas->Brush->Color = LP_ITEM_OVER;
		break;

	case IS_SELECTED:
		Canvas->Brush->Color = LP_ITEM_SELECTED;
		break;

    default:
		Canvas->Brush->Color = LP_ITEM_DEF;
	}

    /* 绘制背景 */
	Canvas->FillRect(Rect);

	Canvas->Font->Color = TColor(RGB(201, 214, 229));

    /* 绘制文字 */
    int var_TextRectTop = Rect.Top + (Rect.Height() - Canvas->TextHeight(FCaption)) / 2;

	TRect var_TextRect(4, var_TextRectTop, Rect.Right - 4, Rect.Bottom);

    Canvas->TextRect(var_TextRect, FCaption);
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
#define LP_BORDER 		    RGB(106, 111, 117)
#define LP_BACKGRND	        RGB(47, 50, 57)//39, 42, 47)

#define LP_BORDER_HL	    RGB(30, 32, 36)
#define LP_BACKGRND_HL	    RGB(67, 73, 80)

#define LP_TXT_NOR          RGB(213, 221, 232)
#define LP_TXT_DISABLE      RGB(100, 108, 119)
#define LP_BREAK		    RGB(100, 108, 119)
#define LP_BOARD_FILL       RGB(76, 82, 91)

#define MIN(x, y)			((x) < (y) ? (x) : (y))
#define MAX(x, y)			((x) > (y) ? (x) : (y))

#define MARGIN				2
//---------------------------------------------------------------------------
__fastcall TListPanel::TListPanel(TComponent *Owner) : TPanel(Owner)
{
//    m_ItemRectList 	= new TList();
	m_ItemList 		= new TList();

	Canvas->Font->Color = LP_TXT_NOR;

	FItemHeight 	= 20;
    FSelectedItemIndex 	= -1;

    m_CurrentItemIndex 	= -1;
    m_RealShowCount 	= 0;

	m_BeginIndex = 0;
	m_EndIndex = 0;

	m_IsLButtonDown = false;

	m_ScrollBar = new TSkinScrollBar(NULL);
	m_ScrollBar->Visible = false;
}
//---------------------------------------------------------------------------
__fastcall TListPanel::~TListPanel()
{
/*	if(m_ItemRectList)
	{
		for( int i=0; i<m_ItemRectList->Count; i++ ){
			delete m_ItemRectList->Items[i];
		}

		m_ItemRectList->Clear();
		delete m_ItemRectList;
		m_ItemRectList = NULL;
	}
*/
	for( int i=0; i<m_ItemList->Count; i++ ){
		delete m_ItemList->Items[i];
	}

	m_ItemList->Clear();
	delete m_ItemList;
	m_ItemList = NULL;

    if(m_ScrollBar)
    {
        delete m_ScrollBar;
        m_ScrollBar = NULL;
    }
}
//---------------------------------------------------------------------------
void __fastcall TListPanel::AddItem(TListPanelItem* Item)
{
	m_ItemList->Add(Item);

/*	if(HandleAllocated()) {
		Reset();
	}
*/
}
//---------------------------------------------------------------------------
void __fastcall TListPanel::Clear()
{
	for( int i=0; i<m_ItemList->Count; i++ ){
		delete m_ItemList->Items[i];
	}
	m_ItemList->Clear();

	FSelectedItemIndex = -1;
	m_CurrentItemIndex 	= -1;

	m_BeginIndex = 0;
	m_EndIndex = 0;

  	ResetScroll();
//	if(HandleAllocated()) {
//		Reset();

//		Repaint();
//	}
}
//---------------------------------------------------------------------------
void __fastcall TListPanel::CreateWnd()
{
	TPanel::CreateWnd();

    // 设置滚动条属性
	m_ScrollBar->Height = Height - 2;
	m_ScrollBar->Top = 1;
	m_ScrollBar->Left = Width - m_ScrollBar->Width - 1;
	m_ScrollBar->Parent = this;
	m_ScrollBar->m_pWndCtrl = this;

    //最大显示数
	m_ShowCount = (Height - 2 * MARGIN) / FItemHeight;

	// 记录显示区域
/*	m_ItemRectList->Clear();
	m_ItemRectList->Add(new TRect(MARGIN, MARGIN, Width - MARGIN, FItemHeight + MARGIN));
	for(int i = 1; i < m_ShowCount; i++)
	{
		int var_ItemTop = i * FItemHeight + MARGIN;
		int var_ItemBottom = var_ItemTop + FItemHeight;

		m_ItemRectList->Add(new TRect(MARGIN, var_ItemTop, Width - MARGIN, var_ItemBottom));
	}
*/
	// 记录Item区域
	m_ItemArea = TRect(MARGIN, MARGIN, Width - MARGIN, m_ShowCount * FItemHeight + MARGIN);

	ResetScroll();
}
//---------------------------------------------------------------------------
int __fastcall TListPanel::GetItemsCount()
{
	if(m_ItemList)
    	return m_ItemList->Count;
    else
    	return -1;
}
//---------------------------------------------------------------------------
//void __fastcall TListPanel::SetTextFontSize(int sz)
//{
//	Canvas->Font->Size = sz;
//}
//---------------------------------------------------------------------------
void __fastcall TListPanel::SetTextFont(String name, int size)
{
	Canvas->Font->Name = name;
	Canvas->Font->Size = size;
}
//---------------------------------------------------------------------------
TListPanelItem *__fastcall TListPanel::GetItem(int Index)
{
	if(ItemsCount == 0 || Index < 0 || Index > ItemsCount)
    	return NULL;
    else
    	return (TListPanelItem *)m_ItemList->Items[Index];
}
/*/---------------------------------------------------------------------------
TRect *__fastcall TListPanel::GetItemRect(int Index)
{
	return (TRect *)m_ItemRectList->Items[Index];
}
*/
//---------------------------------------------------------------------------
void __fastcall TListPanel::MouseDown(TMouseButton Button, TShiftState Shift, int X, int Y)
{
	TPanel::MouseDown(Button, Shift, X, Y);

	if(m_ScrollBar->Visible && Button == 0) {
		m_IsLButtonDown = true;
		m_ScrollBar->Enabled = false;
	}

	int areaRight = 0;

	m_ScrollBar->Visible ? areaRight = m_ItemArea.Right - m_ScrollBar->Width - 1
						 : areaRight = m_ItemArea.Right;

	if(Button == 0 && X >= m_ItemArea.Left && X < areaRight && Y >= m_ItemArea.Top
		&& Y < m_ItemArea.Bottom && ItemsCount > 0)
	{
		int index = (Y - MARGIN) / FItemHeight + m_BeginIndex;

		if(index < m_ItemList->Count && m_ItemList->Count != 0)
		{
			if(FSelectedItemIndex != index)
			{
				if(FSelectedItemIndex >= m_BeginIndex && FSelectedItemIndex < m_EndIndex)
					SetItemStatus(FSelectedItemIndex, IS_UNSELECTED);

				FSelectedItemIndex = index;

				SetItemStatus(FSelectedItemIndex, IS_SELECTED);
			}

			GetItem(FSelectedItemIndex)->OnItemClicked(this, FSelectedItemIndex);
		}
	}
}
//---------------------------------------------------------------------------
void __fastcall TListPanel::MouseMove(TShiftState Shift, int X, int Y)
{
	TPanel::MouseMove(Shift, X, Y);

	if(m_IsLButtonDown) return;

    if(m_MouseX == X && m_MouseY == Y) return;

    m_MouseX = X;
	m_MouseY = Y;

	int areaRight = 0, index = -1;

	m_ScrollBar->Visible ? areaRight = m_ItemArea.Right - m_ScrollBar->Width - 1
						 : areaRight = m_ItemArea.Right;

	if(X >= m_ItemArea.Left && X < areaRight && Y >= m_ItemArea.Top
		&& Y < m_ItemArea.Bottom && ItemsCount > 0)
	{
		index = (Y - MARGIN) / FItemHeight + m_BeginIndex;

		if(index < m_ItemList->Count && m_ItemList->Count != 0)
		{
			if(index != m_CurrentItemIndex)
			{
				/* 还原上一次选中项 */
				if(m_CurrentItemIndex >= m_BeginIndex && m_CurrentItemIndex < m_EndIndex)
				{
					m_CurrentItemIndex == FSelectedItemIndex ? SetItemStatus(m_CurrentItemIndex, IS_SELECTED)
														: SetItemStatus(m_CurrentItemIndex, IS_UNSELECTED);
				}
				/* 更新当前选择项 */
				m_CurrentItemIndex = index;
				/* 重绘选中项 */
				m_CurrentItemIndex == FSelectedItemIndex ? SetItemStatus(m_CurrentItemIndex, IS_SELECTED)
													: SetItemStatus(m_CurrentItemIndex, IS_OVER);
			}
		}
	}

	if( ( index<0 || index>m_ItemList->Count )
						&& m_CurrentItemIndex >= m_BeginIndex
						&& m_CurrentItemIndex < m_EndIndex ){
		m_CurrentItemIndex==FSelectedItemIndex ? SetItemStatus(m_CurrentItemIndex, IS_SELECTED)
											   : SetItemStatus(m_CurrentItemIndex, IS_UNSELECTED);
		m_CurrentItemIndex = -1;
	}
}
//---------------------------------------------------------------------------
void __fastcall TListPanel::MouseUp(TMouseButton Button, TShiftState Shift, int X, int Y)
{
	TPanel::MouseUp(Button, Shift, X, Y);

	if(m_ScrollBar->Visible && Button == 0) {
		m_IsLButtonDown = false;
		m_ScrollBar->Enabled = true;
	}
}
//---------------------------------------------------------------------------
void __fastcall TListPanel::SetItemStatus(int Index, int flag)
{
	int var_ItemTop = ( Index - m_BeginIndex ) * FItemHeight + MARGIN;
	TRect rtDraw( MARGIN, var_ItemTop, Width - MARGIN, var_ItemTop + FItemHeight );

	GetItem(Index)->DrawItem(Canvas, rtDraw, flag);
}
//---------------------------------------------------------------------------
void __fastcall TListPanel::SetSelectedItemIndex(int Index)
{
	if(FSelectedItemIndex != Index) {
		if( FSelectedItemIndex>=m_BeginIndex && FSelectedItemIndex<m_EndIndex ){
			SetItemStatus( FSelectedItemIndex-m_BeginIndex, IS_UNSELECTED );
		}

		if( Index<0 || Index>=m_ItemList->Count ){
			FSelectedItemIndex = -1;
		}
		else{
			FSelectedItemIndex = Index;

			int posScroll = m_BeginIndex;
			if( Index<m_BeginIndex ){
				posScroll = Index;
			}
			else if( Index>=m_EndIndex ){
				posScroll = Index - m_ShowCount + 1;
			}

			if( posScroll==m_BeginIndex ){
				SetItemStatus( FSelectedItemIndex-m_BeginIndex, IS_SELECTED );
			}
			else if( m_ScrollBar->Visible ){
				ScrollPos( posScroll );
				m_ScrollBar->SetPosition(posScroll);
			}
		}
    }
}
//---------------------------------------------------------------------------
void __fastcall TListPanel::Paint()
{
	Canvas->Lock();
	for(int Index = m_BeginIndex; Index < m_EndIndex; Index++)
    {
		if(Index == FSelectedItemIndex)
			SetItemStatus(Index, IS_SELECTED);
		else if(Index == m_CurrentItemIndex)
			SetItemStatus(Index, IS_OVER);
		else
			SetItemStatus(Index, IS_UNSELECTED);
	}

	if( m_ShowCount > ItemsCount ){
		int var_Top = ItemsCount * FItemHeight + MARGIN,
			var_Bottom = var_Top + ( m_ShowCount - ItemsCount ) * FItemHeight;
		TRect rtDraw( MARGIN, var_Top, Width - MARGIN, var_Bottom );

		Canvas->Brush->Color = LP_BACKGRND;
		Canvas->FillRect(rtDraw);
	}

	Canvas->Unlock();
}
//---------------------------------------------------------------------------
void __fastcall TListPanel::ResetScroll()
{
	m_RealShowCount = MIN(ItemsCount, m_ShowCount);

	if( FSelectedItemIndex>=0 ){
		if( FSelectedItemIndex < m_BeginIndex ){
			m_BeginIndex = FSelectedItemIndex;
		}
		else if( FSelectedItemIndex >= m_BeginIndex + m_ShowCount  ){
			m_BeginIndex = FSelectedItemIndex - m_ShowCount + 1;
		}
	}

	m_EndIndex = min( m_BeginIndex + m_RealShowCount, ItemsCount );

	if( ItemsCount > m_ShowCount) {
		m_ScrollBar->Visible = true;
		m_ScrollBar->SetRange(0, ItemsCount - 1);
		m_ScrollBar->SetPageSize(m_ShowCount);
		m_ScrollBar->SetPosition(m_BeginIndex);
	}
	else {
		m_ScrollBar->Visible = false;
	}

	Paint();
}
//---------------------------------------------------------------------------
void __fastcall TListPanel::ScrollPos(int Pos)
{
	if(Pos >= 0 && Pos < ItemsCount){
        int var_bIndex = Pos;
        int var_eIndex = Pos + m_RealShowCount;

        if(var_eIndex > ItemsCount)
        {
            var_eIndex = ItemsCount;
            var_bIndex = var_eIndex - m_RealShowCount;
		}

        if(var_bIndex != m_BeginIndex)
        {
			m_BeginIndex = var_bIndex;
			m_EndIndex = var_eIndex;

			Paint();
		}
	}
}
//---------------------------------------------------------------------------
void __fastcall TListPanel::WMEraseBkgnd(TWMEraseBkgnd &Message)
{
	TCanvas* var_BKCanvas = new TCanvas();
	var_BKCanvas->Handle  = Message.DC;

	TRect var_Rect = GetClientRect();

	var_BKCanvas->Brush->Color = LP_BACKGRND;	// 绘制底色
	var_BKCanvas->FillRect(var_Rect);

	var_BKCanvas->Brush->Color = LP_BORDER;		// 绘制边框
	var_BKCanvas->FrameRect(var_Rect);

	delete var_BKCanvas;
    var_BKCanvas = NULL;
}
//---------------------------------------------------------------------------
void __fastcall TListPanel::WMMouseWheel(TWMMouseWheel &Message)
{
	UINT nSBCode;

	if(m_IsLButtonDown) return;

	if(Message.WheelDelta < 0)
    {
		nSBCode = SB_LINEDOWN;
    }
    else
    {
    	nSBCode = SB_LINEUP;
	}

    if(m_ScrollBar->Visible)
    	Perform(WM_VSCROLL, MAKELONG(nSBCode, 0), NULL);
}
//---------------------------------------------------------------------------
void __fastcall TListPanel::CMMouseLeave(TMessage &Message)
{
	m_CurrentItemIndex = -1;

	Repaint();
}
//---------------------------------------------------------------------------
void __fastcall TListPanel::WMVScroll(TWMScroll &Message)
{
    int minpos, maxpos, page, curpos;

	m_ScrollBar->GetScrollRange(& minpos, & maxpos);

    page = m_ScrollBar->GetPageSize();
    curpos = m_ScrollBar->GetScrollPos();

    switch(Message.ScrollCode)
    {
        case SB_TOP:
        curpos = minpos;
		break;

		case SB_BOTTOM:
        curpos = maxpos - page + 1;
        break;

        case SB_ENDSCROLL:
        break;

        case SB_LINEUP:
        if(curpos > minpos)
        {
            curpos--;
		}
        break;

		case SB_LINEDOWN:
        if(curpos < maxpos - page + 1)
        {
            curpos++;
        }
        break;

        case SB_PAGEUP:
        if(curpos > minpos)
        {
            curpos = MAX(minpos, curpos - page);
        }
        break;

        case SB_PAGEDOWN:
		if(curpos < maxpos)
        {
            curpos = MIN(maxpos - page + 1, curpos + page);
        }
        break;

		case SB_THUMBPOSITION:
        curpos = Message.Pos;
        break;

        case SB_THUMBTRACK:
        curpos = Message.Pos;
        break;
	}

    if(Message.ScrollBar != m_ScrollBar->Handle)
    {
		m_ScrollBar->SetPosition(curpos);
	}

    ScrollPos(curpos);
}
//---------------------------------------------------------------------------
int __fastcall TListPanel::TextWidth(String text)
{
	return Canvas->TextWidth(text);
}
//---------------------------------------------------------------------------

void __fastcall TListPanel::WMSize(Winapi::Messages::TWMSize &Message)
{
	DefaultHandler( &Message );

	m_ScrollBar->Height = Height - 2;
	m_ScrollBar->Top = 1;
	m_ScrollBar->Left = Width - m_ScrollBar->Width - 1;

    //最大显示数
	m_ShowCount = (Height - 2 * MARGIN) / FItemHeight;
	// 记录显示区域
/*	m_ItemRectList->Clear();
	m_ItemRectList->Add(new TRect(MARGIN, MARGIN, Width - MARGIN, FItemHeight + MARGIN));
	for(int i = 1; i < m_ShowCount; i++)
	{
		int var_ItemTop = i * FItemHeight + MARGIN;
		int var_ItemBottom = var_ItemTop + FItemHeight;

		m_ItemRectList->Add(new TRect(MARGIN, var_ItemTop, Width - MARGIN, var_ItemBottom));
	}
*/
	// 记录Item区域
	m_ItemArea = TRect(MARGIN, MARGIN, Width - MARGIN, m_ShowCount * FItemHeight + MARGIN);

//	ResetScroll();
}
//---------------------------------------------------------------------------
