// TTDRAW1.CPP
//
// Copyright (c) 1997-1999 Symbian Ltd.  All rights reserved.
//

#include <eikenv.h>
#include <coecntrl.h>
#include <eikappui.h>
#include <e32keys.h>
#include <eikdef.h>
#include <eiklabel.h>
#include <coemain.h>
#include <coeccntx.h>
#include <eikapp.h>
#include <eikdoc.h>
#include <eikcmds.hrh>
#include <eikbutb.h>
#include <eiktbar.h>
#include <ttdraw1.rsg>
#include "ttdraw1.hrh"

//
// TTDrawModel
//

#ifdef _UNICODE
#define KUidTDrawApp KUidTDrawApp16
#else
#define KUidTDrawApp KUidTDrawApp8
#endif

const TUid KUidTDrawApp8={220};
const TUid KUidTDrawApp16={520};

class TTDrawModel
	{
public:
	TTDrawModel();
	TBool Differs(const TTDrawModel* aCompare) const;
public:
	TInt8 iFullEmphasis;
	TInt8 iPartialEmphasis;
	TInt8 iHAlign;
	TInt8 iVAlign;
	};

TTDrawModel::TTDrawModel()
	{
	iFullEmphasis=(-1);
	iPartialEmphasis=(-1);
	iHAlign=0;
	iVAlign=0;
	}

TBool TTDrawModel::Differs(const TTDrawModel* aCompare) const
	{
	return((*(TInt32*)this)!=(*(TInt32*)aCompare));
	}

//
// Two static functions
//

TCoeHAlignment HAlign(TInt aIndex)
	{
	return((TCoeHAlignment)(EHLeft+aIndex*EHCenter));
	}

TCoeVAlignment VAlign(TInt aIndex)
	{
	return((TCoeVAlignment)(EVTop+aIndex*EVCenter));
	}


//
// MTDrawContainerObserver
//

class MTDrawContainerObserver
	{
public:
	virtual void NotifyEmphasisChanged(TInt aIndex)=0;
	};

//
// class CTDrawContainer
//

const TInt KNumberOfDrawers=3;

class CTDrawContainer : public CCoeControl, public MCoeControlBrushContext
    {
public:
    void ConstructL(const TRect& aRect,MTDrawContainerObserver* aObserver,TTDrawModel* aModel);
    ~CTDrawContainer();
	void SetFullEmphasis(TInt aDrawer);
    void SetHAlignment(TInt aHAlign);
	void SetVAlignment(TInt aVAlign);
	void DrawDrawersNow();
	void SetModel(TTDrawModel* aModel);
private: // framework
	void Draw(const TRect& /*aRect*/) const;
	TKeyResponse OfferKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType);
    void SizeChangedL();
    TInt CountComponentControls() const;
    CCoeControl* ComponentControl(TInt aIndex) const;
private: // new function
    void CreateDrawersL();
    void CreateDrawerL(TInt aDrawer,const TDesC& aText,const CFont* aFont);
	void UpdateDrawerEmphasis(TInt aDrawer,CEikLabel::TTextEmphasis aEmphasis);
private:
    CEikLabel* iDrawer[KNumberOfDrawers];
	TTDrawModel* iModel;
	MTDrawContainerObserver* iObserver;
    };

CTDrawContainer::~CTDrawContainer()
    {
    for (TInt ii=0; ii<KNumberOfDrawers; ii++)
        delete(iDrawer[ii]);
    }
    
void CTDrawContainer::DrawDrawersNow()
	{
    for (TInt ii=0; ii<KNumberOfDrawers; ii++)
		iDrawer[ii]->DrawNow();
	}

const TInt KBorderEdge=1;
const TInt KBorderExternal=9;
const TInt KBorderInternal=7;
const TInt KBorderTotal=KBorderExternal+KBorderInternal;
const TInt KGapBetweenBoxes=10;
const TInt KLeftMargin = 15;
const TInt KRightMargin = 30;
const TInt KTopMargin = 5;
const TInt KBottomMargin = 0;

