// EIKNFYSV.CPP
//
// Copyright (c) 1997-1999 Symbian Ltd.  All rights reserved.
//

#include "eiknfysv.h"
#include <eiksrv.h>
#include "eiksrv.pan"
#include <coemain.h>
#include <eiklabel.h>
#include <eikbtpan.h>
#include <eikcmbut.h>
#include <eiksrv.rsg>
#include <barsread.h>
#include <eikmsg.h>
#include <eikmover.h>

#include "eiksrv.hrh"
#include <eikdialg.hrh>

//
// class CEikServNotifyServer
//

CEikServNotifyServer::CEikServNotifyServer(TInt aPriority) : CServer(aPriority)
	//
	// private c'tor - initialize using NewL()
	//
	{
	__DECLARE_NAME(_S("CEikServNotifyServer"));
	}

CEikServNotifyServer::~CEikServNotifyServer()
	{
	delete iAlert;
	delete iInfoMsg;
	iInfoMsgGroupWin.Close();
	}

CEikServNotifyServer* CEikServNotifyServer::NewL()	
	//
	// static - Create and start the server
	{
	CEikServNotifyServer* server=new(ELeave) CEikServNotifyServer(EActivePriorityIpcEventsHigh);
	server->ConstructL();
	User::LeaveIfError(server->Start());
	return server;
	}

void CEikServNotifyServer::ConstructL()
	//
	// private second phase construction - initialise using NewL()
	//
	{
	iName=__NOTIFIER_NAME.AllocL();

	// notifier alert
	iAlert=new(ELeave) CEikServNotifyAlert();
	iAlert->ConstructL();
	
	// notifier info print
	CEikonEnv* env=CEikonEnv::Static();
	RWsSession wsSession=env->WsSession();
	iInfoMsgGroupWin=RWindowGroup(wsSession);
	User::LeaveIfError(iInfoMsgGroupWin.Construct((TUint32)this));
	iInfoMsgGroupWin.SetOrdinalPosition(0,ECoeWinPriorityAlwaysAtFront-1);
	iInfoMsgGroupWin.EnableReceiptOfFocus(EFalse); // disable key events
	iInfoMsg=new(ELeave) CEikInfoMsgWin(*env);
	iInfoMsg->ConstructL(iInfoMsgGroupWin);
	}

TInt CEikServNotifyServer::DisplayNotifier(const TDesC& aTitle,const TDesC& aLabel, const TDesC& aBut1, const TDesC& aBut2)
	{
	if (iAlert)
		return iAlert->DisplayNotifier(aTitle, aLabel, aBut1, aBut2);
	return KErrNotReady;
	}

void CEikServNotifyServer::DisplayInfoPrint(const TDesC& aDes)
	{
	iInfoMsg->StartDisplay(aDes,EHRightVTop);
	}

CSession* CEikServNotifyServer::NewSessionL(RThread aClient,const TVersion &aVersion) const
	//
	// create a new sesison
	//
	{
	TVersion v(1,0,0); // !! liaise with E32
	if (!User::QueryVersionSupported(v,aVersion))
		User::Leave(KErrNotSupported);
	return new(ELeave) CEikServNotifySession(aClient);
	}

//
// class CEikServNotifySession
//

const TInt KMaxNotifierLabelLength=80;	
const TInt KMaxNotifierButtonLabelLength=20;
const TInt KNotifierLabelGapBetweenLines=5;

CEikServNotifySession::CEikServNotifySession(RThread& aClient) : CSession(aClient)
	//
	// c'tor
	//
	{
	__DECLARE_NAME(_S("CEikServNotifySession"));
	}

void CEikServNotifySession::ServiceL(const RMessage &aMessage)
	//
	// Service requests
	//
	{
	TInt opCode=aMessage.Function();
	switch (opCode)
		{
	case ENotifierNotify:
		DisplayAlert(aMessage);
		break;
	case ENotifierInfoPrint:
		DisplayInfoMsg(aMessage);
		break;
	default:
		aMessage.Complete(KErrNotSupported);
		break;
		}
	}

void CEikServNotifySession::DisplayAlert(const RMessage& aMessage)
	//
	// Display an alert
	//
	{
	TBuf<KMaxNotifierLabelLength> title;
	TBuf<KMaxNotifierLabelLength> label;
	TBuf<KMaxNotifierButtonLabelLength> but1;
	TBuf<KMaxNotifierButtonLabelLength> but2;
	TPckgBuf<TNotifyInfo> pInfo;
	TPckgBuf<TInt> buttonValBuf;
	TRAPD(ret,ReadL(Message().Ptr0(),pInfo));
	if (!ret)
		{
		TNotifyInfo& info=pInfo();
		TRAP(ret,ReadL(info.iLine1,title));
		if (!ret)
			{
			TRAP(ret,ReadL(info.iLine2,label));
			if (!ret)
				{
				TRAP(ret, ReadL(info.iButton1, but1));
				if (!ret)
					{
					TRAP(ret, ReadL(info.iButton2, but2));
					if (!ret)
						{
						TRAP(ret, ReadL(info.iButtonVal, buttonValBuf));
						}
					}
				}
			}
		}
	if (ret)
		aMessage.Panic(__EIKON_SERVER,EEikServPanicNotifyBadDescriptor);
	TInt& buttonVal=buttonValBuf();
	buttonVal=((CEikServNotifyServer*)Server())->DisplayNotifier(title, label, but1, but2);
	TNotifyInfo& info=pInfo();
	TPckg<TInt> buf(buttonVal);
	TRAP(ret, WriteL(info.iButtonVal, buf));
	aMessage.Complete(KErrNone);
	}

