imstutils/imconversationview/imcvuiapp/src/cimcvappsmileyutil.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Tue, 02 Feb 2010 10:12:18 +0200
changeset 0 5e5d6b214f4f
permissions -rw-r--r--
Revision: 201003 Kit: 201005

/*
* Copyright (c) 2007-2008 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:  Utility for selecting smile icon and converting
*                between smile id and smile string.
*
*/

// INCLUDE FILES
#include 	"cimcvappsmileyutil.h"
#include 	"cimcvapppicture.h"
#include    "cimcvappsmileyinformation.h"

#include	<PUAcodes.hrh>

#include	<gulicon.h>
#include 	<txtrich.h>
#include 	<gdi.h>
#include    <eikrted.h>
#include	<frmtlay.h>
#include 	"imcvlogger.h"
#include    "imcvuiliterals.h"
#include    "cimcvengine.h"
//CONSTANT
const TInt KChatSmileyLength( 3 );
_LIT(KSpace, " ");

// ================= MEMBER FUNCTIONS =======================

// -----------------------------------------------------------------------------
// CIMCVAppSmileyUtil::NewL
// Two-phased constructor.
// -----------------------------------------------------------------------------
//
CIMCVAppSmileyUtil* CIMCVAppSmileyUtil::NewL(
							 MIMCVUiAppSkinVariant& aSkinVariant, 
                             MIMCVAppUi& aAppUi, TMessageExtensionTypes aType,
                             CIMCVEngine& aServiceEngine)
    {
    CIMCVAppSmileyUtil* self = new (ELeave) CIMCVAppSmileyUtil( aType );
    CleanupStack::PushL( self );
    self->ConstructL( aSkinVariant, aAppUi,aServiceEngine );
    CleanupStack::Pop();
    return self;
    }

// -----------------------------------------------------------------------------
// CIMCVAppSmileyUtil::~CIMCVAppSmileyUtil
// Destructor
// -----------------------------------------------------------------------------
//
CIMCVAppSmileyUtil::~CIMCVAppSmileyUtil()
    {
    iConvertArray.ResetAndDestroy();
	delete iSmileUtil;
    }

// -----------------------------------------------------------------------------
// CIMCVAppSmileyUtil::CIMCVAppSmileyUtil
// C++ constructor can NOT contain any code, that
// might leave.
// -----------------------------------------------------------------------------
//
CIMCVAppSmileyUtil::CIMCVAppSmileyUtil( TMessageExtensionTypes aType ) 
: MIMCVAppMessageExtension( aType)
    {
    }

// -----------------------------------------------------------------------------
// CIMCVAppSmileyUtil::ConstructL
// ConstructL
// -----------------------------------------------------------------------------
//
void CIMCVAppSmileyUtil::ConstructL(
							 MIMCVUiAppSkinVariant& aSkinVariant, 
                             MIMCVAppUi& aAppUi,
							 CIMCVEngine& aServiceEngine )
    {
    iServiceId = aServiceEngine.GetServiceId();
	iSmileUtil = CIMCVAppSmileIconUtility::NewL(aSkinVariant, aAppUi, aServiceEngine );
    }


