// TMFNE.CPP
//
// Copyright (c) 1997-1999 Symbian Ltd.  All rights reserved.
//

#include <e32keys.h>
#include <barsread.h>
#include <basched.h>
#include <coecntrl.h>
#include <eikdef.h>
#include <eikenv.h>
#include <eikappui.h>
#include <eikdialg.h>
#include <eikdialg.hrh>
#include <eikcmds.hrh>
#include <eikmfne.h>
#include <eikmfne.hrh>
#include <eikapp.h>
#include <eikdoc.h>
#include <eiktbar.h>
#include <eikmenup.h>
#include <tmfne.rsg>
#include "tmfne.hrh"

enum TTMfnePanic
	{
	ETMfnePanicNoMfnesCurrently1,
	ETMfnePanicNoMfnesCurrently2,
	ETMfnePanicBadMfneType1,
	ETMfnePanicBadMfneType2,
	ETMfnePanicBadMfneType3,
	ETMfnePanicBadEditorType,
	ETMfnePanicFocusControlNotFound,
	ETMfnePanicBadFieldType
	};

LOCAL_C void Panic(TTMfnePanic aPanic)
	{
	User::Panic(_L("TMfne"), aPanic);
	}

//
// CTstGenericMfne
//

class CTstGenericMfne : public CEikMfne
	{
public:
	virtual void ConstructFromResourceL(TResourceReader& aResourceReader);
	};

void CTstGenericMfne::ConstructFromResourceL(TResourceReader& aResourceReader)
	{
	TInt numFields=aResourceReader.ReadUint8();
	CreateFieldArrayL(numFields);
	for (TInt i=0; i<numFields; ++i)
		{
		CEikMfneField* field=NULL; // dummy initialization to prevent compiler warning
		TUint type=aResourceReader.ReadUint8();
		switch (type)
			{
		case ETMfneFieldTypeSeparator:
			field=CEikMfneSeparator::NewL(aResourceReader);
			break;
		case ETMfneFieldTypeNumber:
			field=CEikMfneNumber::NewL(*iEikonEnv->NormalFont(), aResourceReader);
			break;
		case ETMfneFieldTypeSymbol:
			field=CEikMfneSymbol::NewL(aResourceReader);
			break;
		default:
			Panic(ETMfnePanicBadFieldType);
			break;
			}
		AddField(field);
		}
	}

//
// CTstDialog1
//

class CTstDialog1 : public CEikDialog
	{
public:
	CTstDialog1(TInt* aNumber, SEikRange* aRange, TTime* aTime, TTime* aDate, TTime* aTimeAndDate, TTimeIntervalSeconds* aDuration,
				TTimeIntervalSeconds* aTimeOffset, SEikDegreesMinutesDirection* aLatitude, SEikDegreesMinutesDirection* aLongitude);
private: // framework
	//IMPORT_C virtual void HandleControlStateChangeL(TInt aResourceId);
	IMPORT_C virtual void PrepareForFocusTransitionL();
	IMPORT_C virtual void PreLayoutDynInitL();
	IMPORT_C virtual TBool OkToExitL(TInt aKeycode);
private:
	TInt* iNumber;
	SEikRange* iRange;
	TTime* iTime;
	TTime* iDate;
	TTime* iTimeAndDate;
	TTimeIntervalSeconds* iDuration;
	TTimeIntervalSeconds* iTimeOffset;
	SEikDegreesMinutesDirection* iLatitude;
	SEikDegreesMinutesDirection* iLongitude;
	};

CTstDialog1::CTstDialog1(TInt* aNumber, SEikRange* aRange, TTime* aTime, TTime* aDate, TTime* aTimeAndDate, TTimeIntervalSeconds* aDuration,
				TTimeIntervalSeconds* aTimeOffset, SEikDegreesMinutesDirection* aLatitude, SEikDegreesMinutesDirection* aLongitude)
	:iNumber(aNumber),
	 iRange(aRange),
	 iTime(aTime),
	 iDate(aDate),
	 iTimeAndDate(aTimeAndDate),
	 iDuration(aDuration),
	 iTimeOffset(aTimeOffset),
	 iLatitude(aLatitude),
	 iLongitude(aLongitude)
	{
	}

