//--------------------------------------------------------------------------- #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); // 通知Panel:Item个数变化 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; } //---------------------------------------------------------------------------