// TEAR1.CPP
//
// Copyright (c) 1997-1999 Symbian Ltd.  All rights reserved.
//

#include <basched.h>
#include <eikenv.h>
#include <coecntrl.h>
#include <eikappui.h>
#include <eikdef.h>
#include <w32std.h>
#include <eikmover.h>
#include <eikmenup.h>
#include <eikmenu.hrh>
#include <eikcmds.hrh>
#include <t32alm.h>
#include <eikdialg.h>
#include <eikdialg.hrh>
#include <eiksndsl.h>
#include <eiksndpy.h>
#include <eikapp.h>
#include <eikdoc.h>
#include <apgwgnam.h>

#include "tear1.hrh"
#include <tear1.rsg>
#include <eikon.rsg>

#define EAlarmEditBox 100

//
// class CTestKeyFilter
//

class CTestKeyFilter : public CCoeControl
	{
public:
	void ConstructL();
private: // framework
	TKeyResponse OfferKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType);
	};

void CTestKeyFilter::ConstructL()
	{
    iEikonEnv->EikAppUi()->AddToStackL(this,ECoeStackPriorityEnvironmentFilter,ECoeStackFlagRefusesFocus|ECoeStackFlagOwnershipTransfered|ECoeStackFlagSharable);
	}

TKeyResponse CTestKeyFilter::OfferKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType)
	{
	TInt code=aKeyEvent.iCode;
	TInt modifiers=aKeyEvent.iModifiers;
    if (aType!=EEventKey)
        return(EKeyWasNotConsumed);
	if (code==CTRL('p') && modifiers&EAllStdModifiers==EModifierFunc|EModifierCtrl)
		{
		const TPtrC nowt;
		iEikonEnv->SendEventToEikonServer(EEventPassword, &nowt, 0);
		return EKeyWasConsumed;
		}
	else if (code==CTRL('a') && modifiers&EAllStdModifiers==EModifierFunc|EModifierCtrl) 
		{
		RAlarmServer almServer;
		if (almServer.Connect())
			User::Panic(_L("TEAR1"),0);
		TTime time;
		time.HomeTime();
		TTime dueTime=time;
		time+=TTimeIntervalSeconds(-10);
		TAlarmMessage message=_L("Session alarm");
		TRequestStatus status;
		TPtrC sound=_L("");
		almServer.SetSessionAlarm(status,time,message,sound,dueTime,RAlarmServer::ESessionTypeTimed);
		almServer.Close();
		User::WaitForRequest(status);
		return EKeyWasConsumed;
		}
	return EKeyWasNotConsumed;
	}

//
// class CMovableWindow
//

const TInt KTitleHeight=21;

class CMovableWindow : public CCoeControl
	{
public:
	CMovableWindow() {}
	~CMovableWindow();
	void ConstructL(CCoeControl* aParent);
	void ActivateL();
	void SizeChangedL();
	inline CEikMover* Mover() const { return iMover; }
	void ChangeMoverText();
	void ChangeMoverActive();
	void ChangeMoverFont();
private:
	void Draw(const TRect& aRect) const;
    TInt CountComponentControls() const;
    CCoeControl* ComponentControl(TInt aIndex) const;
private:
	CEikMover* iMover;
	TBool iTextChanged;
	TBool iFontChanged;
	};

CMovableWindow::~CMovableWindow()
	{
	delete iMover;
	}

void CMovableWindow::ConstructL(CCoeControl* aParent)
	{
	CreateWindowL(aParent);
	EnableDragEvents();
	Window().SetPointerGrab(ETrue);
	iMover=new(ELeave) CEikMover;
	iMover->SetContainerWindowL(*this);
	iMover->SetTextL(_L("Move me!"));
	iMover->SetActive(ETrue);
	}

void CMovableWindow::ActivateL()
	{
	CCoeControl::ActivateL();
	iMover->ActivateL();
	}

void CMovableWindow::SizeChangedL()
	{
	TRect rect=Rect();
	rect.Shrink(1,1);
	rect.iBr.iY=rect.iTl.iY+KTitleHeight;
	iMover->SetRectL(rect);
	}

