Initial commit
This commit is contained in:
@@ -0,0 +1,580 @@
|
||||
//---------------------------------------------------------------------------
|
||||
#include <vcl.h>
|
||||
#pragma hdrstop
|
||||
|
||||
#include "TableViewUnit.h"
|
||||
//---------------------------------------------------------------------------
|
||||
#pragma package(smart_init)
|
||||
//---------------------------------------------------------------------------
|
||||
#define CelOFF 1
|
||||
#define HgtERROR 0
|
||||
//---------------------------------------------------------------------------
|
||||
__fastcall TTableView::TTableView(TComponent* Owner) : TScrollView(Owner)
|
||||
{
|
||||
OnChangeSBPos = DoChgPos;
|
||||
OnChangeSize = DoChgSize;
|
||||
OnHgtTitle = DoHgtTitle;
|
||||
OnHgtBottom = DoHgtBottom;
|
||||
|
||||
FIndFocus = NOSET;
|
||||
FIndSel = NOSET;
|
||||
FCount = 0;
|
||||
FHgtSmall = NOSET;
|
||||
m_Title = NULL;
|
||||
m_Bottom = NULL;
|
||||
|
||||
OnMouseWheel = DoMouseWheel;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
__fastcall TTableView::~TTableView()
|
||||
{
|
||||
DoTableInit();
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
bool __fastcall TTableView::ReloadData(int iCellIndex, SBS iSBS, int iTopline)
|
||||
{
|
||||
bool bRet = true;
|
||||
|
||||
DoTableInit();
|
||||
|
||||
if( FOnTitle ) { //set title
|
||||
|
||||
m_Title = (TPanelDB *)FOnTitle(this);
|
||||
if( m_Title ) m_Title->Parent = this;
|
||||
}
|
||||
|
||||
if( FOnBottom ) { //set Bottom
|
||||
|
||||
m_Bottom = (TPanelDB *)FOnBottom(this);
|
||||
if( m_Bottom ) m_Bottom->Parent = this;
|
||||
}
|
||||
|
||||
if( FOnCellHgt && FOnMDNum && FOnMDCell )
|
||||
{
|
||||
m_DBNum = FOnMDNum(this); //set data num
|
||||
if( m_DBNum<=0 ) bRet = false;
|
||||
|
||||
if( bRet ) {
|
||||
|
||||
for( int index=0; index<m_DBNum; index++ ){ //set data show height
|
||||
|
||||
int iCurHgt = FOnCellHgt(this, index);
|
||||
if( iCurHgt<=HgtERROR ) {
|
||||
bRet = false; //cell nHeight error
|
||||
m_VCHGT.clear();
|
||||
break;
|
||||
}
|
||||
m_VCHGT.push_back(iCurHgt);
|
||||
}
|
||||
|
||||
if( bRet ) {
|
||||
|
||||
DoLstInitial();
|
||||
SetSB(m_PosTotal, m_PosPage, m_PosBegin);
|
||||
|
||||
TStateBtn *pCellTmp = NULL;
|
||||
for(int index=0; index<m_DBNeed; index++){ //set data cell content
|
||||
|
||||
int iAdCell = FOnMDCell(this, index);
|
||||
pCellTmp = (TStateBtn *)iAdCell;
|
||||
if( pCellTmp ) m_LstBtn.push_back(pCellTmp);
|
||||
}
|
||||
|
||||
if( OnChange ) OnChange(this);
|
||||
|
||||
if( NOSET!=iCellIndex ) { SetCellInd(iCellIndex); } //set begin show pos
|
||||
else if( SBS_NONE!=iSBS) { SetSBPos(iSBS, iTopline); }
|
||||
else {
|
||||
DoLstChg();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}else bRet = false; //cell num error
|
||||
|
||||
if( !bRet ) {
|
||||
FIndSel = NOSET;
|
||||
SetSB(0, 0, 0);
|
||||
Paint();
|
||||
}
|
||||
|
||||
return bRet;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
bool __fastcall TTableView::DoLstInitial()
|
||||
{
|
||||
if( 0==m_VCHGT.size() ) return false;
|
||||
|
||||
int nHeight = getContentHeight();
|
||||
|
||||
// get smallest nHeight
|
||||
int iSmlHgt = m_VCHGT[0];
|
||||
for( int i=1; i<m_VCHGT.size(); i++ ) {
|
||||
if( iSmlHgt>m_VCHGT[i] ) iSmlHgt = m_VCHGT[i];
|
||||
}
|
||||
|
||||
int iSmlHgtTmp = iSmlHgt;
|
||||
if(iSmlHgt>nHeight)
|
||||
iSmlHgtTmp = iSmlHgt = (iSmlHgt-nHeight)%nHeight;
|
||||
if( (HgtSmall!=NOSET) && (HgtSmall<iSmlHgtTmp) )
|
||||
iSmlHgtTmp = HgtSmall;
|
||||
|
||||
//get each cell pos num range
|
||||
int iCellShowHgt = 0;
|
||||
int iCellShowNum = 0;
|
||||
int iPosNumCur = 0;
|
||||
int iPosNumTotal = 0;
|
||||
|
||||
bool bSBOK = false;
|
||||
for( int i=0; i<m_VCHGT.size(); i++ ) {
|
||||
|
||||
int iPlus = ( (m_VCHGT[i]%iSmlHgtTmp)==0 ) ? 0:1;
|
||||
iPosNumCur = m_VCHGT[i]/iSmlHgtTmp + iPlus;
|
||||
iPosNumTotal += iPosNumCur;
|
||||
|
||||
m_VCPOS.push_back(iPosNumTotal);
|
||||
|
||||
if(!bSBOK){
|
||||
|
||||
iCellShowNum++;
|
||||
iCellShowHgt += m_VCHGT[i];
|
||||
|
||||
if( iCellShowHgt>=nHeight ) {
|
||||
|
||||
iCellShowNum = nHeight/iSmlHgt;
|
||||
m_PosPage = nHeight/iSmlHgtTmp;
|
||||
|
||||
bSBOK = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
//get sb info
|
||||
m_PosTotal = iPosNumTotal;
|
||||
|
||||
//no sb will show
|
||||
if(iCellShowHgt<nHeight) m_PosPage = m_PosTotal;
|
||||
|
||||
//smallest cell nHeight
|
||||
m_HgtSmall = iSmlHgtTmp;
|
||||
|
||||
//cell visible num + off 2
|
||||
m_DBNeed = iCellShowNum + CelOFF*2;
|
||||
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
bool __fastcall TTableView::DoTableInit()
|
||||
{
|
||||
m_bTop = m_bBom = false;
|
||||
|
||||
m_PosTotal = m_PosPage = m_PosBegin = 0;
|
||||
|
||||
m_DBNum = m_DBNeed = 0;
|
||||
m_IndTop = m_IndBeg = 0;
|
||||
m_UIOffMerge = CelOFF;
|
||||
m_UIOff = 0;
|
||||
|
||||
m_HgtSmall = NOSET;
|
||||
m_HgtTop = m_HgtOver = 0;
|
||||
|
||||
|
||||
m_VCHGT.clear();
|
||||
m_VCPOS.clear();
|
||||
m_VCCHG.clear();
|
||||
|
||||
BtnClear();
|
||||
|
||||
SAFE_DELETE(m_Title);
|
||||
SAFE_DELETE(m_Bottom);
|
||||
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
void __fastcall TTableView::DoLstChg(CELLS eCELLS, int Offset)
|
||||
{
|
||||
DoLstChgPos(eCELLS, Offset);
|
||||
DoLstChgCel(eCELLS);
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
void __fastcall TTableView::DoLstChgPos(CELLS eCELLS, int Offset)
|
||||
{
|
||||
|
||||
bool bPage = false;
|
||||
bool bDown = true;
|
||||
bool bMerge = true; //get cell change list
|
||||
int iMergePos = 0;
|
||||
int iCellChgNum = 0;
|
||||
int iCellTop = 0; //get cell top value
|
||||
int iIndTop = m_IndTop; //get cell index: top and begin
|
||||
|
||||
switch(eCELLS)
|
||||
{
|
||||
case CELLS_Default:
|
||||
{
|
||||
m_IndTop = m_IndBeg = 0;
|
||||
m_HgtTop = 0;
|
||||
m_UIOff = 0;
|
||||
return;
|
||||
} break;
|
||||
case CELLS_Page:
|
||||
{
|
||||
bPage = true;
|
||||
bDown = false;
|
||||
bMerge = false;
|
||||
|
||||
iIndTop = m_IndTop = m_IndBeg;
|
||||
m_HgtTop = 0;
|
||||
m_UIOff = 0;
|
||||
} break;
|
||||
case CELLS_Up:
|
||||
{
|
||||
bDown = false;
|
||||
//--------------when just show > needs cell
|
||||
//merge
|
||||
if(m_UIOff-Offset<0)
|
||||
{
|
||||
bMerge = true;
|
||||
if(m_UIOff!=0){
|
||||
iCellChgNum = Offset - m_UIOff;
|
||||
}else{
|
||||
iCellChgNum = Offset;
|
||||
}
|
||||
m_IndTop -= iCellChgNum;
|
||||
m_UIOff = 0;
|
||||
|
||||
//--------------when just show between needs cell
|
||||
}else{
|
||||
|
||||
bMerge = false;
|
||||
iCellChgNum = 0;
|
||||
m_UIOff -= Offset;
|
||||
}
|
||||
} break;
|
||||
case CELLS_Down:
|
||||
{
|
||||
//--------------when just show > needs cell
|
||||
//merge
|
||||
if(m_UIOff+Offset>m_UIOffMerge ||
|
||||
m_UIOff==1)
|
||||
{
|
||||
bMerge = true;
|
||||
if(m_UIOff<m_UIOffMerge){
|
||||
iCellChgNum =
|
||||
Offset - (m_UIOffMerge - m_UIOff);
|
||||
}else{
|
||||
iCellChgNum = Offset;
|
||||
}
|
||||
m_IndTop += iCellChgNum;
|
||||
m_UIOff = m_UIOffMerge;
|
||||
|
||||
//--------------when just show between needs cell
|
||||
}else{
|
||||
|
||||
bMerge = false;
|
||||
iCellChgNum = 0;
|
||||
m_UIOff += Offset;
|
||||
}
|
||||
|
||||
bDown = true;
|
||||
} break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
int iCelInd = 0;
|
||||
BTNLST::iterator lst_FCell = m_LstBtn.begin();
|
||||
for( VCINT::iterator vc_FHgt = (m_VCHGT).begin() + iIndTop;
|
||||
vc_FHgt != m_VCHGT.end(),
|
||||
lst_FCell != m_LstBtn.end();
|
||||
vc_FHgt++,
|
||||
lst_FCell++ )
|
||||
{
|
||||
if(bPage) { //move too fast, change all the cells
|
||||
|
||||
if( iCelInd<m_DBNeed )
|
||||
m_VCCHG.push_back( iIndTop+iCelInd );
|
||||
iCelInd++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(bMerge) //judge the mergePos, ready for merge the new celllist
|
||||
{
|
||||
if( (bDown&&(iIndTop+iCelInd==m_IndTop)) ||
|
||||
(!bDown&&(iIndTop+iCelInd==iIndTop+m_DBNeed-iCellChgNum)) )
|
||||
iMergePos = iCelInd;
|
||||
}
|
||||
|
||||
// m_VCCHG >> save the change cells's source index
|
||||
if(iCelInd<iCellChgNum) {
|
||||
|
||||
if(bDown){ // down last cells change
|
||||
m_VCCHG.push_back(iIndTop+m_DBNeed+iCelInd);
|
||||
}else{ // up first cells change
|
||||
m_VCCHG.push_back(m_IndTop+iCelInd);
|
||||
}
|
||||
}
|
||||
|
||||
// [m_IndTop, m_IndBeg) >> iCellTop
|
||||
if( m_IndBeg-m_UIOffMerge<=iIndTop+iCelInd &&
|
||||
iIndTop+iCelInd<m_IndBeg )
|
||||
{
|
||||
iCellTop += *vc_FHgt;
|
||||
}
|
||||
|
||||
iCelInd++;
|
||||
}
|
||||
|
||||
if(bPage) { return; }
|
||||
|
||||
m_HgtTop = -iCellTop;
|
||||
|
||||
if( bMerge ) {
|
||||
|
||||
if( iMergePos ) {
|
||||
|
||||
BTNLST::iterator lst_FCell;
|
||||
lst_FCell = m_LstBtn.begin();
|
||||
advance(lst_FCell, iMergePos);
|
||||
m_LstBtn.splice(m_LstBtn.begin(), m_LstBtn, lst_FCell, m_LstBtn.end());
|
||||
}
|
||||
else {
|
||||
int index = m_IndTop;
|
||||
m_VCCHG.clear();
|
||||
for( BTNLST::iterator lst_FCell = (m_LstBtn).begin();
|
||||
lst_FCell != (m_LstBtn).end();
|
||||
lst_FCell++ )
|
||||
{
|
||||
m_VCCHG.push_back(index);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
void __fastcall TTableView::DoLstChgCel(CELLS eCELLS, bool bPaint)
|
||||
{
|
||||
if(!FOnMDCell ) return;
|
||||
|
||||
for( VCINT::iterator vc_FChg = (m_VCCHG).begin();
|
||||
vc_FChg != (m_VCCHG).end();
|
||||
vc_FChg++ )
|
||||
{
|
||||
FOnMDCell(this, *vc_FChg);
|
||||
}
|
||||
|
||||
if( bPaint ) Paint();
|
||||
|
||||
m_VCCHG.clear();
|
||||
|
||||
if( OnChange )
|
||||
OnChange(this);
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
bool __fastcall TTableView::IsCellVisible(int iCellIndex)
|
||||
{
|
||||
bool bVisible = true;
|
||||
|
||||
if( iCellIndex<m_IndBeg ) bVisible = false;
|
||||
|
||||
if( iCellIndex>=GetCellBom() ) bVisible = false;
|
||||
|
||||
return bVisible;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
int __fastcall TTableView::getContentHeight()
|
||||
{
|
||||
int nHeight = Height;
|
||||
if( m_Title ) nHeight -= m_Title->Height;
|
||||
if( m_Bottom ) nHeight -= m_Bottom->Height;
|
||||
return nHeight;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
TStateBtn* __fastcall TTableView::GetCellAds(int iCellIndex)
|
||||
{
|
||||
TStateBtn *rowCellTmp = NULL;
|
||||
|
||||
int index = 0;
|
||||
BTNLST::iterator lst_FCell;
|
||||
for( lst_FCell = (m_LstBtn).begin();
|
||||
lst_FCell != (m_LstBtn).end();
|
||||
lst_FCell++)
|
||||
{
|
||||
if(m_IndTop+index == iCellIndex){
|
||||
rowCellTmp = *lst_FCell;
|
||||
break;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
|
||||
return rowCellTmp;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
int __fastcall TTableView::GetCellHgt(int iCellIndex)
|
||||
{
|
||||
if( 0<=iCellIndex && iCellIndex<=m_DBNum-1 )
|
||||
return m_VCHGT[iCellIndex];
|
||||
|
||||
return 0;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
int __fastcall TTableView::GetCellBeg()
|
||||
{
|
||||
return m_IndBeg;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
int __fastcall TTableView::GetCellBom()
|
||||
{
|
||||
int nHeight = m_RtContent.Height();
|
||||
|
||||
int indBeg = m_IndBeg;
|
||||
int iCurTop = m_HgtOver;
|
||||
int index = 0;
|
||||
for( ; index<m_DBNum; index++ ) {
|
||||
iCurTop += m_VCHGT[index];
|
||||
if( iCurTop>=nHeight ) break;
|
||||
}
|
||||
|
||||
return indBeg+index+1;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
int __fastcall TTableView::GetCellNum()
|
||||
{
|
||||
return m_DBNum;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
void __fastcall TTableView::SetCellInd(int iCellIndex)
|
||||
{
|
||||
if( iCellIndex<0 || iCellIndex>m_DBNum-1) return;
|
||||
|
||||
int iTopLine = 0;
|
||||
if( iCellIndex!=0 ) iTopLine = m_VCPOS[iCellIndex-1];
|
||||
|
||||
SetSBPos(SBS_POS, iTopLine);
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
void __fastcall TTableView::SetSBPos(SBS iSBS, int iTopline)
|
||||
{
|
||||
short ScrollCode = iSBS;
|
||||
|
||||
if(iSBS==SBS_TOP){
|
||||
|
||||
iTopline = 0;
|
||||
|
||||
}else if(iSBS==SBS_BOTTOM){
|
||||
|
||||
iTopline = m_PosTotal-m_PosPage;
|
||||
}
|
||||
|
||||
DoChgPos(this, ScrollCode, iTopline);
|
||||
SetSB(m_PosTotal, m_PosPage, m_PosBegin);
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
void __fastcall TTableView::DoChgPos(TObject *Sender, short ScrollCode, int iTopLine)
|
||||
{
|
||||
if( iTopLine<0 ) {
|
||||
iTopLine = 0;
|
||||
}
|
||||
else if(iTopLine>m_PosTotal-m_PosPage ) {
|
||||
iTopLine = m_PosTotal-m_PosPage;
|
||||
}
|
||||
|
||||
if( m_bTop && (ScrollCode==SB_LINEUP||ScrollCode==SB_PAGEUP ) ){
|
||||
if(FOnMDTop) FOnMDTop(this);
|
||||
return;
|
||||
}
|
||||
else if( m_bBom && (ScrollCode==SB_LINEDOWN||ScrollCode==SB_PAGEDOWN ) ){
|
||||
if(FOnMDBottom) FOnMDBottom(this);
|
||||
return;
|
||||
}
|
||||
else if( iTopLine<0 || iTopLine>m_PosTotal ) return;
|
||||
m_bTop = (0==iTopLine)?true:false;
|
||||
m_bBom = (m_PosTotal-m_PosPage==iTopLine)?true:false;
|
||||
|
||||
//get CELLS
|
||||
CELLS eCELLS;
|
||||
if(abs(m_PosBegin-iTopLine)>=m_PosPage+2) eCELLS = CELLS_Page;
|
||||
else if(m_PosBegin<iTopLine) eCELLS = CELLS_Down;
|
||||
else if(m_PosBegin>iTopLine) eCELLS = CELLS_Up;
|
||||
|
||||
//get new m_IndBeg
|
||||
int iIndChange, iPosCur, iPosPre;
|
||||
iIndChange = iPosCur = iPosPre = 0;
|
||||
|
||||
int front, end, mid;
|
||||
front = 0;
|
||||
end = m_VCPOS.size()-1;
|
||||
mid = (front+end)/2;
|
||||
VCINT::iterator vc_FPos = (m_VCPOS).begin();
|
||||
iPosCur = *(vc_FPos+mid);
|
||||
if(mid==0) iPosPre = 0;
|
||||
else iPosPre = *(vc_FPos+mid-1);
|
||||
while( front<=end ) {
|
||||
|
||||
if(iPosPre<=iTopLine && iTopLine<iPosCur) {
|
||||
iIndChange = mid;
|
||||
break;
|
||||
}
|
||||
|
||||
if(iPosCur<=iTopLine) front = mid+1;
|
||||
else if(iPosCur>iTopLine) end = mid;
|
||||
|
||||
mid = (front+end)/2;
|
||||
iPosCur = *(vc_FPos+mid);
|
||||
if(mid==0) iPosPre = 0;
|
||||
else iPosPre = *(vc_FPos+mid-1);
|
||||
}
|
||||
|
||||
//get new m_IndBeg to it's pre index >> m_HgtOver
|
||||
int iPosBeginNum = 0;
|
||||
if( iIndChange != 0 ) iPosBeginNum = *(m_VCPOS.begin()+iIndChange-1);
|
||||
int iABS = abs(iPosBeginNum-iTopLine);
|
||||
m_HgtOver = -iABS*m_HgtSmall;
|
||||
|
||||
if( iIndChange!=m_IndBeg ) { //change m_IndBeg
|
||||
|
||||
int indBeginTmp = m_IndBeg;
|
||||
m_IndBeg = iIndChange;
|
||||
|
||||
DoLstChg( eCELLS, abs(indBeginTmp-iIndChange) );
|
||||
|
||||
}else { //change m_IndBeg over hegiht
|
||||
|
||||
Paint();
|
||||
}
|
||||
|
||||
m_PosBegin = iTopLine;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
int __fastcall TTableView::DoHgtTitle(TObject *Sender)
|
||||
{
|
||||
if( m_Title) return m_Title->Height;
|
||||
return 0;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
int __fastcall TTableView::DoHgtBottom(TObject *Sender)
|
||||
{
|
||||
if( m_Bottom) return m_Bottom->Height;
|
||||
return 0;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
void __fastcall TTableView::DoPaintLst(TCanvas *pCanvas)
|
||||
{
|
||||
int iTop, iLeft, iWidth, iHeight;
|
||||
iTop = m_HgtTop + m_HgtOver + m_RtContent.Top;
|
||||
iLeft = m_RtContent.Left;
|
||||
iWidth = m_RtContent.Width();
|
||||
|
||||
int iIndex = 0;
|
||||
for(BTNLST::iterator lstBtn=m_LstBtn.begin(); lstBtn!=m_LstBtn.end(); lstBtn++) {
|
||||
|
||||
if(m_IndTop+iIndex>m_VCHGT.size()-1) { break; }
|
||||
|
||||
iHeight = m_VCHGT[m_IndTop+iIndex];
|
||||
|
||||
(*lstBtn)->SetBounds( iLeft, iTop, iWidth, iHeight );
|
||||
(*lstBtn)->Paint(pCanvas);
|
||||
|
||||
iTop += iHeight;
|
||||
iIndex++;
|
||||
}
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
Reference in New Issue
Block a user