messagingappbase/smartmessaging/gmsmodel/src/CGmsPictureControl.cpp
changeset 0 72b543305e3a
equal deleted inserted replaced
-1:000000000000 0:72b543305e3a
       
     1 /*
       
     2 * Copyright (c) 2002 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 *      GMS picture viewer control which is compatible with Editor Base.
       
    16 *      It is based very much on the CMmsImageControl.
       
    17 *  %version: bh1cfmsg#16 %
       
    18 *
       
    19 */
       
    20 
       
    21 
       
    22 
       
    23 // INCLUDE FILES
       
    24 #include "CGmsPictureControl.h"
       
    25 
       
    26 #include <coeutils.h>               // for ConeUtils::FileExists
       
    27 #include <AknUtils.h>
       
    28 #include <imageconversion.h>
       
    29 #include <aknlayoutscalable_apps.cdl.h>
       
    30 #include <MIHLScaler.h>
       
    31 
       
    32 // CONSTANTS
       
    33 
       
    34 // Mime type of the image, required by the decoder.
       
    35 _LIT8( KGmsOtaMimeType, "image/x-ota-bitmap");
       
    36 
       
    37 _LIT(KSmEditorGmsPic,"smeditor gmsPic");
       
    38 
       
    39 // ==========================================================
       
    40 
       
    41 /**
       
    42 * Helper class which allows CGmsPictureControl to receive a callback
       
    43 * to it's callback method when an asynchronous operation has finished.
       
    44 * CAsyncCallBack needed tweaking since it is ment for callback only, and
       
    45 * it completes the task immediately.
       
    46 */
       
    47 class CGmsAOCallBack: public CAsyncCallBack
       
    48     {
       
    49     public:
       
    50     
       
    51         CGmsAOCallBack( const TCallBack &aCallBack, TInt aPriority )
       
    52             : CAsyncCallBack( aCallBack, aPriority )
       
    53             {
       
    54             }
       
    55         
       
    56         void SetItActive() 
       
    57             {
       
    58             SetActive();
       
    59             }
       
    60         
       
    61     protected:         
       
    62        
       
    63         void RunL()
       
    64             {
       
    65             iCallBack.CallBack();
       
    66             }
       
    67     };
       
    68 
       
    69 
       
    70 //  MEMBER FUNCTIONS
       
    71 
       
    72 EXPORT_C CGmsPictureControl* CGmsPictureControl::NewL(
       
    73     const CCoeControl* aParent)
       
    74 {
       
    75     CGmsPictureControl* self = new(ELeave) CGmsPictureControl();
       
    76 
       
    77     CleanupStack::PushL(self);
       
    78     self->ConstructL(aParent);
       
    79     CleanupStack::Pop(self);
       
    80 
       
    81     return self;
       
    82 }
       
    83 
       
    84 EXPORT_C CGmsPictureControl::~CGmsPictureControl()
       
    85 {
       
    86     delete iBitmap;
       
    87     iBitmap = NULL;
       
    88     delete iScaledBitmap;
       
    89     iScaledBitmap = NULL;    
       
    90         
       
    91     delete iConverter;
       
    92     iConverter = NULL;
       
    93     delete iScaler;
       
    94     delete iConversionAO;
       
    95     delete iScalingAO;    
       
    96     iFs.Close();
       
    97 }
       
    98 
       
    99 EXPORT_C void CGmsPictureControl::LoadImageL(
       
   100     const TFileName& aImageFile,
       
   101     TUint            aMaxHeight /* = 0 */)
       
   102 {
       
   103     __ASSERT_DEBUG((aImageFile.Length() > 0), Panic( ENoImageFile ) );
       
   104 
       
   105     if (!ConeUtils::FileExists(aImageFile))
       
   106     {
       
   107         User::Leave(KErrNotFound);
       
   108     }
       
   109     if (aMaxHeight)
       
   110     {
       
   111         iMaxHeight = aMaxHeight;
       
   112     }
       
   113     
       
   114     Reset();
       
   115         
       
   116     iConverter = CImageDecoder::FileNewL( iFs, aImageFile, KGmsOtaMimeType );
       
   117     __ASSERT_ALWAYS( iConverter->FrameCount() == 1, Panic(EBadImageContent) );
       
   118     TFrameInfo frameInfo = iConverter->FrameInfo( 0 );
       
   119     iBitmap = new( ELeave ) CFbsBitmap;
       
   120     User::LeaveIfError( iBitmap->Create( frameInfo.iOverallSizeInPixels,
       
   121                                          EGray2 ) );
       
   122                                              
       
   123     iConverter->Convert( &(iConversionAO->iStatus), *iBitmap );
       
   124 	iConversionAO->SetItActive();
       
   125 }
       
   126 
       
   127 EXPORT_C TSize CGmsPictureControl::OriginalImageResolution() const
       
   128 {
       
   129     TSize size(0,0);
       
   130     if ( iConverter )
       
   131         {
       
   132         size = iConverter->FrameInfo( 0 ).iOverallSizeInPixels;
       
   133         }
       
   134     return size;
       
   135 }
       
   136 
       
   137 TRect CGmsPictureControl::CurrentLineRect()
       
   138 {
       
   139     return Rect();
       
   140 }
       
   141 
       
   142 void CGmsPictureControl::SetAndGetSizeL(TSize& aSize)
       
   143 {
       
   144     // Size proposed in aSize parameter is used, only height is
       
   145     // proposed by this control.
       
   146     
       
   147     if (AknLayoutUtils::ScalableLayoutInterfaceAvailable())
       
   148     {        
       
   149         TAknWindowComponentLayout layout =
       
   150             AknLayoutScalable_Apps::mce_image_pane_g3();
       
   151         TAknLayoutRect layoutRect;
       
   152     	layoutRect.LayoutRect( Rect(), layout.LayoutLine() );
       
   153     	aSize.iHeight = layoutRect.Rect().Height();
       
   154     	
       
   155         // Adjust max height if needed
       
   156         if ( iMaxHeight > 0 && (TUint)aSize.iHeight > iMaxHeight )
       
   157         {
       
   158             aSize.iHeight = iMaxHeight;
       
   159         }    	
       
   160     }
       
   161     
       
   162     else
       
   163     { // use old sizing functionality if scalable IF isn't available:
       
   164         aSize = CalculateControlSize(aSize);
       
   165     }
       
   166 
       
   167     SetSizeWithoutNotification(aSize);
       
   168 }
       
   169 
       
   170 /**
       
   171 * This internal function is the old version and is used ONLY if scalable
       
   172 * layout interface is NOT available. This should be removed when it is always
       
   173 * available.
       
   174 */
       
   175 const TInt KGmsImageHeightMax = 58;
       
   176 const TInt KBaseLineDelta = 17;
       
   177 
       
   178 TSize CGmsPictureControl::CalculateControlSize(TSize& aProposedSize)
       
   179     {
       
   180     // These lines below, although they look a bit strange, are required to
       
   181     // conform with old sizing functionality when scalable layout IF is
       
   182     // not available:
       
   183     if ( iMaxHeight == 0 )
       
   184         { // max height hasn't been set by the client:
       
   185         iMaxHeight = KGmsImageHeightMax;
       
   186         }
       
   187     if ( (TUint)aProposedSize.iHeight > iMaxHeight )
       
   188         { // proposed size is greater than max size -> adjust:
       
   189         aProposedSize.iHeight = iMaxHeight;
       
   190         }    
       
   191     
       
   192     TSize trgSize(aProposedSize.iWidth, 0);
       
   193     
       
   194     if (!iConverter)
       
   195         {
       
   196         return trgSize;
       
   197         }
       
   198     
       
   199     TSize bmpSize = OriginalImageResolution();
       
   200     
       
   201     bmpSize.SetSize(bmpSize.iWidth*2, bmpSize.iHeight*2);
       
   202     
       
   203     if (bmpSize.iHeight < aProposedSize.iHeight)
       
   204         {
       
   205         trgSize.iHeight = bmpSize.iHeight;
       
   206         }
       
   207     else
       
   208         {
       
   209         trgSize.iHeight = aProposedSize.iHeight;
       
   210         }
       
   211     
       
   212     // For "wide" images height may be too big - check aspect ratio
       
   213     TReal widthRatio  = (TReal)bmpSize.iWidth  / (TReal)trgSize.iWidth;
       
   214     TReal heightRatio = (TReal)bmpSize.iHeight / (TReal)trgSize.iHeight;
       
   215     
       
   216     if (widthRatio > heightRatio)
       
   217         {
       
   218         // image must be scaled more in vertical size
       
   219         trgSize.iHeight = (TInt)(bmpSize.iHeight / widthRatio);
       
   220         }
       
   221     
       
   222     if (trgSize.iHeight%KBaseLineDelta)
       
   223         {
       
   224         trgSize.iHeight = trgSize.iHeight-trgSize.iHeight%KBaseLineDelta+KBaseLineDelta;
       
   225         }    
       
   226     return trgSize;
       
   227     }
       
   228 
       
   229 void CGmsPictureControl::ClipboardL(TMsgClipboardFunc /*aFunc*/)
       
   230 {
       
   231     User::Leave(KErrNotSupported);  // Image control does not support clipboard
       
   232 }
       
   233 
       
   234 void CGmsPictureControl::EditL(TMsgEditFunc /*aFunc*/)
       
   235 {
       
   236     User::Leave(KErrNotSupported);  // Image control is not editable
       
   237 }
       
   238 
       
   239 TBool CGmsPictureControl::IsFocusChangePossible(TMsgFocusDirection /*aDirection*/) const
       
   240 {
       
   241     return ETrue;
       
   242 }
       
   243 
       
   244 TBool CGmsPictureControl::IsCursorLocation(TMsgCursorLocation /*aLocation*/) const
       
   245 {
       
   246     return ETrue;
       
   247 }
       
   248 
       
   249 TUint32 CGmsPictureControl::EditPermission() const
       
   250 {
       
   251     return EMsgEditNone;
       
   252 }
       
   253 
       
   254 void CGmsPictureControl::Reset()
       
   255 {
       
   256     delete iBitmap;
       
   257     iBitmap = NULL;
       
   258     delete iScaledBitmap;
       
   259     iScaledBitmap = NULL;    
       
   260         
       
   261     delete iConverter;
       
   262     iConverter = NULL;
       
   263             
       
   264     SetModified( ETrue );    
       
   265 }
       
   266 
       
   267 void CGmsPictureControl::NotifyViewEvent(TMsgViewEvent /*aEvent*/,
       
   268     TInt /*aParam*/)
       
   269 {
       
   270 }
       
   271 
       
   272 TInt CGmsPictureControl::ConversionReady( TAny* aPtr )
       
   273 {
       
   274 	__ASSERT_ALWAYS(aPtr, User::Panic(KSmEditorGmsPic, ENullPtr) );
       
   275     static_cast<CGmsPictureControl*>( aPtr )->DoConversionReady();
       
   276     return 0;
       
   277 }    
       
   278 
       
   279 TInt CGmsPictureControl::ScalingReady( TAny* aPtr )
       
   280 {
       
   281 	__ASSERT_ALWAYS(aPtr, User::Panic(KSmEditorGmsPic, ENullPtr) );
       
   282     static_cast<CGmsPictureControl*>( aPtr )->DoScalingReady();
       
   283     return 0;
       
   284 }    
       
   285 
       
   286 void CGmsPictureControl::PrepareForReadOnly(TBool /*aReadOnly*/)
       
   287 {
       
   288 }
       
   289 
       
   290 TInt CGmsPictureControl::CountComponentControls() const
       
   291     {
       
   292     // This method is required by the base class
       
   293     return 0;
       
   294     }
       
   295 
       
   296 CCoeControl* CGmsPictureControl::ComponentControl(TInt /*aIndex*/) const
       
   297     {
       
   298     // This method is required by the base class
       
   299     return NULL;
       
   300     }
       
   301     
       
   302 void CGmsPictureControl::FocusChanged( TDrawNow /*aDrawNow*/ )
       
   303     {
       
   304     // This method is required by the base class
       
   305     }
       
   306 
       
   307 void CGmsPictureControl::SizeChanged()
       
   308 {
       
   309     iBitmapRect = Rect();
       
   310     
       
   311     if (AknLayoutUtils::ScalableLayoutInterfaceAvailable())
       
   312     {        
       
   313         TAknWindowComponentLayout layout =
       
   314             AknLayoutScalable_Apps::mce_image_pane_g3();
       
   315         TAknLayoutRect layoutRect;
       
   316     	layoutRect.LayoutRect( Rect(), layout.LayoutLine() );
       
   317     	iBitmapRect = layoutRect.Rect();
       
   318     
       
   319         // Adjust max height if needed, this is not the usual case but
       
   320         // implemented here just because of supporting the existing
       
   321         // public LoadImageL() method. Usually the size of imageRect
       
   322         // should be fully determined by avkon layout!
       
   323         if ( iMaxHeight > 0 && (TUint)iBitmapRect.Size().iHeight > iMaxHeight )
       
   324         {
       
   325             iBitmapRect.SetHeight(iMaxHeight);
       
   326         }
       
   327         TInt yAxisOffset = Rect().iTl.iY - iBitmapRect.iTl.iY;
       
   328         iBitmapRect.Move(0,yAxisOffset);
       
   329         
       
   330         // If leave occurs then scaling is not performed
       
   331         TRAP_IGNORE( ScaleIfPossibleL( iBitmapRect.Size() ) );
       
   332     }
       
   333     
       
   334     else
       
   335     { // Use old sizing functionality if scalable IF isn't available:
       
   336       // Note that usage of image size and image rect is not identical
       
   337       // to scalable version!
       
   338         TSize imageSize(CalculateImageSize());
       
   339         
       
   340         // If leave occurs then scaling is not performed
       
   341         TRAP_IGNORE( ScaleIfPossibleL( imageSize ) );                
       
   342     }
       
   343 }
       
   344 
       
   345 void CGmsPictureControl::Draw(const TRect& /*aRect*/) const
       
   346 {   
       
   347     // Ensure that scaled bitmap exists and that no scaling is
       
   348     // currently ongoing.    
       
   349     if ( iScaledBitmap &&
       
   350          iScaledBitmap->Handle() &&
       
   351          ! iScalingAO->IsActive() )
       
   352     {            
       
   353         CWindowGc& gc = SystemGc();
       
   354 		gc.DrawBitmap(iBitmapRect,iScaledBitmap);
       
   355     }
       
   356 }
       
   357 
       
   358 /**
       
   359 * This internal function is the old version and is used ONLY if scalable
       
   360 * layout interface is NOT available. This should be removed when it is always
       
   361 * available.
       
   362 */
       
   363 TSize CGmsPictureControl::CalculateImageSize() const
       
   364 {
       
   365     TSize trgSize(0,0);
       
   366 
       
   367     TSize bmpSize = OriginalImageResolution();
       
   368     bmpSize.SetSize(bmpSize.iWidth*2, bmpSize.iHeight*2);
       
   369 
       
   370     TRect rect(Rect());
       
   371 
       
   372     // Width is basically static during the session, but it's always
       
   373     // calculated anyway.
       
   374     if (bmpSize.iWidth < rect.Width())
       
   375     {
       
   376         // "narrow" image - request only what is needed.
       
   377         trgSize.iWidth = bmpSize.iWidth;
       
   378     }
       
   379     else
       
   380     {
       
   381         // "wide" image - request all we can get.
       
   382         trgSize.iWidth = rect.Width();
       
   383     }
       
   384 
       
   385     // Height is dynamic, i.e. changes when moving up&down in the message.
       
   386     // Request maximum height possible.
       
   387     // Note: Either max size allowed by spec or the size of the image itself
       
   388     // is considered here, i.e. not the given rect.
       
   389     if ( iMaxHeight > 0 && (TUint)bmpSize.iHeight > iMaxHeight )
       
   390     {
       
   391         trgSize.iHeight = iMaxHeight;
       
   392     }
       
   393     else
       
   394     {
       
   395         trgSize.iHeight = bmpSize.iHeight;
       
   396     }
       
   397     return trgSize;
       
   398 }
       
   399 
       
   400 TBool CGmsPictureControl::ScaleIfPossibleL( TSize aSize )
       
   401 {
       
   402 	if ( !iBitmap )    	     
       
   403     { 
       
   404         // Image hasn't been loaded, cannot scale
       
   405         return EFalse;
       
   406     }
       
   407 	else if ( iConversionAO->IsActive() )
       
   408     { 
       
   409         // Conversion is ongoing, but not ready yet,
       
   410         // image will be scaled after conversion finishes.
       
   411         return EFalse;
       
   412     }
       
   413     
       
   414     else
       
   415     {
       
   416         if ( !iScalingAO->IsActive() )
       
   417         {
       
   418         	// Scaling is possible, it is done asynchronously
       
   419         	delete iScaledBitmap;
       
   420         	iScaledBitmap = NULL;        
       
   421         	iScaledBitmap = new( ELeave ) CFbsBitmap;
       
   422                     
       
   423 	        User::LeaveIfError( iScaler->Scale( iScalingAO->iStatus, 
       
   424     	                                        *iBitmap, 
       
   425         	                                    TRect(iBitmap->SizeInPixels()),
       
   426             	                                *iScaledBitmap,
       
   427                 	                            TRect(aSize) ) );
       
   428         	iScalingAO->SetItActive();            
       
   429         	return ETrue;
       
   430         }
       
   431     }
       
   432     return EFalse;            
       
   433 }
       
   434 
       
   435 void CGmsPictureControl::DoConversionReady()
       
   436 {    
       
   437     __ASSERT_DEBUG( iConversionAO->iStatus == KErrNone,
       
   438                     Panic(EConversionError) );
       
   439                     
       
   440     if ( iConversionAO->iStatus == KErrNone )
       
   441     	{        
       
   442         SetModified( ETrue );
       
   443         // We want to scale the image now:       
       
   444         SetRect( Rect() );
       
   445         
       
   446     	//we must delete the converter here because it is holding the
       
   447     	//converted imagefile so that it cant be replaced when FORWARD:ing
       
   448     	delete iConverter;
       
   449     	iConverter = NULL;
       
   450     	}
       
   451 }
       
   452 
       
   453 void CGmsPictureControl::DoScalingReady()
       
   454 {    
       
   455     __ASSERT_DEBUG( iScalingAO->iStatus == KErrNone,
       
   456                     Panic(EScalingError) );
       
   457                     
       
   458     if ( iScalingAO->iStatus == KErrNone )
       
   459     {        
       
   460         SetModified( ETrue );
       
   461         // We want to draw the image now:       
       
   462         DrawNow();
       
   463     }
       
   464 }
       
   465 
       
   466 
       
   467 void CGmsPictureControl::Panic(TGmsPicControlPanic aCode)
       
   468     {
       
   469     User::Panic(KSmEditorGmsPic, aCode);
       
   470     }
       
   471 
       
   472 void CGmsPictureControl::ConstructL(const CCoeControl* aParent)
       
   473 {
       
   474     __ASSERT_DEBUG( aParent, Panic(ENoParent) );
       
   475     
       
   476     User::LeaveIfError( iFs.Connect() );
       
   477 
       
   478     iControlType = EMsgImageControl;    
       
   479 
       
   480     SetContainerWindowL(*aParent);
       
   481     
       
   482     TRect rect(aParent->Rect());
       
   483     if (rect.Height() == 0 || rect.Width() == 0)
       
   484     {
       
   485         // We have been called before view construction.
       
   486         // Set rect to screen size.
       
   487         rect.SetRect (
       
   488             TPoint(0,0),
       
   489             iEikonEnv->EikAppUi()->ClientRect().Size());
       
   490     }
       
   491     SetPosition(rect.iTl);
       
   492     SetSizeWithoutNotification(rect.Size());
       
   493     
       
   494     iConversionAO = new( ELeave ) CGmsAOCallBack(
       
   495         TCallBack( ConversionReady, this ), CActive::EPriorityStandard );    
       
   496     iScaler = IHLScaler::CreateL();
       
   497     iScalingAO = new( ELeave ) CGmsAOCallBack(
       
   498         TCallBack( ScalingReady, this ), CActive::EPriorityStandard );    
       
   499 }
       
   500 
       
   501 CGmsPictureControl::CGmsPictureControl()
       
   502 {
       
   503     // By default iMaxHeight is not used:
       
   504     iMaxHeight = 0;
       
   505 }
       
   506 
       
   507 //  End of File