EXPORT_C void CTstDialog1::PrepareForFocusTransitionL()
	{
	if (IdOfFocusControl()==ETMfneControlIdNumberEditor)
		SetLineDimmedNow(ETMfneControlIdLongitudeEditor,ETrue);
	if (IdOfFocusControl()==ETMfneControlIdRangeEditor)
		SetLineDimmedNow(ETMfneControlIdLatitudeEditor,ETrue);
	if (IdOfFocusControl()==ETMfneControlIdTimeEditor)
		{
		SetLineDimmedNow(ETMfneControlIdLongitudeEditor,EFalse);
		SetLineDimmedNow(ETMfneControlIdLatitudeEditor,EFalse);
		}
	}

EXPORT_C void CTstDialog1::PreLayoutDynInitL()
	{
	SetNumberEditorMinAndMax(ETMfneControlIdNumberEditor, *iNumber-7, *iNumber+7);
	SetNumberEditorValue(ETMfneControlIdNumberEditor, *iNumber);
	SetRangeEditorValue(ETMfneControlIdRangeEditor, *iRange);
	SetTTimeEditorValue(ETMfneControlIdTimeEditor, *iTime);
	SetTTimeEditorValue(ETMfneControlIdDateEditor, *iDate);
	SetTTimeEditorValue(ETMfneControlIdTimeAndDateEditor, *iTimeAndDate);
	SetDurationEditorValue(ETMfneControlIdDurationEditor, *iDuration);
	SetTimeOffsetEditorValue(ETMfneControlIdTimeOffsetEditor, *iTimeOffset);
	SetLatitudeEditorValue(ETMfneControlIdLatitudeEditor, *iLatitude);
	SetLongitudeEditorValue(ETMfneControlIdLongitudeEditor, *iLongitude);
	}

EXPORT_C TBool CTstDialog1::OkToExitL(TInt)
	{
	*iNumber=NumberEditorValue(ETMfneControlIdNumberEditor);
	*iRange=RangeEditorValue(ETMfneControlIdRangeEditor);
	*iTime=TTimeEditorValue(ETMfneControlIdTimeEditor);
	*iDate=TTimeEditorValue(ETMfneControlIdDateEditor);
	*iTimeAndDate=TTimeEditorValue(ETMfneControlIdTimeAndDateEditor);
	*iDuration=DurationEditorValue(ETMfneControlIdDurationEditor);
	*iTimeOffset=DurationEditorValue(ETMfneControlIdTimeOffsetEditor);
	*iLatitude=LatitudeEditorValue(ETMfneControlIdLatitudeEditor);
	*iLongitude=LongitudeEditorValue(ETMfneControlIdLongitudeEditor);
	return ETrue;
	}

//
// CTstDialog2 and CTstDialog3
//

class CTstDialog2 : public CEikDialog
	{
public:
	CTstDialog2();
private: // framework
	virtual void PostLayoutDynInitL();
	virtual TBool OkToExitL(TInt aButtonId);
	};

class CTstDialog3 : public CEikDialog
	{
public:
	CTstDialog3(CEikNumberEditor& aSample);
private: // framework
	virtual void PreLayoutDynInitL();
	virtual TBool OkToExitL(TInt aButtonId);
private:
	CEikNumberEditor& iSample;
	};

CTstDialog2::CTstDialog2()
	{
	__DECLARE_NAME(_S("CTstDialog2"));
	}

void CTstDialog2::PostLayoutDynInitL()
	{
	SetNumberEditorValue(ETMfneControlIdSample, 0);
	}

TBool CTstDialog2::OkToExitL(TInt aButtonId)
	{
	if (aButtonId==EEikBidSpace)
		{
		CEikDialog* dialog=new(ELeave) CTstDialog3(*(CEikNumberEditor*)Control(ETMfneControlIdSample));
		dialog->ExecuteLD(R_TMFNE_DIALOG_3);
		return EFalse;
		}
	return ETrue;
	}

CTstDialog3::CTstDialog3(CEikNumberEditor& aSample)
	:iSample(aSample)
	{
	}

