--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/messagingappbase/msgeditor/mediacontrolsrc/MsgImageControl.cpp Thu Dec 17 08:44:11 2009 +0200
@@ -0,0 +1,1073 @@
+/*
+* Copyright (c) 2005-2006 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:
+* MsgEditor image UI control - a Message Editor Base control.
+*
+*/
+
+
+
+// INCLUDE FILES
+#include "MsgImageControl.h"
+
+#include <DRMCommon.h>
+#include <AknUtils.h> // AknsUtils
+#include <AknsDrawUtils.h> // AknsDrawUtils
+#include <aknlayoutscalable_apps.cdl.h>
+
+#include <MsgEditorView.h> // CMsgEditorView
+#include <MsgEditorCommon.h>
+
+#include <IHLImageFactory.h> // IHLImageFactory
+#include <IHLViewerFactory.h> // IHLViewerFactory
+#include <MIHLFileImage.h> // MIHLFileImage
+#include <MIHLBitmap.h> // MIHLBitmap
+#include <MIHLImageViewer.h> // MIHLImageViewer
+#include <icl/imagecodecdata.h> // KImageTypeBMPUid
+
+#include "MsgFrameControl.h"
+#include "MsgIconControl.h"
+#include "MsgBitmapControl.h"
+
+#include "MsgMediaControlLogging.h"
+
+// ==========================================================
+
+// EXTERNAL DATA STRUCTURES
+
+// EXTERNAL FUNCTION PROTOTYPES
+
+// CONSTANTS
+
+// MACROS
+
+// LOCAL CONSTANTS AND MACROS
+const TInt KAnimationStartDelay = 500000; // 0,5s
+const TInt KAnimationDelayBetweenLoops = 1000000; // 1s
+
+// MODULE DATA STRUCTURES
+
+// LOCAL FUNCTION PROTOTYPES
+
+// ================= MEMBER FUNCTIONS =======================
+
+// ---------------------------------------------------------
+// CMsgImageControl::CMsgImageControl
+//
+// Constructor.
+// ---------------------------------------------------------
+//
+CMsgImageControl::CMsgImageControl( MMsgBaseControlObserver& aBaseControlObserver ) :
+ CMsgMediaControl( aBaseControlObserver, EMsgComponentIdImage, EMsgImageControl )
+ {
+ }
+
+// ---------------------------------------------------------
+// CMsgImageControl::ConstructL
+// ---------------------------------------------------------
+//
+void CMsgImageControl::ConstructL( CMsgEditorView& aParent, MMsgAsyncControlObserver* aObserver )
+ {
+ BaseConstructL( aParent, aObserver );
+
+ iBitmapControl = new( ELeave ) CMsgBitmapControl;
+ iBitmapControl->SetContainerWindowL( *this );
+
+ CalculateMaxSize();
+
+ TRect rect( aParent.Rect() );
+ if ( rect.Height() == 0 || rect.Width() == 0 )
+ {
+ // We have been called before view construction.
+ // Set rect to screen size.
+ rect.SetRect( TPoint(), iMaxSize );
+ }
+
+ SetRect( rect );
+
+ iLoopTimer = CPeriodic::NewL( EPriorityNormal );
+ }
+
+// ---------------------------------------------------------
+// CMsgImageControl::NewL
+//
+// Two-phased constructor.
+// ---------------------------------------------------------
+//
+EXPORT_C CMsgImageControl* CMsgImageControl::NewL( CMsgEditorView& aParent,
+ MMsgAsyncControlObserver* aObserver )
+ {
+ CMsgImageControl* self = new( ELeave ) CMsgImageControl( aParent );
+
+ CleanupStack::PushL( self );
+ self->ConstructL( aParent, aObserver );
+ CleanupStack::Pop( self );
+
+ return self;
+ }
+
+// ---------------------------------------------------------
+// CMsgImageControl::~CMsgImageControl
+//
+// Destructor
+// ---------------------------------------------------------
+//
+CMsgImageControl::~CMsgImageControl()
+ {
+ delete iEngine;
+ delete iDestinationBitmap;
+ delete iSourceImage;
+ delete iBitmapControl;
+ delete iLoopTimer;
+ }
+
+// ---------------------------------------------------------
+// CMsgImageControl::LoadL
+// ---------------------------------------------------------
+//
+void CMsgImageControl::LoadL( RFile& aFileHandle )
+ {
+ Reset();
+
+ iSourceImage = IHLImageFactory::OpenFileImageL( aFileHandle,
+ 0, // image index
+ MIHLFileImage::EOptionNoDRMConsume );
+
+ SetState( EMsgAsyncControlStateOpening );
+
+ iDestinationBitmap = IHLBitmap::CreateL();
+
+ TSize sourceSize( iSourceImage->Size() );
+ TSize targetSize = TSize(
+ Min( sourceSize.iWidth, iMaxSize.iWidth - iFrame->FrameBorderSize().iWidth ),
+ Min( sourceSize.iHeight, iMaxSize.iHeight - iFrame->FrameBorderSize().iHeight ) );
+
+ if ( !iSourceImage->IsAnimation() &&
+ ( iSourceImage->ImageType() == KImageTypeBMPUid ||
+ iSourceImage->ImageType() == KImageTypeGIFUid ||
+ iSourceImage->ImageType() == KImageTypePNGUid ) )
+ {
+ iEngine = IHLViewerFactory::CreateImageViewerL( targetSize,
+ *iSourceImage,
+ *iDestinationBitmap,
+ *this,
+ MIHLImageViewer::EOptionUseBilinearInterpolation);
+ }
+ else
+ {
+ iEngine = IHLViewerFactory::CreateImageViewerL( targetSize,
+ *iSourceImage,
+ *iDestinationBitmap,
+ *this,
+ 0 );
+
+ }
+ }
+
+// ---------------------------------------------------------
+// CMsgImageControl::Cancel
+// ---------------------------------------------------------
+//
+void CMsgImageControl::Cancel()
+ {
+ if ( iState == EMsgAsyncControlStateOpening )
+ {
+ Reset();
+
+ SetState( EMsgAsyncControlStateIdle );
+ }
+ }
+
+// ---------------------------------------------------------
+// CMsgImageControl::PlayL
+// ---------------------------------------------------------
+//
+void CMsgImageControl::PlayL()
+ {
+ if ( IsAnimation() &&
+ iState >= EMsgAsyncControlStateOpening )
+ {
+ DoPlay( 0 );
+ }
+ }
+
+// ---------------------------------------------------------
+// CMsgImageControl::PauseL
+// ---------------------------------------------------------
+//
+void CMsgImageControl::PauseL()
+ {
+ if ( IsAnimation() &&
+ iState >= EMsgAsyncControlStateReady )
+ {
+ DoPause();
+ }
+ }
+
+// ---------------------------------------------------------
+// CMsgImageControl::Stop
+// ---------------------------------------------------------
+//
+void CMsgImageControl::Stop()
+ {
+ if ( IsAnimation() &&
+ iState >= EMsgAsyncControlStateReady )
+ {
+ StopAnimation();
+
+ SetState( EMsgAsyncControlStateStopped );
+ }
+ }
+
+// ---------------------------------------------------------
+// CMsgImageControl::Close
+// ---------------------------------------------------------
+//
+void CMsgImageControl::Close()
+ {
+ Stop();
+ SetState( EMsgAsyncControlStateIdle );
+ }
+
+// ---------------------------------------------------------
+// CMsgImageControl::IsAnimation
+//
+// Return ETrue if loaded image is animation.
+// ---------------------------------------------------------
+//
+EXPORT_C TBool CMsgImageControl::IsAnimation() const
+ {
+ TBool result( EFalse );
+
+ if ( iSourceImage )
+ {
+ result = iSourceImage->IsAnimation();
+ }
+
+ return result;
+ }
+
+// ---------------------------------------------------------
+// CMsgImageControl::SetAnimationLoopCount
+//
+// Sets animation loop count (i.e. how many times animation
+// is played fully through). -1 means that it is looped forever.
+// ---------------------------------------------------------
+//
+EXPORT_C void CMsgImageControl::SetAnimationLoopCount( TInt aCount )
+ {
+ iLoopCount = aCount;
+ }
+
+// ---------------------------------------------------------
+// CMsgImageControl::SetImageFileOpenOrClose
+//
+// Sets image file open or close.
+// ---------------------------------------------------------
+//
+EXPORT_C void CMsgImageControl::SetImageFileClosed( )
+ {
+ if ( iSourceImage )
+ {
+ Stop();
+
+ delete iSourceImage;
+ iSourceImage = NULL;
+
+ delete iEngine;
+ iEngine = NULL;
+
+ SetState( EMsgAsyncControlStateIdle );
+ }
+ }
+
+// ---------------------------------------------------------
+// CMsgImageControl::SetAndGetSizeL
+//
+// Calculates and sets the size of the control and returns new size as
+// reference aSize.
+// ---------------------------------------------------------
+//
+void CMsgImageControl::SetAndGetSizeL( TSize& aSize )
+ {
+ // Adjust max height if needed
+ if ( aSize.iHeight > iMaxSize.iHeight )
+ {
+ aSize.iHeight = iMaxSize.iHeight;
+ }
+
+ // Do not adjust the width. The width of the control must always
+ // be the same as the width of the client rect.
+ aSize = CalculateControlSize( aSize );
+
+ SetSize( aSize );
+ }
+
+
+// ---------------------------------------------------------
+// CMsgImageControl::NotifyViewEvent
+//
+// Animation playback is paused if view looses focus and resumed
+// when focus is again gained. Resuming happens only if animation is
+// still at pause state and control is on playing state.
+// ---------------------------------------------------------
+//
+void CMsgImageControl::NotifyViewEvent( TMsgViewEvent aEvent, TInt aParam )
+ {
+ switch ( aEvent )
+ {
+ case EMsgViewEventViewFocusLost:
+ {
+ if ( iAnimationState == EAnimationPlaying )
+ {
+ PauseAnimation();
+ }
+ break;
+ }
+ case EMsgViewEventViewFocusGain:
+ {
+ if ( iAnimationState == EAnimationPaused &&
+ iState == EMsgAsyncControlStatePlaying )
+ {
+ StartAnimation( KAnimationStartDelay );
+ }
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+
+ CMsgMediaControl::NotifyViewEvent( aEvent, aParam );
+ }
+
+// ---------------------------------------------------------
+// CMsgImageControl::Reset
+//
+// Empties the control.
+// ---------------------------------------------------------
+//
+void CMsgImageControl::Reset()
+ {
+ delete iEngine;
+ iEngine = NULL;
+
+ iAnimationState = EAnimationStopped;
+
+ delete iDestinationBitmap;
+ iDestinationBitmap = NULL;
+
+ iBitmapControl->SetBitmap( NULL );
+
+ delete iSourceImage;
+ iSourceImage = NULL;
+
+ ResetIconId();
+ }
+
+// ---------------------------------------------------------
+// CMsgImageControl::FocusChanged
+//
+// Updates the focus (i.e. set frame control visible/invisible).
+// Calls base class implementation if icon is visible. Otherwise
+// performs it's own handling.
+// Frame control is redraw immediatelly if that
+// is requested and frame control state is changed. Otherwise
+// normal deferred drawing is done. This is activated at
+// CCoeControl::MakeVisible if needed.
+// ---------------------------------------------------------
+//
+void CMsgImageControl::FocusChanged( TDrawNow aDrawNow )
+ {
+ if ( VisiblePlaceholder() )
+ {
+ CMsgMediaControl::FocusChanged( aDrawNow );
+ }
+ else
+ {
+ TBool oldVisibility( iFrame->IsVisible() );
+
+ iFrame->MakeVisible( IsFocused() );
+
+ if ( aDrawNow == EDrawNow &&
+ iFrame->IsVisible() != oldVisibility )
+ {
+ DrawNow();
+ }
+ }
+ }
+
+// ---------------------------------------------------------
+// CMsgImageControl::SizeChanged
+//
+// Called when size is changed.
+// ---------------------------------------------------------
+//
+void CMsgImageControl::SizeChanged()
+ {
+ if ( iEngine &&
+ Size() != iEngine->ViewerSize() )
+ {
+ TSize bitmapSize = iEngine->SourceSize() ;
+ TSize controlSize = iSize;
+ controlSize.iWidth -= iFrame->FrameBorderSize().iWidth;
+ controlSize.iHeight -= iFrame->FrameBorderSize().iHeight;
+
+ TReal widthRatio = static_cast<TReal>( controlSize.iWidth ) /
+ static_cast<TReal>( bitmapSize.iWidth );
+ TReal heightRatio = static_cast<TReal>( controlSize.iHeight ) /
+ static_cast<TReal>( bitmapSize.iHeight );
+ TReal zoomRatio = ( widthRatio < heightRatio ) ? widthRatio : heightRatio;
+
+ iEngine->SetViewerSize( Size() );
+ iEngine->SetZoomRatio( zoomRatio );
+ }
+
+ // Size updated at the ViewerBitmapChanged when image scaling is done.
+ iBitmapControl->SetPosition( Position() + CalculateImagePosition() );
+
+ if ( iDestinationBitmap &&
+ iDestinationBitmap->IsCreated() )
+ {
+ iFrame->SetImageSize( iDestinationBitmap->Bitmap().SizeInPixels() );
+ }
+
+ if ( iState == EMsgAsyncControlStatePlaying )
+ {
+ // Start animation if needed on playing state.
+ StartAnimation( 0 );
+ }
+
+ CMsgMediaControl::SizeChanged();
+ }
+
+// ---------------------------------------------------------
+// CMsgImageControl::Draw
+//
+// Draws the basic skin background for given rectangle.
+// Image is drawn on CBitmapControl::Draw function.
+// ---------------------------------------------------------
+//
+void CMsgImageControl::Draw( const TRect& aRect ) const
+ {
+ CWindowGc& gc = SystemGc();
+
+ if ( !VisiblePlaceholder() )
+ {
+ if ( !AknsDrawUtils::BackgroundBetweenRects( AknsUtils::SkinInstance(),
+ AknsDrawUtils::ControlContext( this ),
+ this,
+ gc,
+ Rect(),
+ iBitmapControl->Rect(),
+ KAknsDrawParamNoClearUnderImage ) )
+ {
+ gc.SetBrushColor( AKN_LAF_COLOR( 0 ) );
+ gc.SetPenStyle( CGraphicsContext::ENullPen );
+ gc.SetBrushStyle( CGraphicsContext::ESolidBrush );
+ gc.DrawRect( aRect );
+ }
+ }
+ else
+ {
+ // Basic icon drawing from base class when icon is visible.
+ CMsgMediaControl::Draw( aRect );
+ }
+ }
+
+// ---------------------------------------------------------
+// CMmsImageControl::MakeVisible
+//
+// Sets same visibility to bitmap control as image control has.
+// ---------------------------------------------------------
+//
+void CMsgImageControl::MakeVisible( TBool aVisible )
+ {
+ iBitmapControl->MakeVisible( aVisible );
+
+ CMsgMediaControl::MakeVisible( aVisible );
+ }
+
+// ---------------------------------------------------------
+// CMmsImageControl::PositionChanged
+//
+// Calculates new position to bitmap control as image control position
+// has changed.
+// ---------------------------------------------------------
+//
+void CMsgImageControl::PositionChanged()
+ {
+ iBitmapControl->SetPosition( Position() + CalculateImagePosition() );
+
+ CMsgMediaControl::PositionChanged();
+ }
+
+// ---------------------------------------------------------
+// CMsgImageControl::HandleResourceChange
+// ---------------------------------------------------------
+//
+void CMsgImageControl::HandleResourceChange( TInt aType )
+ {
+ CMsgMediaControl::HandleResourceChange( aType );
+
+ if ( aType == KEikDynamicLayoutVariantSwitch )
+ {
+ CalculateMaxSize();
+
+ if ( iEngine )
+ {
+ TSize sourceSize( iSourceImage->Size() );
+ TSize targetSize = TSize(
+ Min( sourceSize.iWidth, iMaxSize.iWidth - iFrame->FrameBorderSize().iWidth ),
+ Min( sourceSize.iHeight, iMaxSize.iHeight - iFrame->FrameBorderSize().iHeight ) );
+
+ iBitmapControl->SetSize( TSize( 0, 0 ) );
+ SetSize( targetSize );
+ }
+ }
+ }
+
+// ---------------------------------------------------------
+// CMmsImageControl::CountComponentControls
+//
+// Return count of controls be included in this component.
+// ---------------------------------------------------------
+//
+TInt CMsgImageControl::CountComponentControls() const
+ {
+ return 2;
+ }
+
+// ---------------------------------------------------------
+// CMmsImageControl::ComponentControl
+//
+// Return pointer to component in question.
+// Note! Image and Icon cannot exist at a same time.
+// ---------------------------------------------------------
+//
+CCoeControl* CMsgImageControl::ComponentControl( TInt aIndex ) const
+ {
+ CCoeControl* result = NULL;
+ switch ( aIndex )
+ {
+ case 0:
+ {
+ result = iFrame;
+ break;
+ }
+ case 1:
+ {
+ CCoeControl* visiblePlaceholder = VisiblePlaceholder();
+ if ( visiblePlaceholder )
+ {
+ result = visiblePlaceholder;
+ }
+ else
+ {
+ result = iBitmapControl;
+ }
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+
+ return result;
+ }
+
+// ---------------------------------------------------------
+// CMsgImageControl::IsOffScreen
+//
+// Returns ETrue if image is off screen.
+// ---------------------------------------------------------
+//
+TBool CMsgImageControl::IsOffScreen() const
+ {
+ TRect rect( Position() + CalculateImagePosition(),
+ iDestinationBitmap->Bitmap().SizeInPixels() );
+
+ TBool result( EFalse );
+
+ if ( rect.iTl.iY < 0 ||
+ rect.iBr.iY > MsgEditorCommons::MsgMainPane().Height() )
+ {
+ result = ETrue;
+ }
+
+ return result;
+ }
+
+
+// ---------------------------------------------------------
+// CMsgImageControl::ViewerBitmapChangedL
+//
+// Handle bitmap change notifications. State is changed accordingly
+// if this is the first frame. GIF animation is stopped if control
+// goes off screen and started again when it is fully visible and control
+// is on playing state. On editor mode animation is looped only once.
+// Animation is also stopped if animation loop count is reached.
+// New animation loop is started after KAnimationDelayBetweenLoops
+// delay.
+// ---------------------------------------------------------
+//
+void CMsgImageControl::ViewerBitmapChangedL()
+ {
+ if ( iState == EMsgAsyncControlStateOpening )
+ {
+ SetState( EMsgAsyncControlStateReady );
+
+ if ( iAnimationState == EAnimationPlaying )
+ {
+ SetState( EMsgAsyncControlStatePlaying );
+ }
+ }
+
+ if ( iSourceImage->IsAnimation() )
+ {
+ switch ( iAnimationState )
+ {
+ case EAnimationPlaying:
+ {
+ if ( IsOffScreen() )
+ {
+ // Stop the playback if animation is not fully visible
+ StopAnimation();
+ }
+ else if ( iEngine->AnimationFrame() ==
+ iSourceImage->AnimationFrameCount() - 1 )
+ {
+ // Last frame of the animation has been loaded.
+ iCurrentLoop++;
+
+ if ( iCurrentLoop == iLoopCount )
+ {
+ // Maximum loop count reached. Do not stop yet as first
+ // frame is wanted to be displayed. Stopping is done on
+ // EAnimationStopped state.
+ iAnimationState = EAnimationStopped;
+ }
+ else
+ {
+ iEngine->Stop();
+
+ iLoopTimer->Cancel();
+ iLoopTimer->Start( KAnimationDelayBetweenLoops,
+ KAnimationDelayBetweenLoops,
+ TCallBack( DoStartLoop, this ) );
+ }
+ }
+ break;
+ }
+ case EAnimationStopped:
+ {
+ if( iState == EMsgAsyncControlStatePlaying &&
+ !IsOffScreen() &&
+ iCurrentLoop != iLoopCount )
+ {
+ StartAnimation( 0 );
+ }
+ else
+ {
+ StopAnimation();
+ }
+ break;
+ }
+ case EAnimationNotReady:
+ default:
+ {
+ break;
+ }
+ }
+ }
+
+ iBitmapControl->SetBitmap( iDestinationBitmap );
+
+ TRect imageRect( Position() + CalculateImagePosition(),
+ iDestinationBitmap->Bitmap().SizeInPixels() );
+ iBitmapControl->SetRect( imageRect );
+
+ if( IsVisible() )
+ {
+ // Sometimes iDestinationBitmap is not ready when in SizeChanged()
+ if ( iDestinationBitmap &&
+ iDestinationBitmap->IsCreated() )
+ {
+ iFrame->SetImageSize( imageRect.Size() );
+ }
+
+ DrawNow();
+ }
+ }
+
+// ---------------------------------------------------------
+// CMsgImageControl::ViewerError
+//
+// Handles engine errors.
+// ---------------------------------------------------------
+//
+void CMsgImageControl::ViewerError( TInt aError )
+ {
+ MSGMEDIACONTROLLOGGER_WRITEF_ERROR_STATE( _L("CMsgImageControl::HandleCallback: **aError: %d, CurrentState: %S"),aError, iState);
+
+ iError = aError;
+
+ switch ( aError )
+ {
+ case KErrNone:
+ {
+ if ( iState == EMsgAsyncControlStateOpening )
+ {
+ // image shown in the viewer and image had rights
+ SetState( EMsgAsyncControlStateReady );
+ DoPlay( 0 );
+ }
+ else if ( iState == EMsgAsyncControlStatePlaying )
+ {
+ SetState( EMsgAsyncControlStateReady );
+ DoPlay( 0 );
+ }
+ break;
+ }
+ case DRMCommon::EGeneralError:
+ case DRMCommon::EUnknownMIME:
+ case DRMCommon::EVersionNotSupported:
+ case DRMCommon::ESessionError:
+ case DRMCommon::ENoRights:
+ case DRMCommon::ERightsDBCorrupted:
+ case DRMCommon::EUnsupported:
+ case DRMCommon::ERightsExpired:
+ case DRMCommon::EInvalidRights:
+ {
+ SetState( EMsgAsyncControlStateNoRights );
+ break;
+ }
+ case KErrNoMemory: // cannot recover
+ default:
+ {
+ SetState( EMsgAsyncControlStateCorrupt );
+ break;
+ }
+ }
+ }
+
+// ---------------------------------------------------------
+// CMsgImageControl::CalculateImagePosition
+//
+// Calculates image position so that it is centered to
+// control extent.
+// ---------------------------------------------------------
+//
+TPoint CMsgImageControl::CalculateImagePosition() const
+ {
+ TPoint result;
+
+ TSize controlSize( Size() );
+ TSize imageSize;
+
+ if ( iEngine )
+ {
+ imageSize = iEngine->SourceSize();
+ imageSize.iWidth *= iEngine->ZoomRatio();
+ imageSize.iHeight *= iEngine->ZoomRatio();
+ }
+ else
+ {
+ // Engine has been unloaded. Use current bitmap control size
+ // as imageSize.
+ imageSize = iBitmapControl->Size();
+ }
+
+ result.iX = ( controlSize.iWidth - imageSize.iWidth ) / 2;
+ result.iY = ( controlSize.iHeight - imageSize.iHeight ) / 2;
+
+ if ( result.iX < 0 )
+ {
+ result.iX = 0;
+ }
+
+ if ( result.iY < 0 )
+ {
+ result.iY = 0;
+ }
+
+ return result;
+ }
+
+// ---------------------------------------------------------
+// CMsgImageControl::CalculateControlSize
+//
+// Calculates the correct size for the image control.
+// ---------------------------------------------------------
+//
+TSize CMsgImageControl::CalculateControlSize( const TSize& aProposedSize ) const
+ {
+ TSize result( aProposedSize.iWidth, 0 );
+ TSize bitmapSize = BitmapSize();
+
+ if ( !bitmapSize.iHeight || !bitmapSize.iWidth )
+ {
+ result.iHeight = aProposedSize.iHeight;
+ return result;
+ }
+ else if ( bitmapSize.iHeight < aProposedSize.iHeight )
+ {
+ result.iHeight = bitmapSize.iHeight;
+ }
+ else
+ {
+ result.iHeight = aProposedSize.iHeight;
+ }
+
+ TInt scaledHeight(
+ ( static_cast<TReal>( bitmapSize.iHeight ) /
+ static_cast<TReal>( bitmapSize.iWidth ) ) *
+ aProposedSize.iWidth );
+ if ( scaledHeight < result.iHeight )
+ {
+ result.iHeight = scaledHeight;
+ }
+
+ // Height should be multiple of baseline.
+ // Round up to the next full multiple if needed.
+ TInt remainder = result.iHeight % iBaseLine;
+ if ( remainder )
+ {
+ result.iHeight += ( iBaseLine - remainder );
+ }
+
+ if ( result.iHeight > iMaxSize.iHeight )
+ {
+ result.iHeight = iMaxSize.iHeight;
+ }
+
+ return result;
+ }
+
+// ---------------------------------------------------------
+// CMsgImageControl::BitmapSize
+//
+// Returns correct size for bitmap.
+// ---------------------------------------------------------
+//
+TSize CMsgImageControl::BitmapSize() const
+ {
+ TSize bitmapSize( 0, 0 );
+ if ( !iIconControl->IsVisible() &&
+ ( iBitmapControl->Size().iWidth == 0 ||
+ iBitmapControl->Size().iHeight == 0 ) )
+ {
+ if ( iEngine )
+ {
+ bitmapSize = iEngine->SourceSize() ;
+ bitmapSize.iWidth += iFrame->FrameBorderSize().iWidth;
+ bitmapSize.iHeight += iFrame->FrameBorderSize().iHeight;
+ }
+ }
+ else
+ {
+ // Bitmap or icon visible.
+ bitmapSize = iFrame->FrameSize();
+ }
+
+ return bitmapSize;
+ }
+
+// ---------------------------------------------------------
+// CMsgImageControl::DoPlay
+//
+// Starts animation if possible and sets control to correct state.
+// ---------------------------------------------------------
+//
+void CMsgImageControl::DoPlay( TInt aAnimationStartDelay )
+ {
+ StartAnimation( aAnimationStartDelay );
+
+ if ( iState != EMsgAsyncControlStateOpening )
+ {
+ SetState( EMsgAsyncControlStatePlaying );
+ }
+ }
+
+// ---------------------------------------------------------
+// CMsgImageControl::DoPause
+//
+// Stops animation and sets control to correct state.
+// ---------------------------------------------------------
+//
+void CMsgImageControl::DoPause()
+ {
+ StopAnimation();
+
+ SetState( EMsgAsyncControlStatePaused );
+ }
+
+// ---------------------------------------------------------
+// CMsgImageControl::CalculateMaxSize
+// ---------------------------------------------------------
+//
+void CMsgImageControl::CalculateMaxSize()
+ {
+ TAknLayoutRect maxSizeLayout;
+ maxSizeLayout.LayoutRect( MsgEditorCommons::MsgDataPane(),
+ AknLayoutScalable_Apps::msg_data_pane_g1().LayoutLine() );
+
+ iMaxSize = maxSizeLayout.Rect().Size();
+
+ // Make sure "iMaxSize" is multiple of "iBaseLine"
+ iMaxSize.iHeight = iBaseLine * ( iMaxSize.iHeight / iBaseLine );
+ }
+
+// ---------------------------------------------------------
+// CMsgImageControl::HitRegionContains
+//
+// Note! CONE will do final verification if control is really hit so
+// not need to do it here.
+// ---------------------------------------------------------
+//
+#ifdef RD_SCALABLE_UI_V2
+TBool CMsgImageControl::HitRegionContains( const TPoint& aPoint,
+ const CCoeControl& /*aControl*/ ) const
+ {
+ TBool result( EFalse );
+
+ CCoeControl* visiblePlaceholder = VisiblePlaceholder();
+
+ if ( visiblePlaceholder )
+ {
+ result = visiblePlaceholder->Rect().Contains( aPoint );
+ }
+ else
+ {
+ result = iBitmapControl->Rect().Contains( aPoint );
+ }
+
+ return result;
+ }
+#else
+TBool CMsgImageControl::HitRegionContains( const TPoint& /*aPoint*/,
+ const CCoeControl& /*aControl*/ ) const
+ {
+ return EFalse;
+ }
+#endif
+
+
+// ---------------------------------------------------------
+// CMsgImageControl::FrameSize
+//
+// Returns the framesize
+// ---------------------------------------------------------
+//
+EXPORT_C TSize CMsgImageControl::FrameSize()
+ {
+ return iFrame->FrameSize();
+ }
+
+// ---------------------------------------------------------
+// CMsgImageControl::StartAnimation
+//
+// Starts animation if possible.
+// ---------------------------------------------------------
+//
+void CMsgImageControl::StartAnimation( TInt aAnimationStartDelay )
+ {
+ iLoopTimer->Cancel();
+
+ if ( iEngine &&
+ IsAnimation() &&
+ !IsOffScreen() &&
+ iLoopCount != iCurrentLoop )
+ {
+ iAnimationState = EAnimationPlaying;
+
+ if ( aAnimationStartDelay == 0 )
+ {
+ iEngine->Play();
+ }
+ else
+ {
+ iLoopTimer->Start( aAnimationStartDelay,
+ aAnimationStartDelay,
+ TCallBack( DoStartLoop, this ) );
+ }
+ }
+ }
+
+// ---------------------------------------------------------
+// CMsgImageControl::StopAnimation
+//
+// Stops animation if possible.
+// ---------------------------------------------------------
+//
+void CMsgImageControl::StopAnimation()
+ {
+ iLoopTimer->Cancel();
+
+ if ( iEngine &&
+ IsAnimation() )
+ {
+ iEngine->Stop();
+ iAnimationState = EAnimationStopped;
+ }
+ }
+
+// ---------------------------------------------------------
+// CMsgImageControl::PauseAnimation
+//
+// Pauses animation if possible.
+// ---------------------------------------------------------
+//
+void CMsgImageControl::PauseAnimation()
+ {
+ StopAnimation();
+ iAnimationState = EAnimationPaused;
+ }
+
+// ---------------------------------------------------------
+// CMsgImageControl::DoStartLoop
+//
+// Start new animation loop.
+// ---------------------------------------------------------
+//
+TInt CMsgImageControl::DoStartLoop( TAny* aObject )
+ {
+ // cast, and call non-static function
+ CMsgImageControl* control = static_cast<CMsgImageControl*>( aObject );
+ control->StartLoop();
+
+ return KErrNone;
+ }
+
+// ---------------------------------------------------------
+// CMsgImageControl::StartLoop
+//
+// Start new animation loop.
+// ---------------------------------------------------------
+//
+void CMsgImageControl::StartLoop()
+ {
+ if ( iAnimationState == EAnimationPlaying )
+ {
+ StartAnimation( 0 );
+ }
+ else
+ {
+ iLoopTimer->Cancel();
+ }
+ }
+
+// End of File