// ---------------------------------------------------------
// CIMCVAppSmileyUtil::InsertExtensionL
// (other items were commented in a header).
// ---------------------------------------------------------
//
void CIMCVAppSmileyUtil::InsertExtensionL( CEikRichTextEditor& aEditor,
                                      TBool& aCancelled, TSize asize )
    {
    IM_CV_LOGS(TXT("CIMCVAppSmileyUtil::InsertExtensionL() start") );
	TInt bitmapId( KErrNone );
	TInt retVal = iSmileUtil->LaunchSmileIconDialogL( bitmapId );	
	iSmileUtil->ResizeIcons(asize);		
	if( retVal )
		{
		// check if there is room for icon, if not return
		if( ( aEditor.MaxLength() - aEditor.TextLength() ) < KChatSmileyLength )
			{
			return;
			}		
        //we don't own this
		const TDesC& iconString = iSmileUtil->GetSmileString(bitmapId);		
        TInt cursorPos = aEditor.CursorPos();        
        HBufC* msgBuf = aEditor.GetTextInHBufL();
		CleanupStack::PushL( msgBuf );
		if(msgBuf)
		    {
		    TPtr msgPtr( msgBuf->Des() );		    
		    aEditor.RichText()->InsertL(cursorPos,iconString);
		    cursorPos = aEditor.TextLength();
		    aEditor.SetCursorPosL( cursorPos, EFalse);		    
		    }
		else
		    {
		    aEditor.RichText()->InsertL(cursorPos,iconString);
		    cursorPos = aEditor.TextLength(); 
		    aEditor.SetCursorPosL( cursorPos, EFalse);		  
		    }
		CleanupStack::PopAndDestroy( msgBuf ); // msgBuf		
		if( &aEditor != iEditor )
			{
			iEditor = &aEditor;
			iCurrentCount = 1;
			}
		else
			{
			++iCurrentCount;
			}
			
		aCancelled = EFalse;
		}
    else
        {
        // apply formatting even in case of cancel, as the sizes of icons would have changed and when
		// shifted from portrait to landscape and vice versa, alignment differs.
        TCharFormat charFormat;
        TCharFormatMask charFormatMask;
		
		IM_CV_LOGS(TXT("CIMCVAppSmileyUtil::InsertExtensionL() before applying format") );
        charFormat.iFontPresentation.iPictureAlignment = TFontPresentation::EAlignCentered;
        charFormatMask.SetAttrib( EAttFontPictureAlignment );
        aEditor.RichText()->ApplyCharFormatL( charFormat, charFormatMask, 0,
                                              aEditor.TextLength() );
		IM_CV_LOGS(TXT("CIMCVAppSmileyUtil::InsertExtensionL() after applying format") );
		aEditor.HandleTextChangedL ();
        aCancelled = ETrue;
        }
    IM_CV_LOGS(TXT("CIMCVAppSmileyUtil::InsertExtensionL() end") );
	}

// ---------------------------------------------------------
// CIMCVAppSmileyUtil::ExtensionToStringL
// (other items were commented in a header).
// ---------------------------------------------------------
//
void CIMCVAppSmileyUtil::ExtensionToStringL( CEikRichTextEditor& anEditor, TDes& aDes )
	{
	IM_CV_LOGS(TXT("CIMCVAppSmileyUtil::ExtensionToStringL() start") );
	RArray<TInt> iconIndArray;
	CleanupClosePushL( iconIndArray );
	
	CPicture* editorPic;
	TInt i;
	TInt limit( 0 );

	// for loop gets icon positions to array
    TInt length = aDes.Length();
	for( i = 0; i < length; ++i )
		{
		if( aDes[ i ] ==  CEditableText::EPictureCharacter )
			{
			User::LeaveIfError( iconIndArray.Append( i ) );
			}
		}

	// real count of pictures
	TInt count = anEditor.RichText()->PictureCount();
	TInt indCount = iconIndArray.Count();
	
	if( &anEditor != iEditor )
		{
        Reset();
		}

	// whisper message
	if( indCount > iCurrentCount )
		{
		limit = indCount - iCurrentCount;
		}

    if( indCount > 0 )
        {
        for( i = count; i > limit; --i )
    		{
    		editorPic = anEditor.RichText()->PictureHandleL(
    							iconIndArray[ i - 1 ], MLayDoc::EForceLoadTrue );
    		if ( !editorPic )
    			{
    			User::Leave( KErrBadHandle );
    			}

    		CIMCVAppPicture* icon = static_cast<CIMCVAppPicture*> ( editorPic );

            TInt oldLen = aDes.Length();
            //delete padding char
		    aDes.Delete( iconIndArray[ i - 1 ], 1 ); // 1 = one char
		    //insert string smiley		    
		    aDes.Insert( iconIndArray[ i - 1 ],
		                 iSmileUtil->GetSmileString( icon->Index() ) );
    		}
        }
    CleanupStack::PopAndDestroy(); // iconIndArray.Close()
    IM_CV_LOGS(TXT("CIMCVAppSmileyUtil::ExtensionToStringL() end") );
	}

