// EIKALMCT.CPP
//
// Copyright (c) 1997-1999 Symbian Ltd.  All rights reserved.
//

#include "eikalmct.h"
#include <eikenv.h>
#include <eiklbbut.h>
#include <eikcmbut.h>
#include <eikctgrp.h>
#include <eikspace.h>
#include <eikclock.h>
#include <eikon.rsg>
#include <eiksrv.rsg>
#include <eiklabel.h>
#include "eikalsup.h"
#include <coealign.h>
#include <eikdutil.h>
#include "eiksrv.pan"
#include <eikcolor.h>
#include <barsread.h>
#include <eikdialg.hrh> // button ids
#include <bautils.h>    
#include <eiksvdef.h>
#include <eiktxtut.h>
#include <eikappui.h>
#include <e32hal.h>
#include <eiksrv.h>

const TInt KAlarmMaxCharInTitle=32;
const TInt KAlarmMaxCharsPerLine=64;
const TInt KAlarmButtonMargin=5;
const TInt KAlarmInfoTopMargin=2;
const TInt KAlarmDateTimeTextMargin=2;
const TInt KAlarmInfoRightMargin=5;
const TInt KAlarmInfoLeftMargin=5;
const TInt KAlarmInfoTextBorder=8;


//
// CEikAlarmControlChangeNotifier class
//

CEikAlarmControlChangeNotifier::CEikAlarmControlChangeNotifier(CEikAlarmControlDateTime* aClient)
: CActive(EPriorityStandard),
  iClient(aClient)
	//
	// c'tor
	//
	{
	CActiveScheduler::Add(this);
	}

CEikAlarmControlChangeNotifier::~CEikAlarmControlChangeNotifier()
	//
	// d'tor
	//
	{
	Cancel();
	}

void CEikAlarmControlChangeNotifier::ConstructL()
	//
	// 2nd phase construction
	//
	{
	TInt err=iChangeNotifier.Create();
	if (err==KErrNone)
		err=Logon();
	User::LeaveIfError(err);
	}

TInt CEikAlarmControlChangeNotifier::Logon()
	//
	// logon to the change notifier
	//
	{
	SetActive();
	return iChangeNotifier.Logon(iStatus);
	}

void CEikAlarmControlChangeNotifier::DoCancel()
	{
	iChangeNotifier.LogonCancel();
	}

void CEikAlarmControlChangeNotifier::RunL()
	//
	// Change has occurred
	//
	{
	TInt changes=iStatus.Int();
	if (changes<KErrNone)
		User::Leave(changes);
	if (changes&EChangesMidnightCrossover)
		iClient->UpdateDate();
	if (changes&EChangesPowerStatus)
		{
		// switch the backlight off if necessary
		TSupplyInfoV1Buf sbuf;
		UserHal::SupplyInfo(sbuf);
		TSupplyInfoV1& supplyInfo=*(TSupplyInfoV1*)sbuf.Ptr();
		if (supplyInfo.iMainBatteryStatus<=EVeryLow && !supplyInfo.iExternalPowerPresent)
			UserHal::SetBacklightOn(EFalse);
		}
	User::LeaveIfError(Logon());
	}

//
// CEikAlarmControlDateTime class
//

const TInt KMaxDateLength=40;

CEikAlarmControlDateTime::CEikAlarmControlDateTime()

	//
	// c'tor
	//
	{
	iBorder=TEikBorder(TEikBorder::ENone);
	iContext=this;
	iBrushStyle=CGraphicsContext::ESolidBrush;
	iBrushColor=KRgbDarkGray;
	}

CEikAlarmControlDateTime::~CEikAlarmControlDateTime()
	//
	// d'tor
	//
	{
	delete iDigitalClock;
	delete iChangeNotifier;
	}

void CEikAlarmControlDateTime::ConstructL()
	//
	// 2nd phase construction
	//
	{
	// digital clock
	iDigitalClock=new(ELeave) CEikClock;
	iDigitalClock->SetContainerWindowL(*this);
	TResourceReader reader;
	iCoeEnv->CreateResourceReaderLC(reader, R_EIKALARM_DIGITAL_CLOCK);
	iDigitalClock->ConstructFromResourceL(reader);
	CleanupStack::PopAndDestroy(); // reader
	// change notifier
	iChangeNotifier=new(ELeave) CEikAlarmControlChangeNotifier(this);
	iChangeNotifier->ConstructL();
	}

