--- /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
+