void CTstDialog3::PreLayoutDynInitL()
	{
	SEikRange sampleRange;
	iSample.GetMinimumAndMaximum(sampleRange.iLowerLimit, sampleRange.iUpperLimit);
	SetRangeEditorValue(ETMfneControlIdMinimumAndMaximumOfSample, sampleRange);
	}

TBool CTstDialog3::OkToExitL(TInt)
	{
	SEikRange sampleRange=RangeEditorValue(ETMfneControlIdMinimumAndMaximumOfSample);
	iSample.SetMinimumAndMaximum(sampleRange.iLowerLimit, sampleRange.iUpperLimit);
	iSample.DrawNow();
	return ETrue;
	}

//
// CTstContainer
//

class CTstContainer : public CCoeControl, public MCoeControlObserver
	{
public:
	CTstContainer();
	void ConstructL(const TRect& aRect);
	~CTstContainer();
	void HandleCommandL(TInt aCommand);
private:
	enum {ESpacing=3};
	enum TMfneType
		{
		EMfneTypeGeneric,
		EMfneTypeNumber,
		EMfneTypeRange,
		EMfneTypeTime,
		EMfneTypeTimeWithoutSeconds,
		EMfneTypeDate,
		EMfneTypeTimeAndDate,
		EMfneTypeTimeAndDateWithoutSeconds,
		EMfneTypeDuration,
		EMfneTypeTimeOffset,
		EMfneTypeLatitude,
		EMfneTypeLongitude
		};
private:
	// framework
	void Draw(const TRect& aRect) const;
	TKeyResponse OfferKeyEventL(const TKeyEvent& aKeyEvent, TEventCode aType);
	TInt CountComponentControls() const;
	CCoeControl* ComponentControl(TInt aIndex) const;
	void SizeChangedL();
	void FocusChanged(TDrawNow aDrawNow);
	void HandleControlEventL(CCoeControl* aControl, TCoeEvent aEventType);
	// other functions
	void CreateControlsL();
	TInt ResourceId() const;
	CEikMfne* CreateMfneL() const;
	TInt IndexOfFocusedControl() const;
private:
	TMfneType iMfneType;
	TInt iNumberOfMfnes;
	CEikMfne** iMfnes;
	CCoeControl* iFocusedControl; // does not own anything
	};

CTstContainer::CTstContainer()
	:iMfneType(EMfneTypeGeneric)
	{
	__DECLARE_NAME(_S("CTstContainer"));
	}

void CTstContainer::ConstructL(const TRect& aRect)
	{
	CreateWindowL();
	EnableDragEvents();
	Window().SetBackgroundColor(TRgb(170, 170, 170));
	SetRectL(aRect);
	ActivateL();
	}

CTstContainer::~CTstContainer()
	{
	if (iMfnes)
		{
		for (TInt i=0; i<iNumberOfMfnes; ++i)
			delete iMfnes[i];
		delete [] iMfnes;
		}
	}

TInt CTstContainer::CountComponentControls() const
	{
	return iMfnes? iNumberOfMfnes: 0;
	}

CCoeControl* CTstContainer::ComponentControl(TInt aIndex) const
	{
	__ASSERT_ALWAYS(iMfnes, Panic(ETMfnePanicNoMfnesCurrently1));
	return iMfnes[aIndex];
	}

void CTstContainer::Draw(const TRect&) const
	{
	iEikonEnv->FillTexturedRect(Rect());
	}

void CTstContainer::SizeChangedL()
	{
	if (iMfnes)
		{
		TPoint pos(ESpacing, ESpacing);
		for (TInt i=0; i<iNumberOfMfnes; ++i)
			{
			TSize size=iMfnes[i]->MinimumSize();
			iMfnes[i]->SetExtentL(pos,size);
			pos.iY+=size.iHeight+ESpacing;
			}
		}
	}

void CTstContainer::FocusChanged(TDrawNow aDrawNow)
	{
	if (iFocusedControl)
		iFocusedControl->SetFocus(IsFocused(),aDrawNow);
	}