void CEikAlarmControlDateTime::UpdateDate()
	//
	// Update components to present time/date
	//
	{
	//	Deprecated
	}

TSize CEikAlarmControlDateTime::MinimumSize()
	{
	return iDigitalClock->MinimumSize();
	}

TInt CEikAlarmControlDateTime::CountComponentControls() const
	{
	return 1;
	}

CCoeControl* CEikAlarmControlDateTime::ComponentControl(TInt aIndex) const
	{
	switch (aIndex)
		{
	case 0:
		return iDigitalClock;
	default:
		return NULL;
		}
	}

void CEikAlarmControlDateTime::SizeChangedL()
	//
	// layout the components
	//
	{
	iDigitalClock->SetRectL(Rect());
	}

void CEikAlarmControlDateTime::Draw(const TRect& /*aRect*/) const
	//
	// Draw background
	//
	{
	CGraphicsContext& gc=SystemGc();
	ResetGc();
	gc.SetPenStyle(CGraphicsContext::ENullPen);
	gc.DrawRect(Rect());
	}

//
// CEikAlarmControlTime class
//

const TInt KMaxCityInfoLength=KMaxCityName+KMaxCountryName+1; 

CEikAlarmControlTime::CEikAlarmControlTime()
	//
	// default c'tor
	//
	{
	}

CEikAlarmControlTime::~CEikAlarmControlTime()
	//
	// d'tor
	//
	{
	delete iAnalogClock;
	delete iDateTime;
	delete iCityInfo;
	if (iWorldServer.Handle()!=0)
		iWorldServer.Close();
	}          

void CEikAlarmControlTime::ConstructL()
	{
	// analog clock
	iAnalogClock=new(ELeave) CEikClock;
	iAnalogClock->SetContainerWindowL(*this);
	TResourceReader reader;
	iCoeEnv->CreateResourceReaderLC(reader, R_EIKALARM_ANALOG_CLOCK);
	iAnalogClock->ConstructFromResourceL(reader);
	CleanupStack::PopAndDestroy(); // reader
	// digital clock and date
	iDateTime=new(ELeave) CEikAlarmControlDateTime;
	iDateTime->SetContainerWindowL(*this);
	iDateTime->ConstructL();
	// city info
	iCityInfo=new(ELeave) CEikLabel;
	iCityInfo->SetContainerWindowL(*this);
	iCityInfo->SetBufferReserveLengthL(KMaxCityInfoLength);
	iCityInfo->SetFont(iEikonEnv->LegendFont());
	iCityInfo->SetAlignment(EHCenterVCenter);
	}

TInt CEikAlarmControlTime::MinimumWidth()
	{
	return iAnalogClock->MinimumSize().iWidth;      
	}

void CEikAlarmControlTime::UpdateDate()
	{
	iDateTime->UpdateDate();
	}

void CEikAlarmControlTime::UpdateCityInfo()
	//
	// Update the home city and country labels
	//
	{
	TBuf<KMaxCityInfoLength> cityInfo;
	TInt err=KErrNone;
	if (iWorldServer.Handle()==0) // not connected
		err=KErrServerTerminated/*iWorldServer.Connect()*/; // !! hangs forever
	if (err==KErrNone)
		{
		TWorldId worldId;
		err=iWorldServer.Home(worldId);
		if (err==KErrNone)
			{
			TCityData cityData;
			err=iWorldServer.CityData(cityData, worldId);
			if (err==KErrNone)
				{
				cityInfo.Append(cityData.iCity);
				cityInfo.Append('\n');
				cityInfo.Append(cityData.iCountry);
				}
			}
		}
	iCityInfo->SetTextL(cityInfo);
	if (IsActivated())
		iCityInfo->DrawNow();
	}

