uifw/AvKon/src/akndigitalclock.cpp
changeset 0 2f259fa3e83a
child 4 8ca85d2f0db7
equal deleted inserted replaced
-1:000000000000 0:2f259fa3e83a
       
     1 /*
       
     2 * Copyright (c) 2006-2008 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Implementation for digital clock control.
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 // SYSTEM INCLUDE FILES
       
    20 #include <AknControl.h>
       
    21 #include <AknUtils.h>
       
    22 #include <AknsDrawUtils.h>
       
    23 #include <AknLayoutFont.h>
       
    24 #include <AknStatuspaneUtils.h>
       
    25 #include <aknlayoutscalable_avkon.cdl.h>
       
    26 #include <eikspane.h>
       
    27 #include <AknSmallIndicator.h>
       
    28 #include <touchfeedback.h>
       
    29 #include <AknTasHook.h>
       
    30 
       
    31 // USER INCLUDE FILES
       
    32 #include "akndigitalclock.h"
       
    33 
       
    34 // LOCAL CONSTANTS AND MACROS
       
    35 static const TInt KIntervalTime( 60000000 ); // in microseconds
       
    36 _LIT( KTimeFormat, "%-B%J%:1%T%+B" );
       
    37 
       
    38 enum TAknDigitalClockFlags
       
    39     {
       
    40     EAknDigitalClockButton1DownReceived = 0x00000001,
       
    41     EAknDigitalClockInStatusPane        = 0x00000002
       
    42     };
       
    43 
       
    44 // MODULE DATA STRUCTURES
       
    45 class CAknDigitalClockChangeHandler : public CActive
       
    46     {
       
    47 public: // Constructor and destructor
       
    48     static CAknDigitalClockChangeHandler* NewL(
       
    49         CAknDigitalClock& aClient )
       
    50         {
       
    51         CAknDigitalClockChangeHandler* self =
       
    52             new (ELeave) CAknDigitalClockChangeHandler( aClient );
       
    53         CleanupStack::PushL( self );
       
    54         self->ConstructL();
       
    55         CleanupStack::Pop( self );
       
    56         return self;
       
    57         }
       
    58 
       
    59     virtual ~CAknDigitalClockChangeHandler()
       
    60         {
       
    61         Cancel();
       
    62         iChangeNotifier.Close();
       
    63         }
       
    64 
       
    65 private: // From CActive
       
    66     void DoCancel()
       
    67         {
       
    68         iChangeNotifier.LogonCancel();
       
    69         // Return value is ignored.
       
    70         }
       
    71 
       
    72     void RunL()
       
    73         {
       
    74         if( iStatus.Int() & ( EChangesLocale | EChangesSystemTime ) )
       
    75             {
       
    76             iClient.AdjustPositionL();
       
    77             iClient.DrawDeferred();
       
    78             }
       
    79 
       
    80         User::LeaveIfError( iChangeNotifier.Logon( iStatus ) );
       
    81         SetActive();
       
    82         }
       
    83 
       
    84 private: // Private constructors
       
    85     void ConstructL()
       
    86         {
       
    87         User::LeaveIfError( iChangeNotifier.Create() );
       
    88         User::LeaveIfError( iChangeNotifier.Logon( iStatus ) );
       
    89         SetActive();
       
    90         }
       
    91 
       
    92     CAknDigitalClockChangeHandler( CAknDigitalClock& aClient )
       
    93         : CActive( EPriorityStandard ), iClient( aClient )
       
    94         {
       
    95         CActiveScheduler::Add( this );
       
    96         }
       
    97 
       
    98 private: // Data
       
    99     RChangeNotifier iChangeNotifier;
       
   100     CAknDigitalClock& iClient;
       
   101     };
       
   102 
       
   103 // ============================ MEMBER FUNCTIONS ===============================
       
   104 
       
   105 // -----------------------------------------------------------------------------
       
   106 // CAknDigitalClock::CAknDigitalClock
       
   107 // C++ default constructor can NOT contain any code, that
       
   108 // might leave.
       
   109 // -----------------------------------------------------------------------------
       
   110 //
       
   111 CAknDigitalClock::CAknDigitalClock( TBool aInStatusPane )
       
   112     {
       
   113     if ( aInStatusPane )
       
   114         {
       
   115         iFlags |= EAknDigitalClockInStatusPane;
       
   116         }
       
   117     }
       
   118 
       
   119 
       
   120 // -----------------------------------------------------------------------------
       
   121 // CAknDigitalClock::ConstructL
       
   122 // Symbian 2nd phase constructor can leave.
       
   123 // -----------------------------------------------------------------------------
       
   124 //
       
   125 void CAknDigitalClock::ConstructL()
       
   126     {
       
   127     iHandler = CAknDigitalClockChangeHandler::NewL( *this );
       
   128 
       
   129     iColor = KRgbBlack;
       
   130 
       
   131     iTimeFormat = TLocale().TimeFormat();
       
   132     AdjustPositionL();
       
   133     }
       
   134 
       
   135 
       
   136 // -----------------------------------------------------------------------------
       
   137 // CAknDigitalClock::NewL
       
   138 // Two-phased constructor.
       
   139 // -----------------------------------------------------------------------------
       
   140 //
       
   141 CAknDigitalClock* CAknDigitalClock::NewL( CCoeControl* aContainerWindow,
       
   142                                           TBool aInStatusPane )
       
   143     {
       
   144     CAknDigitalClock* self =
       
   145         new (ELeave) CAknDigitalClock( aInStatusPane );
       
   146     CleanupStack::PushL( self );
       
   147     self->SetContainerWindowL( *aContainerWindow );
       
   148     self->ConstructL();
       
   149     CleanupStack::Pop( self );
       
   150     AKNTASHOOK_ADDL( self, "CAknDigitalClock" );
       
   151     return self;
       
   152     }
       
   153 
       
   154 
       
   155 // -----------------------------------------------------------------------------
       
   156 // Destructor
       
   157 // -----------------------------------------------------------------------------
       
   158 //
       
   159 CAknDigitalClock::~CAknDigitalClock()
       
   160     {
       
   161     AKNTASHOOK_REMOVE();
       
   162     MTouchFeedback* feedback = MTouchFeedback::Instance();
       
   163     if ( feedback )
       
   164         {
       
   165         feedback->RemoveFeedbackForControl(this);
       
   166         }
       
   167 
       
   168     delete iHandler;
       
   169     delete iTimer;
       
   170     }
       
   171 
       
   172 
       
   173 // -----------------------------------------------------------------------------
       
   174 // CAknDigitalClock::TimerCallback
       
   175 // (other items were commented in a header).
       
   176 // -----------------------------------------------------------------------------
       
   177 //
       
   178 TInt CAknDigitalClock::TimerCallback( TAny* aThis )
       
   179     {
       
   180     CAknDigitalClock* self = static_cast<CAknDigitalClock*>( aThis );
       
   181 
       
   182     self->DrawDeferred();
       
   183 
       
   184     // Adjust the timer delay if necessary
       
   185     TTime time;
       
   186     time.HomeTime();
       
   187     TDateTime dateTime = time.DateTime();
       
   188     if ( dateTime.Second() > 0 )
       
   189         {
       
   190         self->iTimer->Cancel();
       
   191         self->iTimer->After( KIntervalTime -
       
   192             1000000 * dateTime.Second() - dateTime.MicroSecond() );
       
   193         }
       
   194 
       
   195     return KErrNone;
       
   196     }
       
   197 
       
   198 
       
   199 // -----------------------------------------------------------------------------
       
   200 // CAknDigitalClock::AdjustPositionL
       
   201 // This method is called when the time format of the clock is changed.
       
   202 // In nHD status pane layouts the small digital clock and universal indicator
       
   203 // pane positions depend on the clock's time format.
       
   204 // -----------------------------------------------------------------------------
       
   205 //
       
   206 void CAknDigitalClock::AdjustPositionL()
       
   207     {
       
   208     TInt format( TLocale().TimeFormat() );
       
   209 
       
   210     if ( iFlags & EAknDigitalClockInStatusPane &&
       
   211          AknStatuspaneUtils::HDLayoutActive() )
       
   212         {
       
   213         CEikStatusPaneBase* sp = CEikStatusPaneBase::Current();
       
   214 
       
   215         if ( sp && format != iTimeFormat )
       
   216             {
       
   217             CCoeControl* indicatorControl =
       
   218                 sp->ContainerControlL(
       
   219                     TUid::Uid( EEikStatusPaneUidIndic ) );
       
   220 
       
   221             CCoeControl* clockControl =
       
   222                 sp->ContainerControlL(
       
   223                     TUid::Uid( EEikStatusPaneUidDigitalClock ) );
       
   224 
       
   225             if ( indicatorControl )
       
   226                 {
       
   227                 TBool flatLayoutActive( AknStatuspaneUtils::FlatLayoutActive() );
       
   228 
       
   229                 TRect spRect;
       
   230                 AknLayoutUtils::LayoutMetricsRect(
       
   231                     AknLayoutUtils::EStatusPane,
       
   232                     spRect );
       
   233 
       
   234                 TAknLayoutRect layoutRect;
       
   235 
       
   236                 if ( !flatLayoutActive )
       
   237                     {
       
   238                     // Indicator pane position does not change in the
       
   239                     // flat layout.
       
   240                     layoutRect.LayoutRect(
       
   241                         spRect,
       
   242                         format == ETime12 ?
       
   243                             AknLayoutScalable_Avkon::indicator_nsta_pane( 3 ) :
       
   244                             AknLayoutScalable_Avkon::indicator_nsta_pane_cp_24( 3 ) );
       
   245                     TRect indicRect( layoutRect.Rect() );
       
   246 
       
   247                     indicatorControl->SetRect( indicRect );
       
   248                     }
       
   249 
       
   250                 if ( clockControl )
       
   251                     {
       
   252                     layoutRect.LayoutRect(
       
   253                         spRect,
       
   254                         format == ETime12 ?
       
   255                             AknLayoutScalable_Avkon::clock_nsta_pane(
       
   256                                 flatLayoutActive ? 3 : 2 ) :
       
   257                             AknLayoutScalable_Avkon::clock_nsta_pane_cp_24(
       
   258                                 flatLayoutActive ? 11 : 2 ) );
       
   259                     TRect clockRect( layoutRect.Rect() );
       
   260 
       
   261                     clockControl->SetRect( clockRect );
       
   262                     }
       
   263 
       
   264                 sp->DrawNow();
       
   265                 }
       
   266             }
       
   267         }
       
   268     MTouchFeedback* feedback = MTouchFeedback::Instance();
       
   269     if (feedback )
       
   270         {
       
   271         CFeedbackSpec* fbSpec = CFeedbackSpec::New();
       
   272         if ( fbSpec )
       
   273             {
       
   274             fbSpec->AddFeedback( ETouchEventStylusDown,
       
   275                                  ETouchFeedbackSensitiveButton );
       
   276             fbSpec->AddFeedback( ETouchEventStylusUp,
       
   277                                  ETouchFeedbackSensitiveButton,
       
   278                                  ETouchFeedbackVibra );
       
   279 
       
   280             feedback->SetFeedbackArea( this,
       
   281                                        0,
       
   282                                        Rect(),
       
   283                                        fbSpec );
       
   284             delete fbSpec; 
       
   285             }        
       
   286         }
       
   287 
       
   288     iTimeFormat = format;
       
   289 
       
   290     }
       
   291 
       
   292 
       
   293 // -----------------------------------------------------------------------------
       
   294 // CAknDigitalClock::HandleResourceChange
       
   295 // (other items were commented in a header).
       
   296 // -----------------------------------------------------------------------------
       
   297 //
       
   298 void CAknDigitalClock::HandleResourceChange( TInt aType )
       
   299     {
       
   300     if ( aType == KAknsMessageSkinChange ||
       
   301          aType == KEikDynamicLayoutVariantSwitch )
       
   302         {
       
   303         DrawDeferred();
       
   304         }
       
   305     return;
       
   306     }
       
   307 
       
   308 
       
   309 // -----------------------------------------------------------------------------
       
   310 // CAknDigitalClock::Draw
       
   311 // (other items were commented in a header).
       
   312 // -----------------------------------------------------------------------------
       
   313 //
       
   314 void CAknDigitalClock::Draw( const TRect& /*aRect*/ ) const
       
   315     {
       
   316     // Draw the time only if text layout has been set and
       
   317     // the clock timer is running, which means that the clock is on
       
   318     // full or partial foreground. In case the clock is drawn when it's
       
   319     // on the background, then only the skin background gets drawn.
       
   320     if ( iTimeLayoutInUse && iTimer && iTimer->IsActive() )
       
   321         {
       
   322         CWindowGc& gc = SystemGc();
       
   323 
       
   324         TRect rect( Rect() );
       
   325 
       
   326         if ( iFlags & EAknDigitalClockInStatusPane )
       
   327             {
       
   328             MAknsSkinInstance* skin = AknsUtils::SkinInstance();
       
   329             MAknsControlContext* cc = AknsDrawUtils::ControlContext( this );
       
   330             AknsDrawUtils::Background( skin, cc, this, gc, Rect() );
       
   331             }
       
   332 
       
   333         const TInt KMaxTextSize = 6 + KMaxAmPmName + 1;
       
   334 
       
   335         TBuf<KMaxTextSize> time;
       
   336 
       
   337         TAknLayoutText layoutText;
       
   338         layoutText.LayoutText( rect, iTimeLayout);
       
   339 
       
   340         TTime homeTime;
       
   341         homeTime.HomeTime();
       
   342 
       
   343         TRAP_IGNORE( homeTime.FormatL( time, KTimeFormat ) );
       
   344 
       
   345         // Before drawing do the arabic indic digit etc. conversions
       
   346         AknTextUtils::DisplayTextLanguageSpecificNumberConversion( time );
       
   347 
       
   348         // Finally draw.
       
   349         layoutText.DrawText( gc, time, ETrue, iColor);
       
   350         }
       
   351     }
       
   352 
       
   353 
       
   354 // -----------------------------------------------------------------------------
       
   355 // CAknDigitalClock::HandlePointerEventL
       
   356 // Starts clock application in down event.
       
   357 // -----------------------------------------------------------------------------
       
   358 //
       
   359 void CAknDigitalClock::HandlePointerEventL( const TPointerEvent& aPointerEvent )
       
   360     {
       
   361     CAknControl:: HandlePointerEventL( aPointerEvent );
       
   362 
       
   363     if ( AknLayoutUtils::PenEnabled() )
       
   364         {
       
   365         // Do nothing if dimmed.
       
   366         if ( IsDimmed() ||
       
   367              Window().IsFaded() )
       
   368             {
       
   369             return;
       
   370             }
       
   371 
       
   372         TRect rect( Rect() );
       
   373 
       
   374         // Currently the small digital clock pane and universal
       
   375         // indicator pane are regarded as one touch responsive area from
       
   376         // which the universal indicator popup should open on tap,
       
   377         // so upon pointer up event it must be checked here if
       
   378         // the down event happened inside this control, but the up event
       
   379         // inside indicator pane area.
       
   380         TRect indicatorRect( 0, 0, 0, 0 );
       
   381 
       
   382         if ( iFlags & EAknDigitalClockInStatusPane &&
       
   383              aPointerEvent.iType == TPointerEvent::EButton1Up )
       
   384             {
       
   385             CEikStatusPaneBase* sp = CEikStatusPaneBase::Current();
       
   386 
       
   387             if ( sp )
       
   388                 {
       
   389                 CCoeControl* indicatorPane = sp->ContainerControlL(
       
   390                     TUid::Uid( EEikStatusPaneUidIndic ) );
       
   391                 if ( indicatorPane )
       
   392                     {
       
   393                     indicatorRect =
       
   394                         TRect( indicatorPane->PositionRelativeToScreen(),
       
   395                                indicatorPane->Size() );
       
   396                     }
       
   397                 }
       
   398             }
       
   399 
       
   400         if ( aPointerEvent.iType == TPointerEvent::EButton1Down &&
       
   401              rect.Contains( aPointerEvent.iPosition ) )
       
   402             {
       
   403             // Set flag that down event was inside the clock.
       
   404             iFlags |= EAknDigitalClockButton1DownReceived;
       
   405 
       
   406             // tactile feedback is done with SetFeedbackArea
       
   407             }
       
   408         else if ( aPointerEvent.iType == TPointerEvent::EButton1Up &&
       
   409                   ( ( iFlags & EAknDigitalClockButton1DownReceived &&
       
   410                       rect.Contains( aPointerEvent.iPosition ) ) ||
       
   411                     ( indicatorRect.Contains( aPointerEvent.iParentPosition ) ) ) )
       
   412             {
       
   413             // Launch the universal indicator popup.
       
   414             CAknSmallIndicator* indicatorNotifier =
       
   415                 CAknSmallIndicator::NewLC( TUid::Uid( 0 ) );
       
   416             indicatorNotifier->HandleIndicatorTapL();
       
   417             CleanupStack::PopAndDestroy( indicatorNotifier );
       
   418 
       
   419             // Up event received, reset button down flag.
       
   420             iFlags &= ( ~EAknDigitalClockButton1DownReceived );
       
   421             }
       
   422         }
       
   423     }
       
   424 
       
   425 
       
   426 // -----------------------------------------------------------------------------
       
   427 // CAknDigitalClock::SetColor
       
   428 // (other items were commented in a header).
       
   429 // -----------------------------------------------------------------------------
       
   430 //
       
   431 void CAknDigitalClock::SetColor( TRgb aColor )
       
   432     {
       
   433     iColor = aColor;
       
   434     }
       
   435 
       
   436 
       
   437 // -----------------------------------------------------------------------------
       
   438 // CAknDigitalClock::SetTimeLayout
       
   439 // (other items were commented in a header).
       
   440 // -----------------------------------------------------------------------------
       
   441 //
       
   442 void CAknDigitalClock::SetTimeLayout( TAknTextLineLayout aTimeLayout )
       
   443     {
       
   444     iTimeLayout = aTimeLayout;
       
   445     iTimeLayoutInUse = ETrue;
       
   446     }
       
   447 
       
   448 
       
   449 // -----------------------------------------------------------------------------
       
   450 // CAknDigitalClock::ClearTimeLayout
       
   451 // (other items were commented in a header).
       
   452 // -----------------------------------------------------------------------------
       
   453 //
       
   454 void CAknDigitalClock::ClearTimeLayout()
       
   455     {
       
   456     iTimeLayoutInUse = EFalse;
       
   457     }
       
   458 
       
   459 
       
   460 // -----------------------------------------------------------------------------
       
   461 // CAknDigitalClock::StartTimer
       
   462 // (other items were commented in a header).
       
   463 // -----------------------------------------------------------------------------
       
   464 //
       
   465 void CAknDigitalClock::StartTimer()
       
   466     {
       
   467     if ( !iTimer )
       
   468         {
       
   469         iTimer = CPeriodic::New( CActive::EPriorityHigh );
       
   470         }
       
   471 
       
   472     if ( iTimer && !iTimer->IsActive() )
       
   473         {
       
   474         TTime time;
       
   475         time.HomeTime();
       
   476         TDateTime dateTime( time.DateTime() );
       
   477         TCallBack callBack( TimerCallback, this );
       
   478 
       
   479         iTimer->Start( TTimeIntervalMicroSeconds32(
       
   480          KIntervalTime - 1000000 * dateTime.Second() - dateTime.MicroSecond() ),
       
   481          TTimeIntervalMicroSeconds32( KIntervalTime ), callBack );
       
   482 
       
   483         DrawDeferred();
       
   484         }
       
   485     }
       
   486 
       
   487 
       
   488 // -----------------------------------------------------------------------------
       
   489 // CAknDigitalClock::StopTimer
       
   490 // (other items were commented in a header).
       
   491 // -----------------------------------------------------------------------------
       
   492 //
       
   493 void CAknDigitalClock::StopTimer()
       
   494     {
       
   495     if ( iTimer && iTimer->IsActive() )
       
   496         {
       
   497         iTimer->Cancel();
       
   498         }
       
   499 
       
   500     // Ensure that the CPeriodic timer stops by destroying it, see Symbian SDK.
       
   501     delete iTimer;
       
   502     iTimer = NULL;
       
   503     }
       
   504 
       
   505 //  End of File