// EIKDCLBI.CPP
//
// Copyright (c) 1997-1999 Symbian Ltd.  All rights reserved.
//

#include <eikdclbi.h>
#include <eikdclbm.h>
#include <eikdutil.h>
#include <eiktxtut.h>
#include <eikclbd.h>
#include <eiklbx.pan>
#include <eikenv.h>

const TInt KParentBitmapIndex=0;
const TInt KFolderBitmapIndex=1;
const TInt KFileBitmapIndex=2;

const TInt KMinNumOfCharsInName=8;
const TInt KMaxNumOfCharsInSize=8; // ie for reading files of size >=100Mb will need to use SetColumnWidths()
const TInt KNumOfFiguresInDate=6; // ie years are shown with only two numbers

const TInt KBitmapColumnIndex=0;
const TInt KNameColumnIndex=1;
const TInt KPostNameGapColumnIndex=2;
const TInt KSizeColumnIndex=3;
const TInt KPostSizeColumnGap=4;
const TInt KDateColumnIndex=5;

const TInt KBitmapNameGap=4;
const TInt KTextTextGap=8;

//
// class CDirContentsListItemDrawer::TColumnWidths
//

EXPORT_C CDirContentsListItemDrawer::TColumnWidths::TColumnWidths()
	: iBitmap(0),iName(0),iSize(0),iDate(0)
	{}

//
// class CDirContentsListItemDrawer
//

EXPORT_C CDirContentsListItemDrawer::CDirContentsListItemDrawer(const CDirContentsListBoxModel* aModel)
	: iModel(aModel)
	{
	iFlags=EShowSize|EShowDate;
	TLocale locale;
	TChar tmp=locale.DateSeparator(1);
	iSeparators.Zero();
	iSeparators.Append(tmp);
	tmp=locale.DateSeparator(2);
	iSeparators.Append(tmp);
	}

EXPORT_C CDirContentsListItemDrawer::~CDirContentsListItemDrawer()
	{
	delete iColumnData;
	}

EXPORT_C void CDirContentsListItemDrawer::ConstructL(CArrayPtr<CFbsBitmap>* aBitmaps,
													const CFont* aFont,const CFont* aDetailsFont)
	{
	iColumnData=CColumnListBoxData::NewL();
	iColumnData->SetGraphicsColumnL(KBitmapColumnIndex,ETrue);
	iColumnData->SetColumnAlignmentL(KBitmapColumnIndex,CGraphicsContext::ELeft);
	iColumnData->SetColumnFontL(KNameColumnIndex,aFont);
	iColumnData->SetColumnAlignmentL(KNameColumnIndex,CGraphicsContext::ELeft);
	iColumnData->SetColumnWidthPixelL(KPostNameGapColumnIndex,KTextTextGap);
	iColumnData->SetColumnFontL(KSizeColumnIndex,aDetailsFont);
	iColumnData->SetColumnAlignmentL(KSizeColumnIndex,CGraphicsContext::ERight);
	iColumnData->SetColumnWidthPixelL(KPostSizeColumnGap,KTextTextGap);
	iColumnData->SetColumnFontL(KDateColumnIndex,aDetailsFont);
	iColumnData->SetColumnAlignmentL(KDateColumnIndex,CGraphicsContext::ERight);
	if (aBitmaps)
		iColumnData->SetBitmapArray(aBitmaps); // ownership transfers to iColumnData
	}

EXPORT_C void CDirContentsListItemDrawer::SetBitmapArray(CArrayPtr<CFbsBitmap>* aBitmaps)
	{
	iColumnData->SetBitmapArray(aBitmaps); // ownership transfers to iColumnData
	}

EXPORT_C CDirContentsListBoxModel* CDirContentsListItemDrawer::DclModel() const
	{
	return (CDirContentsListBoxModel*)iModel;
	}

EXPORT_C TInt CDirContentsListItemDrawer::ItemWidthInPixels(TInt /*aItemIndex*/) const
	{
	TInt itemWidth=0;
	for (TInt ii=0;ii<=KDateColumnIndex;ii++)
		itemWidth+=iColumnData->ColumnWidthPixel(ii);
	return itemWidth;
	}