// -----------------------------------------------------------------------------
// CIMCVAppSmileyUtil::ConvertSelectionToExtensionL
// Convert selection smileys to icons.
// -----------------------------------------------------------------------------
//
void CIMCVAppSmileyUtil::ConvertSelectionToExtensionL( CEikRichTextEditor& aEditor )
    {
    IM_CV_LOGS(TXT("CIMCVAppSmileyUtil::ConvertSelectionToExtensionL() start") );
    TInt selectAdd( 0 );

    // for loop gets icon positions to array
    TInt start = aEditor.Selection().LowerPos();
    TInt end = aEditor.Selection().HigherPos();

    // Clear convert array, it has something, but its not correct
    iConvertArray.ResetAndDestroy();
	
	const TInt KMaxLength( KDefaultMsgLength );
	HBufC* des = HBufC::NewLC( KMaxLength );
	TPtr desText( des->Des() );

    aEditor.GetText( desText );
    TInt txtLen = desText.Length();
    if ( txtLen < end )
        {
        end = txtLen;
        }
    desText.Delete( end, txtLen - end );
    desText.Delete( 0, start );
   
    iSmileUtil->SearchSmilesL( desText, iConvertArray, NULL, start );

	#ifdef _DEBUG
		TPtrC myDebug( aEditor.Text()->Read( 0 ) ); 
	#endif

    for( TInt a( iConvertArray.Count() - 1 ); a >= 0; --a )
        {
        if( iConvertArray[ a ]->Position() >= start && iConvertArray[ a ]->Position() < end ) // do we convert or not
            {                
            TPictureHeader picHeader;
            // Insert icon in place

		    //we don't own this
		    CGulIcon* icon = const_cast<CGulIcon*>(
		        iSmileUtil->GetSmileIcon( iConvertArray[ a ]->Index() ) );

		    //create CIMCVAppPicture from selected icon
		    CIMCVAppPicture* smileIcon = new ( ELeave ) CIMCVAppPicture(
									    *CCoeEnv::Static()->SystemGc().Device(),
									    icon, 
									    iConvertArray[ a ]->Index() );

		    picHeader.iPicture = TSwizzle<CPicture>( smileIcon );
            aEditor.Text()->DeleteL( iConvertArray[ a ]->Position(), 
            							iConvertArray[ a ]->SmileyString().Length() ); 

	#ifdef _DEBUG
			myDebug.Set( aEditor.Text()->Read( 0 ) );
			
	#endif

			aEditor.RichText()->InsertL( iConvertArray[ a ]->Position(), picHeader );
			
	#ifdef _DEBUG
			myDebug.Set( aEditor.Text()->Read( 0 ) );
			
	#endif

            selectAdd -= iConvertArray[ a ]->SmileyString().Length() - 1;

		    // icon is inserted, and it should be converted to text
		    // before sending, so it needs extra chars according to smiley string length
		    TInt textLimit =
		        aEditor.MaxLength() - iConvertArray[ a ]->SmileyString().Length();
            TInt currentlength = aEditor.Text()->DocumentLength();            
		    aEditor.SetTextLimit( Max( textLimit, currentlength ) );
            
		    if( &aEditor != iEditor )
			    {
			    iEditor = &aEditor;
			    iCurrentCount = 1;
			    }
		    else
			    {
			    ++iCurrentCount;
			    }
            }
        }
    
    // Apply formatting
    TInt selectionLen = end + selectAdd - start;
    TCharFormat charFormat;
	TCharFormatMask charFormatMask;
	charFormat.iFontPresentation.iPictureAlignment = 
	    TFontPresentation::EAlignCentered;
	charFormatMask.SetAttrib( EAttFontPictureAlignment );
	aEditor.RichText()->ApplyCharFormatL( charFormat, charFormatMask,
	                                      start, selectionLen );
    
    // Handle changes in editor
    aEditor.TextView()->HandleGlobalChangeL();
    
    // Set selection to correct after adding images
    aEditor.SetSelectionL( start, end + selectAdd );

    // Clear convert array
    iConvertArray.ResetAndDestroy();
    
    CleanupStack::PopAndDestroy( des );
    IM_CV_LOGS(TXT("CIMCVAppSmileyUtil::ConvertSelectionToExtensionL() end") );
    }
    