void CTDrawContainer::SizeChangedL()
    {
    TPoint pos(KGapBetweenBoxes,KGapBetweenBoxes-KBorderInternal);
    for (TInt ii=0; ii<KNumberOfDrawers; ii++)
        {
        TSize size=iDrawer[ii]->MinimumSize();
		size+=TSize(8*KBorderTotal,2*KBorderTotal);
        iDrawer[ii]->SetExtentL(pos,size);
        pos.iY+=size.iHeight+KGapBetweenBoxes;
        }
    }
    
TInt CTDrawContainer::CountComponentControls() const
	{
	return KNumberOfDrawers;
	}

CCoeControl* CTDrawContainer::ComponentControl(TInt aIndex) const
	{
	return (iDrawer[aIndex]);
	}

void CTDrawContainer::ConstructL(const TRect& aRect,MTDrawContainerObserver* aObserver,TTDrawModel* aModel)
    {
	iObserver=aObserver;
	iModel=aModel;
    CreateWindowL();
    Window().SetShadowDisabled(ETrue);
    iContext=this;
    iEikonEnv->SetContextTextured(this);
    CreateDrawersL();
    SetRectL(aRect);
    ActivateL();
    }

void CTDrawContainer::SetModel(TTDrawModel* aModel)
	{
	iModel=aModel;
	SetHAlignment(iModel->iHAlign);
	SetVAlignment(iModel->iVAlign);
	for (TInt ii=0; ii<3; ii++)
		{
		CEikLabel* drawer=iDrawer[ii];
		if (ii==iModel->iFullEmphasis)
			drawer->SetEmphasis(CEikLabel::EFullEmphasis);
		else if (ii==iModel->iPartialEmphasis)
			drawer->SetEmphasis(CEikLabel::EPartialEmphasis);
		else
			drawer->SetEmphasis(CEikLabel::ENoEmphasis);
		}
	}

void CTDrawContainer::CreateDrawerL(TInt aDrawer,const TDesC& aText,const CFont* aFont)
    {
    CEikLabel* drawer=iDrawer[aDrawer]=new(ELeave) CEikLabel;
    drawer->SetFont(aFont);
    drawer->SetTextL(aText);
	drawer->SetContainerWindowL(*this);
    drawer->iMargin.iLeft=KLeftMargin;
	drawer->iMargin.iRight=KRightMargin;
	drawer->iMargin.iTop=KTopMargin;
	drawer->iMargin.iBottom=KBottomMargin;
	if (aDrawer==iModel->iFullEmphasis)
		drawer->SetEmphasis(CEikLabel::EFullEmphasis);
	else if (aDrawer==iModel->iPartialEmphasis)
		drawer->SetEmphasis(CEikLabel::EPartialEmphasis);
    }

void CTDrawContainer::CreateDrawersL()
    {
    CreateDrawerL(0,_L("Hello &world!"),iEikonEnv->NormalFont());
    CreateDrawerL(1,_L("one two\nthree four\nfive si&x"),iEikonEnv->AnnotationFont());
    CreateDrawerL(2,_L("&alpha beta gamma\ndelta"),iEikonEnv->TitleFont());
	SetHAlignment(iModel->iHAlign);
	SetVAlignment(iModel->iVAlign);
    }

void CTDrawContainer::SetHAlignment(TInt aHAlign)
    {
	iModel->iHAlign=(TInt8)aHAlign;
	TCoeHAlignment hAlign=HAlign(aHAlign);
    for (TInt ii=0; ii<KNumberOfDrawers; ii++)
		iDrawer[ii]->iAlignment.SetHAlignment(hAlign);
    }

void CTDrawContainer::SetVAlignment(TInt aVAlign)
    {
	iModel->iVAlign=(TInt8)aVAlign;
	TCoeVAlignment vAlign=VAlign(aVAlign);
    for (TInt ii=0; ii<KNumberOfDrawers; ii++)
		iDrawer[ii]->iAlignment.SetVAlignment(vAlign);
    }