EXPORT_C TSize CDirContentsListItemDrawer::MinimumCellSize() const
	{
	TSize size;
	CFbsBitmap* icon=ItemBitmap(0); // assumes all/no entries have icons and icon is no taller than the name font
	const TSize iconSize=(icon? icon->SizeInPixels() : TSize());
	const CFont* font=iColumnData->ColumnFont(KNameColumnIndex);
	size.iHeight=Max(font->HeightInPixels(),iconSize.iHeight)+VerticalInterItemGap();
	if (icon)
		size.iWidth=icon->SizeInPixels().iWidth+KBitmapNameGap;
	size.iWidth+=font->MaxNormalCharWidthInPixels()*KMinNumOfCharsInName;
	font=iColumnData->ColumnFont(KSizeColumnIndex); // same as date font
	if (iFlags&EShowSize)
		size.iWidth+=(font->WidthZeroInPixels()*KMaxNumOfCharsInSize)+KTextTextGap;
	if (iFlags&EShowDate)
		{
		size.iWidth+=font->TextWidthInPixels(iSeparators.Left(1));
		size.iWidth+=font->TextWidthInPixels(iSeparators.Right(1));
		size.iWidth+=(font->WidthZeroInPixels()*KNumOfFiguresInDate)+KTextTextGap;
		}
	return size;
	}

EXPORT_C void CDirContentsListItemDrawer::SetViewRect(const TRect& aRect)
	{
	iViewRect=aRect;
	CalcColumnWidths();
	}

EXPORT_C void CDirContentsListItemDrawer::SetDclItemDrawerFlags(TInt aFlags)
	{
	iFlags|=aFlags;
	if (iFlags & (EShowSize|EShowDate))
		CalcColumnWidths();
	}

EXPORT_C void CDirContentsListItemDrawer::ClearDclItemDrawerFlags(TInt aFlags)
	{
	iFlags&=~aFlags;
	if (iFlags & (EShowSize|EShowDate))
		CalcColumnWidths();
	}
	
EXPORT_C void CDirContentsListItemDrawer::SetMarkColumnWidth(TInt aWidthInPixels)
	{
	iMarkColumnWidth=aWidthInPixels;
	CalcColumnWidths();
	}

EXPORT_C void CDirContentsListItemDrawer::SetMarkGutter(TInt aGapInPixels)
	{
	iMarkGutter=aGapInPixels;
	CalcColumnWidths();
	}

EXPORT_C void CDirContentsListItemDrawer::CalcColumnWidths()
	{
	// assumes that horiz scrolling will be possible if min width is larger than viewrect width
	if (!iModel || iModel->NumberOfItems()==0)
		return;
	TInt widths=(iDrawMark? iMarkColumnWidth+iMarkGutter : 0);
	TColumnWidths colWidths;
	CFbsBitmap* icon=ItemBitmap(0); // assumes all icons are same width and all entries have icons
	colWidths.iBitmap=icon->SizeInPixels().iWidth;
	widths+=colWidths.iBitmap+KBitmapNameGap;
	const CFont* detailsFont=iColumnData->ColumnFont(KSizeColumnIndex); // same as date font
	const TInt widthOfZero=detailsFont->WidthZeroInPixels(); // asumes no number is wider than 0
	if (iFlags & EShowSize)
		{
		colWidths.iSize = widthOfZero*KMaxNumOfCharsInSize;
		widths += colWidths.iSize + KTextTextGap;
		}
	if (iFlags & EShowDate)
		{
		colWidths.iDate = detailsFont->TextWidthInPixels(iSeparators.Left(1));
		colWidths.iDate += detailsFont->TextWidthInPixels(iSeparators.Right(1));
		colWidths.iDate += widthOfZero * KNumOfFiguresInDate;
		widths += colWidths.iDate + KTextTextGap;
		}
	const TInt minNameWidth = iColumnData->ColumnFont(KNameColumnIndex)->MaxNormalCharWidthInPixels() * KMinNumOfCharsInName;
	colWidths.iName = Max(iViewRect.Size().iWidth-widths,minNameWidth);
	SetColumnWidths(colWidths);
	}

EXPORT_C void CDirContentsListItemDrawer::SetColumnWidths(TColumnWidths& aWidths)
	{
	iColumnData->SetColumnWidthPixelL(KBitmapColumnIndex,aWidths.iBitmap); // won't leave
	iColumnData->SetColumnWidthPixelL(KNameColumnIndex,aWidths.iName); // won't leave
	iColumnData->SetColumnWidthPixelL(KSizeColumnIndex,aWidths.iSize); // won't leave
	iColumnData->SetColumnWidthPixelL(KDateColumnIndex,aWidths.iDate); // won't leave
	}

