// EIKHLBM.CPP
//
// Copyright (c) 1997-1999 Symbian Ltd.  All rights reserved.
//

#include <eikhlbm.h>
#include <eiklbx.pan>

//
// class CHierListItem
//

EXPORT_C CHierListItem::CHierListItem(TInt16 aFlags)
	: iFlags(aFlags)
	{}

EXPORT_C CHierListItem::~CHierListItem()
	{
	delete iText;
	}

EXPORT_C void CHierListItem::SetTextL(const TDesC& aText)
	{
	HBufC* text=aText.AllocL();
	delete iText;
	iText=text;
	}

//
// class CHierarchicalListBoxModel
//

EXPORT_C CHierarchicalListBoxModel::CHierarchicalListBoxModel()
	{}

EXPORT_C CHierarchicalListBoxModel::~CHierarchicalListBoxModel()
	{
	if (iHierListArray)
		{
		const TInt count=iHierListArray->Count();
		for (TInt ii=0;ii<count;ii++)
			delete (*iHierListArray)[ii];
		delete iHierListArray;
		}
	}

EXPORT_C void CHierarchicalListBoxModel::ConstructL()
	{
	iHierListArray=new(ELeave) CArrayFixSeg<CHierListItem*>(5);
	}

EXPORT_C void CHierarchicalListBoxModel::CollapseItem(TInt aItemToBeCollapsed)
	{
	const TInt index=aItemToBeCollapsed;
	CHierListItem* currentItem=Item(index);
	currentItem->SetCollapsed();
	if (index==NumberOfItems()-1)
		return;
	const TInt level=currentItem->Level();
	FOREVER
		{
		const TInt nextItemLevel=Item(index+1)->Level();
		if (nextItemLevel<=level)
			break;
		delete (*iHierListArray)[index+1];
		iHierListArray->Delete(index+1);
		if (index==NumberOfItems()-1)
			break;
		}
	}

EXPORT_C void CHierarchicalListBoxModel::ExpandAllItemsL()
	{
	TInt itemIndex=0;
	while (itemIndex<NumberOfItems())
		ExpandItemL(itemIndex++);
	}

EXPORT_C void CHierarchicalListBoxModel::CollapseAllItems()
	{
	TInt itemIndex=0;
	while (itemIndex<NumberOfItems())
		CollapseItem(itemIndex++);
	}

EXPORT_C TInt CHierarchicalListBoxModel::NumberOfItems() const
	{
	return (iHierListArray->Count());
	}

EXPORT_C CHierListItem* CHierarchicalListBoxModel::Item(TInt aItemIndex) const
	{
	__ASSERT_DEBUG(iHierListArray, Panic(EEikPanicListBoxNoHierArray));
	const TInt count=iHierListArray->Count();
	if (aItemIndex<0 || aItemIndex>=count)
		return NULL;
	else
		{
		if (aItemIndex<0 || aItemIndex>=iHierListArray->Count())
			Panic(EEikPanicListBoxInvalidItemIndexSpecified);
		return ((*iHierListArray)[aItemIndex]);
		}
	}

EXPORT_C TPtrC CHierarchicalListBoxModel::ItemText(TInt aItemIndex) const
	{
	return *(*iHierListArray)[aItemIndex]->Text();
	}

EXPORT_C const MDesCArray* CHierarchicalListBoxModel::MatchableTextArray() const
	{
	return (this);
	}

EXPORT_C TInt CHierarchicalListBoxModel::MdcaCount() const
	{
	return NumberOfItems();
	}

EXPORT_C TPtrC CHierarchicalListBoxModel::MdcaPoint(TInt aIndex) const
	{
	return ItemText(aIndex);
	}