void CTDrawContainer::SetFullEmphasis(TInt aDrawer)
    {
    if (aDrawer==iModel->iFullEmphasis)
        return;
    TInt toBePartial=iModel->iFullEmphasis;
    iModel->iFullEmphasis=(TInt8)aDrawer;
    UpdateDrawerEmphasis(iModel->iFullEmphasis,CEikLabel::EFullEmphasis);
    if (toBePartial>=0)
        UpdateDrawerEmphasis(toBePartial,CEikLabel::EPartialEmphasis);
    if (iModel->iPartialEmphasis>=0 && iModel->iPartialEmphasis!=iModel->iFullEmphasis)
        UpdateDrawerEmphasis(iModel->iPartialEmphasis,CEikLabel::ENoEmphasis);
    iModel->iPartialEmphasis=(TInt8)toBePartial;	
    }

void CTDrawContainer::UpdateDrawerEmphasis(TInt aDrawer,CEikLabel::TTextEmphasis aEmphasis)
    {
    iDrawer[aDrawer]->SetEmphasis(aEmphasis);
    }

TKeyResponse CTDrawContainer::OfferKeyEventL(const TKeyEvent& /*aKeyEvent*/,TEventCode aType)
	{
	if (aType!=EEventKey)
		return(EKeyWasNotConsumed);
//	TInt drawer=CheckForMnemonic(aKeyEvent.iCode);
//	if (drawer>=0)
//		{
//		SetFullEmphasis(drawer);
//		DrawDrawersNow();
//		iObserver->NotifyEmphasisChanged(drawer);
//		}
	return(EKeyWasConsumed);
	}

void CTDrawContainer::Draw(const TRect& /*aRect*/) const
	{
	CWindowGc& gc = SystemGc();
	gc.SetBrushStyle(CGraphicsContext::ESolidBrush);
	gc.DrawRect(Rect());
	gc.SetBrushStyle(CGraphicsContext::ENullBrush);
    for (TInt ii=0; ii<KNumberOfDrawers; ii++)
        {
        TRect box=iDrawer[ii]->Rect();
		box.Grow(KBorderEdge,KBorderEdge);
        gc.DrawRect(box);
        }											  
	}

//
// CTDrawDocument - definition
//

class CTDrawDocument : public CEikDocument
	{
public:
	CTDrawDocument(CEikApplication& aApp): CEikDocument(aApp) { }
	TTDrawModel* Model() { return(&iModel); }
private: // from CEikDocument
	CEikAppUi* CreateAppUiL();
private: // from CApaDocument
	void StoreL(CStreamStore& aStore,CStreamDictionary& aStreamDic) const;
	void RestoreL(const CStreamStore& aStore,const CStreamDictionary& aStreamDic);
private:
	TTDrawModel iModel;
	};

//
// CTDrawAppUi
//

class CTDrawAppUi : public CEikAppUi, public MTDrawContainerObserver
    {
public:
    void ConstructL();
	~CTDrawAppUi();
private: // framework
	void HandleCommandL(TInt aCommand);
	void HandleModelChangeL();
private: // from MTDrawContainerObserver
	void NotifyEmphasisChanged(TInt aIndex);
private: // internal use
	void PrepareToolbarButtons();
private:
    CTDrawContainer* iContainer;
	TEikButtonCoordinator iHorizCoord;
	TEikButtonCoordinator iVertCoord;
	TEikButtonCoordinator iEmphCoord;
	TTDrawModel* iModel;
	TTDrawModel iOriginalModel;
    };

void CTDrawAppUi::NotifyEmphasisChanged(TInt aIndex)
    {
	iToolBar->SetButtonStateOn(aIndex+ETTDrawCmdEmphasisFirst,ETrue);
    }

void CTDrawAppUi::PrepareToolbarButtons()
	{
	iToolBar->CoordinateButtons(ETTDrawCmdHorizLeft,3,&iHorizCoord);
	iToolBar->CoordinateButtons(ETTDrawCmdVertTop,3,&iVertCoord);
	iToolBar->CoordinateButtons(ETTDrawCmdEmphasisFirst,3,&iEmphCoord);
	iToolBar->SetButtonStateOn(ETTDrawCmdHorizLeft+iModel->iHAlign,ETrue);
	iToolBar->SetButtonStateOn(ETTDrawCmdVertTop+iModel->iVAlign,ETrue);
	}
	
