// EIKHLBV.CPP
//
// Copyright (c) 1997-1999 Symbian Ltd.  All rights reserved.
//

#include <w32std.h>
#include <eikhlbv.h>
#include <eikhlbm.h>
#include <eikhlbi.h>
#include <eiklbx.pan>
#include <eikdutil.h>
#include <eikenv.h>
#include <eikcolor.h>

//
// class CHierarchicalListBoxView
//

const KIndentPerLevel=12;

EXPORT_C CHierarchicalListBoxView::CHierarchicalListBoxView()
	{}

void CHierarchicalListBoxView::ClearPreceedingItemRect(TInt aItemIndex) const
	{
	const TInt indentLevel=HlModel()->Item(aItemIndex)->Level();
	TPoint startPoint=ItemPos(aItemIndex);
	startPoint.iX-=indentLevel*KIndentPerLevel;
	const TRect blankRect(startPoint,TPoint(startPoint.iX+indentLevel*KIndentPerLevel,startPoint.iY+iItemHeight));
	iItemDrawer->ClearRect(blankRect);
	}

void CHierarchicalListBoxView::DrawItemLinks(TInt aItemIndex) const
	{
	CHierListItem* itemToBeDrawn=HlModel()->Item(aItemIndex);
	const TInt itemLevel=itemToBeDrawn->Level();
	if (!itemLevel)
		return;
	TPoint startPoint=ItemPos(aItemIndex);
	startPoint.iX-=KIndentPerLevel/2;
	iGc->SetPenStyle(CGraphicsContext::ESolidPen);
	iGc->SetPenColor(CEikonEnv::Static()->Color(EEikColorControlText));
	if (itemLevel)
		{
		const TPoint horizLineStart=startPoint+TPoint(0,iItemHeight/2);
		iGc->MoveTo(horizLineStart);
		iGc->DrawLineTo(TPoint(horizLineStart.iX+KIndentPerLevel/2,horizLineStart.iY));
		}
	TInt lineIndentLevel=itemLevel;
	TInt count=-1;
	while (lineIndentLevel--)
		{
		count++;
		if (lineIndentLevel+1<itemLevel)
			{
			CHierListItem* parent=itemToBeDrawn->Parent();
			if (count>1)
				{
				TInt parentsToFind=count-1;
				while (parentsToFind--)
					parent=parent->Parent();
				}
			if (!(parent->HasFurtherSibling()))
				{
				startPoint.iX-=KIndentPerLevel;
				continue;
				}
			}
		TInt vertLineLength=iItemHeight;
		if (lineIndentLevel+1==itemLevel)
			{
			if (!itemToBeDrawn->HasFurtherSibling())
				vertLineLength/=2;
			}
		iGc->MoveTo(startPoint);
		iGc->DrawLineTo(TPoint(startPoint.iX,startPoint.iY+vertLineLength));
		startPoint.iX-=KIndentPerLevel;
		}
	}

EXPORT_C void CHierarchicalListBoxView::DrawItem(TInt aItemIndex) const
	{
	if (RedrawDisabled())
		return;
	const TInt count=iModel->NumberOfItems();
	if (aItemIndex>=0 && aItemIndex<count && ItemIsVisible(aItemIndex))
		{
		iGc->SetClippingRect(iViewRect);
		const TSize itemSize=ItemSize(aItemIndex);
		iItemDrawer->SetItemCellSize(itemSize);
		ClearPreceedingItemRect(aItemIndex);
		const TPoint pos=ItemPos(aItemIndex);
		TPoint markPos(iViewRect.iTl.iX,pos.iY);
		iItemDrawer->DrawItemMark(ItemIsSelected(aItemIndex),iFlags&EDimmed,markPos);
		DrawItemLinks(aItemIndex);
		STATIC_CAST(CHierarchicalListItemDrawer*,iItemDrawer)->DrawActualItem(aItemIndex,TRect(pos,itemSize),
										aItemIndex==iCurrentItemIndex,iFlags&EEmphasized,iFlags&EDimmed);
		iGc->CancelClippingRect();
		}
	}