void CMovableWindow::Draw(const TRect& /*aRect*/) const
	{
	TRect rect=Rect();
	CWindowGc& gc=SystemGc();
	gc.DrawRect(rect);
	gc.SetBrushStyle(CGraphicsContext::ESolidBrush);
	gc.SetBrushColor(KRgbWhite);
	gc.SetPenStyle(CGraphicsContext::ENullPen);
	rect.Shrink(1,1);
	gc.DrawRect(rect);
	}

TInt CMovableWindow::CountComponentControls() const
    {
    return(1);
    }

void CMovableWindow::ChangeMoverText()
	{
	TPtrC text=_L("Move me!");
	TPtrC altText=_L("Move me now!");
	iTextChanged=!iTextChanged;
	iMover->SetTextL(iTextChanged? altText: text); 
	iMover->DrawNow();
	}

void CMovableWindow::ChangeMoverActive()
	{
	iMover->SetActive(!(iMover->Active()));
	iMover->DrawNow();
	}

void CMovableWindow::ChangeMoverFont()
	{
	iFontChanged=!iFontChanged;
	iMover->SetFont((iFontChanged)? iEikonEnv->AnnotationFont(): NULL);	
	iMover->DrawNow();
	}

CCoeControl* CMovableWindow::ComponentControl(TInt /*aIndex*/) const
    {			 
    return(iMover);
    }

//
// class CSpriteControl
//

class CSpriteControl : public CCoeControl
	{
public:
	CSpriteControl(RWsSession& aWs);
	~CSpriteControl();
	void ConstructL();
    void HandlePointerEventL(const TPointerEvent& aPointerEvent);
private:
	RWsSprite iSprite;
	};

CSpriteControl::CSpriteControl(RWsSession& aWs) : iSprite(aWs)
	{
	}

CSpriteControl::~CSpriteControl()
	{
	iSprite.Close();
	}

void CSpriteControl::ConstructL()
	{
	TPtrC bmpFileName = _L("z:\\system\\test\\ear.mbm");
	CFbsBitmap* bitmap=iEikonEnv->CreateBitmapL(bmpFileName,0);
	TSpriteMember sprite[1];
	sprite[0].iBitmap=bitmap;
	sprite[0].iMaskBitmap=bitmap;
	sprite[0].iInvertMask=ETrue;
	sprite[0].iInterval=0;
	TRAPD(err,iSprite.Construct(*DrawableWindow(), Position(), 0/*flags*/));
	iSprite.AppendMember(sprite[0]); // !! TRAP this too ?
	iSprite.Activate();
	delete bitmap;
	User::LeaveIfError(err);
	}

void CSpriteControl::HandlePointerEventL(const TPointerEvent& aPointerEvent)
	{
	TPoint spritePos=TPoint(50,50);
	TPointerEvent::TType type=aPointerEvent.iType;
	if (type==TPointerEvent::EButton1Down)
		iSprite.SetPosition(spritePos+TPoint(1,1));
	else if (type==TPointerEvent::EButton1Up)
		iSprite.SetPosition(spritePos);
	} 

//
// class CSoundDialog
// 

class CSoundDialog : public CEikDialog
	{
public:
	CSoundDialog(TAlarmSoundName* aSoundName);
	~CSoundDialog();
private: // virtual
    virtual TBool OkToExitL(TInt aKeyCode);
    virtual void PreLayoutDynInitL();
private:
	void LeaveWithErrorL(TInt aError);
private:
	TAlarmSoundName* iSoundName;
	CEikAlarmSoundPlayer* iPlayer;
	};

CSoundDialog::CSoundDialog(TAlarmSoundName* aSoundName)  : iSoundName(aSoundName)
	{
	}

CSoundDialog::~CSoundDialog()
	{
	delete iPlayer;
	}

TBool CSoundDialog::OkToExitL(TInt aKeyCode)
	{
	if (aKeyCode!=EEikBidCancel)
		GetSoundSelectorSound(*iSoundName, ESoundDlgSoundSelector);
	if (aKeyCode==EEikBidCancel)
		{
		if (iPlayer->IsPlaying())
			{
			iPlayer->Stop();
			return EFalse;
			}
		}
	else if (aKeyCode==EEikBidSpace)
		{
		TInt err=0;
		do
			{
			iPlayer->Stop();
			err=iPlayer->Play(iEikonEnv->FsSession(), *iSoundName);
			} while (err == KErrInUse);
		if (err!=KErrNone)
			LeaveWithErrorL(err);
		return EFalse;
		}
	iPlayer->Stop();
	return ETrue;
	}