// -----------------------------------------------------------------------------
// CIMCVAppSmileyUtil::ConvertSelectionToExtensionL
// Convert selection smileys to icons.
// -----------------------------------------------------------------------------
//
void CIMCVAppSmileyUtil::ConvertSelectionToExtensionL( CRichText& aRichText, 
														TCursorSelection& aSelection )
    {
    IM_CV_LOGS(TXT("CIMCVAppSmileyUtil::ConvertSelectionToExtensionL() start") );
    TInt start( aSelection.LowerPos() );
    TInt length( aSelection.Length() );

    // Clear convert array and fetch the text
    iConvertArray.ResetAndDestroy();	
    HBufC* text = HBufC::NewMaxLC( aRichText.DocumentLength() );
    TPtr desText( text->Des() );	   
    aRichText.Extract( desText, start, length );
    
    iSmileUtil->SearchSmilesL( desText, iConvertArray );

    for( TInt a( iConvertArray.Count() - 1 ); a >= 0; --a )
        {
        TPictureHeader picHeader;
        // Insert icon in place
        //we don't own this
	    CGulIcon* icon = const_cast<CGulIcon*>( 
	        iSmileUtil->GetSmileIcon( iConvertArray[ a ]->Index()) );			

	    //create CIMCVAppPicture from selected icon
	    CIMCVAppPicture* smileIcon = new ( ELeave ) CIMCVAppPicture(
								    *CCoeEnv::Static()->SystemGc().Device(),
								    icon, 
								    iConvertArray[ a ]->Index());

	    picHeader.iPicture = TSwizzle<CPicture>( smileIcon );
        aRichText.DeleteL( iConvertArray[ a ]->Position() + start,
                           iConvertArray[ a ]->SmileyString().Length() );

		aRichText.InsertL( iConvertArray[ a ]->Position() + start, picHeader );
        }

    // clean up
    iConvertArray.ResetAndDestroy();
    CleanupStack::PopAndDestroy( text );    
    IM_CV_LOGS(TXT("CIMCVAppSmileyUtil::ConvertSelectionToExtensionL() end") );
    }

