messagingappbase/msgeditor/mediacontrolsrc/MsgImageControl.cpp
changeset 0 72b543305e3a
child 28 fc3320e39880
equal deleted inserted replaced
-1:000000000000 0:72b543305e3a
       
     1 /*
       
     2 * Copyright (c) 2005-2006 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  
       
    15 *       MsgEditor image UI control - a Message Editor Base control.
       
    16 *
       
    17 */
       
    18 
       
    19 
       
    20 
       
    21 // INCLUDE FILES
       
    22 #include "MsgImageControl.h"
       
    23 
       
    24 #include <DRMCommon.h>
       
    25 #include <AknUtils.h>               // AknsUtils
       
    26 #include <AknsDrawUtils.h>          // AknsDrawUtils
       
    27 #include <aknlayoutscalable_apps.cdl.h>
       
    28 
       
    29 #include <MsgEditorView.h>          // CMsgEditorView
       
    30 #include <MsgEditorCommon.h>
       
    31 
       
    32 #include <IHLImageFactory.h>        // IHLImageFactory
       
    33 #include <IHLViewerFactory.h>       // IHLViewerFactory
       
    34 #include <MIHLFileImage.h>          // MIHLFileImage
       
    35 #include <MIHLBitmap.h>             // MIHLBitmap
       
    36 #include <MIHLImageViewer.h>        // MIHLImageViewer
       
    37 #include <icl/imagecodecdata.h>     // KImageTypeBMPUid
       
    38 
       
    39 #include "MsgFrameControl.h"
       
    40 #include "MsgIconControl.h"
       
    41 #include "MsgBitmapControl.h"
       
    42 
       
    43 #include "MsgMediaControlLogging.h"
       
    44 
       
    45 // ==========================================================
       
    46 
       
    47 // EXTERNAL DATA STRUCTURES
       
    48 
       
    49 // EXTERNAL FUNCTION PROTOTYPES
       
    50 
       
    51 // CONSTANTS
       
    52 
       
    53 // MACROS
       
    54 
       
    55 // LOCAL CONSTANTS AND MACROS
       
    56 const TInt KAnimationStartDelay = 500000; // 0,5s
       
    57 const TInt KAnimationDelayBetweenLoops = 1000000; // 1s
       
    58 
       
    59 // MODULE DATA STRUCTURES
       
    60 
       
    61 // LOCAL FUNCTION PROTOTYPES
       
    62 
       
    63 // ================= MEMBER FUNCTIONS =======================
       
    64 
       
    65 // ---------------------------------------------------------
       
    66 // CMsgImageControl::CMsgImageControl
       
    67 //
       
    68 // Constructor.
       
    69 // ---------------------------------------------------------
       
    70 //
       
    71 CMsgImageControl::CMsgImageControl( MMsgBaseControlObserver& aBaseControlObserver ) : 
       
    72     CMsgMediaControl( aBaseControlObserver, EMsgComponentIdImage, EMsgImageControl )
       
    73     {
       
    74     }
       
    75 
       
    76 // ---------------------------------------------------------
       
    77 // CMsgImageControl::ConstructL
       
    78 // ---------------------------------------------------------
       
    79 //
       
    80 void CMsgImageControl::ConstructL( CMsgEditorView& aParent, MMsgAsyncControlObserver* aObserver )
       
    81     {
       
    82     BaseConstructL( aParent, aObserver );    
       
    83     
       
    84     iBitmapControl = new( ELeave ) CMsgBitmapControl;
       
    85     iBitmapControl->SetContainerWindowL( *this );
       
    86     
       
    87     CalculateMaxSize();
       
    88 
       
    89     TRect rect( aParent.Rect() );
       
    90     if ( rect.Height() == 0 || rect.Width() == 0 )
       
    91         {
       
    92         // We have been called before view construction.
       
    93         // Set rect to screen size.
       
    94         rect.SetRect( TPoint(), iMaxSize );
       
    95         }
       
    96 
       
    97     SetRect( rect );
       
    98     
       
    99     iLoopTimer = CPeriodic::NewL( EPriorityNormal );
       
   100     }
       
   101 
       
   102 // ---------------------------------------------------------
       
   103 // CMsgImageControl::NewL
       
   104 //
       
   105 // Two-phased constructor.
       
   106 // ---------------------------------------------------------
       
   107 //
       
   108 EXPORT_C CMsgImageControl* CMsgImageControl::NewL( CMsgEditorView& aParent,
       
   109                                                    MMsgAsyncControlObserver* aObserver )
       
   110     {
       
   111     CMsgImageControl* self = new( ELeave ) CMsgImageControl( aParent );
       
   112     
       
   113     CleanupStack::PushL( self );
       
   114     self->ConstructL( aParent, aObserver );
       
   115     CleanupStack::Pop( self );
       
   116     
       
   117     return self;
       
   118     }
       
   119 
       
   120 // ---------------------------------------------------------
       
   121 // CMsgImageControl::~CMsgImageControl
       
   122 //
       
   123 // Destructor
       
   124 // ---------------------------------------------------------
       
   125 //
       
   126 CMsgImageControl::~CMsgImageControl()
       
   127     {
       
   128     delete iEngine;
       
   129     delete iDestinationBitmap;
       
   130     delete iSourceImage;
       
   131     delete iBitmapControl;
       
   132     delete iLoopTimer;
       
   133     }
       
   134     
       
   135 // ---------------------------------------------------------
       
   136 // CMsgImageControl::LoadL
       
   137 // ---------------------------------------------------------
       
   138 //
       
   139 void CMsgImageControl::LoadL( RFile& aFileHandle )
       
   140     {
       
   141     Reset();
       
   142     
       
   143     iSourceImage = IHLImageFactory::OpenFileImageL( aFileHandle, 
       
   144                                                     0,  // image index
       
   145                                                     MIHLFileImage::EOptionNoDRMConsume );
       
   146     
       
   147     SetState( EMsgAsyncControlStateOpening );
       
   148     
       
   149     iDestinationBitmap = IHLBitmap::CreateL();
       
   150             
       
   151     TSize sourceSize( iSourceImage->Size() );
       
   152     TSize targetSize = TSize(
       
   153     	Min( sourceSize.iWidth, iMaxSize.iWidth - iFrame->FrameBorderSize().iWidth ),
       
   154 		Min( sourceSize.iHeight, iMaxSize.iHeight - iFrame->FrameBorderSize().iHeight ) );
       
   155 
       
   156     if ( !iSourceImage->IsAnimation() &&
       
   157          ( iSourceImage->ImageType() == KImageTypeBMPUid || 
       
   158            iSourceImage->ImageType() == KImageTypeGIFUid ||
       
   159            iSourceImage->ImageType() == KImageTypePNGUid ) )
       
   160         {
       
   161         iEngine = IHLViewerFactory::CreateImageViewerL( targetSize,
       
   162                                                         *iSourceImage, 
       
   163                                                         *iDestinationBitmap, 
       
   164                                                         *this, 
       
   165                                                         MIHLImageViewer::EOptionUseBilinearInterpolation);
       
   166         }
       
   167    else
       
   168         {
       
   169         iEngine = IHLViewerFactory::CreateImageViewerL( targetSize,
       
   170                                                         *iSourceImage, 
       
   171                                                         *iDestinationBitmap, 
       
   172                                                         *this, 
       
   173                                                         0 );
       
   174         
       
   175         }
       
   176     }
       
   177 
       
   178 // ---------------------------------------------------------
       
   179 // CMsgImageControl::Cancel
       
   180 // ---------------------------------------------------------
       
   181 //
       
   182 void CMsgImageControl::Cancel()
       
   183     {
       
   184     if ( iState == EMsgAsyncControlStateOpening )
       
   185         {
       
   186         Reset();
       
   187         
       
   188         SetState( EMsgAsyncControlStateIdle );
       
   189         }
       
   190     }
       
   191 
       
   192 // ---------------------------------------------------------
       
   193 // CMsgImageControl::PlayL
       
   194 // ---------------------------------------------------------
       
   195 //
       
   196 void CMsgImageControl::PlayL()
       
   197     {
       
   198     if ( IsAnimation() &&
       
   199          iState >= EMsgAsyncControlStateOpening )
       
   200         {
       
   201         DoPlay( 0 );
       
   202         }
       
   203     }
       
   204 
       
   205 // ---------------------------------------------------------
       
   206 // CMsgImageControl::PauseL
       
   207 // ---------------------------------------------------------
       
   208 //
       
   209 void CMsgImageControl::PauseL()
       
   210     {
       
   211     if ( IsAnimation() && 
       
   212          iState >= EMsgAsyncControlStateReady )
       
   213         {
       
   214         DoPause();
       
   215         }
       
   216     }
       
   217      
       
   218 // ---------------------------------------------------------
       
   219 // CMsgImageControl::Stop
       
   220 // ---------------------------------------------------------
       
   221 //
       
   222 void CMsgImageControl::Stop()
       
   223     {    
       
   224     if ( IsAnimation() && 
       
   225          iState >= EMsgAsyncControlStateReady )
       
   226         {
       
   227         StopAnimation();
       
   228     
       
   229         SetState( EMsgAsyncControlStateStopped );
       
   230         }
       
   231     }
       
   232 
       
   233 // ---------------------------------------------------------
       
   234 // CMsgImageControl::Close
       
   235 // ---------------------------------------------------------
       
   236 //
       
   237 void CMsgImageControl::Close()
       
   238     {
       
   239     Stop();
       
   240     SetState( EMsgAsyncControlStateIdle );
       
   241     }
       
   242 
       
   243 // ---------------------------------------------------------
       
   244 // CMsgImageControl::IsAnimation
       
   245 //
       
   246 // Return ETrue if loaded image is animation.
       
   247 // ---------------------------------------------------------
       
   248 //
       
   249 EXPORT_C TBool CMsgImageControl::IsAnimation() const
       
   250     {
       
   251     TBool result( EFalse );
       
   252     
       
   253     if ( iSourceImage )
       
   254         {
       
   255         result = iSourceImage->IsAnimation();
       
   256         }
       
   257         
       
   258     return result;
       
   259     }
       
   260 
       
   261 // ---------------------------------------------------------
       
   262 // CMsgImageControl::SetAnimationLoopCount
       
   263 //
       
   264 // Sets animation loop count (i.e. how many times animation
       
   265 // is played fully through). -1 means that it is looped forever.
       
   266 // ---------------------------------------------------------
       
   267 //
       
   268 EXPORT_C void CMsgImageControl::SetAnimationLoopCount( TInt aCount )
       
   269     {
       
   270     iLoopCount = aCount;
       
   271     }
       
   272 
       
   273 // ---------------------------------------------------------
       
   274 // CMsgImageControl::SetImageFileOpenOrClose
       
   275 //
       
   276 // Sets image file open or close.
       
   277 // ---------------------------------------------------------
       
   278 //
       
   279 EXPORT_C void CMsgImageControl::SetImageFileClosed( )
       
   280     {
       
   281     if ( iSourceImage )
       
   282         {
       
   283         Stop();
       
   284         
       
   285         delete iSourceImage;
       
   286         iSourceImage = NULL;
       
   287         
       
   288         delete iEngine;
       
   289         iEngine = NULL;
       
   290         
       
   291         SetState( EMsgAsyncControlStateIdle );
       
   292         }
       
   293     }
       
   294 
       
   295 // ---------------------------------------------------------
       
   296 // CMsgImageControl::SetAndGetSizeL
       
   297 //
       
   298 // Calculates and sets the size of the control and returns new size as
       
   299 // reference aSize.
       
   300 // ---------------------------------------------------------
       
   301 //
       
   302 void CMsgImageControl::SetAndGetSizeL( TSize& aSize )
       
   303     {
       
   304     // Adjust max height if needed
       
   305     if ( aSize.iHeight > iMaxSize.iHeight )
       
   306         {
       
   307         aSize.iHeight = iMaxSize.iHeight;
       
   308         }
       
   309 
       
   310     // Do not adjust the width. The width of the control must always
       
   311     // be the same as the width of the client rect.
       
   312     aSize = CalculateControlSize( aSize );
       
   313 
       
   314     SetSize( aSize );
       
   315     }
       
   316 
       
   317 
       
   318 // ---------------------------------------------------------
       
   319 // CMsgImageControl::NotifyViewEvent
       
   320 //
       
   321 // Animation playback is paused if view looses focus and resumed
       
   322 // when focus is again gained. Resuming happens only if animation is
       
   323 // still at pause state and control is on playing state.
       
   324 // ---------------------------------------------------------
       
   325 //
       
   326 void CMsgImageControl::NotifyViewEvent( TMsgViewEvent aEvent, TInt aParam )
       
   327     {
       
   328     switch ( aEvent )
       
   329         {
       
   330         case EMsgViewEventViewFocusLost:
       
   331             {
       
   332             if ( iAnimationState == EAnimationPlaying )
       
   333                 {
       
   334                 PauseAnimation();
       
   335                 }
       
   336             break;
       
   337             }
       
   338         case EMsgViewEventViewFocusGain:
       
   339             {
       
   340             if ( iAnimationState == EAnimationPaused &&
       
   341                  iState == EMsgAsyncControlStatePlaying )
       
   342                 {
       
   343                 StartAnimation( KAnimationStartDelay );
       
   344                 }
       
   345             break;
       
   346             }
       
   347         default:
       
   348             {
       
   349             break;
       
   350             }
       
   351         }
       
   352         
       
   353     CMsgMediaControl::NotifyViewEvent( aEvent, aParam );
       
   354     }
       
   355 
       
   356 // ---------------------------------------------------------
       
   357 // CMsgImageControl::Reset
       
   358 //
       
   359 // Empties the control.
       
   360 // ---------------------------------------------------------
       
   361 //
       
   362 void CMsgImageControl::Reset()
       
   363     {
       
   364     delete iEngine;
       
   365     iEngine = NULL;
       
   366     
       
   367     iAnimationState = EAnimationStopped;
       
   368     
       
   369     delete iDestinationBitmap;
       
   370     iDestinationBitmap = NULL;
       
   371     
       
   372     iBitmapControl->SetBitmap( NULL );
       
   373     
       
   374     delete iSourceImage;
       
   375     iSourceImage = NULL;
       
   376     
       
   377     ResetIconId();
       
   378     }
       
   379 
       
   380 // ---------------------------------------------------------
       
   381 // CMsgImageControl::FocusChanged
       
   382 //
       
   383 // Updates the focus (i.e. set frame control visible/invisible).
       
   384 // Calls base class implementation if icon is visible. Otherwise
       
   385 // performs it's own handling.
       
   386 // Frame control is redraw immediatelly if that 
       
   387 // is requested and frame control state is changed. Otherwise
       
   388 // normal deferred drawing is done. This is activated at 
       
   389 // CCoeControl::MakeVisible if needed.
       
   390 // ---------------------------------------------------------
       
   391 //
       
   392 void CMsgImageControl::FocusChanged( TDrawNow aDrawNow )
       
   393     {
       
   394     if ( VisiblePlaceholder() )
       
   395         {
       
   396         CMsgMediaControl::FocusChanged( aDrawNow );
       
   397         }
       
   398     else 
       
   399         {
       
   400         TBool oldVisibility( iFrame->IsVisible() );
       
   401     
       
   402         iFrame->MakeVisible( IsFocused() );
       
   403         
       
   404         if ( aDrawNow == EDrawNow &&
       
   405              iFrame->IsVisible() != oldVisibility )
       
   406             {
       
   407             DrawNow();
       
   408             }
       
   409         }
       
   410     }
       
   411 
       
   412 // ---------------------------------------------------------
       
   413 // CMsgImageControl::SizeChanged
       
   414 //
       
   415 // Called when size is changed.
       
   416 // ---------------------------------------------------------
       
   417 //
       
   418 void CMsgImageControl::SizeChanged()
       
   419     {
       
   420     if ( iEngine && 
       
   421          Size() != iEngine->ViewerSize() )
       
   422         {
       
   423         TSize bitmapSize = iEngine->SourceSize() ;
       
   424         TSize controlSize = iSize;
       
   425         controlSize.iWidth -= iFrame->FrameBorderSize().iWidth;
       
   426         controlSize.iHeight -= iFrame->FrameBorderSize().iHeight;
       
   427         
       
   428         TReal widthRatio = static_cast<TReal>( controlSize.iWidth ) / 
       
   429                            static_cast<TReal>( bitmapSize.iWidth );
       
   430         TReal heightRatio = static_cast<TReal>( controlSize.iHeight ) / 
       
   431                             static_cast<TReal>( bitmapSize.iHeight );
       
   432         TReal zoomRatio = ( widthRatio < heightRatio ) ? widthRatio : heightRatio;
       
   433         
       
   434         iEngine->SetViewerSize( Size() );
       
   435         iEngine->SetZoomRatio( zoomRatio );
       
   436         }
       
   437     
       
   438     // Size updated at the ViewerBitmapChanged when image scaling is done.
       
   439     iBitmapControl->SetPosition( Position() + CalculateImagePosition() );
       
   440         
       
   441     if ( iDestinationBitmap && 
       
   442          iDestinationBitmap->IsCreated() )
       
   443         {
       
   444         iFrame->SetImageSize( iDestinationBitmap->Bitmap().SizeInPixels() );
       
   445         }
       
   446     
       
   447     if ( iState == EMsgAsyncControlStatePlaying )
       
   448         {
       
   449         // Start animation if needed on playing state.
       
   450         StartAnimation( 0 );
       
   451         }
       
   452         
       
   453     CMsgMediaControl::SizeChanged();
       
   454     }
       
   455 
       
   456 // ---------------------------------------------------------
       
   457 // CMsgImageControl::Draw
       
   458 //
       
   459 // Draws the basic skin background for given rectangle. 
       
   460 // Image is drawn on CBitmapControl::Draw function.
       
   461 // ---------------------------------------------------------
       
   462 //
       
   463 void CMsgImageControl::Draw( const TRect& aRect ) const
       
   464     {
       
   465     CWindowGc& gc = SystemGc();
       
   466     
       
   467     if ( !VisiblePlaceholder() )
       
   468         {
       
   469         if ( !AknsDrawUtils::BackgroundBetweenRects( AknsUtils::SkinInstance(), 
       
   470                                                  AknsDrawUtils::ControlContext( this ), 
       
   471                                                  this, 
       
   472                                                  gc, 
       
   473                                                  Rect(),
       
   474                                                  iBitmapControl->Rect(),
       
   475                                                  KAknsDrawParamNoClearUnderImage ) )
       
   476             {
       
   477             gc.SetBrushColor( AKN_LAF_COLOR( 0 ) );
       
   478             gc.SetPenStyle( CGraphicsContext::ENullPen );
       
   479     		gc.SetBrushStyle( CGraphicsContext::ESolidBrush );
       
   480         	gc.DrawRect( aRect );
       
   481             }
       
   482         }
       
   483     else 
       
   484         {
       
   485         // Basic icon drawing from base class when icon is visible.
       
   486         CMsgMediaControl::Draw( aRect );
       
   487         }
       
   488     }
       
   489 
       
   490 // ---------------------------------------------------------
       
   491 // CMmsImageControl::MakeVisible
       
   492 //
       
   493 // Sets same visibility to bitmap control as image control has.
       
   494 // ---------------------------------------------------------
       
   495 //
       
   496 void CMsgImageControl::MakeVisible( TBool aVisible )
       
   497     {
       
   498     iBitmapControl->MakeVisible( aVisible );
       
   499     
       
   500     CMsgMediaControl::MakeVisible( aVisible );
       
   501     }
       
   502 
       
   503 // ---------------------------------------------------------
       
   504 // CMmsImageControl::PositionChanged
       
   505 //
       
   506 // Calculates new position to bitmap control as image control position
       
   507 // has changed.
       
   508 // ---------------------------------------------------------
       
   509 //
       
   510 void CMsgImageControl::PositionChanged()
       
   511     {
       
   512     iBitmapControl->SetPosition( Position() + CalculateImagePosition() );
       
   513     
       
   514     CMsgMediaControl::PositionChanged();
       
   515     }
       
   516 
       
   517 // ---------------------------------------------------------
       
   518 // CMsgImageControl::HandleResourceChange
       
   519 // ---------------------------------------------------------
       
   520 //
       
   521 void CMsgImageControl::HandleResourceChange( TInt aType )
       
   522     {
       
   523     CMsgMediaControl::HandleResourceChange( aType ); 
       
   524     
       
   525     if ( aType == KEikDynamicLayoutVariantSwitch )
       
   526         {
       
   527         CalculateMaxSize();
       
   528         
       
   529         if ( iEngine )
       
   530             {
       
   531             TSize sourceSize( iSourceImage->Size() );
       
   532             TSize targetSize = TSize(
       
   533                     Min( sourceSize.iWidth, iMaxSize.iWidth - iFrame->FrameBorderSize().iWidth ),
       
   534                     Min( sourceSize.iHeight, iMaxSize.iHeight - iFrame->FrameBorderSize().iHeight ) );
       
   535             
       
   536             iBitmapControl->SetSize( TSize( 0, 0 ) );
       
   537             SetSize( targetSize );
       
   538             }
       
   539         }
       
   540     }
       
   541 
       
   542 // ---------------------------------------------------------
       
   543 // CMmsImageControl::CountComponentControls
       
   544 //
       
   545 // Return count of controls be included in this component.
       
   546 // ---------------------------------------------------------
       
   547 //
       
   548 TInt CMsgImageControl::CountComponentControls() const
       
   549     {    
       
   550     return 2;
       
   551     }
       
   552 
       
   553 // ---------------------------------------------------------
       
   554 // CMmsImageControl::ComponentControl
       
   555 //
       
   556 // Return pointer to component in question.
       
   557 // Note! Image and Icon cannot exist at a same time.
       
   558 // ---------------------------------------------------------
       
   559 //
       
   560 CCoeControl* CMsgImageControl::ComponentControl( TInt aIndex ) const
       
   561     {
       
   562     CCoeControl* result = NULL;
       
   563     switch ( aIndex )
       
   564         {
       
   565         case 0:
       
   566             {
       
   567             result = iFrame;                
       
   568             break;
       
   569             }
       
   570         case 1:
       
   571             {
       
   572             CCoeControl* visiblePlaceholder = VisiblePlaceholder();
       
   573             if ( visiblePlaceholder )
       
   574                 {
       
   575                 result = visiblePlaceholder;
       
   576                 }
       
   577             else
       
   578                 {
       
   579                 result = iBitmapControl;
       
   580                 }
       
   581             break;
       
   582             }
       
   583         default:
       
   584             {
       
   585             break;
       
   586             }
       
   587         }
       
   588         
       
   589     return result;
       
   590     }
       
   591 
       
   592 // ---------------------------------------------------------
       
   593 // CMsgImageControl::IsOffScreen
       
   594 //
       
   595 // Returns ETrue if image is off screen.
       
   596 // ---------------------------------------------------------
       
   597 //
       
   598 TBool CMsgImageControl::IsOffScreen() const
       
   599     {
       
   600     TRect rect( Position() + CalculateImagePosition(),
       
   601                 iDestinationBitmap->Bitmap().SizeInPixels() );
       
   602     
       
   603     TBool result( EFalse );
       
   604     
       
   605     if ( rect.iTl.iY < 0 || 
       
   606          rect.iBr.iY >  MsgEditorCommons::MsgMainPane().Height() )
       
   607         {
       
   608         result = ETrue;
       
   609         }
       
   610         
       
   611     return result;
       
   612     }
       
   613 
       
   614 
       
   615 // ---------------------------------------------------------
       
   616 // CMsgImageControl::ViewerBitmapChangedL
       
   617 //
       
   618 // Handle bitmap change notifications. State is changed accordingly
       
   619 // if this is the first frame. GIF animation is stopped if control
       
   620 // goes off screen and started again when it is fully visible and control
       
   621 // is on playing state. On editor mode animation is looped only once. 
       
   622 // Animation is also stopped if animation loop count is reached.
       
   623 // New animation loop is started after KAnimationDelayBetweenLoops
       
   624 // delay.
       
   625 // ---------------------------------------------------------
       
   626 //
       
   627 void CMsgImageControl::ViewerBitmapChangedL()
       
   628     {
       
   629     if ( iState == EMsgAsyncControlStateOpening )   
       
   630         {
       
   631         SetState( EMsgAsyncControlStateReady );        
       
   632         
       
   633         if ( iAnimationState == EAnimationPlaying )
       
   634             {
       
   635             SetState( EMsgAsyncControlStatePlaying );
       
   636             }
       
   637         }
       
   638         
       
   639     if ( iSourceImage->IsAnimation() )
       
   640         {
       
   641         switch ( iAnimationState )
       
   642             {
       
   643             case EAnimationPlaying:
       
   644                 {   
       
   645                 if ( IsOffScreen() )
       
   646                     {
       
   647                     // Stop the playback if animation is not fully visible
       
   648                     StopAnimation();
       
   649                     }
       
   650                 else if ( iEngine->AnimationFrame() == 
       
   651                           iSourceImage->AnimationFrameCount() - 1 )
       
   652                     {
       
   653                     // Last frame of the animation has been loaded.
       
   654                     iCurrentLoop++;
       
   655                     
       
   656                     if ( iCurrentLoop == iLoopCount )
       
   657                         {
       
   658                         // Maximum loop count reached. Do not stop yet as first
       
   659                         // frame is wanted to be displayed. Stopping is done on 
       
   660                         // EAnimationStopped state.
       
   661                         iAnimationState = EAnimationStopped;
       
   662                         }
       
   663                     else
       
   664                         {
       
   665                         iEngine->Stop();
       
   666                         
       
   667                         iLoopTimer->Cancel();
       
   668                         iLoopTimer->Start( KAnimationDelayBetweenLoops,
       
   669                                            KAnimationDelayBetweenLoops,
       
   670                                            TCallBack( DoStartLoop, this ) );
       
   671                         }
       
   672                     }
       
   673                 break;
       
   674                 }
       
   675             case EAnimationStopped:
       
   676                 {
       
   677                 if( iState == EMsgAsyncControlStatePlaying &&
       
   678                     !IsOffScreen() &&
       
   679                     iCurrentLoop != iLoopCount )
       
   680                     {
       
   681                     StartAnimation( 0 );
       
   682                     }
       
   683                 else
       
   684                     {
       
   685                     StopAnimation();
       
   686                     }
       
   687                 break;
       
   688                 }
       
   689             case EAnimationNotReady:
       
   690             default:
       
   691                 {
       
   692                 break;
       
   693                 }
       
   694             }
       
   695         }
       
   696     
       
   697     iBitmapControl->SetBitmap( iDestinationBitmap );
       
   698     
       
   699     TRect imageRect( Position() + CalculateImagePosition(),
       
   700                      iDestinationBitmap->Bitmap().SizeInPixels() );
       
   701     iBitmapControl->SetRect( imageRect );
       
   702     
       
   703     if( IsVisible() )
       
   704         {
       
   705         // Sometimes iDestinationBitmap is not ready when in SizeChanged()
       
   706         if ( iDestinationBitmap &&  
       
   707              iDestinationBitmap->IsCreated() )
       
   708             {
       
   709             iFrame->SetImageSize( imageRect.Size() );
       
   710             }  
       
   711 
       
   712         DrawNow();
       
   713         }
       
   714     }
       
   715 
       
   716 // ---------------------------------------------------------
       
   717 // CMsgImageControl::ViewerError
       
   718 //
       
   719 // Handles engine errors.
       
   720 // ---------------------------------------------------------
       
   721 //
       
   722 void CMsgImageControl::ViewerError( TInt aError )
       
   723     {
       
   724     MSGMEDIACONTROLLOGGER_WRITEF_ERROR_STATE( _L("CMsgImageControl::HandleCallback: **aError: %d, CurrentState: %S"),aError, iState);
       
   725     
       
   726     iError = aError;
       
   727             
       
   728     switch ( aError )
       
   729         {
       
   730         case KErrNone:
       
   731             {
       
   732             if ( iState == EMsgAsyncControlStateOpening )
       
   733                 {
       
   734                 // image shown in the viewer and image had rights
       
   735                 SetState( EMsgAsyncControlStateReady );
       
   736                 DoPlay( 0 );
       
   737                 }
       
   738             else if (  iState == EMsgAsyncControlStatePlaying )
       
   739                 {
       
   740                 SetState( EMsgAsyncControlStateReady );
       
   741                 DoPlay( 0 );
       
   742                 }
       
   743             break;
       
   744             }
       
   745         case DRMCommon::EGeneralError:
       
   746         case DRMCommon::EUnknownMIME:
       
   747         case DRMCommon::EVersionNotSupported:
       
   748         case DRMCommon::ESessionError:
       
   749         case DRMCommon::ENoRights:
       
   750         case DRMCommon::ERightsDBCorrupted:
       
   751         case DRMCommon::EUnsupported:
       
   752         case DRMCommon::ERightsExpired:
       
   753         case DRMCommon::EInvalidRights:
       
   754             {
       
   755             SetState( EMsgAsyncControlStateNoRights );
       
   756             break;
       
   757             }
       
   758         case KErrNoMemory:  // cannot recover
       
   759         default:
       
   760             {
       
   761             SetState( EMsgAsyncControlStateCorrupt );
       
   762             break;
       
   763             }
       
   764         }
       
   765     }
       
   766 
       
   767 // ---------------------------------------------------------
       
   768 // CMsgImageControl::CalculateImagePosition
       
   769 //
       
   770 // Calculates image position so that it is centered to 
       
   771 // control extent.
       
   772 // ---------------------------------------------------------
       
   773 //
       
   774 TPoint CMsgImageControl::CalculateImagePosition() const
       
   775     {
       
   776     TPoint result;
       
   777     
       
   778     TSize controlSize( Size() );
       
   779     TSize imageSize;
       
   780     
       
   781     if ( iEngine )
       
   782         {
       
   783         imageSize = iEngine->SourceSize();
       
   784         imageSize.iWidth *= iEngine->ZoomRatio();
       
   785         imageSize.iHeight *= iEngine->ZoomRatio();
       
   786         }
       
   787     else
       
   788         {
       
   789         // Engine has been unloaded. Use current bitmap control size
       
   790         // as imageSize.
       
   791         imageSize = iBitmapControl->Size();
       
   792         }
       
   793     
       
   794     result.iX = ( controlSize.iWidth - imageSize.iWidth ) / 2;
       
   795     result.iY = ( controlSize.iHeight - imageSize.iHeight ) / 2;
       
   796     
       
   797     if ( result.iX < 0 )
       
   798         {
       
   799         result.iX = 0;
       
   800         }
       
   801     
       
   802     if ( result.iY < 0 )
       
   803         {
       
   804         result.iY = 0;
       
   805         }
       
   806         
       
   807     return result;
       
   808     }
       
   809 
       
   810 // ---------------------------------------------------------
       
   811 // CMsgImageControl::CalculateControlSize
       
   812 //
       
   813 // Calculates the correct size for the image control.
       
   814 // ---------------------------------------------------------
       
   815 //
       
   816 TSize CMsgImageControl::CalculateControlSize( const TSize& aProposedSize ) const
       
   817     {
       
   818     TSize result( aProposedSize.iWidth, 0 );
       
   819     TSize bitmapSize = BitmapSize();
       
   820     
       
   821     if ( !bitmapSize.iHeight || !bitmapSize.iWidth )
       
   822         {
       
   823         result.iHeight = aProposedSize.iHeight;
       
   824         return result;
       
   825         }
       
   826     else if ( bitmapSize.iHeight < aProposedSize.iHeight )
       
   827         {
       
   828         result.iHeight = bitmapSize.iHeight;
       
   829         }
       
   830     else
       
   831         {
       
   832         result.iHeight = aProposedSize.iHeight;
       
   833         }
       
   834 
       
   835     TInt scaledHeight( 
       
   836         ( static_cast<TReal>( bitmapSize.iHeight ) /
       
   837           static_cast<TReal>( bitmapSize.iWidth ) ) *
       
   838           aProposedSize.iWidth );
       
   839     if ( scaledHeight < result.iHeight )
       
   840         {
       
   841         result.iHeight = scaledHeight;
       
   842         }
       
   843 
       
   844     // Height should be multiple of baseline.
       
   845     // Round up to the next full multiple if needed.
       
   846     TInt remainder = result.iHeight % iBaseLine;
       
   847     if ( remainder )
       
   848         {
       
   849         result.iHeight += ( iBaseLine - remainder );
       
   850         }
       
   851         
       
   852     if ( result.iHeight > iMaxSize.iHeight )
       
   853         {
       
   854         result.iHeight = iMaxSize.iHeight;
       
   855         }
       
   856 
       
   857     return result;
       
   858     }
       
   859 
       
   860 // ---------------------------------------------------------
       
   861 // CMsgImageControl::BitmapSize
       
   862 // 
       
   863 // Returns correct size for bitmap.
       
   864 // ---------------------------------------------------------
       
   865 //
       
   866 TSize CMsgImageControl::BitmapSize() const
       
   867     {
       
   868     TSize bitmapSize( 0, 0 );
       
   869     if ( !iIconControl->IsVisible() &&
       
   870          ( iBitmapControl->Size().iWidth == 0 ||
       
   871            iBitmapControl->Size().iHeight == 0 ) )
       
   872         {
       
   873         if ( iEngine )
       
   874             {
       
   875             bitmapSize = iEngine->SourceSize() ;
       
   876             bitmapSize.iWidth += iFrame->FrameBorderSize().iWidth;
       
   877             bitmapSize.iHeight += iFrame->FrameBorderSize().iHeight;
       
   878             }
       
   879         }
       
   880     else 
       
   881         {
       
   882         // Bitmap or icon visible. 
       
   883         bitmapSize = iFrame->FrameSize();
       
   884         }
       
   885 
       
   886     return bitmapSize;
       
   887     }
       
   888 
       
   889 // ---------------------------------------------------------
       
   890 // CMsgImageControl::DoPlay
       
   891 //
       
   892 // Starts animation if possible and sets control to correct state.
       
   893 // ---------------------------------------------------------
       
   894 //
       
   895 void CMsgImageControl::DoPlay( TInt aAnimationStartDelay )
       
   896     {
       
   897     StartAnimation( aAnimationStartDelay );
       
   898     
       
   899     if ( iState != EMsgAsyncControlStateOpening )
       
   900         {
       
   901         SetState( EMsgAsyncControlStatePlaying );
       
   902         }
       
   903     }
       
   904 
       
   905 // ---------------------------------------------------------
       
   906 // CMsgImageControl::DoPause
       
   907 //
       
   908 // Stops animation and sets control to correct state.
       
   909 // ---------------------------------------------------------
       
   910 //
       
   911 void CMsgImageControl::DoPause()
       
   912     {
       
   913     StopAnimation();
       
   914     
       
   915     SetState( EMsgAsyncControlStatePaused );
       
   916     }
       
   917 
       
   918 // ---------------------------------------------------------
       
   919 // CMsgImageControl::CalculateMaxSize
       
   920 // ---------------------------------------------------------
       
   921 //
       
   922 void CMsgImageControl::CalculateMaxSize()
       
   923     {
       
   924     TAknLayoutRect maxSizeLayout;
       
   925     maxSizeLayout.LayoutRect( MsgEditorCommons::MsgDataPane(),
       
   926                               AknLayoutScalable_Apps::msg_data_pane_g1().LayoutLine() );
       
   927     
       
   928     iMaxSize = maxSizeLayout.Rect().Size();
       
   929     
       
   930     // Make sure "iMaxSize" is multiple of "iBaseLine"
       
   931     iMaxSize.iHeight = iBaseLine * ( iMaxSize.iHeight / iBaseLine );
       
   932     }
       
   933 
       
   934 // ---------------------------------------------------------
       
   935 // CMsgImageControl::HitRegionContains
       
   936 // 
       
   937 // Note! CONE will do final verification if control is really hit so
       
   938 //       not need to do it here.
       
   939 // ---------------------------------------------------------
       
   940 //
       
   941 #ifdef RD_SCALABLE_UI_V2
       
   942 TBool CMsgImageControl::HitRegionContains( const TPoint& aPoint, 
       
   943                                      const CCoeControl& /*aControl*/ ) const
       
   944     {
       
   945     TBool result( EFalse );
       
   946     
       
   947     CCoeControl* visiblePlaceholder = VisiblePlaceholder();
       
   948     
       
   949     if ( visiblePlaceholder )
       
   950         {
       
   951         result = visiblePlaceholder->Rect().Contains( aPoint );
       
   952         }
       
   953     else
       
   954         {
       
   955         result = iBitmapControl->Rect().Contains( aPoint );
       
   956         }
       
   957         
       
   958     return result;
       
   959     }
       
   960 #else
       
   961 TBool CMsgImageControl::HitRegionContains( const TPoint& /*aPoint*/, 
       
   962                                      const CCoeControl& /*aControl*/ ) const
       
   963     {
       
   964     return EFalse;
       
   965     }
       
   966 #endif
       
   967 
       
   968 
       
   969 // ---------------------------------------------------------
       
   970 // CMsgImageControl::FrameSize
       
   971 //
       
   972 // Returns the framesize
       
   973 // ---------------------------------------------------------
       
   974 //
       
   975 EXPORT_C TSize CMsgImageControl::FrameSize()
       
   976     {
       
   977     return iFrame->FrameSize();
       
   978     }
       
   979 
       
   980 // ---------------------------------------------------------
       
   981 // CMsgImageControl::StartAnimation
       
   982 //
       
   983 // Starts animation if possible.
       
   984 // ---------------------------------------------------------
       
   985 //
       
   986 void CMsgImageControl::StartAnimation( TInt aAnimationStartDelay )
       
   987     {
       
   988     iLoopTimer->Cancel();
       
   989     
       
   990     if ( iEngine && 
       
   991          IsAnimation() && 
       
   992          !IsOffScreen() &&
       
   993          iLoopCount != iCurrentLoop )
       
   994         {    
       
   995         iAnimationState = EAnimationPlaying;
       
   996             
       
   997         if ( aAnimationStartDelay == 0 )
       
   998             {
       
   999             iEngine->Play();
       
  1000             }
       
  1001         else 
       
  1002             {
       
  1003             iLoopTimer->Start( aAnimationStartDelay,
       
  1004                                aAnimationStartDelay,
       
  1005                                TCallBack( DoStartLoop, this ) );
       
  1006             }
       
  1007         }
       
  1008     }
       
  1009 
       
  1010 // ---------------------------------------------------------
       
  1011 // CMsgImageControl::StopAnimation
       
  1012 //
       
  1013 // Stops animation if possible.
       
  1014 // ---------------------------------------------------------
       
  1015 //
       
  1016 void CMsgImageControl::StopAnimation()
       
  1017     {
       
  1018     iLoopTimer->Cancel();
       
  1019     
       
  1020     if ( iEngine &&  
       
  1021          IsAnimation() )
       
  1022         {
       
  1023         iEngine->Stop();
       
  1024         iAnimationState = EAnimationStopped;
       
  1025         }
       
  1026     }
       
  1027 
       
  1028 // ---------------------------------------------------------
       
  1029 // CMsgImageControl::PauseAnimation
       
  1030 //
       
  1031 // Pauses animation if possible.
       
  1032 // ---------------------------------------------------------
       
  1033 //
       
  1034 void CMsgImageControl::PauseAnimation()
       
  1035     {
       
  1036     StopAnimation();
       
  1037     iAnimationState = EAnimationPaused;
       
  1038     }
       
  1039 
       
  1040 // ---------------------------------------------------------
       
  1041 // CMsgImageControl::DoStartLoop
       
  1042 //
       
  1043 // Start new animation loop.
       
  1044 // ---------------------------------------------------------
       
  1045 //
       
  1046 TInt CMsgImageControl::DoStartLoop( TAny* aObject )
       
  1047     {
       
  1048     // cast, and call non-static function
       
  1049     CMsgImageControl* control = static_cast<CMsgImageControl*>( aObject );
       
  1050     control->StartLoop();
       
  1051     
       
  1052     return KErrNone;
       
  1053     }
       
  1054 
       
  1055 // ---------------------------------------------------------
       
  1056 // CMsgImageControl::StartLoop
       
  1057 //
       
  1058 // Start new animation loop.
       
  1059 // ---------------------------------------------------------
       
  1060 //
       
  1061 void CMsgImageControl::StartLoop()
       
  1062     {
       
  1063     if ( iAnimationState == EAnimationPlaying )
       
  1064         {
       
  1065         StartAnimation( 0 );
       
  1066         }
       
  1067     else
       
  1068         {
       
  1069         iLoopTimer->Cancel();
       
  1070         }
       
  1071     }
       
  1072 
       
  1073 //  End of File