// TEDWIN.CPP
//
// Copyright (c) 1997-1999 Symbian Ltd.  All rights reserved.
//

#include <basched.h>
#include <eikenv.h>
#include <coecntrl.h>
#include <eikappui.h>
#include <e32keys.h>
#include <eikdef.h>
#include <eikedwin.h>
#include <eikrted.h>
#include <eikedwin.hrh>
#include <eikpprob.h>
#include <eikprtdg.h>
#include <eikprtpv.h>
#include <prnsetup.h>
#include <eikcmds.hrh>
#include <eikapp.h>
#include <eikdoc.h>
#include <txtrich.h>
#include "tedwin.hrh"
#include <tedwin.rsg>
#include <eikon.rsg>

//
// class CSimpleControl
//

const TInt KNumOfEdwins=5;
const KProfileTimingTests=8;

class CSimpleControl : public CCoeControl, public MCoeControlObserver
	{
public:
	~CSimpleControl();
	void ConstructL();
	void TestConstructionTimingL(TInt aCommand);
private: // framework
	void Draw(const TRect& aRect) const;
	TKeyResponse OfferKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType);
	void HandleControlEventL(CCoeControl* aControl,TCoeEvent aEventType);
	void ActivateL();
	TInt CountComponentControls() const;
	CCoeControl* ComponentControl(TInt aIndex) const;
private:
    void SetFocusControl(CCoeControl* aControl);
	TInt IndexOfFocusedEdwin();
	void CreateEdwinsL();
	void TimeConstructionL(TInt aCommand);
	void TimeTextViewConstructionL();
	void TimeTextLayoutConstructionL();
	void DisplayTime();
private:
	CCoeControl* iFocusControl;
    CEikEdwin* iEdwin[KNumOfEdwins];
	};

CSimpleControl::~CSimpleControl()
	{
	for (TInt ii=0;ii<KNumOfEdwins;ii++)
		delete iEdwin[ii];
	}

void CSimpleControl::ConstructL()
    {
    CreateWindowL();
    Window().SetShadowDisabled(ETrue);
	CreateEdwinsL();
    iFocusControl=iEdwin[KNumOfEdwins-1];
    SetExtentToWholeScreenL();
	ActivateL();
    iFocusControl->SetFocus(ETrue);
    }

void CSimpleControl::ActivateL()
	{
	CCoeControl::ActivateL();
	for (TInt ii=0;ii<KNumOfEdwins;ii++)
		iEdwin[ii]->ActivateL();
	}

void CSimpleControl::HandleControlEventL(CCoeControl* aControl,TCoeEvent aEventType)
	{
	if (aEventType==EEventRequestFocus)
		SetFocusControl(aControl);
	}

void CSimpleControl::CreateEdwinsL()
	{
	TPoint pos(10,20);
	TInt leftEdwinsVertGap=15;
	TInt leftEdwinsHeight=24;
	iEdwin[0]=new(ELeave) CEikEdwin;
	iEdwin[0]->SetContainerWindowL(*this);
	iEdwin[0]->SetObserver(this);
	iEdwin[0]->ConstructL(EEikEdwinNoWrap,15,0,3);
	iEdwin[0]->SetExtentL(pos,iEdwin[0]->MinimumSize());
	pos.iY+=iEdwin[0]->Size().iHeight;
	for (TInt ii=1;ii<KNumOfEdwins-1;ii++)
		{
		iEdwin[ii]=new(ELeave) CEikEdwin;
		iEdwin[ii]->SetContainerWindowL(*this);
		iEdwin[ii]->SetObserver(this);
		iEdwin[ii]->ConstructL(EEikEdwinNoWrap,15,0,3);
		iEdwin[ii]->SetExtentL(TPoint(pos.iX,pos.iY+leftEdwinsVertGap*ii+leftEdwinsHeight*(ii-1)),
									TSize(250,leftEdwinsHeight));
		}
	iEdwin[KNumOfEdwins-1]=new(ELeave) CEikRichTextEditor;
	STATIC_CAST(CEikRichTextEditor*,iEdwin[KNumOfEdwins-1])->ConstructL(this,0,0,EEikEdwinInclusiveSizeFixed);
	iEdwin[KNumOfEdwins-1]->SetObserver(this);
	iEdwin[KNumOfEdwins-1]->CreateScrollBarFrameL();
	iEdwin[KNumOfEdwins-1]->ScrollBarFrame()->SetScrollBarVisibilityL(CEikScrollBarFrame::EOff, CEikScrollBarFrame::EOn);
	iEdwin[KNumOfEdwins-1]->SetExtentL(TPoint(290,20),TSize(300,200));
	}