void CEikAlarmControlTime::SizeChangedL()
	{
	// layout the components
	// date and digital clock
	TSize dateTimeSize=iDateTime->MinimumSize();
	dateTimeSize.iWidth=MinimumWidth();
	iDateTime->SetExtentL(iPosition, dateTimeSize);
	// analog clock
	TSize analogClockSize=iAnalogClock->MinimumSize();
	TPoint analogClockPos(iPosition.iX+(iSize.iWidth-analogClockSize.iWidth)/2, iPosition.iY+dateTimeSize.iHeight+(iSize.iHeight-dateTimeSize.iHeight-analogClockSize.iHeight)/2);
	iAnalogClock->SetExtentL(analogClockPos, analogClockSize);
	// city info
	TSize cityInfoSize=iCityInfo->MinimumSize();
	TPoint cityInfoPos(analogClockPos+TPoint(0, analogClockSize.iHeight));
	iCityInfo->SetExtentL(cityInfoPos, cityInfoSize);
	}

TInt CEikAlarmControlTime::CountComponentControls() const
	{
	return 3;
	}

CCoeControl* CEikAlarmControlTime::ComponentControl(TInt aIndex) const
	{
	switch (aIndex)
		{
	case 0:
		return iAnalogClock;
	case 1:
		return iDateTime;
	case 2:
	default:
		return iCityInfo;
		}
	}

void CEikAlarmControlTime::Draw(const TRect& /*aRect*/) const
	{
	CGraphicsContext& gc=SystemGc();
	gc.SetPenStyle(CGraphicsContext::ENullPen);
	gc.DrawRect(Rect());
	} 

//
// CEikAlarmControlInfo class
//

CEikAlarmControlInfo::CEikAlarmControlInfo()
	{
	iBorder=TEikBorder(TEikBorder::ESingleGray);
	iFont=iEikonEnv->NormalFont();
	}

CEikAlarmControlInfo::~CEikAlarmControlInfo()
	{
	for (TInt i=EFirst; i<ELast; i++)
		delete iLabels[i];
	}

void CEikAlarmControlInfo::ConstructL()
	{
	TRgb backColor=iEikonEnv->ControlColor(EEikColorWindowBackground,*this); // KEikAlarmControlInfoBackGroundColor
	Window().SetBackgroundColor(backColor);
    iContext=this;
	iBrushStyle=CGraphicsContext::ESolidBrush;
	iBrushColor=backColor;
	TInt reserveLength[ELast] = { KAlarmMaxCharsPerLine, KMaxAlarmMessage, KAlarmMaxCharsPerLine };
	for (TInt i=EFirst; i<ELast; i++)
		{
		iLabels[i]=new(ELeave) CEikLabel();
		iLabels[i]->SetContainerWindowL(*this);
		iLabels[i]->SetBufferReserveLengthL(reserveLength[i]); 
		iLabels[i]->SetAlignment(EHCenterVCenter);
		iLabels[i]->SetTextL(TPtrC());
		iLabels[i]->SetFont(iFont);
		}
	}

TInt CEikAlarmControlInfo::CountComponentControls() const
	{
	return ELast;
	}

CCoeControl* CEikAlarmControlInfo::ComponentControl(TInt aIndex) const
	{
	__ASSERT_DEBUG((aIndex>=EFirst && aIndex<ELast), Panic(EEikServPanicNoSuchLabelInAlarm));
	return iLabels[aIndex];
	}

void CEikAlarmControlInfo::SetSoundOff()
	//
	// Change display info to indicate alarm sound is off
	//
	{
	TBuf<KAlarmMaxCharsPerLine> buf;
	iEikonEnv->ReadResource(buf, R_EIKALARM_ALARM_SOUND_OFF);
	SetLabelText(ESnooze, buf);
	}

void CEikAlarmControlInfo::SetManyDueAlarms()
	{
	// Deprecated
	}

void CEikAlarmControlInfo::SetNoSoundToPlay(TSilentType aSilentType)
	{
	TInt resId=R_EIKALARM_ALARM_IS_SILENT;
	if (aSilentType==EAlarmSilenced)
		resId=R_EIKALARM_ALARM_SILENCED;
	TBuf<KAlarmMaxCharsPerLine> buf;
	iEikonEnv->ReadResource(buf, resId);
	SetLabelText(ESnooze, buf);
	}

