Customized listbox

Question

i saw you had a customized listbox. I have been working on it during the whole weekend without positive result. I cannot control my listbox in anyway. Could you guide me just a bit on how to do it?. I am working for the 3rd edition, with a background, and 3 views with 3 containers, my customized listboxes.

Answer

I don't know if there's been changes with third edition, so caveat emptor.

>
> Main problem i have, is that i can't resize the components.

The attached files show an example. The main ideas are (that I've been using):

derive from CEikFormattedCellListBox
override ConstructL as necessary
override CreateItemDrawerL (I'm calling another function CreateAndReturnItemDrawerL here)

in CreateAndReturnItemDrawerL you create a CFormattedCellListBoxData with all the cells in your item. You can have as many cells as you like, each with a position, size, margins, font and alignment. The cells can be either text or graphic. You then give this cell list data to CFormattedCellListBoxItemDrawer and set that as the listbox's iItemDrawer. This is all in CAutoTagListBoxList.

In this code I'm even customizing the CFormattedCellListBoxItemDrawer because I don't want the selection to be drawn when the list is not focused. This is in CAutoTagDrawer.

(the CAutoTagListBoxImpl just basically draws borders around the list, could be done better)

There's another example in http://db.cs.helsinki.fi/~mraento/lxr/source/ContextUI/src/doublelinebox.cpp
That one shows also how to change text colors depending on the current item.

>
> Thanks in advance

    Mika



#ifndef CONTEXT_CM_AUTOTAGLIST_H_INCLUDED
#define CONTEXT_CM_AUTOTAGLIST_H_INCLUDED 1

#include <e32base.h>
#include <bamdesca.h>
#include <eikfrlbd.h> 

class MAskForNames {
public:
	virtual TBool NameCell(TInt aBaseId, const class TBBCellId& aCellId, TDes& aNameInto) = 0;
	virtual TBool NameCity(const class TBBCellId& aCellId, TDes& aNameInto) = 0;
	virtual TBool GetExistingCell(TInt aBaseId, const class TBBCellId& aCellId, TDes& aNameInto) = 0;
	virtual TBool GetExistingCity(const class TBBCellId& aCellId, TDes& aNameInto) = 0;
};

class CAutoTagArray : public CBase, public MDesCArray {
public:
	IMPORT_C static CAutoTagArray*	NewL(MAskForNames* aAskForNames=0);

	virtual TInt GetIncludedTagsBitField() const = 0;

	virtual void ToggleField(TInt aIndex) = 0;
	virtual void ClearField(TInt aIndex) = 0;

	virtual TInt GetSharing() const = 0;
	virtual void SetPost(class CCMPost* aPost) = 0;
};

class CAutoTagListBox : public CCoeControl {
public:
	IMPORT_C static CAutoTagListBox* NewL(CAutoTagArray* aArray, 
		const CCoeControl* aParent, class CAknIconArray *aIconList);

	virtual TInt RowHeight() = 0;
	virtual TInt Width() = 0;
	virtual TInt BorderWidth() = 0;
	IMPORT_C static class CAknIconArray * CreateIconList();
	virtual void SetCurrentItemIndexAndDraw(TInt aItemIndex) const = 0;
	virtual void SetTopItemIndex(TInt aItemIndex) const = 0;
	virtual TInt CurrentItemIndex() const = 0;
	virtual TInt BottomItemIndex() const = 0;
	virtual TInt TopItemIndex() const = 0;
	virtual void SetCurrentItemIndex(TInt aItemIndex) const = 0;
};

#endif



#include "cm_autotaglist.h"
#include "cm_post.h"
#include "csd_presence.h"
#include "symbian_auto_ptr.h"
#include <eikenv.h>
#include "icons.h"
#include <contextmediauitags.mbg>
#include <akniconarray.h>
#include <contextmediaui.rsg>
#include <coemain.h>
#include <coeaui.h>
#include <eikappui.h>

static const int KNbIcons=5;

static const TIconID iconId[KNbIcons]=
{
	_INIT_T_ICON_ID("c:\\system\\data\\contextmediauitags.mbm", EMbmContextmediauitagsEmpty, EMbmContextmediauitagsEmpty),
	_INIT_T_ICON_ID("c:\\system\\data\\contextmediauitags.mbm", EMbmContextmediauitagsUnchecked, EMbmContextmediauitagsUnchecked),
	_INIT_T_ICON_ID("c:\\system\\data\\contextmediauitags.mbm", EMbmContextmediauitagsChecked, EMbmContextmediauitagsChecked),
	_INIT_T_ICON_ID("c:\\system\\data\\contextmediauitags.mbm", EMbmContextmediauitagsDisabled, EMbmContextmediauitagsDisabled),
	_INIT_T_ICON_ID("c:\\system\\data\\contextmediauitags.mbm", EMbmContextmediauitagsAsk, EMbmContextmediauitagsAsk)
};

enum TTagIcon {
	EEmptyIcon = 0,
	EUncheckedIcon = 1,
	ECheckedIcon = 2,
	EDisabledIcon = 3,
	EAskIcon = 4
};

void GpsTimeSinceStamp(TDes& aInto, TTime stamp, TTime compare)
{
	CALLSTACKITEM_N(_CL(""), _CL("GpsTimeSinceStamp"));

	TTime now=compare;
	TBuf<128> ret;

	TTimeIntervalYears years = now.YearsFrom(stamp);
	TTimeIntervalMonths months = now.MonthsFrom(stamp);
	TTimeIntervalDays days = now.DaysFrom(stamp);

	if (years.Int() > 0 )
	{
		ret.Append(_L(">2D"));
	}
	else if (months.Int() > 0 )
	{
		ret.Append(_L(">2D"));
	}
	else if (days.Int() >= 2)
	{
		ret.Append(_L(">2D"));
	}
	else if (days.Int() >= 1)
	{
		ret.Append(_L(">1D"));
	}
	else
	{
		TTimeIntervalHours hours;
		now.HoursFrom(stamp, hours);
		TTimeIntervalMinutes minutes;
		now.MinutesFrom(stamp, minutes);
		TTimeIntervalSeconds seconds;
		now.SecondsFrom(stamp, seconds);
				
		if (hours.Int() > 0 ) {
			ret.AppendNum(hours.Int());
			ret.Append(_L("h"));
		} else {				
			TInt min = minutes.Int() - hours.Int() * 60;
			TInt secs1 = seconds.Int() - hours.Int() * 60 *60 - min*60;
			if (secs1<0) secs1=0;

			if (min>0) {
				TUint secs=secs1;
				ret.AppendNum(min);
				ret.Append(_L("min"));
				if (min<3) {
					ret.Append(_L(" "));
					ret.AppendNumFixedWidth(secs, EDecimal, 2);
					ret.Append(_L("s"));
				}
			} else {
				ret.AppendNum(secs1);
				ret.Append(_L("s"));
			}
		}
	}

	aInto.Append(ret);
}


EXPORT_C class CAknIconArray * CAutoTagListBox::CreateIconList()
{
	auto_ptr<CAknIconArray> icons(new (ELeave) CAknIconArray(4));
	TInt scale=1;
	if ( ((CEikAppUi*)CEikonEnv::Static()->AppUi())->ApplicationRect().Width()>300) scale=2;
	LoadIcons(icons.get(), iconId, KNbIcons, scale);
	return icons.release();
}

class CAutoTagArrayImpl : public CAutoTagArray, public MContextBase {

	CCMPost* iPost;
	MAskForNames* iAskForNames;
	CEikonEnv*	iEikEnv;
	CAutoTagArrayImpl(MAskForNames* aAskForNames) : iAskForNames(aAskForNames) {
		iEikEnv=CEikonEnv::Static();
	}
	mutable TBuf<100> iBuf;
	TInt MdcaCount() const {
		return 8;
	}
	TInt iSharing;
	TGeoLatLong	iLatLong;
	virtual void SetPost(CCMPost* aPost) {
		CALLSTACKITEM_N(_CL("CAutoTagArrayImpl"), _CL("SetPost"));

		iPost=aPost;
		iLatLong.iLat.Zero();
		iLatLong.iLong.Zero();
		if (iPost) {
			CBBPresence *p=bb_cast<CBBPresence>(iPost->iPresence());
			if (p) {
				NmeaToLatLong(p->iGps(), iLatLong);
				if (iAskForNames &&
					(	p->iBaseInfo.iCurrent.iLeft()!=TTime(0) || 
						p->iBaseInfo.iCurrent.iBaseName().Length()==0
					) &&
					p->iCellName().Length()==0) {

					if (p->iBaseInfo.iCurrent.iLeft()==TTime(0)) {
						iAskForNames->GetExistingCell(p->iBaseInfo.iCurrent.iBaseId(),
							p->iCellId,
							p->iBaseInfo.iCurrent.iBaseName());
					} else {
						iAskForNames->GetExistingCell(0,
							p->iCellId,
							p->iBaseInfo.iCurrent.iBaseName());
					}
				}
					
			}
			iFlags=iPost->iIncludedTagsBitField();
			iSharing=aPost->iSharing();
		} else {
			iFlags=0x0;
			iSharing=0x0;
		}
	}


	void Ask(TInt aIndex) {
		CALLSTACKITEM_N(_CL("CAutoTagArrayImpl"), _CL("Ask"));

		if (!iAskForNames) return;
		CBBPresence *p=bb_cast<CBBPresence>(iPost->iPresence());
		if (!p) return;
		switch(aIndex) {
		case 1: {
			TBuf<50> name;
			if (iAskForNames->NameCity(p->iCellId, name))
				p->iCity()=name;
			}
			break;
		case 2: {
			TBuf<50> name;
			TInt baseid=-1;
			if (p->iBaseInfo.iCurrent.iLeft()==TTime(0)) {
				baseid=p->iBaseInfo.iCurrent.iBaseId();
			}
			if (iAskForNames->NameCell(baseid, p->iCellId, name)) {
				if (baseid>0) {
					p->iBaseInfo.iCurrent.iBaseName()=name;
				}
				p->iCellName()=name;
			}
			}
			break;
		}
	}
	TBool IsAskable(TInt aIndex) const {
		if (!iAskForNames) return EFalse;
		CBBPresence *p=bb_cast<CBBPresence>(iPost->iPresence());
		if (!p) return EFalse;
		switch(aIndex) {
		case 1:
			return ETrue;
		case 2:
			return ETrue;
		/*case 5:
			return ETrue;
		case 6:
			return ETrue;*/
		default:
			return EFalse;
		}
	}
	TBool IsKnown(TInt aIndex) const {
		if (!iPost || !iPost->iPresence()) {
			return EFalse;
		}
		CBBPresence *p=bb_cast<CBBPresence>(iPost->iPresence());
		switch(aIndex) {
		case 0:
			return (p->iCountry().Length()>0);
		case 1:
			return (p->iCity().Length()>0);
		case 2:
			return (
				 (p->iBaseInfo.iCurrent.iLeft()==TTime(0) &&
				  p->iBaseInfo.iCurrent.iBaseName().Length()>0) ||
				p->iCellName().Length()>0);
		case 3:
			return (p->iCellId.iCellId()!=0);
		case 4:
			return (p->iDevices->Count()>0);
		case 5:
			return (p->iCalendar.iCurrent.iDescription().Length()>0);
		case 6:
			return (iLatLong.iLat.Length()>0 && iLatLong.iLong.Length()>0);
		case 7:
			return ETrue;
		}
		return EFalse;
	}
	TInt iFlags;
	virtual TInt GetIncludedTagsBitField() const {
		return iFlags;
	}
	virtual void IncludeTags(TInt aBits) {
		iFlags |= aBits;
	}
	virtual TInt GetIndexBit(TInt aIndex) const {
		TInt flag=0x0;
		switch(aIndex) {
		case 0:
			flag=CCMPost::ECountry;
			break;
		case 1:
			flag=CCMPost::ECity;
			break;
		case 2:
			flag=CCMPost::EBase;
			break;
		case 3:
			flag=CCMPost::ECell;
			break;
		case 4:
			flag=CCMPost::EBt;
			break;
		case 5:
			flag=CCMPost::ECalendar;
			break;
		case 6:
			flag=CCMPost::EGps;
			break;
		}
		return flag;
	}
	virtual void ToggleField(TInt aIndex) {
		if (!iPost) return;
		if (aIndex==7) {
			ToggleSharing();
			return;
		}
		if (!iPost->iPresence()) return;

		if (IsKnown(aIndex)) {
			TInt set=iFlags & GetIndexBit(aIndex);
			if (set)
				iFlags ^= GetIndexBit(aIndex);
			else 
				iFlags |= GetIndexBit(aIndex);
		} else if (IsAskable(aIndex)) {
			Ask(aIndex);
		}
	}
	virtual void ClearField(TInt aIndex) {
		if (!iPost || !iPost->iPresence()) return;
		CBBPresence *p=bb_cast<CBBPresence>(iPost->iPresence());

		if (aIndex==1) {
			p->iCity().Zero();
		} else if (aIndex==2) {
			p->iBaseInfo.iCurrent.iBaseName().Zero();
			p->iCellName().Zero();
		}/* else if (aIndex==5) {
			p->iCalendar()=TBBCalendar();
		} else if (aIndex==6) {
			iLatLong.iLat.Zero();
			iLatLong.iLong.Zero();
		}*/
	}


	TBool IsEnabled(TInt aIndex) const {
		if (!iPost) {
			return EFalse;
		}
		if (aIndex==7) return ETrue;
		if (!iPost->iPresence()) return EFalse;

		TInt flag=GetIndexBit(aIndex);
		return (iFlags & flag);
	}
	virtual void ToggleSharing() {
		iSharing = (iSharing + 1) % 5;
	}
	virtual TInt GetSharing() const {
		return iSharing;
	}

	TPtrC MdcaPoint(TInt aIndex) const {
		iBuf.Zero();

		if (aIndex==7) {
			switch (iSharing) {
			case CCMPost::EPrivate:
				iEikEnv->ReadResourceAsDes16(iBuf, R_PRIVATE);
				break;
			case CCMPost::EFriends:
				iEikEnv->ReadResourceAsDes16(iBuf, R_FRIENDS);
				break;
			case CCMPost::EPublic:
				iEikEnv->ReadResourceAsDes16(iBuf, R_PUBLIC);
				break;
			case CCMPost::EFamily:
				iEikEnv->ReadResourceAsDes16(iBuf, R_FAMILY);
				break;
			case CCMPost::EFriendsAndFamily:
				iEikEnv->ReadResourceAsDes16(iBuf, R_FRIENDS_AND_FAMILY);
				break;
			}
			iBuf.Append(_L("\t"));
			iBuf.AppendNum(EEmptyIcon);
			return iBuf;
		}

		if (!iPost || !iPost->iPresence()) {
			if (aIndex==1) {
				iEikEnv->ReadResourceAsDes16(iBuf, R_NO_CONTEXT);
			}
			iBuf.Append(_L("\t"));
			iBuf.AppendNum(EEmptyIcon);
			return iBuf;
		}
		CBBPresence *p=bb_cast<CBBPresence>(iPost->iPresence());
		switch(aIndex) {
		case 0:
			iBuf.Append(p->iCountry());
			if (p->iCountry().Length()==0) 
				iEikEnv->ReadResourceAsDes16(iBuf, R_NO_COUNTRY);
			break;
		case 1:
			iBuf.Append(p->iCity());
			if (p->iCity().Length()==0) 
				iEikEnv->ReadResourceAsDes16(iBuf, R_NO_CITY);
			break;
		case 2:
			if (p->iBaseInfo.iCurrent.iLeft()==TTime(0))
				iBuf=(p->iBaseInfo.iCurrent.iBaseName());
			if (iBuf.Length()==0) iBuf=p->iCellName();
			if (iBuf.Length()==0) 
				iEikEnv->ReadResourceAsDes16(iBuf, R_NO_LOCATION);
			break;
		case 3:
			if (p->iCellId.iCellId()!=0) {
				iBuf.Append(_L("GSM "));
				iBuf.AppendNum(p->iCellId.iMCC());
				iBuf.Append(_L(":"));
				iBuf.AppendNum(p->iCellId.iMNC());
				iBuf.Append(_L(":"));
				iBuf.AppendNum(p->iCellId.iLocationAreaCode());
				iBuf.Append(_L(":"));
				iBuf.AppendNum(p->iCellId.iCellId());
			} else {
				iEikEnv->ReadResourceAsDes16(iBuf, R_NO_GSM);
			}
			break;
		case 4:
			if (p->iDevices->Count()>0) {
				TBuf<40> btcount;
				iEikEnv->ReadResourceAsDes16(btcount, R_BT_DEVICES);
				iBuf.AppendNum(p->iDevices->Count());
				iBuf.Append(btcount);
			} else {
				iEikEnv->ReadResourceAsDes16(iBuf, R_NO_BT);
			}
			break;
		case 5:
			iBuf.Append(p->iCalendar.iCurrent.iDescription());
			if (p->iCalendar.iCurrent.iDescription().Length()==0) 
				iEikEnv->ReadResourceAsDes16(iBuf, R_NO_CALENDAR);
			break;
		case 6:
			if (iLatLong.iLat.Length()==0 || iLatLong.iLong.Length()==0) {
				iEikEnv->ReadResourceAsDes16(iBuf, R_NO_GPS);
			} else {
				if (p->iGpsStamp() != TTime(0)) {
					iBuf=_L("GPS [");
					GpsTimeSinceStamp(iBuf, p->iGpsStamp(), iPost->iTimeStamp());
					TBuf<10> ago; iEikEnv->ReadResourceAsDes16(ago, R_AGO);
					iBuf.Append(_L(" "));
					iBuf.Append(ago);
					iBuf.Append(_L("] "));
				}

				iBuf.Append(iLatLong.iLat); iBuf.Append(_L(", ")); iBuf.Append(iLatLong.iLong);
			}
			break;
		}
		iBuf.Append(_L("\t"));
		if (IsKnown(aIndex)) {
			if (IsEnabled(aIndex)) iBuf.AppendNum(ECheckedIcon);
			else iBuf.AppendNum(EUncheckedIcon);
		} else {
			if (IsAskable(aIndex)) iBuf.AppendNum(EAskIcon);
			else iBuf.AppendNum(EDisabledIcon);
		}
		return iBuf;
	}
	friend CAutoTagArray;
};

EXPORT_C CAutoTagArray*	CAutoTagArray::NewL(MAskForNames* aAskForNames)
{
	return new (ELeave) CAutoTagArrayImpl(aAskForNames);
}

class CAutoTagDrawer : public CFormattedCellListBoxItemDrawer {
public:
	CEikFormattedCellListBox* iParent;
	CAutoTagDrawer(MTextListBoxModel *aModel, 
					const CFont *aFont, 
					CFormattedCellListBoxData *aFormattedCellData, 
					CEikFormattedCellListBox* aParent) :
	CFormattedCellListBoxItemDrawer(aModel, aFont, aFormattedCellData), iParent(aParent) { }

private:
	void DrawItemText(TInt aItemIndex, const TRect &aItemTextRect,
                                TBool aItemIsCurrent, TBool aViewIsEmphasized, 
				TBool aItemIsSelected) const;
};

void CAutoTagDrawer::DrawItemText(TInt aItemIndex, const TRect &aItemTextRect,
                                TBool aItemIsCurrent, TBool aViewIsEmphasized, 
				TBool aItemIsSelected) const
{
	if (iParent->IsFocused()) {
		CFormattedCellListBoxItemDrawer::DrawItemText(aItemIndex, 
			aItemTextRect, aItemIsCurrent, aViewIsEmphasized,
			aItemIsSelected);
	} else {
		CFormattedCellListBoxItemDrawer::DrawItemText(aItemIndex, 
			aItemTextRect, EFalse, aViewIsEmphasized,
			aItemIsSelected);
	}
}
	
class CAutoTagListBoxList : public CEikFormattedCellListBox {
	friend class CAutoTagListBoxImpl;

	CAutoTagArray* iArray;

	CAknIconArray* iIconList; // marker that we have set the list
	CAutoTagListBoxList(CAutoTagArray* aArray) : iArray(aArray) { }

	void ConstructL(CCoeControl *aParent, CAknIconArray* aIconlist) {
		if ( ((CEikAppUi*)iEikonEnv->AppUi())->ApplicationRect().Width()>300) iScale=2;
		else iScale=1;
		CEikFormattedCellListBox::ConstructL(aParent, 0);
		View()->SetMatcherCursor(EFalse);
		Model()->SetItemTextArray(iArray);
		Model()->SetOwnershipType(ELbmDoesNotOwnItemArray);
		SetItemHeightL(RowHeight());
		ItemDrawer()->FormattedCellData()->SetIconArray(aIconlist);
		iIconList=aIconlist;
	}
	~CAutoTagListBoxList() {
		if (iIconList) ItemDrawer()->FormattedCellData()->SetIconArray(0);
	}

	TInt iCells;
	TInt iScale;
	void AddSubCell(CFormattedCellListBoxData* itemd,
				       TMargins marg, TSize size, TPoint pos, TInt baselinepos, 
				       CGraphicsContext::TTextAlign aAlign, TBool aGraphic)
	{
		itemd->SetSubCellMarginsL(iCells, marg);		
		itemd->SetSubCellSizeL(iCells,  size);
		itemd->SetSubCellPositionL(iCells,  pos);
		itemd->SetSubCellBaselinePosL(iCells, baselinepos);
		itemd->SetSubCellFontL(iCells, iEikonEnv->DenseFont() );
		itemd->SetSubCellAlignmentL(iCells, aAlign);
		if (aGraphic)
			itemd->SetGraphicsSubCellL(iCells, ETrue);

		++iCells;
	}

	virtual TInt RowHeight() { return iScale*15; }
	virtual TInt Width() { return iScale*118; }

	CFormattedCellListBoxItemDrawer* CreateAndReturnItemDrawerL(void)
	{
		CFormattedCellListBoxData* itemd=CFormattedCellListBoxData::NewL();
#ifdef __S60V2__
		itemd->SetSkinEnabledL(EFalse);
#endif
		CleanupStack::PushL(itemd);

		TMargins marg;
		marg.iBottom=marg.iTop=marg.iLeft=marg.iRight=0;

		marg.iTop=0; marg.iLeft=2*iScale;
		AddSubCell(itemd, marg, TSize(Width()-12*iScale, RowHeight()), TPoint(12*iScale, 0), RowHeight()-2*iScale, 
			CGraphicsContext::ELeft, EFalse);

		marg.iTop=1*iScale; marg.iLeft=2*iScale;
		AddSubCell(itemd, marg, TSize(12*iScale, RowHeight()), TPoint(0, 0), RowHeight()-2*iScale, 
			CGraphicsContext::ELeft, ETrue);

		CFormattedCellListBoxItemDrawer* d=new (ELeave) CAutoTagDrawer(Model(), iEikonEnv->DenseFont(), 
			itemd, this);

		CleanupStack::Pop();
		return d;
	}
	void CreateItemDrawerL(void) {
		iItemDrawer=CreateAndReturnItemDrawerL();
	}

};

class CAutoTagListBoxImpl : public CAutoTagListBox, public MEikListBoxObserver, public MContextBase  {

	
	CAutoTagListBoxImpl() { }

	CAutoTagArray* iArray;
	CAutoTagListBoxList* iListBox;
	TInt iScale;

	CAknIconArray* iIconList; // marker that we have set the list
	void ConstructL(CAutoTagArray* aArray, const CCoeControl* aParent, 
		CAknIconArray *aIconlist) {

		CALLSTACKITEM_N(_CL("CAutoTagListBoxImpl"), _CL("ConstructL"));
		iScale=1;
		if ( ((CEikAppUi*)iEikonEnv->AppUi())->ApplicationRect().Width()>300) iScale=2;

		SetContainerWindowL(*aParent);
		iArray=aArray;
		iListBox=new (ELeave) CAutoTagListBoxList(aArray);
		iListBox->ConstructL(this, aIconlist);

		//SetBorder(TGulBorder::ESingleBlack);
		iListBox->SetListBoxObserver(this);
		iListBox->ActivateL();
	}
	~CAutoTagListBoxImpl() {
		delete iListBox;
	}

	TInt CountComponentControls() const { return 1; }
	CCoeControl* ComponentControl(TInt aIndex) const { return iListBox; }
	void Draw(const TRect& aRect) const {
		CWindowGc& gc = SystemGc();
		gc.SetPenStyle(CGraphicsContext::ESolidPen);
		if (iScale>1) {
			gc.SetPenSize(TSize(iScale, iScale));
		}
		gc.SetBrushColor(KRgbBlack);
		gc.SetBrushStyle(CGraphicsContext::ENullBrush);
		gc.DrawRect(aRect);
		if (iScale>1) {
			gc.SetPenSize(TSize(1, 1));
		}
	}
	void SizeChanged() {
		TRect r=Rect();
		r.Move(1*iScale, 1*iScale);
		r.Resize(-2*iScale, -2*iScale);
		iListBox->SetRect(r);
	}
	virtual void FocusChanged(TDrawNow aDrawNow) {
		iListBox->SetFocus(IsFocused(), aDrawNow);
	}
	TKeyResponse OfferKeyEventL(const TKeyEvent &aKeyEvent, TEventCode aType)
	{
		if (aKeyEvent.iCode==EKeyDelete || aKeyEvent.iCode==EKeyBackspace) {
			TInt idx=iListBox->CurrentItemIndex();
			iArray->ClearField(idx);
			DrawNow();
			return EKeyWasConsumed;
		}
		return iListBox->OfferKeyEventL(aKeyEvent, aType);
	}


	virtual TInt RowHeight() { return iListBox->RowHeight(); }
	virtual TInt Width() { return iListBox->Width() + BorderWidth()*2; }
	virtual TInt BorderWidth() { return 1*iScale; }

	virtual void SetCurrentItemIndexAndDraw(TInt aItemIndex) const {
		iListBox->SetCurrentItemIndexAndDraw(aItemIndex);
	}
	virtual void SetTopItemIndex(TInt aItemIndex) const {
		iListBox->SetTopItemIndex(aItemIndex);
	}
	virtual TInt CurrentItemIndex() const {
		return iListBox->CurrentItemIndex();
	}
	virtual TInt BottomItemIndex() const {
		return iListBox->BottomItemIndex();
	}
	virtual TInt TopItemIndex() const {
		return iListBox->TopItemIndex();
	}
	virtual void SetCurrentItemIndex(TInt aItemIndex) const {
		iListBox->SetCurrentItemIndex(aItemIndex);
	}

	void HandleListBoxEventL(CEikListBox* aListBox, TListBoxEvent aEventType) {
		if (aEventType==EEventEnterKeyPressed) {
			TInt idx=iListBox->CurrentItemIndex();
			iArray->ToggleField(idx);
			DrawNow();
		}
	}

	friend CAutoTagListBox;
	friend auto_ptr<CAutoTagListBoxImpl>;
};

EXPORT_C CAutoTagListBox* CAutoTagListBox::NewL(CAutoTagArray* aArray, const CCoeControl* aParent, 
						CAknIconArray *aIconList)
{
	auto_ptr<CAutoTagListBoxImpl> ret(new (ELeave) CAutoTagListBoxImpl);
	ret->ConstructL(aArray, aParent, aIconList);
	return ret.release();
}