void CSimpleControl::SetFocusControl(CCoeControl* aControl)
    {
    iFocusControl->SetFocus(EFalse,EDrawNow);
    iFocusControl=aControl;
    iFocusControl->SetFocus(ETrue,EDrawNow);
    }

TInt CSimpleControl::IndexOfFocusedEdwin()
	{
	TInt count=0;
	while (count<KNumOfEdwins)
		{
		if (iEdwin[count]->IsFocused())
			break;
		++count;
		}
	return count;
	}

TKeyResponse CSimpleControl::OfferKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType)
	{
	if (aType==EEventKey)
		{
		if (aKeyEvent.iModifiers & EModifierCtrl)
			{
			switch (aKeyEvent.iCode)
				{
			case CTRL('e'):
				CBaActiveScheduler::Exit();
			case EKeyUpArrow:
				{
				const TInt index=IndexOfFocusedEdwin();
				if (index!=0)
					SetFocusControl(iEdwin[index-1]);
				else
					SetFocusControl(iEdwin[KNumOfEdwins-1]);
				break;
				}
			case EKeyDownArrow:
				{
				const TInt index=IndexOfFocusedEdwin();
				if (index<KNumOfEdwins-1)
					SetFocusControl(iEdwin[index+1]);
				else
					SetFocusControl(iEdwin[0]);
				break;
				}
			default:
				;
				}
			}
		iFocusControl->OfferKeyEventL(aKeyEvent, aType);
		}
	return(EKeyWasConsumed);
	}

void CSimpleControl::Draw(const TRect& /*aRect*/) const
	{
	iEikonEnv->FillTexturedRect(Rect());
	}

TInt CSimpleControl::CountComponentControls() const
	{
	return KNumOfEdwins;
	}

CCoeControl* CSimpleControl::ComponentControl(TInt aIndex) const
	{
	if (aIndex<KNumOfEdwins)
		return iEdwin[aIndex];
	return NULL;
	}

void CSimpleControl::TestConstructionTimingL(TInt aCommand)
	{
	switch (aCommand)
		{
	case EAppCmdTimeOwnWindow:
	case EAppCmdTimeLodger:
		TimeConstructionL(aCommand);
		break;
	case EAppCmdTimeTextView:
		TimeTextViewConstructionL();
		break;
	case EAppCmdTimeTextLayout:
		TimeTextLayoutConstructionL();
		break;
		}
	}

void CSimpleControl::DisplayTime()
	{
	TProfile profile;
	RDebug::ProfileResult(&profile,KProfileTimingTests,1);
	const TInt timeInMSecs=profile.iTime/20000; // all tests are carried out 20 times
	TBuf<16> buf;
	buf.Format(_L("time %d ms"),timeInMSecs);
	iEikonEnv->AlertWin(buf);
	}

void CSimpleControl::TimeConstructionL(TInt aCommand)
	{
	TInt flags=0;
	switch (aCommand)
		{
	case EAppCmdTimeOwnWindow:
		flags=EEikEdwinOwnsWindow;
		break;
	case EAppCmdTimeLodger:
		break;
		}
	for (TInt kk=4;kk<25;kk+=4)
		{
		TBuf<32> buf;
		buf.Format(_L("1 line, %d chars wide"),kk);
		iEikonEnv->InfoMsg(buf);
		CEikEdwin* edwin[20];
		RDebug::ProfileReset(KProfileTimingTests,1);
		__PROFILE_START(KProfileTimingTests)
		for (TInt ii=0;ii<20;ii++)
			{
			edwin[ii]=new(ELeave) CEikEdwin;
			CleanupStack::PushL(edwin[ii]);
			edwin[ii]->ConstructL(flags,4,4,2);
			edwin[ii]->SetContainerWindowL(*this);
			edwin[ii]->CreateTextViewL();
			edwin[ii]->SetExtentL(TPoint(),edwin[ii]->MinimumSize());
			edwin[ii]->ActivateL();
			}
		__PROFILE_END(KProfileTimingTests)
		for (TInt jj=0;jj<20;jj++)
			CleanupStack::PopAndDestroy();
		DisplayTime();
		}
	}

