diff -r 000000000000 -r 2f259fa3e83a uifw/AvKon/src/akntextcontrol.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/uifw/AvKon/src/akntextcontrol.cpp Tue Feb 02 01:00:49 2010 +0200 @@ -0,0 +1,495 @@ +/* +* Copyright (c) 2002 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: +* +*/ + + +#include "AknPanic.h" +#include "akntextcontrol.h" + +#include "AknUtils.h" +#include "AknBidiTextUtils.h" + +#include +#include + +// CONSTANTS + +const TInt KDefaultMinCharWidthInPixels = 4; + +const TText KLineFeed = 0x000A; +const TText KCarriageReturn = 0x000D; +const TText KLineSeparator = 0x2028; +const TText KParagraphSeparator = 0x2029; + +CAknTextControl* CAknTextControl::NewL(const CAknText::TType& aTextType) + { + CAknTextControl* self = new (ELeave) CAknTextControl(); + CleanupStack::PushL(self); + self->ConstructL(aTextType); + CleanupStack::Pop(); //self + return self; + } + +void CAknTextControl::ConstructL(const CAknText::TType& aTextType) + { + iText = new (ELeave) CAknText( aTextType ); + iWrappedArray = new (ELeave) CArrayFixFlat(5); + iPictoInterface = CAknPictographInterface::NewL( *this, *this ); + } + +CAknTextControl::CAknTextControl() + { + } + +CAknTextControl::~CAknTextControl() + { + delete iText; + delete iWrappedArray; + delete iPictoInterface; + iLines.ResetAndDestroy(); + iLines.Close(); + } + +/* + * Copy text and labels across (pointer copy) + */ +CAknTextControl& CAknTextControl::operator=(CAknTextControl& aTextControl) + { + if (&aTextControl == this) + return *this; + + if (aTextControl.iText && iText) + *iText = *aTextControl.iText; + + if (aTextControl.NumberOfLines() > 0 && NumberOfLines() == 0) + { + iLines.ResetAndDestroy(); + + for ( TInt i = aTextControl.NumberOfLines() - 1; i >= 0; i--) + if (iLines.Insert( aTextControl.iLines[i], 0) == KErrNone) + aTextControl.iLines.Remove(i); + } + + if (aTextControl.iTextIsAlreadyInLabel) + iTextIsAlreadyInLabel = aTextControl.iTextIsAlreadyInLabel; + + return *this; + } + +void CAknTextControl::ConstructFromResourceL(TResourceReader& aRes) + { + if (iText) + iText->ConstructFromResourceL(aRes); + } + +TInt CAknTextControl::CountComponentControls() const + { + return NumberOfLines(); + } + +CCoeControl* CAknTextControl::ComponentControl(TInt anIndex) const + { + return const_cast(Line(anIndex)); + } + +TInt CAknTextControl::NumberOfLines() const + { + __ASSERT_DEBUG(iLines.Count() >= iNumberOfLines, Panic(EAknPanicSelfCheckFailure)); + return iNumberOfLines; + } + +CEikLabel* CAknTextControl::Line(TInt aIndex) const + { + if (aIndex >= 0 && aIndex < NumberOfLines()) + return iLines[aIndex]->iLabel; + return NULL; + } + +TBool CAknTextControl::LineModified(TInt aIndex) const + { + if (aIndex >= 0 && aIndex < NumberOfLines()) + return iLines[aIndex]->iModified; + return EFalse; + } + +void CAknTextControl::SetLineModified(TInt aIndex, TBool aValue) + { + if (aIndex >= 0 && aIndex < NumberOfLines()) + iLines[aIndex]->iModified = aValue; + } + +void CAknTextControl::SetTextPluralityL(TBool aIsPlural) + { + if (iText) + iText->SetPluralityL(aIsPlural); + } + +void CAknTextControl::SetTextNumberL(TInt aNumber) + { + if (iText) + iText->SetNumberL(aNumber); + } + +/** + * Set the text, to be spread across labels. + */ +void CAknTextControl::SetTextL(const TDesC& aText) + { + if (iText) + { + iText->SetL(aText); + iTextIsAlreadyInLabel = EFalse; + } + } + +/** + * Set text into a single label. ParseText will do nothing if this + * method has been called. + * + * If the line already exists and it has already the same text and font + * then return without doing anything. + * + * If the line does not exist, create it. + * + * SetBufferReserveLengthL causes a reallocation but this should never + * be called unless somebody decides to change the font after the label + * has been created and with this new font you can fit more characters + * in the same width + */ + + +void CAknTextControl::SetTextL( + const TDesC& aText, + TInt aLineNum, + const CFont* aFont, + CArrayFixFlat* aLineWidths ) + { + __ASSERT_DEBUG( aLineNum >= 0, Panic( EAknPanicInvalidValue ) ); + + if ( aLineNum >= iNumberOfLines ) + { + CreateLabelsL( aLineNum + 1, aFont, aLineWidths ); + iNumberOfLines = aLineNum + 1; + } + else + { + if ( aText == *( Line( aLineNum )->Text() ) ) + { + iTextIsAlreadyInLabel = ETrue; + return; + } + } + + TInt newReservedLength = aText.Length() + KAknBidiExtraSpacePerLine; + + HBufC* visualText = HBufC::NewL( newReservedLength ); + CleanupStack::PushL( visualText ); + + *visualText = aText; + + Line( aLineNum )->SetFont( aFont ); + + if ( Line( aLineNum )->BufferReserveLength() < newReservedLength ) + { + Line( aLineNum )->SetBufferReserveLengthL( newReservedLength ); + } + + TInt clipWidth = aLineWidths->At( aLineNum ); + + // Logical-to-visual conversion is disabled in the owned CEikLabel instances, + // so we do the conversion here, while clipping. + + TPtr ptr = visualText->Des(); + + AknBidiTextUtils::ConvertToVisualAndClipL( + ptr, + *aFont, + clipWidth, + clipWidth ); + + Line( aLineNum )->SetTextL( *visualText ); + iLines[aLineNum]->iModified = ETrue; + iTextIsAlreadyInLabel = ETrue; + + CleanupStack::PopAndDestroy(); // visualText; + } + + +TPtr CAknTextControl::Text() const + { + if (iText) + return iText->Get(); + return TPtr(0,0); + } + +/** + * Wraps the text and sets it into the labels. + */ +void CAknTextControl::ParseTextL(const CFont* aFont, CArrayFixFlat* aLineWidths,const TWrapMethod& aWrapMethod) + { + if ( aWrapMethod == ENoAllocation && iWrappedArray ) + { + // We preallocate text required in construction of alert win, so we just replace the texts in labels. + TPtrC remainder = Text(); + TChar endlchar('\n'); + TInt linebreak = remainder.LocateReverse(endlchar); + + TBuf<17 + KAknBidiExtraSpacePerLine> temp; //KEikAlertMaxMsgLength not declared in this scope + + if ( linebreak == KErrNotFound ) + { + AknBidiTextUtils::ConvertToVisualAndClip(remainder, temp, *aFont, KMaxTInt, KMaxTInt ); + Line(0)->SetTextL(temp); // won't leave as there is enough space in buffer + iLines[0]->iModified = ETrue; + Line(1)->SetTextL(KNullDesC); + iLines[1]->iModified = ETrue; + } + else + { + AknBidiTextUtils::ConvertToVisualAndClip( + remainder.Left(linebreak), temp, *aFont, KMaxTInt, KMaxTInt ); + Line(0)->SetTextL(temp); + iLines[0]->iModified = ETrue; + if ( remainder.Length()-1 == linebreak) // Line break is the last character + { + Line(1)->SetTextL(KNullDesC); + } + else + { + AknBidiTextUtils::ConvertToVisualAndClip( + remainder.Right(remainder.Length()-linebreak-1), temp, *aFont, KMaxTInt, KMaxTInt ); + Line(1)->SetTextL(temp); // we don't want new line to label, thus -1 + } + iLines[1]->iModified = ETrue; + } + return; + } + if (iTextIsAlreadyInLabel || !iWrappedArray) + return; + + TInt maxLines = aLineWidths->Count(); + + // user handles all text processing + if ( aWrapMethod == ENoProcessing ) + { + iWrappedArray->Reset(); + + TPtrC remainder = Text(); + + while ( remainder.Length() && iWrappedArray->Count() < maxLines ) + { + const TText* textArray = remainder.Ptr(); + TInt textLength = remainder.Length(); + + TInt i = 0; + + for ( ; i < textLength ; i++ ) + { + TText t = textArray[i]; + + if ( t == KLineFeed || + t == KLineSeparator || + t == KParagraphSeparator || + t == KCarriageReturn ) + { + break; + } + } + + iWrappedArray->AppendL( remainder.Left( i ) ); + + // After a CR, skip also possible matching LF + if ( i < textLength - 1 && + textArray[i] == KCarriageReturn && + textArray[i + 1] == KLineFeed ) + { + i++; + } + + i++; + + if ( i >= textLength ) + { + break; + } + remainder.Set( remainder.Right( textLength - i ) ); + } + } + + else + { + TPtr text = Text(); + + HBufC* visualBuffer = HBufC::NewLC( + text.Length() + maxLines * KAknBidiExtraSpacePerLine ); + *visualBuffer = text; + TPtr ptr = visualBuffer->Des(); + + AknTextUtils::DisplayTextLanguageSpecificNumberConversion( ptr); + + if (aWrapMethod == EWord) + { + AknBidiTextUtils::ConvertToVisualAndWrapToArrayL( + ptr, *aLineWidths, *aFont, *iWrappedArray, ETrue ); + } + else if (aWrapMethod == ELine) + { + AknBidiTextUtils::ConvertToVisualAndChopToArrayL( + ptr, *aLineWidths, *aFont, *iWrappedArray ); + } + else + { + __ASSERT_DEBUG(0,Panic(EAknPanicNotSupported)); + } + } + + TInt numLines = iWrappedArray->Count(); + + UpdateLabelsL(numLines,aFont,aLineWidths); + SetWrappedTextIntoLabelsL(*iWrappedArray, numLines, aFont); + + if ( aWrapMethod != ENoProcessing ) + { + CleanupStack::PopAndDestroy(); // visualBuffer + } + } + +/** + * Set text and font into labels. + * + * SetBufferReserveLengthL causes a reallocation but this should never + * be called unless somebody decides to change the font after the label + * has been created and with this new font you can fit more characters + * in the same width + + */ +void CAknTextControl::SetWrappedTextIntoLabelsL(const CArrayFix& aWrappedArray, TInt aNumLines, const CFont* aFont) + { + __ASSERT_DEBUG(aNumLines == iNumberOfLines, Panic(EAknPanicSelfCheckFailure)); + aNumLines = aNumLines ; // just for fixing warning + for (TInt i=0; i < iNumberOfLines; i++) + { + + if (Line(i)->BufferReserveLength() < aWrappedArray.At(i).Length()) + Line(i)->SetBufferReserveLengthL(aWrappedArray.At(i).Length()); + + if (*(Line(i)->Text()) != aWrappedArray.At(i) ) + { + Line(i)->SetTextL(aWrappedArray.At(i)); + Line(i)->SetFont(aFont); + iLines[i]->iModified = ETrue; + } + } + } +/** + * Reset text in existing labels and create new ones if needed. + * + * Update the number of lines. + */ +void CAknTextControl::UpdateLabelsL(const TInt aNum,const CFont* aFont, CArrayFixFlat* aLineWidths) + { + __ASSERT_DEBUG(iNumberOfLines <= iLines.Count(), Panic(EAknPanicSelfCheckFailure)); + + if (aNum <= iNumberOfLines) + { + for (TInt i = aNum; i < iNumberOfLines; i++) + { + Line(i)->SetTextL(KNullDesC); + iLines[i]->iModified = ETrue; + } + } + else + { + CreateLabelsL(aNum,aFont,aLineWidths); + } + + iNumberOfLines = aNum; + } + +/** + * Create labels up to the specified number. + * + * When a new label is created, allocate a buffer inside the label so + * that it can contains a text as long as the maximum number of 'l' characters + * that fit into the given line width (in pixels). + */ +void CAknTextControl::CreateLabelsL(const TInt aNum,const CFont* aFont, CArrayFixFlat* aLineWidths) + { + __ASSERT_DEBUG(aFont,Panic(EAknPanicSelfCheckFailure)); + __ASSERT_DEBUG(aLineWidths->Count() >= aNum,Panic(EAknPanicSelfCheckFailure)); + + TInt minCharWidthInPixels = aFont->CharWidthInPixels('l'); + if ( minCharWidthInPixels < 1) + { + minCharWidthInPixels = KDefaultMinCharWidthInPixels; + } + + for (TInt i = iNumberOfLines; i < aNum; i++) + { + CEikLabel* label = CreateLabelLC(aLineWidths->At(i) / minCharWidthInPixels); + CLine* line = new (ELeave) CLine(label); + CleanupStack::Pop(); //label + CleanupStack::PushL(line); + User::LeaveIfError(iLines.Append(line)); + CleanupStack::Pop(); //line + } + } + +/** + * Create a label + */ +CEikLabel* CAknTextControl::CreateLabelLC(TInt aLen) + { + CEikLabel* label = new(ELeave) CEikLabel; + CleanupStack::PushL(label); + + label->SetContainerWindowL(*this); + label->SetBufferReserveLengthL(aLen); +#ifdef RD_UI_TRANSITION_EFFECTS_POPUPS + label->SetParent( this ); +#endif + + // we do logical to visual conversion ourselves while wrapping text + label->UseLogicalToVisualConversion( EFalse ); + + if ( iPictoInterface ) + { + label->EnablePictographsL( *iPictoInterface ); + } + + return label; + } + +void CAknTextControl::SetPictographCallBackL( TCallBack& aCallBack ) + { + iPictoCallBack = aCallBack; + } + +CAknPictographInterface* CAknTextControl::PictographInterface() const + { + return iPictoInterface; + } + +void CAknTextControl::DrawPictographArea() + { + if ( iPictoCallBack.iFunction ) + { + iPictoCallBack.CallBack(); + } + } + + +// End of File