/*
* Copyright (c) 2005-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: Button component
*
*/
// INCLUDE FILES
#include <aknbutton.h>
#include <gulicon.h> // CGulIcon
#include <barsread.h> // TResourceReader
#include <avkon.hrh>
#include <StringLoader.h> // StringLoader
#include <AknsDrawUtils.h>
#include <AknsControlContext.h>
#include <AknBidiTextUtils.h>
#include <aknlayout.cdl.h>
#include <aknlayoutscalable_avkon.cdl.h>
#include <AknInfoPopupNoteController.h>
#include <AknPictographInterface.h>
#include <AknPictographDrawerInterface.h>
#include <AknsFrameBackgroundControlContext.h>
#include <aknconsts.h>
#include <layoutmetadata.cdl.h>
#include <AknPriv.hrh>
#include <AknLayoutFont.h>
#include <akniconconfig.h>
#include <AknTasHook.h> // for testability hooks
#include "aknresourceprovider.h"
#include "aknbitmapresourceitem.h"
#include "akncommandbuttonstate.h"
#include <touchfeedback.h>
const TUint KPointerFlag = 3; // second bit
// CONSTANTS
enum TSkinItemIdIndex
{
KFrameId = 0,
KCenterId,
KLatchedFrameId,
KLatchedCenterId,
KDimmedFrameId,
KDimmedCenterId,
KPressedFrameId,
KPressedCenterId,
KLatchedDimmedFrameId,
KLatchedDimmedCenterId
};
// ATTENTION, if the values bellow are changed, make the changes in AknButton.h
const TInt KTimeoutBeforeHelpNote = 150; // in milliseconds
const TInt KTimeoutInViewHelpNote = 3000; // in milliseconds
const TInt KKeyRepeatDelay = 500000; // 0,5 seconds
const TInt KKeyRepeatInterval = 500000; // 0,5 seconds
const TInt KLongPressInterval = 800000; // 0,8 seconds
const TInt KDragEventSensitivity = 1;
// Value table for 70% Transparency
const TInt KTransparency[256] =
{
0, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 7, 7, 7,
8, 8, 8, 8, 9, 9, 9, 10, 10, 10, 11, 11, 11, 11, 12, 12, 12, 13, 13, 13,
14, 14, 14, 14, 15, 15, 15, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 19,
19, 19, 20, 20, 20, 20, 21, 21, 21, 22, 22, 22, 23, 23, 23, 23, 24, 24,
24, 25, 25, 25, 26, 26, 26, 26, 27, 27, 27, 28, 28, 28, 29, 29, 29, 29,
30, 30, 30, 31, 31, 31, 32, 32, 32, 32, 33, 33, 33, 34, 34, 34, 35, 35,
35, 35, 36, 36, 36, 37, 37, 37, 38, 38, 38, 38, 39, 39, 39, 40, 40, 40,
41, 41, 41, 41, 42, 42, 42, 43, 43, 43, 44, 44, 44, 44, 45, 45, 45, 46,
46, 46, 47, 47, 47, 47, 48, 48, 48, 49, 49, 49, 50, 50, 50, 50, 51, 51,
51, 52, 52, 52, 53, 53, 53, 53, 54, 54, 54, 55, 55, 55, 56, 56, 56, 56,
57, 57, 57, 58, 58, 58, 59, 59, 59, 59, 60, 60, 60, 61, 61, 61, 62, 62,
62, 62, 63, 63, 63, 64, 64, 64, 65, 65, 65, 65, 66, 66, 66, 67, 67, 67,
68, 68, 68, 68, 69, 69, 69, 70, 70, 70, 71, 71, 71, 71, 72, 72, 72, 73,
73, 73, 74, 74, 74, 74, 75, 75, 75, 76, 76, 76, 77, 77
};
// -----------------------------------------------------------------------------
// ResizeIcon
// Tries to resize the given icon. If the operation fails the icon is deleted.
// -----------------------------------------------------------------------------
//
static TInt ResizeIcon( CGulIcon*& aIcon,
const TSize& aSize,
TScaleMode aScaleMode )
{
TInt retval = KErrNotFound;
if ( aIcon )
{
CFbsBitmap* bmp = aIcon->Bitmap();
if ( bmp )
{
retval = !( aSize == bmp->SizeInPixels() );
}
if ( retval != KErrNone )
{
retval = AknIconUtils::SetSize( bmp, aSize, aScaleMode );
}
// Retval is checked outside of the "if ( bmp )" scope above in order
// to detect if the given icon's bitmap is NULL. This is required since
// AknIconUtils::SetSize returns KErrNone for NULL bitmaps and we want
// to delete icons that couldn't be resized.
if ( retval != KErrNone )
{
delete aIcon;
aIcon = NULL;
}
}
return retval;
}
static void ReplaceIconStatic( CGulIcon*& aIcon, CGulIcon* aNewIcon,
TScaleMode aScaleMode )
{
TSize iconSize( 0, 0 );
if ( aIcon && aIcon->Bitmap() )
{
iconSize = aIcon->Bitmap()->SizeInPixels();
}
delete aIcon;
aIcon = aNewIcon;
if ( iconSize != TSize( 0, 0 ) )
{
ResizeIcon( aIcon, iconSize, aScaleMode );
}
}
// -----------------------------------------------------------------------------
// CreateAndSetDimmedIconL
// Creates and sets a dimmed icon from the normal icon
// by making a partially transparent version of it.
//
// @param aIcon The original icon
// @param aDimmedIcon The dimmed icon
// @param aScaleMode The preferred ScaleMode
// -----------------------------------------------------------------------------
static void CreateAndSetDimmedIconL( CGulIcon*& aDimmedIcon,
const CGulIcon* aIcon,
TScaleMode aScaleMode )
{
if ( aIcon )
{
CFbsBitmap* mask = aIcon->Mask();
if ( mask && mask->DisplayMode() == EGray256 )
{
CGulIcon* newIcon = CGulIcon::NewLC();
CFbsBitmap* newPic = new ( ELeave ) CFbsBitmap;
newPic->Duplicate( aIcon->Bitmap()->Handle() );
//newPic ownership is transferred to newIcon
newIcon->SetBitmap( newPic );
CFbsBitmap* newMask = new ( ELeave ) CFbsBitmap;
CleanupStack::PushL( newMask );
User::LeaveIfError( newMask->Create(
newIcon->Bitmap()->SizeInPixels(), EGray256 ) );
CFbsBitmapDevice* bitmapDevice = CFbsBitmapDevice::NewL( newMask );
CleanupStack::PushL( bitmapDevice );
CFbsBitGc* bitGc( NULL );
User::LeaveIfError( bitmapDevice->CreateContext( bitGc ) );
CleanupStack::PushL( bitGc );
bitGc->SetPenStyle( CGraphicsContext::ESolidPen );
bitGc->BitBlt( TPoint( 0, 0 ), mask );
newMask->LockHeap();
TInt w = mask->SizeInPixels().iWidth;
TInt h = mask->SizeInPixels().iHeight;
TInt dataStride = mask->DataStride() - w;
unsigned char* address = (unsigned char *)newMask->DataAddress();
for ( TInt i = 0; i < h; ++i )
{
for ( TInt j = 0; j < w; ++j )
{
*address = KTransparency[*address];
++address;
}
address += dataStride;
}
newMask->UnlockHeap();
newIcon->SetMask( newMask );
ReplaceIconStatic( aDimmedIcon, newIcon, aScaleMode );
CleanupStack::PopAndDestroy( 2 ); // bitmapDevice, bitGc
CleanupStack::Pop( 2 ); // newIcon, newMask
}
}
}
// ============================ EXTENSION CLASS ================================
NONSHARABLE_CLASS( CAknButtonExtension ) : public CBase, MCoeControlHitTest
{
friend class CAknButton;
public:
// bitflags used to keep track of several button's internal features
enum TFlags
{
EUseAdditionalMask,
ECheckHitArea,
EDimmed,
ELongPressReported,
EUseDefaultIconSize,
EKeyRepeatEventReported,
EUseDefaultMargins
};
static CAknButtonExtension* NewL( CAknButton& aButton );
~CAknButtonExtension();
// Starts the long press timer.
void StartLongPressTimerL();
TBool HitRegionContains( const TPoint &aPoint,
const CCoeControl &aControl ) const;
void HandleFeedbackAreaChange();
private:
CAknButtonExtension( CAknButton& aButton );
void ConstructL();
// Callback method for long press timer.
static TInt ReportLongPressL( TAny* aThis );
// Handles long press.
void DoReportLongPressL();
// Deletes pressed down bitmaps
void DeletePressedBmps();
// Fetches bitmaps from resource provider (if one exists)
TBool FetchProviderPressedBmpsL();
// Sets bitmaps to resource provider (if one exists)
void SetProviderPressedBmpsL();
//Verify new rectagle size equals to the original
TBool TextRectSizeChanged( TRect aNewRect );
private: // Data
CAknButton& iButton;
CAknButton::TTooltipPosition iTooltipPosition;
CAknPictographInterface* iPictographInterface; // not owned
CPeriodic* iLongPressTimer;
TInt iLongPressInterval;
TFontUnderline iUnderlineStyle;
RArray<TAknsItemID> iFrameAndCenterIds;
CAknButton::TAlignment iVerticalIconAlignment;
CAknButton::TAlignment iHorizontalIconAlignment;
TMargins8 iMargins;
TSize iIconSize;
CAknButton::TTextAndIconAlignment iTextAndIconAlignment;
TBitFlags iFlags;
MTouchFeedback* iFeedback;
CFbsBitmap* iPressedDownBmp;
CFbsBitmap* iPressedDownBmpMask;
CAknResourceProvider* iResourceProvider;
//Previous touch down or drag position, valid only with pressed state.
TPoint iPrePointerPos;
CAknsFrameBackgroundControlContext* iHighlightContext;
// buffer for visually ordered text
TBuf<255 + KAknBidiExtraSpacePerLine> iVisualText;
TBool iFeedbackEnabled;
TAknsItemID iBackgroundSkinIID;
TRect iBgFrameRect;
TRect iTextRect;
};
// ============================ MEMBER FUNCTIONS ===============================
// -----------------------------------------------------------------------------
// CAknButtonExtension::CAknButtonExtension
// C++ default constructor.
// -----------------------------------------------------------------------------
//
CAknButtonExtension::CAknButtonExtension( CAknButton& aButton )
: iButton( aButton ),
iTooltipPosition( CAknButton::EPositionTop ),
iLongPressTimer( NULL ),
iLongPressInterval( KLongPressInterval ),
iUnderlineStyle( EUnderlineOff ),
iFrameAndCenterIds( 2 ),
iVerticalIconAlignment( CAknButton::ECenter ),
iHorizontalIconAlignment( CAknButton::ECenter ),
iTextAndIconAlignment( CAknButton::EIconBeforeText ),
iResourceProvider( 0 ),
iFeedbackEnabled( ETrue )
{
// default margins, these are applied to both text and icon
iMargins.SetAllValuesTo(
AknLayoutScalable_Avkon::aid_value_unit2().LayoutLine().iW / 10 );
// default icon size
TRect rect( TSize( 100, 100 ) );
TAknLayoutRect layoutRect;
layoutRect.LayoutRect( rect,
AknLayoutScalable_Avkon::toolbar_button_pane_g10().LayoutLine() );
iIconSize = layoutRect.Rect().Size();
iFlags.Set( EUseDefaultIconSize );
iFlags.Set( EUseDefaultMargins );
iTextRect = TRect::EUninitialized;
}
// -----------------------------------------------------------------------------
// CAknButtonExtension::~CAknButtonExtension
// Destructor.
// -----------------------------------------------------------------------------
//
CAknButtonExtension::~CAknButtonExtension()
{
delete iLongPressTimer;
iPictographInterface = NULL; // not owned
iFrameAndCenterIds.Close();
DeletePressedBmps();
delete iHighlightContext;
}
// -----------------------------------------------------------------------------
// CAknButtonExtension::NewL
// Symbian two-phased constructor.
// -----------------------------------------------------------------------------
//
CAknButtonExtension* CAknButtonExtension::NewL( CAknButton& aButton )
{
CAknButtonExtension* ext = new ( ELeave ) CAknButtonExtension( aButton );
CleanupStack::PushL( ext );
ext->ConstructL();
CleanupStack::Pop( ext );
return ext;
}
// -----------------------------------------------------------------------------
// CAknButtonExtension::ConstructL
// Symbian 2nd stage constructor.
// -----------------------------------------------------------------------------
//
void CAknButtonExtension::ConstructL()
{
// Normal frame and center
iFrameAndCenterIds.AppendL( KAknsIIDQsnFrButtonNormal );
iFrameAndCenterIds.AppendL( KAknsIIDQsnFrButtonCenterNormal );
// Latched frame and center
iFrameAndCenterIds.AppendL( KAknsIIDQsnFrButtonPressed );
iFrameAndCenterIds.AppendL( KAknsIIDQsnFrButtonCenterPressed );
// Dimmed frame and center
iFrameAndCenterIds.AppendL( KAknsIIDQsnFrButtonInactive );
iFrameAndCenterIds.AppendL( KAknsIIDQsnFrButtonCenterInactive );
// Pressed frame and center
iFrameAndCenterIds.AppendL( KAknsIIDQsnFrButtonPressed );
iFrameAndCenterIds.AppendL( KAknsIIDQsnFrButtonCenterPressed );
// Latched dimmed frame and center
iFrameAndCenterIds.AppendL( KAknsIIDQsnFrButtonInactive );
iFrameAndCenterIds.AppendL( KAknsIIDQsnFrButtonCenterInactive );
if ( !iHighlightContext )
{
iHighlightContext = CAknsFrameBackgroundControlContext::NewL(
KAknsIIDNone, TRect(), TRect(), EFalse );
iHighlightContext->SetFrame( KAknsIIDQsnFrButtonHighlight );
iHighlightContext->SetCenter( KAknsIIDQsnFrButtonHighlightCenter );
}
}
// -----------------------------------------------------------------------------
// CAknButtonExtension::StartLongPressTimerL
// Starts the long press timer. The timer is constructed when used for the
// first time.
// -----------------------------------------------------------------------------
//
void CAknButtonExtension::StartLongPressTimerL()
{
if ( !iLongPressTimer )
{
iLongPressTimer = CPeriodic::NewL( CActive::EPriorityStandard );
}
else if ( iLongPressTimer->IsActive() )
{
iLongPressTimer->Cancel();
}
if ( iLongPressInterval > 0 )
{
iLongPressTimer->Start( iLongPressInterval, iLongPressInterval,
TCallBack( ReportLongPressL, this ) );
}
}
// -----------------------------------------------------------------------------
// CAknButtonExtension::ReportLongPressL
// -----------------------------------------------------------------------------
//
TInt CAknButtonExtension::ReportLongPressL( TAny* aThis )
{
static_cast<CAknButtonExtension*>( aThis )->DoReportLongPressL();
return 0;
}
// -----------------------------------------------------------------------------
// CAknButtonExtension::DoReportLongPressL
// -----------------------------------------------------------------------------
//
void CAknButtonExtension::DoReportLongPressL()
{
if ( iLongPressTimer && iLongPressTimer->IsActive() )
{
iLongPressTimer->Cancel();
}
if ( iButton.Observer() )
{
iButton.Observer()->HandleControlEventL( &iButton,
static_cast<MCoeControlObserver::TCoeEvent>(
CAknButton::ELongPressEvent ) );
iFlags.Set( ELongPressReported );
}
}
// -----------------------------------------------------------------------------
// CAknButtonExtension::DeletePressedBmps
// Deletes pressed down bitmaps
// -----------------------------------------------------------------------------
//
void CAknButtonExtension::DeletePressedBmps()
{
delete iPressedDownBmp;
delete iPressedDownBmpMask;
iPressedDownBmp = 0;
iPressedDownBmpMask = 0;
}
// -----------------------------------------------------------------------------
// CAknButtonExtension::FetchProviderPressedBmpsL
// Fetches bitmaps from provider (if one exists). Returns ETrue if bitmaps were
// found.
// -----------------------------------------------------------------------------
//
TBool CAknButtonExtension::FetchProviderPressedBmpsL()
{
TBool bmpsFetched = EFalse;
if ( iResourceProvider )
{
MAknResourceItem* resourceItem = 0;
// Check if resource provider has item for KPressedFrameId
if ( iResourceProvider->GetResourceL(
KPressedFrameId, resourceItem ) != KErrNotFound
&& resourceItem )
{
DeletePressedBmps();
static_cast<CAknBitmapResourceItem*>( resourceItem )->GetBitmaps(
iPressedDownBmp, iPressedDownBmpMask );
delete resourceItem;
// Check if found bitmap size matches with button size
if ( iPressedDownBmp
&& iPressedDownBmpMask
&& iPressedDownBmp->SizeInPixels() == iButton.Size() )
{
bmpsFetched = ETrue;
}
// If not, delete the fetched bitmaps
else
{
DeletePressedBmps();
}
}
}
return bmpsFetched;
}
// -----------------------------------------------------------------------------
// CAknButtonExtension::SetProviderPressedBmpsL
// Sets bitmaps to provider (if one exists).
// -----------------------------------------------------------------------------
//
void CAknButtonExtension::SetProviderPressedBmpsL()
{
if ( iResourceProvider )
{
CAknBitmapResourceItem* resourceItem =
CAknBitmapResourceItem::NewL( KPressedFrameId );
resourceItem->SetBitmapsL( iPressedDownBmp, iPressedDownBmpMask );
iResourceProvider->SetResourceL(
KPressedFrameId,
static_cast<MAknResourceItem*>( resourceItem ) );
}
}
//Verify new rectangle size equals to the original
TBool CAknButtonExtension::TextRectSizeChanged( TRect aNewRect )
{
TBool result( ETrue );
if ( !iTextRect.IsEmpty() && !aNewRect.IsEmpty() )
{
if ( iTextRect.Width() == aNewRect.Width()
&& iTextRect.Height() == aNewRect.Height() )
{
result = EFalse;
}
}
return result;
}
//
TBool CAknButtonExtension::HitRegionContains( const TPoint &aPoint,
const CCoeControl& /*aControl*/ ) const
{
TBool retval = EFalse;
TRAP_IGNORE( retval = iButton.HitAreaContainsL( aPoint, iFlags.IsSet( ECheckHitArea ) ) );
return retval;
}
void CAknButtonExtension::HandleFeedbackAreaChange()
{
if ( !iFeedbackEnabled )
{
return;
}
// it is possible that feedback does not exist, eg. while booting.
// try getting one, and give up if that fails.
if ( !iFeedback )
{
iFeedback = MTouchFeedback::Instance();
}
if ( !iFeedback )
{
return;
}
if ( iButton.ButtonFlags() & KAknButtonHitTest )
{
// no registry feedback if shaped buttons are used
iFeedback->RemoveFeedbackArea( &iButton, 0 );
}
else
{
CFeedbackSpec* spec = CFeedbackSpec::New();
if (spec)
{
spec->AddFeedback( ETouchEventStylusDown,
ETouchFeedbackBasicButton );
spec->AddFeedback( ETouchEventStylusUp,
ETouchFeedbackBasicButton,
ETouchFeedbackVibra );
iFeedback->SetFeedbackArea( &iButton, 0, iButton.Rect(), spec );
delete spec;
}
}
}
// ============================ EXTENSION CLASS ================================
NONSHARABLE_CLASS( CAknButtonStateExtension ) : public CBase
{
friend class CAknButtonState;
public:
static CAknButtonStateExtension* NewL();
~CAknButtonStateExtension();
void ConfigureExtensionFromResourceL( const TInt aResourceId );
void ConfigureExtensionFromResourceL( TResourceReader& aReader );
private:
CAknButtonStateExtension();
void ConstructL();
private: // Data
TBool iGeneratedDimmedIcon;
HBufC* iFilePath;
TInt iBmpId;
TInt iMaskId;
TInt iDimmedBmpId;
TInt iDimmedMaskId;
TInt iPressedBmpId;
TInt iPressedMaskId;
TInt iHoverBmpId;
TInt iHoverMaskId;
TAknsItemID iId;
TAknsItemID iDimmedId;
TAknsItemID iPressedId;
TAknsItemID iHoverId;
TScaleMode iScaleMode;
TBool iFlagsChanged;
TBool iTextChanged;
};
// ============================ MEMBER FUNCTIONS ===============================
// -----------------------------------------------------------------------------
// CAknButtonStateExtension::CAknButtonStateExtension
// C++ default constructor.
// -----------------------------------------------------------------------------
//
CAknButtonStateExtension::CAknButtonStateExtension()
: iGeneratedDimmedIcon ( EFalse ), iBmpId( -1 ), iMaskId( -1 ),
iDimmedBmpId( -1 ), iDimmedMaskId( -1 ), iPressedBmpId( -1 ),
iPressedMaskId( -1 ), iHoverBmpId( -1 ), iHoverMaskId( -1 ),
iId( KAknsIIDNone ), iDimmedId( KAknsIIDNone ),
iPressedId( KAknsIIDNone ), iHoverId( KAknsIIDNone ),
iScaleMode( EAspectRatioNotPreserved )
{
}
// -----------------------------------------------------------------------------
// CAknButtonStateExtension::~CAknButtonStateExtension
// Destructor.
// -----------------------------------------------------------------------------
//
CAknButtonStateExtension::~CAknButtonStateExtension()
{
delete iFilePath;
}
// -----------------------------------------------------------------------------
// CAknButtonStateExtension::NewL
// Symbian two-phased constructor.
// -----------------------------------------------------------------------------
//
CAknButtonStateExtension* CAknButtonStateExtension::NewL()
{
CAknButtonStateExtension* ext = new ( ELeave ) CAknButtonStateExtension;
CleanupStack::PushL( ext );
ext->ConstructL();
CleanupStack::Pop( ext );
return ext;
}
// -----------------------------------------------------------------------------
// CAknButtonStateExtension::ConstructL
// Symbian 2nd stage constructor.
// -----------------------------------------------------------------------------
//
void CAknButtonStateExtension::ConstructL()
{
} //lint !e1762 function cannot be made const
// -----------------------------------------------------------------------------
// CAknButtonStateExtension::ConfigureExtensionFromResourceL
// -----------------------------------------------------------------------------
//
void CAknButtonStateExtension::ConfigureExtensionFromResourceL(
const TInt aResourceId )
{
if ( aResourceId )
{
TResourceReader reader;
CCoeEnv::Static()->CreateResourceReaderLC( reader, aResourceId );
ConfigureExtensionFromResourceL( reader );
CleanupStack::PopAndDestroy();
}
}
// -----------------------------------------------------------------------------
// CAknButtonStateExtension::ConfigureExtensionFromResourceL
// -----------------------------------------------------------------------------
//
void CAknButtonStateExtension::ConfigureExtensionFromResourceL(
TResourceReader& aReader )
{
TInt version = aReader.ReadInt8();
// bmp ids
TInt major = aReader.ReadInt32();
TInt minor = aReader.ReadInt32();
if ( major != 0 && minor != 0 )
{
iId.Set( major, minor );
}
// dimmed ids
major = aReader.ReadInt32();
minor = aReader.ReadInt32();
if ( major != 0 && minor != 0 )
{
iDimmedId.Set( major, minor );
}
// pressed ids
major = aReader.ReadInt32();
minor = aReader.ReadInt32();
if ( major != 0 && minor != 0 )
{
iPressedId.Set( major, minor );
}
// hover ids
major = aReader.ReadInt32();
minor = aReader.ReadInt32();
if ( major != 0 && minor != 0 )
{
iHoverId.Set( major, minor );
}
}
// ============================ MEMBER FUNCTIONS ===============================
// -----------------------------------------------------------------------------
// CAknButtonState::CAknButtonState
// Constructor
// -----------------------------------------------------------------------------
//
EXPORT_C CAknButtonState::CAknButtonState( const TInt aFlags ) :
iFlags( aFlags )
{
}
// -----------------------------------------------------------------------------
// CAknButtonState::~CAknButtonState
// Destructor
// -----------------------------------------------------------------------------
//
EXPORT_C CAknButtonState::~CAknButtonState()
{
delete iIcon;
delete iDimmedIcon;
delete iPressedIcon;
delete iHoverIcon;
delete iText;
delete iHelpText;
delete iExtension;
}
// -----------------------------------------------------------------------------
// CAknButtonState::ConstructFromResourceL
// Constructs the button state from the resources
// -----------------------------------------------------------------------------
//
EXPORT_C void CAknButtonState::ConstructFromResourceL( TResourceReader& aReader )
{
if ( !iExtension )
{
iExtension = CAknButtonStateExtension::NewL();
}
// flags
iFlags = aReader.ReadInt16();
// txt
TPtrC txt = aReader.ReadTPtrC();
SetTextL( txt );
// helptxt
TPtrC helpTxt = aReader.ReadTPtrC();
SetHelpTextL( helpTxt );
if ( iExtension->iFilePath )
{
delete iExtension->iFilePath;
iExtension->iFilePath = NULL;
}
// bmpfile
iExtension->iFilePath = aReader.ReadTPtrC().AllocL();
// bmpid & bmpmask
iExtension->iBmpId = aReader.ReadInt16();
iExtension->iMaskId = aReader.ReadInt16();
// dim_bmpid & dim_bmpmask
iExtension->iDimmedBmpId = aReader.ReadInt16();
iExtension->iDimmedMaskId = aReader.ReadInt16();
// press_bmpid & press_bmpmask
iExtension->iPressedBmpId = aReader.ReadInt16();
iExtension->iPressedMaskId = aReader.ReadInt16();
// hover_bmpid & hover_bmpmask
iExtension->iHoverBmpId = aReader.ReadInt16();
iExtension->iHoverMaskId = aReader.ReadInt16();
// extension
TInt extensionLink = aReader.ReadInt32();
if ( extensionLink != 0 )
{
iExtension->ConfigureExtensionFromResourceL( extensionLink );
}
LoadButtonIcon( iIcon );
LoadButtonIcon( iDimmedIcon );
LoadButtonIcon( iPressedIcon );
LoadButtonIcon( iHoverIcon );
}
// -----------------------------------------------------------------------------
// CAknButtonState::ConstructL
//
// -----------------------------------------------------------------------------
//
EXPORT_C void CAknButtonState::ConstructL( CGulIcon* aIcon,
CGulIcon* aDimmedIcon,
CGulIcon* aPressedIcon,
CGulIcon* aHoverIcon,
const TDesC& aText,
const TDesC& aHelpText )
{
if ( !iExtension )
{
iExtension = CAknButtonStateExtension::NewL();
}
SetIcon( aIcon );
SetDimmedIcon( aDimmedIcon );
SetPressedIcon( aPressedIcon );
SetHoverIcon( aHoverIcon );
SetTextL( aText );
SetHelpTextL( aHelpText );
}
// -----------------------------------------------------------------------------
// CAknButtonState::
// Symbian 2nd phase constructor.
// -----------------------------------------------------------------------------
//
EXPORT_C void CAknButtonState::ConstructL( const TDesC& aFilePath,
const TInt aBmpId,
const TInt aMaskId,
const TInt aDimmedBmpId,
const TInt aDimmedMaskId,
const TInt aPressedBmpId,
const TInt aPressedMaskId,
const TInt aHoverBmpId,
const TInt aHoverMaskId,
const TDesC& aText,
const TDesC& aHelpText,
const TAknsItemID& aId,
const TAknsItemID& aDimmedId,
const TAknsItemID& aPressedId,
const TAknsItemID& aHoverId )
{
UpdateIconL( aFilePath, aBmpId, aMaskId, aDimmedBmpId, aDimmedMaskId,
aPressedBmpId, aPressedMaskId, aHoverBmpId, aHoverMaskId, aId, aDimmedId,
aPressedId, aHoverId );
SetTextL( aText );
SetHelpTextL( aHelpText );
}
// -----------------------------------------------------------------------------
// CAknButtonState::Icon
// Returns the icon for the normal state.
// -----------------------------------------------------------------------------
//
EXPORT_C const CGulIcon* CAknButtonState::Icon() const
{
return iIcon;
}
// -----------------------------------------------------------------------------
// CAknButtonState::DimmedIcon
// Returns the icon for the dimmed state
// -----------------------------------------------------------------------------
//
EXPORT_C const CGulIcon* CAknButtonState::DimmedIcon() const
{
return iDimmedIcon;
}
// -----------------------------------------------------------------------------
// CAknButtonState::PressedIcon
// Returns the icon for the pressed but not released state.
// -----------------------------------------------------------------------------
//
EXPORT_C const CGulIcon* CAknButtonState::PressedIcon() const
{
return iPressedIcon;
}
// -----------------------------------------------------------------------------
// CAknButtonState::HoverIcon
// Returns the icon for the hover state.
// -----------------------------------------------------------------------------
//
EXPORT_C const CGulIcon* CAknButtonState::HoverIcon() const
{
return iHoverIcon;
}
// -----------------------------------------------------------------------------
// CAknButtonState::Text
// Returns the text inside the button.
// -----------------------------------------------------------------------------
//
EXPORT_C const TDesC& CAknButtonState::Text() const
{
if ( iText )
{
return *iText;
}
else
{
return KNullDesC();
}
}
// -----------------------------------------------------------------------------
// CAknButtonState::HelpText
// Returns the text inside the help note.
// -----------------------------------------------------------------------------
//
EXPORT_C const TDesC& CAknButtonState::HelpText() const
{
if ( iHelpText )
{
return *iHelpText;
}
else
{
return KNullDesC();
}
}
// -----------------------------------------------------------------------------
// CAknButtonState::Flags
// Returns the state flags.
// -----------------------------------------------------------------------------
//
EXPORT_C TInt CAknButtonState::Flags() const
{
return iFlags;
}
// -----------------------------------------------------------------------------
// CAknButtonState::SetIcon
// Sets the icon for the normal state.
// -----------------------------------------------------------------------------
//
EXPORT_C void CAknButtonState::SetIcon( CGulIcon* aIcon )
{
ReplaceIcon( iIcon, aIcon );
if ( iExtension->iGeneratedDimmedIcon )
{
TRAP_IGNORE( CreateAndSetDimmedIconL( iDimmedIcon, iIcon,
iExtension->iScaleMode ) );
}
}
// -----------------------------------------------------------------------------
// CAknButtonState::SetDimmedIcon
// Sets the icon for the dimmed state.
// -----------------------------------------------------------------------------
//
EXPORT_C void CAknButtonState::SetDimmedIcon( CGulIcon* aDimmedIcon )
{
ReplaceIcon( iDimmedIcon, aDimmedIcon );
}
// -----------------------------------------------------------------------------
// CAknButtonState::SetPressedIcon
// Sets the icon for the pressed but not released state.
// -----------------------------------------------------------------------------
//
EXPORT_C void CAknButtonState::SetPressedIcon( CGulIcon* aPressedIcon )
{
ReplaceIcon( iPressedIcon, aPressedIcon );
}
// -----------------------------------------------------------------------------
// CAknButtonState::SetHoverIcon
// Sets the icon for the hover state.
// -----------------------------------------------------------------------------
//
EXPORT_C void CAknButtonState::SetHoverIcon( CGulIcon* aHoverIcon )
{
ReplaceIcon( iHoverIcon, aHoverIcon );
}
// -----------------------------------------------------------------------------
// CAknButtonState::ReplaceIcon
// Replaces the given icon with a new one. If the original icon had its size set
// then the new icon is scaled to that size.
// -----------------------------------------------------------------------------
//
void CAknButtonState::ReplaceIcon( CGulIcon*& aIcon, CGulIcon* aNewIcon )
{
ReplaceIconStatic( aIcon, aNewIcon, iExtension->iScaleMode );
}
// -----------------------------------------------------------------------------
// CAknButtonState::SetTextL
// Sets the text inside the button
// -----------------------------------------------------------------------------
//
EXPORT_C void CAknButtonState::SetTextL( const TDesC& aText )
{
delete iText;
iText = NULL;
iText = aText.AllocL();
iExtension->iTextChanged = ETrue;
}
// -----------------------------------------------------------------------------
// CAknButtonState::SetHelpTextL
// Sets the text inside the help note
// -----------------------------------------------------------------------------
//
EXPORT_C void CAknButtonState::SetHelpTextL( const TDesC& aHelpText )
{
delete iHelpText;
iHelpText = NULL;
iHelpText = aHelpText.AllocL();
}
// -----------------------------------------------------------------------------
// CAknButtonState::
// Sets state flags.
// -----------------------------------------------------------------------------
//
EXPORT_C void CAknButtonState::SetFlags( const TInt aFlags )
{
if ( ( iFlags & KAknButtonStateHasLatchedFrame ) !=
( aFlags & KAknButtonStateHasLatchedFrame ) )
{
iExtension->iFlagsChanged = ETrue;
}
iFlags = aFlags;
}
// -----------------------------------------------------------------------------
// CAknButtonState::UpdateIconL
// Updates button icons.
// -----------------------------------------------------------------------------
void CAknButtonState::UpdateIconL( const TDesC& aFilePath,
const TInt aBmpId,
const TInt aMaskId,
const TInt aDimmedBmpId,
const TInt aDimmedMaskId,
const TInt aPressedBmpId,
const TInt aPressedMaskId,
const TInt aHoverBmpId,
const TInt aHoverMaskId,
const TAknsItemID& aId,
const TAknsItemID& aDimmedId,
const TAknsItemID& aPressedId,
const TAknsItemID& aHoverId )
{
if ( !iExtension )
{
iExtension = CAknButtonStateExtension::NewL();
}
if ( iExtension->iFilePath )
{
delete iExtension->iFilePath;
iExtension->iFilePath = NULL;
}
// try to save some ram by defaulting to avkon bitmap file
if ( aFilePath != KAvkonBitmapFile )
{
iExtension->iFilePath = aFilePath.AllocL();
}
iExtension->iBmpId = aBmpId;
iExtension->iMaskId = aMaskId;
iExtension->iDimmedBmpId = aDimmedBmpId;
iExtension->iDimmedMaskId = aDimmedMaskId;
iExtension->iPressedBmpId = aPressedBmpId;
iExtension->iPressedMaskId = aPressedMaskId;
iExtension->iHoverBmpId = aHoverBmpId;
iExtension->iHoverMaskId = aHoverMaskId;
iExtension->iId = aId;
iExtension->iDimmedId = aDimmedId;
iExtension->iPressedId = aPressedId;
iExtension->iHoverId = aHoverId;
LoadButtonIcon( iIcon );
LoadButtonIcon( iDimmedIcon );
LoadButtonIcon( iPressedIcon );
LoadButtonIcon( iHoverIcon );
}
// -----------------------------------------------------------------------------
// CAknButtonState::UpdateExtensionInfoL
// Updates extension information.
// -----------------------------------------------------------------------------
void CAknButtonState::UpdateExtensionInfoL( TInt aResource )
{
if ( iExtension )
{
iExtension->ConfigureExtensionFromResourceL( aResource );
LoadButtonIcon( iIcon );
LoadButtonIcon( iDimmedIcon );
LoadButtonIcon( iPressedIcon );
LoadButtonIcon( iHoverIcon );
}
}
// -----------------------------------------------------------------------------
// CAknButtonState::SizeChanged
// Scales function graphics to the given size
// -----------------------------------------------------------------------------
//
EXPORT_C void CAknButtonState::SizeChanged( const TRect& aRect,
TScaleMode aScaleMode )
{
ScaleIcons( aRect.Size(), aScaleMode );
}
// -----------------------------------------------------------------------------
// CAknButtonState::HasText
// Returns ETrue if the text inside button is not empty or space.
// -----------------------------------------------------------------------------
//
EXPORT_C TBool CAknButtonState::HasText() const
{
if ( !iText )
return EFalse;
TBool ret = EFalse;
for ( TInt i = 0; i < iText->Des().Length(); i++ )
{
TChar c ( (iText->Des())[i]);
// TChar::TCategory cat = c.GetCategory();
if ( !c.IsSpace() /*&& cat != TChar::ECoCategory*/ )
{
// not space and not private use char
ret = ETrue;
break;
}
}
return ret;
}
// -----------------------------------------------------------------------------
// CAknButtonState::HasHelp
// Returns ETrue if the text inside the help note is not empty or space.
// -----------------------------------------------------------------------------
//
EXPORT_C TBool CAknButtonState::HasHelp() const
{
if ( !iHelpText )
return EFalse;
TBool ret = EFalse;
for ( TInt i = 0; i < iHelpText->Des().Length(); i++ )
{
TChar c( ( *iHelpText )[i] );
// TChar::TCategory cat = c.GetCategory();
if ( !c.IsSpace() /*&& cat != TChar::ECoCategory*/ )
{
// not space and not private use char
ret = ETrue;
break;
}
}
return ret;
}
// -----------------------------------------------------------------------------
// CAknButtonState::HandleResourceChange
// Handles changes in state's environment.
// -----------------------------------------------------------------------------
//
void CAknButtonState::HandleResourceChange( TInt aType )
{
// Update icons if skin is changed. KEikDynamicLayoutVariantSwitch event is
// handled via SizeChanged.
if ( aType == KAknsMessageSkinChange )
{
LoadButtonIcon( iIcon );
LoadButtonIcon( iDimmedIcon );
LoadButtonIcon( iPressedIcon );
LoadButtonIcon( iHoverIcon );
// generated dimmed state icon has to be regenerated
if ( iExtension->iGeneratedDimmedIcon )
{
TRAP_IGNORE( CreateAndSetDimmedIconL( iDimmedIcon, iIcon,
iExtension->iScaleMode ) );
}
}
}
// -----------------------------------------------------------------------------
// CAknButtonState::SetIconScaleMode
// Sets default scaling mode.
// -----------------------------------------------------------------------------
//
void CAknButtonState::SetIconScaleMode( const TScaleMode aScaleMode )
{
iExtension->iScaleMode = aScaleMode;
}
// -----------------------------------------------------------------------------
// CAknButtonState::CreateButtonIconL
// Creates one of the icons
// -----------------------------------------------------------------------------
//
void CAknButtonState::CreateButtonIconL( CGulIcon*& aIcon,
const TDesC& aFilePath,
TInt aBmpId,
TInt aMaskId,
const TAknsItemID& aId ) const
{
MAknsSkinInstance* skin = AknsUtils::SkinInstance();
if ( aIcon )
{
if ( ( aId != KAknsIIDNone && skin ) || aBmpId != -1 )
{
delete aIcon;
aIcon = NULL;
}
}
if ( aFilePath == KNullDesC || aBmpId == -1 )
{
if ( aId != KAknsIIDNone && skin )
{
aIcon = AknsUtils::CreateGulIconL( skin, aId, EFalse );
}
}
else
{
if ( aId != KAknsIIDNone && skin )
{
aIcon = AknsUtils::CreateGulIconL( skin, aId, aFilePath, aBmpId,
aMaskId);
}
else
{
CFbsBitmap* bmp;
CFbsBitmap* mask;
AknIconUtils::CreateIconLC( bmp, mask, aFilePath, aBmpId, aMaskId);
aIcon = CGulIcon::NewL( bmp, mask ); // ownership passed
CleanupStack::Pop( 2 );
}
}
}
// -----------------------------------------------------------------------------
// CAknButtonState::LoadButtonIcon
// Reloads one button icon.
// -----------------------------------------------------------------------------
//
void CAknButtonState::LoadButtonIcon( CGulIcon*& aIcon ) const
{
TSize iconSize( 0, 0 );
if ( aIcon && aIcon->Bitmap() )
{
iconSize = aIcon->Bitmap()->SizeInPixels();
}
TInt bmpId = -1;
TInt maskId = -1;
TAknsItemID skinId = KAknsIIDNone;
if ( &aIcon == &iIcon )
{
bmpId = iExtension->iBmpId;
maskId = iExtension->iMaskId;
skinId = iExtension->iId;
}
else if ( &aIcon == &iPressedIcon )
{
bmpId = iExtension->iPressedBmpId;
maskId = iExtension->iPressedMaskId;
skinId = iExtension->iPressedId;
}
else if ( &aIcon == &iDimmedIcon )
{
bmpId = iExtension->iDimmedBmpId;
maskId = iExtension->iDimmedMaskId;
skinId = iExtension->iDimmedId;
}
else if ( &aIcon == &iHoverIcon )
{
bmpId = iExtension->iHoverBmpId;
maskId = iExtension->iHoverMaskId;
skinId = iExtension->iHoverId;
}
TPtrC16 bitmapFile;
if ( iExtension->iFilePath )
{
bitmapFile.Set( *iExtension->iFilePath );
}
else
{
bitmapFile.Set( KAvkonBitmapFile );
}
// aIcon is set to NULL if the next call fails
TRAP_IGNORE( CreateButtonIconL( aIcon, bitmapFile, bmpId, maskId, skinId ) );
if ( aIcon && iconSize != TSize( 0, 0 ) )
{
ResizeIcon( aIcon, iconSize, iExtension->iScaleMode );
}
}
// -----------------------------------------------------------------------------
// CAknButtonState::ScaleIcons
// Sets the size for bitmap and mask
// -----------------------------------------------------------------------------
//
TInt CAknButtonState::ScaleIcons( const TSize& aSize, TScaleMode aScaleMode )
{
TInt retval = ResizeIcon( iIcon, aSize, aScaleMode );
retval = Min( retval, ResizeIcon( iPressedIcon, aSize, aScaleMode ) );
// Generated dimmed state icon has to be regenerated
if ( iExtension->iGeneratedDimmedIcon )
{
TRAP_IGNORE ( CreateAndSetDimmedIconL( iDimmedIcon, iIcon, aScaleMode ) );
}
else
{
retval = Min( retval, ResizeIcon( iDimmedIcon, aSize, aScaleMode ) );
}
return retval;
}
// -----------------------------------------------------------------------------
// CAknButtonState::ScaleMode
// Getter for the current scalemode of the state
// -----------------------------------------------------------------------------
TScaleMode CAknButtonState::ScaleMode() const
{
return iExtension->iScaleMode;
}
// -----------------------------------------------------------------------------
// CAknButtonState::SetGeneratedDimmedIcon
// Whether the dimmed icon of the state is created by owning Button
// -----------------------------------------------------------------------------
void CAknButtonState::SetGeneratedDimmedIcon( TBool aDimmedIconCreatedByButton )
{
iExtension->iGeneratedDimmedIcon = aDimmedIconCreatedByButton;
}
// -----------------------------------------------------------------------------
// CAknButtonState::FlagsChanged
// Returns ETrue if button state flags are changed so that
// KAknStateHasLatchedDownFrame is setted or cleared
// -----------------------------------------------------------------------------
TBool CAknButtonState::FlagsChanged()
{
return iExtension->iFlagsChanged;
}
// -----------------------------------------------------------------------------
// CAknButtonState::ResetFlagsChanged
// Frame has been updated so boolean iFlagsChanged can be set to EFalse
// -----------------------------------------------------------------------------
void CAknButtonState::ResetFlagsChanged()
{
iExtension->iFlagsChanged = EFalse;
}
// -----------------------------------------------------------------------------
// CAknButtonState::TextChanged
// Returns ETrue if text is changed and button's visual text has
// not been updated.
// -----------------------------------------------------------------------------
TBool CAknButtonState::TextChanged()
{
return iExtension->iTextChanged;
}
// -----------------------------------------------------------------------------
// CAknButtonState::ResetTextChanged
// Visual text has been updated so boolean iTextChanged can be set to EFalse
// -----------------------------------------------------------------------------
void CAknButtonState::ResetTextChanged()
{
iExtension->iTextChanged = EFalse;
}
// -----------------------------------------------------------------------------
// CAknButtonState::Extension
// -----------------------------------------------------------------------------
//
CAknButtonStateExtension* CAknButtonState::Extension() const
{
return iExtension;
}
// ============================ MEMBER FUNCTIONS ===============================
// -----------------------------------------------------------------------------
// CAknButton::NewL
// Two-phased constructor.
// Constructs an empty button
// -----------------------------------------------------------------------------
//
EXPORT_C CAknButton* CAknButton::NewL()
{
CAknButton* self = NewLC();
CleanupStack::Pop( self );
return self;
}
// -----------------------------------------------------------------------------
// CAknButton::NewLC
// Two-phased constructor.
// Constructs an empty button
// -----------------------------------------------------------------------------
//
EXPORT_C CAknButton* CAknButton::NewLC()
{
CAknButton* self = new (ELeave) CAknButton( 0 );
CleanupStack::PushL( self );
self->ConstructL();
AKNTASHOOK_ADDL( self, "CAknButton" );
return self;
}
// -----------------------------------------------------------------------------
// CAknButton::NewL
// Two-phased constructor.
// Constructs the button from resources.
// -----------------------------------------------------------------------------
//
EXPORT_C CAknButton* CAknButton::NewL( TResourceReader& aReader )
{
CAknButton* self = NewLC( aReader );
CleanupStack::Pop( self );
return self;
}
// -----------------------------------------------------------------------------
// CAknButton::NewLC
// Two-phased constructor.
// Constructs the button from resources.
// -----------------------------------------------------------------------------
//
EXPORT_C CAknButton* CAknButton::NewLC( TResourceReader& aReader )
{
CAknButton* self = new( ELeave ) CAknButton( 0 );
CleanupStack::PushL( self );
self->ConstructL();
self->ConstructFromResourceL( aReader );
AKNTASHOOK_ADDL( self, "CAknButton" );
return self;
}
// -----------------------------------------------------------------------------
// CAknButton::NewL
// Two-phased constructor.
// Constructs the button from resources.
// -----------------------------------------------------------------------------
//
EXPORT_C CAknButton* CAknButton::NewL( const TInt aResourceId )
{
CAknButton* self = NewLC( aResourceId );
CleanupStack::Pop( self );
return self;
}
// -----------------------------------------------------------------------------
// CAknButton::NewLC
// Two-phased constructor.
// Constructs the button from resources.
// -----------------------------------------------------------------------------
//
EXPORT_C CAknButton* CAknButton::NewLC( const TInt aResourceId )
{
CAknButton* self = new (ELeave) CAknButton( 0 );
CleanupStack::PushL( self );
self->ConstructL();
self->ConstructFromResourceL( aResourceId );
AKNTASHOOK_ADDL( self, "CAknButton" );
return self;
}
// -----------------------------------------------------------------------------
// CAknButton::NewL
// Two-phased constructor.
// Constructs one state button.
// -----------------------------------------------------------------------------
//
EXPORT_C CAknButton* CAknButton::NewL( CGulIcon* aIcon,
CGulIcon* aDimmedIcon,
CGulIcon* aPressedIcon,
CGulIcon* aHoverIcon,
const TDesC& aText,
const TDesC& aHelpText,
const TInt aButtonFlags,
const TInt aStateFlags )
{
CAknButton* self = NewLC( aIcon, aDimmedIcon, aPressedIcon, aHoverIcon,
aText, aHelpText, aButtonFlags, aStateFlags );
CleanupStack::Pop( self );
return self;
}
// -----------------------------------------------------------------------------
// CAknButton::NewLC
// Two-phased constructor.
// Constructs one state button.
// -----------------------------------------------------------------------------
//
EXPORT_C CAknButton* CAknButton::NewLC( CGulIcon* aIcon,
CGulIcon* aDimmedIcon,
CGulIcon* aPressedIcon,
CGulIcon* aHoverIcon,
const TDesC& aText,
const TDesC& aHelpText,
const TInt aButtonFlags,
const TInt aStateFlags )
{
CAknButton* self = new (ELeave) CAknButton( aButtonFlags );
CleanupStack::PushL( self );
self->ConstructL( aIcon, aDimmedIcon, aPressedIcon, aHoverIcon, aText,
aHelpText, aStateFlags );
AKNTASHOOK_ADDL( self, "CAknButton" );
return self;
}
// -----------------------------------------------------------------------------
// CAknButton::NewL
// Two-phased constructor.
// Constructs one state button.
// -----------------------------------------------------------------------------
//
EXPORT_C CAknButton* CAknButton::NewL( const TDesC& aFilePath,
const TInt aBmpId,
const TInt aMaskId,
const TInt aDimmedBmpId,
const TInt aDimmedMaskId,
const TInt aPressedBmpId,
const TInt aPressedMaskId,
const TInt aHoverBmpId,
const TInt aHoverMaskId,
const TDesC& aText,
const TDesC& aHelpText,
const TInt aButtonFlags,
const TInt aStateFlags,
const TAknsItemID& aId,
const TAknsItemID& aDimmedId,
const TAknsItemID& aPressedId,
const TAknsItemID& aHoverId )
{
CAknButton* self = NewLC( aFilePath, aBmpId, aMaskId, aDimmedBmpId,
aDimmedMaskId, aPressedBmpId, aPressedMaskId, aHoverBmpId, aHoverMaskId,
aText, aHelpText, aButtonFlags, aStateFlags, aId, aDimmedId, aPressedId,
aHoverId );
CleanupStack::Pop( self );
return self;
}
// -----------------------------------------------------------------------------
// CAknButton::NewLC
// Two-phased constructor.
// Constructs one state button.
// -----------------------------------------------------------------------------
//
EXPORT_C CAknButton* CAknButton::NewLC( const TDesC& aFilePath,
const TInt aBmpId,
const TInt aMaskId,
const TInt aDimmedBmpId,
const TInt aDimmedMaskId,
const TInt aPressedBmpId,
const TInt aPressedMaskId,
const TInt aHoverBmpId,
const TInt aHoverMaskId,
const TDesC& aText,
const TDesC& aHelpText,
const TInt aButtonFlags,
const TInt aStateFlags,
const TAknsItemID& aId,
const TAknsItemID& aDimmedId,
const TAknsItemID& aPressedId,
const TAknsItemID& aHoverId )
{
CAknButton* self = new (ELeave) CAknButton( aButtonFlags );
CleanupStack::PushL( self );
self->ConstructL( aFilePath, aBmpId, aMaskId, aDimmedBmpId, aDimmedMaskId,
aPressedBmpId, aPressedMaskId, aHoverBmpId, aHoverMaskId,
aText, aHelpText, aStateFlags, aId, aDimmedId, aPressedId, aHoverId );
AKNTASHOOK_ADDL( self, "CAknButton" );
return self;
}
// -----------------------------------------------------------------------------
// CAknButton::CAknButton
// C++ constructor.
// -----------------------------------------------------------------------------
//
EXPORT_C CAknButton::CAknButton( const TInt aFlags )
: iFlags( aFlags ),
iVerticalAlignment( ECenter ),
iHorizontalAlignment( CGraphicsContext::ECenter ),
iTextColorTableId( KAknsIIDQsnTextColors ), // TODO
iTextColorIndex( EAknsCIQsnTextColorsCG80 ), // TODO
iScaleMode( EAspectRatioNotPreserved ),
iHelpNoteWaitInterval( KTimeoutBeforeHelpNote ),
iHelpNoteInViewInterval( KTimeoutInViewHelpNote ),
iKeyRepeatDelay( KKeyRepeatDelay ),
iKeyRepeatInterval( KKeyRepeatInterval )
{
}
// -----------------------------------------------------------------------------
// CAknButton::ConstructL
// Symbian 2nd phase constructor.
// Constructor for the empty button.
// -----------------------------------------------------------------------------
//
EXPORT_C void CAknButton::ConstructL()
{
TRgb textColor;
if ( AknsUtils::GetCachedColor( AknsUtils::SkinInstance(), textColor,
iTextColorTableId, iTextColorIndex ) == KErrNone )
{
OverrideColorL( EColorButtonText, textColor );
}
if ( AknsUtils::GetCachedColor( AknsUtils::SkinInstance(), textColor,
iTextColorTableId, EAknsCIQsnTextColorsCG84 ) == KErrNone )
{
OverrideColorL( EColorButtonTextPressed, textColor );
}
if ( !iStates )
{
iStates = new ( ELeave ) CArrayPtrFlat<CAknButtonState>( 2 );
}
if ( !iBgContext )
{
iBgContext = CAknsFrameBackgroundControlContext::NewL(
KAknsIIDNone, TRect(), TRect(), EFalse );
}
if ( !iExtension )
{
iExtension = CAknButtonExtension::NewL( *this );
}
if ( iFlags & KAknButtonHitTest )
{
SetHitTest( iExtension );
}
if ( iFlags & KAknButtonNoFrame )
{
iExtension->iMargins.SetAllValuesTo( 0 );
}
if ( iFlags & KAknButtonTextLeft )
{
iHorizontalAlignment = CGraphicsContext::ELeft;
}
iExtension->HandleFeedbackAreaChange();
SetFrameIDs();
}
// -----------------------------------------------------------------------------
// CAknButton::ConstructL
// Symbian 2nd phase constructor for 1 state button.
// -----------------------------------------------------------------------------
//
EXPORT_C void CAknButton::ConstructL( CGulIcon* aIcon,
CGulIcon* aDimmedIcon,
CGulIcon* aPressedIcon,
CGulIcon* aHoverIcon,
const TDesC& aText,
const TDesC& aHelpText,
const TInt aStateFlags )
{
ConstructL();
AddStateL( aIcon, aDimmedIcon, aPressedIcon, aHoverIcon, aText, aHelpText,
aStateFlags);
}
// -----------------------------------------------------------------------------
// CAknButton::ConstructL
// Symbian 2nd phase constructor for 1 state button
// -----------------------------------------------------------------------------
//
EXPORT_C void CAknButton::ConstructL( const TDesC& aFilePath,
const TInt aBmpId,
const TInt aMaskId,
const TInt aDimmedBmpId,
const TInt aDimmedMaskId,
const TInt aPressedBmpId,
const TInt aPressedMaskId,
const TInt aHoverBmpId,
const TInt aHoverMaskId,
const TDesC& aText,
const TDesC& aHelpText,
const TInt aStateFlags,
const TAknsItemID& aId,
const TAknsItemID& aDimmedId,
const TAknsItemID& aPressedId,
const TAknsItemID& aHoverId )
{
ConstructL();
AddStateL( aFilePath, aBmpId, aMaskId, aDimmedBmpId, aDimmedMaskId,
aPressedBmpId, aPressedMaskId, aHoverBmpId, aHoverMaskId,
aText, aHelpText, aStateFlags, aId, aDimmedId, aPressedId, aHoverId );
}
// -----------------------------------------------------------------------------
// Destructor
// -----------------------------------------------------------------------------
//
EXPORT_C CAknButton::~CAknButton()
{
AKNTASHOOK_REMOVE();
if ( iStates )
{
iStates->ResetAndDestroy();
delete iStates;
}
// MTouchFeedback instance lives in AknAppUi. AppUi might be
// destroyed when this destructor is running. If there is no
// MTouchFeedback instance there is no need to remove any areas
// either, as these are ( naturally ) destroyed with
// MTouchFeedback instance.
MTouchFeedback* fb = MTouchFeedback::Instance();
if ( fb )
{
fb->RemoveFeedbackForControl( this );
}
delete iBgContext;
delete iDimmedHelpText;
delete iHelpNote;
delete iKeyRepeatTimer;
delete iExtension;
iFont = NULL;
}
// -----------------------------------------------------------------------------
// CAknButton::ActivateL
// Sets control as ready to be drawn.
// -----------------------------------------------------------------------------
//
EXPORT_C void CAknButton::ActivateL()
{
// request for drag events outside the button
SetAllowStrayPointers();
// Requesting pointer drag events
EnableDragEvents();
CAknControl::ActivateL();
}
// -----------------------------------------------------------------------------
// CAknButton::ConstructFromResourceL
// Constructs controls from a resource file.
// -----------------------------------------------------------------------------
//
EXPORT_C void CAknButton::ConstructFromResourceL( TResourceReader& aReader )
{
if ( !iExtension )
{
iExtension = CAknButtonExtension::NewL( *this );
}
// flags
iFlags = aReader.ReadInt16();
// state index
SetStateIndexL( aReader.ReadInt16() );
// read states
const TInt stateCount = aReader.ReadInt16();
for ( TInt ii = 0; ii < stateCount; ii++ )
{
CAknButtonState* state = new (ELeave) CAknButtonState( 0 );
CleanupStack::PushL( state );
state->ConstructFromResourceL( aReader );
iStates->AppendL( state );
CleanupStack::Pop( state );
}
aReader.ReadInt32(); // extension link, not used currently
if ( iFlags & KAknButtonHitTest )
{
SetHitTest( iExtension );
}
if ( iFlags & KAknButtonNoFrame )
{
iExtension->iMargins.SetAllValuesTo( 0 );
}
if ( iFlags & KAknButtonTextLeft )
{
iHorizontalAlignment = CGraphicsContext::ELeft;
}
iExtension->HandleFeedbackAreaChange();
}
// -----------------------------------------------------------------------------
// CAknButton::HandleResourceChange
// Handles a change to the control's resources.
// -----------------------------------------------------------------------------
//
EXPORT_C void CAknButton::HandleResourceChange( TInt aType )
{
// No need to call base class implementation since CountComponentControls
// is always zero.
if ( aType == KAknsMessageSkinChange || aType == KEikDynamicLayoutVariantSwitch )
{
if ( iButtonPressed )
{
ResetState();
DrawDeferred();
}
}
// UIFW informs control about lost focus when moved to background.
// Rest of pointer events are no longer forvarded to control.
if ( aType == KAknMessageFocusLost || aType == KEikMessageFadeAllWindows )
{
if (iHelpNote)
{
iHelpNote->HideInfoPopupNote();
}
if (iButtonPressed)
{
ResetState();
DrawDeferred();
}
return;
}
if ( iStates )
{
for ( TInt i = 0; i < iStates->Count(); ++i )
{
CAknButtonState* state = iStates->At( i );
if ( state )
{
state->HandleResourceChange( aType );
}
}
}
if ( aType == KAknsMessageSkinChange )
{
TRgb textColor;
if ( AknsUtils::GetCachedColor( AknsUtils::SkinInstance(), textColor,
iTextColorTableId, iTextColorIndex ) == KErrNone )
{
TRAP_IGNORE( OverrideColorL( EColorButtonText, textColor ) );
}
if ( AknsUtils::GetCachedColor( AknsUtils::SkinInstance(), textColor,
iTextColorTableId, EAknsCIQsnTextColorsCG84 ) == KErrNone )
{
TRAP_IGNORE( OverrideColorL( EColorButtonTextPressed, textColor ) );
}
// generated pressed frame has to be regenerated
if ( iFlags & KAknButtonNoFrame && iFlags & KAknButtonPressedDownFrame )
{
iExtension->DeletePressedBmps();
TRAP_IGNORE( CreatePressedDownFrameL() );
}
}
}
// -----------------------------------------------------------------------------
// CAknButton::MinimumSize
// Returns the control's minimum required size. This doesn't include highlight
// area.
// -----------------------------------------------------------------------------
//
EXPORT_C TSize CAknButton::MinimumSize()
{
// by default, margins decide the absolute minimum size...
TInt width = iExtension->iMargins.iLeft + iExtension->iMargins.iRight;
TInt height = iExtension->iMargins.iTop + iExtension->iMargins.iBottom;
// ...but possible frames may enlarge the required area...
if ( !( iFlags & KAknButtonNoFrame ) )
{
TAknLayoutRect tl;
tl.LayoutRect( Rect(),
AknLayoutScalable_Avkon::toolbar_button_pane_g2().LayoutLine() );
TAknLayoutRect br;
br.LayoutRect( Rect(),
AknLayoutScalable_Avkon::toolbar_button_pane_g5().LayoutLine() );
TInt frameWidth = tl.Rect().Width() + br.Rect().Width();
TInt frameHeight = tl.Rect().Height() + br.Rect().Height();
if ( !( iFlags & KAknButtonTextInsideFrame ) )
{
width = Max( width, frameWidth );
height = Max( height, frameHeight );
}
else
{
width = frameWidth;
height = frameHeight;
}
}
// ...as well as evil flags
if ( iStates && ( iFlags & KAknButtonSizeFitText ) )
{
if ( !iFont )
{
iFont = iCoeEnv->NormalFont();
}
height += iFont->FontMaxHeight();
TInt textWidth = 0;
// choose the longest one
for ( TInt ii = 0; ii < iStates->Count(); ii++ )
{
CAknButtonState* state = iStates->At( ii );
if ( state && state->HasText() )
{
TInt tempWidth = iFont->TextWidthInPixels( state->Text() );
textWidth = Max( textWidth, tempWidth );
}
}
width += textWidth;
}
return TSize( width, height );
}
// -----------------------------------------------------------------------------
// CAknButton::SetDimmed
// Sets button dimmed. Doesn't redraw.
// Button needs to get pointer events even if it is dimmed to be able to show
// help text in dimmed state. So, the CCoeControl::SetDimmed(TBool) cannot be
// used to set button dimmed if the help text is used.
// -----------------------------------------------------------------------------
//
EXPORT_C void CAknButton::SetDimmed( TBool aDimmed )
{
if ( aDimmed )
{
StopKeyRepeatTimer();
StopLongPressTimer();
HideHelp();
iButtonPressed = EFalse;
}
if ( aDimmed )
{
iExtension->iFlags.Set( CAknButtonExtension::EDimmed );
}
else
{
iExtension->iFlags.Clear( CAknButtonExtension::EDimmed );
}
if ( iExtension->iFeedbackEnabled && iExtension->iFeedback )
{
if ( aDimmed )
{
iExtension->iFeedback->MoveFeedbackAreaToFirstPriority( this, 0 );
}
iExtension->iFeedback->EnableFeedbackForControl( this, !aDimmed && IsVisible() );
}
TBool hasHelp ( EFalse );
for ( TInt i = 0; i < iStates->Count(); ++i )
{
CAknButtonState* state = iStates->At( i );
if ( state )
{
if ( !state->iDimmedIcon )
{
TRAP_IGNORE ( CreateAndSetDimmedIconL( state->iDimmedIcon,
state->iIcon, state->ScaleMode() ) );
state->SetGeneratedDimmedIcon( ETrue );
}
if ( state->HasHelp() )
{
hasHelp = ETrue;
}
}
}
// None of states has help text, CCoeControl::SetDimmed can be used
if ( !hasHelp )
{
CCoeControl::SetDimmed( aDimmed );
}
SetFrameIDs();
}
// -----------------------------------------------------------------------------
// CAknButton::OfferKeyEventL
// Handles key events.
// -----------------------------------------------------------------------------
//
EXPORT_C TKeyResponse CAknButton::OfferKeyEventL( const TKeyEvent& aKeyEvent,
TEventCode aType )
{
if ( IsDimmed() )
return EKeyWasNotConsumed;
if ( aType == EEventKeyDown && IsVisible() )
{
HideHelp(); // hides help text as soon as the first key event comes.
}
if ( aKeyEvent.iScanCode == EStdKeyDevice3 ||
aKeyEvent.iScanCode == EStdKeyEnter )
{
if ( aType == EEventKeyDown )
{
iKeyDownReported = ETrue;
if ( !iButtonPressed )
{
// show press changes
iButtonPressed = ETrue;
iExtension->iPrePointerPos.SetXY( -1, -1 );
SetFrameIDs();
if ( NeedsRedrawWhenPressed() )
{
DrawNow();
}
}
if ( iFlags & KAknButtonReportOnKeyDown )
{
ChangeState( ETrue );
if ( Observer() )
{
Observer()->HandleControlEventL( this,
MCoeControlObserver::EEventStateChanged );
}
}
if ( iFlags & KAknButtonKeyRepeat )
{
iExtension->iFlags.Clear( CAknButtonExtension::EKeyRepeatEventReported );
StartKeyRepeatTimerL();
}
if ( iFlags & KAknButtonReportOnLongPress )
{
iExtension->iFlags.Clear( CAknButtonExtension::ELongPressReported );
iExtension->StartLongPressTimerL();
}
}
else if ( aType == EEventKeyUp )
{
if ( iButtonPressed )
{
iButtonPressed = EFalse;
SetFrameIDs();
if ( NeedsRedrawWhenPressed() )
{
DrawNow();
}
}
StopKeyRepeatTimer();
StopLongPressTimer();
// The state is not changed, if it is already changed on key
// down event, or if a long press or a key repeat event is
// already reported to the observer.
if ( !( iFlags & KAknButtonReportOnKeyDown ) &&
!( iExtension->iFlags.IsSet( CAknButtonExtension::ELongPressReported ) ) &&
!( iExtension->iFlags.IsSet( CAknButtonExtension::EKeyRepeatEventReported ) ) &&
iKeyDownReported )
{
ChangeState( ETrue );
if ( Observer() )
{
Observer()->HandleControlEventL( this,
MCoeControlObserver::EEventStateChanged );
}
}
else
{
if ( iExtension->iFlags.IsSet( CAknButtonExtension::ELongPressReported ) && iKeyDownReported )
{
Observer()->HandleControlEventL( this,
static_cast<MCoeControlObserver::TCoeEvent>(
CAknButton::ELongPressEndedEvent ) );
}
iExtension->iFlags.Clear( CAknButtonExtension::ELongPressReported );
iExtension->iFlags.Clear( CAknButtonExtension::EKeyRepeatEventReported );
}
TInt reported = iKeyDownReported;
iKeyDownReported = EFalse;
if ( reported && RequestExit() && Observer() )
{
Observer()->HandleControlEventL( this,
MCoeControlObserver::EEventRequestExit );
}
}
// we don't want aKeyEvent to go somewhere else :)
return EKeyWasConsumed;
}
return EKeyWasNotConsumed;
}
// -----------------------------------------------------------------------------
// CAknButton::MakeVisible
// Sets this control as visible or invisible.
// -----------------------------------------------------------------------------
//
EXPORT_C void CAknButton::MakeVisible( TBool aVisible )
{
if ( aVisible != IsVisible() )
{
CAknControl::MakeVisible( aVisible );
if ( iExtension->iFeedbackEnabled && iExtension->iFeedback )
{
if ( aVisible )
{
iExtension->iFeedback->MoveFeedbackAreaToFirstPriority( this,
0 );
}
iExtension->iFeedback->EnableFeedbackForControl(
this,
aVisible && !IsDimmed() );
}
CAknButtonState* state = State();
if ( !aVisible && iButtonPressed )
{
ResetState();
}
else if ( !aVisible && state && state->HasHelp() )
{
HideHelp();
}
}
}
// -----------------------------------------------------------------------------
// CAknButton::PrepareForFocusLossL
// This function is called by the dialog framework immediately before it removes
// keyboard focus from a control within a dialog.
// Currently has empty implementation.
// -----------------------------------------------------------------------------
//
EXPORT_C void CAknButton::PrepareForFocusLossL()
{
CAknControl::PrepareForFocusLossL(); // empty but it can be changed... :)
}
// -----------------------------------------------------------------------------
// CAknButton::PrepareForFocusGainL
// Prepares the control for gaining focus.
// Must be used before calling SetFocus() function in case when help note
// should be shown.
// -----------------------------------------------------------------------------
//
EXPORT_C void CAknButton::PrepareForFocusGainL()
{
CAknControl::PrepareForFocusGainL(); // empty but it can be changed... :)
CAknButtonState* state = State();
if ( state && state->HasHelp() && IsVisible() && !IsFocused() )
{
iShowHelp = ETrue;
}
else
{
iShowHelp = EFalse;
}
}
// -----------------------------------------------------------------------------
// CAknButton::SizeChanged
// Responds to size changes to sets the size and position of the contents of
// this control.
// -----------------------------------------------------------------------------
//
EXPORT_C void CAknButton::SizeChanged()
{
//Reset state if observer modified the rectangel.
if ( iButtonPressed && !Rect().Contains( iExtension->iPrePointerPos ) )
{
ResetState();
}
// If default icon size from LAF is used re-request that, otherwise trust
// that size will be updated by the utilising application.
if ( iExtension->iFlags.IsSet( CAknButtonExtension::EUseDefaultIconSize ) )
{
if ( iFlags & KAknButtonNoFrame && !State()->HasText() )
{
iExtension->iIconSize = Size();
}
else
{
TAknLayoutRect layoutRect;
layoutRect.LayoutRect( Rect(),
AknLayoutScalable_Avkon::toolbar_button_pane_g10().LayoutLine() );
iExtension->iIconSize = layoutRect.Rect().Size();
}
}
// Update margins from LAF if default values are used. This also refreshes
// icon size in case it overlaps margins.
CalculateDefaultMargins();
// scale all icons
ScaleIcons();
// Pressed down frame has to be regenerated
if ( iFlags & KAknButtonNoFrame && iFlags & KAknButtonPressedDownFrame )
{
TRAP_IGNORE( CreatePressedDownFrameL() );
}
SetFrameRects();
iExtension->HandleFeedbackAreaChange();
}
// -----------------------------------------------------------------------------
// CAknButton::HandlePointerEventL
// Handles pointer events.
// @param aPointerEvent is the pointer event.
// -----------------------------------------------------------------------------
//
EXPORT_C void CAknButton::HandlePointerEventL( const TPointerEvent& aPointerEvent )
{
if ( AknLayoutUtils::PenEnabled() )
{
if ( !IsVisible() )
{
if ( iButtonPressed )
{
ResetState();
}
return;
}
if ( iExtension )
{
iExtension->iPrePointerPos = aPointerEvent.iPosition;
}
TBool buttonEvent( TouchArea().Contains( aPointerEvent.iPosition ) );
CAknButtonState* state = State();
if ( !state )
{
return;
}
TBool hitArea( EFalse );
TRAP_IGNORE( hitArea = HitAreaContainsL( aPointerEvent.iPosition, EFalse ))
if ( ( iFlags & KAknButtonHitTest ) && !hitArea )
{
buttonEvent = EFalse;
}
TBool redrawNeeded(EFalse);
switch ( aPointerEvent.iType )
{
case TPointerEvent::EButton1Down:
{
if ( buttonEvent && IsDimmed() )
{
ShowHelpL();
}
else if ( buttonEvent )
{
if ( !iButtonPressed )
{
iButtonPressed = ETrue;
SetFrameIDs();
// feedback/basic on down event, if hit test is
// used. Area registry is used for rectangular
// buttons
if ( ( iFlags & KAknButtonHitTest )
&& !IsDimmed()
&& iExtension->iFeedback )
{
iExtension->iFeedback->InstantFeedback(
this,
ETouchFeedbackBasicButton,
aPointerEvent );
}
// make a mark so that we can later test that the button press comes from pointer event
iButtonPressed |= KPointerFlag;
// Redraw button, if needed
if ( NeedsRedrawWhenPressed() )
{
redrawNeeded = ETrue;
}
ShowHelpL();
}
if ( iFlags & KAknButtonReportOnKeyDown )
{
// State is changed on button down event
ChangeState( EFalse );
redrawNeeded = EFalse;
DrawNow(); //Redraw before noticing the observer for observer might open dialog
if ( Observer() )
{
Observer()->HandleControlEventL( this,
MCoeControlObserver::EEventStateChanged );
}
}
if ( iFlags & KAknButtonKeyRepeat )
{
// Key repeat
iExtension->iFlags.Clear( CAknButtonExtension::EKeyRepeatEventReported );
StartKeyRepeatTimerL();
}
if ( iFlags & KAknButtonReportOnLongPress )
{
iExtension->iFlags.Clear( CAknButtonExtension::ELongPressReported );
iExtension->StartLongPressTimerL();
}
}
break;
}
case TPointerEvent::EDrag:
{
iNumberOfDragEvents++;
if ( iNumberOfDragEvents >= KDragEventSensitivity )
{
iNumberOfDragEvents = 0;
// Pointer is dragged out of the button area
if ( !buttonEvent && iButtonPressed )
{
// Redraw button, if needed
if ( NeedsRedrawWhenPressed() )
{
redrawNeeded = ETrue;
}
iButtonPressed = EFalse;
SetFrameIDs();
StopKeyRepeatTimer();
StopLongPressTimer();
if ( !IsFocused() )
{
HideHelp();
}
if ( iExtension->iFlags.IsSet( CAknButtonExtension::ELongPressReported ) && Observer() )
{
Observer()->HandleControlEventL( this,
static_cast<MCoeControlObserver::TCoeEvent>(
CAknButton::ELongPressEndedEvent ) );
}
iExtension->iFlags.Clear( CAknButtonExtension::ELongPressReported );
}
// Pointer is dragged back into button area
else if ( buttonEvent && !iButtonPressed && !IsDimmed() )
{
iButtonPressed = ETrue;
SetFrameIDs();
// Redraw button, if needed
if ( NeedsRedrawWhenPressed() )
{
redrawNeeded = ETrue;
}
if ( iFlags & KAknButtonKeyRepeat )
{
// Continue key repeat
StartKeyRepeatTimerL();
}
if ( ( iFlags & KAknButtonReportOnLongPress ) &&
!( iExtension->iFlags.IsSet( CAknButtonExtension::ELongPressReported ) ) )
{
// Restart long press timer
StartLongPressTimerL();
}
}
}
break;
}
case TPointerEvent::EButton1Up:
{
if ( iExtension )
{
iExtension->iPrePointerPos.SetXY( -1, -1 );
}
iNumberOfDragEvents = 0;
HideHelp();
StopKeyRepeatTimer();
StopLongPressTimer();
if ( iButtonPressed )
{
// Redraw button, if needed
if ( NeedsRedrawWhenPressed() )
{
iButtonPressed = EFalse;
if ( ! ( buttonEvent && iStates->Count() > 1 ) )
{
redrawNeeded = ETrue;
}
}
iButtonPressed = EFalse;
SetFrameIDs();
}
TBool hasDrawn( EFalse );
if ( buttonEvent && !IsDimmed() )
{
// feedback/BasicButton on up event, if hit test is
// used. Area registry is used for rectangular
// buttons
if ( ( iFlags & KAknButtonHitTest )
&& iExtension->iFeedback )
{
iExtension->iFeedback->InstantFeedback(
this,
ETouchFeedbackBasicButton,
ETouchFeedbackVibra,
aPointerEvent );
}
// The state is not changed, if it is already changed on key
// down event, or if a long press or a key repeat event is
// already reported to the observer.
if ( !( iFlags & KAknButtonReportOnKeyDown ) &&
!( iExtension->iFlags.IsSet( CAknButtonExtension::ELongPressReported ) ) &&
!( iExtension->iFlags.IsSet( CAknButtonExtension::EKeyRepeatEventReported ) ) )
{
ChangeState( EFalse );
if ( !hasDrawn )
{
DrawNow();
hasDrawn = ETrue;
}
if ( Observer() )
{
Observer()->HandleControlEventL( this,
MCoeControlObserver::EEventStateChanged );
}
}
else
{
if ( iExtension->iFlags.IsSet( CAknButtonExtension::ELongPressReported ) && Observer() )
{
if ( redrawNeeded && !hasDrawn )
{
DrawNow();
hasDrawn = ETrue;
}
Observer()->HandleControlEventL( this,
static_cast<MCoeControlObserver::TCoeEvent>(
CAknButton::ELongPressEndedEvent ) );
}
iExtension->iFlags.Clear( CAknButtonExtension::ELongPressReported );
iExtension->iFlags.Clear( CAknButtonExtension::EKeyRepeatEventReported );
}
if ( RequestExit() && Observer() )
{
if ( redrawNeeded && !hasDrawn )
{
DrawNow();
hasDrawn = ETrue;
}
Observer()->HandleControlEventL( this,
MCoeControlObserver::EEventRequestExit );
}
}
if ( !buttonEvent && !IsDimmed() && Observer() )
{
if ( redrawNeeded && !hasDrawn )
{
DrawNow();
hasDrawn = ETrue;
}
Observer()->HandleControlEventL( this,
MCoeControlObserver::EEventRequestCancel );
if ( iExtension->iFlags.IsSet( CAknButtonExtension::ELongPressReported ) )
{
Observer()->HandleControlEventL( this,
static_cast<MCoeControlObserver::TCoeEvent>(
CAknButton::ELongPressEndedEvent ) );
iExtension->iFlags.Clear( CAknButtonExtension::ELongPressReported );
iExtension->iFlags.Clear( CAknButtonExtension::EKeyRepeatEventReported );
}
}
if ( hasDrawn )
{
redrawNeeded = EFalse;
}
break;
}
default:
break;
}
if (redrawNeeded)
{
DrawNow();
}
}
}
// -----------------------------------------------------------------------------
// CAknButton::PositionChanged
//
// -----------------------------------------------------------------------------
//
EXPORT_C void CAknButton::PositionChanged()
{
if ( iExtension ) iExtension->HandleFeedbackAreaChange();
CAknControl::PositionChanged();
//Reset state if observer moved button position.
if ( iButtonPressed && iExtension && !Rect().Contains( iExtension->iPrePointerPos ) )
{
ResetState();
}
SetFrameRects();
}
// -----------------------------------------------------------------------------
// CAknButton::FocusChanged
// This function is called whenever a control gains or loses focus.
// -----------------------------------------------------------------------------
//
EXPORT_C void CAknButton::FocusChanged( TDrawNow aDrawNow )
{
if ( !IsFocused() && iButtonPressed )
{
iButtonPressed = EFalse;
SetFrameIDs();
iKeyDownReported = EFalse;
}
if ( IsVisible() )
{
if ( IsFocused() && iShowHelp )
{
TRAP_IGNORE( ShowHelpL() );
}
else
{
HideHelp();
// Stop the timers if active
StopLongPressTimer();
StopKeyRepeatTimer();
}
if ( !IsBackedUp() && aDrawNow )
{
DrawNow();
}
}
iShowHelp = EFalse;
}
// -----------------------------------------------------------------------------
// CAknButton::ExtensionInterface
// For future extensions
// -----------------------------------------------------------------------------
//
EXPORT_C void* CAknButton::ExtensionInterface( TUid /*aInterface*/ )
{
return NULL;
}
// -----------------------------------------------------------------------------
// CAknButton::Draw
// Draw a control called by window server.
// -----------------------------------------------------------------------------
//
EXPORT_C void CAknButton::Draw( const TRect& /*aRect*/ ) const
{
TRect rect( Rect() );
TRect highlightRect( HighlightRect() );
CWindowGc& gc = SystemGc();
CAknButtonState* state = State();
if ( !( iFlags & KAknButtonNoFrame ) && !iButtonPressed && state &&
state->FlagsChanged() )
{
SetFrameIDs();
}
if ( !iExtension->iFlags.IsSet( CAknButtonExtension::EUseAdditionalMask ) )
{
MAknsSkinInstance* skin = AknsUtils::SkinInstance();
MAknsControlContext* cc = AknsDrawUtils::ControlContext( this );
if ( !( iFlags & KAknButtonNoFrame ) )
{
// frame graphics
if ( !AknsDrawUtils::Background( skin, iBgContext, NULL, gc,
rect, KAknsDrawParamNoClearUnderImage ) )
{
gc.SetBrushColor( KRgbRed );
gc.SetBrushStyle( CGraphicsContext::ESolidBrush );
gc.DrawRect( rect );
}
if ( IsFocused() && !highlightRect.IsEmpty() )
{
// frame graphics
if ( !AknsDrawUtils::Background( skin,
iExtension->iHighlightContext, NULL, gc, rect,
KAknsDrawParamNoClearUnderImage ) )
{
gc.SetBrushColor( KRgbRed );
gc.SetBrushStyle( CGraphicsContext::ESolidBrush );
gc.DrawRect( rect );
}
}
}
else if ( ( iFlags & KAknButtonNoFrame && iFlags & KAknButtonPressedDownFrame ) &&
( iButtonPressed ||
( state && state->Flags() & KAknButtonStateHasLatchedFrame &&
!IsDimmed() ) ) )
{
gc.BitBltMasked( Rect().iTl, iExtension->iPressedDownBmp,
TRect( TPoint(0,0), Size() ),
iExtension->iPressedDownBmpMask, EFalse );
}
}
else if ( !( iFlags & KAknButtonNoFrame ) )
{
if ( AknsUtils::SkinInstance() )
{
AknsDrawUtils::Background( AknsUtils::SkinInstance(), iBgContext, this, gc,
rect, KAknsDrawParamNoClearUnderImage );
}
}
TBool hasIcon = ( GetCurrentIcon() != NULL );
TBool hasText = state && state->HasText();
if ( hasIcon && hasText )
{
DrawTextAndIconButton( gc );
}
else if ( hasText )
{
DrawTextButton( gc );
}
else if ( hasIcon )
{
DrawIconButton( gc );
}
}
// -----------------------------------------------------------------------------
// CAknButton::ConstructFromResourceL
// Constructs controls from a resource file.
// @param aResourceId is the ID for this component's resource
// -----------------------------------------------------------------------------
//
EXPORT_C void CAknButton::ConstructFromResourceL( const TInt aResourceId )
{
if ( aResourceId )
{
TResourceReader reader;
iCoeEnv->CreateResourceReaderLC( reader, aResourceId );
ConstructFromResourceL( reader );
CleanupStack::PopAndDestroy();
}
}
// -----------------------------------------------------------------------------
// CAknButton::SetCurrentState
// Sets active button state index
// @param aStateIndex is the index inside state array
// @param aDrawNow should be ETrue for the button to be redrawn
// -----------------------------------------------------------------------------
//
EXPORT_C void CAknButton::SetCurrentState( const TInt aStateIndex,
const TBool aDrawNow )
{
TInt newIndex = -1;
if ( iStates && iStates->Count() )
{
newIndex = aStateIndex % iStates->Count();
}
TRAP_IGNORE( SetStateIndexL( newIndex ) );
SetFrameIDs();
if ( aDrawNow )
{
DrawNow();
}
}
// -----------------------------------------------------------------------------
// CAknButton::AddStateL
// Adds one more state for the button to the end of state array.
// -----------------------------------------------------------------------------
//
EXPORT_C void CAknButton::AddStateL( CGulIcon* aIcon,
CGulIcon* aDimmedIcon,
CGulIcon* aPressedIcon,
CGulIcon* aHoverIcon,
const TDesC& aText,
const TDesC& aHelpText,
const TInt aStateFlags )
{
CAknButtonState* state = new (ELeave) CAknButtonState( aStateFlags );
CleanupStack::PushL( state );
state->ConstructL( aIcon, aDimmedIcon, aPressedIcon, aHoverIcon, aText,
aHelpText );
iStates->AppendL( state );
CleanupStack::Pop( state );
}
// -----------------------------------------------------------------------------
// CAknButton::AddStateL
// Adds one more state for the button to the end of state array.
// -----------------------------------------------------------------------------
//
EXPORT_C void CAknButton::AddStateL( const TDesC& aFilePath,
const TInt aBmpId,
const TInt aMaskId,
const TInt aDimmedBmpId,
const TInt aDimmedMaskId,
const TInt aPressedBmpId,
const TInt aPressedMaskId,
const TInt aHoverBmpId,
const TInt aHoverMaskId,
const TDesC& aText,
const TDesC& aHelpText,
const TInt aStateFlags,
const TAknsItemID& aId,
const TAknsItemID& aDimmedId,
const TAknsItemID& aPressedId,
const TAknsItemID& aHoverId )
{
CAknButtonState* state = new (ELeave) CAknButtonState( aStateFlags );
CleanupStack::PushL( state );
state->ConstructL( aFilePath, aBmpId, aMaskId, aDimmedBmpId, aDimmedMaskId,
aPressedBmpId, aPressedMaskId, aHoverBmpId, aHoverMaskId,
aText, aHelpText, aId, aDimmedId, aPressedId, aHoverId );
iStates->AppendL( state );
CleanupStack::Pop( state );
}
// -----------------------------------------------------------------------------
// CAknButton::AddStateL
// Adds one more state for the button to the end of state array.
// -----------------------------------------------------------------------------
//
void CAknButton::AddStateL( CGulIcon* aIcon,
CGulIcon* aDimmedIcon,
CGulIcon* aPressedIcon,
CGulIcon* aHoverIcon,
const TDesC& aText,
const TDesC& aHelpText,
const TInt aStateFlags,
const TInt aCommandId )
{
CAknCommandButtonState* state =
new (ELeave) CAknCommandButtonState( aStateFlags, aCommandId );
CleanupStack::PushL( state );
state->ConstructL( aIcon, aDimmedIcon, aPressedIcon, aHoverIcon, aText,
aHelpText );
iStates->AppendL( state );
CleanupStack::Pop( state );
}
// -----------------------------------------------------------------------------
// CAknButton::SetFlags
// Sets the button flags
// -----------------------------------------------------------------------------
//
EXPORT_C void CAknButton::SetButtonFlags( const TInt aFlags )
{
if ( !( iFlags & KAknButtonNoFrame ) )
{
if ( aFlags & KAknButtonNoFrame )
{
iExtension->iMargins.SetAllValuesTo( 0 );
}
}
if ( aFlags & KAknButtonHitTest )
{
SetHitTest( iExtension );
iExtension->HandleFeedbackAreaChange();
}
if ( aFlags & KAknButtonNoFrame && aFlags & KAknButtonPressedDownFrame )
{
TRAP_IGNORE ( CreatePressedDownFrameL() );
}
iFlags = aFlags;
}
// -----------------------------------------------------------------------------
// CAknButton::SetFrameAndCenterIds
// Sets specified frame IDs. Can be used when default frame is not suitable.
// Use KAknsIIDNone value in case when some frame or center drawing is not
// needed or KAknsIIDDefault when the default button frame should be used.
// -----------------------------------------------------------------------------
//
EXPORT_C void CAknButton::SetFrameAndCenterIds(
const TAknsItemID& aFrameId,
const TAknsItemID& aCenterId,
const TAknsItemID& aLatchedFrameId,
const TAknsItemID& aLatchedCenterId,
const TAknsItemID& aDimmedFrameId,
const TAknsItemID& aDimmedCenterId,
const TAknsItemID& aPressedFrameId,
const TAknsItemID& aPressedCenterId,
const TAknsItemID& aLatchedDimmedFrameId,
const TAknsItemID& aLatchedDimmedCenterId )
{
RArray<TAknsItemID>& skinIds = iExtension->iFrameAndCenterIds;
if ( aFrameId != KAknsIIDDefault )
{
skinIds[KFrameId] = aFrameId;
}
if ( aCenterId != KAknsIIDDefault )
{
skinIds[KCenterId] = aCenterId;
}
if ( aLatchedFrameId != KAknsIIDDefault )
{
skinIds[KLatchedFrameId] = aLatchedFrameId;
}
if ( aLatchedCenterId != KAknsIIDDefault )
{
skinIds[KLatchedCenterId] = aLatchedCenterId;
}
if ( aDimmedFrameId != KAknsIIDDefault )
{
skinIds[KDimmedFrameId] = aDimmedFrameId;
}
if ( aDimmedCenterId != KAknsIIDDefault )
{
skinIds[KDimmedCenterId] = aDimmedCenterId;
}
if ( aPressedFrameId != KAknsIIDDefault )
{
skinIds[KPressedFrameId] = aPressedFrameId;
}
if ( aPressedCenterId != KAknsIIDDefault )
{
skinIds[KPressedCenterId] = aPressedCenterId;
}
if ( aLatchedDimmedFrameId != KAknsIIDDefault )
{
skinIds[KLatchedDimmedFrameId] = aLatchedDimmedFrameId;
}
if ( aLatchedDimmedCenterId != KAknsIIDDefault )
{
skinIds[KLatchedDimmedCenterId] = aLatchedDimmedCenterId;
}
SetFrameIDs();
}
// -----------------------------------------------------------------------------
// CAknButton::SetBackgroundIds
// -----------------------------------------------------------------------------
//
EXPORT_C void CAknButton::SetBackgroundIds(
const TAknsItemID& aBackgroundId,
const TAknsItemID& aLatchedBackgroundId,
const TAknsItemID& aDimmedBackgroundId,
const TAknsItemID& aPressedBackgroundId,
const TAknsItemID& aLatchedDimmedBackgroundId )
{
CAknButton::SetFrameAndCenterIds( aBackgroundId, aBackgroundId,
aLatchedBackgroundId,
aLatchedBackgroundId,
aDimmedBackgroundId, aDimmedBackgroundId,
aPressedBackgroundId,
aPressedBackgroundId,
aLatchedDimmedBackgroundId,
aLatchedDimmedBackgroundId );
}
// -----------------------------------------------------------------------------
// CAknButton::SetTextFont
// Sets some specific text font.
// -----------------------------------------------------------------------------
//
EXPORT_C void CAknButton::SetTextFont( const CFont* aFont )
{
iFont = aFont;
ConvertTextToVisualAndClip( iExtension->iTextRect );
}
// -----------------------------------------------------------------------------
// CAknButton::SetTextColorIds
// Sets the color table and color index for the button text.
// It will be used on button drawing if color of the text shouldn't be taken
// from text layout.
// -----------------------------------------------------------------------------
//
EXPORT_C void CAknButton::SetTextColorIds( const TAknsItemID& aTextColorTableId,
const TInt aTextColorIndex )
{
iTextColorTableId = aTextColorTableId;
iTextColorIndex = aTextColorIndex;
TRgb textColor;
if ( AknsUtils::GetCachedColor( AknsUtils::SkinInstance(), textColor,
iTextColorTableId, iTextColorIndex ) == KErrNone )
{
TRAP_IGNORE( OverrideColorL( EColorButtonText, textColor ) );
DrawDeferred();
}
}
// -----------------------------------------------------------------------------
// CAknButton::SetTextHorizontalAlignment
// Sets the horizontal alignment for the text inside the button. It will be used
// if alignment shouldn't be taken from text layout. By default it will be
// centered.
// -----------------------------------------------------------------------------
//
EXPORT_C void CAknButton::SetTextHorizontalAlignment(
const CGraphicsContext::TTextAlign aHorizontalAlignment )
{
iHorizontalAlignment = aHorizontalAlignment;
}
// -----------------------------------------------------------------------------
// CAknButton::SetTextVerticalAlignment
// Sets the vertical alignment for the text inside the button. It will be used
// if alignment shouldn't be taken from text layout. By default it will be
// centered.
// -----------------------------------------------------------------------------
//
EXPORT_C void CAknButton::SetTextVerticalAlignment(
const CAknButton::TAlignment aVerticalAlignment )
{
iVerticalAlignment = aVerticalAlignment;
}
// -----------------------------------------------------------------------------
// CAknButton::SetTextUnderlineStyle
// Sets the text underline style for the text inside the button.
// -----------------------------------------------------------------------------
//
EXPORT_C void CAknButton::SetTextUnderlineStyle( TFontUnderline aUnderlineStyle )
{
iExtension->iUnderlineStyle = aUnderlineStyle;
}
// -----------------------------------------------------------------------------
// CAknButton::SetIconScaleMode
// Sets the scale mode for the icon inside the button. The default is
// EAspectRatioNotPreserved.
// -----------------------------------------------------------------------------
//
EXPORT_C void CAknButton::SetIconScaleMode( const TScaleMode aScaleMode )
{
iScaleMode = aScaleMode;
for ( TInt i = 0; i < iStates->Count(); ++i )
{
CAknButtonState* state = iStates->At( i );
if ( state )
{
state->SetIconScaleMode( aScaleMode );
}
}
}
// -----------------------------------------------------------------------------
// CAknButton::SetIconHorizontalAlignment
// Sets the horizontal alignment for the icon inside the button.
// The default is ECenter
// -----------------------------------------------------------------------------
//
EXPORT_C void CAknButton::SetIconHorizontalAlignment(
const CAknButton::TAlignment aHorizontalAlignment )
{
iExtension->iHorizontalIconAlignment = aHorizontalAlignment;
}
// -----------------------------------------------------------------------------
// CAknButton::SetIconVerticalAlignment
// Sets the vertical alignment for the icon inside the button.
// The default is ECenter
// -----------------------------------------------------------------------------
//
EXPORT_C void CAknButton::SetIconVerticalAlignment(
const CAknButton::TAlignment aVerticalAlignment )
{
iExtension->iVerticalIconAlignment = aVerticalAlignment;
}
// -----------------------------------------------------------------------------
// CAknButton::SetTextAndIconAlignment
// Sets the icon and text alignment for the button having both
// The default is EIconBeforeText
// -----------------------------------------------------------------------------
//
EXPORT_C void CAknButton::SetTextAndIconAlignment (
const CAknButton::TTextAndIconAlignment aAlignment )
{
iExtension->iTextAndIconAlignment = aAlignment;
}
// -----------------------------------------------------------------------------
// CAknButton::SetHelpNoteTimeouts
// Sets the delay before the help text is shown and also specifies the time for
// how long help text is visible.
// -----------------------------------------------------------------------------
//
EXPORT_C void CAknButton::SetHelpNoteTimeouts( const TInt aBeforeTimeout,
const TInt aInViewTimeout )
{
if ( aBeforeTimeout >= 0 )
{
iHelpNoteWaitInterval = aBeforeTimeout;
}
if ( aInViewTimeout >= 0 )
{
iHelpNoteInViewInterval = aInViewTimeout;
}
if(iHelpNote)
{
iHelpNote->SetTimeDelayBeforeShow( iHelpNoteWaitInterval );
iHelpNote->SetTimePopupInView( iHelpNoteInViewInterval );
}
}
// -----------------------------------------------------------------------------
// CAknButton::SetKeyRepeatInterval
// Sets the interval for the key repeat.
// -----------------------------------------------------------------------------
//
EXPORT_C void CAknButton::SetKeyRepeatInterval( const TInt aKeyRepeatDelay,
const TInt aKeyRepeatInterval )
{
// Convert time intervals to microseconds
iKeyRepeatDelay = aKeyRepeatDelay * 1000;
iKeyRepeatInterval = aKeyRepeatInterval * 1000;
}
// -----------------------------------------------------------------------------
// CAknButton::SetLongPressInterval
// Sets the interval for the long presses.
// -----------------------------------------------------------------------------
//
EXPORT_C void CAknButton::SetLongPressInterval( const TInt aLongPressInterval )
{
iExtension->iLongPressInterval = aLongPressInterval * 1000;
}
// -----------------------------------------------------------------------------
// CAknButton::StateIndex
// Returns the index of the current button state.
// -----------------------------------------------------------------------------
//
EXPORT_C TInt CAknButton::StateIndex() const
{
return iStateIndex;
}
// -----------------------------------------------------------------------------
// CAknButton::EnablePictographsL
// Enables pictograph drawing in the button text.
// Only effective in Japanese variant.
// By default, it is disabled.
// -----------------------------------------------------------------------------
//
EXPORT_C void CAknButton::EnablePictographsL( CAknPictographInterface& aInterface )
{
iExtension->iPictographInterface = &aInterface;
}
// -----------------------------------------------------------------------------
// CAknButton::DisablePictographs
// Disables pictograph drawing in the button text.
// Only effective in Japanese variant.
// By default, it is disabled.
// -----------------------------------------------------------------------------
//
EXPORT_C void CAknButton::DisablePictographs()
{
iExtension->iPictographInterface = NULL;
}
// -----------------------------------------------------------------------------
// CAknButton::SetHighlightRect
// It will change the default highlight rectangular around
// the focused button
// -----------------------------------------------------------------------------
//
EXPORT_C void CAknButton::SetHighlightRect( const TRect& aRect )
{
iHighlightRect = aRect;
}
// -----------------------------------------------------------------------------
// CAknButton::HighlightRect
// Returns highlight rectangular around button
// -----------------------------------------------------------------------------
//
EXPORT_C TRect CAknButton::HighlightRect() const
{
if ( IsNonFocusing() )
{
return TRect();
}
else
{
return iHighlightRect;
}
}
// -----------------------------------------------------------------------------
// CAknButton::SetTooltipPosition
// -----------------------------------------------------------------------------
//
EXPORT_C void CAknButton::SetTooltipPosition( const TTooltipPosition aPosition )
{
iExtension->iTooltipPosition = aPosition;
}
// -----------------------------------------------------------------------------
// CAknButton::RequestExit
// -----------------------------------------------------------------------------
//
EXPORT_C void CAknButton::SetRequestExit( const TBool aRequestExit )
{
if (aRequestExit)
{
iFlags |= KAknButtonRequestExitOnButtonUpEvent;
}
else
{
iFlags &= ~KAknButtonRequestExitOnButtonUpEvent;
}
}
// -----------------------------------------------------------------------------
// CAknButton::IsDimmed
// -----------------------------------------------------------------------------
//
EXPORT_C TBool CAknButton::IsDimmed() const
{
return iExtension->iFlags.IsSet( CAknButtonExtension::EDimmed );
}
// -----------------------------------------------------------------------------
// CAknButton::SetHelpTextL
// Sets the help text for dimmed button
// -----------------------------------------------------------------------------
//
EXPORT_C void CAknButton::SetDimmedHelpTextL( const TDesC& aHelpText )
{
delete iDimmedHelpText;
iDimmedHelpText = NULL;
iDimmedHelpText = aHelpText.AllocL();
}
// -----------------------------------------------------------------------------
// CAknButton::ChangeState
// Changes the state of the button
// -----------------------------------------------------------------------------
//
EXPORT_C TInt CAknButton::ChangeState( TBool aDrawNow )
{
if ( !iStates || !iStates->Count() )
{
return -1;
}
TInt newIndex( iStateIndex + 1 );
if ( iStateIndex == iStates->Count() - 1 )
{
newIndex = 0;
}
TRAP_IGNORE( SetStateIndexL( newIndex ) );
// Updating background context might be needed if states flags differ
SetFrameIDs();
if ( aDrawNow )
{
DrawNow();
}
return iStateIndex;
}
// -----------------------------------------------------------------------------
// CAknButton::GetCurrentText
// Returns the texts which will be displayed inside the button for the current
// state.
// -----------------------------------------------------------------------------
//
EXPORT_C const TDesC& CAknButton::GetCurrentText() const
{
CAknButtonState* state = State();
if ( state )
{
return state->Text();
}
else
{
return KNullDesC();
}
}
// -----------------------------------------------------------------------------
// CAknButton::GetCurrentIcon
// Returns the right icon for the current state
// -----------------------------------------------------------------------------
//
EXPORT_C const CGulIcon* CAknButton::GetCurrentIcon() const
{
CAknButtonState* state = State();
const CGulIcon* icon = NULL;
if ( state )
{
if ( iButtonPressed && state->PressedIcon() )
{
icon = state->PressedIcon();
}
else if ( IsDimmed() && state->DimmedIcon() )
{
icon = state->DimmedIcon();
}
else
{
icon = state->Icon();
}
}
return icon;
}
// -----------------------------------------------------------------------------
// CAknButton::ShowHelpL
// Shows help text for a certain period of time.
// -----------------------------------------------------------------------------
//
EXPORT_C void CAknButton::ShowHelpL()
{
if ( !IsVisible() )
{
return;
}
if ( !iHelpNote )
{
iHelpNote = CAknInfoPopupNoteController::NewL();
iHelpNote->SetTimeDelayBeforeShow( iHelpNoteWaitInterval );
iHelpNote->SetTimePopupInView( iHelpNoteInViewInterval );
iHelpNote->SetTooltipModeL( ETrue );
}
if ( IsDimmed() && iDimmedHelpText )
{
iHelpNote->SetTextL( *iDimmedHelpText );
}
else
{
CAknButtonState* state = State();
if ( state && state->HasHelp() )
{
iHelpNote->SetTextL( state->HelpText() );
}
else
{
return;
}
}
UpdateTooltipPosition();
iHelpNote->ShowInfoPopupNote();
}
// -----------------------------------------------------------------------------
// CAknButton::HideHelp
// Hides help text after certain interval.
// -----------------------------------------------------------------------------
//
EXPORT_C void CAknButton::HideHelp()
{
if(iHelpNote)
{
iHelpNote->HideInfoPopupNote();
}
}
// -----------------------------------------------------------------------------
// CAknButton::State
// Returns current state.
// -----------------------------------------------------------------------------
//
EXPORT_C CAknButtonState* CAknButton::State() const
{
return State( iStateIndex );
}
// -----------------------------------------------------------------------------
// CAknButton::State
// Returns the state under the specified index.
// -----------------------------------------------------------------------------
//
EXPORT_C CAknButtonState* CAknButton::State( const TInt aStateIndex ) const
{
CAknButtonState* state = NULL;
if ( iStates && aStateIndex >= 0 && aStateIndex < iStates->Count() )
{
state = iStates->At( aStateIndex );
}
return state;
}
// -----------------------------------------------------------------------------
// CAknButton::Flags
// -----------------------------------------------------------------------------
//
EXPORT_C TInt CAknButton::ButtonFlags() const
{
return iFlags;
}
// -----------------------------------------------------------------------------
// CAknButton::SetMargins
// Sets button's marginals.
// -----------------------------------------------------------------------------
//
EXPORT_C void CAknButton::SetMargins( const TMargins8& aMargins )
{
iExtension->iFlags.Clear( CAknButtonExtension::EUseDefaultMargins );
iExtension->iMargins = aMargins;
SizeChanged();
}
// -----------------------------------------------------------------------------
// CAknButton::SetIconSize
// Sets button's icon size.
// -----------------------------------------------------------------------------
//
EXPORT_C TInt CAknButton::SetIconSize( const TSize& aSize )
{
iExtension->iFlags.Clear( CAknButtonExtension::EUseDefaultIconSize );
iExtension->iIconSize = aSize;
return ScaleIcons();
}
// -----------------------------------------------------------------------------
// CAknButton::ResetState
// Sets button to unpressed state.
// -----------------------------------------------------------------------------
//
EXPORT_C void CAknButton::ResetState( )
{
StopKeyRepeatTimer();
StopLongPressTimer();
iButtonPressed = EFalse;
SetFrameIDs();
HideHelp();
if ( iExtension )
{
if ( iExtension->iFlags.IsSet( CAknButtonExtension::ELongPressReported ) && Observer() )
{
TRAP_IGNORE( Observer()->HandleControlEventL( this,
static_cast<MCoeControlObserver::TCoeEvent>( CAknButton::ELongPressEndedEvent ) ) );
}
iExtension->iFlags.Clear( CAknButtonExtension::ELongPressReported );
iExtension->iFlags.Clear( CAknButtonExtension::EKeyRepeatEventReported );
}
}
// -----------------------------------------------------------------------------
// CAknButton::CalculateDefaultMargins
// Calculates default margins.
// -----------------------------------------------------------------------------
//
void CAknButton::CalculateDefaultMargins()
{
if ( iExtension->iFlags.IsSet( CAknButtonExtension::EUseDefaultMargins ) )
{
if ( !( iFlags & KAknButtonNoFrame ) )
{
TAknLayoutRect layoutRect;
layoutRect.LayoutRect( Rect(),
AknLayoutScalable_Avkon::aid_value_unit2().LayoutLine() );
iExtension->iMargins.SetAllValuesTo(
layoutRect.Rect().Size().iWidth / 10 ); // always square
}
}
if ( iExtension->iFlags.IsSet( CAknButtonExtension::EUseDefaultIconSize ) )
{
// ensure that icon size never exceeds the space inside margins
TRect rectInsideMargins( iExtension->iMargins.InnerRect( Rect() ) );
if ( rectInsideMargins.Size().iWidth < iExtension->iIconSize.iWidth )
{
iExtension->iIconSize.iWidth =
Max( 0, rectInsideMargins.Size().iWidth );
}
if ( rectInsideMargins.Size().iHeight < iExtension->iIconSize.iHeight )
{
iExtension->iIconSize.iHeight =
Max( 0, rectInsideMargins.Size().iHeight );
}
}
}
// -----------------------------------------------------------------------------
// CAknButton::ScaleIcons
// Scales all icons.
// -----------------------------------------------------------------------------
//
TInt CAknButton::ScaleIcons()
{
TInt retval = KErrNone;
for ( TInt i = 0; i < iStates->Count(); ++i )
{
CAknButtonState* state = iStates->At( i );
if ( state )
{
retval = Min( retval, state->ScaleIcons( iExtension->iIconSize,
iScaleMode ) );
if ( iExtension->iFlags.IsSet( CAknButtonExtension::EDimmed ) &&
!state->iDimmedIcon &&
state->iIcon )
{
TRAP_IGNORE( CreateAndSetDimmedIconL( state->iDimmedIcon,
state->iIcon, state->ScaleMode() ) );
}
}
}
return retval;
}
// -----------------------------------------------------------------------------
// CAknButton::DrawTextButton
// Continues drawing of the button which has only text
// -----------------------------------------------------------------------------
//
void CAknButton::DrawTextButton( CWindowGc& aGc ) const
{
TRect textRect;
TRect iconRect; //this is no use
GetCurrentStateTextAndIconRect( iconRect, textRect );
CAknButtonState* state = State();
if ( state->TextChanged() || iExtension->TextRectSizeChanged( textRect ) )
{
ConvertTextToVisualAndClip( textRect );
}
DrawText( aGc, textRect );
}
// -----------------------------------------------------------------------------
// CAknButton::DrawText
// Continues drawing of the button which has text
// -----------------------------------------------------------------------------
//
void CAknButton::DrawText( CWindowGc& aGc, TRect& aTextRect ) const
{
MAknsSkinInstance* skin = AknsUtils::SkinInstance();
aGc.SetBrushStyle( CGraphicsContext::ENullBrush );
TRgb penColor;
TRgb brushColor;
GetTextColors( penColor, brushColor );
aGc.SetPenColor( penColor );
aGc.SetBrushColor( brushColor );
const CFont* font = iFont;
if ( !font )
{
font = iCoeEnv->NormalFont();
}
aGc.UseFont( font );
aGc.SetUnderlineStyle( iExtension->iUnderlineStyle );
TInt baselineOffset = 0;
switch ( iVerticalAlignment )
{
case ETop:
baselineOffset = font->AscentInPixels();
break;
case EBottom:
baselineOffset = aTextRect.Height();
break;
default: // centered
baselineOffset = font->AscentInPixels() +
( aTextRect.Height() - font->AscentInPixels() ) / 2;
}
CGraphicsContext::TTextAlign horAlignment = iHorizontalAlignment;
aGc.DrawText( iExtension->iVisualText, aTextRect, baselineOffset,
horAlignment );
if ( iExtension->iPictographInterface )
{
// For Japanese variant only
iExtension->iPictographInterface->Interface()->DrawPictographsInText(
aGc, *font, iExtension->iVisualText, aTextRect, baselineOffset,
horAlignment );
}
}
// -----------------------------------------------------------------------------
// CAknButton::DrawIconButton
// Continues drawing of the button which has only an icon in it
// -----------------------------------------------------------------------------
//
void CAknButton::DrawIconButton( CWindowGc& aGc ) const
{
TRect iconRect;
TRect textRect;
GetCurrentStateTextAndIconRect( iconRect, textRect );
aGc.SetBrushStyle( CGraphicsContext::ENullBrush );
const CGulIcon* icon = GetCurrentIcon();
CFbsBitmap* buttonBmp = icon->Bitmap();
CFbsBitmap* buttonMask = icon->Mask();
TPoint iconPoint;
TSize iconSize ( buttonBmp->SizeInPixels());
switch ( iExtension->iHorizontalIconAlignment )
{
case ERight:
{
iconPoint.iX = iconRect.iBr.iX - iconSize.iWidth;
}
break;
case ECenter:
{
iconPoint.iX = iconRect.iTl.iX +
(iconRect.Width() / 2 - iconSize.iWidth / 2 );
}
break;
case ELeft:
{
iconPoint.iX = iconRect.iTl.iX;
}
break;
default:
// Should never come here
break;
}
switch ( iExtension->iVerticalIconAlignment )
{
case ETop:
{
iconPoint.iY = iconRect.iTl.iY;
}
break;
case ECenter:
{
iconPoint.iY = iconRect.iTl.iY +
( iconRect.Height() / 2 - iconSize.iHeight / 2 );
}
break;
case EBottom:
{
iconPoint.iY = iconRect.iBr.iY - iconSize.iHeight;
}
break;
default:
// Should never come here
break;
}
if( buttonBmp && buttonMask )
{
aGc.BitBltMasked( iconPoint, buttonBmp,
iconRect.Size(), buttonMask, ETrue );
}
else if ( buttonBmp )
{
aGc.BitBlt( iconPoint, buttonBmp, iconRect.Size() );
}
}
// -----------------------------------------------------------------------------
// CAknButton::DrawTextAndIconButton
// Continues drawing of the button which has both text and icon
// -----------------------------------------------------------------------------
//
void CAknButton::DrawTextAndIconButton( CWindowGc& aGc ) const
{
CAknButtonState* state = State();
if ( !state || !state->HasText() )
{
return;
}
const CGulIcon* icon = GetCurrentIcon();
TRect iconRect;
TRect textRect;
GetCurrentStateTextAndIconRect( iconRect, textRect );
CFbsBitmap* buttonBmp = icon->Bitmap();
CFbsBitmap* buttonMask = icon->Mask();
TSize iconSize ( buttonBmp->SizeInPixels());
if ( state->TextChanged() || iExtension->TextRectSizeChanged( textRect ) )
{
ConvertTextToVisualAndClip( textRect );
}
// Draw icon
TPoint iconPoint;
switch ( iExtension->iHorizontalIconAlignment )
{
case ERight:
{
iconPoint.iX = iconRect.iBr.iX - iconSize.iWidth;
}
break;
case ECenter:
{
iconPoint.iX = iconRect.iTl.iX +
(iconRect.Width() / 2 - iconSize.iWidth / 2 );
}
break;
case ELeft:
{
iconPoint.iX = iconRect.iTl.iX;
}
break;
default:
// Should never come here
break;
}
switch ( iExtension->iVerticalIconAlignment )
{
case ETop:
{
iconPoint.iY = iconRect.iTl.iY;
}
break;
case ECenter:
{
iconPoint.iY = iconRect.iTl.iY +
( iconRect.Height() / 2 - iconSize.iHeight / 2 );
}
break;
case EBottom:
{
iconPoint.iY = iconRect.iBr.iY - iconSize.iHeight;
}
break;
default:
// Should never come here
break;
}
if( buttonBmp && buttonMask )
{
aGc.BitBltMasked( iconPoint, buttonBmp,
iconRect.Size(), buttonMask, ETrue );
}
else if ( buttonBmp )
{
aGc.BitBlt( iconPoint, buttonBmp, iconRect.Size() );
}
DrawText( aGc, textRect );
}
// -----------------------------------------------------------------------------
// Starts the long press timer.
// -----------------------------------------------------------------------------
//
void CAknButton::StartLongPressTimerL()
{
if ( iExtension )
{
iExtension->StartLongPressTimerL();
}
}
// -----------------------------------------------------------------------------
// Stops the long press timer.
// -----------------------------------------------------------------------------
//
void CAknButton::StopLongPressTimer()
{
if ( iExtension && iExtension->iLongPressTimer &&
iExtension->iLongPressTimer->IsActive() )
{
iExtension->iLongPressTimer->Cancel();
}
}
// -----------------------------------------------------------------------------
// CAknButton::StartKeyRepeatTimerL
// Starts the timer for the long presses. The timer is constructed when used
// for the first time.
// -----------------------------------------------------------------------------
//
void CAknButton::StartKeyRepeatTimerL()
{
if ( !iKeyRepeatTimer )
{
iKeyRepeatTimer = CPeriodic::NewL( CActive::EPriorityStandard );
}
else if ( iKeyRepeatTimer->IsActive() )
{
iKeyRepeatTimer->Cancel();
}
if ( iKeyRepeatInterval > 0 )
{
iKeyRepeatTimer->Start( iKeyRepeatDelay, iKeyRepeatInterval,
TCallBack( ReportKeyRepeatL, this ) );
}
}
// -----------------------------------------------------------------------------
// Stops the key repeat timer.
// -----------------------------------------------------------------------------
//
void CAknButton::StopKeyRepeatTimer()
{
if ( iKeyRepeatTimer && iKeyRepeatTimer->IsActive() )
{
iKeyRepeatTimer->Cancel();
}
}
// -----------------------------------------------------------------------------
// CAknButton::ReportKeyRepeatL
// Cancel the timer.
// -----------------------------------------------------------------------------
//
TInt CAknButton::ReportKeyRepeatL( TAny* aThis )
{
// Fixes TSW error AJUA-7CEF8H
User::ResetInactivityTime();
CAknButton* self = reinterpret_cast< CAknButton* >( aThis );
if ( self->IsVisible() &&
!self->iExtension->iFlags.IsSet( CAknButtonExtension::EDimmed ) )
{
if ( self->iStates->Count() > 1 )
{
self->ChangeState( ETrue );
}
if ( self->Observer() )
{
self->Observer()->HandleControlEventL( self,
MCoeControlObserver::EEventStateChanged );
}
TBool feedbackNeeded = (self->iStates->Count() > 1) || (self->Observer());
TBool pointerRepeat = (self->iButtonPressed & KPointerFlag); // it was caused by pointer event
if ( self->iExtension->iFeedback && feedbackNeeded && pointerRepeat)
{
self->iExtension->iFeedback->InstantFeedback( self, ETouchFeedbackSensitiveButton );
}
self->iExtension->iFlags.Set( CAknButtonExtension::EKeyRepeatEventReported );
}
else if ( self->iKeyRepeatTimer && self->iKeyRepeatTimer->IsActive() )
{
self->iKeyRepeatTimer->Cancel();
}
return 1; // CPeriodic ignores return value
}
// -----------------------------------------------------------------------------
// CAknButton::Extension
// -----------------------------------------------------------------------------
//
CAknButtonExtension* CAknButton::Extension() const
{
return iExtension;
}
// -----------------------------------------------------------------------------
// CAknButton::UpdateTooltipPosition
// -----------------------------------------------------------------------------
//
void CAknButton::UpdateTooltipPosition()
{
TPoint position;
if ( AknsUtils::GetControlPosition( this, position ) != KErrNone )
{
position = PositionRelativeToScreen();
}
TRect rect( position, Size() );
TPoint center = rect.Center();
switch ( iExtension->iTooltipPosition )
{
case EPositionTop:
{
iHelpNote->SetPositionAndAlignment(
TPoint( center.iX, rect.iTl.iY ), EHCenterVBottom );
break;
}
case EPositionBottom:
{
iHelpNote->SetPositionAndAlignment(
TPoint( center.iX, rect.iBr.iY ), EHCenterVTop );
break;
}
case EPositionLeft:
{
iHelpNote->SetPositionAndAlignment(
TPoint( rect.iTl.iX, center.iY ), EHRightVCenter );
break;
}
case EPositionRight:
{
iHelpNote->SetPositionAndAlignment(
TPoint( rect.iBr.iX, center.iY ), EHLeftVCenter );
break;
}
default:
{
return;
}
}
}
// -----------------------------------------------------------------------------
// CAknButton::RequestExit
// Returns whether button should send EEventRequestExit to command observer
// on button up events.
// -----------------------------------------------------------------------------
//
TBool CAknButton::RequestExit() const
{
if ( iFlags & KAknButtonRequestExitOnButtonUpEvent )
{
return ETrue;
}
else
{
return EFalse;
}
}
// -----------------------------------------------------------------------------
// CAknButton::ContentRect
// Returns the the rectangle reserved for frame center, or the rect for text and
// icon, if the button has no frames (controls rect for now).
// -----------------------------------------------------------------------------
//
TRect CAknButton::ContentRect() const
{
TRect rect( Size() );
if ( !( iFlags & KAknButtonNoFrame ) &&
( iFlags & KAknButtonTextInsideFrame ) )
{
TAknLayoutRect centerLayout;
centerLayout.LayoutRect( rect,
AknLayoutScalable_Avkon::toolbar_button_pane_g1().LayoutLine() );
rect = centerLayout.Rect();
}
return rect;
}
// -----------------------------------------------------------------------------
// CAknButton::NeedsRedrawWhenPressed
// Returns boolean value indicating whether button needs redraw when it is
// pressed or released without changes in its state.
// -----------------------------------------------------------------------------
//
TBool CAknButton::NeedsRedrawWhenPressed() const
{
CAknButtonState* state = State();
if ( !iButtonPressed && iStates->Count() > 1 )
{
return EFalse;
}
if ( iButtonPressed && iFlags & KAknButtonPressedDownFrame )
{
return ETrue;
}
return ( state && state->PressedIcon() ||
( !( iFlags & KAknButtonNoFrame ) &&
!( iFlags & KAknButtonNoFramePressEvent ) &&
!( state && state->Flags() & KAknButtonStateHasLatchedFrame &&
SkinIID( KPressedFrameId ) == SkinIID( KLatchedFrameId ) ) ) );
}
// -----------------------------------------------------------------------------
// CAknButton::SkinIID
// -----------------------------------------------------------------------------
//
TAknsItemID CAknButton::SkinIID( const TInt aIndex ) const
{
if ( iExtension && aIndex >= 0 &&
aIndex < iExtension->iFrameAndCenterIds.Count() )
{
return iExtension->iFrameAndCenterIds[aIndex];
}
else
{
return KAknsIIDNone;
}
}
// -----------------------------------------------------------------------------
// CAknButton::HitAreaContainsL
// Checks if a button icon's non-transparent area was tapped.
// -----------------------------------------------------------------------------
//
TBool CAknButton::HitAreaContainsL( const TPoint& aPoint, TBool aCheckHitArea ) const
{
TBool buttonEvent( ETrue );
if ( aCheckHitArea )
{
if ( TouchArea().Contains( aPoint ) )
{
return ETrue;
}
else
{
return EFalse;
}
}
else if ( iFlags & KAknButtonHitTest )
{
TRect rect( Size() );
TRect contentRect( ContentRect() );
CFbsBitmap* bitmap = new (ELeave) CFbsBitmap;
CleanupStack::PushL( bitmap );
User::LeaveIfError( bitmap->Create( rect.Size(), EGray256 ) );
CFbsBitmapDevice* device = CFbsBitmapDevice::NewL( bitmap );
CleanupStack::PushL( device );
CFbsBitGc* gc = CFbsBitGc::NewL();
gc->Activate( device );
gc->SetBrushStyle( CGraphicsContext::ENullBrush );
MAknsSkinInstance* skin = AknsUtils::SkinInstance();
MAknsControlContext* cc = AknsDrawUtils::ControlContext( this );
if ( !(iFlags & KAknButtonNoFrame ) )
{
CAknButtonState* state = State();
TInt frameIdIndex = KFrameId;
if ( iButtonPressed )
{
frameIdIndex = KPressedFrameId;
}
else if ( state && state->Flags() & KAknButtonStateHasLatchedFrame )
{
if ( IsDimmed() )
{
// dimmed latched frame
frameIdIndex = KLatchedDimmedFrameId;
}
else
{
// latched down
frameIdIndex = KLatchedFrameId;
}
}
else if ( IsDimmed())
{
// dimmed frame
frameIdIndex = KDimmedFrameId;
}
if ( SkinIID( frameIdIndex ) != KAknsIIDNone )
{
TAknsItemID frameId = SkinIID( frameIdIndex );
TAknsItemID centerId = SkinIID( frameIdIndex + 1 );
gc->SetBrushColor( KRgbWhite );
if ( !AknsDrawUtils::DrawFrame( skin, *gc, rect,
contentRect, frameId, centerId, KAknsSDMAlphaOnly ) )
{
gc->DrawRect( rect );
}
gc->DrawRect( contentRect );
}
}
else if ( GetCurrentIcon() )
{
// if button has (only) icon, then mark other parts transparent
gc->SetBrushColor( KRgbBlack );
gc->Clear();
CFbsBitmap* mask = GetCurrentIcon()->Mask();
if ( mask )
{
gc->BitBlt( contentRect.iTl, mask, mask->SizeInPixels() );
}
}
else if ( GetCurrentText() != KNullDesC )
{
gc->SetBrushColor( KRgbWhite );
gc->Clear( contentRect );
}
else
{
// if this happens.. make the whole button transparent!
gc->SetBrushColor( KRgbBlack );
gc->Clear( contentRect );
}
TRgb pixel;
TPoint point( aPoint - Rect().iTl );
bitmap->GetPixel( pixel, point );
delete gc;
CleanupStack::PopAndDestroy( 2 ); // bitmap, device
if ( pixel == KRgbBlack )
{
buttonEvent = EFalse;
}
} // iFlags & KAknButtonHitTest
return buttonEvent;
}
// -----------------------------------------------------------------------------
// CAknButton::UsesDefaultMargins
// Checks if the button uses default margins.
// -----------------------------------------------------------------------------
//
TBool CAknButton::UsesDefaultMargins() const
{
return iExtension->iFlags.IsSet( CAknButtonExtension::EUseDefaultMargins );
}
// -----------------------------------------------------------------------------
// CAknButton::TextColor
// Gets the correct text color.
// -----------------------------------------------------------------------------
//
TRgb CAknButton::TextColor() const
{
TRgb color;
if ( IsDimmed() )
{
color = iEikonEnv->ControlColor( EColorButtonText, *this );
color.SetAlpha( 77 );
}
else if ( iButtonPressed )
{
color = iEikonEnv->ControlColor( EColorButtonTextPressed, *this );
}
else
{
color = iEikonEnv->ControlColor( EColorButtonText, *this );
}
return color;
}
// -----------------------------------------------------------------------------
// CAknButton::CreatePressedDownFrameL
// Generates a pressed down mask
// -----------------------------------------------------------------------------
//
void CAknButton::CreatePressedDownFrameL()
{
// Fetch frames from frame provider if one exists
if ( iExtension->FetchProviderPressedBmpsL() )
{
return;
}
if ( iExtension->iPressedDownBmp &&
iExtension->iPressedDownBmp->SizeInPixels() == Size() )
{
iExtension->SetProviderPressedBmpsL();
return;
}
iExtension->DeletePressedBmps();
// Fetch preffered display mode for icon type images
AknIconConfig::TPreferredDisplayMode displayMode;
AknIconConfig::PreferredDisplayMode(
displayMode, AknIconConfig::EImageTypeIcon );
iExtension->iPressedDownBmp = new ( ELeave ) CFbsBitmap;
User::LeaveIfError( iExtension->iPressedDownBmp->Create( Size(),
displayMode.iBitmapMode) );
iExtension->iPressedDownBmpMask = new ( ELeave ) CFbsBitmap;
User::LeaveIfError( iExtension->iPressedDownBmpMask->Create( Size(),
displayMode.iMaskMode ) );
CFbsBitmapDevice* bmpDevice = CFbsBitmapDevice::NewL(
iExtension->iPressedDownBmp );
CleanupStack::PushL( bmpDevice );
CFbsBitGc* bmpGc (NULL );
User::LeaveIfError( bmpDevice->CreateContext( bmpGc ) );
CleanupStack::PushL( bmpGc );
CFbsBitmapDevice* bmpMaskDevice = CFbsBitmapDevice::NewL(
iExtension->iPressedDownBmpMask );
CleanupStack::PushL( bmpMaskDevice );
CFbsBitGc* bmpMaskGc( NULL );
User::LeaveIfError( bmpMaskDevice->CreateContext( bmpMaskGc ) );
CleanupStack::PushL( bmpMaskGc );
TRect rect ( Size() );
TAknLayoutRect centerLayout;
centerLayout.LayoutRect( rect,
AknLayoutScalable_Avkon::toolbar_button_pane_g1().LayoutLine() );
TRect innerRect( centerLayout.Rect() );
TAknWindowLineLayout unit = AknLayoutScalable_Avkon::aid_value_unit2().LayoutLine();
innerRect.Shrink( unit.iW/10, unit.iH/10 );
AknsDrawUtils::DrawFrame( AknsUtils::SkinInstance(),
*bmpGc, rect, innerRect,
SkinIID( KPressedFrameId ), KAknsIIDDefault,
KAknsDrawParamRGBOnly );
AknsDrawUtils::DrawFrame( AknsUtils::SkinInstance(),
*bmpMaskGc, rect, innerRect,
SkinIID( KPressedFrameId ), KAknsIIDDefault,
KAknsSDMAlphaOnly );
// Modify mask 50% transparent
iExtension->iPressedDownBmpMask->LockHeap();
TInt w = iExtension->iPressedDownBmpMask->SizeInPixels().iWidth;
TInt h = iExtension->iPressedDownBmpMask->SizeInPixels().iHeight;
TInt dataStride = iExtension->iPressedDownBmpMask->DataStride() - w;
unsigned char* address = (unsigned char *)iExtension->iPressedDownBmpMask->DataAddress();
for ( TInt i = 0; i < h; ++i )
{
for ( TInt j = 0; j < w; ++j )
{
*address >>= 1;
++address;
}
address += dataStride;
}
iExtension->iPressedDownBmpMask->UnlockHeap();
// Set created frames to frame provider if one exists
iExtension->SetProviderPressedBmpsL();
CleanupStack::PopAndDestroy( 4 ); // bmpDevice, bmpGc, bmpMaskDevice, bmpMaskGc
}
// -----------------------------------------------------------------------------
// CAknButton::HideTooltipWhenAppFaded
// Sets tooltip to show or hide itself when background faded. By default tooltip
// is not shown when background faded.
// -----------------------------------------------------------------------------
//
void CAknButton::HideTooltipWhenAppFaded( TBool aHide )
{
if(iHelpNote)
{
iHelpNote->HideWhenAppFaded( aHide );
}
}
// -----------------------------------------------------------------------------
// CAknButton::CheckHitArea
// This checks hit area for fixed toolbar buttons.
// -----------------------------------------------------------------------------
//
void CAknButton::CheckHitArea( )
{
iExtension->iFlags.Set( CAknButtonExtension::ECheckHitArea );
SetHitTest( iExtension );
iExtension->HandleFeedbackAreaChange();
}
// -----------------------------------------------------------------------------
// CAknButton::UseAdditionalMask
// Sets button to use additional masks during drawing.
// -----------------------------------------------------------------------------
//
void CAknButton::UseMaskedDraw( TBool aMaskedDraw )
{
if ( aMaskedDraw )
{
iExtension->iFlags.Set( CAknButtonExtension:: EUseAdditionalMask );
}
else
{
iExtension->iFlags.Clear( CAknButtonExtension:: EUseAdditionalMask );
}
}
// -----------------------------------------------------------------------------
// Registers resource provider.
// -----------------------------------------------------------------------------
//
void CAknButton::RegisterResourceProvider( CAknResourceProvider* aProvider )
{
iExtension->iResourceProvider = aProvider;
}
// -----------------------------------------------------------------------------
// Unregisters resource provider.
// -----------------------------------------------------------------------------
//
void CAknButton::UnregisterResourceProvider()
{
iExtension->iResourceProvider = 0;
}
CAknsFrameBackgroundControlContext* CAknButton::BgContext()
{
return iBgContext;
}
// -----------------------------------------------------------------------------
// CAknButton::RemoveCurrentState
// Removes the current state.
// -----------------------------------------------------------------------------
//
void CAknButton::RemoveCurrentState()
{
// Can't remove the state if it's the only one left.
if ( iStates->Count() > 1 )
{
CAknButtonState* state = iStates->At( iStateIndex );
delete state;
state = NULL;
iStates->Delete( iStateIndex );
iStateIndex <= 0 ? iStateIndex = 0 : iStateIndex--;
SetFrameIDs();
DrawNow();
}
}
// -----------------------------------------------------------------------------
// CAknButton::CalculateLuminance
// Calculates color's luminance value.
// -----------------------------------------------------------------------------
//
TInt CAknButton::CalculateLuminance( const TRgb& aColor ) const
{
TInt R = aColor.Red();
TInt G = aColor.Green();
TInt B = aColor.Blue();
// Should be scaled to 0-255?
TInt Y = (((66 * R) + (129 * G) + (25 * B) + 128) >> 8) + 16;
return Y;
}
// -----------------------------------------------------------------------------
// CAknButton::ConvertColorsForOutlineEffect
// Converts the outline color to be white or black if the fill color is
// too similar to outline color.
// -----------------------------------------------------------------------------
//
void CAknButton::ConvertColorsForOutlineEffect( TRgb& aFillColor, TRgb& aOutlineColor ) const
{
// @todo maybe there is already some conversion utility in multimedia image library?
TInt innerLum = CalculateLuminance(aFillColor);
TInt outerLum = CalculateLuminance(aOutlineColor);
// if the defined colours are the same, then change the outline color so that
// it's either black or white, contrasting according to the font label text color's brightness
TInt difference = outerLum - innerLum;
difference = Abs(difference);
TInt half = (0xff / 2); // @todo figure out hlsMax somehow
TInt threshold = (0xff / 3); // @todo figure out hlsMax somehow, and decide on the threshold!
if(difference < threshold)
{
// if inner luminance is low, the outer luminance should be high, i.e. white
aOutlineColor = (innerLum < half) ? KRgbWhite : KRgbBlack;
}
}
// -----------------------------------------------------------------------------
// CAknButton::GetTextColors
// Gets correct text colors
// -----------------------------------------------------------------------------
//
void CAknButton::GetTextColors( TRgb& aPenColor, TRgb& aBrushColor ) const
{
TBool outlineEffectOn = EFalse;
const CAknLayoutFont* layoutFont = CAknLayoutFont::AsCAknLayoutFontOrNull( iFont );
if ( layoutFont )
{
outlineEffectOn = layoutFont->FontSpecification().IsOutlineEffectOn();
}
if ( IsDimmed() )
{
aPenColor = TextColor();
aBrushColor = iEikonEnv->ControlColor( EColorControlDimmedBackground,*this );
}
else
{
aPenColor = TextColor();
aBrushColor = iEikonEnv->ControlColor( EColorControlBackground,*this );
}
if ( outlineEffectOn )
{
ConvertColorsForOutlineEffect( aBrushColor, aPenColor );
}
}
// -----------------------------------------------------------------------------
// CAknButton::SetStateIndexL
// Sets new state index
// -----------------------------------------------------------------------------
//
void CAknButton::SetStateIndexL( TInt aNewIndex )
{
if ( iStateIndex != aNewIndex )
{
iStateIndex = aNewIndex;
// Create new popup note controller every time state changes
// (text is not updated properly in help note if this is not done)
if ( iHelpNote )
{
delete iHelpNote;
iHelpNote = 0;
}
iHelpNote = CAknInfoPopupNoteController::NewL();
iHelpNote->SetTimeDelayBeforeShow( iHelpNoteWaitInterval );
iHelpNote->SetTimePopupInView( iHelpNoteInViewInterval );
iHelpNote->SetTooltipModeL( ETrue );
//When state changed, empty rect to enable recalculate the
//visual text if text exists in current state.
if ( !(iExtension->iTextRect.IsEmpty()) )
{
iExtension->iTextRect = TRect::EUninitialized;
}
}
}
// -----------------------------------------------------------------------------
// CAknButton::SetFrameIDs
// Sets frame ids for background context
// -----------------------------------------------------------------------------
//
void CAknButton::SetFrameIDs() const
{
// Skin ids are determined here (a bit too early than necessary) so that
// we can avoid doing the same thing in DrawMaskedL.
CAknButtonState* state = State();
if ( !( iFlags & KAknButtonNoFrame ) )
{
TInt frameIdIndex = KFrameId;
if ( iButtonPressed )
{
frameIdIndex = KPressedFrameId;
}
else if ( state && state->Flags() & KAknButtonStateHasLatchedFrame )
{
if ( IsDimmed() )
{
// dimmed latched frame
frameIdIndex = KLatchedDimmedFrameId;
}
else
{
// latched down
frameIdIndex = KLatchedFrameId;
}
}
else if ( IsDimmed() )
{
// dimmed frame
frameIdIndex = KDimmedFrameId;
}
TAknsItemID skinIID( SkinIID( frameIdIndex ) );
// Only change the background frame graphics if necessary.
if ( skinIID != KAknsIIDNone &&
skinIID != iExtension->iBackgroundSkinIID )
{
iBgContext->SetFrame( skinIID );
iBgContext->SetCenter( SkinIID( ++frameIdIndex) );
iExtension->iBackgroundSkinIID = skinIID;
}
}
if ( state )
{
state->ResetFlagsChanged();
}
}
// -----------------------------------------------------------------------------
// CAknButton::SetFrameRects
// -----------------------------------------------------------------------------
//
void CAknButton::SetFrameRects()
{
TRect rect( Rect() );
// Only change the frame rects is the button rectangle is valid and the
// button size has changed.
if ( !rect.IsEmpty() && iExtension->iBgFrameRect != rect )
{
TAknLayoutRect centerLayout;
centerLayout.LayoutRect( rect,
AknLayoutScalable_Avkon::toolbar_button_pane_g1().LayoutLine() );
TRect innerRect( centerLayout.Rect() );
iBgContext->SetFrameRects( rect, innerRect );
iExtension->iHighlightContext->SetFrameRects( rect, innerRect );
iExtension->iBgFrameRect = rect;
}
}
// -----------------------------------------------------------------------------
// CAknButton::ConvertTextToVisualAndClip
// -----------------------------------------------------------------------------
//
void CAknButton::ConvertTextToVisualAndClip( const TRect& aRect ) const
{
CAknButtonState* state = State();
if ( !state || !state->HasText() )
{
if ( state )
{
state->ResetTextChanged();
}
return;
}
TRect textRect( aRect );
//Using given rect to calculate the visual text if it's not empty.
if ( !textRect.IsEmpty() )
{
iExtension->iTextRect = textRect;
}
//Calculate text area.
//This branch means that it's the first calling after the state changed
//or client using new font before this is shown.
else
{
TRect iconRect;
GetCurrentStateTextAndIconRect( iconRect, textRect );
iExtension->iTextRect = textRect;
}
TInt clipWidth = textRect.Width();
const CFont* font = iFont;
if ( !font )
{
font = iCoeEnv->NormalFont();
}
// bidi processing - using AknBidiTextUtils.
AknBidiTextUtils::ConvertToVisualAndClip(
state->Text(),
iExtension->iVisualText,
*font,
clipWidth,
clipWidth );
}
// -----------------------------------------------------------------------------
// CAknButton::GetCurrentStateTextAndIconRect()
// Get rect for icon and text of the current button state .
// -----------------------------------------------------------------------------
//
void CAknButton::GetCurrentStateTextAndIconRect( TRect& aIconRect,
TRect& aTextRect ) const
{
TRect iconRect( TRect::EUninitialized ) ;
TRect textRect( TRect::EUninitialized );
CAknButtonState* state = State();
//Return directly if no state
if ( !state )
{
aIconRect = iconRect;
aTextRect = textRect;
return;
}
TBool hasText( state->HasText() );
TBool hasIcon( EFalse );
const CGulIcon* icon = GetCurrentIcon();
if ( icon )
{
hasIcon = ETrue;
}
TRect rect = iExtension->iMargins.InnerRect( Rect() );
//Icon area is not effected by the frame flags.
if ( hasIcon )
{
iconRect = rect;
}
if ( !( iFlags & KAknButtonNoFrame ) &&
( iFlags & KAknButtonTextInsideFrame ))
{
TAknLayoutRect centerLayout;
centerLayout.LayoutRect( rect,
AknLayoutScalable_Avkon::toolbar_button_pane_g1().LayoutLine() );
rect = centerLayout.Rect();
}
if ( hasText )
{
textRect = rect;
}
if ( hasText && hasIcon )
{
CFbsBitmap* buttonBmp = icon->Bitmap();
CFbsBitmap* buttonMask = icon->Mask();
TSize iconSize ( buttonBmp->SizeInPixels());
// Set rects for icon and text according to their positioning
// First icon rect according to icon size - rest is for text
switch ( iExtension->iTextAndIconAlignment )
{
case CAknButton::EIconBeforeText:
if ( AknLayoutUtils::LayoutMirrored() )
{
textRect.SetRect( rect.iTl.iX, rect.iTl.iY,
rect.iBr.iX - iconSize.iWidth, rect.iBr.iY);
iconRect.SetRect( rect.iTl.iX +
rect.Width() -iconSize.iWidth,
rect.iTl.iY, rect.iBr.iX, rect.iBr.iY );
}
else
{
iconRect.SetRect( rect.iTl.iX, rect.iTl.iY,
rect.iTl.iX + iconSize.iWidth, rect.iBr.iY);
textRect.SetRect( rect.iTl.iX + iconSize.iWidth,
rect.iTl.iY, rect.iBr.iX, rect.iBr.iY );
}
break;
case CAknButton::EIconAfterText:
if ( AknLayoutUtils::LayoutMirrored() )
{
iconRect.SetRect( rect.iTl.iX, rect.iTl.iY,
rect.iTl.iX + iconSize.iWidth, rect.iBr.iY);
textRect.SetRect( rect.iTl.iX + iconSize.iWidth,
rect.iTl.iY, rect.iBr.iX, rect.iBr.iY );
}
else
{
textRect.SetRect( rect.iTl.iX, rect.iTl.iY,
rect.iBr.iX - iconSize.iWidth, rect.iBr.iY);
iconRect.SetRect( rect.iTl.iX +
rect.Width() -iconSize.iWidth,
rect.iTl.iY, rect.iBr.iX, rect.iBr.iY );
}
break;
case CAknButton::EIconOverText:
iconRect.SetRect( rect.iTl.iX, rect.iTl.iY,
rect.iBr.iX, rect.iTl.iY + iconSize.iHeight );
textRect.SetRect( rect.iTl.iX, rect.iTl.iY + iconSize.iHeight,
rect.iBr.iX, rect.iBr.iY );
break;
case CAknButton::EIconUnderText:
textRect.SetRect( rect.iTl.iX, rect.iTl.iY,
rect.iBr.iX, rect.iBr.iY - iconSize.iHeight );
iconRect.SetRect( rect.iTl.iX, rect.iBr.iY - iconSize.iHeight,
rect.iBr.iX, rect.iBr.iY );
break;
case CAknButton::EOverlay:
{
textRect = rect;
iconRect = rect;
}
break;
default:
break; //Do nothing.
}
}
aTextRect = textRect;
aIconRect = iconRect;
}
// -----------------------------------------------------------------------------
// CAknButton::TouchArea
// Returns the button touchable area.
// -----------------------------------------------------------------------------
//
TRect CAknButton::TouchArea() const
{
TRect touchRect( Rect() );
if ( iExtension->iFlags.IsSet( CAknButtonExtension::ECheckHitArea ) )
{
TAknLayoutRect layoutRect;
layoutRect.LayoutRect( Rect(),
AknLayoutScalable_Avkon::aid_touch_sctrl_middle(
!Layout_Meta_Data::IsLandscapeOrientation() ).LayoutLine() );
touchRect = layoutRect.Rect();
}
return touchRect;
}
// -----------------------------------------------------------------------------
// CAknButton::EnableFeedback
// Enables or disables tactile feedback
// -----------------------------------------------------------------------------
//
EXPORT_C void CAknButton::EnableFeedback( TBool aEnable )
{
if ( iExtension->iFeedbackEnabled == aEnable )
{
return;
}
iExtension->iFeedbackEnabled = aEnable;
if ( aEnable )
{
if ( !iExtension->iFeedback )
{
iExtension->iFeedback = MTouchFeedback::Instance();
}
if ( !iExtension->iFeedback )
{
return;
}
if ( IsVisible() )
{
iExtension->iFeedback->MoveFeedbackAreaToFirstPriority( this,
0 );
iExtension->iFeedback->EnableFeedbackForControl(
this,
!IsDimmed() );
}
iExtension->HandleFeedbackAreaChange();
}
else
{
// MTouchFeedback instance lives in AknAppUi. If there is no
// MTouchFeedback instance there is no need to remove any areas
// either.
MTouchFeedback* fb = MTouchFeedback::Instance();
if ( fb )
{
fb->RemoveFeedbackForControl( this );
}
}
}
// end of file