// TPACKAGE.CPP
//
// Copyright (c) 1997-1999 Symbian Ltd.  All rights reserved.
//

#include <eikenv.h>
#include <coecntrl.h>
#include <basched.h>
#include <coeccntx.h>
#include <eikappui.h>
#include <e32keys.h>
#include <eikembal.h>
#include <bamdesca.h>
#include <eikcmds.hrh>
#include <eikdialg.h>
#include <eikchlst.h>
#include <eikdoc.h>
#include <eikapp.h>
#include <s32file.h>
#include <eikprtpv.h>
#include <eikproc.h>
#include <eikon.rsg>

#include <tpackage.rsg>
#include "tpackage.hrh"

//
// CPackagerModel
//

const TUid KUidPackagerApp={213};

struct SPackage
	{
public:
	TBuf<20> iPrompt;
	CApaDocument* iDocument;
	};

class CPackagerModel : public CArrayFixFlat<SPackage>
	{
public:
	CPackagerModel(CApaProcess* aProcess);
	~CPackagerModel();
	void AppendDocL(CApaDocument* aDoc);
	void DeleteDoc(TInt aPos);
private:
	CApaProcess* iProcess;
	};

CPackagerModel::CPackagerModel(CApaProcess* aProcess)
	: CArrayFixFlat<SPackage> (2)
	{
	iProcess=aProcess;
	}

CPackagerModel::~CPackagerModel()
	{
	const TInt count=Count();
	for (TInt pos=0; pos<count; pos++)
		iProcess->DestroyDocument((*this)[pos].iDocument);
	}

void CPackagerModel::AppendDocL(CApaDocument* aDoc)
	{
	SPackage package;
	package.iDocument=aDoc;
	TRAPD(err,AppendL(package));
	if (err)
		{
		iProcess->DestroyDocument(aDoc);
		User::Leave(err);
		}
	}

void CPackagerModel::DeleteDoc(TInt aPos)
	{
	CApaDocument* doc=(*this)[aPos].iDocument;
	iProcess->DestroyDocument(doc);
	Delete(aPos);
	}

//
// CPackagerContainer
//

class CPackagerContainer : public CCoeControl, public MCoeControlBrushContext
    {
public:
    void ConstructL(const TRect& aRect);
	~CPackagerContainer();
private: // framework
    void Draw(const TRect& aRect) const;
	TKeyResponse OfferKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType);
    void SizeChangedL();
    void FocusChanged(TDrawNow aDrawNow);
private:
    };

void CPackagerContainer::FocusChanged(TDrawNow /*aDrawNow*/)
    {
    }
    
void CPackagerContainer::ConstructL(const TRect& aRect)
    {
    CreateWindowL();
    Window().SetShadowDisabled(ETrue);
	EnableDragEvents();
	iBrushStyle=CGraphicsContext::ESolidBrush;
	iBrushColor=KRgb1in4DitheredGray;
    iContext=this;
	Window().SetBackgroundColor(KRgb1in4DitheredGray);
    SetRectL(aRect);
    ActivateL();
    }

CPackagerContainer::~CPackagerContainer()
	{
	}

void CPackagerContainer::Draw(const TRect& aRect) const
    {
	CGraphicsContext& gc=SystemGc();
	gc.SetPenStyle(CGraphicsContext::ENullPen);
	gc.DrawRect(aRect);
    }

void CPackagerContainer::SizeChangedL()
    {
    }

TKeyResponse CPackagerContainer::OfferKeyEventL(const TKeyEvent& /*aKeyEvent*/,TEventCode /*aType*/)
    {
    return(EKeyWasConsumed);
    }

//
// CPackagerDocument - definition
//

class CPackagerDocument : public CEikDocument
	{
public:
	CPackagerDocument(CEikApplication& aApp): CEikDocument(aApp), iModel(Process()) { }
	CPackagerModel* 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:
	CPackagerModel iModel;
	};

//
// CPackagerAppUi
//

class CPackagerAppUi : public CEikAppUi
    {
public:
    void ConstructL();
	~CPackagerAppUi();
private: // from CEikAppUi
    void HandleCommandL(TInt aCommand);
private: // internal functions
	void CmdInsertObjectL();
	void CmdEditObjectL();
	void CmdDeleteObjectL();
	TInt SelectDocumentL(TInt aHelpRid,TInt aTitleRid);
private:
    CPackagerContainer* iContainer;
	CPackagerModel* iModel;
    };

void CPackagerAppUi::ConstructL()
    {
	iModel=((CPackagerDocument*)iDocument)->Model();
    BaseConstructL();
    iContainer=new(ELeave) CPackagerContainer;
    iContainer->ConstructL(ClientRect());
    AddToStackL(iContainer);
    }

CPackagerAppUi::~CPackagerAppUi()
	{
    delete iContainer;
	}

