uifw/AvKon/src/akndigitalclock.cpp
changeset 0 2f259fa3e83a
child 4 8ca85d2f0db7
--- /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 <AknControl.h>
+#include <AknUtils.h>
+#include <AknsDrawUtils.h>
+#include <AknLayoutFont.h>
+#include <AknStatuspaneUtils.h>
+#include <aknlayoutscalable_avkon.cdl.h>
+#include <eikspane.h>
+#include <AknSmallIndicator.h>
+#include <touchfeedback.h>
+#include <AknTasHook.h>
+
+// 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<CAknDigitalClock*>( 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<KMaxTextSize> 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