/*
* 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: Shows number keypad and generates keypress event when
* buttons are pressed.
*
*/
// INCLUDE FILES
#include <gulicon.h>
#include <AknUtils.h>
#include <aknbutton.h>
#include <AknControl.h>
#include <AknsUtils.h>
#include <AknsSkinInstance.h>
#include <AknsDrawUtils.h>
#include <data_caging_path_literals.hrh> // for KDC_APP_RESOURCE_DIR
#include <touchfeedback.h>
#include <aknlayoutscalable_avkon.cdl.h>
#include <aknlayoutscalable_apps.cdl.h>
#include <AknsFrameBackgroundControlContext.h>
#include "dialercommon.h"
#include "dialertrace.h"
#include "cdialerkeypadbutton.h"
_LIT( KDialerMifFileName, "dialer.mif" );
// Keypad icon size relative to height of button.
static const TInt KIconSizePercent = 40;
// Keypad icon size used when key has already two lines
// of text, and the icon needs to be squeezed into smaller space.
static const TInt KSmallIconSizePercent = 30;
// Horizontal icon margin relative to button width.
static const TInt KIconMarginXPercent = 10;
// Vertical icon margin relative to button height.
static const TInt KIconMarginYPercent = 5;
static const TInt KCent = 100;
// Copied from CAknButton
const TInt KDragEventSensitivity = 1;
// ---------------------------------------------------------------------------
// C++ default constructor
// ---------------------------------------------------------------------------
//
CDialerKeyPadButton::CDialerKeyPadButton( const TDesC& aNumberLabel,
const TDesC& aPrimaryAlphaLabel,
const TDesC& aSecondaryAlphaLabel,
TInt aScanCode,
TInt aKeyCode,
TMifDialer aButtonIconId,
TMifDialer aButtonIconMaskId,
TInt aFlags ):
CAknButton( aFlags ),
iScanCode( aScanCode ),
iKeyCode( aKeyCode ),
iButtonIconId( aButtonIconId ),
iButtonIconMaskId( aButtonIconMaskId ),
iNumberLabel( aNumberLabel ),
iPrimaryAlphaLabel( aPrimaryAlphaLabel ),
iSecondaryAlphaLabel( aSecondaryAlphaLabel )
{
}
// -----------------------------------------------------------------------------
// CDialerKeyPadButton::NewLC
// Two-phased constructor.
// Constructs dialer button.
// -----------------------------------------------------------------------------
//
CDialerKeyPadButton* CDialerKeyPadButton::NewLC( const TDesC& aNumberLabel,
const TDesC& aPrimaryAlphaLabel,
const TDesC& aSecondaryAlphaLabel,
TInt aScanCode,
TInt aKeyCode,
TMifDialer aButtonIconId,
TMifDialer aButtonIconMaskId,
TInt aFlags )
{
CDialerKeyPadButton* self = new (ELeave) CDialerKeyPadButton( aNumberLabel,
aPrimaryAlphaLabel,
aSecondaryAlphaLabel,
aScanCode,
aKeyCode,
aButtonIconId,
aButtonIconMaskId,
aFlags );
CleanupStack::PushL( self );
self->ConstructL( aFlags );
return self;
}
// -----------------------------------------------------------------------------
// CDialerKeyPadButton::ConstructL
// Symbian 2nd phase constructor for dialer button.
// -----------------------------------------------------------------------------
//
void CDialerKeyPadButton::ConstructL( TInt aFlags )
{
CAknButton::ConstructL( NULL, NULL, NULL, NULL, KNullDesC, KNullDesC, aFlags );
UpdateIconL();
// button text color
SetTextColorIds( KAknsIIDQsnTextColors, EAknsCIQsnTextColorsCG65 );
SetIconScaleMode( EAspectRatioPreserved );
SetMargins( TMargins8(0,0,0,0) );
AknsUtils::RegisterControlPosition( this );
}
// ---------------------------------------------------------------------------
// Destructor
// ---------------------------------------------------------------------------
//
CDialerKeyPadButton::~CDialerKeyPadButton()
{
AknsUtils::DeregisterControlPosition( this );
MTouchFeedback* feedback = MTouchFeedback::Instance();
if ( feedback )
{
feedback->RemoveFeedbackForControl( this );
}
}
// ---------------------------------------------------------------------------
// Draw dialer button, text and icon.
// ---------------------------------------------------------------------------
//
void CDialerKeyPadButton::Draw( const TRect& aRect ) const
{
TAknLayoutRect centerLayout;
centerLayout.LayoutRect( aRect,
AknLayoutScalable_Avkon::toolbar_button_pane_g1().LayoutLine() );
TRect innerRect = centerLayout.Rect();
CWindowGc& gc = SystemGc();
MAknsSkinInstance* skin = AknsUtils::SkinInstance();
TAknsItemID frameId = KAknsIIDQsnFrButtonNormal;
if ( iButtonPressed )
{
frameId = KAknsIIDQsnFrButtonPressed;
}
else if ( IsDimmed() )
{
frameId = KAknsIIDQsnFrButtonInactive;
}
iBgContext->SetFrame( frameId );
iBgContext->SetCenter( KAknsIIDQsnFrButtonCenterNormal );
iBgContext->SetFrameRects( aRect, innerRect );
TBool bgDrawn = AknsDrawUtils::Background( skin,
iBgContext,
NULL,
gc,
aRect,
KAknsDrawParamNoClearUnderImage );
__ASSERT_DEBUG( bgDrawn, DialerPanic( EDialerPanicDrawingError ) );
DrawIconAndText( gc );
}
// -----------------------------------------------------------------------------
// Respond to changes in the button size
// -----------------------------------------------------------------------------
//
void CDialerKeyPadButton::SizeChanged()
{
CAknButton::SizeChanged();
AknsUtils::RegisterControlPosition( this );
TRect buttonRect = Rect();
TAknLayoutRect iconLayout;
const CGulIcon* icon = GetCurrentIcon();
if ( iOperationMode == EModeEasyDialing )
{
// Number layout
TAknTextComponentLayout numLayout =
AknLayoutScalable_Apps::cell_dia3_key_num_pane_t1( iVariety );
// Center the number label if key doens't contain any alphabets or icon.
if ( !icon && !iPrimaryAlphaLabel.Length() && !iSecondaryAlphaLabel.Length() )
{
// eliminate margins, alignment takes care of correct position
numLayout.Setl( 0 );
numLayout.Setr( 0 );
numLayout.SetJ( 1 ); // ID for center alignment
}
iNumberLayout.LayoutText( buttonRect, numLayout );
// Alphabet layout is different if two rows of alphabets are given
if ( iSecondaryAlphaLabel.Length() )
{
iPrimaryAlphaLayout.LayoutText( buttonRect,
AknLayoutScalable_Apps::cell_dia3_key_num_pane_t3( iVariety ) );
iSecondaryAlphaLayout.LayoutText( buttonRect,
AknLayoutScalable_Apps::cell_dia3_key_num_pane_t4( iVariety ) );
}
else
{
iPrimaryAlphaLayout.LayoutText( buttonRect,
AknLayoutScalable_Apps::cell_dia3_key_num_pane_t2( iVariety ) );
}
}
else if ( iOperationMode == EModeDialer )
{
// Number layout
// Center number labels as only numbers are shown
TAknTextComponentLayout numLayout =
AknLayoutScalable_Apps::cell_dia3_key_num_pane_t1( iVariety );
// eliminate margins, alignment takes care of correct position
numLayout.Setl( 0 );
numLayout.Setr( 0 );
numLayout.SetJ( 1 ); // ID for center alignment
iNumberLayout.LayoutText( buttonRect, numLayout );
}
else // video mode layout
{
// Number layout
iNumberLayout.LayoutText( buttonRect,
AknLayoutScalable_Apps::cell_video_dialer_keypad_pane_t1() );
}
SetIconLayout( buttonRect );
}
// ---------------------------------------------------------------------------
// Pointer event handling. Implemented here just to detect when touch is
// dragged outside pressed button as no appropriate control event is sent
// by CAknButton when this happens.
// ---------------------------------------------------------------------------
//
void CDialerKeyPadButton::HandlePointerEventL( const TPointerEvent& aPointerEvent )
{
// Do the check before forwarding events to base class as it will update
// iButtonPressed member variable used here.
// Own drag event counter has to be used.
// Logic here to determine whether pointer is dragged outside button is
// the same as used in CAknButton.
if ( State() && IsVisible() )
{
if ( aPointerEvent.iType == TPointerEvent::EButton1Down )
{
iDragEventCounter = 0;
}
else if ( aPointerEvent.iType == TPointerEvent::EDrag )
{
iDragEventCounter++;
if ( iDragEventCounter >= KDragEventSensitivity )
{
iDragEventCounter = 0;
TBool buttonEvent( Rect().Contains( aPointerEvent.iPosition ) );
// Pointer is dragged outside the pressed button area
if ( !buttonEvent && iButtonPressed && Observer() )
{
Observer()->HandleControlEventL( this,
static_cast<MCoeControlObserver::TCoeEvent>(
CDialerKeyPadButton::EEventDraggingOutsideButton ) );
}
}
}
}
CAknButton::HandlePointerEventL( aPointerEvent );
}
// -----------------------------------------------------------------------------
// Gets the correct text color.
// -----------------------------------------------------------------------------
//
void CDialerKeyPadButton::GetTextColors( TRgb& aPenColor, TRgb& aBrushColor ) const
{
aBrushColor = iEikonEnv->ControlColor( EColorControlBackground, *this );
if ( iButtonPressed )
{
aPenColor = iEikonEnv->ControlColor( EColorButtonTextPressed, *this );
}
else
{
aPenColor = iEikonEnv->ControlColor( EColorButtonText, *this );
}
}
// --------------------------------------------------------------------------
// Draw text and icon according to the layout.
// --------------------------------------------------------------------------
//
void CDialerKeyPadButton::DrawIconAndText( CWindowGc& aGc ) const
{
TRect parentRect( Rect() );
TAknLayoutText buttonText;
TAknLayoutRect layoutRect;
TRgb penColor;
TRgb brushColor;
GetTextColors( penColor, brushColor );
// Don't ues logical-to-visual conversion, strings in our keypad resources are already
// in visual order.
TBool logToVisConv = EFalse;
iNumberLayout.DrawText( aGc, iNumberLabel, logToVisConv, penColor );
// Draw also alphabet label(s) in Easy Dialing mode
if ( iOperationMode == EModeEasyDialing )
{
if ( iPrimaryAlphaLabel.Length() )
{
iPrimaryAlphaLayout.DrawText( aGc, iPrimaryAlphaLabel, logToVisConv, penColor );
}
if ( iSecondaryAlphaLabel.Length() )
{
iSecondaryAlphaLayout.DrawText( aGc, iSecondaryAlphaLabel, logToVisConv, penColor );
}
}
const CGulIcon* icon = GetCurrentIcon();
if ( icon )
{
CFbsBitmap* buttonBmp = icon->Bitmap();
CFbsBitmap* buttonMask = icon->Mask();
if ( buttonBmp && buttonMask )
{
aGc.BitBltMasked( iIconRect.iTl, buttonBmp,
iIconRect.Size(), buttonMask, ETrue );
}
}
}
// --------------------------------------------------------------------------
// Set layout data for text.
// --------------------------------------------------------------------------
void CDialerKeyPadButton::SetVariety( TInt aVariety )
{
iVariety = aVariety;
}
// --------------------------------------------------------------------------
// Set layout data for text.
// --------------------------------------------------------------------------
void CDialerKeyPadButton::SetOperationMode( TDialerOperationMode aMode )
{
iOperationMode = aMode;
}
// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
//
void CDialerKeyPadButton::SetNumLabel( const TDesC& aLabel )
{
iNumberLabel.Set( aLabel );
}
// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
//
void CDialerKeyPadButton::SetPrimaryAlphaLabel( const TDesC& aLabel )
{
iPrimaryAlphaLabel.Set( aLabel );
}
// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
//
void CDialerKeyPadButton::SetSecondaryAlphaLabel( const TDesC& aLabel )
{
iSecondaryAlphaLabel.Set( aLabel );
}
// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
//
TInt CDialerKeyPadButton::ScanCode() const
{
return iScanCode;
}
// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
//
TInt CDialerKeyPadButton::KeyCode() const
{
return iKeyCode;
}
// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
//
void CDialerKeyPadButton::MapDialerIconToSkinIcon(
TInt aDialerIcon, TAknsItemID& aItemId ) const
{
switch ( aDialerIcon )
{
case EMbmDialerQgn_indi_dialer_voicemail:
aItemId = KAknsIIDQgnIndiDialerVoicemail;
break;
default:
break;
}
}
// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
//
void CDialerKeyPadButton::SetIconLayout( const TRect& aRect )
{
// Calculate icon size and placement.
TInt iconSize = aRect.Height() * KIconSizePercent / KCent;
TInt xMargin = aRect.Width() * KIconMarginXPercent / KCent;
TInt yMargin = aRect.Height() * KIconMarginYPercent / KCent;
// Adapt icon size and vertical margin. If the button has
// already two lines of text, use smaller icon size
if ( iOperationMode == EModeEasyDialing && iSecondaryAlphaLabel.Length() )
{
iconSize = aRect.Height() * KSmallIconSizePercent / KCent;
yMargin = 0;
}
if ( AknLayoutUtils::LayoutMirrored() )
{
iIconRect.SetRect( aRect.iTl.iX + xMargin,
aRect.iTl.iY + yMargin,
aRect.iTl.iX + xMargin + iconSize,
aRect.iTl.iY + iconSize + yMargin );
}
else
{
iIconRect.SetRect( aRect.iBr.iX - iconSize - xMargin,
aRect.iTl.iY + yMargin,
aRect.iBr.iX - xMargin,
aRect.iTl.iY + iconSize + yMargin );
}
SetIconSize( iIconRect.Size() );
}
// ---------------------------------------------------------------------------
// Update icon when skin is changed
// ---------------------------------------------------------------------------
//
void CDialerKeyPadButton::UpdateIconL()
{
if ( KDialerNoIcon != iButtonIconId )
{
TFileName mifPath( KDriveZ );
mifPath.Append( KDC_APP_BITMAP_DIR );
mifPath.Append( KDialerMifFileName );
MAknsSkinInstance* skin = AknsUtils::SkinInstance();
CFbsBitmap* bitmap (NULL);
CFbsBitmap* mask (NULL);
// Get icon id.
TAknsItemID skinItemId( KAknsIIDNone );
MapDialerIconToSkinIcon( iButtonIconId, skinItemId );
AknsUtils::CreateColorIconLC(
skin,
skinItemId,
KAknsIIDQsnIconColors,
EAknsCIQsnIconColorsCG30,
bitmap,
mask,
mifPath,
iButtonIconId,
iButtonIconMaskId,
KRgbBlack
);
CGulIcon* icon = CGulIcon::NewL( bitmap, mask );
CleanupStack::Pop( 2 );
State()->SetIcon( icon ); // icon ownership transfered
}
}
// ---------------------------------------------------------------------------
//
// Enable or disable audio but keep vibra feedback
// ---------------------------------------------------------------------------
//
void CDialerKeyPadButton::EnableAudioFeedback( const TBool aEnable )
{
MTouchFeedback* feedback = MTouchFeedback::Instance();
if ( feedback )
{
feedback->EnableFeedbackForControl( this, ETrue, aEnable );
}
}
// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
//
void CDialerKeyPadButton::HandleResourceChange( TInt aType )
{
CAknButton::HandleResourceChange( aType );
if ( KAknsMessageSkinChange == aType )
{
TRAP_IGNORE( UpdateIconL() );
}
}
// End of File