uifw/AvKon/src/akntextcontrol.cpp
changeset 0 2f259fa3e83a
child 19 aecbbf00d063
equal deleted inserted replaced
-1:000000000000 0:2f259fa3e83a
       
     1 /*
       
     2 * Copyright (c) 2002 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include "AknPanic.h"
       
    20 #include "akntextcontrol.h"
       
    21 
       
    22 #include "AknUtils.h"
       
    23 #include "AknBidiTextUtils.h"
       
    24 
       
    25 #include <AknPictographInterface.h>
       
    26 #include <AknPictographDrawerInterface.h>
       
    27 
       
    28 // CONSTANTS
       
    29 
       
    30 const TInt KDefaultMinCharWidthInPixels = 4;
       
    31 
       
    32 const TText KLineFeed               = 0x000A;
       
    33 const TText KCarriageReturn         = 0x000D;
       
    34 const TText KLineSeparator          = 0x2028;
       
    35 const TText KParagraphSeparator     = 0x2029;
       
    36 
       
    37 CAknTextControl* CAknTextControl::NewL(const CAknText::TType& aTextType)
       
    38 	{
       
    39 	CAknTextControl* self = new (ELeave) CAknTextControl();
       
    40 	CleanupStack::PushL(self);
       
    41 	self->ConstructL(aTextType);
       
    42 	CleanupStack::Pop(); //self
       
    43 	return self;
       
    44 	}
       
    45 
       
    46 void CAknTextControl::ConstructL(const CAknText::TType& aTextType)
       
    47 	{
       
    48 	iText = new (ELeave) CAknText( aTextType );
       
    49 	iWrappedArray = new (ELeave) CArrayFixFlat<TPtrC>(5);
       
    50 	iPictoInterface = CAknPictographInterface::NewL( *this, *this );
       
    51 	}
       
    52 
       
    53 CAknTextControl::CAknTextControl() 
       
    54 	{
       
    55 	}
       
    56 
       
    57 CAknTextControl::~CAknTextControl()
       
    58 	{
       
    59 	delete iText;
       
    60 	delete iWrappedArray;
       
    61 	delete iPictoInterface;
       
    62 	iLines.ResetAndDestroy();
       
    63 	iLines.Close();
       
    64 	}
       
    65 
       
    66 /*
       
    67  * Copy text and labels across (pointer copy)
       
    68  */
       
    69 CAknTextControl& CAknTextControl::operator=(CAknTextControl& aTextControl)
       
    70 	{
       
    71 	if (&aTextControl == this)
       
    72 		return *this;
       
    73 
       
    74 	if (aTextControl.iText && iText)
       
    75 		*iText = *aTextControl.iText;
       
    76 
       
    77 	if (aTextControl.NumberOfLines() > 0 && NumberOfLines() == 0)
       
    78 		{
       
    79 		iLines.ResetAndDestroy();
       
    80 		
       
    81 		for ( TInt i = aTextControl.NumberOfLines() - 1; i >= 0; i--)
       
    82 			if (iLines.Insert( aTextControl.iLines[i], 0) == KErrNone)
       
    83 				aTextControl.iLines.Remove(i);
       
    84 		}
       
    85 
       
    86 	if (aTextControl.iTextIsAlreadyInLabel)
       
    87 		iTextIsAlreadyInLabel = aTextControl.iTextIsAlreadyInLabel;
       
    88 
       
    89 	return *this;
       
    90 	}
       
    91 
       
    92 void CAknTextControl::ConstructFromResourceL(TResourceReader& aRes)
       
    93 	{
       
    94 	if (iText)
       
    95 		iText->ConstructFromResourceL(aRes);
       
    96 	}
       
    97 
       
    98 TInt CAknTextControl::CountComponentControls() const
       
    99 	{
       
   100 	return NumberOfLines();
       
   101 	}
       
   102 
       
   103 CCoeControl* CAknTextControl::ComponentControl(TInt anIndex) const
       
   104 	{
       
   105 	return const_cast<CEikLabel*>(Line(anIndex));
       
   106 	}
       
   107 
       
   108 TInt CAknTextControl::NumberOfLines() const
       
   109 	{
       
   110 	__ASSERT_DEBUG(iLines.Count() >= iNumberOfLines, Panic(EAknPanicSelfCheckFailure));
       
   111 	return iNumberOfLines;
       
   112 	}
       
   113 
       
   114 CEikLabel* CAknTextControl::Line(TInt aIndex) const
       
   115 	{
       
   116 	if (aIndex >= 0 && aIndex < NumberOfLines())
       
   117 		return iLines[aIndex]->iLabel;
       
   118 	return NULL;
       
   119 	}
       
   120 
       
   121 TBool CAknTextControl::LineModified(TInt aIndex) const
       
   122 	{
       
   123 	if (aIndex >= 0 && aIndex < NumberOfLines())
       
   124 		return iLines[aIndex]->iModified;
       
   125 	return EFalse;
       
   126 	}
       
   127 
       
   128 void  CAknTextControl::SetLineModified(TInt aIndex, TBool aValue)
       
   129 	{
       
   130 	if (aIndex >= 0 && aIndex < NumberOfLines())
       
   131 		iLines[aIndex]->iModified = aValue;
       
   132 	}
       
   133 
       
   134 void CAknTextControl::SetTextPluralityL(TBool aIsPlural)
       
   135 	{
       
   136 	if (iText)
       
   137 		iText->SetPluralityL(aIsPlural);
       
   138     }
       
   139 
       
   140 void CAknTextControl::SetTextNumberL(TInt aNumber)
       
   141 	{
       
   142 	if (iText)
       
   143 		iText->SetNumberL(aNumber);
       
   144     }
       
   145 
       
   146 /**
       
   147  * Set the text, to be spread across labels.
       
   148  */
       
   149 void CAknTextControl::SetTextL(const TDesC& aText)
       
   150 	{
       
   151 	if (iText)
       
   152 		{
       
   153 		iText->SetL(aText);
       
   154 		iTextIsAlreadyInLabel = EFalse;
       
   155 		}
       
   156 	}
       
   157 
       
   158 /**
       
   159  * Set text into a single label. ParseText will do nothing if this
       
   160  * method has been called.
       
   161  *
       
   162  * If the line already exists and it has already the same text and font
       
   163  * then return without doing anything.
       
   164  *
       
   165  * If the line does not exist, create it.
       
   166  *
       
   167  * SetBufferReserveLengthL causes a reallocation but this should never
       
   168  * be called unless somebody decides to change the font after the label
       
   169  * has been created and with this new font you can fit more characters 
       
   170  * in the same width
       
   171  */
       
   172 
       
   173 
       
   174 void CAknTextControl::SetTextL(
       
   175     const TDesC& aText,
       
   176     TInt aLineNum,
       
   177     const CFont* aFont,
       
   178     CArrayFixFlat<TInt>* aLineWidths )
       
   179 	{
       
   180 	__ASSERT_DEBUG( aLineNum >= 0, Panic( EAknPanicInvalidValue ) );
       
   181 	
       
   182 	if ( aLineNum >= iNumberOfLines )
       
   183 		{
       
   184 		CreateLabelsL( aLineNum + 1, aFont, aLineWidths );
       
   185 		iNumberOfLines = aLineNum + 1;
       
   186 		}
       
   187 	else
       
   188 		{
       
   189 		if ( aText == *( Line( aLineNum )->Text() ) )
       
   190 			{
       
   191 			iTextIsAlreadyInLabel = ETrue;
       
   192             return;
       
   193 			}
       
   194 		}
       
   195 
       
   196     TInt newReservedLength = aText.Length() + KAknBidiExtraSpacePerLine;
       
   197 
       
   198     HBufC* visualText = HBufC::NewL( newReservedLength );
       
   199     CleanupStack::PushL( visualText );
       
   200 
       
   201     *visualText = aText;
       
   202 
       
   203 	Line( aLineNum )->SetFont( aFont );
       
   204 
       
   205 	if ( Line( aLineNum )->BufferReserveLength() < newReservedLength )
       
   206         {
       
   207 		Line( aLineNum )->SetBufferReserveLengthL( newReservedLength );
       
   208         }
       
   209 
       
   210     TInt clipWidth = aLineWidths->At( aLineNum );
       
   211 
       
   212     // Logical-to-visual conversion is disabled in the owned CEikLabel instances,
       
   213     // so we do the conversion here, while clipping.
       
   214 
       
   215     TPtr ptr = visualText->Des();
       
   216 
       
   217     AknBidiTextUtils::ConvertToVisualAndClipL(
       
   218         ptr,
       
   219         *aFont,
       
   220         clipWidth,
       
   221         clipWidth );
       
   222 
       
   223 	Line( aLineNum )->SetTextL( *visualText );
       
   224 	iLines[aLineNum]->iModified = ETrue;
       
   225 	iTextIsAlreadyInLabel = ETrue;
       
   226 
       
   227     CleanupStack::PopAndDestroy(); // visualText;
       
   228 	}
       
   229 
       
   230 
       
   231 TPtr CAknTextControl::Text() const
       
   232 	{
       
   233 	if (iText) 
       
   234 		return iText->Get();
       
   235 	return TPtr(0,0);
       
   236 	}
       
   237 
       
   238 /**
       
   239  * Wraps the text and sets it into the labels.
       
   240  */
       
   241 void CAknTextControl::ParseTextL(const CFont* aFont, CArrayFixFlat<TInt>* aLineWidths,const TWrapMethod& aWrapMethod)
       
   242     { 
       
   243 	if ( aWrapMethod == ENoAllocation && iWrappedArray )
       
   244 		{
       
   245 		// We preallocate text required in construction of alert win, so we just replace the texts in labels.
       
   246         TPtrC remainder = Text();
       
   247 		TChar endlchar('\n');
       
   248 		TInt linebreak = remainder.LocateReverse(endlchar);
       
   249         
       
   250 		TBuf<17 + KAknBidiExtraSpacePerLine> temp; //KEikAlertMaxMsgLength not declared in this scope
       
   251 
       
   252         if ( linebreak == KErrNotFound )
       
   253             {
       
   254             AknBidiTextUtils::ConvertToVisualAndClip(remainder, temp, *aFont, KMaxTInt, KMaxTInt );
       
   255             Line(0)->SetTextL(temp); // won't leave as there is enough space in buffer
       
   256             iLines[0]->iModified = ETrue;
       
   257             Line(1)->SetTextL(KNullDesC);
       
   258             iLines[1]->iModified = ETrue;
       
   259             }
       
   260         else
       
   261             {
       
   262             AknBidiTextUtils::ConvertToVisualAndClip(
       
   263                 remainder.Left(linebreak), temp, *aFont, KMaxTInt, KMaxTInt );
       
   264             Line(0)->SetTextL(temp);
       
   265             iLines[0]->iModified = ETrue;
       
   266             if ( remainder.Length()-1 == linebreak) // Line break is the last character
       
   267                 {
       
   268                 Line(1)->SetTextL(KNullDesC);
       
   269                 }
       
   270             else
       
   271                 {
       
   272                 AknBidiTextUtils::ConvertToVisualAndClip( 
       
   273                     remainder.Right(remainder.Length()-linebreak-1), temp, *aFont, KMaxTInt, KMaxTInt );
       
   274                 Line(1)->SetTextL(temp); // we don't want new line to label, thus -1
       
   275                 }
       
   276             iLines[1]->iModified = ETrue;		
       
   277 			}
       
   278 		return;
       
   279 		}
       
   280 	if (iTextIsAlreadyInLabel || !iWrappedArray)
       
   281 		return;
       
   282 
       
   283     TInt maxLines = aLineWidths->Count();
       
   284 
       
   285     // user handles all text processing
       
   286     if ( aWrapMethod == ENoProcessing )
       
   287         {
       
   288         iWrappedArray->Reset();
       
   289 
       
   290         TPtrC remainder = Text();
       
   291 
       
   292         while ( remainder.Length() && iWrappedArray->Count() < maxLines )
       
   293             {
       
   294             const TText* textArray = remainder.Ptr();
       
   295             TInt textLength = remainder.Length();
       
   296 
       
   297             TInt i = 0;
       
   298 
       
   299             for ( ; i < textLength ; i++ )
       
   300                 {
       
   301                 TText t = textArray[i];
       
   302 
       
   303                 if ( t == KLineFeed ||
       
   304                      t == KLineSeparator ||
       
   305                      t == KParagraphSeparator ||
       
   306                      t == KCarriageReturn )
       
   307                     {
       
   308                     break;
       
   309                     }
       
   310                 }
       
   311 
       
   312             iWrappedArray->AppendL( remainder.Left( i ) );
       
   313 
       
   314             // After a CR, skip also possible matching LF
       
   315             if ( i < textLength - 1 &&
       
   316                  textArray[i] == KCarriageReturn &&
       
   317                  textArray[i + 1] == KLineFeed )
       
   318                 {
       
   319                 i++;
       
   320                 }
       
   321 
       
   322             i++;
       
   323 
       
   324             if ( i >= textLength )
       
   325                 {
       
   326                 break;
       
   327                 }
       
   328             remainder.Set( remainder.Right( textLength - i ) );
       
   329             }
       
   330         }
       
   331 
       
   332     else
       
   333         {
       
   334         TPtr text = Text();
       
   335 
       
   336         HBufC* visualBuffer = HBufC::NewLC( 
       
   337             text.Length() + maxLines * KAknBidiExtraSpacePerLine );
       
   338         *visualBuffer = text;
       
   339         TPtr ptr = visualBuffer->Des();
       
   340 
       
   341         AknTextUtils::DisplayTextLanguageSpecificNumberConversion( ptr);
       
   342 
       
   343 	    if (aWrapMethod == EWord)
       
   344             {
       
   345             AknBidiTextUtils::ConvertToVisualAndWrapToArrayL(
       
   346                 ptr, *aLineWidths, *aFont, *iWrappedArray, ETrue );
       
   347             }
       
   348 	    else if (aWrapMethod == ELine)
       
   349             {
       
   350 		    AknBidiTextUtils::ConvertToVisualAndChopToArrayL(
       
   351                 ptr, *aLineWidths, *aFont, *iWrappedArray );
       
   352             }
       
   353 	    else
       
   354             {
       
   355 		    __ASSERT_DEBUG(0,Panic(EAknPanicNotSupported));
       
   356             }
       
   357         }
       
   358 
       
   359     TInt numLines = iWrappedArray->Count();
       
   360 
       
   361 	UpdateLabelsL(numLines,aFont,aLineWidths);	
       
   362 	SetWrappedTextIntoLabelsL(*iWrappedArray, numLines, aFont);
       
   363 
       
   364     if ( aWrapMethod != ENoProcessing )
       
   365         {
       
   366         CleanupStack::PopAndDestroy(); // visualBuffer
       
   367         }
       
   368     }
       
   369 
       
   370 /**
       
   371  * Set text and font into labels.
       
   372  *
       
   373  * SetBufferReserveLengthL causes a reallocation but this should never
       
   374  * be called unless somebody decides to change the font after the label
       
   375  * has been created and with this new font you can fit more characters 
       
   376  * in the same width
       
   377 
       
   378  */
       
   379 void CAknTextControl::SetWrappedTextIntoLabelsL(const CArrayFix<TPtrC>& aWrappedArray, TInt aNumLines, const CFont* aFont)
       
   380 	{
       
   381 	__ASSERT_DEBUG(aNumLines == iNumberOfLines, Panic(EAknPanicSelfCheckFailure));
       
   382 	aNumLines = aNumLines ; // just for fixing warning
       
   383 	for (TInt i=0; i < iNumberOfLines; i++)
       
   384 		{
       
   385 		
       
   386 		if (Line(i)->BufferReserveLength() < aWrappedArray.At(i).Length())
       
   387 			Line(i)->SetBufferReserveLengthL(aWrappedArray.At(i).Length());
       
   388 
       
   389 		if (*(Line(i)->Text()) != aWrappedArray.At(i) )
       
   390 			{
       
   391 			Line(i)->SetTextL(aWrappedArray.At(i));
       
   392 			Line(i)->SetFont(aFont);
       
   393 			iLines[i]->iModified = ETrue;
       
   394 			}
       
   395 		}
       
   396 	}
       
   397 /**
       
   398  * Reset text in existing labels and create new ones if needed.
       
   399  *
       
   400  * Update the number of lines.
       
   401  */
       
   402 void CAknTextControl::UpdateLabelsL(const TInt aNum,const CFont* aFont, CArrayFixFlat<TInt>* aLineWidths)
       
   403 	{
       
   404 	__ASSERT_DEBUG(iNumberOfLines <= iLines.Count(), Panic(EAknPanicSelfCheckFailure));
       
   405 
       
   406 	if (aNum <= iNumberOfLines)
       
   407 		{
       
   408 		for (TInt i = aNum; i < iNumberOfLines; i++)
       
   409 			{
       
   410 			Line(i)->SetTextL(KNullDesC);
       
   411 			iLines[i]->iModified = ETrue;
       
   412 			}
       
   413 		}
       
   414 	else
       
   415 		{
       
   416 		CreateLabelsL(aNum,aFont,aLineWidths);
       
   417 		}
       
   418 
       
   419 	iNumberOfLines = aNum;
       
   420 	}
       
   421 
       
   422 /**
       
   423  * Create labels up to the specified number. 
       
   424  *
       
   425  * When a new label is created, allocate a buffer inside the label so 
       
   426  * that it can contains a text as long as the maximum number of 'l' characters 
       
   427  * that fit into the given line width (in pixels). 
       
   428  */
       
   429 void CAknTextControl::CreateLabelsL(const TInt aNum,const CFont* aFont, CArrayFixFlat<TInt>* aLineWidths)
       
   430 	{
       
   431 	__ASSERT_DEBUG(aFont,Panic(EAknPanicSelfCheckFailure));
       
   432 	__ASSERT_DEBUG(aLineWidths->Count() >= aNum,Panic(EAknPanicSelfCheckFailure));
       
   433 
       
   434     TInt minCharWidthInPixels = aFont->CharWidthInPixels('l');
       
   435     if ( minCharWidthInPixels < 1)
       
   436         {
       
   437         minCharWidthInPixels = KDefaultMinCharWidthInPixels;
       
   438         }
       
   439 
       
   440 	for (TInt i = iNumberOfLines; i < aNum; i++)
       
   441 		{
       
   442 		CEikLabel* label = CreateLabelLC(aLineWidths->At(i) / minCharWidthInPixels);
       
   443 		CLine* line = new (ELeave) CLine(label);
       
   444 		CleanupStack::Pop(); //label
       
   445 		CleanupStack::PushL(line);
       
   446 		User::LeaveIfError(iLines.Append(line));
       
   447 		CleanupStack::Pop(); //line
       
   448 		}
       
   449 	}
       
   450 
       
   451 /**
       
   452  * Create a label
       
   453  */
       
   454 CEikLabel* CAknTextControl::CreateLabelLC(TInt aLen)
       
   455 	{
       
   456 	CEikLabel* label = new(ELeave) CEikLabel;
       
   457 	CleanupStack::PushL(label);
       
   458 
       
   459 	label->SetContainerWindowL(*this);
       
   460 	label->SetBufferReserveLengthL(aLen);
       
   461 #ifdef RD_UI_TRANSITION_EFFECTS_POPUPS
       
   462     label->SetParent( this );
       
   463 #endif	
       
   464 	
       
   465     // we do logical to visual conversion ourselves while wrapping text
       
   466     label->UseLogicalToVisualConversion( EFalse );
       
   467 
       
   468     if ( iPictoInterface )
       
   469         {
       
   470         label->EnablePictographsL( *iPictoInterface );
       
   471         }
       
   472 	
       
   473 	return label;
       
   474 	}
       
   475 
       
   476 void CAknTextControl::SetPictographCallBackL( TCallBack& aCallBack )
       
   477     {
       
   478     iPictoCallBack = aCallBack;
       
   479     }
       
   480 
       
   481 CAknPictographInterface* CAknTextControl::PictographInterface() const
       
   482     {
       
   483     return iPictoInterface;
       
   484     }
       
   485 
       
   486 void CAknTextControl::DrawPictographArea()
       
   487     {
       
   488     if ( iPictoCallBack.iFunction )
       
   489         {
       
   490         iPictoCallBack.CallBack();
       
   491         }
       
   492     }
       
   493 
       
   494 		
       
   495 // End of File