EXPORT_C CDirContentsListItemDrawer::TColumnWidths CDirContentsListItemDrawer::ColumnWidths() const
	{
	TColumnWidths widths;
	widths.iBitmap=iColumnData->ColumnWidthPixel(KBitmapColumnIndex);
	widths.iName=iColumnData->ColumnWidthPixel(KNameColumnIndex);
	widths.iSize=iColumnData->ColumnWidthPixel(KSizeColumnIndex);
	widths.iDate=iColumnData->ColumnWidthPixel(KDateColumnIndex);
	return widths;
	}

EXPORT_C void CDirContentsListItemDrawer::DrawActualItem(TInt aItemIndex,const TRect& aActualItemRect,
														 TBool aItemIsCurrent,TBool aViewIsEmphasized,
														 TBool /*aViewIsDimmed*/) const
	{
	iGc->SetPenColor(CEikonEnv::Static()->Color(EEikColorControlText));
	iGc->SetBrushColor(iBackColor);
	TBuf<300> itemText;
	GetItemText(itemText,aItemIndex);
	iColumnData->Draw(*iGc,&itemText,aActualItemRect,(aItemIsCurrent && aViewIsEmphasized));
	if (aItemIsCurrent && !aViewIsEmphasized)
		{
		iGc->SetBrushStyle(CGraphicsContext::ENullBrush);
		iGc->SetPenStyle(CGraphicsContext::ESolidPen);
		iGc->SetPenColor(CEikonEnv::Static()->Color(EEikColorControlText)); 
		TRect rect = aActualItemRect;
		rect.iTl.iX += iColumnData->ColumnWidthPixel(KBitmapColumnIndex) - 1;
		iGc->DrawRect(rect);
		}
	}

void CDirContentsListItemDrawer::GetItemText(TDes& aText,TInt aItemIndex) const
	{
	aText.Zero();
	// bitmap column
	TInt bmpIndex=-1;
	if (DclModel()->ItemIsParent(aItemIndex))
		bmpIndex=KParentBitmapIndex;
	else
		bmpIndex=(DclModel()->ItemIsSubDir(aItemIndex)? KFolderBitmapIndex : KFileBitmapIndex);
	TBuf<1> index;
	index.Num(bmpIndex);
	aText.Append(index);
	aText.Append(TChar(KColumnListSeparator));
	if (DclModel()->ItemIsParent(aItemIndex))
		return;
	// name column
	TFileName name=DclModel()->ItemName(aItemIndex);
	const CFont* font=iColumnData->ColumnFont(KNameColumnIndex);
	const TInt maxNameWidth=iColumnData->ColumnWidthPixel(KNameColumnIndex);
	if (!name.Length())
		aText.Append(TChar(KColumnListSeparator));
	else if (font->TextWidthInPixels(name)>maxNameWidth)
		TextUtils::ClipToFit(name,*font,maxNameWidth);
	aText.Append(name);
	aText.Append(TChar(KColumnListSeparator));
	if (DclModel()->ItemIsSubDir(aItemIndex))
		return;
	CDirContentsListBoxModel::TFileInfo info=DclModel()->ItemInfo(aItemIndex);
	if (iFlags&EShowSize)
		{
		// gap
		aText.Append(TChar(KColumnListSeparator));
		// size column
		TBuf<12> size;
		size.Num(info.iSize);
		aText.Append(size);
		aText.Append(TChar(KColumnListSeparator));
		}
	if (iFlags&EShowDate)
		{
		// gap
		aText.Append(TChar(KColumnListSeparator));
		// date column
		const TTime time=info.iModified;
		TBuf<16> fullDate;
		TBuf<16> buffer;
		buffer.Format(_L("%%D%%M%%*Y%%1%c%%2%c%%3"),(TInt)(iSeparators[0]),(TInt)(iSeparators[1]));
		time.FormatL(fullDate,buffer);
		aText.Append(fullDate);
		aText.Append(TChar(KColumnListSeparator));
		}
	}

CFbsBitmap* CDirContentsListItemDrawer::ItemBitmap(TInt aItemIndex) const
	{
	CArrayPtr<CFbsBitmap>* bitmaps=iColumnData->BitmapArray();
	if (!bitmaps || aItemIndex<=-1 || aItemIndex>=DclModel()->NumberOfItems())
		return NULL;
	if (DclModel()->ItemIsParent(aItemIndex))
		return (*bitmaps)[KParentBitmapIndex];
	const TInt bitmapIndex=(DclModel()->ItemIsSubDir(aItemIndex)? KFolderBitmapIndex : KFileBitmapIndex);
	return (*bitmaps)[bitmapIndex];
	}