void CEikAlarmControlInfo::SetNoMemoryToSnooze()
	{
	// iEikonEnv->InfoMsg(R_EIKALARM_NO_SNOOZE_MEMORY);     // Deprecated
	}

void CEikAlarmControlInfo::SetQuietPeriodTimeEnd(TTime aDeferUntil)
	{
	TBuf<KAlarmMaxCharsPerLine> temp;
	iEikonEnv->ReadResource(temp, R_EIKALARM_ALARM_OFF_UNTIL);
	TBuf<KAlarmMaxCharsPerLine> buf;
	TRAPD(err, aDeferUntil.FormatL(buf, temp));
	if (err)
		;// !! do something
	SetLabelText(ESnooze, buf);
	}

void CEikAlarmControlInfo::SetPauseSoundTime(TInt aMinutes)
	{
	TBool visible=(aMinutes>0);
	if (!visible)
		SetLabelText(ESnooze, TPtrC());
	else
		{
		TBuf<KAlarmMaxCharsPerLine> buf;
		if (aMinutes==1)
			iEikonEnv->ReadResource(buf, R_EIKALARM_SNOOZED_FOR_ONE_MINUTE);
		else
			{
			TBuf<KAlarmMaxCharsPerLine> temp;
			iEikonEnv->ReadResource(temp, R_EIKALARM_SNOOZED_FOR);
			buf.Format(temp, aMinutes);
			}
		SetLabelText(ESnooze, buf);
		}
	}

void CEikAlarmControlInfo::SetAlarm(const TAlarmInfo& aAlarm, const TDesC& aOwner)
	{
	TInt resId=(aAlarm.iType==EAlarmTypeDay)? R_EIKALARM_UNTIMED_ALARM_DUE : R_EIKALARM_TIMED_ALARM_DUE ;
	TBuf<KAlarmMaxCharsPerLine> temp;
	iEikonEnv->ReadResource(temp, resId);
	TBuf<KAlarmMaxCharsPerLine> buf;
	const TTime* time=&(aAlarm.iDueTime);
	if (aAlarm.iDueTime==Time::NullTTime())
		time=&(aAlarm.iAlarmTime);
	TRAPD(err,time->FormatL(buf, temp)); 
	if (err)
		;// !! do something !!
	buf.Append(aOwner);
	TextUtils::ClipToFit(buf, *iFont, iTextRect.Width());
	SetLabelText(EDue, buf);
	SetAndLayoutAlarmMessage(aAlarm.iMessage);
	}

void CEikAlarmControlInfo::SetLabelText(TInt aIndex, const TDesC& aText)
	//
	// Set label[aIndex] to the given text
	//
	{
	__ASSERT_DEBUG((aIndex>=EFirst && aIndex<ELast), Panic(EEikServPanicNoSuchLabelInAlarm));
	iLabels[aIndex]->SetTextL(aText);       // Won't actually leave since label was pre-allocated
	}

void CEikAlarmControlInfo::SetAndLayoutAlarmMessage(const TAlarmMessage& aMessage)
	//
	// Break up the alarm message into 1, 2 or 3 linas as necessary
	//
	{
	TInt width=iTextRect.Width();
	if (iFont->TextWidthInPixels(aMessage) < width)
		{
		SetLabelText(EMessage, aMessage);
		return;
		}
	// need to do some breaking up
	TInt numOfLines=2;
	TInt messageLength=aMessage.Length();
	TInt firstEnd=DetermineMessageSplit(aMessage, width, 0);
	TInt thirdStart=DetermineMessageSplit(aMessage, width, firstEnd+1);
	if (thirdStart<messageLength)
		numOfLines=3;
	TBuf<KMaxAlarmMessage> buf(aMessage);
	buf[firstEnd]='\n';
	if (numOfLines==3)
		buf[thirdStart]='\n';
	SetLabelText(EMessage, buf);
	}

