Files
AC_Pro/ProgHandlePanel.cpp
2026-06-13 00:05:19 +08:00

677 lines
17 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//---------------------------------------------------------------------------
#pragma hdrstop
#include "ProgHandlePanel.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
//---------------------------------------------------------------------------
#define ITEM_OVER TColor(RGB(67, 73, 80))
#define ITEM_SELECTED TColor(RGB(29, 31, 35))
#define ITEM_DEF TColor(RGB(47, 50, 57))
#define ITEM_TEXT_COLOR TColor(RGB(213, 221, 232))
#define BORDER TColor(RGB(106, 111, 117))
#define BACKGRND TColor(RGB(47, 50, 57))
#define BORDER_HL TColor(RGB(30, 32, 36))
#define BACKGRND_HL TColor(RGB(67, 73, 80))
#define TEXT_COLOR TColor(RGB(213, 221, 232))
#define TEXT_DISABLE TColor(RGB(100, 108, 119))
#define BREAK TColor(RGB(100, 108, 119))
#define BOARD_FILL TColor(RGB(76, 82, 91))
#define MIN(x, y) ((x) < (y) ? (x) : (y))
#define MAX(x, y) ((x) > (y) ? (x) : (y))
#define MARGIN 2
//---------------------------------------------------------------------------
/****************************************************************************
*
* TProgHandleItem
*
*****************************************************************************/
__fastcall TProgHandleItem::TProgHandleItem(TProgHandlePanel *OwnerPanel, String Caption)
{
if(mChildItem == NULL) {
mChildItem = new TList();
}
mLevel = 0;
FParent = NULL;
FOwnerPanel = OwnerPanel;
FCaption = Caption;
FOwnerPanel->AddTopLevelItem(this);
}
//---------------------------------------------------------------------------
__fastcall TProgHandleItem::TProgHandleItem(TProgHandleItem *Parent, String Caption)
{
if(mChildItem == NULL) {
mChildItem = new TList();
}
FParent = Parent;
FOwnerPanel = Parent->GetOwnerPanel();
mLevel = Parent->mLevel + 1;
FCaption = Caption;
FParent->AddChild(this);
}
//---------------------------------------------------------------------------
__fastcall TProgHandleItem::~TProgHandleItem()
{
if(mChildItem) {
mChildItem->Clear();
delete mChildItem;
mChildItem = NULL;
}
if(mHeaderIconButton) {
delete mHeaderIconButton;
mHeaderIconButton = NULL;
}
if(mCheckBox) {
delete mCheckBox;
mCheckBox = NULL;
}
}
//---------------------------------------------------------------------------
void __fastcall TProgHandleItem::AfterConstruction()
{
FIsUnfold = true;
FIsSelected = false;
FIsFocus = false;
FIsHidden = false;
FIsChecked = true;
mCanvas = NULL;
mRect.init(0, 0, 0, 0);
mValidRect.init(0, 0, 0, 0);
mIconRect.init(0, 0, 0, 0);
mCaptionRect.init(0, 0, 0, 0);
mHeaderIconButton = new TPNGButton(FOwnerPanel);
mHeaderIconButton->Parent = FOwnerPanel;
mHeaderIconButton->ImgStates = 2;
mHeaderIconButton->Visible = true;
mHeaderIconButton->Width = 12;
mHeaderIconButton->Height = 12;
mHeaderIconButton->Top = -12;
mHeaderIconButton->Left = -12;
mHeaderIconButton->OnClick = DoHeaderClick;
mCheckBox = new TPNGButton(FOwnerPanel);
mCheckBox->Parent = FOwnerPanel;
mCheckBox->ImgStates = 2;
mCheckBox->Visible = true;
mCheckBox->Top = -20;
mCheckBox->Left = -20;
mCheckBox->Width = 20;
mCheckBox->Height = 20;
mCheckBox->OnClick = DoCheckClick;
}
//---------------------------------------------------------------------------
void __fastcall TProgHandleItem::DrawItem(TCanvas *Canvas, TRect Rect)
{
if(mRect != Rect) {
mRect = Rect;
mValidRect = TRect(Rect);
mValidRect.Left += mLevel * 20;
mIconRect = TRect(mValidRect);
mIconRect.Right = mIconRect.Left + 20;
mCaptionRect = TRect(mValidRect);
mCaptionRect.Left += 20;
}
mCanvas = Canvas;
if(ChildCount > 0) {
if(IsUnfold)
mHeaderIconButton->PngImg->LoadFromResourceName((int)HInstance, L"imgUnfold");
else
mHeaderIconButton->PngImg->LoadFromResourceName((int)HInstance, L"imgFold");
mHeaderIconButton->Top = mIconRect.Top + (mIconRect.Height() - 12) / 2;
mHeaderIconButton->Left = mIconRect.Left + (mIconRect.Width() - 12) / 2;
}
else {
if(FIsChecked)
mCheckBox->PngImg->LoadFromResourceName((int)HInstance, L"imgItemChecked");
else
mCheckBox->PngImg->LoadFromResourceName((int)HInstance, L"imgItemUnchecked");
mCheckBox->Top = mIconRect.Top;
mCheckBox->Left = mIconRect.Left;
}
if(FIsSelected)
mCanvas->Brush->Color = ITEM_SELECTED;
else if(FIsFocus && !FIsSelected)
mCanvas->Brush->Color = ITEM_OVER;
else
mCanvas->Brush->Color = ITEM_DEF;
mCanvas->FillRect(mCaptionRect);
mCanvas->Font->Color = ITEM_TEXT_COLOR;
int textHeight = mCanvas->TextHeight(FCaption);
int textLeft = mCaptionRect.Left + 4;
int textTop = mCaptionRect.Top + (mCaptionRect.Height() - textHeight) / 2;
int textRight = mCaptionRect.Right - 4;
int textBottom = textTop + textHeight;
TRect textRect(textLeft, textTop, textRight, textBottom);
mCanvas->TextRect(textRect, FCaption);
}
//---------------------------------------------------------------------------
void __fastcall TProgHandleItem::RedrawItem()
{
if(mCanvas && !FIsHidden) {
DrawItem(mCanvas, mRect);
}
}
//---------------------------------------------------------------------------
void __fastcall TProgHandleItem::MouseDown(TMouseButton Button, TShiftState Shift, int X, int Y)
{
if(mCaptionRect.Contains(TPoint(X, Y))) {
if(!FIsSelected){
FIsSelected = true;
RedrawItem();
// 选择项
FOwnerPanel->DoSelectedItem(this);
}
}
}
//---------------------------------------------------------------------------
void __fastcall TProgHandleItem::MouseMove(TShiftState Shift, int X, int Y)
{
if(mCaptionRect.Contains(TPoint(X, Y))) {
if(!FIsFocus) {
FIsFocus = true;
RedrawItem();
// 当前项
FOwnerPanel->DoCurrentItem(this);
}
}
else{
if(FIsFocus) {
FIsFocus = false;
RedrawItem();
}
}
}
//---------------------------------------------------------------------------
void __fastcall TProgHandleItem::MouseUp(TMouseButton Button, TShiftState Shift, int X, int Y)
{
//
}
//---------------------------------------------------------------------------
TProgHandlePanel *TProgHandleItem::GetOwnerPanel()
{
return FOwnerPanel;
}
//---------------------------------------------------------------------------
void __fastcall TProgHandleItem::SetCaption(String Value)
{
if(FCaption != Value) {
FCaption = Value;
RedrawItem();
// 通知Panel:名称变化事件
}
}
//---------------------------------------------------------------------------
void __fastcall TProgHandleItem::SetUnfold(bool Value)
{
if(FIsUnfold != Value) {
FIsUnfold = Value;
RedrawItem();
// 通知Panel: 结构变化
FOwnerPanel->DoItemChange(this);
}
}
//---------------------------------------------------------------------------
void __fastcall TProgHandleItem::DoHeaderClick(TObject *Sender)
{
IsUnfold = !IsUnfold;
}
//---------------------------------------------------------------------------
void __fastcall TProgHandleItem::DoCheckClick(TObject *Sender)
{
IsChecked = !IsChecked;
}
//---------------------------------------------------------------------------
void __fastcall TProgHandleItem::SetSelected(bool Value)
{
if(FIsSelected != Value) {
FIsSelected = Value;
RedrawItem();
// 通知Panel:选择变化事件
}
}
//---------------------------------------------------------------------------
void __fastcall TProgHandleItem::SetHidden(bool Value)
{
if(FIsHidden != Value) {
FIsHidden = Value;
if(mHeaderIconButton)
mHeaderIconButton->Visible = !Value;
if(mCheckBox)
mCheckBox->Visible = !Value;
}
}
//---------------------------------------------------------------------------
void __fastcall TProgHandleItem::SetChecked(bool Value)
{
if(FIsChecked != Value) {
FIsChecked = Value;
RedrawItem();
}
}
//---------------------------------------------------------------------------
int __fastcall TProgHandleItem::GetChildCount()
{
return mChildItem->Count;
}
//---------------------------------------------------------------------------
void TProgHandleItem::AddChild(TProgHandleItem *Child)
{
mChildItem->Add(Child);
// 通知PanelItem个数变化
FOwnerPanel->DoItemChange(this);
}
//---------------------------------------------------------------------------
TProgHandleItem *TProgHandleItem::Child(int Index)
{
if(Index >= 0 && Index < ChildCount) {
return (TProgHandleItem *)mChildItem->Items[Index];
}
return NULL;
}
/****************************************************************************
*
* TProgHandlePanel
*
*****************************************************************************/
__fastcall TProgHandlePanel::TProgHandlePanel(TComponent *Owner) : TPanel(Owner)
{
SetParentComponent(Owner);
mTopLevelItemList = new TList();
mItemRectList = new TList();
mItemList = new TList();
mCurrentItem = NULL;
mEndIndex = 0;
FItemHeight = 20;
mScrollBar = new TSkinScrollBar(NULL);
mScrollBar->Visible = false;
}
//---------------------------------------------------------------------------
__fastcall TProgHandlePanel::~TProgHandlePanel()
{
if(mTopLevelItemList) {
mTopLevelItemList->Clear();
delete mTopLevelItemList;
mTopLevelItemList = NULL;
}
if(mItemRectList) {
mItemRectList->Clear();
delete mItemRectList;
mItemRectList = NULL;
}
if(mItemList) {
mItemList->Clear();
delete mItemList;
mItemList = NULL;
}
if(mScrollBar) {
delete mScrollBar;
mScrollBar = NULL;
}
if(mCurrentItem) {
delete mCurrentItem;
mCurrentItem = NULL;
}
}
//---------------------------------------------------------------------------
void __fastcall TProgHandlePanel::AddTopLevelItem(TProgHandleItem* Item)
{
mTopLevelItemList->Add(Item);
DoItemChange(NULL);
}
//---------------------------------------------------------------------------
void __fastcall TProgHandlePanel::ScrollPos(int Pos)
{
if(Pos >= 0 && Pos <= mItemList->Count - mRealShowCount) {
if(mBeginIndex != Pos) {
// 重置项
mBeginIndex = Pos;
mEndIndex = mBeginIndex + mRealShowCount;
Paint();
}
}
}
//---------------------------------------------------------------------------
TProgHandleItem *TProgHandlePanel::GetItem(int Index)
{
if(Index >= 0 && Index < mItemList->Count) {
return (TProgHandleItem *) mItemList->Items[Index];
}
return NULL;
}
//---------------------------------------------------------------------------
TProgHandleItem *TProgHandlePanel::GetTopLevelItem(int Index)
{
if(Index >= 0 && Index < mTopLevelItemList->Count) {
return (TProgHandleItem *) mTopLevelItemList->Items[Index];
}
return NULL;
}
//---------------------------------------------------------------------------
void __fastcall TProgHandlePanel::RecalcItemsRect()
{
//最大显示数
mShowCount = (Height - 2 * MARGIN) / FItemHeight;
// 记录显示区域
mItemRectList->Clear();
mItemRectList->Add(new TRect(MARGIN, MARGIN, Width - MARGIN, FItemHeight + MARGIN));
for(int i = 1; i < mShowCount; i++) {
int itemTop = i * FItemHeight + MARGIN;
int itemBottom = itemTop + FItemHeight;
mItemRectList->Add(new TRect(MARGIN, itemTop, Width - MARGIN, itemBottom));
}
}
//---------------------------------------------------------------------------
void __fastcall TProgHandlePanel::Reset()
{
mRealShowCount = MIN(mItemList->Count, mShowCount);
mEndIndex = mBeginIndex + mRealShowCount;
while(mEndIndex > mItemList->Count) {
mBeginIndex--;
mEndIndex--;
}
int Index = mBeginIndex;
while(Index < mEndIndex) {
TProgHandleItem *Item = (TProgHandleItem *)mItemList->Items[Index];
if(Item->IsSelected)
break;
Index++;
}
if(Index == mEndIndex) {
DoSelectedItem(NULL);
}
if(HandleAllocated()) {
if(mItemList->Count > mShowCount) {
mScrollBar->Visible = true;
mScrollBar->SetRange(0, mItemList->Count - 1);
mScrollBar->SetPageSize(mShowCount);
mScrollBar->SetPosition(mBeginIndex);
FItemWidth = Width - mScrollBar->Width - 20;
}
else {
mScrollBar->Visible = false;
FItemWidth = Width;
}
}
}
//---------------------------------------------------------------------------
void __fastcall TProgHandlePanel::LoadItem(TProgHandleItem* Item)
{
if(Item->Parent == NULL) {
Item->IsHidden = false;
}
else {
Item->IsHidden = (Item->Parent->IsHidden || !Item->Parent->IsUnfold);
}
if(!Item->IsHidden) {
mItemList->Add(Item);
}
for(int i = 0; i < Item->ChildCount; i++) {
TProgHandleItem *Child = Item->Child(i);
LoadItem(Child);
}
}
//---------------------------------------------------------------------------
void __fastcall TProgHandlePanel::WMSize(TWMSize &Message)
{
mScrollBar->Height = Height - 2;
mScrollBar->Top = 1;
mScrollBar->Left = Width - mScrollBar->Width - 1;
RecalcItemsRect();
}
//---------------------------------------------------------------------------
void __fastcall TProgHandlePanel::WMEraseBkgnd(TWMEraseBkgnd &Message)
{
TCanvas* tmpCanvas = new TCanvas();
tmpCanvas->Handle = Message.DC;
tmpCanvas->Brush->Color = BACKGRND; // 绘制底色
tmpCanvas->FillRect(ClientRect);
tmpCanvas->Brush->Color = BORDER; // 绘制边框
tmpCanvas->FrameRect(ClientRect);
delete tmpCanvas;
}
//---------------------------------------------------------------------------
void __fastcall TProgHandlePanel::WMMouseWheel(TWMMouseWheel &Message)
{
UINT nSBCode;
if(Message.WheelDelta < 0) {
nSBCode = SB_LINEDOWN;
}
else {
nSBCode = SB_LINEUP;
}
if(mScrollBar->Visible)
Perform(WM_VSCROLL, MAKELONG(nSBCode, 0), NULL);
}
//---------------------------------------------------------------------------
void __fastcall TProgHandlePanel::CMMouseLeave(TMessage &Message)
{
MouseMove(TShiftState(0), -1, -1);
}
//---------------------------------------------------------------------------
void __fastcall TProgHandlePanel::WMVScroll(TWMScroll &Message)
{
int minpos, maxpos, page, curpos;
mScrollBar->GetScrollRange(&minpos, &maxpos);
page = mScrollBar->GetPageSize();
curpos = mScrollBar->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 != mScrollBar->Handle) {
mScrollBar->SetPosition(curpos);
}
ScrollPos(curpos);
}
//---------------------------------------------------------------------------
void __fastcall TProgHandlePanel::AfterConstruction()
{
}
//---------------------------------------------------------------------------
void __fastcall TProgHandlePanel::CreateWnd()
{
TPanel::CreateWnd();
mScrollBar->Parent = this;
mScrollBar->m_pWndCtrl = this;
FItemWidth = Width;
Reset();
RecalcItemsRect();
}
//---------------------------------------------------------------------------
void __fastcall TProgHandlePanel::Paint()
{
Canvas->Lock();
for(int Index = 0; Index < this->mItemList->Count; Index++) {
TProgHandleItem *item = GetItem(Index);
if(Index >= mBeginIndex && Index < mEndIndex) {
item->IsHidden = false;
TRect *Rect = (TRect *) mItemRectList->Items[Index - mBeginIndex];
item->DrawItem(Canvas, *Rect);
}
else {
item->IsHidden = true;
}
}
Canvas->Unlock();
}
//---------------------------------------------------------------------------
void __fastcall TProgHandlePanel::MouseDown(TMouseButton Button, TShiftState Shift, int X, int Y)
{
TPanel::MouseDown(Button, Shift, X, Y);
for(int Index = mBeginIndex; Index < mEndIndex; Index++) {
TProgHandleItem *item = GetItem(Index);
item->MouseDown(Button, Shift, X, Y);
}
}
//---------------------------------------------------------------------------
void __fastcall TProgHandlePanel::MouseMove(TShiftState Shift, int X, int Y)
{
TPanel::MouseMove(Shift, X, Y);
for(int Index = mBeginIndex; Index < mEndIndex; Index++) {
TProgHandleItem *item = GetItem(Index);
item->MouseMove(Shift, X, Y);
}
}
//---------------------------------------------------------------------------
void __fastcall TProgHandlePanel::MouseUp(TMouseButton Button, TShiftState Shift, int X, int Y)
{
TPanel::MouseUp(Button, Shift, X, Y);
}
//---------------------------------------------------------------------------
void __fastcall TProgHandlePanel::DoItemChange(TObject *Sender)
{
mItemList->Clear();
for(int i = 0; i < mTopLevelItemList->Count; i++) {
TProgHandleItem *Item = GetTopLevelItem(i);
LoadItem(Item);
}
if(HandleAllocated()) {
Reset();
Repaint();
}
}
//---------------------------------------------------------------------------
void __fastcall TProgHandlePanel::DoSelectedItem(TObject *Sender)
{
TProgHandleItem *Item = (TProgHandleItem *)Sender;
if(mCurrentItem != Sender) {
if(mCurrentItem)
mCurrentItem->IsSelected = false;
mCurrentItem = Item;
}
if(FOnSelectedItem) {
FOnSelectedItem(Sender);
}
}
//---------------------------------------------------------------------------
void __fastcall TProgHandlePanel::DoCurrentItem(TObject *Sender)
{
}
//---------------------------------------------------------------------------
int __fastcall TProgHandlePanel::GetTopLevelItemCount()
{
return mTopLevelItemList->Count;
}
//---------------------------------------------------------------------------
void __fastcall TProgHandlePanel::SetTextFont(String name, int size)
{
Canvas->Font->Name = name;
Canvas->Font->Size = size;
}
//---------------------------------------------------------------------------