void CTstContainer::HandleControlEventL(CCoeControl* aControl, TCoeEvent aEventType)
	{
	switch (aEventType)
		{
	case EEventPrepareFocusTransition:
		iFocusedControl->PrepareForFocusLossL();
		break;
	case EEventRequestFocus:
		if (iFocusedControl!=aControl)
			{
			iFocusedControl->SetFocus(EFalse,EDrawNow);
			iFocusedControl=aControl;
			iFocusedControl->SetFocus(ETrue,EDrawNow);
			}
		break;
	default:
		break;
		}
	}

TKeyResponse CTstContainer::OfferKeyEventL(const TKeyEvent& aKeyEvent, TEventCode aType)
	{
	if (aType==EEventKey)
		{
		switch (TCharLC(aKeyEvent.iCode))
			{
		case EKeyEnter:
			if (iMfnes)
				{
				TInt notUsed;
				iFocusedControl->PrepareForFocusLossL();
				TBuf<64> buffer;
				switch (iMfneType)
					{
				case EMfneTypeGeneric:
					break;
				case EMfneTypeNumber:
					buffer.Format(_L("Number: %d"), ((CEikNumberEditor*)iFocusedControl)->Number());
					break;
				case EMfneTypeRange:
					{
					SEikRange range=((CEikRangeEditor*)iFocusedControl)->Range();
					buffer.Format(_L("Range: %d-%d"), range.iLowerLimit, range.iUpperLimit);
					}
					break;
				case EMfneTypeTime:
				case EMfneTypeTimeWithoutSeconds:
					TRAP(notUsed, ((CEikTimeEditor*)iFocusedControl)->Time().FormatL(buffer, _L("%FTime: %H%:%T%:%S")));
					break;
				case EMfneTypeDate:
					TRAP(notUsed, ((CEikDateEditor*)iFocusedControl)->Date().FormatL(buffer, _L("%FDate: %D %N %Y")));
					break;
				case EMfneTypeTimeAndDate:
				case EMfneTypeTimeAndDateWithoutSeconds:
					TRAP(notUsed, ((CEikTimeAndDateEditor*)iFocusedControl)->TimeAndDate().FormatL(buffer, _L("%FTime and date: %H%:%T%:%S %D %N %Y")));
					break;
				case EMfneTypeDuration:
					buffer.Format(_L("Duration: %d"), ((CEikDurationEditor*)iFocusedControl)->Duration().Int());
					break;
				case EMfneTypeTimeOffset:
					buffer.Format(_L("Time-offset: %d"), ((CEikTimeOffsetEditor*)iFocusedControl)->TimeOffset().Int());
					break;
				case EMfneTypeLatitude:
					{
					SEikDegreesMinutesDirection latitude=((CEikLatitudeEditor*)iFocusedControl)->Latitude();
					buffer.Format(_L("Latitude: %d°%d %c"), latitude.iDegrees, latitude.iMinutes, (latitude.iDirection==EEikCompassNorth)? 'N': 'S');
					}
					break;
				case EMfneTypeLongitude:
					{
					SEikDegreesMinutesDirection longitude=((CEikLongitudeEditor*)iFocusedControl)->Longitude();
					buffer.Format(_L("Longitude: %d°%d %c"), longitude.iDegrees, longitude.iMinutes, (longitude.iDirection==EEikCompassWest)? 'W': 'E');
					}
					break;
				default:
					Panic(ETMfnePanicBadMfneType1);
					break;
					}
				if (buffer.Length())
					{
					iEikonEnv->InfoMsg(buffer);
					return EKeyWasConsumed;
					}
				}
			return EKeyWasNotConsumed;
		case EKeyUpArrow:
		case EKeyDownArrow:
			if (iMfnes)
				{
				TInt indexOfFocusedControl=IndexOfFocusedControl();
				TInt indexOfNewFocusedControl=(aKeyEvent.iCode==EKeyUpArrow)?
												((indexOfFocusedControl>0)? indexOfFocusedControl-1: iNumberOfMfnes-1):
												((indexOfFocusedControl<iNumberOfMfnes-1)? indexOfFocusedControl+1: 0);
				if (iFocusedControl!=iMfnes[indexOfNewFocusedControl])
					{
					iFocusedControl->PrepareForFocusLossL();
					iFocusedControl->SetFocus(EFalse, EDrawNow);
					iFocusedControl=iMfnes[indexOfNewFocusedControl];
					iFocusedControl->SetFocus(ETrue, EDrawNow);
					}
				return EKeyWasConsumed;
				}
			return EKeyWasNotConsumed;
		default:
			break;
			}
		}
	return iFocusedControl? iFocusedControl->OfferKeyEventL(aKeyEvent, aType): EKeyWasNotConsumed;
	}

