uifw/AvKon/src/AknSkinnableClock.cpp
changeset 0 2f259fa3e83a
child 18 fcdfafb36fe7
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 skinnable clock.
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 // SYSTEM INCLUDE FILES
       
    20 #include <bitdev.h>
       
    21 #include <eikenv.h>
       
    22 #include <eikspane.h>
       
    23 #include <AknsDrawUtils.h>
       
    24 #include <aknlayoutscalable_avkon.cdl.h>
       
    25 #include <akniconconfig.h>
       
    26 #include <aknappui.h>
       
    27 #include <apgcli.h>
       
    28 
       
    29 #include <AknTasHook.h>
       
    30 // USER INCLUDE FILES
       
    31 #include "AknUtils.h"
       
    32 #include "AknSkinnableClock.h"
       
    33 #include "AknSkinnableClockFace.h"
       
    34 #include "aknconsts.h"
       
    35 #include "AknDef.h"
       
    36 #include "AknStatuspaneUtils.h"
       
    37 #include "layoutmetadata.cdl.h"
       
    38 
       
    39 #include <touchfeedback.h>
       
    40 
       
    41 // LOCAL CONSTANTS AND MACROS
       
    42 static const TInt KIntervalTime(60000000); // in microseconds
       
    43 _LIT( KClockApplication, "\\sys\\bin\\clock.exe" );
       
    44 
       
    45 // MODULE DATA STRUCTURES
       
    46 class CAknSkinnableClockChangeHandler : public CActive
       
    47     {
       
    48     public: // Constructor and destructor
       
    49         static CAknSkinnableClockChangeHandler* NewL(
       
    50             CAknSkinnableClock& aClient )
       
    51             {
       
    52             CAknSkinnableClockChangeHandler* self =
       
    53                 new (ELeave) CAknSkinnableClockChangeHandler( aClient );
       
    54             CleanupStack::PushL( self );
       
    55             self->ConstructL();
       
    56             CleanupStack::Pop( self );
       
    57             return self;
       
    58             }
       
    59 
       
    60         virtual ~CAknSkinnableClockChangeHandler()
       
    61             {
       
    62             Cancel();
       
    63             iChangeNotifier.Close();
       
    64             }
       
    65 
       
    66     private: // From CActive
       
    67         void DoCancel()
       
    68             {
       
    69             iChangeNotifier.LogonCancel();
       
    70             // Return value is ignored.
       
    71             }
       
    72 
       
    73         void RunL()
       
    74             {
       
    75             if( iStatus.Int() & ( EChangesLocale | EChangesSystemTime ) )
       
    76                 {
       
    77                 iClient.TimeOrLocaleChanged();
       
    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         CAknSkinnableClockChangeHandler( CAknSkinnableClock& aClient )
       
    93             : CActive( EPriorityStandard ), iClient( aClient )
       
    94             {
       
    95             CActiveScheduler::Add( this );
       
    96             }
       
    97 
       
    98     private: // Data
       
    99         RChangeNotifier     iChangeNotifier;
       
   100         CAknSkinnableClock& iClient;
       
   101     };
       
   102 
       
   103 // ============================ MEMBER FUNCTIONS ===============================
       
   104 
       
   105 // -----------------------------------------------------------------------------
       
   106 // CAknSkinnableClock::CAknSkinnableClock
       
   107 // C++ default constructor can NOT contain any code, that
       
   108 // might leave.
       
   109 // -----------------------------------------------------------------------------
       
   110 //
       
   111 CAknSkinnableClock::CAknSkinnableClock( const TBool aFormatFromLocale,
       
   112                                         const TBool aContextPaneClock )
       
   113     {
       
   114     iFormatFromLocale = aFormatFromLocale;
       
   115     iContextPaneClock = aContextPaneClock;
       
   116 
       
   117     iClockFormat = TLocale().ClockFormat();
       
   118     }
       
   119 
       
   120 // -----------------------------------------------------------------------------
       
   121 // CAknSkinnableClock::ConstructL
       
   122 // Symbian 2nd phase constructor can leave.
       
   123 // -----------------------------------------------------------------------------
       
   124 //
       
   125 void CAknSkinnableClock::ConstructL()
       
   126     {
       
   127     // We observe foreground events in order
       
   128     // to stop the clock timer if clock is not visible.
       
   129     iCoeEnv->AddMessageMonitorObserverL( *this );
       
   130 
       
   131     SetFormatL( iClockFormat );
       
   132 
       
   133     iHandler = CAknSkinnableClockChangeHandler::NewL( *this );
       
   134 
       
   135     SetHitTest( this );
       
   136 
       
   137     // Start timer if necessary.
       
   138     // Later on, timer is stopped & restarted in MonitorWsMessage.
       
   139     CAknAppUiBase* base =
       
   140         static_cast<CAknAppUiBase*>( iEikonEnv->EikAppUi() );
       
   141     iInForeground = base->HasFullOrPartialForeground();
       
   142     if ( iInForeground )
       
   143         {
       
   144         StartTimer();
       
   145         }
       
   146 
       
   147     /* Register MHWRMLightObserver */
       
   148     iLight = CHWRMLight::NewL( this );
       
   149     }
       
   150 
       
   151 
       
   152 // -----------------------------------------------------------------------------
       
   153 // CAknSkinnableClock::NewL
       
   154 // Two-phased constructor.
       
   155 // -----------------------------------------------------------------------------
       
   156 //
       
   157 EXPORT_C CAknSkinnableClock* CAknSkinnableClock::NewL(
       
   158     CCoeControl* aContainerWindow,
       
   159     const TBool aFormatFromLocale,
       
   160     const TBool aContextPaneClock )
       
   161     {
       
   162     CAknSkinnableClock* self =
       
   163         new (ELeave) CAknSkinnableClock( aFormatFromLocale, aContextPaneClock );
       
   164     CleanupStack::PushL( self );
       
   165     self->SetContainerWindowL( *aContainerWindow );
       
   166     self->ConstructL();
       
   167     CleanupStack::Pop( self );
       
   168     AKNTASHOOK_ADDL( self, "CAknSkinnableClock" );
       
   169     return self;
       
   170     }
       
   171 
       
   172 
       
   173 // -----------------------------------------------------------------------------
       
   174 // Destructor
       
   175 // -----------------------------------------------------------------------------
       
   176 //
       
   177 EXPORT_C CAknSkinnableClock::~CAknSkinnableClock()
       
   178     {
       
   179     AKNTASHOOK_REMOVE();
       
   180     iCoeEnv->RemoveMessageMonitorObserver( *this );
       
   181 
       
   182     delete iHandler;
       
   183     delete iTimer;
       
   184     delete iFace;
       
   185 
       
   186     delete iLight;
       
   187     }
       
   188 
       
   189 
       
   190 
       
   191 
       
   192 // -----------------------------------------------------------------------------
       
   193 // CAknSkinnableClock::UpdateDisplay
       
   194 // (other items were commented in a header).
       
   195 // -----------------------------------------------------------------------------
       
   196 //
       
   197 EXPORT_C void CAknSkinnableClock::UpdateDisplay()
       
   198     {
       
   199     DrawDeferred();
       
   200     }
       
   201 
       
   202 
       
   203 // -----------------------------------------------------------------------------
       
   204 // CAknSkinnableClock::TimeOrLocaleChanged
       
   205 // (other items were commented in a header).
       
   206 // -----------------------------------------------------------------------------
       
   207 //
       
   208 void CAknSkinnableClock::TimeOrLocaleChanged()
       
   209     {
       
   210     TLocale locale;
       
   211     if ( ( locale.ClockFormat() != iClockFormat ) && iFormatFromLocale )
       
   212         {
       
   213         TRAP_IGNORE( SetFormatL( locale.ClockFormat() ) );
       
   214         }
       
   215     else
       
   216         {
       
   217         UpdateDisplay();
       
   218         }
       
   219     }
       
   220 
       
   221 
       
   222 // -----------------------------------------------------------------------------
       
   223 // CAknSkinnableClock::SetFormatL
       
   224 // (other items were commented in a header).
       
   225 // -----------------------------------------------------------------------------
       
   226 //
       
   227 EXPORT_C void CAknSkinnableClock::SetFormatL( const TClockFormat aFormat )
       
   228     {
       
   229     if ( Size() != TSize(0,0) ) // Perf optimization
       
   230         {
       
   231         delete iFace;
       
   232         iFace = NULL;
       
   233 
       
   234         switch( aFormat )
       
   235             {
       
   236             case EClockAnalog:
       
   237                 {
       
   238                 iFace = CAknSkinnableClockFaceAnalogue::NewL(iContextPaneClock);
       
   239                 break;
       
   240                 }
       
   241             case EClockDigital:
       
   242                 {
       
   243                 iFace = CAknSkinnableClockFaceDigital::NewL();
       
   244                 break;
       
   245                 }
       
   246             };
       
   247         }
       
   248 
       
   249     iClockFormat = aFormat;
       
   250 
       
   251     UpdateDisplay();
       
   252     }
       
   253 
       
   254 
       
   255 
       
   256 
       
   257 
       
   258 // -----------------------------------------------------------------------------
       
   259 // CAknSkinnableClock::TimerCallback
       
   260 // (other items were commented in a header).
       
   261 // -----------------------------------------------------------------------------
       
   262 //
       
   263 TInt CAknSkinnableClock::TimerCallback( TAny* aThis )
       
   264     {
       
   265     CAknSkinnableClock* self = static_cast< CAknSkinnableClock* >( aThis );
       
   266 
       
   267     // Update the clock display
       
   268     self->UpdateDisplay();
       
   269 
       
   270     // Adjust the timer delay if necessary
       
   271     TTime time;
       
   272     time.HomeTime();
       
   273     TDateTime dateTime( time.DateTime() );
       
   274     if( dateTime.Second() > 0)
       
   275         {
       
   276         self->iTimer->Cancel();
       
   277         self->iTimer->After( KIntervalTime -
       
   278             1000000 * dateTime.Second() - dateTime.MicroSecond());
       
   279         }
       
   280 
       
   281     return KErrNone;
       
   282     }
       
   283 
       
   284 
       
   285 // -----------------------------------------------------------------------------
       
   286 // CAknSkinnableClock::BufferDisplayMode
       
   287 // (other items were commented in a header).
       
   288 // -----------------------------------------------------------------------------
       
   289 //
       
   290 TDisplayMode CAknSkinnableClock::BufferDisplayMode()
       
   291     {
       
   292     return EColor16MA;
       
   293     }
       
   294 
       
   295 
       
   296 // -----------------------------------------------------------------------------
       
   297 // CAknSkinnableClock::IsVisibleInContextPane
       
   298 // (other items were commented in a header).
       
   299 // -----------------------------------------------------------------------------
       
   300 //
       
   301 TBool CAknSkinnableClock::IsVisibleInContextPane() const
       
   302     {
       
   303     CEikStatusPaneBase* statusPane = CEikStatusPaneBase::Current();
       
   304     TRect screenRect;
       
   305     AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::EScreen, screenRect );
       
   306 
       
   307     if ( statusPane && statusPane->PaneCapabilities(
       
   308         TUid::Uid( EEikStatusPaneUidClock ) ).IsInCurrentLayout() )
       
   309         {
       
   310         return ETrue;
       
   311         }
       
   312     else if ( screenRect.Width() > screenRect.Height() &&
       
   313               AknStatuspaneUtils::IdleLayoutActive() )
       
   314         {
       
   315         // in landscape phone/idle shows the clock
       
   316         return ETrue;
       
   317         }
       
   318 
       
   319     return EFalse;
       
   320     }
       
   321 
       
   322 
       
   323 // -----------------------------------------------------------------------------
       
   324 // CAknSkinnableClock::HandleResourceChange
       
   325 // (other items were commented in a header).
       
   326 // -----------------------------------------------------------------------------
       
   327 //
       
   328 void CAknSkinnableClock::HandleResourceChange( TInt aType )
       
   329     {
       
   330     if ( aType == KEikDynamicLayoutVariantSwitch )
       
   331         {
       
   332         // Face needs to be resized too...
       
   333         TRAP_IGNORE( SetFormatL( iClockFormat ) );
       
   334         // Setformat calls UpdateDisplay, no need to update it manually.
       
   335         }
       
   336     else if ( aType == KAknsMessageSkinChange )
       
   337         {
       
   338         UpdateDisplay();
       
   339         }
       
   340     }
       
   341 
       
   342 
       
   343 // -----------------------------------------------------------------------------
       
   344 // CAknSkinnableClock::HitRegionContains
       
   345 // (other items were commented in a header).
       
   346 // -----------------------------------------------------------------------------
       
   347 //
       
   348 TBool CAknSkinnableClock::HitRegionContains(
       
   349     const TPoint &aPoint,
       
   350     const CCoeControl& /*aControl*/ ) const
       
   351     {
       
   352     TBool handleEvent( EFalse );
       
   353 
       
   354     if ( Rect().Contains( aPoint ) )
       
   355         {
       
   356         TVwsViewId idleView;
       
   357         TInt err = AknDef::GetPhoneIdleViewId( idleView );
       
   358         if ( !err )
       
   359             {
       
   360             RWsSession& wsSession = iCoeEnv->WsSession();
       
   361 
       
   362             TApaTaskList taskList( wsSession );
       
   363             TApaTask idle( taskList.FindApp( idleView.iAppUid ) );
       
   364 
       
   365             if ( idle.Exists() )
       
   366                 {
       
   367                 TThreadId id;
       
   368                 wsSession.GetWindowGroupClientThreadId(
       
   369                     wsSession.GetFocusWindowGroup(), id );
       
   370 
       
   371                 if ( id == idle.ThreadId() )
       
   372                     {
       
   373                     handleEvent = ETrue;
       
   374                     }
       
   375                 }
       
   376             }
       
   377         }
       
   378 
       
   379     return handleEvent;
       
   380     }
       
   381 
       
   382 
       
   383 // -----------------------------------------------------------------------------
       
   384 // CAknSkinnableClock::PositionChanged
       
   385 //
       
   386 // -----------------------------------------------------------------------------
       
   387 //
       
   388 EXPORT_C void CAknSkinnableClock::PositionChanged()
       
   389     {
       
   390     CCoeControl::PositionChanged();
       
   391     }
       
   392 
       
   393 
       
   394 // -----------------------------------------------------------------------------
       
   395 // CAknSkinnableClock::Draw
       
   396 // (other items were commented in a header).
       
   397 // -----------------------------------------------------------------------------
       
   398 //
       
   399 void CAknSkinnableClock::Draw( const TRect& /*aRect*/ ) const
       
   400     {
       
   401 
       
   402     CWindowGc& gc = SystemGc();
       
   403     MAknsSkinInstance* skin = AknsUtils::SkinInstance();
       
   404     MAknsControlContext* cc = AknsDrawUtils::ControlContext(this);
       
   405     TRect rect(Rect());
       
   406 
       
   407     gc.SetPenStyle(CGraphicsContext::ENullPen);
       
   408     gc.SetBrushStyle(CGraphicsContext::ESolidBrush);
       
   409     gc.SetBrushColor(KRgbWhite);
       
   410 
       
   411     AknsDrawUtils::Background(skin, cc, this, gc, rect);
       
   412 
       
   413     gc.SetPenStyle(CGraphicsContext::ESolidPen);
       
   414     gc.SetBrushStyle(CGraphicsContext::ENullBrush);
       
   415 
       
   416     TTime homeTime;
       
   417     homeTime.HomeTime();
       
   418     if (iFace)
       
   419         {
       
   420         iFace->DrawTimeToBitmapL(rect, gc, homeTime);
       
   421         }
       
   422     }
       
   423 
       
   424 
       
   425 // -----------------------------------------------------------------------------
       
   426 // CAknSkinnableClock::HandlePointerEventL
       
   427 // Changes clock format between digital and analog in down event.
       
   428 // The clock format is saved then to TLocale
       
   429 // -----------------------------------------------------------------------------
       
   430 //
       
   431 EXPORT_C void CAknSkinnableClock::HandlePointerEventL(
       
   432     const TPointerEvent& aPointerEvent )
       
   433     {
       
   434     if ( AknLayoutUtils::PenEnabled() )
       
   435         {
       
   436         // Do nothing if dimmed.
       
   437         if ( IsDimmed() )
       
   438             {
       
   439             return;
       
   440             }
       
   441 
       
   442         // Tactile feedback is played on both down and up event    
       
   443         if ( aPointerEvent.iType == TPointerEvent::EButton1Down
       
   444                 && Rect().Contains( aPointerEvent.iPosition ))
       
   445             {
       
   446             MTouchFeedback* feedback = MTouchFeedback::Instance();
       
   447             if (feedback)
       
   448                 {
       
   449                 feedback->InstantFeedback( this, 
       
   450                                            ETouchFeedbackSensitiveButton, 
       
   451                                            aPointerEvent );
       
   452                 }
       
   453             }
       
   454 
       
   455         // Start clock application
       
   456         if ( aPointerEvent.iType == TPointerEvent::EButton1Up
       
   457                 && Rect().Contains( aPointerEvent.iPosition ))
       
   458             {
       
   459             MTouchFeedback* feedback = MTouchFeedback::Instance();
       
   460             if (feedback)
       
   461                 {
       
   462                 // on up-event, only vibra feedback (no sound) is played
       
   463                 feedback->InstantFeedback( this, 
       
   464                                            ETouchFeedbackSensitiveButton, 
       
   465                                            ETouchFeedbackVibra, 
       
   466                                            aPointerEvent );
       
   467                 }
       
   468             RApaLsSession apa;
       
   469             User::LeaveIfError( apa.Connect() );
       
   470             CleanupClosePushL( apa );
       
   471             CApaCommandLine* cmdLine = CApaCommandLine::NewLC();
       
   472             cmdLine->SetExecutableNameL( KClockApplication );
       
   473             cmdLine->SetCommandL( EApaCommandRun );
       
   474             User::LeaveIfError( apa.StartApp( *cmdLine ) );
       
   475             CleanupStack::PopAndDestroy( 2, &apa ); // cmdLine and apa
       
   476             }
       
   477         }
       
   478     }
       
   479 
       
   480 
       
   481 // -----------------------------------------------------------------------------
       
   482 // CAknSkinnableClock::SizeChanged
       
   483 // (other items were commented in a header).
       
   484 // -----------------------------------------------------------------------------
       
   485 //
       
   486 void CAknSkinnableClock::SizeChanged()
       
   487     {
       
   488      TRAP_IGNORE( SetFormatL(iClockFormat) );
       
   489     }
       
   490 
       
   491 
       
   492 // ---------------------------------------------------------------------------
       
   493 // CAknSkinnableClock::MakeVisible
       
   494 // (other items were commented in a header).
       
   495 // ---------------------------------------------------------------------------
       
   496 //
       
   497 void CAknSkinnableClock::MakeVisible( TBool aVisible )
       
   498     {
       
   499     CCoeControl::MakeVisible( aVisible );
       
   500 
       
   501     if ( !aVisible )
       
   502         {
       
   503         // Stop the timer if this control is made non-visible.
       
   504         // This control may exist in status pane layouts which
       
   505         // don't show clock, and in those it's hidden via
       
   506         // this method, so no need to keep the timer running.
       
   507         StopTimer();
       
   508         }
       
   509     else if ( iInForeground )
       
   510         {
       
   511         StartTimer();
       
   512         }
       
   513     }
       
   514 
       
   515 
       
   516 // ---------------------------------------------------------------------------
       
   517 // CAknSkinnableClock::MonitorWsMessage
       
   518 // (other items were commented in a header).
       
   519 // -----------------------------------------------------------------------------
       
   520 //
       
   521 void CAknSkinnableClock::MonitorWsMessage( const TWsEvent& aEvent )
       
   522     {
       
   523     switch ( aEvent.Type() )
       
   524         {
       
   525         case KAknFullOrPartialForegroundGained:
       
   526             {
       
   527             iInForeground = ETrue;
       
   528 
       
   529             TRAP_IGNORE( ForegroundGainedL() );
       
   530             break;
       
   531             }
       
   532 
       
   533         case KAknFullOrPartialForegroundLost:
       
   534             {
       
   535             iInForeground = EFalse;
       
   536             StopTimer();
       
   537 
       
   538             // Ensure that the clock gets drawn with only skin background.
       
   539             // This has a similar kind of effect as clearing the redraw
       
   540             // store at this point, but produces less flicker.
       
   541             DrawDeferred();
       
   542 
       
   543             break;
       
   544             }
       
   545 
       
   546         default:
       
   547             break;
       
   548         }
       
   549     }
       
   550 
       
   551 
       
   552 // -----------------------------------------------------------------------------
       
   553 // CAknSkinnableClock::StartTimer
       
   554 // (other items were commented in a header).
       
   555 // -----------------------------------------------------------------------------
       
   556 //
       
   557 void CAknSkinnableClock::StartTimer()
       
   558     {
       
   559     if ( !iTimer )
       
   560         {
       
   561         iTimer = CPeriodic::New( CActive::EPriorityHigh );
       
   562         }
       
   563 
       
   564     if ( iTimer && !iTimer->IsActive() )
       
   565         {
       
   566         // Need to update first.
       
   567         UpdateDisplay();
       
   568 
       
   569         TTime time;
       
   570         time.HomeTime();
       
   571         TDateTime dateTime( time.DateTime() );
       
   572         TCallBack callBack( TimerCallback, this );
       
   573 
       
   574         iTimer->Start(
       
   575             TTimeIntervalMicroSeconds32(
       
   576                 KIntervalTime - 1000000 * dateTime.Second() - dateTime.MicroSecond() ),
       
   577             TTimeIntervalMicroSeconds32( KIntervalTime ),
       
   578             callBack );
       
   579         }
       
   580     }
       
   581 
       
   582 
       
   583 // -----------------------------------------------------------------------------
       
   584 // CAknSkinnableClock::StopTimer
       
   585 // (other items were commented in a header).
       
   586 // -----------------------------------------------------------------------------
       
   587 //
       
   588 void CAknSkinnableClock::StopTimer()
       
   589     {
       
   590     if ( iTimer && iTimer->IsActive() )
       
   591         {
       
   592         iTimer->Cancel();
       
   593         }
       
   594 
       
   595     // Ensure the CPeriodic timer stops by destroying it, see Symbian SDK.
       
   596     delete iTimer;
       
   597     iTimer = NULL;
       
   598     }
       
   599 
       
   600 
       
   601 // ---------------------------------------------------------------------------
       
   602 // CAknSkinnableClock::ForegroundGainedL
       
   603 // Contains the leaving function calls in the foreground gain situation.
       
   604 // ---------------------------------------------------------------------------
       
   605 //
       
   606 void CAknSkinnableClock::ForegroundGainedL()
       
   607     {
       
   608     if ( IsVisible() )
       
   609 	    {
       
   610 	    StartTimer();
       
   611 	    }
       
   612     }
       
   613 
       
   614 
       
   615 void CAknSkinnableClock::LightStatusChanged(TInt aTarget,
       
   616                                             CHWRMLight::TLightStatus aStatus)
       
   617     {
       
   618     if( aTarget == CHWRMLight::EPrimaryDisplay
       
   619         || aTarget == CHWRMLight::EPrimaryDisplayAndKeyboard )
       
   620         {
       
   621         if( aStatus == CHWRMLight::ELightOn && iInForeground )
       
   622             {
       
   623             StartTimer();
       
   624             }
       
   625         else if( aStatus == CHWRMLight::ELightOff )
       
   626             {
       
   627             StopTimer();
       
   628             }
       
   629         }
       
   630     }
       
   631 
       
   632 //  End of File