void CPackagerAppUi::HandleCommandL(TInt aCommand)
    {
	switch (aCommand)
		{
	case EEikCmdExit:
		SaveAnyChangesL();
        Exit();
		break;
	case ETPackagerCmdInsertObject:
		CmdInsertObjectL();
		break;
	case ETPackagerCmdEditObject:
		CmdEditObjectL();
		break;
	case ETPackagerCmdDeleteObject:
		CmdDeleteObjectL();
		break;
		}
    }

TInt CPackagerAppUi::SelectDocumentL(TInt aHelpRid,TInt aTitleRid)
	{
	const TInt max=iModel->Count();
	if (!max)
		{
		TBuf<20> tmp;
		iCoeEnv->ReadResource(tmp,aHelpRid);
		iEikonEnv->LeaveWithInfoMsg(R_TPCK_TBUF_NO_OBJECTS_TO_XXX,&tmp);
		}
	TInt pos=1;
	if (max>1)
		{
		CEikDialog* dialog=new(ELeave) CEikNumDialog(pos,1,max,aTitleRid,R_TPCK_TBUF_DLG_PROMPT);
		if (!(dialog->ExecuteLD(R_EIK_DIALOG_SINGLE_NUMED)))
			CBaActiveScheduler::LeaveNoAlert();
		}
	return(pos-1);
	}

void CPackagerAppUi::CmdEditObjectL()
	{
	TInt pos=SelectDocumentL(R_TPCK_TBUF_EDIT,R_TPCK_TBUF_EDIT_DLG_TITLE);
	CApaDocument* doc=(*iModel)[pos].iDocument;
	((CEikDocument*)doc)->EditL(NULL);
	}

void CPackagerAppUi::CmdDeleteObjectL()
	{
	TInt pos=SelectDocumentL(R_TPCK_TBUF_DELETE,R_TPCK_TBUF_DELETE_DLG_TITLE);
	iModel->DeleteDoc(pos);
	}

void CPackagerAppUi::CmdInsertObjectL()
	{
	CEikEmbeddableAppList* list=new(ELeave) CEikEmbeddableAppList;
	CleanupStack::PushL(list);
	list->ConstructL();
	TInt count=list->Count();
	if (!count)
		iEikonEnv->InfoMsg(R_TPCK_TBUF_NO_EMBEDDABLE_APPS_FOUND);
	else
		{
		CEikDialog* dialog=new(ELeave) CEikDialog;
		dialog->PrepareLC(R_TPCK_DLG_INSERT_OBJECT);
		CEikChoiceList* choiceList=(CEikChoiceList*)dialog->Control(ETPackagerInsertObjectDlgApps);
		choiceList->SetArrayL(list);
		TInt choice=0;
		dialog->DeclareAutoChoiceList(ETPackagerInsertObjectDlgApps,&choice);
		if (dialog->RunLD())
			{
			CEikDocument* newDoc=list->CreateEmbeddedDocumentL(choice,iEikonEnv->Process());
			iModel->AppendDocL(newDoc);
			newDoc->EditL(NULL);
			}
		}
	CleanupStack::PopAndDestroy(); // list
	}

//
// CPackagerDocument - implementation
//

CEikAppUi* CPackagerDocument::CreateAppUiL()
	{
    return(new(ELeave) CPackagerAppUi);
	}

void CPackagerDocument::StoreL(CStreamStore& aStore,CStreamDictionary& aStreamDic) const
	{
	RStoreWriteStream stream;
	TStreamId streamId=stream.CreateLC(aStore);
//	stream<<iModel;
	stream.CommitL();
	CleanupStack::PopAndDestroy(); // stream
	aStreamDic.AssignL(KUidPackagerApp,streamId);
	}

void CPackagerDocument::RestoreL(const CStreamStore& aStore,const CStreamDictionary& aStreamDic)
	{
	TStreamId headStreamId=aStreamDic.At(KUidPackagerApp);
	RStoreReadStream stream;
	stream.OpenLC(aStore,headStreamId);
//	stream>>iModel;
	CleanupStack::PopAndDestroy(); // stream
	}
	
//
// CPackagerApplication
//

class CPackagerApplication : public CEikApplication
	{
private: // from CApaApplication
	CApaDocument* CreateDocumentL();
	TUid AppDllUid() const;
	};

TUid CPackagerApplication::AppDllUid() const
	{
	return(KUidPackagerApp);
	}

CApaDocument* CPackagerApplication::CreateDocumentL()
	{
	return new(ELeave) CPackagerDocument(*this);
	}

//
// EXPORTed functions
//

EXPORT_C CApaApplication* NewApplication()
	{
	return(new CPackagerApplication);
	}

GLDEF_C TInt E32Dll(TDllReason)
	{
	return(KErrNone);
	}
