phoneuis/dialer/src/cdialertoolbarcontainer.cpp
branchRCL_3
changeset 25 5266b1f337bd
equal deleted inserted replaced
24:41a7f70b3818 25:5266b1f337bd
       
     1 /*
       
     2 * Copyright (c) 2009, 2010 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:  CDialerToolbarContainer replaces the standard S60 toolbar
       
    15 *               in the Dialer layout in the Easy dialing mode. It's 
       
    16 *               responsible of the toolbar layout and logic, but not of the 
       
    17 *               contents which are provided by an instance of 
       
    18 *               MPhoneDialerController.
       
    19 *
       
    20 */
       
    21 
       
    22 #include <aknbutton.h>
       
    23 #include <aknappui.h>
       
    24 #include <AknsUtils.h>
       
    25 #include <aknlayoutscalable_apps.cdl.h>
       
    26 #include <layoutmetadata.cdl.h>
       
    27 #include <phoneui.rsg>
       
    28 #include <phoneappcommands.hrh>
       
    29 #include <StringLoader.h>
       
    30 #include <data_caging_path_literals.hrh>
       
    31 
       
    32 #include "dialercommon.h"
       
    33 #include "cdialertoolbarcontainer.h"
       
    34 
       
    35 
       
    36 // CONSTANTS
       
    37 const TInt KDialerToolbarButtonKeyRepeatDelay = 300;
       
    38 const TInt KDialerToolbarKeyRepeatInterval = 75;
       
    39 
       
    40 
       
    41 
       
    42 // CLASS DEFINITION
       
    43 
       
    44 // ---------------------------------------------------------------------------
       
    45 // NewL
       
    46 //
       
    47 // ---------------------------------------------------------------------------
       
    48 //
       
    49 CDialerToolbarContainer* CDialerToolbarContainer::NewL( CCoeControl& aParent,
       
    50         MPhoneDialerController* aContentProvider )
       
    51     {
       
    52     CDialerToolbarContainer* self = 
       
    53             new (ELeave) CDialerToolbarContainer( aParent, aContentProvider );
       
    54     CleanupStack::PushL( self );
       
    55     self->ConstructL();
       
    56     CleanupStack::Pop( self );
       
    57     return self;
       
    58     }
       
    59 
       
    60 // ---------------------------------------------------------------------------
       
    61 // CDialerToolbarContainer
       
    62 //
       
    63 // ---------------------------------------------------------------------------
       
    64 //
       
    65 CDialerToolbarContainer::CDialerToolbarContainer( CCoeControl& aParent,
       
    66         MPhoneDialerController* aContentProvider ) : 
       
    67     CDialerContainerBase( aParent ), 
       
    68     iContentProvider( aContentProvider )
       
    69     {
       
    70     }
       
    71 
       
    72 // ---------------------------------------------------------------------------
       
    73 // ~CDialerToolbarContainer
       
    74 //
       
    75 // ---------------------------------------------------------------------------
       
    76 //
       
    77 CDialerToolbarContainer::~CDialerToolbarContainer()
       
    78     {
       
    79     iCoeEnv->RemoveForegroundObserver( *this );
       
    80     DeleteButtons();
       
    81     }
       
    82 
       
    83 // ---------------------------------------------------------------------------
       
    84 // ConstructL
       
    85 //
       
    86 // ---------------------------------------------------------------------------
       
    87 //
       
    88 void CDialerToolbarContainer::ConstructL()
       
    89     {
       
    90     BaseConstructL();
       
    91     
       
    92     CreateButtonsL();
       
    93 
       
    94     iCoeEnv->AddForegroundObserverL( *this );
       
    95     }
       
    96 
       
    97 // ---------------------------------------------------------------------------
       
    98 // SetContentProviderL
       
    99 //
       
   100 // ---------------------------------------------------------------------------
       
   101 //
       
   102 void CDialerToolbarContainer::SetContentProviderL( MPhoneDialerController* aProvider )
       
   103     {
       
   104     if ( iContentProvider != aProvider )
       
   105         {
       
   106         iContentProvider = aProvider;
       
   107         
       
   108         // Recreate buttons to reset available button states
       
   109         DeleteButtons();
       
   110         CreateButtonsL();
       
   111         }
       
   112     }
       
   113 
       
   114 // ---------------------------------------------------------------------------
       
   115 // UpdateButtonStates
       
   116 //
       
   117 // ---------------------------------------------------------------------------
       
   118 //
       
   119 void CDialerToolbarContainer::UpdateButtonStates()
       
   120     {
       
   121     // safety check
       
   122     if ( iButtons.Count() < MPhoneDialerController::ENumberOfButtons ||
       
   123          !iContentProvider )
       
   124         {
       
   125         return;
       
   126         }
       
   127     
       
   128     for ( TInt i = 0 ; i < MPhoneDialerController::ENumberOfButtons ; ++i )
       
   129         {
       
   130         MPhoneDialerController::TButtonIndex idx =
       
   131             static_cast< MPhoneDialerController::TButtonIndex >( i );
       
   132         TInt state = iContentProvider->ButtonState( idx );
       
   133         TBool dimmed = iContentProvider->ButtonDimmed( idx );
       
   134         if ( state >= 0 )
       
   135             {
       
   136             iButtons[i]->SetCurrentState( state, EFalse );
       
   137             }
       
   138         iButtons[i]->SetDimmed( dimmed );
       
   139         }
       
   140     }
       
   141 
       
   142 // ---------------------------------------------------------------------------
       
   143 // SetVariety
       
   144 //
       
   145 // ---------------------------------------------------------------------------
       
   146 //
       
   147 void CDialerToolbarContainer::SetVariety()
       
   148     {
       
   149     iVariety = ( Layout_Meta_Data::IsLandscapeOrientation() ?
       
   150         EDialerVarietyLandscape : EDialerVarietyPortrait );
       
   151     }
       
   152 
       
   153 // ---------------------------------------------------------------------------
       
   154 // SetLayout
       
   155 //
       
   156 // ---------------------------------------------------------------------------
       
   157 //
       
   158 void CDialerToolbarContainer::SetLayout()
       
   159     {
       
   160     if ( iButtons.Count() < MPhoneDialerController::ENumberOfButtons )
       
   161         {
       
   162         return;
       
   163         }
       
   164     
       
   165     // Position for the first button
       
   166     TPoint buttonPos = Rect().iTl;
       
   167     
       
   168     if ( iVariety == EDialerVarietyPortrait )
       
   169         {
       
   170         // In portrait, buttons are laid out from top to bottom
       
   171         for ( TInt i = 0 ; i < iButtons.Count() ; ++i )
       
   172             {
       
   173             buttonPos = LayoutButton( i, buttonPos );
       
   174             }
       
   175         }
       
   176     else
       
   177         {
       
   178         // In landscape, buttons are laid out from right to left.
       
   179         // This is achieved by looping button array backwards and laying
       
   180         // those out from left to right.
       
   181         for ( TInt i = iButtons.Count()-1 ; i >= 0  ; --i )
       
   182             {
       
   183             buttonPos = LayoutButton( i, buttonPos );
       
   184             }
       
   185         }
       
   186     }
       
   187 
       
   188 // ---------------------------------------------------------------------------
       
   189 // CountComponentControls
       
   190 //
       
   191 // ---------------------------------------------------------------------------
       
   192 //
       
   193 TInt CDialerToolbarContainer::CountComponentControls() const
       
   194     {
       
   195     return iButtons.Count();
       
   196     }
       
   197 
       
   198 // ---------------------------------------------------------------------------
       
   199 // ComponentControl
       
   200 //
       
   201 // ---------------------------------------------------------------------------
       
   202 //
       
   203 CCoeControl* CDialerToolbarContainer::ComponentControl( TInt aIndex ) const
       
   204     {
       
   205     CCoeControl* control = NULL;
       
   206     if ( aIndex >= 0 && aIndex < iButtons.Count() )
       
   207         {
       
   208         control = iButtons[ aIndex ];
       
   209         }
       
   210     return control;
       
   211     }
       
   212 
       
   213 // ---------------------------------------------------------------------------
       
   214 // HandleControlEventL
       
   215 //
       
   216 // ---------------------------------------------------------------------------
       
   217 //
       
   218 void CDialerToolbarContainer::HandleControlEventL( CCoeControl* aControl, TCoeEvent aEventType )
       
   219     {
       
   220     if ( aEventType == MCoeControlObserver::EEventStateChanged )
       
   221         {
       
   222         // Give dialer a chance to update editor state before handling the button press.
       
   223         // Used to reconfigure editor after user has closed virtual keyboard.
       
   224         iParentControl.PrepareForFocusGainL();
       
   225 
       
   226         // Handle button press. 
       
   227 
       
   228         // Multistate buttons change state automatically when pressed. 
       
   229         // Revert this change as we do not want to use states
       
   230         // for "toggle button" type of functionality but to give one button
       
   231         // different functions depending on the situation.
       
   232         // Must initiate button redraw so that the state change done here 
       
   233         // is drawn too; the automatically changed state is drawn within 
       
   234         // AknButton just before EEventStateChanged is reported 
       
   235         // (in emulator button icon flashing can be seen).
       
   236         UpdateButtonStates();
       
   237         aControl->DrawNow();
       
   238 
       
   239         // Handle the command attached to the button
       
   240         CAknButton* button = static_cast<CAknButton*>( aControl );
       
   241         TInt commandId = ButtonCommand( *button );
       
   242         
       
   243         if ( commandId == EPhoneDialerCmdClear )
       
   244             {
       
   245             SimulateBackspace();
       
   246             }
       
   247         else
       
   248             {
       
   249             // Forward pressed toolbar button to the framework 
       
   250             // so that we can handle it in active state
       
   251             CAknAppUi* appUi = static_cast<CAknAppUi*>( iCoeEnv->AppUi() );
       
   252             appUi->ProcessCommandL( commandId );  
       
   253             }
       
   254         }
       
   255     }
       
   256 
       
   257 // ---------------------------------------------------------------------------
       
   258 // HandlePointerEventL
       
   259 //
       
   260 // ---------------------------------------------------------------------------
       
   261 //
       
   262 void CDialerToolbarContainer::HandlePointerEventL( const TPointerEvent& aPointerEvent )
       
   263     {
       
   264     iLatestPointerEvent = aPointerEvent;
       
   265     CCoeControl::HandlePointerEventL( aPointerEvent );
       
   266     }
       
   267 
       
   268 // ---------------------------------------------------------------------------
       
   269 // HandleGainingForeground
       
   270 //
       
   271 // ---------------------------------------------------------------------------
       
   272 //
       
   273 void CDialerToolbarContainer::HandleGainingForeground()
       
   274     {
       
   275     // no implementation needed
       
   276     }
       
   277 
       
   278 // ---------------------------------------------------------------------------
       
   279 // HandleLosingForeground
       
   280 //
       
   281 // ---------------------------------------------------------------------------
       
   282 //
       
   283 void CDialerToolbarContainer::HandleLosingForeground()
       
   284     {
       
   285     // This is needed when dialer control disappeares during keypress. 
       
   286     // Last pressed pointer event must be forwarted to framework 
       
   287     // as pointer up event. Thus button is set to unpressed state etc.
       
   288     // This code calls HandlePointerEventL of the parent class instead of this.
       
   289     // If we call this classes HandlePointerEventL, this classes 
       
   290     // grab status is not cleared, and later coming EButton1Up events may end
       
   291     // up erroneously to this class, although intended elsewhere.
       
   292     // 
       
   293     if ( iLatestPointerEvent.iType != TPointerEvent::EButton1Up && Parent() )
       
   294         {    
       
   295         iLatestPointerEvent.iType = TPointerEvent::EButton1Up;
       
   296         TRAP_IGNORE( Parent()->HandlePointerEventL( iLatestPointerEvent ) );
       
   297         }    
       
   298     }
       
   299 
       
   300 // ---------------------------------------------------------------------------
       
   301 // CreateButtonsL
       
   302 //
       
   303 // ---------------------------------------------------------------------------
       
   304 //
       
   305 void CDialerToolbarContainer::CreateButtonsL()
       
   306     {
       
   307     // Create the avkon button objects
       
   308     for ( TInt i = 0 ; i < MPhoneDialerController::ENumberOfButtons ; ++i )
       
   309         {
       
   310         CAknButton* button = CAknButton::NewLC();
       
   311         button->SetContainerWindowL( *this ); // this sets also parent and mopParent
       
   312         button->SetObserver( this );
       
   313         button->SetIconScaleMode( EAspectRatioPreserved );
       
   314         AknsUtils::RegisterControlPosition( button );
       
   315         button->ActivateL();
       
   316         iButtons.AppendL( button );
       
   317         CleanupStack::Pop( button );
       
   318         iButtonCommands.AppendL( RArray<TInt>() );
       
   319         }
       
   320 
       
   321     // Backspace button has auto-repeat feature
       
   322     iButtons[MPhoneDialerController::EClearButton]->SetButtonFlags( KAknButtonKeyRepeat );
       
   323     iButtons[MPhoneDialerController::EClearButton]->SetKeyRepeatInterval( 
       
   324         KDialerToolbarButtonKeyRepeatDelay, KDialerToolbarKeyRepeatInterval );
       
   325     
       
   326     // Call button doesn't use default button background but a green one 
       
   327     // (same as used by in-call view for answer button)
       
   328     iButtons[MPhoneDialerController::ECallButton]->SetFrameAndCenterIds( 
       
   329             KAknsIIDQsnFrButtonNormalAnswer, KAknsIIDQsnFrButtonNormalAnswerCenter,
       
   330             KAknsIIDQsnFrButtonPressedAnswer, KAknsIIDQsnFrButtonPressedAnswerCenter, 
       
   331             KAknsIIDQsnFrButtonInactiveAnswer, KAknsIIDQsnFrButtonInactiveAnswerCenter, 
       
   332             KAknsIIDQsnFrButtonPressedAnswer, KAknsIIDQsnFrButtonPressedAnswerCenter, 
       
   333             KAknsIIDQsnFrButtonInactiveAnswer, KAknsIIDQsnFrButtonInactiveAnswerCenter
       
   334             );
       
   335         
       
   336     // Add button states
       
   337     if ( iContentProvider )
       
   338         {
       
   339         for ( TInt i = 0 ; i < MPhoneDialerController::ENumberOfButtons ; ++i )
       
   340             {
       
   341             MPhoneDialerController::TButtonIndex btnIdx =
       
   342                 static_cast< MPhoneDialerController::TButtonIndex >( i );
       
   343             RPointerArray< MPhoneDialerController::CButtonData > states;
       
   344             CleanupClosePushL( states );
       
   345             iContentProvider->GetButtonData( btnIdx, states );
       
   346             for ( TInt j = 0 ; j < states.Count() ; ++j )
       
   347                 {
       
   348                 TRAP_IGNORE( AddButtonStateL( i, *states[j] ) );
       
   349                 delete states[j];
       
   350                 states[j] = NULL;
       
   351                 }
       
   352             CleanupStack::PopAndDestroy( &states );
       
   353             }
       
   354         }
       
   355     }
       
   356 
       
   357 // ---------------------------------------------------------------------------
       
   358 // DeleteButtons
       
   359 // Reset internal arrays holding the button data
       
   360 // ---------------------------------------------------------------------------
       
   361 //
       
   362 void CDialerToolbarContainer::DeleteButtons()
       
   363     {
       
   364     for ( TInt i = 0 ; i < iButtons.Count() ; ++i )
       
   365         {
       
   366         AknsUtils::DeregisterControlPosition( iButtons[i] );
       
   367         }
       
   368     iButtons.ResetAndDestroy();
       
   369     
       
   370     for ( TInt i = 0 ; i < iButtonCommands.Count() ; ++i )
       
   371         {
       
   372         iButtonCommands[i].Reset();
       
   373         }
       
   374     iButtonCommands.Reset();
       
   375     }
       
   376 
       
   377 // ---------------------------------------------------------------------------
       
   378 // AddButtonStateL
       
   379 //
       
   380 // ---------------------------------------------------------------------------
       
   381 //
       
   382 void CDialerToolbarContainer::AddButtonStateL( TInt aButtonIndex, 
       
   383         MPhoneDialerController::CButtonData& aButtonData )
       
   384     {
       
   385     iButtons[ aButtonIndex ]->AddStateL(
       
   386             aButtonData.iIcon,      //CGulIcon* aIcon, 
       
   387             NULL,                   //CGulIcon* aDimmedIcon, 
       
   388             NULL,                   //CGulIcon* aPressedIcon,
       
   389             NULL,                   //CGulIcon* aHoverIcon,
       
   390             KNullDesC,              //const TDesC& aText, 
       
   391             *aButtonData.iTooltip,  //const TDesC& aHelpText, 
       
   392             0 );                    //const TInt aStateFlags
       
   393     aButtonData.iIcon = NULL; // ownership transferred
       
   394     iButtonCommands[ aButtonIndex ].AppendL( aButtonData.iCommandId );
       
   395     }
       
   396 
       
   397 // ---------------------------------------------------------------------------
       
   398 // ButtonCommand
       
   399 //
       
   400 // ---------------------------------------------------------------------------
       
   401 //
       
   402 TInt CDialerToolbarContainer::ButtonCommand( const CAknButton& aButton ) const
       
   403     {
       
   404     TInt commandId = KErrNotFound;
       
   405     
       
   406     // Find out index of the button in iButtons array
       
   407     TInt btnIndex = iButtons.Find( &aButton );
       
   408     __ASSERT_DEBUG( btnIndex >= 0, DialerPanic( EDialerPanicToolbarButtonNotFound ) );
       
   409     
       
   410     // Find the corresponding command from command array
       
   411     TInt btnStateIdx = aButton.StateIndex();
       
   412     if ( btnIndex < iButtonCommands.Count() &&
       
   413          btnStateIdx < iButtonCommands[btnIndex].Count() )
       
   414         {
       
   415         commandId = iButtonCommands[btnIndex][btnStateIdx];
       
   416         }
       
   417     
       
   418     __ASSERT_DEBUG( commandId != KErrNotFound, DialerPanic( EDialerPanicToolbarButtonNotFound ) );
       
   419     return commandId;
       
   420     }
       
   421 
       
   422 // ---------------------------------------------------------------------------
       
   423 // LayoutButton
       
   424 // Set layout for one button.
       
   425 // ---------------------------------------------------------------------------
       
   426 //
       
   427 TPoint CDialerToolbarContainer::LayoutButton( TInt aButtonIdx, TPoint aPos )
       
   428     {
       
   429     TRect parentRect = Rect();
       
   430 
       
   431     TAknWindowComponentLayout buttonLayout = 
       
   432         ( aButtonIdx == MPhoneDialerController::ECallButton ? 
       
   433           AknLayoutScalable_Apps::cell_dia3_key1_fun_pane( iVariety ) :
       
   434           AknLayoutScalable_Apps::cell_dia3_key0_fun_pane( iVariety ) );
       
   435         
       
   436     TAknLayoutRect layoutRect;
       
   437     layoutRect.LayoutRect( parentRect, buttonLayout );
       
   438     TRect outerRect = layoutRect.Rect();
       
   439     outerRect.SetRect( aPos, outerRect.Size() );
       
   440 
       
   441     TRect innerRect = outerRect;
       
   442     innerRect.Shrink( 1, 1 );
       
   443     iButtons[ aButtonIdx ]->SetRect( innerRect );
       
   444     AknsUtils::RegisterControlPosition( iButtons[ aButtonIdx ] );
       
   445     
       
   446     // Calculate position for the next button
       
   447     TPoint nextPos = aPos;
       
   448     if ( iVariety == EDialerVarietyPortrait )
       
   449         {
       
   450         nextPos.iY += outerRect.Height();
       
   451         }
       
   452     else
       
   453         {
       
   454         nextPos.iX += outerRect.Width();
       
   455         }
       
   456     
       
   457     return nextPos;
       
   458     }
       
   459 
       
   460 // ---------------------------------------------------------------------------
       
   461 // SimulateBackspace
       
   462 // Simulate backspace press including key down event, key event, and key up 
       
   463 // event
       
   464 // ---------------------------------------------------------------------------
       
   465 //
       
   466 void CDialerToolbarContainer::SimulateBackspace()
       
   467     {
       
   468     TKeyEvent keyEvent;
       
   469     keyEvent.iModifiers = 0;
       
   470     keyEvent.iRepeats = 0;
       
   471     keyEvent.iCode = 0; // key code is always 0 for key up and down events
       
   472     keyEvent.iScanCode = EStdKeyBackspace;
       
   473 
       
   474     TRAP_IGNORE( iCoeEnv->SimulateKeyEventL( keyEvent, EEventKeyDown ) );
       
   475 
       
   476     keyEvent.iCode = EKeyBackspace;
       
   477     TRAP_IGNORE( iCoeEnv->SimulateKeyEventL( keyEvent, EEventKey ) );
       
   478     
       
   479     keyEvent.iCode = 0;
       
   480     TRAP_IGNORE( iCoeEnv->SimulateKeyEventL( keyEvent, EEventKeyUp ) );
       
   481     }
       
   482 
       
   483 // end of file