void CTstContainer::HandleCommandL(TInt aCommand)
	{
	TMfneType newMfneType=EMfneTypeGeneric; // dummy initialization to prevent compiler warning
	switch (aCommand)
		{
	case ETMfneCmdGenericEditors:
		newMfneType=EMfneTypeGeneric;
		goto createControls;
	case ETMfneCmdNumberEditors:
		newMfneType=EMfneTypeNumber;
		goto createControls;
	case ETMfneCmdRangeEditors:
		newMfneType=EMfneTypeRange;
		goto createControls;
	case ETMfneCmdTimeEditors:
		newMfneType=EMfneTypeTime;
		goto createControls;
	case ETMfneCmdTimeEditorsWithoutSeconds:
		newMfneType=EMfneTypeTimeWithoutSeconds;
		goto createControls;
	case ETMfneCmdDateEditors:
		newMfneType=EMfneTypeDate;
		goto createControls;
	case ETMfneCmdTimeAndDateEditors:
		newMfneType=EMfneTypeTimeAndDate;
		goto createControls;
	case ETMfneCmdTimeAndDateEditorsWithoutSeconds:
		newMfneType=EMfneTypeTimeAndDateWithoutSeconds;
		goto createControls;
	case ETMfneCmdDurationEditors:
		newMfneType=EMfneTypeDuration;
		goto createControls;
	case ETMfneCmdTimeOffsetEditors:
		newMfneType=EMfneTypeTimeOffset;
		goto createControls;
	case ETMfneCmdLatitudeEditors:
		newMfneType=EMfneTypeLatitude;
		goto createControls;
	case ETMfneCmdLongitudeEditors:
		newMfneType=EMfneTypeLongitude;
		goto createControls;
	createControls:
		if ((iMfnes==NULL) || (iMfneType!=newMfneType))
			{
			iMfneType=newMfneType;
			CreateControlsL();
			}
		break;
	case ETMfneCmdDialog1:
		{
		TInt number=7;
		SEikRange range;
		range.iLowerLimit=8;
		range.iUpperLimit=9;
		TTime time=TDateTime(0, EJanuary, 0, 8+12, 45, 30, 0);
		TTime date=TDateTime(1992, EFebruary, 29-1, 0, 0, 0, 0);
		TTime timeAndDate=TDateTime(1992, EMarch, 10-1, 6, 20, 0, 0);
		TTimeIntervalSeconds duration=76;
		TTimeIntervalSeconds timeOffset=84;
		SEikDegreesMinutesDirection latitude;
		latitude.iDegrees=12;
		latitude.iMinutes=34;
		latitude.iDirection=EEikCompassSouth;
		SEikDegreesMinutesDirection longitude;
		longitude.iDegrees=123;
		longitude.iMinutes=45;
		longitude.iSeconds=6;
		longitude.iDirection=EEikCompassEast;
		CEikDialog* dialog=new(ELeave) CTstDialog1(&number, &range, &time, &date, &timeAndDate, &duration, &timeOffset, &latitude, &longitude);
		dialog->ExecuteLD(R_TMFNE_DIALOG_1);
		}
		break;
	case ETMfneCmdDialog2:
		{
		CEikDialog* dialog=new(ELeave) CTstDialog2;
		dialog->ExecuteLD(R_TMFNE_DIALOG_2);
		}
		break;
	case EEikCmdExit:
		CBaActiveScheduler::Exit();
		break;
	default:
		Panic(ETMfnePanicBadEditorType);
		}
	}