// -----------------------------------------------------------------------------
// CIMCVAppSmileyUtil::ConvertSelectionToStringL
// Convert selection smileys to strings
// -----------------------------------------------------------------------------
//
void CIMCVAppSmileyUtil::ConvertSelectionToStringL( CEikRichTextEditor& aEditor, TBool aPreserve )
    {
    IM_CV_LOGS(TXT("CIMCVAppSmileyUtil::ConvertSelectionToStringL() start") );
    // Clear convert array
    iConvertArray.ResetAndDestroy();

    HBufC* text = HBufC::NewMaxLC( KDefaultMsgLength );
    TPtr textCopy( text->Des() );
    aEditor.GetText( textCopy );

	// for loop gets icon positions to array
    TInt start = 0;
    TInt end = aEditor.Text()->DocumentLength();
    //aEditor.Selection().HigherPos();
	
	TInt i;
    for( i = start; i < end; ++i )
		{
		if( textCopy[ i ] ==  CEditableText::EPictureCharacter )
			{
            CIMCVAppSmileyInformation* smileInfo = CIMCVAppSmileyInformation::NewL(); 
            CleanupStack::PushL( smileInfo );
            smileInfo->SetPosition( i );
            smileInfo->SetIcon( ETrue );
			User::LeaveIfError( iConvertArray.Append( smileInfo ) );
			CleanupStack::Pop( smileInfo );
			}
        }

    TInt count = iConvertArray.Count();
	for( i = count - 1; i >= 0; --i )
		{
		CPicture* editorPic = aEditor.RichText()->PictureHandleL( 
            iConvertArray[ i ]->Position(), MLayDoc::EForceLoadTrue );
        
		if ( !editorPic )
			{
			User::Leave( KErrBadHandle );
			}

		CIMCVAppPicture* icon = static_cast<CIMCVAppPicture*> ( editorPic );

        const TDesC& iconString = iSmileUtil->GetSmileString( icon->Index() );
        iConvertArray[ i ]->SetSmileyStringL( iconString );
        iConvertArray[ i ]->SetIndex( icon->Index() );
		}

    textCopy.Delete( end, textCopy.Length() - end );
    textCopy.Delete( 0, start );
    iSmileUtil->SearchSmilesL( textCopy, iConvertArray, NULL, start );

    // Change icons to strings
	TPtrC myDebug( aEditor.Text()->Read( 0 ) ); 

    TInt selectAdd( 0 );
    count = iConvertArray.Count();
    for( i = count - 1; i >= 0; --i )
        {
        if( iConvertArray[ i ]->IsIcon() ) // Icon
            {
            TCursorSelection deleteSel( iConvertArray[ i ]->Position(),
                                        iConvertArray[ i ]->Position() + 1 );
                                        
            aEditor.InsertDeleteCharsL( iConvertArray[ i ]->Position(),
                                        iConvertArray[ i ]->SmileyString(),
                                        deleteSel );
            selectAdd += iConvertArray[ i ]->SmileyString().Length() - 1;
            //aEditor.SetMaxLength( aEditor.MaxLength() + selectAdd );
            }
        }
	myDebug.Set( aEditor.Text()->Read( 0 ) );
	

    aEditor.SetSelectionL( start, end + selectAdd );
    aEditor.TextView()->HandleGlobalChangeL();

    if( !aPreserve )
        {
	    iConvertArray.ResetAndDestroy();
        }
        
    CleanupStack::PopAndDestroy( text );
    IM_CV_LOGS(TXT("CIMCVAppSmileyUtil::ConvertSelectionToStringL() end") );
    }

// ---------------------------------------------------------
// CIMCVAppSmileyUtil::DeleteExtensionL
// (other items were commented in a header).
// ---------------------------------------------------------
//
void CIMCVAppSmileyUtil::DeleteExtensionL( CEikRichTextEditor& aEditor, TInt aPos )
    {
    IM_CV_LOGS(TXT("CIMCVAppSmileyUtil::DeleteExtensionL() start") );
    // Set cursor position before deletion.
    // Deletion may cause editor size to change and if
    // cursor pos is not updated before that ETEXT 12 panic
    // is raised.
    aEditor.SetCursorPosL( aPos, EFalse );
    aEditor.RichText()->DeleteL( aPos, 1 );
	aEditor.HandleTextChangedL();
	// Ugly hack. Needed to keep alignment of
	// cursor correct.
	aEditor.SetCursorPosL( aPos, EFalse );
	
	// update editors length, it grows by 2 when icon is deleted
	TInt textLimit = aEditor.MaxLength() + 2;		
	aEditor.SetTextLimit( textLimit );
	
	--iCurrentCount;
	IM_CV_LOGS(TXT("CIMCVAppSmileyUtil::DeleteExtensionL() end") );
	}

// -----------------------------------------------------------------------------
// CIMCVAppSmileyUtil::Reset
// Reset extension
// -----------------------------------------------------------------------------
//
void CIMCVAppSmileyUtil::Reset()
    {
    iCurrentCount = 0;
    }