TInt CEikAlarmControlInfo::DetermineMessageSplit(const TAlarmMessage& aMessage, TInt aWidth, TInt aStart) const
	//
	// return the next split point in the message, starting from aStart
	//
	{
	TInt messageLength=aMessage.Length();
	TInt index=aStart;
	TInt prevIndex=index;
	TInt textWidth=0;
	do
		{
		prevIndex=index;
		for (index=prevIndex+1; index<messageLength; index++)
			{
			if (aMessage[index]==' ')
				break;
			}
		textWidth=iFont->TextWidthInPixels(aMessage.Mid(aStart, index-aStart));
		}
	while ((textWidth <= aWidth) && (index<messageLength-1));
	TBool overflow=(!(textWidth <= aWidth));
	TBool end=(index==messageLength);
	TBool longWord=(prevIndex==aStart && overflow);
	if (end && !overflow) 
		return index;
	// overflow==ETrue to have exited loop
	if (longWord)
		return (aStart+messageLength/3);
	// overflow && !longWord
	return prevIndex;
	}

void CEikAlarmControlInfo::DrawSnoozeLabelNow() const
	{
	iLabels[ESnooze]->DrawNow();
	}

void CEikAlarmControlInfo::DrawAllLabelsNow() const
	{
	for (TInt i=EFirst; i<ELast; i++)
		iLabels[i]->DrawNow();
	}

void CEikAlarmControlInfo::SizeChangedL()
	{
	// layout components
	iTextRect=iBorder.InnerRect(Rect());
	iTextRect.Shrink(KAlarmInfoTextBorder, KAlarmInfoTextBorder);
	TInt rectWidth=iTextRect.Width();
	TInt dueHeight=iLabels[EDue]->MinimumSize().iHeight;
	iLabels[EDue]->SetExtentL(iTextRect.iTl, TSize(rectWidth, dueHeight));
	TInt snoozeHeight=iLabels[ESnooze]->MinimumSize().iHeight;
	TPoint pos(iTextRect.iTl.iX, iTextRect.iBr.iY-snoozeHeight);
	iLabels[ESnooze]->SetExtentL(pos, TSize(rectWidth, snoozeHeight));
	TRect messageRect(iTextRect.iTl+TPoint(0, dueHeight), iTextRect.iBr-TPoint(0, snoozeHeight));
	iLabels[EMessage]->SetRectL(messageRect);
	}

void CEikAlarmControlInfo::Draw(const TRect& /*aRect*/) const
	{
	CGraphicsContext& gc=SystemGc();
	TRect rect=Rect();
	iBorder.Draw(gc, rect);
	gc.SetPenStyle(CGraphicsContext::ENullPen);
	EikDrawUtils::ClearBetweenRects(gc, iBorder.InnerRect(rect), iTextRect);
	}


//
// CEikAlarmControl class
//

const TInt KButtonSpacerLength=20;
const TInt KButtonPanelHeight=60;
const TInt KGapBetweenButtonsAndInfo=10;
const TInt KButtonTextTopAndBottomMargin=8;

CEikAlarmControl::CEikAlarmControl(CEikAlmControlSupervisor* aSupervisor, CEikServAppUi* aAppUi) 
: iSupervisor(aSupervisor),
iAppUi(aAppUi)
	//
	// default c'tor
	//
	{
	iBorder=TEikBorder(TEikBorder::EDeepRaised);
	}

CEikAlarmControl::~CEikAlarmControl()
	//
	// d'tor
	//
	{
	delete iButtons;
	delete iTime;
	delete iAlarmInfoView;
	iEikonEnv->RemoveFromStack(this);
	}

