diff -r aecbbf00d063 -r d48ab3b357f1 uifw/EikStd/coctlsrc/AknButton.cpp --- a/uifw/EikStd/coctlsrc/AknButton.cpp Tue Aug 31 15:28:30 2010 +0300 +++ b/uifw/EikStd/coctlsrc/AknButton.cpp Wed Sep 01 12:16:19 2010 +0100 @@ -1,5 +1,5 @@ /* -* Copyright (c) 2005-2008 Nokia Corporation and/or its subsidiary(-ies). +* 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" @@ -264,7 +264,10 @@ // 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; @@ -284,6 +287,16 @@ 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 =============================== @@ -303,7 +316,8 @@ iVerticalIconAlignment( CAknButton::ECenter ), iHorizontalIconAlignment( CAknButton::ECenter ), iTextAndIconAlignment( CAknButton::EIconBeforeText ), - iResourceProvider( 0 ) + iResourceProvider( 0 ), + iFeedbackEnabled( ETrue ) { // default margins, these are applied to both text and icon iMargins.SetAllValuesTo( @@ -317,6 +331,7 @@ iIconSize = layoutRect.Rect().Size(); iFlags.Set( EUseDefaultIconSize ); iFlags.Set( EUseDefaultMargins ); + iTextRect = TRect::EUninitialized; } // ----------------------------------------------------------------------------- @@ -330,6 +345,7 @@ iPictographInterface = NULL; // not owned iFrameAndCenterIds.Close(); DeletePressedBmps(); + delete iHighlightContext; } // ----------------------------------------------------------------------------- @@ -368,6 +384,13 @@ // 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 ); + } } // ----------------------------------------------------------------------------- @@ -499,6 +522,20 @@ } } +//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; + } // @@ -514,6 +551,10 @@ 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 ) @@ -579,6 +620,8 @@ TAknsItemID iPressedId; TAknsItemID iHoverId; TScaleMode iScaleMode; + TBool iFlagsChanged; + TBool iTextChanged; }; // ============================ MEMBER FUNCTIONS =============================== @@ -991,6 +1034,7 @@ iText = NULL; iText = aText.AllocL(); + iExtension->iTextChanged = ETrue; } // ----------------------------------------------------------------------------- @@ -1013,6 +1057,11 @@ // EXPORT_C void CAknButtonState::SetFlags( const TInt aFlags ) { + if ( ( iFlags & KAknButtonStateHasLatchedFrame ) != + ( aFlags & KAknButtonStateHasLatchedFrame ) ) + { + iExtension->iFlagsChanged = ETrue; + } iFlags = aFlags; } @@ -1070,7 +1119,21 @@ 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 @@ -1321,6 +1384,44 @@ { 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 @@ -1562,7 +1663,12 @@ { OverrideColorL( EColorButtonText, textColor ); } - + + if ( AknsUtils::GetCachedColor( AknsUtils::SkinInstance(), textColor, + iTextColorTableId, EAknsCIQsnTextColorsCG84 ) == KErrNone ) + { + OverrideColorL( EColorButtonTextPressed, textColor ); + } if ( !iStates ) { iStates = new ( ELeave ) CArrayPtrFlat( 2 ); @@ -1594,6 +1700,7 @@ iHorizontalAlignment = CGraphicsContext::ELeft; } iExtension->HandleFeedbackAreaChange(); + SetFrameIDs(); } // ----------------------------------------------------------------------------- @@ -1796,6 +1903,11 @@ 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 ) { @@ -1889,7 +2001,6 @@ HideHelp(); iButtonPressed = EFalse; } - if ( aDimmed ) { iExtension->iFlags.Set( CAknButtonExtension::EDimmed ); @@ -1898,7 +2009,7 @@ { iExtension->iFlags.Clear( CAknButtonExtension::EDimmed ); } - if ( iExtension->iFeedback ) + if ( iExtension->iFeedbackEnabled && iExtension->iFeedback ) { if ( aDimmed ) { @@ -1933,6 +2044,7 @@ { CCoeControl::SetDimmed( aDimmed ); } + SetFrameIDs(); } // ----------------------------------------------------------------------------- @@ -1962,6 +2074,9 @@ { // show press changes iButtonPressed = ETrue; + iExtension->iPrePointerPos.SetXY( -1, -1 ); + + SetFrameIDs(); if ( NeedsRedrawWhenPressed() ) { DrawNow(); @@ -1996,6 +2111,7 @@ if ( iButtonPressed ) { iButtonPressed = EFalse; + SetFrameIDs(); if ( NeedsRedrawWhenPressed() ) { @@ -2032,14 +2148,14 @@ iExtension->iFlags.Clear( CAknButtonExtension::ELongPressReported ); iExtension->iFlags.Clear( CAknButtonExtension::EKeyRepeatEventReported ); } - - if ( iKeyDownReported && RequestExit() && Observer() ) + + TInt reported = iKeyDownReported; + iKeyDownReported = EFalse; + if ( reported && RequestExit() && Observer() ) { Observer()->HandleControlEventL( this, MCoeControlObserver::EEventRequestExit ); - } - - iKeyDownReported = EFalse; + } } // we don't want aKeyEvent to go somewhere else :) return EKeyWasConsumed; @@ -2058,7 +2174,7 @@ if ( aVisible != IsVisible() ) { CAknControl::MakeVisible( aVisible ); - if ( iExtension->iFeedback ) + if ( iExtension->iFeedbackEnabled && iExtension->iFeedback ) { if ( aVisible ) { @@ -2071,7 +2187,11 @@ } CAknButtonState* state = State(); - if ( !aVisible && state && state->HasHelp() ) + if ( !aVisible && iButtonPressed ) + { + ResetState(); + } + else if ( !aVisible && state && state->HasHelp() ) { HideHelp(); } @@ -2120,6 +2240,11 @@ // 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 ) ) @@ -2149,6 +2274,7 @@ { TRAP_IGNORE( CreatePressedDownFrameL() ); } + SetFrameRects(); iExtension->HandleFeedbackAreaChange(); } @@ -2171,6 +2297,10 @@ } return; } + if ( iExtension ) + { + iExtension->iPrePointerPos = aPointerEvent.iPosition; + } TBool buttonEvent( TouchArea().Contains( aPointerEvent.iPosition ) ); CAknButtonState* state = State(); if ( !state ) @@ -2198,6 +2328,7 @@ if ( !iButtonPressed ) { iButtonPressed = ETrue; + SetFrameIDs(); // feedback/basic on down event, if hit test is // used. Area registry is used for rectangular // buttons @@ -2227,7 +2358,8 @@ { // State is changed on button down event ChangeState( EFalse ); - redrawNeeded = ETrue; + redrawNeeded = EFalse; + DrawNow(); //Redraw before noticing the observer for observer might open dialog if ( Observer() ) { Observer()->HandleControlEventL( this, @@ -2264,10 +2396,10 @@ // Redraw button, if needed if ( NeedsRedrawWhenPressed() ) { - iButtonPressed = EFalse; redrawNeeded = ETrue; } iButtonPressed = EFalse; + SetFrameIDs(); StopKeyRepeatTimer(); StopLongPressTimer(); @@ -2289,6 +2421,7 @@ else if ( buttonEvent && !iButtonPressed && !IsDimmed() ) { iButtonPressed = ETrue; + SetFrameIDs(); // Redraw button, if needed if ( NeedsRedrawWhenPressed() ) @@ -2315,6 +2448,10 @@ case TPointerEvent::EButton1Up: { + if ( iExtension ) + { + iExtension->iPrePointerPos.SetXY( -1, -1 ); + } iNumberOfDragEvents = 0; HideHelp(); @@ -2333,8 +2470,10 @@ } } iButtonPressed = EFalse; + SetFrameIDs(); } + TBool hasDrawn( EFalse ); if ( buttonEvent && !IsDimmed() ) { // feedback/BasicButton on up event, if hit test is @@ -2357,7 +2496,12 @@ !( iExtension->iFlags.IsSet( CAknButtonExtension::EKeyRepeatEventReported ) ) ) { ChangeState( EFalse ); - redrawNeeded = ETrue; + if ( !hasDrawn ) + { + DrawNow(); + hasDrawn = ETrue; + } + if ( Observer() ) { Observer()->HandleControlEventL( this, @@ -2368,6 +2512,11 @@ { if ( iExtension->iFlags.IsSet( CAknButtonExtension::ELongPressReported ) && Observer() ) { + if ( redrawNeeded && !hasDrawn ) + { + DrawNow(); + hasDrawn = ETrue; + } Observer()->HandleControlEventL( this, static_cast( CAknButton::ELongPressEndedEvent ) ); @@ -2378,6 +2527,11 @@ if ( RequestExit() && Observer() ) { + if ( redrawNeeded && !hasDrawn ) + { + DrawNow(); + hasDrawn = ETrue; + } Observer()->HandleControlEventL( this, MCoeControlObserver::EEventRequestExit ); } @@ -2385,6 +2539,11 @@ if ( !buttonEvent && !IsDimmed() && Observer() ) { + if ( redrawNeeded && !hasDrawn ) + { + DrawNow(); + hasDrawn = ETrue; + } Observer()->HandleControlEventL( this, MCoeControlObserver::EEventRequestCancel ); @@ -2397,7 +2556,10 @@ iExtension->iFlags.Clear( CAknButtonExtension::EKeyRepeatEventReported ); } } - + if ( hasDrawn ) + { + redrawNeeded = EFalse; + } break; } @@ -2420,6 +2582,13 @@ { if ( iExtension ) iExtension->HandleFeedbackAreaChange(); CAknControl::PositionChanged(); + + //Reset state if observer moved button position. + if ( iButtonPressed && iExtension && !Rect().Contains( iExtension->iPrePointerPos ) ) + { + ResetState(); + } + SetFrameRects(); } // ----------------------------------------------------------------------------- @@ -2432,6 +2601,7 @@ if ( !IsFocused() && iButtonPressed ) { iButtonPressed = EFalse; + SetFrameIDs(); iKeyDownReported = EFalse; } if ( IsVisible() ) @@ -2476,49 +2646,14 @@ EXPORT_C void CAknButton::Draw( const TRect& /*aRect*/ ) const { TRect rect( Rect() ); - TAknLayoutRect centerLayout; - centerLayout.LayoutRect( rect, - AknLayoutScalable_Avkon::toolbar_button_pane_g1().LayoutLine() ); - TRect innerRect( centerLayout.Rect() ); TRect highlightRect( HighlightRect() ); CWindowGc& gc = SystemGc(); CAknButtonState* state = State(); - // Skin ids are determined here (a bit too early than necessary) so that - // we can avoid doing the same thing in DrawMaskedL. - if ( !( iFlags & KAknButtonNoFrame ) ) + if ( !( iFlags & KAknButtonNoFrame ) && !iButtonPressed && state && + state->FlagsChanged() ) { - 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 ) - { - iBgContext->SetFrame( SkinIID( frameIdIndex ) ); - iBgContext->SetCenter( SkinIID( ++frameIdIndex ) ); - iBgContext->SetFrameRects( rect, innerRect ); - } + SetFrameIDs(); } if ( !iExtension->iFlags.IsSet( CAknButtonExtension::EUseAdditionalMask ) ) @@ -2540,13 +2675,10 @@ if ( IsFocused() && !highlightRect.IsEmpty() ) { - iBgContext->SetFrame( KAknsIIDQsnFrButtonHighlight ); - iBgContext->SetCenter( KAknsIIDQsnFrButtonHighlightCenter ); - iBgContext->SetFrameRects( rect, innerRect ); - // frame graphics - if ( !AknsDrawUtils::Background( skin, iBgContext, NULL, gc, - rect, KAknsDrawParamNoClearUnderImage ) ) + if ( !AknsDrawUtils::Background( skin, + iExtension->iHighlightContext, NULL, gc, rect, + KAknsDrawParamNoClearUnderImage ) ) { gc.SetBrushColor( KRgbRed ); gc.SetBrushStyle( CGraphicsContext::ESolidBrush ); @@ -2624,6 +2756,7 @@ } TRAP_IGNORE( SetStateIndexL( newIndex ) ); + SetFrameIDs(); if ( aDrawNow ) { DrawNow(); @@ -2713,10 +2846,13 @@ // ----------------------------------------------------------------------------- // EXPORT_C void CAknButton::SetButtonFlags( const TInt aFlags ) - { - if ( !(iFlags & KAknButtonNoFrame ) && aFlags & KAknButtonNoFrame ) + { + if ( !( iFlags & KAknButtonNoFrame ) ) { - iExtension->iMargins.SetAllValuesTo( 0 ); + if ( aFlags & KAknButtonNoFrame ) + { + iExtension->iMargins.SetAllValuesTo( 0 ); + } } if ( aFlags & KAknButtonHitTest ) { @@ -2791,6 +2927,7 @@ { skinIds[KLatchedDimmedCenterId] = aLatchedDimmedCenterId; } + SetFrameIDs(); } // ----------------------------------------------------------------------------- @@ -2822,6 +2959,7 @@ EXPORT_C void CAknButton::SetTextFont( const CFont* aFont ) { iFont = aFont; + ConvertTextToVisualAndClip( iExtension->iTextRect ); } // ----------------------------------------------------------------------------- @@ -3116,6 +3254,8 @@ } TRAP_IGNORE( SetStateIndexL( newIndex ) ); + // Updating background context might be needed if states flags differ + SetFrameIDs(); if ( aDrawNow ) { @@ -3294,6 +3434,7 @@ StopKeyRepeatTimer(); StopLongPressTimer(); iButtonPressed = EFalse; + SetFrameIDs(); HideHelp(); if ( iExtension ) { @@ -3383,24 +3524,28 @@ // void CAknButton::DrawTextButton( CWindowGc& aGc ) const { + TRect textRect; + + TRect iconRect; //this is no use + GetCurrentStateTextAndIconRect( iconRect, textRect ); + CAknButtonState* state = State(); - if ( !state || !state->HasText() ) - return; - + 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(); - TRect textRect = iExtension->iMargins.InnerRect( Rect() ); - - if ( !( iFlags & KAknButtonNoFrame ) && - ( iFlags & KAknButtonTextInsideFrame ) ) - { - TAknLayoutRect center; - center.LayoutRect( Rect(), - AknLayoutScalable_Avkon::toolbar_button_pane_g1().LayoutLine() ); - - textRect = center.Rect(); - } - aGc.SetBrushStyle( CGraphicsContext::ENullBrush ); TRgb penColor; @@ -3418,17 +3563,6 @@ aGc.SetUnderlineStyle( iExtension->iUnderlineStyle ); - // buffer for visually ordered text - TBuf<255 + KAknBidiExtraSpacePerLine> visualText; - TInt clipWidth = textRect.Width(); - - // bidi processing - using AknBidiTextUtils. - AknBidiTextUtils::ConvertToVisualAndClip( - state->Text(), - visualText, - *font, - clipWidth, - clipWidth ); TInt baselineOffset = 0; switch ( iVerticalAlignment ) @@ -3438,22 +3572,24 @@ break; case EBottom: - baselineOffset = textRect.Height(); + baselineOffset = aTextRect.Height(); break; default: // centered baselineOffset = font->AscentInPixels() + - ( textRect.Height() - font->AscentInPixels() ) / 2; + ( aTextRect.Height() - font->AscentInPixels() ) / 2; } CGraphicsContext::TTextAlign horAlignment = iHorizontalAlignment; - aGc.DrawText( visualText, textRect, baselineOffset, horAlignment ); + aGc.DrawText( iExtension->iVisualText, aTextRect, baselineOffset, + horAlignment ); if ( iExtension->iPictographInterface ) { // For Japanese variant only iExtension->iPictographInterface->Interface()->DrawPictographsInText( - aGc, *font, visualText, textRect, baselineOffset, horAlignment ); + aGc, *font, iExtension->iVisualText, aTextRect, baselineOffset, + horAlignment ); } } @@ -3464,13 +3600,13 @@ // void CAknButton::DrawIconButton( CWindowGc& aGc ) const { - TRect iconRect( iExtension->iMargins.InnerRect( Rect() ) ); + TRect iconRect; + TRect textRect; + GetCurrentStateTextAndIconRect( iconRect, textRect ); aGc.SetBrushStyle( CGraphicsContext::ENullBrush ); const CGulIcon* icon = GetCurrentIcon(); - if ( !icon ) - return; CFbsBitmap* buttonBmp = icon->Bitmap(); CFbsBitmap* buttonMask = icon->Mask(); @@ -3552,98 +3688,24 @@ if ( !state || !state->HasText() ) { return; - } + } const CGulIcon* icon = GetCurrentIcon(); - if ( !icon ) - { - return; - } - - TRect rect = iExtension->iMargins.InnerRect( Rect() ); + + TRect iconRect; TRect textRect; + GetCurrentStateTextAndIconRect( iconRect, textRect ); - if ( !( iFlags & KAknButtonNoFrame ) && - ( iFlags & KAknButtonTextInsideFrame )) - { - TAknLayoutRect centerLayout; - centerLayout.LayoutRect( rect, - AknLayoutScalable_Avkon::toolbar_button_pane_g1().LayoutLine() ); - rect = centerLayout.Rect(); - } - 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 ) + + if ( state->TextChanged() || iExtension->TextRectSizeChanged( textRect ) ) { - case 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 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 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 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 EOverlay: - { - textRect = rect; - iconRect = rect; - } - break; - - default: - return; + ConvertTextToVisualAndClip( textRect ); } - // Draw icon TPoint iconPoint; switch ( iExtension->iHorizontalIconAlignment ) @@ -3708,57 +3770,7 @@ aGc.BitBlt( iconPoint, buttonBmp, iconRect.Size() ); } - const CFont* font = iFont; - if ( !font ) - { - font = iCoeEnv->NormalFont(); - } - aGc.UseFont( font ); - - TRgb penColor; - TRgb brushColor; - GetTextColors( penColor, brushColor ); - aGc.SetPenColor( penColor ); - aGc.SetBrushColor( brushColor ); - - aGc.SetUnderlineStyle( iExtension->iUnderlineStyle ); - - TBuf<255 + KAknBidiExtraSpacePerLine> visualText; // buffer for visually ordered text - TInt clipWidth = textRect.Width(); - - // bidi processing - using AknBidiTextUtils. - AknBidiTextUtils::ConvertToVisualAndClip( - state->Text(), - visualText, - *font, - clipWidth, - clipWidth ); - - TInt baselineOffset = 0; - switch ( iVerticalAlignment ) - { - case ETop: - baselineOffset = font->AscentInPixels(); - break; - - case EBottom: - baselineOffset = textRect.Height(); - break; - - default: // centered - baselineOffset = font->AscentInPixels() + - ( textRect.Height() - font->AscentInPixels() ) / 2; - } - - CGraphicsContext::TTextAlign horAlignment = iHorizontalAlignment; - - aGc.DrawText( visualText, textRect, baselineOffset, horAlignment ); - if ( iExtension->iPictographInterface ) - { - // For Japanese variant only - iExtension->iPictographInterface->Interface()->DrawPictographsInText( - aGc, *font, visualText, textRect, baselineOffset, horAlignment ); - } + DrawText( aGc, textRect ); } // ----------------------------------------------------------------------------- @@ -4345,6 +4357,7 @@ iStates->Delete( iStateIndex ); iStateIndex <= 0 ? iStateIndex = 0 : iStateIndex--; + SetFrameIDs(); DrawNow(); } } @@ -4442,10 +4455,271 @@ 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. // ----------------------------------------------------------------------------- @@ -4463,4 +4737,49 @@ } 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