void CTDrawAppUi::ConstructL()
    {
    BaseConstructL();
	CreateHotKeyControlL(R_TTDR_HOTKEYS);
	iModel=((CTDrawDocument*)iDocument)->Model();
	iOriginalModel=(*iModel);
	PrepareToolbarButtons();
    iContainer=new(ELeave) CTDrawContainer;
    iContainer->ConstructL(ClientRect(),this,iModel);
    AddToStackL(iContainer);
    }

void CTDrawAppUi::HandleModelChangeL()
	{
	iModel=((CTDrawDocument*)iDocument)->Model();
	iOriginalModel=(*iModel);
	PrepareToolbarButtons();
	iContainer->SetModel(iModel);
	iContainer->DrawNow();
	}

void CTDrawAppUi::HandleCommandL(TInt aCommand)
	{
	switch (aCommand)
		{
	case ETTDrawCmdHorizLeft:
	case ETTDrawCmdHorizCenter:
	case ETTDrawCmdHorizRight:
		iContainer->SetHAlignment(aCommand-ETTDrawCmdHorizLeft);
		break;
	case ETTDrawCmdVertTop:
	case ETTDrawCmdVertMiddle:
	case ETTDrawCmdVertBottom:
		iContainer->SetVAlignment(aCommand-ETTDrawCmdVertTop);
		break;
	case ETTDrawCmdEmphasisFirst:
	case ETTDrawCmdEmphasisSecond:
	case ETTDrawCmdEmphasisThird:
		iContainer->SetFullEmphasis(aCommand-ETTDrawCmdEmphasisFirst);
		break;
	case EEikCmdExit:
		if (iOriginalModel.Differs(iModel))
			SaveL();
		Exit();
		return;
		}
	iToolBar->SetButtonStateOn(aCommand,ETrue); // does nothing if already on
	iContainer->DrawDrawersNow();
	}

CTDrawAppUi::~CTDrawAppUi()
	{
    delete iContainer;
	if (iDoorObserver)
		iDoorObserver->NotifyExit(MApaEmbeddedDocObserver::EKeepChanges);
	}

//
// CTDrawDocument - implementation
//

CEikAppUi* CTDrawDocument::CreateAppUiL()
	{
    return(new(ELeave) CTDrawAppUi);
	}

void CTDrawDocument::StoreL(CStreamStore& aStore,CStreamDictionary& aStreamDic) const
	{
	RStoreWriteStream stream;
	TStreamId streamId=stream.CreateLC(aStore);
	stream<<iModel.iFullEmphasis;
	stream<<iModel.iPartialEmphasis;
	stream<<iModel.iHAlign;
	stream<<iModel.iVAlign;
	stream.CommitL();
	CleanupStack::PopAndDestroy(); // stream
	aStreamDic.AssignL(KUidTDrawApp,streamId);
	}

void CTDrawDocument::RestoreL(const CStreamStore& aStore,const CStreamDictionary& aStreamDic)
	{
	TStreamId headStreamId=aStreamDic.At(KUidTDrawApp);
	RStoreReadStream stream;
	stream.OpenLC(aStore,headStreamId);
	stream>>iModel.iFullEmphasis;
	stream>>iModel.iPartialEmphasis;
	stream>>iModel.iHAlign;
	stream>>iModel.iVAlign;
	CleanupStack::PopAndDestroy(); // stream
	}

//
// CTDrawApplication
//

class CTDrawApplication : public CEikApplication
	{
private: // from CApaApplication
	CApaDocument* CreateDocumentL();
	TUid AppDllUid() const;
	};

TUid CTDrawApplication::AppDllUid() const
	{
	return(KUidTDrawApp);
	}

CApaDocument* CTDrawApplication::CreateDocumentL()
	{
	return(new(ELeave) CTDrawDocument(*this));
	}

//
// EXPORTed functions
//

EXPORT_C CApaApplication* NewApplication()
	{
	return(new CTDrawApplication);
	}

GLDEF_C TInt E32Dll(TDllReason)
	{
	return(KErrNone);
	}