void CEikAlarmControl::ConstructL()
	//
	// Create window and components
	//
	{
	CreateWindowL(iAppUi->AlertGroupWin());
	EnableDragEvents();
	SetPointerCapture(ETrue);
    iEikonEnv->EikAppUi()->AddToStackL(this,ECoeStackPriorityAlert+10,ECoeStackFlagRefusesAllKeys|ECoeStackFlagRefusesFocus|ECoeStackFlagSharable);
	Window().SetPointerGrab(ETrue);
    iContext=this;
	iBrushColor=KRgbWhite;
	iBrushStyle=CGraphicsContext::ESolidBrush;
    Window().SetBackgroundColor(iBrushColor);
	// buttons
	iButtons=new(ELeave) CEikControlGroup;
	iButtons->SetContainerWindowL(*this);
	iButtons->ConstructL(CEikControlGroup::EFromTopLeft, CEikControlGroup::ELayHorizontally);
	TInt resIds[3]={R_EIKALARM_LABELED_BUTTON_SNOOZE, R_EIKALARM_LABELED_BUTTON_SILENCE, R_EIKALARM_LABELED_BUTTON_CLEAR};
	TInt butIds[3]={EEikBidSpace, EEikBidOk, EEikBidCancel};
	for (TInt i=0; i<3; i++)
		{
		TResourceReader reader;
		iCoeEnv->CreateResourceReaderLC(reader, resIds[i]);
		CEikLabeledButton*button=new(ELeave) CEikLabeledButton;
		CleanupStack::PushL(button);
		button->SetObserver(this);
		button->ConstructFromResourceL(reader);
		TMargins8& margins=((CEikCommandButton*)button->Button())->Label()->iMargin;
		margins.iTop=margins.iBottom=KButtonTextTopAndBottomMargin;
		TEikGroupControl groupControl(button, butIds[i], 0, TEikGroupControl::EAllowStretch|TEikGroupControl::ESetLength);
		iButtons->AddControlL(groupControl);
		CleanupStack::Pop(); // button
		CleanupStack::PopAndDestroy(); // reader
		}
	for (TInt ii=1; ii<4; ii+=2)
		{
		CEikSpacer* spacer=new(ELeave) CEikSpacer(KButtonSpacerLength, 0, KRgbWhite);
		CleanupStack::PushL(spacer);
		TEikGroupControl groupControl(spacer, 0, KButtonSpacerLength, TEikGroupControl::ESetLength);
		iButtons->InsertControlL(groupControl, ii);
		CleanupStack::Pop(); // spacer
		}
	// clocks, date etc
	iTime=new(ELeave) CEikAlarmControlTime;
    iTime->SetContainerWindowL(*this);
	iTime->ConstructL();
	// info window
	iAlarmInfoView=new(ELeave) CEikAlarmControlInfo;
	iAlarmInfoView->SetContainerWindowL(*this);
	iAlarmInfoView->ConstructL();
	MakeVisible(EFalse);
	SetExtentToWholeScreenL();
	}

void CEikAlarmControl::ShowAlarm()
	{
	if (IsVisible())
		return;
	RWindowGroup& groupWin=iAppUi->AlertGroupWin();
	iExternalKeys[0]=groupWin.CaptureKey(KExternalKey1, KExternalKeyModifierMask, KExternalKeyModifier);
	iExternalKeys[1]=groupWin.CaptureKey(KExternalKey2, KExternalKeyModifierMask, KExternalKeyModifier);
	iExternalKeys[2]=groupWin.CaptureKey(KExternalKey3, KExternalKeyModifierMask, KExternalKeyModifier);
	iExternalKeyUpAndDowns[0]=groupWin.CaptureKeyUpAndDowns(EStdKeyDictaphoneRecord, KExternalKeyModifierMask, KExternalKeyModifier);
	iExternalKeyUpAndDowns[1]=groupWin.CaptureKeyUpAndDowns(EStdKeyDictaphoneStop, KExternalKeyModifierMask, KExternalKeyModifier);
	iExternalKeyUpAndDowns[2]=groupWin.CaptureKeyUpAndDowns(EStdKeyDictaphonePlay, KExternalKeyModifierMask, KExternalKeyModifier);
	iAppUi->BringAlertGroupWinForwards(ETrue);
	DrawableWindow()->SetOrdinalPosition(0);
	ClaimPointerGrab();
	MakeVisible(ETrue);
	iEikonEnv->RouseSleepingDialog(this,ETrue);
    ActivateL();
	}

