--- /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 <AknPictographInterface.h>
+#include <AknPictographDrawerInterface.h>
+
+// 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<TPtrC>(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<CEikLabel*>(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<TInt>* 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<TInt>* 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<TPtrC>& 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<TInt>* 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<TInt>* 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