// -----------------------------------------------------------------------------
// CIMCVAppSmileyUtil::SizeChanged
// Reset extension
// -----------------------------------------------------------------------------
//
void CIMCVAppSmileyUtil::SizeChanged( TSize& aSize )
    {
    IM_CV_LOGS(TXT("CIMCVAppSmileyUtil::SizeChanged() start") );
    iSmileUtil->ResizeIcons( aSize );
    IM_CV_LOGS(TXT("CIMCVAppSmileyUtil::SizeChanged() end") );
    }

// -----------------------------------------------------------------------------
// CIMCVAppSmileyUtil::ConvertSelectionToStringL
// Convert selection smileys to strings
// -----------------------------------------------------------------------------
//
void CIMCVAppSmileyUtil::ConvertSelectionToStringL(
    CEikRichTextEditor& aEditor,
    TDes& aResultString,
    TCursorSelection& aSelectionAfterConversion,
    TBool aPreserve )
    {
    IM_CV_LOGS(TXT("CIMCVAppSmileyUtil::ConvertSelectionToStringL() start") );
    // Clear convert array
    iConvertArray.ResetAndDestroy();
	
    // Get text from editor
    HBufC* text = HBufC::NewMaxLC( KDefaultMsgLength );
    TPtr textCopy( text->Des() );
    aEditor.GetText( textCopy );

	// For loop gets icon positions to array
    TInt start = aEditor.Selection().LowerPos();
    TInt end = aEditor.Selection().HigherPos();
	
	// Copy text to result string
	aResultString.Append( textCopy );
	
	TInt i = 0;
    for( i = start; i < end; ++i )
        {
		if ( textCopy[i] ==  CEditableText::EPictureCharacter )
			{
            CIMCVAppSmileyInformation* smileInfo = CIMCVAppSmileyInformation::NewL(); 
            CleanupStack::PushL( smileInfo );
            smileInfo->SetPosition( i );
            smileInfo->SetIcon( ETrue );
			User::LeaveIfError( iConvertArray.Append( smileInfo ) );
			CleanupStack::Pop( smileInfo );
			}	
        }

    TInt count = iConvertArray.Count();
	for( i = count - 1; i >= 0; --i )
		{
		CPicture* editorPic = NULL;
		
		editorPic = aEditor.RichText()->PictureHandleL( 
                iConvertArray[i]->Position(), MLayDoc::EForceLoadTrue );
        
		if ( !editorPic )
			{
			User::Leave( KErrBadHandle );
			}

		CIMCVAppPicture* icon = static_cast<CIMCVAppPicture*> ( editorPic );

        const TDesC& iconString = iSmileUtil->GetSmileString( icon->Index() );
        iConvertArray[i]->SetSmileyStringL( iconString );
        iConvertArray[i]->SetIndex( icon->Index() );
		}

    textCopy.Delete( end, textCopy.Length() - end );
    textCopy.Delete( 0, start );
    iSmileUtil->SearchSmilesL( textCopy, iConvertArray, NULL, start );

    // Change icons to strings
    TInt selectAdd = 0;
    count = iConvertArray.Count();
    for( i = count - 1; i >= 0; --i )
        {
        if( iConvertArray[ i ]->IsIcon() ) // Icon
            {
            // Append smiley string to result
            aResultString.Delete( iConvertArray[i]->Position(), 1 );
            aResultString.Insert( iConvertArray[i]->Position(), iConvertArray[i]->SmileyString() );
            selectAdd += iConvertArray[ i ]->SmileyString().Length() - 1;
            }
        }

    if( !aPreserve )
        {
	    iConvertArray.ResetAndDestroy();
        }
    
    // Set correct selection
    aSelectionAfterConversion.SetSelection( end + selectAdd, start );
        
    CleanupStack::PopAndDestroy( text );
    IM_CV_LOGS(TXT("CIMCVAppSmileyUtil::ConvertSelectionToStringL() end") );
    }
// -----------------------------------------------------------------------------
// CIMCVAppSmileyUtil::ServiceId
// Convert selection smileys to strings
// -----------------------------------------------------------------------------
//
TInt CIMCVAppSmileyUtil::ServiceId() const
    {
    return iServiceId;
    }
        
// End of File