EXPORT_C void CHierarchicalListBoxModel::AddItemL(CHierListItem* aListItem,TInt aParentIndex,TInt aIndexOfSiblingToInsertAfter)
	{
	aListItem->SetParent(Item(aParentIndex));
	TInt indexOfItemBeingAdded=-1;
	if (aParentIndex==-1)
		{
		aListItem->SetLevel(0);
		if (aIndexOfSiblingToInsertAfter==KEikHierListInsertAsFirstSibling)
			{
			indexOfItemBeingAdded=aParentIndex+1;
			iHierListArray->InsertL(indexOfItemBeingAdded,&aListItem,1);
			}
		else if (aIndexOfSiblingToInsertAfter==-1)
			{
			iHierListArray->AppendL(aListItem);
			indexOfItemBeingAdded=NumberOfItems()-1;
			}
		else
			{
			indexOfItemBeingAdded=aIndexOfSiblingToInsertAfter+1;
			iHierListArray->InsertL(indexOfItemBeingAdded,&aListItem,1);
			}
		}
	else
		{
		aListItem->SetLevel((TInt16)((*iHierListArray)[aParentIndex]->Level()+1));
		if (aIndexOfSiblingToInsertAfter==-1 || aIndexOfSiblingToInsertAfter==KEikHierListInsertAsFirstSibling)
			{
			indexOfItemBeingAdded=aParentIndex+1;
			iHierListArray->InsertL(indexOfItemBeingAdded,&aListItem,1);
			}
		else
			{
			indexOfItemBeingAdded=aIndexOfSiblingToInsertAfter+1;
			iHierListArray->InsertL(indexOfItemBeingAdded,&aListItem,1);
			}
		}
	const TInt previousSiblingIndex=PreviousSiblingIndex(indexOfItemBeingAdded);
	const TInt nextSiblingIndex=NextSiblingIndex(indexOfItemBeingAdded);
	if (previousSiblingIndex!=-1)
		Item(previousSiblingIndex)->SetHasFurtherSibling();
	if (nextSiblingIndex!=-1)
		Item(indexOfItemBeingAdded)->SetHasFurtherSibling();
	}

EXPORT_C void CHierarchicalListBoxModel::RemoveItem(TInt aItemIndex)
	{
	CollapseItem(aItemIndex);
	if (!Item(aItemIndex)->HasFurtherSibling())
		{
		const TInt previousSiblingIndex=PreviousSiblingIndex(aItemIndex);
		if (previousSiblingIndex!=-1)
			Item(previousSiblingIndex)->SetHasNoFurtherSibling();
		}
	delete (*iHierListArray)[aItemIndex];
	iHierListArray->Delete(aItemIndex);
	}

EXPORT_C void CHierarchicalListBoxModel::RemoveAllItems()
	{
	TInt count=0;
	while (count<NumberOfItems())
		RemoveItem(0);
	iHierListArray->Reset();
	}

EXPORT_C TInt CHierarchicalListBoxModel::FirstChildIndex(TInt aItemIndex) const
	{
	if (aItemIndex==NumberOfItems()-1)
		return -1;
	if ((*iHierListArray)[aItemIndex]->Level()==(*iHierListArray)[aItemIndex+1]->Level()-1)
		return aItemIndex+1;
	return -1;
	}

EXPORT_C TInt CHierarchicalListBoxModel::NextSiblingIndex(TInt aItemIndex) const
	{
	const TInt level=Item(aItemIndex)->Level();
	const TInt maxIndex=NumberOfItems();
	while (++aItemIndex < maxIndex)
		{
		const TInt itemLevel=Item(aItemIndex)->Level();
		if (itemLevel==level)
			return aItemIndex;
		else if (itemLevel<level)
			return -1;
		}
	return -1;
	}

EXPORT_C TInt CHierarchicalListBoxModel::PreviousSiblingIndex(TInt aItemIndex) const
	{
	const TInt level=Item(aItemIndex)->Level();
	while (--aItemIndex >= 0)
		{
		const TInt itemLevel=Item(aItemIndex)->Level();
		if (itemLevel==level)
			return aItemIndex;
		else if (itemLevel<level)
			return -1;
		}
	return -1;
	}

EXPORT_C TInt CHierarchicalListBoxModel::ParentIndex(TInt aItemIndex) const
	{
	const TInt level=Item(aItemIndex)->Level();
	if (!level)
		return -1;
	while (--aItemIndex >= 0)
		{
		const TInt itemLevel=Item(aItemIndex)->Level();
		if (itemLevel==level-1)
			return aItemIndex;
		}
	return -1;
	}

EXPORT_C void CHierarchicalListBoxModel::GetChildrenIndexesL(TInt aItemIndex,CArrayFix<TInt>* aChildren) const
	{
	const TInt level=Item(aItemIndex)->Level();
	aChildren->Reset();
	const TInt itemCount=NumberOfItems();
	while (++aItemIndex<itemCount)
		{
		const TInt nextItemLevel=Item(aItemIndex)->Level();
		if (nextItemLevel>level+1)
			continue;
		if (nextItemLevel<=level)
			break;
		aChildren->AppendL(aItemIndex);
		}
	}

EXPORT_C void CHierarchicalListBoxModel::Reset()
	{
	RemoveAllItems();
	iHierListArray->Reset();
	}