void CEikAlarmControl::HideAlarm()
	{
	if (!IsVisible())
		return;
	RWindowGroup& groupWin=iAppUi->AlertGroupWin();
	for (TInt i=0; i<3; i++)
		{
		groupWin.CancelCaptureKey(iExternalKeys[i]);
		groupWin.CancelCaptureKeyUpAndDowns(iExternalKeyUpAndDowns[i]);
		}
	iAppUi->BringAlertGroupWinForwards(EFalse);
	MakeVisible(EFalse);
	iEikonEnv->RouseSleepingDialog(this,EFalse);
	}

void CEikAlarmControl::UpdateSoundPauseTimeInterval(TInt aMinutes)
	//
	// Update the visual pause time
	//
	{
	iAlarmInfoView->SetPauseSoundTime(aMinutes);
	iAlarmInfoView->DrawSnoozeLabelNow();
	}

void CEikAlarmControl::UpdateForAlarmServerState(TInt aNewAlarmServerState)
	{
	// The order of the following are important
	// Note that these are always updated because they can change independently
	// of their binary state.
	TInt timePaused=iSupervisor->PauseSoundMinutes();
	if (!timePaused && aNewAlarmServerState&EAlmSvrSoundOff) 
		iAlarmInfoView->SetSoundOff();
	else if (!timePaused && aNewAlarmServerState&EAlmSvrQuietPeriod)
		iAlarmInfoView->SetQuietPeriodTimeEnd(iSupervisor->QuietPeriodEndTime());
	else 
		iAlarmInfoView->SetPauseSoundTime(timePaused);
	if (aNewAlarmServerState==iCurrentAlarmServerState)
		return;
	if (!timePaused && (aNewAlarmServerState&EAlmSvrNoSoundToPlay) && (!(aNewAlarmServerState&EAlmSvrSoundOff))) 
		{
		CEikAlarmControlInfo::TSilentType silent=CEikAlarmControlInfo::ESilentAlarm;
		if (!(iButtons->ControlById(EEikBidOk)->IsDimmed())) // silence pressed
			silent=CEikAlarmControlInfo::EAlarmSilenced;
		iAlarmInfoView->SetNoSoundToPlay(silent);
		}
	if (aNewAlarmServerState&EAlmSvrManyDueAlarms)
		iAlarmInfoView->SetManyDueAlarms();
	if (aNewAlarmServerState&EAlmSvrNoSnoozeMemory)
		iAlarmInfoView->SetNoMemoryToSnooze();
	iAlarmInfoView->DrawSnoozeLabelNow();
	//
	iCurrentAlarmServerState=aNewAlarmServerState;
	CheckSilenceButtonDimmed();
	}

void CEikAlarmControl::CheckSilenceButtonDimmed()
	{
	CCoeControl* silenceButton=iButtons->ControlById(EEikBidOk);
	TBool wasDimmed=silenceButton->IsDimmed();
	TBool newDimmed=iCurrentAlarmServerState&(EAlmSvrQuietPeriod|EAlmSvrSoundOff|EAlmSvrNoSoundToPlay);
	if (wasDimmed!=newDimmed)
		{
		silenceButton->SetDimmed(newDimmed);
		silenceButton->DrawNow();
		}
	}

void CEikAlarmControl::UpdateAlarmInfo(const TAlarmInfo &aAlarm,const TFullName &aOwner)
	{
	iTime->UpdateDate();
	iTime->UpdateCityInfo();
	TBuf<5> formatBuf=_L(" (%S)");
	TBuf<KAlarmMaxCharInTitle> ownerBuf;
	if (aAlarm.iType!=EAlarmTypeClock)
		{
		TPtrC owner=BaflUtils::ExtractAppNameFromFullName(aOwner);
		if (owner.Length())
			ownerBuf.Format(formatBuf ,&owner); 
		}
	iAlarmInfoView->SetAlarm(aAlarm, ownerBuf);
	iAlarmInfoView->DrawAllLabelsNow();
	}

