wvuing/wvuiave/AppSrc/CCASmileIconUtility.cpp
changeset 0 094583676ce7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wvuing/wvuiave/AppSrc/CCASmileIconUtility.cpp	Thu Dec 17 08:41:52 2009 +0200
@@ -0,0 +1,478 @@
+/*
+* Copyright (c) 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:  Utility for selecting smile icon and converting
+*                between smile id and smile string.
+*
+*/
+
+
+// INCLUDE FILES
+#include "CCASmileIconUtility.h"
+#include "CCASmileIconDialog.h"
+#include "ccasmilestring.h"
+#include "ccasmileyinformation.h"
+#include "IMUtils.h"
+
+#include "CCAAppUi.h"
+#include "MCASkinVariant.h"
+#include "CCAApp.h"
+#include "CCAVariantFactory.h"
+#include "ChatDebugPrint.h"
+#include "chatdebugassert.h"
+
+#include <chatNG.rsg>
+#include <bautils.h>
+#include <PUAcodes.hrh>
+#include <barsread.h> // RResourceReader
+#include <coemain.h>
+#include <eikenv.h>
+#include <gulicon.h>
+#include <akniconutils.h>
+
+// The Settings have been moved to Cenrep (also retained in the Resource file),
+// so the enums for keys and central repository header is added here
+#include 	"VariantKeys.h"
+// ================= MEMBER FUNCTIONS =======================
+
+// Two-phased constructor.
+CCASmileIconUtility* CCASmileIconUtility::NewL(
+    MCASkinVariant& aSkinVariant,
+    MCAAppUi& aAppUi )
+    {
+    CCASmileIconUtility* self = new ( ELeave ) CCASmileIconUtility( aSkinVariant, aAppUi );
+    CleanupStack::PushL( self );
+    self->ConstructL( R_SMILE_ARRAY_RESOURCE );
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+// Two-phased constructor.
+CCASmileIconUtility* CCASmileIconUtility::NewL(
+    MCASkinVariant& aSkinVariant,
+    MCAAppUi& aAppUi,
+    TInt aResourceId )
+    {
+    CCASmileIconUtility* self = new ( ELeave ) CCASmileIconUtility( aSkinVariant, aAppUi );
+    CleanupStack::PushL( self );
+    self->ConstructL( aResourceId );
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+// Destructor
+CCASmileIconUtility::~CCASmileIconUtility()
+    {
+    iAppUi.RemoveResourceChangeObserver( this );
+    iIconArray.ResetAndDestroy();
+    iStringArray.ResetAndDestroy();
+    iSmileArray.ResetAndDestroy();
+    iIconToSmileyPointers.Close();
+
+    iSmileDlgIconArray.ResetAndDestroy();
+    }
+
+// C++ constructor can NOT contain any code, that
+// might leave.
+//
+CCASmileIconUtility::CCASmileIconUtility( MCASkinVariant& aSkinVariant,
+                                          MCAAppUi& aAppUi )
+        : iSkinVariant( aSkinVariant ), iAppUi( aAppUi )
+    {
+    }
+
+// ConstructL
+//
+void CCASmileIconUtility::ConstructL( TInt aResourceId )
+    {
+    // we need to be resource aware
+    iAppUi.AddResourceChangeObserver( this );
+
+    ConstructFromResourceL( aResourceId );
+    }
+
+// ---------------------------------------------------------
+// CCASmileIconUtility::ConstructSmileDialogIconArrayL
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CCASmileIconUtility::ConstructSmileDialogIconArrayL( TInt aResourceId )
+    {
+    TResourceReader reader;
+    CCoeEnv::Static()->CreateResourceReaderLC( reader, aResourceId );
+
+    TInt iconId;
+    TInt maskId;
+    TInt err( KErrNone );
+
+    TInt iconCount( reader.ReadInt16() );
+    for ( TInt i( 0 ); i < iconCount; ++i )
+        {
+        iconId = reader.ReadInt16();
+        maskId = reader.ReadInt16();
+
+        CGulIcon* icon = iSkinVariant.LoadBitmapL( iconId, maskId,
+                                                   iAppUi.MbmFullPath() );
+
+        err = iSmileDlgIconArray.Append( icon );
+        if ( err )
+            {
+            delete icon;
+            User::Leave( err );
+            }
+
+        TInt stringCount( reader.ReadInt16() );
+        if ( !stringCount )
+            {
+            User::Leave( KErrGeneral );
+            }
+
+        HBufC* shortertString = NULL;
+        for ( TInt j( 0 ); j < stringCount; ++j )
+            {
+            HBufC* smileString = reader.ReadHBufCL();
+            delete smileString;
+            }
+        }
+    CleanupStack::PopAndDestroy( ); // reader
+    }
+
+// ---------------------------------------------------------
+// CCASmileIconUtility::LaunchSmileIconDialogL
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+TInt CCASmileIconUtility::LaunchSmileIconDialogL( TInt& aSelectedIconId )
+    {
+    if ( iSmileDlgIconArray.Count() <= 0 )
+        {
+        ConstructSmileDialogIconArrayL( R_SMILE_ARRAY_RESOURCE );
+        }
+
+    CCASmileIconDialog* dialog = CCASmileIconDialog::NewL( iSmileDlgIconArray,
+                                                           aSelectedIconId );
+    TInt dialogVal = dialog->ExecuteLD( R_SELECT_SMILE_DIALOG );
+
+    return dialogVal;
+    }
+
+// ---------------------------------------------------------
+// CCASmileIconUtility::SmileIconCount
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+TInt CCASmileIconUtility::SmileIconCount() const
+    {
+    return iIconArray.Count();
+    }
+
+// ---------------------------------------------------------
+// CCASmileIconUtility::GetSmileIcon
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+const CGulIcon* CCASmileIconUtility::GetSmileIcon( TInt aIconId ) const
+    {
+    return iIconArray[ aIconId ];
+    }
+
+// ---------------------------------------------------------
+// CCASmileIconUtility::GetSmileString
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+const TDesC& CCASmileIconUtility::GetSmileString( TInt aIconId ) const
+    {
+    return iStringArray[ iIconToSmileyPointers[ aIconId ] ]->HasShortestString() ?
+           iStringArray[ iIconToSmileyPointers[ aIconId ] ]->ShortestSmileString() :
+           iStringArray[ iIconToSmileyPointers[ aIconId ] ]->SmileString();
+    }
+
+// ---------------------------------------------------------
+// CCASmileIconUtility::SearchSmilesL
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CCASmileIconUtility::SearchSmilesL( const TDesC& aStr, TDes& aFixedStr,
+                                         RArray<TInt>* aArray )
+    {
+
+    CHAT_DP( D_CHAT_LIT( "CCASmileIconUtility::SearchSmilesL: begin %S" ),
+             &aStr );
+    TInt i;
+    iSmileArray.ResetAndDestroy();
+    SearchSmilesL( aStr, iSmileArray, &aFixedStr );
+
+    aArray->Reset();
+    TInt arrayCount( iSmileArray.Count() );
+
+    for ( i = 0; i < arrayCount; ++i )
+        {
+        User::LeaveIfError( aArray->Append( iSmileArray[ i ]->Index() ) );
+        }
+
+    iSmileArray.ResetAndDestroy();
+    CHAT_DP( D_CHAT_LIT( "CCASmileIconUtility::SearchSmilesL: done %S" ),
+             &aFixedStr );
+    }
+
+// -----------------------------------------------------------------------------
+// CCASmileIconUtility::SearchSmilesL
+// Search smileys from string and sort them in linear order.
+// -----------------------------------------------------------------------------
+//
+void CCASmileIconUtility::SearchSmilesL( const TDesC& aStr,
+                                         RPointerArray< CCASmileyInformation >& aSmileyInfoArray,
+                                         TDes* aFixedStr /*= NULL */,
+                                         TInt aStartPos /* = 0 */ ) const
+    {
+    CHAT_DP( D_CHAT_LIT( "CCASmileIconUtility::SearchSmilesL2: %S %d" ),
+             &aStr, aStartPos );
+
+    HBufC* text = HBufC::NewMaxLC( aStr.Length() );
+    TPtr fixedText( text->Des() );
+    fixedText.Copy( aStr.Left( fixedText.MaxLength() ) );
+
+    HBufC* replaceString = HBufC::NewMaxLC( iLongestSmileyLength );
+    TPtr replace( replaceString->Des() );
+    if ( aFixedStr )
+        {
+        replace.Fill( KPuaCodeSmileyIconPadding, 1 );
+        }
+    else
+        {
+        //we dont need fixed, but we do need correct positions
+        replace.Fill( KPuaCodeSmileyIconPadding, iLongestSmileyLength );
+        }
+
+    // order to sort array by the position
+    TLinearOrder< CCASmileyInformation > order( CCASmileIconUtility::Compare );
+
+    // for i-loop goes throug every smile string
+    // while-loop searches smiles from given string
+    TInt arrayCount = iStringArray.Count();
+    TInt index = 0;
+    for ( TInt i = 0; i < arrayCount; ++i )
+        {
+        const TDesC& smileString( iStringArray[ i ]->SmileString() );
+        index = fixedText.Find( smileString );
+        while ( index != KErrNotFound )
+            {
+            CCASmileyInformation* smileInfo = CCASmileyInformation::NewL();
+            CleanupStack::PushL( smileInfo );
+
+            smileInfo->SetPosition( index + aStartPos );
+            smileInfo->SetIndex( iStringArray[ i ]->SmileIconIndex() );
+            smileInfo->SetSmileyStringL( smileString );
+            smileInfo->SetIcon( EFalse );
+
+            User::LeaveIfError( aSmileyInfoArray.Append( smileInfo ) );
+            CleanupStack::Pop( smileInfo );
+
+            TInt smilyLength = smileString.Length();
+            // Only replace the same amount of chars than in smiley, so we
+            // don't mess up the length or index table.
+            fixedText.Replace( index,
+                               smilyLength,
+                               replace.Left( smilyLength ) );
+            index = fixedText.Find( smileString );
+            } // while
+        } // for i
+
+    aSmileyInfoArray.Sort( order );
+    if ( aFixedStr )
+        {
+        *aFixedStr = fixedText;
+        }
+
+    CleanupStack::PopAndDestroy( 2, text ); // replaceString, text
+    CHAT_DP_TXT( "CCASmileIconUtility::SearchSmilesL2: done" );
+    }
+
+// ---------------------------------------------------------
+// CCASmileIconUtility::Compare
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+TInt CCASmileIconUtility::Compare( const CCASmileyInformation& aFirst,
+                                   const CCASmileyInformation& aSecond )
+    {
+    return ( aFirst.Position() - aSecond.Position() );
+    }
+
+// -----------------------------------------------------------------------------
+// CCASmileIconUtility::CompareSmileyLengthReversed
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CCASmileIconUtility::CompareSmileyLengthReversed(
+    const CCASmileString& aFirst,
+    const CCASmileString& aSecond )
+    {
+    return ( aSecond.SmileString().Length() - aFirst.SmileString().Length() );
+    }
+
+// ---------------------------------------------------------
+// CCASmileIconUtility::ResizeIcons
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CCASmileIconUtility::ResizeIcons( const TSize& aSize )
+    {
+    TInt count( SmileIconCount() );
+    for ( TInt i( 0 ); i < count; i++ )
+        {
+        AknIconUtils::SetSize( iIconArray[ i ]->Bitmap(), aSize );
+        }
+    }
+
+// ---------------------------------------------------------
+// CCASmileIconUtility::ConstructFromResourceL
+// (other items were commented in a header).
+// ---------------------------------------------------------
+//
+void CCASmileIconUtility::ConstructFromResourceL( TInt aResourceId )
+    {
+    TResourceReader reader;
+    CCoeEnv::Static()->CreateResourceReaderLC( reader, aResourceId );
+
+    iLongestSmileyLength = 1;
+    TInt iconId;
+    TInt maskId;
+    TInt err( KErrNone );
+    TInt iconCount( reader.ReadInt16() );
+    for ( TInt i( 0 ); i < iconCount; ++i )
+        {
+        iconId = reader.ReadInt16();
+        maskId = reader.ReadInt16();
+
+        CGulIcon* icon = iSkinVariant.LoadBitmapL( iconId, maskId,
+                                                   iAppUi.MbmFullPath() );
+
+        err = iIconArray.Append( icon );
+        if ( err )
+            {
+            delete icon;
+            User::Leave( err );
+            }
+
+        TInt stringCount( reader.ReadInt16() );
+        if ( !stringCount )
+            {
+            User::Leave( KErrGeneral );
+            }
+
+        HBufC* shortertString = NULL;
+
+        for ( TInt j( 0 ); j < stringCount; ++j )
+            {
+            CCASmileString* smileArray = CCASmileString::NewL();
+            CleanupStack::PushL( smileArray );
+
+            HBufC* smileString = reader.ReadHBufCL();
+            // ownership is transferred
+            smileArray->Set( smileString, i );
+
+            // Update the smiley length
+            if ( smileString->Length() > iLongestSmileyLength )
+                {
+                iLongestSmileyLength = smileString->Length();
+                }
+
+            // Check for shorter smiley strings,
+            // needed when converting smileys from images to
+            // strings before sending to avoid descriptor overflow
+            if ( shortertString )
+                {
+                if ( shortertString->Length() < shortertString->Length() )
+                    {
+                    // Set shotestString to current smiley
+                    smileArray->SetShortestSmileStringL( *shortertString );
+                    }
+                else
+                    {
+                    // Found a new shortest string
+                    // Set it to previous similar smileys
+                    for ( TInt ii = 0; ii < j; ii++ )
+                        {
+                        iStringArray[iStringArray.Count() - ii - 1]->
+                        SetShortestSmileStringL( *smileString );
+                        }
+                    // Store new shortest string
+                    shortertString = smileString;
+                    }
+                }
+            else
+                {
+                // First string, store to shortestString
+                shortertString = smileString;
+                }
+
+            User::LeaveIfError( iStringArray.Append( smileArray ) );
+            CleanupStack::Pop( smileArray );
+            }
+        }
+
+    CleanupStack::PopAndDestroy(); // reader
+
+    // Sort smileys according to their string length, so that searching
+    // for smileys is done from the longest smiley to the shortest. This
+    // prevents the chat from detecting smaller smileys inside the big ones.
+    TLinearOrder< CCASmileString >
+    order( CCASmileIconUtility::CompareSmileyLengthReversed );
+    iStringArray.Sort( order );
+
+    // Precalculate an ref table from icon to smiley.
+    iIconToSmileyPointers.Reset();
+    TInt count = iIconArray.Count();
+    for ( TInt i = 0; i < count; ++i )
+        {
+        User::LeaveIfError(
+            iIconToSmileyPointers.Append( GetFirstSmileyIndex( i ) ) );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CCASmileIconUtility::GetFirstSmileyIndex
+// -----------------------------------------------------------------------------
+//
+TInt CCASmileIconUtility::GetFirstSmileyIndex( TInt aIconIndex ) const
+    {
+    TInt count = iStringArray.Count();
+
+    for ( TInt i = 0; i < count; ++i )
+        {
+        if ( iStringArray[ i ]->SmileIconIndex() == aIconIndex )
+            {
+            return i;
+            }
+        }
+
+    // Icon was not found.
+    __CHAT_ASSERT_DEBUG( EFalse );
+    return KErrNotFound;
+    }
+
+// -----------------------------------------------------------------------------
+// CCASmileIconUtility::HandleResourceChange
+// -----------------------------------------------------------------------------
+//
+void CCASmileIconUtility::ResourceChangedL()
+    {
+    iIconArray.ResetAndDestroy();
+    iStringArray.ResetAndDestroy();
+    ConstructFromResourceL( R_SMILE_ARRAY_RESOURCE );
+    }
+
+// End of File
+