void CSoundDialog::PreLayoutDynInitL()
	{
	iPlayer=CEikAlarmSoundPlayer::NewL();
	SetSoundSelectorSound(ESoundDlgSoundSelector, *iSoundName);
	}

void CSoundDialog::LeaveWithErrorL(TInt aError)
	{
	iEikonEnv->LeaveWithErrorContext(aError,_L("Sound player"));
	}

//
// class CTestContainer
//

class CTestContainer : public CCoeControl, public MCoeControlObserver
    {
public:
    void ConstructL();
    ~CTestContainer();
	inline CMovableWindow* MovableWindow() const { return iWindow; }
private: // framework
	TKeyResponse OfferKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType);
    void Draw(const TRect& aRect) const;
    TInt CountComponentControls() const;
    CCoeControl* ComponentControl(TInt aIndex) const;
private: // from MCoeControlObserver
    void HandleControlEventL(CCoeControl* aControl,TCoeEvent aEventType);
private: // new functions
    void CreateSpriteControlL();
	void CreateMovableWindowL();
	void CreateSoundSelectorL();
    void HandleSpriteClickL();
private:
    CSpriteControl* iSprite;
	CMovableWindow* iWindow;
	CEikSoundSelector* iSndSel;
    };

void CTestContainer::ConstructL()
    {
    CreateWindowL();
    Window().SetShadowDisabled(ETrue);
    Window().SetBackgroundColor(KRgbGray);
    EnableDragEvents();
    CreateSpriteControlL();
	CreateMovableWindowL();
	CreateSoundSelectorL();
    SetExtentToWholeScreenL();
    ActivateL();
    }

CTestContainer::~CTestContainer()
    {
    delete(iSprite);
	delete iWindow;
	delete iSndSel;
    }

TKeyResponse CTestContainer::OfferKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType)
    {
    if (aType!=EEventKey)
        return(EKeyWasNotConsumed);
    if (aKeyEvent.iCode==CTRL('e'))
        CBaActiveScheduler::Exit();
	for (TInt i=0; i<CountComponentControls();i++)
		{
		TKeyResponse key=ComponentControl(i)->OfferKeyEventL(aKeyEvent, aType);
		if (key==EKeyWasConsumed)
			return key;
		}
	return(EKeyWasNotConsumed);
    }

void CTestContainer::CreateSpriteControlL()
    {
	iSprite=new(ELeave) CSpriteControl(iEikonEnv->WsSession());
	iSprite->SetExtentL(TPoint(50,50), TSize(16,16));
	iSprite->SetContainerWindowL(*this);
	iSprite->SetObserver(this);
 	iSprite->ConstructL();
    }

void CTestContainer::CreateMovableWindowL()
	{
	iWindow=new(ELeave) CMovableWindow;
	iWindow->ConstructL(this);
	iWindow->SetExtentL(TPoint(100,100), TSize(200,100));
	}

void CTestContainer::CreateSoundSelectorL()
	{
	iSndSel=new(ELeave) CEikSoundSelector;
	iSndSel->SetContainerWindowL(*this);
	iSndSel->ConstructL();
	iSndSel->SetExtentL(TPoint(400,100), iSndSel->MinimumSize());
	}

void CTestContainer::HandleControlEventL(CCoeControl* /*aControl*/,TCoeEvent /*aEventType*/)
    {
    }

void CTestContainer::HandleSpriteClickL()
    {
    iEikonEnv->InfoMsg(_L("Ear clicked"));
    }

TInt CTestContainer::CountComponentControls() const
    {
    return(3);
    }

CCoeControl* CTestContainer::ComponentControl(TInt aIndex) const
    {
	if (aIndex==0)
		return(iSprite);
	else if (aIndex==1) 
		return(iWindow);
	else
		return iSndSel;
    }

void CTestContainer::Draw(const TRect& /*aRect*/) const
    {
    iEikonEnv->FillTexturedRect(Rect());
    }

//
// CButAppUi
//

