diff -r 000000000000 -r 094583676ce7 wvuing/wvuiave/AppSrc/CCASmileIconUtility.cpp --- /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 +#include +#include +#include // RResourceReader +#include +#include +#include +#include + +// 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* 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 +