EXPORT_C void CHierarchicalListBoxView::DrawFromItem(TInt aIndexOfFirstItemToDraw)
	{
	iGc->SetClippingRect(iViewRect);
	const TInt lastPotentialItemIndex = iTopItemIndex + NumberOfItemsThatFitInRect(iViewRect) - 1;
	TInt ii=0;
	for (ii=aIndexOfFirstItemToDraw;ii<=lastPotentialItemIndex;ii++)
		{
		if (ItemIsVisible(ii))
			{
			if (ii==aIndexOfFirstItemToDraw)
				DrawItemWithoutLinks(ii);
			else
				DrawItem(ii);
			}
		else
			break;
		}
	TRect usedPortionOfViewRect(iViewRect.iTl, TSize(iViewRect.Width(), (ii - iTopItemIndex) * iItemHeight));
	iGc->SetBrushColor(BackColor());
	EikDrawUtils::ClearBetweenRects(*iGc,iViewRect,usedPortionOfViewRect);
	iGc->CancelClippingRect();
	}

EXPORT_C void CHierarchicalListBoxView::DrawItemWithoutLinks(TInt aItemIndex) const
	{
	const TPoint itemPos=ItemPos(aItemIndex);
	iGc->SetClippingRect(TRect(itemPos,TPoint(iViewRect.iBr.iX,itemPos.iY+iItemHeight)));
	DrawItem(aItemIndex);
	iGc->CancelClippingRect();
	}

EXPORT_C void CHierarchicalListBoxView::VerticalMoveToItemL(TInt aTargetItemIndex, TSelectionMode aSelectionMode)
	{
	if (!ItemIsVisible(aTargetItemIndex))
		CListBoxView::VerticalMoveToItemL(aTargetItemIndex,aSelectionMode);
	else
		{
		const TInt oldCurrentItemIndex = iCurrentItemIndex;
		iCurrentItemIndex = aTargetItemIndex;
		DrawItemWithoutLinks(oldCurrentItemIndex);
		DrawItemWithoutLinks(iCurrentItemIndex);
		}
	}

EXPORT_C TSize CHierarchicalListBoxView::ItemSize(TInt aItemIndex) const
	{
	if (! HlModel()->Item(aItemIndex))
		return TSize(0, 0);
	const TInt indent=HlModel()->Item(aItemIndex)->Level()*KIndentPerLevel;
	return TSize(Max(iViewRect.Width()-indent, DataWidth()), iItemHeight);
	}

EXPORT_C TPoint CHierarchicalListBoxView::ItemPos(TInt aItemIndex) const
	{
	// assumes aItemIndex is currently visible
	TInt indentLevel=0;
	if (aItemIndex>-1 && aItemIndex<HlModel()->NumberOfItems())
		indentLevel=HlModel()->Item(aItemIndex)->Level();
	TPoint pos(-iHScrollOffset + iViewRect.iTl.iX + indentLevel*KIndentPerLevel,
					iViewRect.iTl.iY + (aItemIndex-iTopItemIndex)*iItemHeight);
	return pos;
	}

EXPORT_C void CHierarchicalListBoxView::CalcDataWidth()
	{
	TInt ii=-1;
	TInt largestDataWidth=0;
	while (++ii<HlModel()->NumberOfItems())
		{
		TInt dataWidth=iItemDrawer->ItemWidthInPixels(ii);
		dataWidth+=HlModel()->Item(ii)->Level()*KIndentPerLevel;
		largestDataWidth=Max(largestDataWidth, dataWidth); 
		}
	iDataWidth=largestDataWidth;
	}

CHierarchicalListBoxModel* CHierarchicalListBoxView::HlModel() const
	{
	return (CHierarchicalListBoxModel*)iModel;
	}

EXPORT_C void CHierarchicalListBoxView::SetCurrentItemIndexOnly(TInt aIndex)
	{
	iCurrentItemIndex=aIndex;
	}