void CTstContainer::CreateControlsL()
	{
	TTime timeAndDateNow;
	timeAndDateNow.HomeTime();
	TResourceReader resourceReader;
	iCoeEnv->CreateResourceReaderLC(resourceReader, ResourceId());
	TInt numberOfMfnes=resourceReader.ReadUint8();
	CEikMfne** mfnes=new(ELeave) CEikMfne*[numberOfMfnes];
	CleanupStack::PushL(mfnes);
	TPoint position(ESpacing, ESpacing);
	TInt i;
	for (i=0; i<numberOfMfnes; ++i)
		mfnes[i]=NULL;
	TLocale locale;
	for (i=0; i<numberOfMfnes; ++i)
		{
		locale.SetTimeFormat((TTimeFormat)(i%2));
		locale.SetAmPmSpaceBetween((i/2)%2);
		locale.SetAmPmSymbolPosition((TLocalePos)((i/4)%2));
		locale.SetDateFormat((TDateFormat)(i%3));
		locale.Set();
		mfnes[i]=CreateMfneL();
		mfnes[i]->SetContainerWindowL(*this);
		mfnes[i]->SetObserver(this);
		mfnes[i]->ConstructFromResourceL(resourceReader);
		switch (iMfneType)
			{
		case EMfneTypeTime:
		case EMfneTypeTimeWithoutSeconds:
			((CEikTimeEditor*)mfnes[i])->SetTime(timeAndDateNow);
			break;
		case EMfneTypeDate:
			((CEikDateEditor*)mfnes[i])->SetDate(timeAndDateNow);
			break;
		case EMfneTypeTimeAndDate:
		case EMfneTypeTimeAndDateWithoutSeconds:
			((CEikTimeAndDateEditor*)mfnes[i])->SetTimeAndDate(timeAndDateNow);
			break;
		default:
			break;
			}
		mfnes[i]->SetExtentL(position, mfnes[i]->MinimumSize());
		mfnes[i]->ActivateL();
		mfnes[i]->DrawDeferred();
		position.iY+=mfnes[i]->Size().iHeight+ESpacing;
		}
	CleanupStack::Pop(); // pop off mfnes as it will soon be owned by iMfnes
	CleanupStack::PopAndDestroy(); // pop and destroy the resource reader
	if (iMfnes)
		{
		for (TInt i=0; i<iNumberOfMfnes; ++i)
			{
			if (iMfnes[i])
				{
				iMfnes[i]->DrawDeferred();
				delete iMfnes[i];
				}
			}
		delete [] iMfnes;
		iMfnes=NULL;
		}
	iNumberOfMfnes=numberOfMfnes;
	iMfnes=mfnes;
	iFocusedControl=mfnes[0];
	iFocusedControl->SetFocus(ETrue);
	}

TInt CTstContainer::ResourceId() const
	{
	switch (iMfneType)
		{
	case EMfneTypeGeneric:
		return R_TMFNE_GENERIC_MFNES;
	case EMfneTypeNumber:
		return R_TMFNE_NUMBER_EDITORS;
	case EMfneTypeRange:
		return R_TMFNE_RANGE_EDITORS;
	case EMfneTypeTime:
		return R_TMFNE_TIME_EDITORS;
	case EMfneTypeTimeWithoutSeconds:
		return R_TMFNE_TIME_EDITORS_WITHOUT_SECONDS;
	case EMfneTypeDate:
		return R_TMFNE_DATE_EDITORS;
	case EMfneTypeTimeAndDate:
		return R_TMFNE_TIME_AND_DATE_EDITORS;
	case EMfneTypeTimeAndDateWithoutSeconds:
		return R_TMFNE_TIME_AND_DATE_EDITORS_WITHOUT_SECONDS;
	case EMfneTypeDuration:
		return R_TMFNE_DURATION_EDITORS;
	case EMfneTypeTimeOffset:
		return R_TMFNE_TIME_OFFSET_EDITORS;
	case EMfneTypeLatitude:
		return R_TMFNE_LATITUDE_EDITORS;
	case EMfneTypeLongitude:
		return R_TMFNE_LONGITUDE_EDITORS;
	default:
		Panic(ETMfnePanicBadMfneType2);
		return 0; // dummy return to prevent compiler error
		}
	}