void CEikServNotifySession::DisplayInfoMsg(const RMessage& aMessage)
	//
	// Display an info message
	//
	{
	TBuf<80> msg;
	TRAPD(err, ReadL(Message().Ptr0(), msg));
	if (err)
		aMessage.Panic(__EIKON_SERVER,EEikServPanicNotifyBadDescriptor);
	aMessage.Complete(KErrNone);
	((CEikServNotifyServer*)Server())->DisplayInfoPrint(msg);
	}

//
// CEikServNotifyAlert
//

CEikServNotifyAlert::CEikServNotifyAlert()
	//
	// c'tor
	//
	{
	__DECLARE_NAME(_S("CEikServNotifyAlert"));
	}

CEikServNotifyAlert::~CEikServNotifyAlert()
	//
	// d'tor - only delete the button panel not in use, other is same as iButtonPanel deleted in ~CEikDialog
	//
	{
	if (ButtonPanel()==iTwoButtonPanel)
		delete iOneButtonPanel;
	else
		delete iTwoButtonPanel;
	// Title (CEikMover*) has taken ownership of iTitleText
	}

void CEikServNotifyAlert::ConstructL()
	//
	// pre-allocation of sleeping alert dialog
	//
	{
	SetGloballyCapturing(ETrue);
	ConstructSleepingAlertDialogL(R_EIKSERV_NOTIFIER_DIALOG); // constructs with two labels & two buttons
	iTwoButtonPanel=ButtonPanel();
	CreateSingleButtonPanelL();
	iTitleText=HBufC::NewL(KMaxNotifierLabelLength);
	Title()->SetText(iTitleText); // takes ownership - done here in case notifier never displayed
	SetButtonLabelReserveLengthsL();
	CEikonEnv::Static()->AddDialogLikeControlToStackL(this);
	}

void CEikServNotifyAlert::PreLayoutDynInitL()
	{
	}

TBool CEikServNotifyAlert::OkToExitL(TInt aButtonId)
	{
	//
	// Only exit on Ok (Enter) if we have two buttons
	//
	if (aButtonId==EEikBidOk && ButtonPanel()==iOneButtonPanel)
		return EFalse;
	return ETrue;
	}

void CEikServNotifyAlert::CreateSingleButtonPanelL()
	//
	// Create the single button case panel
	//
	{
	iOneButtonPanel=new(ELeave) CEikButtonPanel;
	iOneButtonPanel->SetContainerWindowL(*this);
	iOneButtonPanel->SetObserver(this);
	iOneButtonPanel->SetHorizontal();
    TResourceReader reader;
    iCoeEnv->CreateResourceReaderLC(reader,R_EIKSERV_NOTIFIER_BUTTONS_ONE);
	iOneButtonPanel->ConstructFromResourceL(reader);
	CleanupStack::PopAndDestroy(); // reader
	}

void CEikServNotifyAlert::SetButtonLabelReserveLengthsL()
	//
	// pre-allocate button label lengths to prevent failiyre on SetTextL() later
	//
	{
	CEikLabel* label=STATIC_CAST(CEikCommandButton*,iOneButtonPanel->ButtonById(EEikBidCancel))->Label();
	label->SetBufferReserveLengthL(KMaxNotifierButtonLabelLength);
	label=STATIC_CAST(CEikCommandButton*,iTwoButtonPanel->ButtonById(EEikBidCancel))->Label();
	label->SetBufferReserveLengthL(KMaxNotifierButtonLabelLength);
	label=STATIC_CAST(CEikCommandButton*,iTwoButtonPanel->ButtonById(EEikBidOk))->Label();
	label->SetBufferReserveLengthL(KMaxNotifierButtonLabelLength);
	}

TInt CEikServNotifyAlert::DisplayNotifier(const TDesC& aTitle, const TDesC& aLabel, const TDesC& aBut1, const TDesC& aBut2)
	//
	// Display the appropriate notifier	and return id of button pressed
	//
	{
	// none of the following SetTextL() calls will leave due to pre-allocated buffers
	CEikLabel* label=(CEikLabel*)Control(EESrvNotifyAlertLabel);
	iTitleText->Des().Copy(aTitle);
	Title()->SetText(iTitleText);
	label->SetTextL(aLabel);
	TBool oneButton=ETrue;
	if (aBut2.Length())
		{
		SetButtonPanel(iTwoButtonPanel);
		oneButton=EFalse;
		}
	else
		SetButtonPanel(iOneButtonPanel);
	CEikButtonPanel* butPan=(oneButton)? iOneButtonPanel : iTwoButtonPanel;
	CEikLabel* but1=STATIC_CAST(CEikCommandButton*,butPan->ButtonById(EEikBidCancel))->Label();
	if (aBut1.Length())
		but1->SetTextL(aBut1);
	else  // defaults to language specific "Continue"
		{
		TBuf<40> buf;
		iEikonEnv->ReadResource(buf, R_EIKSRV_TBUF_CONTINUE);
		but1->SetTextL(buf);
		}
	if (!oneButton)
		STATIC_CAST(CEikCommandButton*,butPan->ButtonById(EEikBidOk))->Label()->SetTextL(aBut2);
	if (RouseSleepingDialog())
		return 1; // EEikBidOk
	else
		return 0; // EEikBidCancel
	}

