diff -r 000000000000 -r 2f259fa3e83a uifw/AvKon/src/akndigitalclock.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/uifw/AvKon/src/akndigitalclock.cpp Tue Feb 02 01:00:49 2010 +0200 @@ -0,0 +1,505 @@ +/* +* 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 digital clock control. +* +*/ + + +// SYSTEM INCLUDE FILES +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// USER INCLUDE FILES +#include "akndigitalclock.h" + +// LOCAL CONSTANTS AND MACROS +static const TInt KIntervalTime( 60000000 ); // in microseconds +_LIT( KTimeFormat, "%-B%J%:1%T%+B" ); + +enum TAknDigitalClockFlags + { + EAknDigitalClockButton1DownReceived = 0x00000001, + EAknDigitalClockInStatusPane = 0x00000002 + }; + +// MODULE DATA STRUCTURES +class CAknDigitalClockChangeHandler : public CActive + { +public: // Constructor and destructor + static CAknDigitalClockChangeHandler* NewL( + CAknDigitalClock& aClient ) + { + CAknDigitalClockChangeHandler* self = + new (ELeave) CAknDigitalClockChangeHandler( aClient ); + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop( self ); + return self; + } + + virtual ~CAknDigitalClockChangeHandler() + { + Cancel(); + iChangeNotifier.Close(); + } + +private: // From CActive + void DoCancel() + { + iChangeNotifier.LogonCancel(); + // Return value is ignored. + } + + void RunL() + { + if( iStatus.Int() & ( EChangesLocale | EChangesSystemTime ) ) + { + iClient.AdjustPositionL(); + iClient.DrawDeferred(); + } + + User::LeaveIfError( iChangeNotifier.Logon( iStatus ) ); + SetActive(); + } + +private: // Private constructors + void ConstructL() + { + User::LeaveIfError( iChangeNotifier.Create() ); + User::LeaveIfError( iChangeNotifier.Logon( iStatus ) ); + SetActive(); + } + + CAknDigitalClockChangeHandler( CAknDigitalClock& aClient ) + : CActive( EPriorityStandard ), iClient( aClient ) + { + CActiveScheduler::Add( this ); + } + +private: // Data + RChangeNotifier iChangeNotifier; + CAknDigitalClock& iClient; + }; + +// ============================ MEMBER FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// CAknDigitalClock::CAknDigitalClock +// C++ default constructor can NOT contain any code, that +// might leave. +// ----------------------------------------------------------------------------- +// +CAknDigitalClock::CAknDigitalClock( TBool aInStatusPane ) + { + if ( aInStatusPane ) + { + iFlags |= EAknDigitalClockInStatusPane; + } + } + + +// ----------------------------------------------------------------------------- +// CAknDigitalClock::ConstructL +// Symbian 2nd phase constructor can leave. +// ----------------------------------------------------------------------------- +// +void CAknDigitalClock::ConstructL() + { + iHandler = CAknDigitalClockChangeHandler::NewL( *this ); + + iColor = KRgbBlack; + + iTimeFormat = TLocale().TimeFormat(); + AdjustPositionL(); + } + + +// ----------------------------------------------------------------------------- +// CAknDigitalClock::NewL +// Two-phased constructor. +// ----------------------------------------------------------------------------- +// +CAknDigitalClock* CAknDigitalClock::NewL( CCoeControl* aContainerWindow, + TBool aInStatusPane ) + { + CAknDigitalClock* self = + new (ELeave) CAknDigitalClock( aInStatusPane ); + CleanupStack::PushL( self ); + self->SetContainerWindowL( *aContainerWindow ); + self->ConstructL(); + CleanupStack::Pop( self ); + AKNTASHOOK_ADDL( self, "CAknDigitalClock" ); + return self; + } + + +// ----------------------------------------------------------------------------- +// Destructor +// ----------------------------------------------------------------------------- +// +CAknDigitalClock::~CAknDigitalClock() + { + AKNTASHOOK_REMOVE(); + MTouchFeedback* feedback = MTouchFeedback::Instance(); + if ( feedback ) + { + feedback->RemoveFeedbackForControl(this); + } + + delete iHandler; + delete iTimer; + } + + +// ----------------------------------------------------------------------------- +// CAknDigitalClock::TimerCallback +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TInt CAknDigitalClock::TimerCallback( TAny* aThis ) + { + CAknDigitalClock* self = static_cast( aThis ); + + self->DrawDeferred(); + + // 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; + } + + +// ----------------------------------------------------------------------------- +// CAknDigitalClock::AdjustPositionL +// This method is called when the time format of the clock is changed. +// In nHD status pane layouts the small digital clock and universal indicator +// pane positions depend on the clock's time format. +// ----------------------------------------------------------------------------- +// +void CAknDigitalClock::AdjustPositionL() + { + TInt format( TLocale().TimeFormat() ); + + if ( iFlags & EAknDigitalClockInStatusPane && + AknStatuspaneUtils::HDLayoutActive() ) + { + CEikStatusPaneBase* sp = CEikStatusPaneBase::Current(); + + if ( sp && format != iTimeFormat ) + { + CCoeControl* indicatorControl = + sp->ContainerControlL( + TUid::Uid( EEikStatusPaneUidIndic ) ); + + CCoeControl* clockControl = + sp->ContainerControlL( + TUid::Uid( EEikStatusPaneUidDigitalClock ) ); + + if ( indicatorControl ) + { + TBool flatLayoutActive( AknStatuspaneUtils::FlatLayoutActive() ); + + TRect spRect; + AknLayoutUtils::LayoutMetricsRect( + AknLayoutUtils::EStatusPane, + spRect ); + + TAknLayoutRect layoutRect; + + if ( !flatLayoutActive ) + { + // Indicator pane position does not change in the + // flat layout. + layoutRect.LayoutRect( + spRect, + format == ETime12 ? + AknLayoutScalable_Avkon::indicator_nsta_pane( 3 ) : + AknLayoutScalable_Avkon::indicator_nsta_pane_cp_24( 3 ) ); + TRect indicRect( layoutRect.Rect() ); + + indicatorControl->SetRect( indicRect ); + } + + if ( clockControl ) + { + layoutRect.LayoutRect( + spRect, + format == ETime12 ? + AknLayoutScalable_Avkon::clock_nsta_pane( + flatLayoutActive ? 3 : 2 ) : + AknLayoutScalable_Avkon::clock_nsta_pane_cp_24( + flatLayoutActive ? 11 : 2 ) ); + TRect clockRect( layoutRect.Rect() ); + + clockControl->SetRect( clockRect ); + } + + sp->DrawNow(); + } + } + } + MTouchFeedback* feedback = MTouchFeedback::Instance(); + if (feedback ) + { + CFeedbackSpec* fbSpec = CFeedbackSpec::New(); + if ( fbSpec ) + { + fbSpec->AddFeedback( ETouchEventStylusDown, + ETouchFeedbackSensitiveButton ); + fbSpec->AddFeedback( ETouchEventStylusUp, + ETouchFeedbackSensitiveButton, + ETouchFeedbackVibra ); + + feedback->SetFeedbackArea( this, + 0, + Rect(), + fbSpec ); + delete fbSpec; + } + } + + iTimeFormat = format; + + } + + +// ----------------------------------------------------------------------------- +// CAknDigitalClock::HandleResourceChange +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CAknDigitalClock::HandleResourceChange( TInt aType ) + { + if ( aType == KAknsMessageSkinChange || + aType == KEikDynamicLayoutVariantSwitch ) + { + DrawDeferred(); + } + return; + } + + +// ----------------------------------------------------------------------------- +// CAknDigitalClock::Draw +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CAknDigitalClock::Draw( const TRect& /*aRect*/ ) const + { + // Draw the time only if text layout has been set and + // the clock timer is running, which means that the clock is on + // full or partial foreground. In case the clock is drawn when it's + // on the background, then only the skin background gets drawn. + if ( iTimeLayoutInUse && iTimer && iTimer->IsActive() ) + { + CWindowGc& gc = SystemGc(); + + TRect rect( Rect() ); + + if ( iFlags & EAknDigitalClockInStatusPane ) + { + MAknsSkinInstance* skin = AknsUtils::SkinInstance(); + MAknsControlContext* cc = AknsDrawUtils::ControlContext( this ); + AknsDrawUtils::Background( skin, cc, this, gc, Rect() ); + } + + const TInt KMaxTextSize = 6 + KMaxAmPmName + 1; + + TBuf time; + + TAknLayoutText layoutText; + layoutText.LayoutText( rect, iTimeLayout); + + TTime homeTime; + homeTime.HomeTime(); + + TRAP_IGNORE( homeTime.FormatL( time, KTimeFormat ) ); + + // Before drawing do the arabic indic digit etc. conversions + AknTextUtils::DisplayTextLanguageSpecificNumberConversion( time ); + + // Finally draw. + layoutText.DrawText( gc, time, ETrue, iColor); + } + } + + +// ----------------------------------------------------------------------------- +// CAknDigitalClock::HandlePointerEventL +// Starts clock application in down event. +// ----------------------------------------------------------------------------- +// +void CAknDigitalClock::HandlePointerEventL( const TPointerEvent& aPointerEvent ) + { + CAknControl:: HandlePointerEventL( aPointerEvent ); + + if ( AknLayoutUtils::PenEnabled() ) + { + // Do nothing if dimmed. + if ( IsDimmed() || + Window().IsFaded() ) + { + return; + } + + TRect rect( Rect() ); + + // Currently the small digital clock pane and universal + // indicator pane are regarded as one touch responsive area from + // which the universal indicator popup should open on tap, + // so upon pointer up event it must be checked here if + // the down event happened inside this control, but the up event + // inside indicator pane area. + TRect indicatorRect( 0, 0, 0, 0 ); + + if ( iFlags & EAknDigitalClockInStatusPane && + aPointerEvent.iType == TPointerEvent::EButton1Up ) + { + CEikStatusPaneBase* sp = CEikStatusPaneBase::Current(); + + if ( sp ) + { + CCoeControl* indicatorPane = sp->ContainerControlL( + TUid::Uid( EEikStatusPaneUidIndic ) ); + if ( indicatorPane ) + { + indicatorRect = + TRect( indicatorPane->PositionRelativeToScreen(), + indicatorPane->Size() ); + } + } + } + + if ( aPointerEvent.iType == TPointerEvent::EButton1Down && + rect.Contains( aPointerEvent.iPosition ) ) + { + // Set flag that down event was inside the clock. + iFlags |= EAknDigitalClockButton1DownReceived; + + // tactile feedback is done with SetFeedbackArea + } + else if ( aPointerEvent.iType == TPointerEvent::EButton1Up && + ( ( iFlags & EAknDigitalClockButton1DownReceived && + rect.Contains( aPointerEvent.iPosition ) ) || + ( indicatorRect.Contains( aPointerEvent.iParentPosition ) ) ) ) + { + // Launch the universal indicator popup. + CAknSmallIndicator* indicatorNotifier = + CAknSmallIndicator::NewLC( TUid::Uid( 0 ) ); + indicatorNotifier->HandleIndicatorTapL(); + CleanupStack::PopAndDestroy( indicatorNotifier ); + + // Up event received, reset button down flag. + iFlags &= ( ~EAknDigitalClockButton1DownReceived ); + } + } + } + + +// ----------------------------------------------------------------------------- +// CAknDigitalClock::SetColor +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CAknDigitalClock::SetColor( TRgb aColor ) + { + iColor = aColor; + } + + +// ----------------------------------------------------------------------------- +// CAknDigitalClock::SetTimeLayout +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CAknDigitalClock::SetTimeLayout( TAknTextLineLayout aTimeLayout ) + { + iTimeLayout = aTimeLayout; + iTimeLayoutInUse = ETrue; + } + + +// ----------------------------------------------------------------------------- +// CAknDigitalClock::ClearTimeLayout +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CAknDigitalClock::ClearTimeLayout() + { + iTimeLayoutInUse = EFalse; + } + + +// ----------------------------------------------------------------------------- +// CAknDigitalClock::StartTimer +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CAknDigitalClock::StartTimer() + { + if ( !iTimer ) + { + iTimer = CPeriodic::New( CActive::EPriorityHigh ); + } + + if ( iTimer && !iTimer->IsActive() ) + { + TTime time; + time.HomeTime(); + TDateTime dateTime( time.DateTime() ); + TCallBack callBack( TimerCallback, this ); + + iTimer->Start( TTimeIntervalMicroSeconds32( + KIntervalTime - 1000000 * dateTime.Second() - dateTime.MicroSecond() ), + TTimeIntervalMicroSeconds32( KIntervalTime ), callBack ); + + DrawDeferred(); + } + } + + +// ----------------------------------------------------------------------------- +// CAknDigitalClock::StopTimer +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CAknDigitalClock::StopTimer() + { + if ( iTimer && iTimer->IsActive() ) + { + iTimer->Cancel(); + } + + // Ensure that the CPeriodic timer stops by destroying it, see Symbian SDK. + delete iTimer; + iTimer = NULL; + } + +// End of File