class CButAppUi : public CEikAppUi
    {
public:
    ~CButAppUi();
    void ConstructL();
public: // menu stuff
	virtual void DynInitMenuPaneL(TInt aMenuId,CEikMenuPane* aMenuPane);
protected:
private: // framework
	virtual void HandleCommandL(TInt aCommand);
private:
// Alarm functions
	void SetAlarmL(TInt aSeconds, TInt aAlarmNumber);
	void GetAlarmMessageL(TAlarmMessage& aMessage);
	void AlarmSoundDialogL();
	void SetSessionAlarmL();
private:
    CTestContainer* iContainer;
	TAlarmSoundName iSound;
	TUint32 iPasswordKey;
	TUint32 iAlarmKey;
	CTestKeyFilter* iKeyFilter;
    };

CButAppUi::~CButAppUi()
    {
	RWindowGroup& groupWin=iEikonEnv->RootWin();
	groupWin.CancelCaptureKey(iPasswordKey);
	groupWin.CancelCaptureKey(iAlarmKey);
    delete(iContainer);
    }

void CButAppUi::ConstructL()
    {
	BaseConstructL();
	iSound=_L("not silent");
    iContainer=new(ELeave) CTestContainer;
    iContainer->ConstructL();
    AddToStackL(iContainer);
	RWindowGroup& groupWin=iEikonEnv->RootWin();
	CTestKeyFilter* filter=new(ELeave) CTestKeyFilter();
	CleanupStack::PushL(filter);
	filter->ConstructL();
	CleanupStack::Pop();
	iPasswordKey=groupWin.CaptureKey(CTRL('p'), EAllStdModifiers, EModifierFunc|EModifierCtrl);
	iAlarmKey=groupWin.CaptureKey(CTRL('a'), EAllStdModifiers, EModifierFunc|EModifierCtrl);
    }

void CButAppUi::DynInitMenuPaneL(TInt aMenuId,CEikMenuPane* aMenuPane)
	{
	if (aMenuId==R_TEAR1_MENU_MOVER)
		{
		if (iContainer->MovableWindow()->Mover()->Active())	// !! yuck
			aMenuPane->SetItemButtonState(ETear1CmdActive,EEikMenuItemSymbolOn);
		}
    }

void CButAppUi::HandleCommandL(TInt aCommand)
	{
	switch (aCommand)
		{
	case ETear1CmdText:
		iContainer->MovableWindow()->ChangeMoverText();
		break;
	case ETear1CmdActive:
		iContainer->MovableWindow()->ChangeMoverActive();
		break;
	case ETear1CmdFont:
		iContainer->MovableWindow()->ChangeMoverFont();
		break;
	case ETear1CmdAlarmBefore:
		SetAlarmL(-10, 1);
		break;
	case ETear1CmdAlarmAfter:
		SetAlarmL(65, 2);
		break;
	case ETear1CmdSessionAlarm:
		SetSessionAlarmL();
		break;
	case ETear1CmdAlarmSound:
		AlarmSoundDialogL();
		break;
	case ETear1CmdKill:
		User::Exit(KErrGeneral);
		break;
	case ETear1CmdNotifierAlert11:
	case ETear1CmdNotifierAlert12:
	case ETear1CmdNotifierAlert21:
	case ETear1CmdNotifierAlert22:
	case ETear1CmdNotifierAlertDefault1:
	case ETear1CmdNotifierAlertDefault2:
		{
		RNotifier notifier;
		notifier.Connect();
		TInt button=0;
		TRequestStatus status;
		switch (aCommand)
			{
		case ETear1CmdNotifierAlert11:
			notifier.Notify(_L("This is a one line notifier"), _L(""), _L("Button one"), _L(""), button, status);
			break;
		case ETear1CmdNotifierAlert12:
			notifier.Notify(_L("This is a one line notiifer"), _L(""), _L("Button one"), _L("Button two"), button, status);
			break;
		case ETear1CmdNotifierAlert21:
			notifier.Notify(_L("This is a two line notifier"), _L("This is the second line"), _L("Button one"), _L(""), button, status);
			break;
		case ETear1CmdNotifierAlert22:
			notifier.Notify(_L("This is a two line notifier"), _L("This is the second line"), _L("Button one"), _L("Button two"), button, status);
			break;
		case ETear1CmdNotifierAlertDefault1:
			notifier.Notify(_L("Default one button text"), TPtrC(), TPtrC(), TPtrC(), button, status);
			break;
		case ETear1CmdNotifierAlertDefault2:
			notifier.Notify(_L("Default two button text"), _L("Button one has default text"), TPtrC(), _L("Button two"), button, status);
			break;
			}
		User::WaitForRequest(status);
		notifier.Close();
		TBuf<40> msg;
		msg.Format(_L("Button %d pressed"), button+1);
		iEikonEnv->InfoMsg(msg);
		}
		break;
	case ETear1CmdNotifierInfoPrint:
		User::InfoPrint(_L("Notifier info print"));
		break;
	case EEikCmdExit:
		CBaActiveScheduler::Exit();
	default:
		break;
		}
	}