CEikMfne* CTstContainer::CreateMfneL() const
	{
	switch (iMfneType)
		{
	case EMfneTypeGeneric:
		return new(ELeave) CTstGenericMfne;
	case EMfneTypeNumber:
		return new(ELeave) CEikNumberEditor;
	case EMfneTypeRange:
		return new(ELeave) CEikRangeEditor;
	case EMfneTypeTime:
	case EMfneTypeTimeWithoutSeconds:
		return new(ELeave) CEikTimeEditor;
	case EMfneTypeDate:
		return new(ELeave) CEikDateEditor;
	case EMfneTypeTimeAndDate:
	case EMfneTypeTimeAndDateWithoutSeconds:
		return new(ELeave) CEikTimeAndDateEditor;
	case EMfneTypeDuration:
		return new(ELeave) CEikDurationEditor;
	case EMfneTypeTimeOffset:
		return new(ELeave) CEikTimeOffsetEditor;
	case EMfneTypeLatitude:
		return new(ELeave) CEikLatitudeEditor;
	case EMfneTypeLongitude:
		return new(ELeave) CEikLongitudeEditor;
	default:
		Panic(ETMfnePanicBadMfneType3);
		return NULL; // dummy return to prevent compiler error
		}
	}

TInt CTstContainer::IndexOfFocusedControl() const
	{
	__ASSERT_ALWAYS(iMfnes, Panic(ETMfnePanicNoMfnesCurrently2));
	for (TInt i=0; i<iNumberOfMfnes; ++i)
		if (iFocusedControl==iMfnes[i])
			return i;
	Panic(ETMfnePanicFocusControlNotFound);
	return 0; // dummy return to prevent compiler error
	}

//
// CTstAppUi
//

class CTstAppUi : public CEikAppUi
	{
public:
	void ConstructL();
	virtual ~CTstAppUi();
private: // framework
	virtual void HandleCommandL(TInt aCommand);
private: // internal use
	void LaunchToolBarPopoutMenuL(TInt aButtonId,TInt aMenuId);
private:
	CTstContainer* iContainer;
	};

void CTstAppUi::ConstructL()
	{
	BaseConstructL();
	CreateHotKeyControlL(R_TMFNE_HOTKEYS);
	iContainer=new(ELeave) CTstContainer;
	iContainer->ConstructL(ClientRect());
	AddToStackL(iContainer);
	}

CTstAppUi::~CTstAppUi()
	{
	delete iContainer;
	}

void CTstAppUi::HandleCommandL(TInt aCommand)
	{
	if (aCommand==ETMfneCmdDialogs)
		{
		LaunchToolBarPopoutMenuL(ETMfneCmdDialogs,R_TMFNE_DIALOG_POPOUT_MENU);
		return;
		}
	iContainer->HandleCommandL(aCommand);
	}

void CTstAppUi::LaunchToolBarPopoutMenuL(TInt aButtonId,TInt aMenuId)
	{
	CCoeControl* button=iToolBar->ControlById(aButtonId);
	const TPoint targetPos=button->PositionRelativeToScreen();
	LaunchPopupMenuL(aMenuId,targetPos,EPopupTargetTopRight);
	Popup()->ClaimPointerGrab();
	}

//
// CTstDocument
//

class CTstDocument : public CEikDocument
	{
public:
	CTstDocument(CEikApplication& aApp): CEikDocument(aApp) { }
private: // from CApaDocument
	CEikAppUi* CreateAppUiL();
	};

CEikAppUi* CTstDocument::CreateAppUiL()
	{
    return(new(ELeave) CTstAppUi);
	}

//
// CTstApplication
//

class CTstApplication : public CEikApplication
	{
private: // from CApaApplication
	CApaDocument* CreateDocumentL();
	TUid AppDllUid() const;
	};

const TUid KUidTstApp={214};

TUid CTstApplication::AppDllUid() const
	{
	return(KUidTstApp);
	}

CApaDocument* CTstApplication::CreateDocumentL()
	{
	return(new(ELeave) CTstDocument(*this));
	}

//
// EXPORTed functions
//

EXPORT_C CApaApplication* NewApplication()
	{
	return(new CTstApplication);
	}

GLDEF_C TInt E32Dll(TDllReason)
	{
	return(KErrNone);
	}