void CSimpleControl::TimeTextViewConstructionL()
	{
	CGlobalText* text=CGlobalText::NewL(iEikonEnv->SystemParaFormatLayerL(),
										iEikonEnv->SystemCharFormatLayerL());
	CleanupStack::PushL(text);
	for (TInt kk=20;kk<150;kk+=20)
		{
		TBuf<32> buf;
		buf.Format(_L("width: %d , height: 20"),kk);
		iEikonEnv->InfoMsg(buf);
		CTextLayout* txtLay=CTextLayout::NewL(text,kk);
		CleanupStack::PushL(txtLay);
		const TRect viewRect(TPoint(0,0),TSize(kk,20));
		CTextView* txtView[20];
		RDebug::ProfileReset(KProfileTimingTests,1);
		__PROFILE_START(KProfileTimingTests)
		for (TInt ii=0;ii<20;ii++)
			{
			txtView[ii]=CTextView::NewL(txtLay,viewRect,iEikonEnv->ScreenDevice(),
									iEikonEnv->ScreenDevice(),&Window(),&iEikonEnv->RootWin(),
									&iEikonEnv->WsSession());
			CleanupStack::PushL(txtView[ii]);
			}
		__PROFILE_END(KProfileTimingTests)
		for (TInt jj=0;jj<20;jj++)
			CleanupStack::PopAndDestroy(); // txtView[jj]
		CleanupStack::PopAndDestroy(); // txtLay
		DisplayTime();
		}
	CleanupStack::PopAndDestroy(); // text
	}

void CSimpleControl::TimeTextLayoutConstructionL()
	{
	CGlobalText* text=CGlobalText::NewL(iEikonEnv->SystemParaFormatLayerL(),
										iEikonEnv->SystemCharFormatLayerL());
	CleanupStack::PushL(text);
	CTextLayout* txtLay[20];
	RDebug::ProfileReset(KProfileTimingTests,1);
	__PROFILE_START(KProfileTimingTests)
	for (TInt ii=0;ii<20;ii++)
		{
		txtLay[ii]=CTextLayout::NewL(text,50);
		CleanupStack::PushL(txtLay[ii]);
		}
	__PROFILE_END(KProfileTimingTests)
	for (TInt jj=0;jj<20;jj++)
		CleanupStack::PopAndDestroy(); // txtLay[jj]
	CleanupStack::PopAndDestroy(); // text
	DisplayTime();
	}

//
// class CEdwinAppUi
//

const TInt KMaxNoOfPages=99;
const TInt KInitialNumOfPages=10;

class CEdwinAppUi : public CEikAppUi
    {
public:
    ~CEdwinAppUi();
    void ConstructL();
private: // framework
	void HandleCommandL(TInt aCommand);
private:
	CSimpleControl* iSimpleControl;
    };

CEdwinAppUi::~CEdwinAppUi()
    {
	delete iSimpleControl;
	}
    
void CEdwinAppUi::ConstructL()
    {
    BaseConstructL();
	iSimpleControl=new(ELeave) CSimpleControl;
	iSimpleControl->ConstructL();
	AddToStackL(iSimpleControl);
    }

void CEdwinAppUi::HandleCommandL(TInt aCommand)
	{
	switch (aCommand)
		{
	case EAppCmdTimeOwnWindow:
	case EAppCmdTimeLodger:
	case EAppCmdTimeTextView:
	case EAppCmdTimeTextLayout:
		iSimpleControl->TestConstructionTimingL(aCommand);
		break;
		}
	}

//
// CEdwinDocument
//

class CEdwinDocument : public CEikDocument
	{
public:
	CEdwinDocument(CEikApplication& aApp): CEikDocument(aApp) { }
private: // from CApaDocument
	CEikAppUi* CreateAppUiL();
	};

CEikAppUi* CEdwinDocument::CreateAppUiL()
	{
    return(new(ELeave) CEdwinAppUi);
	}

//
// CEdwinApplication
//

class CEdwinApplication : public CEikApplication
	{
private: // from CApaApplication
	CApaDocument* CreateDocumentL();
	TUid AppDllUid() const;
	};

const TUid KUidEdwinApp={216};

TUid CEdwinApplication::AppDllUid() const
	{
	return(KUidEdwinApp);
	}

CApaDocument* CEdwinApplication::CreateDocumentL()
	{
	return(new(ELeave) CEdwinDocument(*this));
	}

//
// EXPORTed functions
//

EXPORT_C CApaApplication* NewApplication()
	{
	return(new CEdwinApplication);
	}

GLDEF_C TInt E32Dll(TDllReason)
	{
	return(KErrNone);
	}
