reman3/Rayman_X/cpa/tempgrp/ITF/sort3lst.cpp

2324 lines
70 KiB
C++

/*=============================================================================
*
* Filename: Sort3Lst.cpp
* Version: 1.0
* Date: 06/11/96
* Author: V.L.
*
* Description: implementation of ThreeSortedList class
*
*===========================================================================*/
#include "stdafx.h"
#ifdef ACTIVE_EDITOR
#include "itf/Sort3lst.hpp"
#include "itf/CPADD.hpp"
#include "IncTUT.h"
/*=============================================================================
* implementation of CBitmapList
=============================================================================*/
/*BOOL CTextureDlg::m_fn_bIsAValidTexture(CString csFileName)
{
FILE *hFile;
BITMAPFILEHEADER bf;
BITMAPINFOHEADER bi;
if ( (hFile = fopen(csFileName, "rb")) == NULL)
return FALSE;
CString csExtension(strrchr(LPCTSTR(csFileName), '.'));
if ( !csExtension.CompareNoCase(".tga") )
{
unsigned char a18_ucTgaHeader[18];
//read TGA header
if ( fread(a18_ucTgaHeader, 18, 1, hFile) != 1 )
{
fclose(hFile);
return FALSE;
}
//get image width and height
bi.biWidth = (a18_ucTgaHeader[13]<<8) + a18_ucTgaHeader[12];
bi.biHeight = (a18_ucTgaHeader[15]<<8) + a18_ucTgaHeader[14];
bi.biBitCount = a18_ucTgaHeader[16];
}
else if ( !csExtension.CompareNoCase(".bmp") )
{
if (sizeof(bf) != fread( &bf, 1, sizeof(bf), hFile ))
{
fclose(hFile);
return FALSE;
}
if (bf.bfType != 0x4d42 ) //BM
{
fclose(hFile);
return FALSE;
}
if (sizeof(bi) != fread( &bi, 1, sizeof(bi), hFile ))
{
fclose(hFile);
return FALSE;
}
}
else
{
fclose(hFile);
return FALSE;
}
// verify color depth
if ( (bi.biBitCount == 24) || (bi.biBitCount == 32) )
{
LONG lSize = bi.biWidth * bi.biHeight;
LONG lMask = 1;
while (lMask != 0)
{
if ((lSize ^ lMask) == 0)
{
fclose(hFile);
return TRUE;
}
lMask <<= 1;
}
}
fclose(hFile);
return FALSE;
} */
/*-----------------------------------------------------------------------------
* Description : load a bitmap file, returns the handle on the image
*---------------------------------------------------------------------------*/
HBITMAP CBitmapList::m_hLoadImage(
CString _csName, int _cx, int _cy,
CString _csNameOfSmallVersion,
BOOL _bOverrideOptimizedImages
)
{
HBITMAP hBitmap = NULL;
CString csExtension = strrchr(LPCTSTR(_csName), '.');
short wImageType;
if ( !csExtension.CompareNoCase(".bmp") ) // load a bmp file
wImageType = 'BM';
else if ( !csExtension.CompareNoCase(".tga") ) // load a tga file
wImageType = 'TG';
else
wImageType = 0;
if ( wImageType )
{
FILE *p_stTextureFile;
p_stTextureFile = fopen(LPCTSTR(_csName),"rb");
if ( p_stTextureFile )
{
BITMAPINFO stBitmapInfo;
unsigned char aDEF_ucReadBuffer[512L*4L];
short wTgaWidth, wTgaHeight;
unsigned char ucBBP;
if ( wImageType == 'BM' ) // load a bmp file
{
BITMAPFILEHEADER bf;
BITMAPINFOHEADER bi;
fread(&bf, 1, sizeof(bf), p_stTextureFile);
fread(&bi, 1, sizeof(bi), p_stTextureFile);
stBitmapInfo.bmiHeader = bi;
wTgaWidth = (short) bi.biWidth;
wTgaHeight = (short) bi.biHeight;
ucBBP = (unsigned char) bi.biBitCount;
}
else if ( wImageType == 'TG' ) // load a bmp file
{
//read TGA header
fread(aDEF_ucReadBuffer,18,1,p_stTextureFile);
//get image width and height
wTgaWidth = (aDEF_ucReadBuffer[13]<<8) + aDEF_ucReadBuffer[12];
wTgaHeight = (aDEF_ucReadBuffer[15]<<8) + aDEF_ucReadBuffer[14];
ucBBP = aDEF_ucReadBuffer[16];
}
else
{
if ( m_bLoadOnlyOptimizedImages )
{
CString csBadTextureName = _csName + "\n";
if ( m_hBadTexturesLogFile )
{
fprintf(m_hBadTexturesLogFile, LPCTSTR(csBadTextureName));
fflush(m_hBadTexturesLogFile);
}
}
fclose(p_stTextureFile);
return NULL;
}
//here, we have read the header of the image file, either BMP or TGA
//check that the image has the proper size, only if we are trying to load the original one
if
(
(m_bLoadOnlyOptimizedImages && !_bOverrideOptimizedImages)
#if defined(D_UseSmallBitmaps)
&& !_csNameOfSmallVersion.IsEmpty() //do not test image optimisation on small versions
#endif //D_UseSmallBitmaps
)
{
LONG lSize = wTgaWidth * wTgaHeight;
LONG lMask = 1;
while (lMask != 0)
{
if ((lSize ^ lMask) == 0)
break;
else
lMask <<= 1;
}
if ( lMask == 0 )
{
CString csBadTextureName = _csName + "\n";
if ( m_hBadTexturesLogFile )
{
fprintf(m_hBadTexturesLogFile, LPCTSTR(csBadTextureName));
fflush(m_hBadTexturesLogFile);
}
fclose(p_stTextureFile);
return NULL;
}
}
//here, the file has a size that we accept
if ( wImageType == 'BM' ) // load a bmp file with the Windows API
{
fclose(p_stTextureFile);
hBitmap = (HBITMAP) LoadImage(NULL, _csName, IMAGE_BITMAP, _cx, _cy, LR_LOADFROMFILE|LR_CREATEDIBSECTION);
}
else if ( wImageType = 'TG' ) // load a tga file
{
BITMAPINFO stBitmapInfo;
unsigned char *pRawBits;
//we load only true color images
if ( ucBBP != 24 && ucBBP != 32 )
{
if ( m_bLoadOnlyOptimizedImages )
{
CString csBadTextureName = _csName + "\n";
if ( m_hBadTexturesLogFile )
{
fprintf(m_hBadTexturesLogFile, LPCTSTR(csBadTextureName));
fflush(m_hBadTexturesLogFile);
}
}
fclose(p_stTextureFile);
return NULL;
}
//get the number of bytes per pixel (3 or 4)
ucBBP >>= 3;
ASSERT(wTgaWidth * ucBBP <= sizeof(aDEF_ucReadBuffer));
//fill the other useful fields of the header
stBitmapInfo.bmiHeader.biWidth = _cx;
stBitmapInfo.bmiHeader.biHeight = _cy;
stBitmapInfo.bmiHeader.biPlanes = 1;
stBitmapInfo.bmiHeader.biBitCount = 24; //we dont care about alpha channel here, so we wont save it
stBitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
stBitmapInfo.bmiHeader.biCompression = BI_RGB;
stBitmapInfo.bmiHeader.biSizeImage = 0 /*stBitmapInfo.bmiHeader.biWidth * stBitmapInfo.bmiHeader.biHeight * ucBBP*/;
stBitmapInfo.bmiHeader.biXPelsPerMeter = 0;
stBitmapInfo.bmiHeader.biYPelsPerMeter = 0;
stBitmapInfo.bmiHeader.biClrUsed = 0;
stBitmapInfo.bmiHeader.biClrImportant = 0;
//create the bitmap image of the size we want (_cx, _cy)
hBitmap = CreateDIBSection(NULL, &stBitmapInfo, DIB_RGB_COLORS, (void **) &pRawBits, NULL, 0);
//copy/stretch the tga raw data in the image's bits area
if ( hBitmap && pRawBits )
{
long lDestLine, lSrcLine, lOldSrcLine = -1;
for ( lDestLine = 0; lDestLine < _cy; lDestLine ++ )
{
lSrcLine = (lDestLine * wTgaHeight) / _cy;
//read as many lines in the as required to reach the proper source data
while ( lSrcLine != lOldSrcLine )
{
lOldSrcLine ++;
//read a line in the file
fread((void*)aDEF_ucReadBuffer, ucBBP, wTgaWidth, p_stTextureFile);
}
unsigned char *pSrcLine = aDEF_ucReadBuffer;
unsigned char *pDestLine = pRawBits + lDestLine * _cx * 3;
long lDestPixel, lSrcPixel;
for ( lDestPixel = 0; lDestPixel < _cx; lDestPixel ++ )
{
lSrcPixel = (lDestPixel * wTgaWidth) / _cx;
unsigned char *pSrcPixel = pSrcLine + lSrcPixel * ucBBP;
unsigned char *pDestPixel = pDestLine + lDestPixel * 3;
*(pDestPixel ++) = *(pSrcPixel ++);
*(pDestPixel ++) = *(pSrcPixel ++);
*(pDestPixel ++) = *(pSrcPixel ++);
} //column scan loop
} //image scan loop
} //bitmap creation test
else
hBitmap = NULL;
fclose(p_stTextureFile);
} //image type test
} //file open test
}//image type test
#if defined(D_UseSmallBitmaps)
//save a small copy if asked for
if ( !_csNameOfSmallVersion.IsEmpty() && hBitmap )
{
//create or truncate the file
CFile oFile;
if ( oFile.Open(_csNameOfSmallVersion, CFile::modeCreate + CFile::typeBinary + CFile::modeWrite) )
{
BITMAPFILEHEADER bf;
BITMAPINFOHEADER bi;
CBitmap *p_oBitmap = CBitmap::FromHandle(hBitmap);
BITMAP stBitmap;
p_oBitmap->GetBitmap(&stBitmap);
//prepare the file's headers
bf.bfType = 'MB'; //reverse order because of f**ing intel byte swaps!!!
//file header + image header + image data
bf.bfSize = sizeof(bf) + sizeof(bi) + stBitmap.bmWidthBytes * stBitmap.bmHeight;
bf.bfReserved1 = 0;
bf.bfReserved2 = 0;
bf.bfOffBits = sizeof(bf) + sizeof(bi);
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = stBitmap.bmWidth;
bi.biHeight = stBitmap.bmHeight;
bi.biPlanes = stBitmap.bmPlanes;
bi.biBitCount = stBitmap.bmBitsPixel;
bi.biCompression = BI_RGB;
bi.biSizeImage = 0;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrUsed = 0;
bi.biClrImportant = 0;
//write the headers
oFile.Write(&bf, sizeof(bf));
oFile.Write(&bi, sizeof(bi));
//write the image data
oFile.Write(stBitmap.bmBits, stBitmap.bmWidthBytes * stBitmap.bmHeight);
oFile.Close();
}
}
#endif //D_UseSmallBitmaps
return hBitmap;
}
/*-----------------------------------------------------------------------------
* Description : Constructor
*---------------------------------------------------------------------------*/
CBitmapList::CBitmapList()
{
m_oMaxSize.cx = -1;
m_oMaxSize.cy = -1;
}
/*-----------------------------------------------------------------------------
* Description : Destructor
*---------------------------------------------------------------------------*/
CBitmapList::~CBitmapList()
{
POSITION pos = m_oItemList.GetHeadPosition();
tdstBitmapItem *p_stItem;
// delete all item in list
while (pos)
{
p_stItem = m_oItemList.GetNext( pos );
if (!p_stItem->m_bDeleted)
{
DeleteObject( p_stItem->m_hBitmap );
}
delete (p_stItem);
}
if ( m_bLoadOnlyOptimizedImages && m_hBadTexturesLogFile )
{
fclose(m_hBadTexturesLogFile);
m_hBadTexturesLogFile = NULL;
}
}
/*-----------------------------------------------------------------------------
* Description : check out the creation of bitmaplist
*---------------------------------------------------------------------------*/
void CBitmapList::m_fn_vIsCreated()
{
if ( (m_oMaxSize.cx == -1) && (m_oMaxSize.cy == -1) )
{
AfxMessageBox("Error : CBitmapList not created");
exit(-1);
}
}
/*-----------------------------------------------------------------------------
* Description : creation of CBitmapList
* three case : _bSize = C_cFixedSize : bitmap size is fixed and equal to (_cx, _cy)
* _bSize = C_cVariableSize : bitmap size is variable and
* _cx = 0 or _cy = 0: not limited
* else (_cx,_cy) is the maximum the bitmap size can't be exceded
*---------------------------------------------------------------------------*/
void CBitmapList::m_fn_vCreate(
BOOL _bSize /*= TRUE*/,
int _cx /*= 0*/,
int _cy /*= 0*/,
BOOL _bLoadOnlyOptimizedImages /*= FALSE*/,
BOOL _bUseSmallCopies /*= FALSE*/
)
{
if ( (m_oMaxSize.cx == -1) && (m_oMaxSize.cy == -1) ) //only first call is to be handled
{
#if defined(D_UseSmallBitmaps)
m_bUseSmallCopies =
#endif //D_UseSmallBitmaps
_bUseSmallCopies; //prevent compiler warning in case the argument is not used
m_bLoadOnlyOptimizedImages = _bLoadOnlyOptimizedImages;
m_bVariableSize = _bSize;
if (m_bVariableSize)
{
if ( (_cx == 0) || (_cy == 0) )
_cx = _cy = 0;
}
else
{
if (_cx < 8) _cx = 8;
if (_cy < 8) _cy = 8;
}
m_oMaxSize.cx = _cx;
m_oMaxSize.cy = _cy;
if ( m_bLoadOnlyOptimizedImages )
m_hBadTexturesLogFile = fopen("BadTextures.log", "wt");
}
else
AfxMessageBox("Warning : CBitmapList created more than once");
}
/*-----------------------------------------------------------------------------
* Description : return number of bitmap in list, warning some element could
* have been erased so number returned isn't always right
*---------------------------------------------------------------------------*/
long CBitmapList::m_fn_lGetCount( void )
{
return m_oItemList.GetCount();
}
/*-----------------------------------------------------------------------------
* Description : check out if a bitmap is already loaded or not
*---------------------------------------------------------------------------*/
int CBitmapList::m_fn_iFindBitmapByName( CString csName )
{
int iPos = 0;
POSITION pos = m_oItemList.GetHeadPosition();
tdstBitmapItem *p_stItem;
while (pos)
{
p_stItem = m_oItemList.GetNext( pos );
if (!p_stItem->m_bDeleted)
if (csName.CompareNoCase(p_stItem->m_csName) == 0)
return iPos;
iPos ++;
}
return -1;
}
/*-----------------------------------------------------------------------------
* Decription : get index of a bitmap
*---------------------------------------------------------------------------*/
int CBitmapList::m_fn_iGetBitmapIndex( char *szBitmapName )
{
return m_fn_iFindBitmapByName( szBitmapName );
}
/*-----------------------------------------------------------------------------
* Description : return size of bitmap given by it's name
*---------------------------------------------------------------------------*/
BOOL CBitmapList::m_fn_bGetBitmapSize( CString csFileName, CSize *sz)
{
FILE *hFile;
BITMAPFILEHEADER bf;
BITMAPINFOHEADER bi;
CString csExtension = strrchr(LPCTSTR(csFileName), '.');
if ( (hFile = fopen( csFileName, "rb")) == NULL)
return FALSE;
if ( !csExtension.CompareNoCase(".tga") )
{
unsigned char a18_ucTgaHeader[18];
//read TGA header
if ( fread(a18_ucTgaHeader, 18, 1, hFile) != 1 )
{
fclose(hFile);
return FALSE;
}
//get image width and height
bi.biWidth = (a18_ucTgaHeader[13]<<8) + a18_ucTgaHeader[12];
bi.biHeight = (a18_ucTgaHeader[15]<<8) + a18_ucTgaHeader[14];
}
else if ( !csExtension.CompareNoCase(".bmp") )
{
if (sizeof(bf) != fread( &bf, 1, sizeof(bf), hFile ))
{
fclose(hFile);
return FALSE;
}
if (bf.bfType != 0x4d42 /*BM*/)
{
fclose(hFile);
return FALSE;
}
if (sizeof(bi) != fread( &bi, 1, sizeof(bi), hFile ))
{
fclose(hFile);
return FALSE;
}
}
sz->cx = bi.biWidth;
sz->cy = bi.biHeight;
fclose(hFile);
return TRUE;
}
/*-----------------------------------------------------------------------------
* Description : return max size to englobe all bitmaps in list
*---------------------------------------------------------------------------*/
void CBitmapList::m_fn_vGetBoundBox( int& _cx, int& _cy)
{
POSITION pos = m_oItemList.GetHeadPosition();
tdstBitmapItem *p_stItem;
BITMAP stBitmap;
// init max
_cx = _cy = 0;
// for all bitmap in list
while (pos)
{
p_stItem = m_oItemList.GetNext( pos );
if (!p_stItem->m_bDeleted)
{
GetObject( p_stItem->m_hBitmap, sizeof(BITMAP), &stBitmap );
if ( _cx < stBitmap.bmWidth) _cx = stBitmap.bmWidth;
if ( _cy < stBitmap.bmHeight) _cy = stBitmap.bmHeight;
}
}
}
/*-----------------------------------------------------------------------------
* Description : add a bitmap in list, return -1 if it fails
* the size of bitmap depends on the creation parameters and on
* the _cx & _cy parameters
* If m_bVariableSize is false, we load bitmap with a size of m_oMaxSize
* else if _cx = 0 || _cy = 0 we load the bitmap with real size
* else with size (_cx,_cy)
*---------------------------------------------------------------------------*/
int CBitmapList::m_fn_iAdd(
CString _csName, int _cx /*= 0*/, int _cy /*= 0*/,
BOOL _bSmallCopyIfRelevant /*= TRUE*/, BOOL _bOverrideOptimizedImages /*= FALSE*/
)
{
_bSmallCopyIfRelevant; //prevent compiler warnings in case the argument is not used
//verify the CBitmapList creation
m_fn_vIsCreated();
//create the directory in case it does not exist
#if defined(D_UseSmallBitmaps)
CString csNameOfSmallVersion;
if ( m_bUseSmallCopies && _bSmallCopyIfRelevant )
{
char szFullName[_MAX_PATH], szDrive[_MAX_DRIVE], szPath[_MAX_DIR], szName[_MAX_FNAME], szExt[_MAX_EXT];
//insert a subdirectory in the name of the image to compute the full name of the small file
strcpy(szFullName, LPCTSTR(_csName));
_splitpath(szFullName, szDrive, szPath, szName, szExt);
strcat(szPath, "Small\\");
_makepath(szFullName, szDrive, szPath, NULL, NULL);
CreateDirectory(szFullName, NULL);
_makepath(szFullName, szDrive, szPath, szName, szExt);
//we will always generate a BMP file, so modify the name and add the extension
char *pszExtDot = strrchr(szFullName, '.');
if ( pszExtDot )
{
*pszExtDot = '_';
strcat(szFullName, ".bmp");
}
csNameOfSmallVersion = szFullName;
}
else
csNameOfSmallVersion = _csName;
#endif //D_UseSmallBitmaps
int iPos = m_fn_iFindBitmapByName(_csName);
// bitmap is already loaded
if (iPos != -1)
return iPos;
if ( !m_bVariableSize )
{
_cx = m_oMaxSize.cx;
_cy = m_oMaxSize.cy;
}
else
{
CSize oBMSize;
if ( (_cx == 0) || (_cy == 0))
{ //if one value is equal to zero set the twice to zero
_cx = _cy = 0;
}
// check if ther's a maximum size
if ( m_oMaxSize.cx )
{
if
( //try to read the size of one of the files containing the image to load
#if defined(D_UseSmallBitmaps)
( (m_bUseSmallCopies && _bSmallCopyIfRelevant) && !m_fn_bGetBitmapSize(csNameOfSmallVersion, &oBMSize) )
||
#endif //D_UseSmallBitmaps
( !m_fn_bGetBitmapSize(_csName, &oBMSize) )
)
return -1;
if ( (oBMSize.cx > m_oMaxSize.cx) || (oBMSize.cy > m_oMaxSize.cy))
{ // image is to large, reduce size and keep ratio
float fx = (float) oBMSize.cx / m_oMaxSize.cx;
float fy = (float) oBMSize.cy / m_oMaxSize.cy;
if (fx > fy)
{
_cx = m_oMaxSize.cx;
_cy = (int) (oBMSize.cy / fx);
}
else
{
_cy = m_oMaxSize.cy;
_cx = (int) (oBMSize.cx / fy);
}
}
}
}
// load bitmap
HBITMAP hBitmap;
#if defined(D_UseSmallBitmaps)
if ( m_bUseSmallCopies && _bSmallCopyIfRelevant )
{
//try to load the small one
hBitmap = (HBITMAP) m_hLoadImage(csNameOfSmallVersion, _cx, _cy, _bOverrideOptimizedImages);
if ( !hBitmap ) //try to load the original one and to save a small version
hBitmap = (HBITMAP) m_hLoadImage(_csName, _cx, _cy, csNameOfSmallVersion, _bOverrideOptimizedImages);
}
else //try only with the original version here
#endif //D_UseSmallBitmaps
hBitmap = (HBITMAP) m_hLoadImage(_csName, _cx, _cy, "", _bOverrideOptimizedImages);
if ( !hBitmap )
return -1;
// search for the place where to put new item
int iPlace;
tdstBitmapItem *p_stItem;
if ( (iPlace = m_fn_iGetFreeIndex()) == -1)
p_stItem = new tdstBitmapItem();
else
{
POSITION xPos = m_oItemList.FindIndex(iPlace);
p_stItem = m_oItemList.GetAt(xPos);
}
// set item members
p_stItem->m_csName = _csName;
p_stItem->m_hBitmap = hBitmap;
p_stItem->m_bDeleted = FALSE;
// put item in list in the good place
if (iPlace == -1)
{
m_oItemList.AddTail(p_stItem);
return (m_oItemList.GetCount() - 1);
}
else
return iPlace;
}
/*-----------------------------------------------------------------------------
* Description : reload a bitmap
*---------------------------------------------------------------------------*/
void CBitmapList::m_fn_vReload( CString _csBitmapName )
{
POSITION pos = m_oItemList.GetHeadPosition();
tdstBitmapItem *p_stItem;
while (pos)
{
p_stItem = m_oItemList.GetNext( pos );
if (!p_stItem->m_bDeleted)
if (_csBitmapName.CompareNoCase(p_stItem->m_csName) == 0)
{
int cx, cy;
BITMAP stBitmap;
CBitmap *p_oBitmap = CBitmap::FromHandle( p_stItem->m_hBitmap );
p_oBitmap->GetBitmap( &stBitmap );
cx = stBitmap.bmWidth;
cy = stBitmap.bmHeight;
DeleteObject( p_stItem->m_hBitmap );
p_stItem->m_hBitmap = (HBITMAP) m_hLoadImage(_csBitmapName, cx, cy, "", FALSE);
break;
}
}
}
/*-----------------------------------------------------------------------------
* Description : get long associated with a bitmap
*---------------------------------------------------------------------------*/
long CBitmapList::m_fn_lGetBitmapLong( int iImage )
{
POSITION pos;
if ( (iImage>=0) && (pos = m_oItemList.FindIndex( iImage )) != NULL)
{
tdstBitmapItem *p_stItem = m_oItemList.GetAt( pos );
return p_stItem->lData;
}
return 0;
}
/*-----------------------------------------------------------------------------
* Description : set long associated with a bitmap
*---------------------------------------------------------------------------*/
void CBitmapList::m_fn_vSetBitmapLong( int iImage, long lLong )
{
POSITION pos;
if (iImage < 0)
return;
if ((pos = m_oItemList.FindIndex( iImage )) != NULL)
{
tdstBitmapItem *p_stItem = m_oItemList.GetAt( pos );
p_stItem->lData = lLong;
}
}
/*-----------------------------------------------------------------------------
* Description : set long associated with a bitmap
*---------------------------------------------------------------------------*/
int CBitmapList::m_fn_iGetBitmapIndexByLong( long lValue )
{
int iPos = 0;
POSITION pos = m_oItemList.GetHeadPosition();
tdstBitmapItem *p_stItem;
while (pos)
{
p_stItem = m_oItemList.GetNext( pos );
if ( (!p_stItem->m_bDeleted) && (p_stItem->lData == lValue) )
return iPos;
iPos ++;
}
return -1;
}
/*-----------------------------------------------------------------------------
* Description : get handle of bitmap
*---------------------------------------------------------------------------*/
HBITMAP CBitmapList::m_fn_hGetBitmap( int iImage )
{
POSITION pos;
if ( (iImage>=0) && (pos = m_oItemList.FindIndex( iImage )) != NULL)
{
tdstBitmapItem *p_stItem = m_oItemList.GetAt( pos );
if (!p_stItem->m_bDeleted)
return p_stItem->m_hBitmap;
}
return 0;
}
/*-----------------------------------------------------------------------------
* Description : get bitmap name
*---------------------------------------------------------------------------*/
CString CBitmapList::m_fn_csGetBitmapName( int iImage )
{
POSITION pos;
if ( (iImage>=0) && (pos = m_oItemList.FindIndex( iImage )) != NULL)
{
tdstBitmapItem *p_stItem = m_oItemList.GetAt( pos );
if (!p_stItem->m_bDeleted)
return p_stItem->m_csName;
}
return "";
}
/*-----------------------------------------------------------------------------
* Description : delete a bitmap
*---------------------------------------------------------------------------*/
void CBitmapList::m_fn_vDelete( int iBitmap )
{
POSITION pos;
if (iBitmap < 0)
return;
if ((pos= m_oItemList.FindIndex( iBitmap )) != NULL)
{
tdstBitmapItem *p_stItem = m_oItemList.GetAt( pos );
if (!p_stItem->m_bDeleted)
{
DeleteObject( p_stItem->m_hBitmap );
p_stItem->m_bDeleted = TRUE;
}
}
}
/*-----------------------------------------------------------------------------
* Description : delete all bitmaps
*---------------------------------------------------------------------------*/
void CBitmapList::m_fn_vDeleteAll( void )
{
POSITION pos = m_oItemList.GetHeadPosition();
tdstBitmapItem *p_stItem;
// delete all item in list
while (pos)
{
p_stItem = m_oItemList.GetNext( pos );
if (!p_stItem->m_bDeleted)
{
DeleteObject( p_stItem->m_hBitmap );
}
delete p_stItem;
}
// delete all pointer in list
m_oItemList.RemoveAll();
}
/*-----------------------------------------------------------------------------
* Description : delete all bitmaps
*---------------------------------------------------------------------------*/
int CBitmapList::m_fn_iGetFreeIndex( void )
{
int iIndex = 0;
POSITION pos = m_oItemList.GetHeadPosition();
tdstBitmapItem *p_stItem;
//search for a free item
while (pos)
{
p_stItem = m_oItemList.GetNext( pos );
if (p_stItem->m_bDeleted)
return iIndex;
iIndex ++;
}
return -1;
}
/*-----------------------------------------------------------------------------
* Description : draw an image in the given CDC, at the given point
*---------------------------------------------------------------------------*/
void CBitmapList::m_fn_vDraw( CDC* pDC, int iImage, POINT pt, RECT *pClipBox, char cAlignX /*= BA_LEFT*/, char cAlignY /*= BA_TOP*/ )
{
//verify the CBitmapList creation
m_fn_vIsCreated();
// get position of image in list
BITMAP stBitmap;
SIZE sz;
POSITION pos;
if (iImage < 0)
return;
if ((pos = m_oItemList.FindIndex( iImage )) != NULL)
{
// get bitmap item
tdstBitmapItem *p_stItem = m_oItemList.GetAt( pos );
if (p_stItem->m_bDeleted)
return;
// get bitmap information
GetObject( p_stItem->m_hBitmap, sizeof(BITMAP), &stBitmap );
// compute x coordinates and width
switch (cAlignX)
{
case BA_LEFT:
sz.cx = pClipBox->right - pt.x;
if (sz.cx > stBitmap.bmWidth)
sz.cx = stBitmap.bmWidth;
break;
case BA_RIGHT:
sz.cx = pt.x - pClipBox->left;
pt.x -= sz.cx;
if (sz.cx < stBitmap.bmWidth)
pt.x = 0;
else
sz.cx = stBitmap.bmWidth;
break;
case BA_CENTER:
sz.cx = ( ((pt.x - pClipBox->left) < (pClipBox->right - pt.x)) ?
(pt.x - pClipBox->left) : (pClipBox->right - pt.x) ) * 2;
if (sz.cx > stBitmap.bmWidth)
sz.cx = stBitmap.bmWidth;
pt.x -= sz.cx / 2;
break;
}
// compute y coordinates and width
switch (cAlignY)
{
case BA_TOP:
sz.cy = pClipBox->bottom - pt.y;
if (sz.cy > stBitmap.bmHeight)
sz.cy = stBitmap.bmHeight;
break;
case BA_BOTTOM:
sz.cy = pt.y - pClipBox->top;
if (sz.cy > stBitmap.bmHeight)
sz.cy = stBitmap.bmHeight;
pt.y -= sz.cy;
break;
case BA_CENTER:
sz.cy = ( ((pt.y - pClipBox->top) < (pClipBox->bottom- pt.y)) ?
(pt.y - pClipBox->top) : (pClipBox->bottom - pt.y) ) * 2;
if (sz.cy > stBitmap.bmHeight)
sz.cy = stBitmap.bmHeight;
pt.y -= sz.cy / 2;
break;
}
pDC->DrawState( pt, sz, p_stItem->m_hBitmap, DSS_NORMAL );
}
}
/*=============================================================================
*
* implementation of CThreeSortedList
*
=============================================================================*/
/******************************************************************************
* INTERNAL FUNCTION
*****************************************************************************/
/*-----------------------------------------------------------------------------
* Description : macro that return a boolean that indicate if index is valid or not
*---------------------------------------------------------------------------*/
#define M_bIsIndexValid(wIndex) ((wIndex >= 0) && (wIndex < m_lNumberOfElements))
/*-----------------------------------------------------------------------------
* Description : function that verify validity off index and give true index
* switch given order
*---------------------------------------------------------------------------*/
short CThreeSortedList::m_fn_wGetIndexSwitchOrder( short wIndex, char cOrder )
{
// verify index
if ( !M_bIsIndexValid(wIndex) )
return TSL_cItemNotFound;
// transform index switch order
switch (cOrder)
{
case C_cAlphaOrder:
return wIndex;
case C_cCommonOrder:
return (short) m_d_lCommonIndex[wIndex];
case C_cEditedOrder:
return (short) m_d_lEditedIndex[wIndex];
}
// no correspondant order, return TSL_cItemNotFound
return TSL_cItemNotFound;
}
/*-----------------------------------------------------------------------------
* Description : find index in order list of an item index in alpha order
*---------------------------------------------------------------------------*/
short CThreeSortedList::m_fn_wAlphaToAnotherOrder(short wIndex, char cOrder)
{
long *m_p_lOrder;
short wResult;
// verify index
if ( !M_bIsIndexValid(wIndex) )
return TSL_cItemNotFound;
switch (cOrder)
{
case C_cAlphaOrder:
return wIndex;
case C_cCommonOrder:
m_p_lOrder = m_d_lCommonIndex;
break;
case C_cEditedOrder:
m_p_lOrder = m_d_lEditedIndex;
break;
default:
return TSL_cItemNotFound;
}
//find in the reorder array which element references the alpha index we specified
for ( wResult = 0; wResult < m_lNumberOfElements; wResult ++ )
if ( m_p_lOrder[wResult] == wIndex )
return wResult;
return TSL_cItemNotFound;
}
/******************************************************************************
* CONSTRUCTOR / DESTRUCTOR
*****************************************************************************/
/*-----------------------------------------------------------------------------
* Description : Constructor
*---------------------------------------------------------------------------*/
CThreeSortedList::CThreeSortedList()
{
// initialised item list to null, zero items
//m_d_stItem = NULL;
m_lMaxElements = 0;
m_lNumberOfElements = 0;
m_d_lCommonIndex = NULL;
m_d_lEditedIndex = NULL;
m_p_oBitmapList = NULL;
m_lSelectedItem = TSL_cItemNotFound;
}
/*-----------------------------------------------------------------------------
* Description : destructor
*---------------------------------------------------------------------------*/
CThreeSortedList::~CThreeSortedList()
{
m_fn_bDeleteAllItems();
m_p_oBitmapList = NULL;
}
/*-----------------------------------------------------------------------------
* Description : Add an item
*---------------------------------------------------------------------------*/
int CThreeSortedList::m_fn_iAddItem(CString csName, short wImage, long lContent, char cSortType /* = C_cAlphaOrder*/)
{
// allocate memory if necessary
if ( m_lMaxElements == m_lNumberOfElements )
{
// if no more place in list, increase max of elemenst
m_lMaxElements += 20;
// reallocate pointers
m_oArrayOfTSLItem . SetSize(m_lMaxElements);
m_d_lCommonIndex = (long *) realloc(m_d_lCommonIndex, sizeof(long) * m_lMaxElements);
m_d_lEditedIndex = (long *) realloc(m_d_lEditedIndex, sizeof(long) * m_lMaxElements);
}
// find place where to put new item in alphabetic order
long lTopIndex, lBottomIndex, lInsertIndex;
lTopIndex = 0; //up is first in alpha order
lBottomIndex = m_lNumberOfElements; //bottom is last
if ( lBottomIndex == lTopIndex )
lInsertIndex = 0;
else
do
{
lInsertIndex = (lTopIndex + lBottomIndex) / 2;
short wCompareResult = csName.CompareNoCase(m_oArrayOfTSLItem[lInsertIndex]->m_csName);
if ( wCompareResult < 0 ) //string is in the upper part of the array
lBottomIndex = lInsertIndex; //move the bottom of the range up
else if ( wCompareResult > 0 ) //string is in the lower part of the array
lTopIndex = lInsertIndex + 1; //move the top of the range down, leaving the tested element out of the range
else //the string is equal to the middle's string
lTopIndex = lBottomIndex = lInsertIndex; //insert it here
} while ( lTopIndex != lBottomIndex );
lInsertIndex = lTopIndex;
//create the new item and fill it
tdstTSLItem *p_stTSLItem = new tdstTSLItem;
p_stTSLItem->m_csName = csName;
p_stTSLItem->m_wImage = wImage;
p_stTSLItem->m_lContent = lContent;
// insert item at the found position
m_oArrayOfTSLItem.InsertAt(lInsertIndex, p_stTSLItem);
// if item is inserted before the selected item, shift selection number
if ( (m_lSelectedItem != TSL_cItemNotFound) && m_lSelectedItem >= lInsertIndex )
m_lSelectedItem ++;
//shift all items in the reorder lists that are after the one referenced
for
(
long lIndex = 0, *p_lCommon = m_d_lCommonIndex, *p_lEdited = m_d_lEditedIndex;
lIndex < m_lNumberOfElements;
lIndex ++, p_lCommon ++, p_lEdited ++
)
{
if ( *p_lCommon >= lInsertIndex )
(*p_lCommon) ++;
if ( *p_lEdited >= lInsertIndex )
(*p_lEdited) ++;
}
// add item in order list
m_d_lCommonIndex[m_lNumberOfElements] = lInsertIndex;
m_d_lEditedIndex[m_lNumberOfElements] = lInsertIndex;
// increase number of elements
m_lNumberOfElements ++;
return m_fn_wAlphaToAnotherOrder((short) lInsertIndex, cSortType);
}
/*-----------------------------------------------------------------------------
* Description : change name for the given item, this operation change
* order in alphabetical list.
* return the new index in list of the item
*---------------------------------------------------------------------------*/
int CThreeSortedList::m_fn_iSetItemName( long lIndex, char *szName, char cSortType /*= C_cAlphaOrder */)
{
short wImage;
long lContent;
BOOL bIsTheSelectedItem;
// recuperate true index, return if invalid index
if ( (lIndex = m_fn_wGetIndexSwitchOrder((short) lIndex, cSortType )) == TSL_cItemNotFound )
return TSL_cItemNotFound;
// check if item is the selected one
bIsTheSelectedItem = (lIndex == m_lSelectedItem);
// save item data
wImage = m_oArrayOfTSLItem[lIndex]->m_wImage;
lContent = m_oArrayOfTSLItem[lIndex]->m_lContent;
// delete item
m_fn_bDeleteItem(lIndex);
// add an item with old image and content but new name
lIndex = m_fn_iAddItem(szName, wImage, lContent);
// set the new number for selected item if the item was the selected one
if (bIsTheSelectedItem)
m_lSelectedItem = lIndex;
// return item index in the given order
return m_fn_wAlphaToAnotherOrder((short) lIndex, cSortType);
}
/*-----------------------------------------------------------------------------
* Description : change image index for the given item
*---------------------------------------------------------------------------*/
void CThreeSortedList::m_fn_vSetItemImage( long lIndex, short _wImage, char cSortType /*= C_cAlphaOrder */)
{
// recuperate true index
if ( (lIndex = m_fn_wGetIndexSwitchOrder((short) lIndex, cSortType )) == TSL_cItemNotFound )
return;
// set item image
m_oArrayOfTSLItem[lIndex]->m_wImage = _wImage;
}
/*-----------------------------------------------------------------------------
* Description : change pointer on content
*---------------------------------------------------------------------------*/
void CThreeSortedList::m_fn_vSetItemContent( long lIndex, long lContent, char cSortType /*= C_cAlphaOrder */)
{
// recuperate true index
if ( (lIndex = m_fn_wGetIndexSwitchOrder((short) lIndex, cSortType )) == TSL_cItemNotFound )
return;
// set content of item
m_oArrayOfTSLItem[lIndex]->m_lContent = lContent;
}
/*-----------------------------------------------------------------------------
* Description : delete an item
*---------------------------------------------------------------------------*/
BOOL CThreeSortedList::m_fn_bDeleteItem( long lIndex, char cSortType /*= C_cAlphaOrder */ )
{
// recuperate true index
if ( (lIndex = m_fn_wGetIndexSwitchOrder((short) lIndex, cSortType )) == TSL_cItemNotFound)
return FALSE;
// update selected item
if (lIndex == m_lSelectedItem)
m_lSelectedItem = TSL_cItemNotFound;
else if (m_lSelectedItem > lIndex)
m_lSelectedItem --;
//destroy the item, and remove it from the array
delete (m_oArrayOfTSLItem[lIndex]);
m_oArrayOfTSLItem.RemoveAt(lIndex);
//shift all items in the reorder lists that are after the one referenced
for
(
long lOrder = 0, *p_lCommon = m_d_lCommonIndex, *p_lEdited = m_d_lEditedIndex;
lOrder < m_lNumberOfElements;
lOrder ++, p_lCommon ++, p_lEdited ++
)
{
if ( *p_lCommon >= lIndex )
(*p_lCommon) --;
if ( *p_lEdited >= lIndex )
(*p_lEdited) --;
}
// decrease number of item
m_lNumberOfElements --;
return TRUE;
}
/*-----------------------------------------------------------------------------
* Description : delete all items
*---------------------------------------------------------------------------*/
BOOL CThreeSortedList::m_fn_bDeleteAllItems(void)
{
for( int i = 0; i< m_lNumberOfElements ; i ++ )
delete m_oArrayOfTSLItem[i];
if ( m_d_lCommonIndex )
{
free(m_d_lCommonIndex);
m_d_lCommonIndex = NULL;
}
if ( m_d_lEditedIndex )
{
free(m_d_lEditedIndex);
m_d_lEditedIndex = NULL;
}
m_lSelectedItem = TSL_cItemNotFound;
m_lMaxElements = 0;
m_lNumberOfElements = 0;
m_oArrayOfTSLItem.SetSize(0);
return TRUE;
}
/*-----------------------------------------------------------------------------
* Description : swaps two items
*---------------------------------------------------------------------------*/
void CThreeSortedList::m_fn_vSwapEditedItems( long lIndex1, long lIndex2 )
{
long lTemp;
if ( M_bIsIndexValid(lIndex1) && M_bIsIndexValid(lIndex2) )
{
lTemp = m_d_lEditedIndex[lIndex1];
m_d_lEditedIndex[lIndex1] = m_d_lEditedIndex[lIndex2];
m_d_lEditedIndex[lIndex2] = lTemp;
}
}
/*-----------------------------------------------------------------------------
* description : deplace one item in a order list
*---------------------------------------------------------------------------*/
void CThreeSortedList::m_fn_vDeplaceOrderedItem(long lIndex, long lNewIndex, char cSortType)
{
long *m_p_lOrder;
// get order list, or exit if order is invalid (unknown or alpha order)
switch (cSortType)
{
case C_cCommonOrder:
m_p_lOrder = m_d_lCommonIndex;
break;
case C_cEditedOrder:
m_p_lOrder = m_d_lEditedIndex;
break;
default:
return;
}
// verify data (the two index)
if (M_bIsIndexValid(lIndex) && M_bIsIndexValid(lNewIndex) && (lIndex != lNewIndex) )
{
// save index item to deplace
long lTemp = m_p_lOrder[lIndex];
// move other index to make a place
if (lIndex > lNewIndex)
memmove(m_p_lOrder + lNewIndex + 1, m_p_lOrder + lNewIndex, sizeof(long) * (lIndex - lNewIndex));
else // lIndex < lNewIndex
memmove(m_p_lOrder + lIndex, m_p_lOrder + lIndex + 1, sizeof(long) * (lNewIndex - lIndex));
// set item in the new place
m_p_lOrder[lNewIndex] = lTemp;
}
}
/*-----------------------------------------------------------------------------
* description : set the more common item
*---------------------------------------------------------------------------*/
void CThreeSortedList::m_fn_vSetCommonItem(long lIndex)
{
m_fn_vDeplaceOrderedItem(lIndex, 0, C_cCommonOrder);
}
/*-----------------------------------------------------------------------------
* Description : get an item
*---------------------------------------------------------------------------*/
tdstTSLItem *CThreeSortedList::m_fn_p_stGetItem(long lIndex, char cSortType /*= C_cAlphaOrder */)
{
// recuperate true index
if ( (lIndex = m_fn_wGetIndexSwitchOrder((short) lIndex, cSortType )) == TSL_cItemNotFound)
return NULL;
//return &m_d_stItem[lIndex];
return m_oArrayOfTSLItem[lIndex];
}
/*-----------------------------------------------------------------------------
* Description : get name of an item
*---------------------------------------------------------------------------*/
CString CThreeSortedList::m_fn_csGetName( long lIndex, char cSortType /*= C_cAlphaOrder */)
{
// get item
tdstTSLItem *p_stItem = m_fn_p_stGetItem(lIndex, cSortType);
// return item string if item was found
if (p_stItem)
return ( p_stItem->m_csName );
return "";
}
/*-----------------------------------------------------------------------------
* Description : get image of an item
*---------------------------------------------------------------------------*/
short CThreeSortedList::m_fn_wGetImage(long lIndex, char cSortType /*= C_cAlphaOrder */)
{
// get item
tdstTSLItem *p_stItem = m_fn_p_stGetItem(lIndex, cSortType);
// return image index of item
if (p_stItem)
return ( p_stItem->m_wImage);
return -1;
}
/*-----------------------------------------------------------------------------
* Description : get content of an item
*---------------------------------------------------------------------------*/
long CThreeSortedList::m_fn_lGetContent( long lIndex, char cSortType /*= C_cAlphaOrder */ )
{
// get item
tdstTSLItem *p_stItem = m_fn_p_stGetItem( lIndex, cSortType );
// return item content if item was found
if (p_stItem)
return ( p_stItem->m_lContent );
return NULL;
}
/*-----------------------------------------------------------------------------
* Description : find an item that correspond to the given item pointer
*---------------------------------------------------------------------------*/
long CThreeSortedList::m_fn_lFindItem(long lStartAt, tdstTSLItem *p_stItem, char cSortType /*= C_cAlphaOrder */)
{
if ( lStartAt < 0 )
lStartAt = 0;
for (short wIndex = (short) lStartAt; wIndex < (short) m_lNumberOfElements; wIndex ++)
{
//if ( &m_d_stItem[ m_fn_wGetIndexSwitchOrder(wIndex, cSortType) ] == p_stItem )
if ( (m_oArrayOfTSLItem[m_fn_wGetIndexSwitchOrder(wIndex, cSortType)]) == p_stItem )
return wIndex;
}
return TSL_cItemNotFound;
}
/*-----------------------------------------------------------------------------
* Description : find item with same name as the given one
*---------------------------------------------------------------------------*/
long CThreeSortedList::m_fn_lFindName(long lStartAt, CString csName, char cSortType /*= C_cAlphaOrder */)
{
if ( lStartAt < 0 )
lStartAt = 0;
for (short wIndex = (short) lStartAt; wIndex < (short) m_lNumberOfElements; wIndex ++)
{
if (csName == (m_oArrayOfTSLItem[m_fn_wGetIndexSwitchOrder(wIndex, cSortType)])->m_csName )
return wIndex;
}
return TSL_cItemNotFound;
}
/*-----------------------------------------------------------------------------
* Description : find item with the same image as the given one
*---------------------------------------------------------------------------*/
long CThreeSortedList::m_fn_lFindImage( long lStartAt, short wImage, char cSortType /*= C_cAlphaOrder */)
{
if ( lStartAt < 0 )
lStartAt = 0;
for (short wIndex = (short) lStartAt; wIndex < (short) m_lNumberOfElements; wIndex ++)
{
if (m_oArrayOfTSLItem[m_fn_wGetIndexSwitchOrder(wIndex, cSortType)]->m_wImage == wImage )
return wIndex;
}
return TSL_cItemNotFound;
}
/*-----------------------------------------------------------------------------
* Description : find item with the same content as the given one
*---------------------------------------------------------------------------*/
long CThreeSortedList::m_fn_lFindContent( long lStartAt, long lContent, char cSortType /*= C_cAlphaOrder*/ )
{
if ( lStartAt < 0 )
lStartAt = 0;
for (short wIndex = (short) lStartAt; wIndex < (short) m_lNumberOfElements; wIndex ++)
{
if (m_oArrayOfTSLItem[m_fn_wGetIndexSwitchOrder(wIndex, cSortType)]->m_lContent == lContent )
return wIndex;
}
return TSL_cItemNotFound;
}
/*-----------------------------------------------------------------------------
* Description : set selected item
*---------------------------------------------------------------------------*/
void CThreeSortedList::m_fn_vSetSelectedItem( long lIndex, char cSortType )
{
m_lSelectedItem = m_fn_wGetIndexSwitchOrder( (short) lIndex, cSortType );
}
/*-----------------------------------------------------------------------------
* Description : return selected item
*---------------------------------------------------------------------------*/
long CThreeSortedList::m_fn_lGetSelectedItem( char cSortType )
{
return m_fn_wAlphaToAnotherOrder( (short) m_lSelectedItem, cSortType );
}
/*-----------------------------------------------------------------------------
* Description : is the given item the selected one ?
*---------------------------------------------------------------------------*/
BOOL CThreeSortedList::m_fn_bIsItemSelected( long lIndex, char cSortType )
{
return (m_lSelectedItem == m_fn_wGetIndexSwitchOrder( (short) lIndex, cSortType ));
}
/*-----------------------------------------------------------------------------
* Description : unselect item
*---------------------------------------------------------------------------*/
void CThreeSortedList::m_fn_vUnselectItem( void )
{
m_lSelectedItem = TSL_cItemNotFound;
}
/*=============================================================================
* implementation of class C3ListFrame
=============================================================================*/
IMPLEMENT_DYNCREATE(C3ListFrame, FRMBase)
BEGIN_MESSAGE_MAP(C3ListFrame, FRMBase)
ON_WM_CREATE()
ON_WM_CLOSE()
END_MESSAGE_MAP()
/*-----------------------------------------------------------------------------
* Description : constructor
*---------------------------------------------------------------------------*/
C3ListFrame::C3ListFrame(void)
{
}
/*-----------------------------------------------------------------------------
* Description : create the window
*---------------------------------------------------------------------------*/
int C3ListFrame::OnCreate(LPCREATESTRUCT _p_stCreateStruct)
{
// Create frame
if (CFrameWnd::OnCreate(_p_stCreateStruct) == -1)
return -1;
return 0;
}
/*-----------------------------------------------------------------------------
* Description : close the window
*---------------------------------------------------------------------------*/
void C3ListFrame::OnClose(void)
{
CFrameWnd::OnClose();
}
/*=============================================================================
* implementation off C3ListView class
=============================================================================*/
IMPLEMENT_DYNCREATE(C3ListView, CScrollView)
BEGIN_MESSAGE_MAP(C3ListView, CScrollView)
ON_WM_PAINT()
ON_WM_CREATE()
ON_WM_RBUTTONDOWN()
ON_WM_LBUTTONDOWN()
ON_WM_MOUSEMOVE()
ON_MESSAGE( WM_DRAGDROP_END, OnDragDropEnd )
ON_MESSAGE( WM_DRAGDROP_MOVE, OnDragDropMove )
ON_MESSAGE( WM_DRAGDROP_SCROLL, OnDragDropScroll )
ON_WM_WINDOWPOSCHANGED()
ON_WM_KEYDOWN()
END_MESSAGE_MAP()
/*-----------------------------------------------------------------------------
* Description : constructor
*---------------------------------------------------------------------------*/
C3ListView::C3ListView( void ): CScrollView(), CThreeSortedList()
{
// initialise member variables
// box to display bitmap alone
m_a_oDisplayBox[C_cDisplayBitmap].cx = 30;
m_a_oDisplayBox[C_cDisplayBitmap].cy = 30;
// box to display text & bitmap
m_a_oDisplayBox[C_cDisplayBitmapAndText].cx = 80;
m_a_oDisplayBox[C_cDisplayBitmapAndText].cy = 50;
// box to display text alone
m_a_oDisplayBox[C_cDisplayText].cx = 80;
m_a_oDisplayBox[C_cDisplayText].cy = 20;
// display grid
m_bGrid = TRUE;
// current order
m_cCurrentOrder = C_cAlphaOrder;
// current deplacement type
m_cMoveType = C_cSwap;
// init menu flags
m_lMenuFlags = TLVM_lMenu | TLVM_lGrid | TLVM_lOrder | TLVM_lDisplay;
//Init Drag&Drop data
m_oDDCase.fn_vSetDataType( 1234 );
m_oDDCase.fn_vSetEditorName("coucou");
m_wCaseWithTips = -1;
}
/*-----------------------------------------------------------------------------
* Description : set Drag and drop data and editor type
*---------------------------------------------------------------------------*/
void C3ListView::m_fn_vSetDDTypeAndEditor( UINT uiDataType, char *szEditorName )
{
m_oDDCase.fn_vSetDataType( uiDataType );
m_oDDCase.fn_vSetEditorName( szEditorName );
}
/*-----------------------------------------------------------------------------
* Description : get case index following point in client window rect
*---------------------------------------------------------------------------*/
short C3ListView::m_fn_wGetCaseFromClientPoint( int x, int y)
{
short wLine, wCase, wCol;
// compute coordinates in View
x += GetScrollPosition().x;
y += GetScrollPosition().y;
// compute col, line and case were point is
wCol = (short) (x / m_oCurrentBox.cx);
wLine = (short) (y / m_oCurrentBox.cy);
wCase = wLine * m_wNumberOfCols + wCol;
// check if case is valid
if ( (wCol >= m_wNumberOfCols) || (wLine >= m_wNumberOfLines) || (wCase >= m_fn_lGetCount()) )
return TSL_cItemNotFound;
return wCase;
}
/*-----------------------------------------------------------------------------
* Description : get case rectangle of a case given by it's index
*---------------------------------------------------------------------------*/
void C3ListView::m_fn_vGetCaseRect( short wIndex, RECT *pRect )
{
// get line and column of case
short wLine = wIndex / m_wNumberOfCols;
short wCol = wIndex - wLine * m_wNumberOfCols;
// compute rect
pRect->left = wCol * m_oCurrentBox.cx;
pRect->right = pRect->left + m_oCurrentBox.cx;
pRect->top = wLine * m_oCurrentBox.cy;
pRect->bottom = pRect->top + m_oCurrentBox.cy;
}
/*-----------------------------------------------------------------------------
* Description : Hide the tips for the m_wCaseWithTips case
*---------------------------------------------------------------------------*/
void C3ListView::m_fn_vHideTips( )
{
CDC *p_oDC;
long lWidth;
long lHeight;
if (m_wCaseWithTips == -1)
return;
m_wCaseWithTips = -1;
//p_oDC = GetWindowDC();
p_oDC = GetDesktopWindow()->GetWindowDC();
lWidth = m_stTipsRect.right - m_stTipsRect.left + 1;
lHeight = m_stTipsRect.bottom - m_stTipsRect.top + 1;
p_oDC->BitBlt( m_stTipsRect.left, m_stTipsRect.top, lWidth, lHeight, &m_oCDCTip, 0, 0, SRCCOPY );
ReleaseDC( p_oDC );
m_oCDCTip.DeleteDC();
m_oBitmapTip.DeleteObject();
}
/*-----------------------------------------------------------------------------
* Description : show the tips for the m_wCaseWithTips case
*---------------------------------------------------------------------------*/
void C3ListView::m_fn_vShowTips( void )
{
CDC *p_oDC;
CFont xFnt, *xFntPrev = NULL;
PLOGFONT plf = (PLOGFONT) LocalAlloc(LPTR, sizeof(LOGFONT));
CString csString;
CSize oTextSize;
RECT stWinRect;
if (m_wCaseWithTips == -1)
return;
p_oDC = GetDesktopWindow()->GetWindowDC();
/*
* compute tip rect
*/
m_fn_vGetCaseRect( m_wCaseWithTips, &m_stTipsRect );
m_stTipsRect.left -= GetScrollPosition().x;
m_stTipsRect.right -= GetScrollPosition().x;
m_stTipsRect.top -= GetScrollPosition().y;
m_stTipsRect.bottom -= GetScrollPosition().y;
ClientToScreen( &m_stTipsRect );
lstrcpy(plf->lfFaceName, "Arial Narrow");
plf->lfWeight = FW_NORMAL;
plf->lfHeight = 16;
plf->lfEscapement = 0;
if (xFnt.CreateFontIndirect(plf))
xFntPrev = p_oDC->SelectObject( &xFnt );
csString = m_fn_csGetName( m_wCaseWithTips, m_cCurrentOrder );
oTextSize = p_oDC->GetTextExtent( csString, csString.GetLength() );
oTextSize.cx += 4;
oTextSize.cy += 4;
m_stTipsRect.left = (m_stTipsRect.left + m_stTipsRect.right - 1 - oTextSize.cx) / 2;
m_stTipsRect.right = m_stTipsRect.left + oTextSize.cx;
if (m_cDisplayType == C_cDisplayBitmap)
{
m_stTipsRect.top = m_stTipsRect.bottom;
m_stTipsRect.bottom += oTextSize.cy;
}
else
m_stTipsRect.top = m_stTipsRect.bottom - oTextSize.cy;
GetWindowRect( &stWinRect );
if (m_stTipsRect.top > stWinRect.bottom)
{
m_stTipsRect.top = stWinRect.bottom;
m_stTipsRect.bottom = m_stTipsRect.top + oTextSize.cy;
}
/*
* save tip background
*/
m_oCDCTip.CreateCompatibleDC( p_oDC );
m_oBitmapTip.CreateCompatibleBitmap( p_oDC, oTextSize.cx , oTextSize.cy );
m_oCDCTip.SelectObject( &m_oBitmapTip );
m_oCDCTip.BitBlt( 0, 0, oTextSize.cx, oTextSize.cy, p_oDC, m_stTipsRect.left, m_stTipsRect.top, SRCCOPY);
/*
* draw tip
*/
p_oDC->Rectangle( &m_stTipsRect );
//p_oDC->FillSolidRect( &m_stTipsRect, RGB(255,255,255) );
// draw string
p_oDC->SetBkMode( TRANSPARENT );
p_oDC->SetTextAlign( TA_CENTER | TA_BOTTOM );
p_oDC->TextOut((m_stTipsRect.left + m_stTipsRect.right + 1) / 2, m_stTipsRect.bottom - 2, csString, csString.GetLength());
if ( xFntPrev )
{
p_oDC->SelectObject(xFntPrev);
xFnt.DeleteObject();
}
//do not forget to free the memory for the font
LocalFree(plf);
ReleaseDC( p_oDC);
}
/*-----------------------------------------------------------------------------
* Description : make the view scroll so that the item is visible, if necessary
*---------------------------------------------------------------------------*/
void C3ListView::m_vScrollToMakeItemVisible(short _wItem)
{
Invalidate();
if ( _wItem == TSL_cItemNotFound )
return;
CRect oItemRect, oClientRect;
GetClientRect(oClientRect);
oClientRect.OffsetRect(GetScrollPosition());
m_fn_vGetCaseRect(_wItem, &oItemRect);
//if the item's rectangle is not entirely visible in the client
if ( (oClientRect & oItemRect) != oItemRect )
{
//make the view scroll so that the center of the item's rectangle is
//vertically moved to the middle of the client area
POINT stPoint;
stPoint.x = GetScrollPosition().x;
stPoint.y = oItemRect.CenterPoint().y - oClientRect.Height() / 2;
ScrollToPosition(stPoint);
}
}
/*-----------------------------------------------------------------------------
* Description : change display type
*---------------------------------------------------------------------------*/
void C3ListView::m_fn_vChangeDisplayType( char _cDisplayType )
{
// check display type
if
(
(((unsigned char) _cDisplayType) >= C_cNumberOfDisplayTypes)
//|| (m_cDisplayType == _cDisplayType)
)
return;
// change current case size
m_oCurrentBox = m_a_oDisplayBox[ _cDisplayType ];
// change display type varialbe
m_cDisplayType = _cDisplayType;
// calculate new size of CScrollView
RECT rect;
CSize sz;
//GetParent()->GetClientRect( &rect );
GetWindowRect( &rect );
// compute number of columns that fit in view rect
//m_wNumberOfCols = rect.right / m_oCurrentCase.cx;
m_wNumberOfCols = (short) ((rect.right - rect.left - 14) / m_oCurrentBox.cx);
if (m_wNumberOfCols <= 0) m_wNumberOfCols = 1;
// compute number of lines
m_wNumberOfLines = (m_fn_lGetCount() + m_wNumberOfCols - 1) / m_wNumberOfCols;
// compute size of view
sz.cx = m_wNumberOfCols * m_oCurrentBox.cx;
sz.cy = m_wNumberOfLines * m_oCurrentBox.cy;
if (sz.cy == 0) sz.cy = 1;
SetScrollSizes( MM_TEXT, sz );
// redraw view
m_vScrollToMakeItemVisible((short) m_fn_lGetSelectedItem(m_cCurrentOrder));
}
/*-----------------------------------------------------------------------------
* Description : change order
*---------------------------------------------------------------------------*/
void C3ListView::m_fn_vChangeOrder( char _cOrder )
{
if (_cOrder == m_cCurrentOrder)
return;
// resize view if necessary
/*
if ( _cOrder == C_cEditedOrder || m_cCurrentOrder == C_cEditedOrder)
{
CWnd *pFrameBase = GetParent();
while ( !pFrameBase->IsKindOf( RUNTIME_CLASS( FRMBase ) ) )
{
pFrameBase = pFrameBase->GetParent();
}
((FRMBase *) pFrameBase)->m_fn_vSwapFullScreen();
}
*/
// change order variable
m_cCurrentOrder = _cOrder;
// redraw view
m_vScrollToMakeItemVisible((short) m_fn_lGetSelectedItem(m_cCurrentOrder));
}
/*-----------------------------------------------------------------------------
* Description : change size of a display box
*---------------------------------------------------------------------------*/
void C3ListView::m_fn_vSetBox( char _cDisplayType, int _iWidth, int _iHeight)
{
// check display type
if (((unsigned char) _cDisplayType) >= C_cNumberOfDisplayTypes)
return;
// set new size
m_a_oDisplayBox[ _cDisplayType ].cx = _iWidth;
m_a_oDisplayBox[ _cDisplayType ].cy = _iHeight;
if (_cDisplayType == m_cDisplayType )
m_fn_vChangeDisplayType( _cDisplayType ); // to refresh display
}
/*-----------------------------------------------------------------------------
* Description : enable a menu flag
*---------------------------------------------------------------------------*/
void C3ListView::m_fn_vEnableMenuItem( long lFlags )
{
m_lMenuFlags |= lFlags;
}
/*-----------------------------------------------------------------------------
* Description : disable some menu flag
*---------------------------------------------------------------------------*/
void C3ListView::m_fn_vDisableMenuItem( long lFlags )
{
m_lMenuFlags &= ~lFlags;
}
/*-----------------------------------------------------------------------------
* Description : handle function fo WM_CREATE message
*---------------------------------------------------------------------------*/
int C3ListView::OnCreate( LPCREATESTRUCT _p_stCreateStruct )
{
if ( CScrollView::OnCreate(_p_stCreateStruct) == -1 )
return -1;
m_fn_vChangeDisplayType( C_cDisplayText );
m_oDDCase.fn_vSetOwner( this );
return 0;
}
/*-----------------------------------------------------------------------------
* Description : handle function fo WM_RBUTTONDOWN message
*---------------------------------------------------------------------------*/
void C3ListView::OnRButtonDown(UINT nFlags, CPoint pt )
{
if ((m_lMenuFlags & TLVM_lMenu) == 0)
return;
// hide tips if one
m_fn_vHideTips();
ClientToScreen( &pt );
// create popup menu
CMenu oMenu;
oMenu.CreatePopupMenu();
// entries to change display type
if (m_lMenuFlags & TLVM_lBitmapAndText)
oMenu.AppendMenu( MF_STRING | ((m_cDisplayType == C_cDisplayBitmapAndText)?MF_CHECKED:MF_UNCHECKED), 1, "Bitmap and Text");
if (m_lMenuFlags & TLVM_lText)
oMenu.AppendMenu( MF_STRING | ((m_cDisplayType == C_cDisplayText)?MF_CHECKED:MF_UNCHECKED), 2, "Only Text");
if (m_lMenuFlags & TLVM_lBitmap)
oMenu.AppendMenu( MF_STRING | ((m_cDisplayType == C_cDisplayBitmap)?MF_CHECKED:MF_UNCHECKED), 3, "Only Bitmap");
if ((m_lMenuFlags & TLVM_lDisplay ) && (m_lMenuFlags & (TLVM_lGrid | TLVM_lOrder)) )
oMenu.AppendMenu( MF_SEPARATOR );
// entry to swap grid on/off
if (m_lMenuFlags & TLVM_lGrid)
{
oMenu.AppendMenu( (m_bGrid ? MF_CHECKED : MF_UNCHECKED) | MF_STRING, 4, "Grid");
if (m_lMenuFlags & TLVM_lOrder)
oMenu.AppendMenu( MF_SEPARATOR );
}
// entries to change display order
if (m_lMenuFlags & TLVM_lAlphabetic)
oMenu.AppendMenu( MF_STRING | ((m_cCurrentOrder == C_cAlphaOrder)?MF_CHECKED:MF_UNCHECKED), 5, "Alphabetic");
if (m_lMenuFlags & TLVM_lCommon)
oMenu.AppendMenu( MF_STRING | ((m_cCurrentOrder == C_cCommonOrder)?MF_CHECKED:MF_UNCHECKED), 6, "Common");
if (m_lMenuFlags & TLVM_lEdited)
oMenu.AppendMenu( MF_STRING | ((m_cCurrentOrder == C_cEditedOrder)?MF_CHECKED:MF_UNCHECKED), 7, "Edited");
// entry to change move type (if in edited order)
if (m_cCurrentOrder == C_cEditedOrder)
{
oMenu.AppendMenu( MF_SEPARATOR );
if (m_cMoveType == C_cSwap)
oMenu.AppendMenu( MF_STRING, 8, "Deplace");
else
oMenu.AppendMenu( MF_STRING, 8, "Swap");
}
//enable derived instances to add their own entries in the menu, starting with this value
_InitPopupMenu(oMenu, 9);
// register the popup menu for the tutorial module
TUT_M_vGetTutDll ();
TUT_M_vRegisterMenu (this -> m_hWnd , oMenu . m_hMenu , pt. x , pt . y);
// display & track popup menu
oMenu.TrackPopupMenu( TPM_LEFTALIGN | TPM_RIGHTBUTTON, pt.x, pt.y, this);
// destroy menus
oMenu.DestroyMenu();
}
/*-----------------------------------------------------------------------------
* Description : on select item
*---------------------------------------------------------------------------*/
void C3ListView::OnSelectItem( short wCase )
{
RECT rect;
CDC *pDC = GetDC();
CPoint oPt = GetScrollPosition();
long lOldSelected = m_fn_lGetSelectedItem(m_cCurrentOrder);
m_fn_vSetSelectedItem( wCase, m_cCurrentOrder );
if (wCase != lOldSelected )
{
if ( lOldSelected != TSL_cItemNotFound )
{
m_fn_vGetCaseRect((short) lOldSelected, &rect );
rect.top -= oPt.y;
rect.bottom -= oPt.y;
rect.left -= oPt.x;
rect.right -= oPt.x;
pDC->InvertRect( &rect );
}
if ( wCase != TSL_cItemNotFound )
{
m_fn_vGetCaseRect(wCase, &rect );
rect.top -= oPt.y;
rect.bottom -= oPt.y;
rect.left -= oPt.x;
rect.right -= oPt.x;
pDC->InvertRect( &rect );
}
}
ReleaseDC( pDC );
}
/*-----------------------------------------------------------------------------
* Description : handle function fo WM_LBUTTONDOWN message
*---------------------------------------------------------------------------*/
void C3ListView::OnLButtonDown(UINT nFlags, CPoint pt )
{
short wCase;
RECT rect;
// hide tips if one
m_fn_vHideTips();
// compute case under mouse
wCase = m_fn_wGetCaseFromClientPoint( pt.x, pt.y);
OnSelectItem( wCase );
if ( wCase == TSL_cItemNotFound )
return;
// get case rectangle
m_fn_vGetCaseRect( wCase, &rect );
// Set Drag & drop data
m_oDDCase.fn_vSetData( (void *) wCase );
// Add reference on window that accept Drop message
// can drag and drop in this window only if we are in Edited order
if (m_cCurrentOrder == C_cEditedOrder )
{
RECT windowRect;
RECT scrollRect;
int iWidth;
GetWindowRect( &windowRect );
if ((iWidth = (windowRect.bottom - windowRect.top) / 2) > 10)
iWidth = 10;
scrollRect.right = windowRect.right;
scrollRect.left = windowRect.left;
scrollRect.top = windowRect.top;
scrollRect.bottom = scrollRect.top + iWidth;
DD_vRegisterRect( &scrollRect, this->GetSafeHwnd() );
scrollRect.bottom = windowRect.bottom;
scrollRect.top = scrollRect.bottom - iWidth;
DD_vRegisterRect( &scrollRect, this->GetSafeHwnd() );
DD_vSetScrollTime( 100 );
DD_eAddReference( this->GetSafeHwnd(), m_oDDCase.fn_p_szGetEditorName(), m_oDDCase.fn_uiGetDataType(), FALSE );
}
// launch drag & drop operation
HWND hWnd = DD_hBeginDragDrop( &rect, &m_oDDCase );
// if item was dragged to another window, set first in the common order
if ( (hWnd != this->GetSafeHwnd()) && (hWnd != NULL) )
{
m_fn_vSetCommonItem( wCase );
Invalidate();
}
}
/*-----------------------------------------------------------------------------
* Description : handle function fo WM_MOUSEMOVE message
*---------------------------------------------------------------------------*/
void C3ListView::OnMouseMove( UINT nFlags, CPoint pt)
{
short wCase;
if (GetCapture() == this)
{
RECT stRect;
GetClientRect( &stRect );
if( (pt.x < 0) || (pt.y < 0) || (pt.x>stRect.right) || (pt.y>stRect.bottom) )
{
m_fn_vHideTips();
ReleaseCapture();
return;
}
if ((GetForegroundWindow() != this) || (GetActiveWindow() != this))
{
m_fn_vHideTips();
ReleaseCapture();
return;
}
}
else
{
SetCapture();
}
wCase = m_fn_wGetCaseFromClientPoint( pt.x, pt.y);
if (wCase == TSL_cItemNotFound)
{
if (m_wCaseWithTips != -1 )
m_fn_vHideTips();
}
else
{
if (m_wCaseWithTips != wCase)
{
if (m_wCaseWithTips != -1)
m_fn_vHideTips();
m_wCaseWithTips = wCase;
m_fn_vShowTips();
}
}
}
/*-----------------------------------------------------------------------------
* Description : handle function fo WM_DRAGDROP_SCROLL message
*---------------------------------------------------------------------------*/
LONG C3ListView::OnDragDropScroll( UINT wParam , LONG lParam)
{
RECT windowRect;
RECT *scrollRect = (RECT *) lParam;
POINT pos = GetScrollPosition();
GetWindowRect( &windowRect );
if (scrollRect->top == windowRect.top)
pos.y -= 20;
else
pos.y += 20;
ScrollToPosition( pos );
return 0;
}
/*-----------------------------------------------------------------------------
* Description : handle function fo WM_DRAGDROP_END message
*---------------------------------------------------------------------------*/
LONG C3ListView::OnDragDropEnd( UINT wParam , LONG lParam)
{
short wCase;
// check current order
if (m_cCurrentOrder != C_cEditedOrder)
return 0;
DD_Object *p_oDDObject = (DD_Object *) lParam;
// check if data come from this
if (p_oDDObject != &m_oDDCase )
return 0;
// compute case where object were dropped
ScreenToClient( &p_oDDObject->m_stMousePos );
wCase = m_fn_wGetCaseFromClientPoint( p_oDDObject->m_stMousePos.x, p_oDDObject->m_stMousePos.y );
if ( wCase == TSL_cItemNotFound )
return 0;
// swap item or deplace item switch move type
if (m_cMoveType == C_cSwap)
m_fn_vSwapEditedItems( (short) p_oDDObject->fn_p_vGetData(), wCase );
else
m_fn_vDeplaceOrderedItem( (short) p_oDDObject->fn_p_vGetData(), wCase, C_cEditedOrder );
//redraw list;
Invalidate();
return 0;
}
/*-----------------------------------------------------------------------------
* Description : handle function fo WM_DRAGDROP_MOVE message
*---------------------------------------------------------------------------*/
LONG C3ListView::OnDragDropMove( UINT wParam , LONG lParam)
{
return 0;
}
/*-----------------------------------------------------------------------------
* Description : pretranslate message
*---------------------------------------------------------------------------*/
BOOL C3ListView::PreTranslateMessage( MSG* pMsg )
{
if (pMsg->message == WM_KEYDOWN)
{
if (pMsg->wParam != VK_TAB)
{
OnKeyDown( pMsg->wParam, LOWORD(pMsg->lParam),HIWORD(pMsg->lParam) );
return 1;
}
}
return 0;
}
/*-----------------------------------------------------------------------------
* Description : handle function fo WM_COMMAND message
*---------------------------------------------------------------------------*/
BOOL C3ListView::OnCommand( WPARAM wParam, LPARAM lParam )
{
if (HIWORD(wParam) == 0) // command from a menu
{
switch (LOWORD(wParam) ) //ID of menu item
{
case 1:
m_fn_vChangeDisplayType( C_cDisplayBitmapAndText );
break;
case 2:
m_fn_vChangeDisplayType( C_cDisplayText );
break;
case 3:
m_fn_vChangeDisplayType( C_cDisplayBitmap );
break;
case 4:
m_bGrid = !m_bGrid;
Invalidate();
break;
case 5:
m_fn_vChangeOrder( C_cAlphaOrder );
break;
case 6:
m_fn_vChangeOrder( C_cCommonOrder );
break;
case 7:
m_fn_vChangeOrder( C_cEditedOrder );
break;
case 8:
m_cMoveType = 1 - m_cMoveType;
break;
//handle entries added by derived instances
default:
_OnCommand(LOWORD(wParam));
break;
}
}
return FALSE;
}
/*-----------------------------------------------------------------------------
* Description : handle function fo WM_KEYDOW message
*---------------------------------------------------------------------------*/
void C3ListView::OnKeyDown( UINT nChar, UINT nRepCnt, UINT nFlags )
{
short wDeltaY = 0;
switch (nChar)
{
case VK_DOWN: wDeltaY = 10; break;
case VK_UP: wDeltaY = -10; break;
case VK_PRIOR: wDeltaY = -50; break;
case VK_NEXT: wDeltaY = 50; break;
case VK_HOME: wDeltaY = (short) -GetScrollPosition().y; break;
case VK_END: wDeltaY = (short) (GetTotalSize().cy - GetScrollPosition().y); break;
}
if (wDeltaY)
{
CPoint pt = GetScrollPosition();
pt.y += wDeltaY;
ScrollToPosition( (POINT) pt );
}
}
/*-----------------------------------------------------------------------------
* Description : handle function for WM_WINDOWPOSCHANGED message
*---------------------------------------------------------------------------*/
void C3ListView::OnWindowPosChanged( WINDOWPOS* lpwndpos )
{
m_fn_vChangeDisplayType(m_cDisplayType);
}
/*-----------------------------------------------------------------------------
* Description : handle function for drawing message
*---------------------------------------------------------------------------*/
void C3ListView::OnDraw(CDC *pDC )
{
RECT rect;
pDC->GetClipBox( &rect);
m_fn_vHideTips();
// calculate first case and last case in drawing zone
short wFirstLine = (short) (rect.top / m_oCurrentBox.cy);
short wLastLine = (short) (rect.bottom / m_oCurrentBox.cy);
if (wFirstLine < 0) wFirstLine = 0;
if (wLastLine >= m_wNumberOfLines) wLastLine = m_wNumberOfLines - 1;
rect.top = wFirstLine * m_oCurrentBox.cy;
rect.bottom = rect.top + m_oCurrentBox.cy;
short wCase = wFirstLine * m_wNumberOfCols;
for ( short wLine = wFirstLine; wLine <= wLastLine ; wLine ++)
{
rect.left = 0;
rect.right = m_oCurrentBox.cx;
for ( short wCol = 0; wCol < m_wNumberOfCols && wCase < m_fn_lGetCount(); wCase ++, wCol ++ )
{
m_fn_vOverriddenDrawItem( wCase, pDC, &rect );
rect.left += m_oCurrentBox.cx;
rect.right += m_oCurrentBox.cx;
}
rect.top += m_oCurrentBox.cy;
rect.bottom += m_oCurrentBox.cy;
}
}
/*-----------------------------------------------------------------------------
* Description : draw an item
*---------------------------------------------------------------------------*/
void C3ListView::m_fn_vDrawItem(short wItem, CDC *pDC, RECT *p_Rect, short _wSpecialImage /*= TSL_cItemNotFound */ )
{
RECT stBitmapRect;
CPoint oImageOrg;
short wImage = m_fn_wGetImage(wItem, m_cCurrentOrder);
// draw rectangle
if ( m_bGrid )
pDC->Rectangle(p_Rect);
else
pDC->FillRect(p_Rect, pDC->GetCurrentBrush());
switch ( m_cDisplayType )
{
case C_cDisplayBitmap:
if ( (m_fn_p_oGetBitmapList()) && (wImage != TSL_cItemNotFound) )
{
stBitmapRect.top = p_Rect->top - GetScrollPosition().y + 1;
stBitmapRect.bottom = p_Rect->bottom - GetScrollPosition().y - 1;
stBitmapRect.left = p_Rect->left - GetScrollPosition().x + 1;
stBitmapRect.right = p_Rect->right - GetScrollPosition().x - 1;
oImageOrg.x = (stBitmapRect.left + stBitmapRect.right) / 2;
oImageOrg.y = (stBitmapRect.top + stBitmapRect.bottom) / 2;
m_fn_p_oGetBitmapList()->m_fn_vDraw( pDC, wImage, oImageOrg, &stBitmapRect, BA_CENTER , BA_CENTER );
}
break;
case C_cDisplayBitmapAndText:
// display bitmap
if ( (m_fn_p_oGetBitmapList()) && (wImage != TSL_cItemNotFound) )
{
stBitmapRect.top = p_Rect->top - GetScrollPosition().y + 2;
stBitmapRect.bottom = p_Rect->bottom - GetScrollPosition().y - 20;
stBitmapRect.left = p_Rect->left - GetScrollPosition().x + 1;
stBitmapRect.right = p_Rect->right - GetScrollPosition().x - 1;
oImageOrg.x = (stBitmapRect.left + stBitmapRect.right) / 2;
oImageOrg.y = stBitmapRect.top;
m_fn_p_oGetBitmapList()->m_fn_vDraw( pDC, wImage, oImageOrg, &stBitmapRect, BA_CENTER , BA_TOP );
}
// no break : draw bitmap too
case C_cDisplayText:
// compute max number char to show to stay in rect
{
CFont xFnt, *xFntPrev = NULL;
PLOGFONT plf = (PLOGFONT) LocalAlloc(LPTR, sizeof(LOGFONT));
lstrcpy(plf->lfFaceName, "Arial Narrow");
plf->lfWeight = (m_cDisplayType == C_cDisplayBitmapAndText || wImage == _wSpecialImage) ? FW_NORMAL : FW_BOLD;
plf->lfHeight = 16;
plf->lfEscapement = 0;
if (xFnt.CreateFontIndirect(plf))
xFntPrev = pDC->SelectObject( &xFnt );
CString csString = m_fn_csGetName( wItem, m_cCurrentOrder );
short wNbChar = csString.GetLength() + 1;
CSize oTextSize;
do
{
wNbChar --;
oTextSize = pDC->GetTextExtent( csString, wNbChar );
} while (oTextSize.cx > (p_Rect->right - p_Rect->left -2) );
// draw string
pDC->SetBkMode( TRANSPARENT );
pDC->SetTextAlign( TA_CENTER | TA_BOTTOM );
pDC->TextOut((p_Rect->left + p_Rect->right) / 2, p_Rect->bottom - 2, csString, wNbChar);
if ( xFntPrev )
{
pDC->SelectObject(xFntPrev);
xFnt.DeleteObject();
}
//do not forget to free the memory for the font
LocalFree(plf);
}
break;
}
if ( m_fn_bIsItemSelected( wItem, m_cCurrentOrder) )
pDC->InvertRect( p_Rect );
}
/*-----------------------------------------------------------------------------
* Description : add an item
*---------------------------------------------------------------------------*/
int C3ListView::m_fn_iAddItem( CString csName, short wImage , long lContent, char cSortType /* C_cAlphaOrder*/ )
{
int iResult = CThreeSortedList::m_fn_iAddItem( csName, wImage, lContent, cSortType );
m_fn_vChangeDisplayType( m_cDisplayType );
return iResult;
}
/*-----------------------------------------------------------------------------
* Description : delete an item
*---------------------------------------------------------------------------*/
BOOL C3ListView::m_fn_bDeleteItem( long lIndex, char cSortType /*= C_cAlphaOrder*/ )
{
BOOL bResult = CThreeSortedList::m_fn_bDeleteItem( lIndex, cSortType );
if (bResult)
m_fn_vChangeDisplayType( m_cDisplayType);
return bResult;
}
/*-----------------------------------------------------------------------------
* Description : delete all items
*---------------------------------------------------------------------------*/
BOOL C3ListView::m_fn_bDeleteAllItems()
{
BOOL bResult = CThreeSortedList::m_fn_bDeleteAllItems();
if (bResult)
m_fn_vChangeDisplayType(m_cDisplayType);
return bResult;
}
#endif // ACTIVE_EDITOR