phoneuis/dialer/src/cdialertoolbarcontainer.cpp
branchRCL_3
changeset 9 8871b09be73b
child 15 2a26698d78ba
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/phoneuis/dialer/src/cdialertoolbarcontainer.cpp	Fri Feb 19 22:50:26 2010 +0200
@@ -0,0 +1,461 @@
+/*
+* Copyright (c) 2009, 2010 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:  CDialerToolbarContainer replaces the standard S60 toolbar
+*               in the Dialer layout in the Easy dialing mode. It's 
+*               responsible of the toolbar layout and logic, but not of the 
+*               contents which are provided by an instance of 
+*               MPhoneDialerController.
+*
+*/
+
+#include <aknbutton.h>
+#include <aknappui.h>
+#include <AknsUtils.h>
+#include <aknlayoutscalable_apps.cdl.h>
+#include <layoutmetadata.cdl.h>
+#include <phoneui.rsg>
+#include <phoneappcommands.hrh>
+#include <StringLoader.h>
+#include <data_caging_path_literals.hrh>
+
+#include "dialercommon.h"
+#include "cdialertoolbarcontainer.h"
+
+
+// CONSTANTS
+const TInt KDialerToolbarButtonKeyRepeatDelay = 300;
+const TInt KDialerToolbarKeyRepeatInterval = 75;
+
+
+
+// CLASS DEFINITION
+
+// ---------------------------------------------------------------------------
+// NewL
+//
+// ---------------------------------------------------------------------------
+//
+CDialerToolbarContainer* CDialerToolbarContainer::NewL( CCoeControl& aParent,
+        MPhoneDialerController* aContentProvider )
+    {
+    CDialerToolbarContainer* self = 
+            new (ELeave) CDialerToolbarContainer( aParent, aContentProvider );
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+// ---------------------------------------------------------------------------
+// CDialerToolbarContainer
+//
+// ---------------------------------------------------------------------------
+//
+CDialerToolbarContainer::CDialerToolbarContainer( CCoeControl& aParent,
+        MPhoneDialerController* aContentProvider ) : 
+    CDialerContainerBase( aParent ), 
+    iContentProvider( aContentProvider )
+    {
+    }
+
+// ---------------------------------------------------------------------------
+// ~CDialerToolbarContainer
+//
+// ---------------------------------------------------------------------------
+//
+CDialerToolbarContainer::~CDialerToolbarContainer()
+    {
+    iCoeEnv->RemoveForegroundObserver( *this );
+    DeleteButtons();
+    }
+
+// ---------------------------------------------------------------------------
+// ConstructL
+//
+// ---------------------------------------------------------------------------
+//
+void CDialerToolbarContainer::ConstructL()
+    {
+    BaseConstructL();
+    
+    CreateButtonsL();
+
+    iCoeEnv->AddForegroundObserverL( *this );
+    }
+
+// ---------------------------------------------------------------------------
+// SetContentProviderL
+//
+// ---------------------------------------------------------------------------
+//
+void CDialerToolbarContainer::SetContentProviderL( MPhoneDialerController* aProvider )
+    {
+    if ( iContentProvider != aProvider )
+        {
+        iContentProvider = aProvider;
+        
+        // Recreate buttons to reset available button states
+        DeleteButtons();
+        CreateButtonsL();
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// UpdateButtonStates
+//
+// ---------------------------------------------------------------------------
+//
+void CDialerToolbarContainer::UpdateButtonStates()
+    {
+    // safety check
+    if ( iButtons.Count() < MPhoneDialerController::ENumberOfButtons ||
+         !iContentProvider )
+        {
+        return;
+        }
+    
+    for ( TInt i = 0 ; i < MPhoneDialerController::ENumberOfButtons ; ++i )
+        {
+        MPhoneDialerController::TButtonIndex idx =
+            static_cast< MPhoneDialerController::TButtonIndex >( i );
+        TInt state = iContentProvider->ButtonState( idx );
+        TBool dimmed = iContentProvider->ButtonDimmed( idx );
+        if ( state >= 0 )
+            {
+            iButtons[i]->SetCurrentState( state, EFalse );
+            }
+        iButtons[i]->SetDimmed( dimmed );
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// SetVariety
+//
+// ---------------------------------------------------------------------------
+//
+void CDialerToolbarContainer::SetVariety()
+    {
+    iVariety = ( Layout_Meta_Data::IsLandscapeOrientation() ?
+        EDialerVarietyLandscape : EDialerVarietyPortrait );
+    }
+
+// ---------------------------------------------------------------------------
+// SetLayout
+//
+// ---------------------------------------------------------------------------
+//
+void CDialerToolbarContainer::SetLayout()
+    {
+    if ( iButtons.Count() < MPhoneDialerController::ENumberOfButtons )
+        {
+        return;
+        }
+    
+    // Position for the first button
+    TPoint buttonPos = Rect().iTl;
+    
+    if ( iVariety == EDialerVarietyPortrait )
+        {
+        // In portrait, buttons are laid out from top to bottom
+        for ( TInt i = 0 ; i < iButtons.Count() ; ++i )
+            {
+            buttonPos = LayoutButton( i, buttonPos );
+            }
+        }
+    else
+        {
+        // In landscape, buttons are laid out from right to left.
+        // This is achieved by looping button array backwards and laying
+        // those out from left to right.
+        for ( TInt i = iButtons.Count()-1 ; i >= 0  ; --i )
+            {
+            buttonPos = LayoutButton( i, buttonPos );
+            }
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CountComponentControls
+//
+// ---------------------------------------------------------------------------
+//
+TInt CDialerToolbarContainer::CountComponentControls() const
+    {
+    return iButtons.Count();
+    }
+
+// ---------------------------------------------------------------------------
+// ComponentControl
+//
+// ---------------------------------------------------------------------------
+//
+CCoeControl* CDialerToolbarContainer::ComponentControl( TInt aIndex ) const
+    {
+    CCoeControl* control = NULL;
+    if ( aIndex >= 0 && aIndex < iButtons.Count() )
+        {
+        control = iButtons[ aIndex ];
+        }
+    return control;
+    }
+
+// ---------------------------------------------------------------------------
+// HandleControlEventL
+//
+// ---------------------------------------------------------------------------
+//
+void CDialerToolbarContainer::HandleControlEventL( CCoeControl* aControl, TCoeEvent aEventType )
+    {
+    if ( aEventType == MCoeControlObserver::EEventStateChanged )
+        {
+        // Handle button press. 
+
+        // Multistate buttons change state automatically when pressed. 
+        // Revert this change as we do not want to use states
+        // for "toggle button" type of functionality but to give one button
+        // different functions depending on the situation.
+        UpdateButtonStates();
+
+        // Handle the command attached to the button
+        CAknButton* button = static_cast<CAknButton*>( aControl );
+        TInt commandId = ButtonCommand( *button );
+        
+        if ( commandId == EPhoneDialerCmdClear )
+            {
+            // simulate backspace
+            TKeyEvent keyEvent;
+            keyEvent.iModifiers = 0;
+            keyEvent.iRepeats = 0;
+            keyEvent.iCode = EKeyBackspace;
+            keyEvent.iScanCode = EStdKeyBackspace;
+            iCoeEnv->SimulateKeyEventL( keyEvent, EEventKey );
+            }
+        else
+            {
+            // Forward pressed toolbar button to the framework 
+            // so that we can handle it in active state
+            CAknAppUi* appUi = static_cast<CAknAppUi*>( iCoeEnv->AppUi() );
+            appUi->ProcessCommandL( commandId );  
+            }
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// HandlePointerEventL
+//
+// ---------------------------------------------------------------------------
+//
+void CDialerToolbarContainer::HandlePointerEventL( const TPointerEvent& aPointerEvent )
+    {
+    iLatestPointerEvent = aPointerEvent;
+    CCoeControl::HandlePointerEventL( aPointerEvent );
+    }
+
+// ---------------------------------------------------------------------------
+// HandleGainingForeground
+//
+// ---------------------------------------------------------------------------
+//
+void CDialerToolbarContainer::HandleGainingForeground()
+    {
+    // no implementation needed
+    }
+    
+// ---------------------------------------------------------------------------
+// HandleLosingForeground
+//
+// ---------------------------------------------------------------------------
+//
+void CDialerToolbarContainer::HandleLosingForeground()
+    {
+    // This is needed when dialer control disappeares during keypress. 
+    // Last pressed pointer event must be forwarted to framework 
+    // as pointer up event. Thus button is set to unpressed state etc. 
+    // 
+    if ( iLatestPointerEvent.iType != TPointerEvent::EButton1Up )
+        {    
+        iLatestPointerEvent.iType = TPointerEvent::EButton1Up;
+        TRAP_IGNORE( HandlePointerEventL( iLatestPointerEvent ) );
+        }    
+    }
+
+// ---------------------------------------------------------------------------
+// CreateButtonsL
+//
+// ---------------------------------------------------------------------------
+//
+void CDialerToolbarContainer::CreateButtonsL()
+    {
+    // Create the avkon button objects
+    for ( TInt i = 0 ; i < MPhoneDialerController::ENumberOfButtons ; ++i )
+        {
+        CAknButton* button = CAknButton::NewLC();
+        button->SetContainerWindowL( *this ); // this sets also parent and mopParent
+        button->SetObserver( this );
+        button->SetIconScaleMode( EAspectRatioPreserved );
+        AknsUtils::RegisterControlPosition( button );
+        button->ActivateL();
+        iButtons.AppendL( button );
+        CleanupStack::Pop( button );
+        iButtonCommands.AppendL( RArray<TInt>() );
+        }
+
+    // Backspace button has auto-repeat feature
+    iButtons[MPhoneDialerController::EClearButton]->SetButtonFlags( KAknButtonKeyRepeat );
+    iButtons[MPhoneDialerController::EClearButton]->SetKeyRepeatInterval( 
+        KDialerToolbarButtonKeyRepeatDelay, KDialerToolbarKeyRepeatInterval );
+    
+    // Call button doesn't use default button background but a green one 
+    // (same as used by in-call view for answer button)
+    iButtons[MPhoneDialerController::ECallButton]->SetFrameAndCenterIds( 
+            KAknsIIDQsnFrButtonNormalAnswer, KAknsIIDQsnFrButtonNormalAnswerCenter,
+            KAknsIIDQsnFrButtonPressedAnswer, KAknsIIDQsnFrButtonPressedAnswerCenter, 
+            KAknsIIDQsnFrButtonInactiveAnswer, KAknsIIDQsnFrButtonInactiveAnswerCenter, 
+            KAknsIIDQsnFrButtonPressedAnswer, KAknsIIDQsnFrButtonPressedAnswerCenter, 
+            KAknsIIDQsnFrButtonInactiveAnswer, KAknsIIDQsnFrButtonInactiveAnswerCenter
+            );
+        
+    // Add button states
+    if ( iContentProvider )
+        {
+        for ( TInt i = 0 ; i < MPhoneDialerController::ENumberOfButtons ; ++i )
+            {
+            MPhoneDialerController::TButtonIndex btnIdx =
+                static_cast< MPhoneDialerController::TButtonIndex >( i );
+            RPointerArray< MPhoneDialerController::CButtonData > states;
+            CleanupClosePushL( states );
+            iContentProvider->GetButtonData( btnIdx, states );
+            for ( TInt j = 0 ; j < states.Count() ; ++j )
+                {
+                TRAP_IGNORE( AddButtonStateL( i, *states[j] ) );
+                delete states[j];
+                states[j] = NULL;
+                }
+            CleanupStack::PopAndDestroy( &states );
+            }
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// DeleteButtons
+// Reset internal arrays holding the button data
+// ---------------------------------------------------------------------------
+//
+void CDialerToolbarContainer::DeleteButtons()
+    {
+    for ( TInt i = 0 ; i < iButtons.Count() ; ++i )
+        {
+        AknsUtils::DeregisterControlPosition( iButtons[i] );
+        }
+    iButtons.ResetAndDestroy();
+    
+    for ( TInt i = 0 ; i < iButtonCommands.Count() ; ++i )
+        {
+        iButtonCommands[i].Reset();
+        }
+    iButtonCommands.Reset();
+    }
+
+// ---------------------------------------------------------------------------
+// AddButtonStateL
+//
+// ---------------------------------------------------------------------------
+//
+void CDialerToolbarContainer::AddButtonStateL( TInt aButtonIndex, 
+        MPhoneDialerController::CButtonData& aButtonData )
+    {
+    iButtons[ aButtonIndex ]->AddStateL(
+            aButtonData.iIcon,      //CGulIcon* aIcon, 
+            NULL,                   //CGulIcon* aDimmedIcon, 
+            NULL,                   //CGulIcon* aPressedIcon,
+            NULL,                   //CGulIcon* aHoverIcon,
+            KNullDesC,              //const TDesC& aText, 
+            *aButtonData.iTooltip,  //const TDesC& aHelpText, 
+            0 );                    //const TInt aStateFlags
+    aButtonData.iIcon = NULL; // ownership transferred
+    iButtonCommands[ aButtonIndex ].AppendL( aButtonData.iCommandId );
+    }
+
+// ---------------------------------------------------------------------------
+// ButtonCommand
+//
+// ---------------------------------------------------------------------------
+//
+TInt CDialerToolbarContainer::ButtonCommand( const CAknButton& aButton ) const
+    {
+    TInt commandId = KErrNotFound;
+    
+    // Find out index of the button in iButtons array
+    TInt btnIndex = KErrNotFound;
+    for ( TInt i = 0 ; i < iButtons.Count() ; ++i )
+        {
+        if ( iButtons[i] == &aButton )
+            {
+            btnIndex = i;
+            i = iButtons.Count(); // to break out of the loop
+            }
+        }
+    __ASSERT_DEBUG( btnIndex >= 0, DialerPanic( EDialerPanicToolbarButtonNotFound ) );
+    
+    // Find the corresponding command from command array
+    TInt btnStateIdx = aButton.StateIndex();
+    if ( btnIndex < iButtonCommands.Count() &&
+         btnStateIdx < iButtonCommands[btnIndex].Count() )
+        {
+        commandId = iButtonCommands[btnIndex][btnStateIdx];
+        }
+    
+    __ASSERT_DEBUG( commandId != KErrNotFound, DialerPanic( EDialerPanicToolbarButtonNotFound ) );
+    return commandId;
+    }
+
+// ---------------------------------------------------------------------------
+// LayoutButton
+// Set layout for one button.
+// ---------------------------------------------------------------------------
+//
+TPoint CDialerToolbarContainer::LayoutButton( TInt aButtonIdx, TPoint aPos )
+    {
+    TRect parentRect = Rect();
+
+    TAknWindowComponentLayout buttonLayout = 
+        ( aButtonIdx == MPhoneDialerController::ECallButton ? 
+          AknLayoutScalable_Apps::cell_dia3_key1_fun_pane( iVariety ) :
+          AknLayoutScalable_Apps::cell_dia3_key0_fun_pane( iVariety ) );
+        
+    TAknLayoutRect layoutRect;
+    layoutRect.LayoutRect( parentRect, buttonLayout );
+    TRect outerRect = layoutRect.Rect();
+    outerRect.SetRect( aPos, outerRect.Size() );
+
+    TRect innerRect = outerRect;
+    innerRect.Shrink( 1, 1 );
+    iButtons[ aButtonIdx ]->SetRect( innerRect );
+    AknsUtils::RegisterControlPosition( iButtons[ aButtonIdx ] );
+    
+    // Calculate position for the next button
+    TPoint nextPos = aPos;
+    if ( iVariety == EDialerVarietyPortrait )
+        {
+        nextPos.iY += outerRect.Height();
+        }
+    else
+        {
+        nextPos.iX += outerRect.Width();
+        }
+    
+    return nextPos;
+    }
+
+// end of file