void CButAppUi::AlarmSoundDialogL()
	{
	CSoundDialog* dialog=new(ELeave) CSoundDialog(&iSound);
	dialog->ExecuteLD(R_TEAR1_DIALOG);
	}

void CButAppUi::SetAlarmL(TInt aSeconds, TInt aAlarmNumber)
	{
	RAlarmServer almServer;
	if (almServer.Connect())
		User::Panic(_L("TEAR1"),0);
	iEikonEnv->InfoMsg(almServer.FullName());
	TTime time;
	time.HomeTime();
	time+=TTimeIntervalSeconds(aSeconds);
	TAlarmMessage message=_L("Hello world!  This is a very long alarm message to test the message splitting algorithm.  The only question is - has it worked?");
	GetAlarmMessageL(message);
	almServer.SetClockAlarm(aAlarmNumber,time,message,iSound,EAlarmClockOnce);
	almServer.Close();
	}

void CButAppUi::GetAlarmMessageL(TAlarmMessage& aMessage)
	{
	CEikDialog* dialog = new(ELeave) CEikDialog;
	dialog->ConstructAutoDialogLC(EEikDialogFlagWait, R_EIK_BUTTONS_CANCEL_OK);
	dialog->SetTitleL(_L("Enter alarm message text"));
	dialog->AddAutoTextEditorL(_L("Message"), EAlarmEditBox, 0, 30, 1, &aMessage);
	dialog->RunLD();
	}   

void CButAppUi::SetSessionAlarmL()
	{
	RAlarmServer almServer;
	if (almServer.Connect())
		User::Panic(_L("TEAR1"),0);
	TTime time;
	time.HomeTime();
	TTime dueTime=time;
	time+=TTimeIntervalSeconds(-10);
	TAlarmMessage message=_L("Session alarm");
	TRequestStatus status;
	almServer.SetSessionAlarm(status,time,message,iSound,dueTime,RAlarmServer::ESessionTypeTimed);
	almServer.Close();
	User::WaitForRequest(status);
	}
    
//
// CButDocument
//

class CButDocument : public CEikDocument
	{
public:
	CButDocument(CEikApplication& aApp): CEikDocument(aApp) { }
public: // virtual from CEikDocument
	virtual void UpdateTaskNameL(CApaWindowGroupName* aWgName);
private: // from CApaDocument
	CEikAppUi* CreateAppUiL();
	};

void CButDocument::UpdateTaskNameL(CApaWindowGroupName* aWgName)
	{
	aWgName->SetCaptionL(_L("Test alarms and notifiers"));
	}

CEikAppUi* CButDocument::CreateAppUiL()
	{
    return(new(ELeave) CButAppUi);
	}

//
// CButApplication
//

class CButApplication : public CEikApplication
	{
private: // from CApaApplication
	CApaDocument* CreateDocumentL();
	TUid AppDllUid() const;
	};

CApaDocument* CButApplication::CreateDocumentL()
	{
	return(new(ELeave) CButDocument(*this));
	}

const TUid KUidButApp={218};

TUid CButApplication::AppDllUid() const
	{
	return(KUidButApp);
	}

//
// EXPORTed functions
//

EXPORT_C CApaApplication* NewApplication()
	{
	return(new CButApplication);
	}

GLDEF_C TInt E32Dll(TDllReason)
	{
	return(KErrNone);
	}