TKeyResponse CEikAlarmControl::OfferKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType)
	{
    if (aType!=EEventKey)
	return(EKeyWasConsumed);
	switch (aKeyEvent.iCode)
		{
	case EKeySpace:
	case KExternalKey1:
	case KExternalKey2:
	case KExternalKey3:
		((CEikCommandButton*)((CEikLabeledButton*)(iButtons->ControlById(EEikBidSpace)))->Button())->Animate();
		iSupervisor->CmdPauseAlarmSound();
		break;
	case EKeyEnter:
		{
		CCoeControl* silenceBut=iButtons->ControlById(EEikBidOk);
		if (!silenceBut->IsDimmed())
			{
			((CEikCommandButton*)((CEikLabeledButton*)silenceBut)->Button())->Animate();
			iSupervisor->CmdSilenceAlarmSound();
			}
		}
		break;
	case EKeyEscape:
		((CEikCommandButton*)((CEikLabeledButton*)(iButtons->ControlById(EEikBidCancel)))->Button())->Animate();
		iSupervisor->CmdAcknowledgeAlarm();
		break;
	case EKeyTab:
		// task away
		iSupervisor->CmdTaskAwayFromAlarm();
		break;
#if defined(_DEBUG)
	case EKeyUpArrow:
		User::Exit(KErrNone); // fake death of Eikon server
		break;
#endif
	default:
		{
		TBuf<2> nudgeChars;
		iEikonEnv->ReadResource(nudgeChars, R_EIK_TBUF_NUDGE_CHARS);
		if (aKeyEvent.iCode==nudgeChars[0])
			iSupervisor->CmdPauseAlarmSound(-1);     
		else if (aKeyEvent.iCode==nudgeChars[1])
			iSupervisor->CmdPauseAlarmSound(1);      
		}
		break;
		}
	return(EKeyWasConsumed);
	}

TInt CEikAlarmControl::CountComponentControls() const
	{
	return 3;
	}

CCoeControl* CEikAlarmControl::ComponentControl(TInt aIndex) const
	{
	switch (aIndex)
		{
	case 0:
		return iButtons;
	case 1:
		return iTime;
	case 2:
		return iAlarmInfoView;
	default:
		return NULL;    
		}
	}

TSize CEikAlarmControl::MinimumSize()
	//
	// MinimumSize is whole screen!
	//
	{
	return iEikonEnv->ScreenDevice()->SizeInPixels();
	}

void CEikAlarmControl::HandleControlEventL(CCoeControl* aControl,TCoeEvent aEventType)
	{
	if (aEventType!=EEventStateChanged || !iSupervisor)
		return;
	TInt id=iButtons->ControlId(aControl);
	switch (id)
		{
	case EEikBidSpace:      // snooze
		iSupervisor->CmdPauseAlarmSound();
		break;
	case EEikBidOk: // silence
		iSupervisor->CmdSilenceAlarmSound();
		break;
	case EEikBidCancel:     // clear
		iSupervisor->CmdAcknowledgeAlarm();
		break;
	default:
		break;
		}
	}

void CEikAlarmControl::SizeChangedL()
	//
	// Layout the components
	//
	{
    TRect rect=iBorder.InnerRect(Rect());
	// time
	TInt timeWidth=iTime->MinimumWidth();
	TRect timeRect(rect.iTl, TSize(timeWidth, rect.Height()));
	iTime->SetRectL(timeRect);
	rect.iTl+=TPoint(timeWidth+KAlarmInfoLeftMargin, KAlarmInfoTopMargin);
	rect.iBr.iX-=KAlarmInfoRightMargin;
	// buttons
	TInt topY=rect.iTl.iY;
	rect.iTl.iY=rect.iBr.iY-KButtonPanelHeight;
	iButtons->SetRectL(rect);
	// info
	rect.iTl.iY=topY;
	rect.iBr.iY-=(KButtonPanelHeight+KGapBetweenButtonsAndInfo);
	iAlarmInfoView->SetRectL(rect);
	}

void CEikAlarmControl::Draw(const TRect& /*aRect*/) const
	//
	// Draw border and background
	//
	{
	TRect rect=Rect();
	CGraphicsContext& gc=SystemGc();
	iBorder.Draw(gc,rect);
	TRect innerRect=iBorder.InnerRect(rect);
	gc.SetPenStyle(CGraphicsContext::ENullPen);
    gc.DrawRect(innerRect);
	}

