diff -r 000000000000 -r 2f259fa3e83a uifw/AvKon/src/AknSkinnableClock.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/uifw/AvKon/src/AknSkinnableClock.cpp Tue Feb 02 01:00:49 2010 +0200 @@ -0,0 +1,632 @@ +/* +* Copyright (c) 2006-2008 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: Implementation for skinnable clock. +* +*/ + + +// SYSTEM INCLUDE FILES +#include +#include +#include +#include +#include +#include +#include +#include + +#include +// USER INCLUDE FILES +#include "AknUtils.h" +#include "AknSkinnableClock.h" +#include "AknSkinnableClockFace.h" +#include "aknconsts.h" +#include "AknDef.h" +#include "AknStatuspaneUtils.h" +#include "layoutmetadata.cdl.h" + +#include + +// LOCAL CONSTANTS AND MACROS +static const TInt KIntervalTime(60000000); // in microseconds +_LIT( KClockApplication, "\\sys\\bin\\clock.exe" ); + +// MODULE DATA STRUCTURES +class CAknSkinnableClockChangeHandler : public CActive + { + public: // Constructor and destructor + static CAknSkinnableClockChangeHandler* NewL( + CAknSkinnableClock& aClient ) + { + CAknSkinnableClockChangeHandler* self = + new (ELeave) CAknSkinnableClockChangeHandler( aClient ); + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop( self ); + return self; + } + + virtual ~CAknSkinnableClockChangeHandler() + { + Cancel(); + iChangeNotifier.Close(); + } + + private: // From CActive + void DoCancel() + { + iChangeNotifier.LogonCancel(); + // Return value is ignored. + } + + void RunL() + { + if( iStatus.Int() & ( EChangesLocale | EChangesSystemTime ) ) + { + iClient.TimeOrLocaleChanged(); + } + + User::LeaveIfError( iChangeNotifier.Logon(iStatus) ); + SetActive(); + } + + private: // Private constructors + void ConstructL() + { + User::LeaveIfError( iChangeNotifier.Create() ); + User::LeaveIfError( iChangeNotifier.Logon( iStatus ) ); + SetActive(); + } + + CAknSkinnableClockChangeHandler( CAknSkinnableClock& aClient ) + : CActive( EPriorityStandard ), iClient( aClient ) + { + CActiveScheduler::Add( this ); + } + + private: // Data + RChangeNotifier iChangeNotifier; + CAknSkinnableClock& iClient; + }; + +// ============================ MEMBER FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// CAknSkinnableClock::CAknSkinnableClock +// C++ default constructor can NOT contain any code, that +// might leave. +// ----------------------------------------------------------------------------- +// +CAknSkinnableClock::CAknSkinnableClock( const TBool aFormatFromLocale, + const TBool aContextPaneClock ) + { + iFormatFromLocale = aFormatFromLocale; + iContextPaneClock = aContextPaneClock; + + iClockFormat = TLocale().ClockFormat(); + } + +// ----------------------------------------------------------------------------- +// CAknSkinnableClock::ConstructL +// Symbian 2nd phase constructor can leave. +// ----------------------------------------------------------------------------- +// +void CAknSkinnableClock::ConstructL() + { + // We observe foreground events in order + // to stop the clock timer if clock is not visible. + iCoeEnv->AddMessageMonitorObserverL( *this ); + + SetFormatL( iClockFormat ); + + iHandler = CAknSkinnableClockChangeHandler::NewL( *this ); + + SetHitTest( this ); + + // Start timer if necessary. + // Later on, timer is stopped & restarted in MonitorWsMessage. + CAknAppUiBase* base = + static_cast( iEikonEnv->EikAppUi() ); + iInForeground = base->HasFullOrPartialForeground(); + if ( iInForeground ) + { + StartTimer(); + } + + /* Register MHWRMLightObserver */ + iLight = CHWRMLight::NewL( this ); + } + + +// ----------------------------------------------------------------------------- +// CAknSkinnableClock::NewL +// Two-phased constructor. +// ----------------------------------------------------------------------------- +// +EXPORT_C CAknSkinnableClock* CAknSkinnableClock::NewL( + CCoeControl* aContainerWindow, + const TBool aFormatFromLocale, + const TBool aContextPaneClock ) + { + CAknSkinnableClock* self = + new (ELeave) CAknSkinnableClock( aFormatFromLocale, aContextPaneClock ); + CleanupStack::PushL( self ); + self->SetContainerWindowL( *aContainerWindow ); + self->ConstructL(); + CleanupStack::Pop( self ); + AKNTASHOOK_ADDL( self, "CAknSkinnableClock" ); + return self; + } + + +// ----------------------------------------------------------------------------- +// Destructor +// ----------------------------------------------------------------------------- +// +EXPORT_C CAknSkinnableClock::~CAknSkinnableClock() + { + AKNTASHOOK_REMOVE(); + iCoeEnv->RemoveMessageMonitorObserver( *this ); + + delete iHandler; + delete iTimer; + delete iFace; + + delete iLight; + } + + + + +// ----------------------------------------------------------------------------- +// CAknSkinnableClock::UpdateDisplay +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +EXPORT_C void CAknSkinnableClock::UpdateDisplay() + { + DrawDeferred(); + } + + +// ----------------------------------------------------------------------------- +// CAknSkinnableClock::TimeOrLocaleChanged +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CAknSkinnableClock::TimeOrLocaleChanged() + { + TLocale locale; + if ( ( locale.ClockFormat() != iClockFormat ) && iFormatFromLocale ) + { + TRAP_IGNORE( SetFormatL( locale.ClockFormat() ) ); + } + else + { + UpdateDisplay(); + } + } + + +// ----------------------------------------------------------------------------- +// CAknSkinnableClock::SetFormatL +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +EXPORT_C void CAknSkinnableClock::SetFormatL( const TClockFormat aFormat ) + { + if ( Size() != TSize(0,0) ) // Perf optimization + { + delete iFace; + iFace = NULL; + + switch( aFormat ) + { + case EClockAnalog: + { + iFace = CAknSkinnableClockFaceAnalogue::NewL(iContextPaneClock); + break; + } + case EClockDigital: + { + iFace = CAknSkinnableClockFaceDigital::NewL(); + break; + } + }; + } + + iClockFormat = aFormat; + + UpdateDisplay(); + } + + + + + +// ----------------------------------------------------------------------------- +// CAknSkinnableClock::TimerCallback +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TInt CAknSkinnableClock::TimerCallback( TAny* aThis ) + { + CAknSkinnableClock* self = static_cast< CAknSkinnableClock* >( aThis ); + + // Update the clock display + self->UpdateDisplay(); + + // Adjust the timer delay if necessary + TTime time; + time.HomeTime(); + TDateTime dateTime( time.DateTime() ); + if( dateTime.Second() > 0) + { + self->iTimer->Cancel(); + self->iTimer->After( KIntervalTime - + 1000000 * dateTime.Second() - dateTime.MicroSecond()); + } + + return KErrNone; + } + + +// ----------------------------------------------------------------------------- +// CAknSkinnableClock::BufferDisplayMode +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TDisplayMode CAknSkinnableClock::BufferDisplayMode() + { + return EColor16MA; + } + + +// ----------------------------------------------------------------------------- +// CAknSkinnableClock::IsVisibleInContextPane +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TBool CAknSkinnableClock::IsVisibleInContextPane() const + { + CEikStatusPaneBase* statusPane = CEikStatusPaneBase::Current(); + TRect screenRect; + AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::EScreen, screenRect ); + + if ( statusPane && statusPane->PaneCapabilities( + TUid::Uid( EEikStatusPaneUidClock ) ).IsInCurrentLayout() ) + { + return ETrue; + } + else if ( screenRect.Width() > screenRect.Height() && + AknStatuspaneUtils::IdleLayoutActive() ) + { + // in landscape phone/idle shows the clock + return ETrue; + } + + return EFalse; + } + + +// ----------------------------------------------------------------------------- +// CAknSkinnableClock::HandleResourceChange +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CAknSkinnableClock::HandleResourceChange( TInt aType ) + { + if ( aType == KEikDynamicLayoutVariantSwitch ) + { + // Face needs to be resized too... + TRAP_IGNORE( SetFormatL( iClockFormat ) ); + // Setformat calls UpdateDisplay, no need to update it manually. + } + else if ( aType == KAknsMessageSkinChange ) + { + UpdateDisplay(); + } + } + + +// ----------------------------------------------------------------------------- +// CAknSkinnableClock::HitRegionContains +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TBool CAknSkinnableClock::HitRegionContains( + const TPoint &aPoint, + const CCoeControl& /*aControl*/ ) const + { + TBool handleEvent( EFalse ); + + if ( Rect().Contains( aPoint ) ) + { + TVwsViewId idleView; + TInt err = AknDef::GetPhoneIdleViewId( idleView ); + if ( !err ) + { + RWsSession& wsSession = iCoeEnv->WsSession(); + + TApaTaskList taskList( wsSession ); + TApaTask idle( taskList.FindApp( idleView.iAppUid ) ); + + if ( idle.Exists() ) + { + TThreadId id; + wsSession.GetWindowGroupClientThreadId( + wsSession.GetFocusWindowGroup(), id ); + + if ( id == idle.ThreadId() ) + { + handleEvent = ETrue; + } + } + } + } + + return handleEvent; + } + + +// ----------------------------------------------------------------------------- +// CAknSkinnableClock::PositionChanged +// +// ----------------------------------------------------------------------------- +// +EXPORT_C void CAknSkinnableClock::PositionChanged() + { + CCoeControl::PositionChanged(); + } + + +// ----------------------------------------------------------------------------- +// CAknSkinnableClock::Draw +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CAknSkinnableClock::Draw( const TRect& /*aRect*/ ) const + { + + CWindowGc& gc = SystemGc(); + MAknsSkinInstance* skin = AknsUtils::SkinInstance(); + MAknsControlContext* cc = AknsDrawUtils::ControlContext(this); + TRect rect(Rect()); + + gc.SetPenStyle(CGraphicsContext::ENullPen); + gc.SetBrushStyle(CGraphicsContext::ESolidBrush); + gc.SetBrushColor(KRgbWhite); + + AknsDrawUtils::Background(skin, cc, this, gc, rect); + + gc.SetPenStyle(CGraphicsContext::ESolidPen); + gc.SetBrushStyle(CGraphicsContext::ENullBrush); + + TTime homeTime; + homeTime.HomeTime(); + if (iFace) + { + iFace->DrawTimeToBitmapL(rect, gc, homeTime); + } + } + + +// ----------------------------------------------------------------------------- +// CAknSkinnableClock::HandlePointerEventL +// Changes clock format between digital and analog in down event. +// The clock format is saved then to TLocale +// ----------------------------------------------------------------------------- +// +EXPORT_C void CAknSkinnableClock::HandlePointerEventL( + const TPointerEvent& aPointerEvent ) + { + if ( AknLayoutUtils::PenEnabled() ) + { + // Do nothing if dimmed. + if ( IsDimmed() ) + { + return; + } + + // Tactile feedback is played on both down and up event + if ( aPointerEvent.iType == TPointerEvent::EButton1Down + && Rect().Contains( aPointerEvent.iPosition )) + { + MTouchFeedback* feedback = MTouchFeedback::Instance(); + if (feedback) + { + feedback->InstantFeedback( this, + ETouchFeedbackSensitiveButton, + aPointerEvent ); + } + } + + // Start clock application + if ( aPointerEvent.iType == TPointerEvent::EButton1Up + && Rect().Contains( aPointerEvent.iPosition )) + { + MTouchFeedback* feedback = MTouchFeedback::Instance(); + if (feedback) + { + // on up-event, only vibra feedback (no sound) is played + feedback->InstantFeedback( this, + ETouchFeedbackSensitiveButton, + ETouchFeedbackVibra, + aPointerEvent ); + } + RApaLsSession apa; + User::LeaveIfError( apa.Connect() ); + CleanupClosePushL( apa ); + CApaCommandLine* cmdLine = CApaCommandLine::NewLC(); + cmdLine->SetExecutableNameL( KClockApplication ); + cmdLine->SetCommandL( EApaCommandRun ); + User::LeaveIfError( apa.StartApp( *cmdLine ) ); + CleanupStack::PopAndDestroy( 2, &apa ); // cmdLine and apa + } + } + } + + +// ----------------------------------------------------------------------------- +// CAknSkinnableClock::SizeChanged +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CAknSkinnableClock::SizeChanged() + { + TRAP_IGNORE( SetFormatL(iClockFormat) ); + } + + +// --------------------------------------------------------------------------- +// CAknSkinnableClock::MakeVisible +// (other items were commented in a header). +// --------------------------------------------------------------------------- +// +void CAknSkinnableClock::MakeVisible( TBool aVisible ) + { + CCoeControl::MakeVisible( aVisible ); + + if ( !aVisible ) + { + // Stop the timer if this control is made non-visible. + // This control may exist in status pane layouts which + // don't show clock, and in those it's hidden via + // this method, so no need to keep the timer running. + StopTimer(); + } + else if ( iInForeground ) + { + StartTimer(); + } + } + + +// --------------------------------------------------------------------------- +// CAknSkinnableClock::MonitorWsMessage +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CAknSkinnableClock::MonitorWsMessage( const TWsEvent& aEvent ) + { + switch ( aEvent.Type() ) + { + case KAknFullOrPartialForegroundGained: + { + iInForeground = ETrue; + + TRAP_IGNORE( ForegroundGainedL() ); + break; + } + + case KAknFullOrPartialForegroundLost: + { + iInForeground = EFalse; + StopTimer(); + + // Ensure that the clock gets drawn with only skin background. + // This has a similar kind of effect as clearing the redraw + // store at this point, but produces less flicker. + DrawDeferred(); + + break; + } + + default: + break; + } + } + + +// ----------------------------------------------------------------------------- +// CAknSkinnableClock::StartTimer +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CAknSkinnableClock::StartTimer() + { + if ( !iTimer ) + { + iTimer = CPeriodic::New( CActive::EPriorityHigh ); + } + + if ( iTimer && !iTimer->IsActive() ) + { + // Need to update first. + UpdateDisplay(); + + TTime time; + time.HomeTime(); + TDateTime dateTime( time.DateTime() ); + TCallBack callBack( TimerCallback, this ); + + iTimer->Start( + TTimeIntervalMicroSeconds32( + KIntervalTime - 1000000 * dateTime.Second() - dateTime.MicroSecond() ), + TTimeIntervalMicroSeconds32( KIntervalTime ), + callBack ); + } + } + + +// ----------------------------------------------------------------------------- +// CAknSkinnableClock::StopTimer +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CAknSkinnableClock::StopTimer() + { + if ( iTimer && iTimer->IsActive() ) + { + iTimer->Cancel(); + } + + // Ensure the CPeriodic timer stops by destroying it, see Symbian SDK. + delete iTimer; + iTimer = NULL; + } + + +// --------------------------------------------------------------------------- +// CAknSkinnableClock::ForegroundGainedL +// Contains the leaving function calls in the foreground gain situation. +// --------------------------------------------------------------------------- +// +void CAknSkinnableClock::ForegroundGainedL() + { + if ( IsVisible() ) + { + StartTimer(); + } + } + + +void CAknSkinnableClock::LightStatusChanged(TInt aTarget, + CHWRMLight::TLightStatus aStatus) + { + if( aTarget == CHWRMLight::EPrimaryDisplay + || aTarget == CHWRMLight::EPrimaryDisplayAndKeyboard ) + { + if( aStatus == CHWRMLight::ELightOn && iInForeground ) + { + StartTimer(); + } + else if( aStatus == CHWRMLight::ELightOff ) + { + StopTimer(); + } + } + } + +// End of File