uifw/EikStd/dlgsrc/EIKCAPCA.CPP
changeset 0 2f259fa3e83a
child 4 8ca85d2f0db7
equal deleted inserted replaced
-1:000000000000 0:2f259fa3e83a
       
     1 /*
       
     2 * Copyright (c) 1997-2009 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 <eikcapca.h>
       
    20 #include <eikcapc.h>
       
    21 #include <AknLayout2ScalableDef.h>
       
    22 #include <AknUtils.h>
       
    23 #include <aknlayoutscalable_avkon.cdl.h>
       
    24 #include <AknsUtils.h>
       
    25 #include <eikedwin.h>
       
    26 #include "AknPanic.h"
       
    27 
       
    28 const TInt KVerticalSpacing=-2;  // Avkon form controls overlap by two pixels!
       
    29 const TInt KVerticalSpacingSquash=0;
       
    30 
       
    31 const TInt KAknTopMargin = 0 ;
       
    32 const TInt KAknNoTopMargin = 0 ;
       
    33 
       
    34 
       
    35 class CEikCapCArrayExtension : public CBase
       
    36 {
       
    37 public:
       
    38 	TInt iCaptionWidth;
       
    39 	TRect iRect;
       
    40 };
       
    41 
       
    42 
       
    43 TBool IsPopupField(CEikCaptionedControl* aCC)
       
    44 {
       
    45 	TInt ctrlType = aCC->iControlType;
       
    46 	if (ctrlType == EAknCtPopupField || ctrlType == EAknCtPopupFieldText)
       
    47 	{
       
    48 		CAknPopupField *field = (CAknPopupField*)aCC->iControl;
       
    49 		if (field->SelectionMode() != CAknPopupField::EAknPopupFieldLabelMode)
       
    50 			return ETrue;
       
    51 		return EFalse;
       
    52 	}
       
    53 	return EFalse;
       
    54 }
       
    55 
       
    56 // NOTE densePacking != iIsFormControl  (i.e. Dialogs are dense packed)
       
    57 
       
    58 EXPORT_C CEikCapCArray::CEikCapCArray(TInt aGranularity)
       
    59 	: CArrayPtrFlat<CEikCaptionedControl>(aGranularity)
       
    60 	{
       
    61 	__DECLARE_NAME(_S("CEikCapCArray"));
       
    62 	}
       
    63 
       
    64 EXPORT_C CEikCapCArray::~CEikCapCArray()
       
    65 	{
       
    66 	delete iExtension;
       
    67 	ResetAndDestroy();
       
    68 	}
       
    69 
       
    70 EXPORT_C void CEikCapCArray::DeleteLine(TInt aIndex)
       
    71 	{		
       
    72 	// Changed the deleting order to fix TSW Error EKMA-7ES98G
       
    73 	// so that now the item is removed from the array first,
       
    74 	// and only after that actually deleted.
       
    75 	CBase* tmp = ((*this)[aIndex]);
       
    76 	Delete(aIndex);
       
    77 	delete tmp;
       
    78 	}
       
    79 
       
    80 EXPORT_C void CEikCapCArray::SetDensePacking(TBool aDensePacking)
       
    81 	{
       
    82 	iDensePacking=aDensePacking;
       
    83 	}
       
    84 
       
    85 
       
    86 void CEikCapCArray::CreateExtensionL()
       
    87 {
       
    88 	iExtension = new(ELeave) CEikCapCArrayExtension;
       
    89 }
       
    90 CEikCapCArrayExtension *CEikCapCArray::ExtensionOrNull() const
       
    91 {
       
    92 	if (!iExtension)
       
    93 		{
       
    94 		TRAP_IGNORE(const_cast<CEikCapCArray*>(this)->CreateExtensionL());
       
    95 		}
       
    96 	return iExtension;
       
    97 }
       
    98 
       
    99 TInt CEikCapCArray::NumberOfTextLines() const
       
   100 {
       
   101 	CEikCaptionedControl *firstCapCC = Count() > 0 ? (*this)[0] : NULL;
       
   102 	const CEikDialogPage *dialogPage = firstCapCC ? firstCapCC->DialogPage() : NULL;
       
   103     CEikDialogPage::TFormLayoutSelection ret = CEikDialogPage::ESingle;
       
   104 	if ( dialogPage )
       
   105 		ret = dialogPage->FormLayout();
       
   106 
       
   107 	TInt lines = 0;
       
   108 	for(TInt i = 0; i<Count(); i++)
       
   109 		{
       
   110 			TInt num_of_lines = 0;
       
   111 			CEikCaptionedControl *line = (*this)[i];
       
   112 			if (ret == CEikDialogPage::ESingle)
       
   113 					{
       
   114 					//line->MinimumSize(); // ensures NumberOfLines() is valid.
       
   115 					TInt h = line->NumberOfLinesForScrollBar();
       
   116 					num_of_lines = h;
       
   117 					}
       
   118 			else if (ret == CEikDialogPage::EDouble)
       
   119 					{
       
   120 					//line->MinimumSize(); // ensures NumberOfLines() is valid.
       
   121 					TInt h = line->NumberOfLinesForScrollBar();
       
   122 					num_of_lines = h; // one for title
       
   123 					}	
       
   124 		lines += num_of_lines;
       
   125 	}
       
   126 	return lines;
       
   127 }
       
   128 
       
   129 TInt CEikCapCArray::NumberOfTextLinesBeforeLine(TInt aLine) const
       
   130 {
       
   131 	CEikCaptionedControl *firstCapCC = Count() > 0 ? (*this)[0] : NULL;
       
   132 	const CEikDialogPage *dialogPage = firstCapCC ? firstCapCC->DialogPage() : NULL;
       
   133     CEikDialogPage::TFormLayoutSelection ret = CEikDialogPage::ESingle;
       
   134 	if ( dialogPage )
       
   135 		ret = dialogPage->FormLayout();
       
   136 
       
   137 	TInt lines = 0;
       
   138 	for(TInt i = 0; i<aLine; i++)
       
   139 		{
       
   140 			TInt num_of_lines = 0;
       
   141 			CEikCaptionedControl *line = (*this)[i];
       
   142 			if (ret == CEikDialogPage::ESingle)
       
   143 					{
       
   144 					//line->MinimumSize(); // ensures NumberOfLines() is valid.
       
   145 					TInt h = line->NumberOfLinesForScrollBar();
       
   146 					num_of_lines = h;
       
   147 					}
       
   148 			else if (ret == CEikDialogPage::EDouble)
       
   149 					{
       
   150 					//line->MinimumSize(); // ensures NumberOfLines() is valid.
       
   151 					TInt h = line->NumberOfLinesForScrollBar();
       
   152 					num_of_lines = h; // one for title
       
   153 					}	
       
   154 		lines += num_of_lines;
       
   155 	}
       
   156 	return lines;
       
   157 
       
   158 }
       
   159 
       
   160 TInt CEikCapCArray::FindItemFromTextLine(TInt aTextLine) const
       
   161 	{
       
   162 	CEikCaptionedControl *firstCapCC = Count() > 0 ? (*this)[0] : NULL;
       
   163 	const CEikDialogPage *dialogPage = firstCapCC ? firstCapCC->DialogPage() : NULL;
       
   164     CEikDialogPage::TFormLayoutSelection ret = CEikDialogPage::ESingle;
       
   165 	if ( dialogPage )
       
   166 		ret = dialogPage->FormLayout();
       
   167 
       
   168 	TInt lines = 0;
       
   169 	TInt i = 0;
       
   170 	for(i = 0; i<Count(); i++)
       
   171 		{
       
   172 			TInt num_of_lines = 0;
       
   173 			CEikCaptionedControl *line = (*this)[i];
       
   174 			if (ret == CEikDialogPage::ESingle)
       
   175 					{
       
   176 					//line->MinimumSize(); // ensures NumberOfLines() is valid.
       
   177 					TInt h = line->NumberOfLinesForScrollBar();
       
   178 					num_of_lines = h;
       
   179 					}
       
   180 			else if (ret == CEikDialogPage::EDouble)
       
   181 					{
       
   182 					//line->MinimumSize(); // ensures NumberOfLines() is valid.
       
   183 					TInt h = line->NumberOfLinesForScrollBar();
       
   184 					num_of_lines = h; // one for title
       
   185 					}	
       
   186 		lines += num_of_lines;
       
   187 		if (lines > aTextLine)
       
   188 			break;
       
   189 	}
       
   190 	return i;
       
   191 	}
       
   192 /**
       
   193  *  Calculate the size of all the component controls stacked vertically.
       
   194  *  For Avkon Forms the controls overlap by 2 pixels (hard coded)
       
   195  */
       
   196 EXPORT_C TSize CEikCapCArray::MinimumSize()
       
   197 	{
       
   198 	TSize size(0,0);
       
   199 
       
   200 	CEikCaptionedControl *firstCapCC = Count() > 0 ? (*this)[0] : NULL;
       
   201 	if (firstCapCC && firstCapCC->iIsFormControl)
       
   202 		{ // we're inside form
       
   203 	    // Minimumsize needs to be called even though we wouldnt use the result (at least it calculates the number of lines)
       
   204 		// TP HACK START (made because MinimumSize() is not good name for situations where content dimensions are desired)
       
   205 		TInt height = 0;
       
   206 		TInt width = 0;
       
   207 		TRect parentRect = Rect();
       
   208 		TSize lineSize; // absolute size, minimumSize = maximumSize = LAF size
       
   209 		for(TInt i=0;i<Count();i++)
       
   210 			{
       
   211 			TInt gap = 0; // not possible to get this from LAF. (should be 0.5u or something)
       
   212 			CEikCaptionedControl *line = (*this)[i];
       
   213 				TAknWindowLineLayout layout;
       
   214 			const CEikDialogPage *dialogPage = firstCapCC->DialogPage();
       
   215 		    CEikDialogPage::TFormLayoutSelection ret = CEikDialogPage::ESingle;
       
   216 			if ( dialogPage )
       
   217 				ret = dialogPage->FormLayout();
       
   218 			if (ret == CEikDialogPage::ESingle)
       
   219 					{
       
   220 					lineSize = line->MinimumSize(); // ensures NumberOfLines() is valid.
       
   221 					}
       
   222 			else if (ret == CEikDialogPage::EDouble)
       
   223 					{
       
   224 					lineSize = line->MinimumSize(); // ensures NumberOfLines() is valid.
       
   225 					}	
       
   226 			height += lineSize.iHeight + gap;
       
   227 			width = lineSize.iWidth;
       
   228 			}
       
   229 		size = TSize(width,height);
       
   230 		}
       
   231 	else
       
   232 		{
       
   233 
       
   234 	TInt wholeWidth=0;
       
   235 	const TInt count=Count();
       
   236 	const TInt topMargin=iDensePacking ? KAknNoTopMargin : KAknTopMargin;
       
   237 	const TInt bottomMargin = iDensePacking ? KAknNoTopMargin : KAknTopMargin ;
       
   238 	const TInt verticalSpacing=iDensePacking ? KVerticalSpacingSquash : KVerticalSpacing;
       
   239 	TInt deltaHeight=0;
       
   240 	CEikCapCArrayExtension *extension = ExtensionOrNull();
       
   241 	if (!extension) return TSize(30,30); // OOM
       
   242 	for (TInt ii=0;ii<count;++ii)
       
   243 		{
       
   244 		CEikCaptionedControl* line=(*this)[ii];
       
   245 		TSize thisSize=line->MinimumSize();
       
   246 		TInt thisDeltaHeight=thisSize.iHeight+verticalSpacing;
       
   247 		if (deltaHeight<thisDeltaHeight)
       
   248 			deltaHeight=thisDeltaHeight;
       
   249 		const TInt thisCaptionWidth=line->iCaptionWidth;
       
   250 		if (!(line->LatentGroupLineFollows()))
       
   251 			{
       
   252 			size.iHeight+=deltaHeight;
       
   253 			deltaHeight=0;
       
   254 			}
       
   255 		if (!thisCaptionWidth)
       
   256 			{
       
   257 			if (wholeWidth<thisSize.iWidth)
       
   258 				wholeWidth=thisSize.iWidth;
       
   259 			}
       
   260 		else
       
   261 			{
       
   262 			thisSize.iWidth-=thisCaptionWidth;
       
   263 			if (extension->iCaptionWidth<thisCaptionWidth)
       
   264 				extension->iCaptionWidth=thisCaptionWidth;
       
   265 			if (size.iWidth<thisSize.iWidth)
       
   266 				size.iWidth=thisSize.iWidth;
       
   267 			}
       
   268 		}
       
   269 	size.iWidth+=extension->iCaptionWidth;
       
   270 	if (size.iWidth<wholeWidth)
       
   271 		size.iWidth=wholeWidth;
       
   272 	// If the total height is zero don't bother adding a top margin
       
   273 	if ( size.iHeight > 0 )
       
   274 		{
       
   275 		size.iHeight+=( topMargin + bottomMargin ) ;
       
   276 		size.iHeight+=2 ;  // (we have included one too many '-2's)
       
   277 		}
       
   278 	}
       
   279 	return size;
       
   280 	}
       
   281 
       
   282 
       
   283 /**
       
   284  * Position all of the component controls in a vertical pile.
       
   285  * For Avkon Forms the controls overlap by two pixels.  (hard coded)
       
   286  */
       
   287 TRect CEikCapCArray::Rect() const
       
   288 {
       
   289 	CEikCapCArrayExtension *ext = ExtensionOrNull();
       
   290 	if (ext)
       
   291 		return ext->iRect;
       
   292 	else
       
   293 		return TRect(0,0, 100,100); // oom
       
   294 }
       
   295 
       
   296 TBool CEikCapCArray::CalcItemIndexes(TInt &aTopItemIndex, TInt &aMiddleItemIndex, TInt &aBottomItemIndex, TSize aAreaSize)
       
   297 { // calculates last item that still fits to the area's size
       
   298 	TBool switchDir = EFalse;
       
   299 	TInt i;
       
   300 	TInt reservedHeight = 0;
       
   301 	TInt newTop = aTopItemIndex, newMiddle = 1, newBottom = aBottomItemIndex;
       
   302 	const TInt count = Count();
       
   303 	CEikCaptionedControl *firstCapCC = Count() > 0 ? (*this)[0] : NULL;
       
   304 	TInt num = 0;
       
   305 
       
   306 	if (newTop == -1) { newTop = Count() - newMiddle - newBottom; }
       
   307 	if (newBottom == -1) { newBottom = Count() - newTop - newMiddle; }
       
   308 
       
   309 
       
   310 	if (aTopItemIndex != -1)
       
   311 		{
       
   312 		num = count - aTopItemIndex;
       
   313 		}
       
   314 	if (aBottomItemIndex != -1)
       
   315 		{
       
   316 		num = count - aBottomItemIndex;
       
   317 		}
       
   318 	for (i = 0; i < num; i++)
       
   319 		{
       
   320 		TInt index = 0;
       
   321 		if (aTopItemIndex != -1)
       
   322 			{
       
   323 			index = i + aTopItemIndex;
       
   324 			}
       
   325 		else if (aBottomItemIndex != -1)
       
   326 			{
       
   327 			index = count - 1 - aBottomItemIndex - i;
       
   328 			}
       
   329 		CEikCaptionedControl* line=(*this)[index];
       
   330 
       
   331 		const CEikDialogPage *dialogPage = firstCapCC->DialogPage();
       
   332 	    CEikDialogPage::TFormLayoutSelection ret = CEikDialogPage::ESingle;
       
   333 		if ( dialogPage )
       
   334 			ret = dialogPage->FormLayout();
       
   335 		TAknWindowLineLayout layout;
       
   336 		if (ret == CEikDialogPage::ESingle)
       
   337 			{
       
   338 			TInt height = line->NumberOfLines();
       
   339 			if (height < 1) height = 1;
       
   340 			if (IsPopupField(line))
       
   341 				{
       
   342 				layout = AknLayoutScalable_Avkon::form_field_popup_pane(height-1).LayoutLine();
       
   343 				}
       
   344 				else
       
   345 				{	
       
   346 				layout = AknLayoutScalable_Avkon::form_field_data_pane(height-1).LayoutLine();
       
   347 				}
       
   348 			}
       
   349 		else if (ret == CEikDialogPage::EDouble)
       
   350 			{
       
   351 			TInt height = line->NumberOfLines();
       
   352 			if (height < 1) height = 1;
       
   353 			if (IsPopupField(line))
       
   354 				{
       
   355 				layout = AknLayoutScalable_Avkon::form_field_popup_wide_pane(height-1).LayoutLine();
       
   356 				}
       
   357 				else
       
   358 				{
       
   359 				layout = AknLayoutScalable_Avkon::form_field_data_wide_pane(height-1).LayoutLine();
       
   360 				}
       
   361 			}	
       
   362 		else
       
   363 			{
       
   364 			// should Panic() here 
       
   365 			}
       
   366 		TRect rect = TRect(TPoint(0,0), aAreaSize);
       
   367 		TAknLayoutRect layoutRect;
       
   368 		layoutRect.LayoutRect(rect, layout);
       
   369 		TInt height2 = layoutRect.Rect().Height();
       
   370 		reservedHeight += height2;
       
   371 
       
   372 		if (reservedHeight > aAreaSize.iHeight)
       
   373 			{
       
   374 			break;
       
   375 			}
       
   376 
       
   377 
       
   378 		newMiddle = i + 1;
       
   379 		if (aTopItemIndex == -1)
       
   380 			{
       
   381 			newTop = count - i - 1 - aBottomItemIndex;
       
   382 			}
       
   383 		if (aBottomItemIndex == -1)
       
   384 			{
       
   385 			newBottom = count - i - 1 - aTopItemIndex;
       
   386 			}
       
   387 
       
   388 		}	
       
   389 	if (reservedHeight <= aAreaSize.iHeight)
       
   390 		{
       
   391 		// 2nd loop for case where item sizes have changed; makes sure screen is full.
       
   392 		for(int i = 0; newBottom > 0 && aTopItemIndex == -1 || newTop > 0 && aBottomItemIndex == -1; i++)
       
   393 			{
       
   394 			switchDir = ETrue;
       
   395 			TInt index = 0;
       
   396 			if (aBottomItemIndex == -1)
       
   397 				{
       
   398 				newMiddle ++;
       
   399 				newTop --;
       
   400 				index = newTop;
       
   401 				}
       
   402 			if (aTopItemIndex == -1)
       
   403 				{
       
   404 				newMiddle ++;
       
   405 				newBottom --;
       
   406 				index = count - 1 - newBottom;
       
   407 				}
       
   408 			CEikCaptionedControl* line=(*this)[index];
       
   409 
       
   410 			const CEikDialogPage *dialogPage = firstCapCC->DialogPage();
       
   411 		    CEikDialogPage::TFormLayoutSelection ret = CEikDialogPage::ESingle;
       
   412 			if ( dialogPage )
       
   413 				ret = dialogPage->FormLayout();
       
   414 			TAknWindowLineLayout layout;
       
   415 			if (ret == CEikDialogPage::ESingle)
       
   416 				{
       
   417 				TInt height = line->NumberOfLines();
       
   418 				if (height < 1) height = 1;
       
   419 			if (IsPopupField(line))
       
   420 				{
       
   421 				layout = AknLayoutScalable_Avkon::form_field_popup_pane(height-1).LayoutLine();
       
   422 				}
       
   423 				else
       
   424 				{	
       
   425 				layout = AknLayoutScalable_Avkon::form_field_data_pane(height-1).LayoutLine();
       
   426 				}
       
   427 				}
       
   428 			else if (ret == CEikDialogPage::EDouble)
       
   429 				{
       
   430 				TInt height = line->NumberOfLines();
       
   431 				if (height < 1) height = 1;
       
   432 			if (IsPopupField(line))
       
   433 				{
       
   434 				layout = AknLayoutScalable_Avkon::form_field_popup_wide_pane(height-1).LayoutLine();
       
   435 				}
       
   436 				else
       
   437 				{
       
   438 				layout = AknLayoutScalable_Avkon::form_field_data_wide_pane(height-1).LayoutLine();
       
   439 				}
       
   440 				}	
       
   441 			else
       
   442 				{
       
   443 				// should Panic() here 
       
   444 				}
       
   445 			TRect rect = TRect(TPoint(0,0), aAreaSize);
       
   446 			TAknLayoutRect layoutRect;
       
   447 			layoutRect.LayoutRect(rect, layout);
       
   448 			TInt height2 = layoutRect.Rect().Height();
       
   449 
       
   450 			reservedHeight += height2;
       
   451 
       
   452 
       
   453 			if (reservedHeight > aAreaSize.iHeight)
       
   454 				break;
       
   455 
       
   456 			}
       
   457 		}
       
   458 	aTopItemIndex = newTop;
       
   459 	aMiddleItemIndex = newMiddle;
       
   460 	aBottomItemIndex = newBottom;
       
   461 	return switchDir;
       
   462 }
       
   463 
       
   464 EXPORT_C void CEikCapCArray::SetRect(const TRect &aRect)
       
   465 {
       
   466 	SetRect(aRect, 0, -1, -1);
       
   467 }
       
   468 
       
   469 /**
       
   470  * If aControl is an edwin, set its clipping rect to empty. This
       
   471  * will disable the text hiding.
       
   472  */
       
   473 static void ResetHides(CEikCaptionedControl *aControl)
       
   474 	{
       
   475 	aControl->SetPartiallyVisible( EFalse );
       
   476 	if (aControl->ControlIsAnEdwin(aControl->iControlType))
       
   477 		{
       
   478 		CEikEdwin *edwin = (CEikEdwin*)aControl->iControl;
       
   479 		edwin->SetTextLinesRect(TRect());
       
   480 		}
       
   481 	}
       
   482 
       
   483 /**
       
   484  * Sets a clipping rectangle for hiding the whole or a part of edwin's text.
       
   485  *
       
   486  * The reason for using this function is the multiline edwins. The text inside
       
   487  * an edwin can be broken to two or more lines, which must be hidden or shown 
       
   488  * independently from each other. That is why it is not enough just to move
       
   489  * the whole edwin out of the screen.
       
   490  *
       
   491  * @param aClipRect The clipping rect for edwin's text. An empty rect disables 
       
   492  *   hiding.
       
   493  *
       
   494  * @return How many subcontrols were hidden
       
   495  */
       
   496 static TInt HideLines_Edwin(CEikEdwin *aEdwin, TRect aClipRect)
       
   497 	{
       
   498 	aEdwin->SetTextLinesRect(aClipRect);
       
   499     
       
   500     // Create rects of the first and last edwin lines
       
   501     TPoint edwinTl( aEdwin->Rect().iTl );
       
   502     TPoint edwinBr( aEdwin->Rect().iBr );
       
   503     TRect textFirstLine;
       
   504     aEdwin->TextLayout()->GetLineRect(edwinTl.iY, textFirstLine);
       
   505     textFirstLine.Move( edwinTl.iX, edwinTl.iY + aEdwin->Margins().iTop );
       
   506     TRect textLastLine;
       
   507     aEdwin->TextLayout()->GetLineRect(edwinBr.iY, textLastLine);
       
   508     textLastLine.Move( edwinBr.iX, edwinBr.iY - aEdwin->Margins().iTop - textLastLine.Height() );
       
   509 
       
   510     // Check if at least one line fits to the clipping rect
       
   511 	if( aClipRect.Contains(textFirstLine.iTl) &&
       
   512 	    aClipRect.iBr.iY >= textFirstLine.iBr.iY )   // The first line fits
       
   513 	    return 0;
       
   514 	if( aClipRect.Contains(textLastLine.iTl) &&
       
   515 	    aClipRect.iBr.iY >= textLastLine.iBr.iY )   // The last line fits
       
   516 	    return 0;
       
   517 	return 1;
       
   518 	}
       
   519 
       
   520 /**
       
   521  * Tries to hide the specified control. The control will be hidden, if it doesn't
       
   522  * fit to the specified clipping rectangle. Checks if the control exists.
       
   523  *
       
   524  * @return How many subcontrols were hidden
       
   525  */
       
   526 static TInt HideLines_Ctrl(CCoeControl *aControl, TRect aClipRect)
       
   527 	{
       
   528 	if ( !aControl )
       
   529 	    return 1;   // It doesn't exist and hence not visible
       
   530 	TRect rect( aControl->Rect() );
       
   531 	if ( !aClipRect.Contains(rect.iTl) || aClipRect.iBr.iY <= rect.iBr.iY )
       
   532 	    // Never use TRect::Contains() for checking the bottom right corner, see documentation
       
   533 		{
       
   534 		// hide it
       
   535 		aControl->SetPosition( TPoint(-666,-666) );
       
   536 		return 1;
       
   537 		}
       
   538     else
       
   539         return 0;
       
   540 	}
       
   541 
       
   542 /**
       
   543  * Get vertically minimal rectangle of the two given.
       
   544  *
       
   545  * Vertically reduces aRect1 by aRect2's dangling part, if aRect2
       
   546  * doesn't fit to aRect1.
       
   547  *
       
   548  * Sets aRect1 to the resulting minimal rectangle.
       
   549  */	
       
   550 static void GetVertMinRect( TRect& aRect1, const TRect aRect2 )
       
   551     {
       
   552     // If aRect2's top doesn't fit, lower aRect1's top
       
   553     if( aRect2.iTl.iY < aRect1.iTl.iY )
       
   554         aRect1.iTl.iY = Max( aRect1.iTl.iY, aRect2.iBr.iY );
       
   555     // If aRect2's bottom doesn't fit, raise aRect1's bottom
       
   556     if( aRect2.iBr.iY > aRect1.iBr.iY )
       
   557         aRect1.iBr.iY = Min( aRect1.iBr.iY, aRect2.iTl.iY );
       
   558     }
       
   559 
       
   560 /**
       
   561  * Hides the specified form line, if it does not fit to the specified clipping rectangle.
       
   562  * The function never hides focused editable lines. If the form layout is single, the whole
       
   563  * captioned control is hidden.
       
   564  * 
       
   565  * @param aControl The form line to be hidden
       
   566  * @param aClipRect The clipping rectangle
       
   567  *
       
   568  * @return How many subcontrols remained visible
       
   569  */	
       
   570 static TInt HideLines(CEikCaptionedControl *aControl, TRect aClipRect)
       
   571 	{
       
   572 	TInt visibleCtrls = 3; // Visible subcontrols after hiding
       
   573 	CEikCaptionedControl *currentdLine = aControl->DialogPage()->CurrentLine();
       
   574 	if( ( aControl == currentdLine ) && aControl->iIsEditable )
       
   575 	    {
       
   576 	    return visibleCtrls;
       
   577 	    }
       
   578 	
       
   579 	TBool isEdwin = aControl->ControlIsAnEdwin(aControl->iControlType);    
       
   580 	CEikEdwin* edwin( NULL );
       
   581 	if( isEdwin )
       
   582 	    edwin = (CEikEdwin*)aControl->iControl;
       
   583 	TRect ctrlRect( aControl->iControl->Rect() );
       
   584 		
       
   585 	if( isEdwin )
       
   586 	    {
       
   587 	    // Adjust rectangle only to the first line (with edwin's top margin)
       
   588 	    TRect textFirstLine;
       
   589 	    edwin->TextLayout()->GetLineRect(ctrlRect.iTl.iY, textFirstLine);
       
   590 	    ctrlRect.iBr.iY = ctrlRect.iTl.iY + edwin->Margins().iTop + textFirstLine.Height();
       
   591 	    }	    
       
   592 	
       
   593 	// Find the minimal clipping rectangle
       
   594 	if( aControl->iBitmap )
       
   595 	    GetVertMinRect( aClipRect, aControl->iBitmap->Rect() );
       
   596 	if( aControl->iCaption )
       
   597 	    GetVertMinRect( aClipRect, aControl->iCaption->Rect() );
       
   598 	GetVertMinRect( aClipRect, ctrlRect );
       
   599 	
       
   600 	
       
   601 	
       
   602 	// Try to hide all controls on the current line
       
   603 	aControl->SetPartiallyVisible( ETrue );
       
   604 	visibleCtrls -= HideLines_Ctrl( aControl->iBitmap, aClipRect );
       
   605 	visibleCtrls -= HideLines_Ctrl( aControl->iCaption, aClipRect );
       
   606 	if( isEdwin )
       
   607 		visibleCtrls -= HideLines_Edwin( edwin, aClipRect );
       
   608 	else
       
   609 		visibleCtrls -= HideLines_Ctrl( aControl->iControl, aClipRect );
       
   610     return visibleCtrls;
       
   611 	}
       
   612 
       
   613 /**
       
   614 * Places the dialog items according to the current visible window position.
       
   615 * When hiding items, uses SetExtent() instead of just SetPosition() in order to call
       
   616 * SizeChanged() of the moved item. For example, this is needed for the editor to
       
   617 * change its cursor accordingly.
       
   618 *
       
   619 * @param aRect Rectangle of the form window
       
   620 * @param aTop Number of items above the window
       
   621 * @param aMiddle Number of items inside the window
       
   622 * @param aBottom Number of items below the window
       
   623 *
       
   624 * Parameter value equal to -1 means that the parameter is not defined and will be
       
   625 * calculated automatically. Normally, either the top number or the bottom one
       
   626 * is only defined. If @a aTop is defined, the items will be placed from top downwards, leaving
       
   627 * @a aTop items above the window. If @a aBottom is defined, the items will be placed from bottom
       
   628 * upwards, leaving @a aBottom items below the window.
       
   629 *
       
   630 * This function panics, if neither @a aTop nor @a aBottom are defined.
       
   631 *
       
   632 * The function first checks if the provided @a aTop and @a aBottom are consistent with
       
   633 * the item sizes and the given window rectangle. If they are not, they will be
       
   634 * corrected. Usually, @a aTop and @a aBottom come out of sync with the item sizes
       
   635 * after the dynamic layout change.
       
   636 */
       
   637 void CEikCapCArray::SetRect(const TRect& aRect, TInt aTop, TInt /*aMiddle*/, TInt aBottom)
       
   638 	{
       
   639     TAknLayoutRect formtLayoutRect;
       
   640     formtLayoutRect.LayoutRect(aRect, AknLayoutScalable_Avkon::listscroll_form_pane().LayoutLine());
       
   641     formtLayoutRect.LayoutRect(formtLayoutRect.Rect(), AknLayoutScalable_Avkon::list_form_gen_pane().LayoutLine());
       
   642     TRect formRect = formtLayoutRect.Rect();
       
   643 	
       
   644 	CEikCapCArrayExtension *extension_or_null = ExtensionOrNull();
       
   645 	if (extension_or_null)
       
   646 		{
       
   647 		extension_or_null->iRect = formRect;
       
   648 		}
       
   649 
       
   650     // controls need to be placed in real locations if physics is enabled
       
   651     if ( Count() > 0 )
       
   652         {
       
   653         CEikCaptionedControl* control = (*this)[0];
       
   654         
       
   655         if ( control->DialogPage()->IsForm() )
       
   656             {
       
   657             SetRealRect( aRect, aTop, aBottom );
       
   658             return;
       
   659             }
       
   660         }
       
   661         
       
   662 	TBool topDefined = EFalse;   // top or bottom number defined?
       
   663 	if( aTop > -1 )
       
   664 	    {
       
   665 	    topDefined = ETrue;
       
   666 	    }
       
   667 	else if( aBottom > -1 )
       
   668 	    {
       
   669 	    topDefined = EFalse;
       
   670 	    }
       
   671 	else    // aBottom == aTop == -1
       
   672 	    {
       
   673 	    User::Panic( _L("CEikCapCArray::SetRect(): Neither top nor bottom items number defined"), EAknPanicInvalidValue );
       
   674 	    }
       
   675 	const TInt count = Count();
       
   676 	const TInt rectHeight = aRect.Height();
       
   677 	/**
       
   678 	* Special invisible points are used for placing the items that are
       
   679 	* outside the window. CCoeControl's invisible flag cannot be used,
       
   680 	* as it is controlled by third-party applications.
       
   681 	*/
       
   682 	const TPoint topInvisPoint( -10000, -10000 );
       
   683 	const TPoint bottomInvisPoint( 10000, 10000 );
       
   684 	
       
   685 	CEikCaptionedControl *firstCapCC = count > 0 ? (*this)[0] : NULL;
       
   686 	if( firstCapCC && firstCapCC->iIsFormControl )  // Forms
       
   687 		{
       
   688 		CEikCaptionedControl *selectedLine( NULL );
       
   689 		if( firstCapCC->DialogPage())
       
   690 	        selectedLine = firstCapCC->DialogPage()->CurrentLine();
       
   691 		
       
   692 		// Check height of items and the input parameters aTop and aBottom.
       
   693 		TInt rest = 0;  // number of the rest items without aTop or aBottom
       
   694 		TInt index = 0;
       
   695     	if( topDefined )
       
   696     	    {
       
   697     	    rest = count - aTop;
       
   698     	    index = aTop;
       
   699     	    }
       
   700     	else
       
   701     	    {
       
   702     	    rest = count - aBottom;
       
   703     	    index = rest - 1;
       
   704     	    }
       
   705 		TInt height = 0;
       
   706 		for( TInt ii = 0; ii < rest; ii++ )
       
   707 			{
       
   708     		CEikCaptionedControl* line = (*this)[index];
       
   709 		    height += line->MinimumSize().iHeight;  // Use MinimumSize() here as a protection from dynamic layout change
       
   710 		    if( height >= rectHeight )
       
   711                 break;  // Input params are OK
       
   712 		    topDefined? index++ : index--;
       
   713 		    }
       
   714 		/** 
       
   715 		* If the window contains too few items inside and there are still items outside,
       
   716 		* correct the input parameters @a aTop and @a aBottom to fill up the window.
       
   717 		*/
       
   718 		if( height < rectHeight )
       
   719 		    {
       
   720 		    if( topDefined && aTop > 0 )    // For top-down placement and there are items above the window
       
   721     		    {
       
   722     		    // Calculate height of controls above the window also
       
   723 		        for( TInt ii = 0; ii < aTop; ii++ )
       
   724 		            {
       
   725     		        CEikCaptionedControl* line = (*this)[ii];
       
   726 		            height += line->MinimumSize().iHeight;
       
   727         		    if( height >= rectHeight )  // All items don't fit to the window anyway
       
   728     		            {
       
   729         		        topDefined = EFalse;   // Reverse direction to bottom-up
       
   730         		        aBottom = 0;
       
   731                         break;
       
   732         		        }
       
   733 		            }
       
   734 		        if( height < rectHeight )  // All items fit to the window
       
   735     		        {
       
   736     		        aTop = 0; // Just place them from the first item
       
   737     		        }
       
   738     		    }
       
   739     	    else if( !topDefined )  // For bottom-up placement
       
   740     	        {
       
   741     		    topDefined = ETrue;   // Reverse direction to top-down
       
   742     		    aTop = 0;
       
   743     	        }
       
   744     	    }
       
   745 		
       
   746 		// Hiding items that are explicitly defined to be outside the window
       
   747 		TInt start;
       
   748 		TInt end;
       
   749 	    TPoint invisPoint;    // current invisible point, depends on placement direction
       
   750     	if( topDefined )
       
   751     	    {
       
   752     	    start = 0;
       
   753     	    end = aTop;
       
   754     	    invisPoint = topInvisPoint;
       
   755     	    }
       
   756     	else
       
   757     	    {
       
   758     	    start = count - aBottom;
       
   759     	    end = count;
       
   760     	    invisPoint = bottomInvisPoint;
       
   761     	    }
       
   762 		for( TInt ii = start; ii < end; ii++ )
       
   763 			{
       
   764 			CEikCaptionedControl* line = (*this)[ii];
       
   765 			line->SetPosition( invisPoint );
       
   766 			}
       
   767 		
       
   768 		// Setting rects for the rest of the items
       
   769     	if( topDefined )
       
   770     	    {
       
   771     	    rest = count - aTop;
       
   772     	    invisPoint = bottomInvisPoint;
       
   773     	    index = aTop;
       
   774     	    }
       
   775     	else
       
   776     	    {
       
   777     	    rest = count - aBottom;
       
   778     	    invisPoint = topInvisPoint;
       
   779     	    index = rest - 1;
       
   780     	    }
       
   781 		TInt reservedHeight = 0; // in pixels
       
   782 		TBool insideWindow = ETrue; // The current item is still inside the window
       
   783         TInt topY = 0;
       
   784         
       
   785 		
       
   786 		for( TInt ii = 0; ii < rest; ii++ )
       
   787 			{
       
   788     		CEikCaptionedControl* line = (*this)[index];
       
   789     		TSize lineSize( line->Size() );
       
   790 		    if( insideWindow )
       
   791 		        {
       
   792 			    ResetHides( line );
       
   793     		    if( topDefined )
       
   794     		        {   // Top-down placement
       
   795     		        topY = aRect.iTl.iY + reservedHeight;   
       
   796     		        }
       
   797     		    else
       
   798     		        {   // Bottom-up placement
       
   799     		        topY = aRect.iBr.iY - reservedHeight - lineSize.iHeight;
       
   800     		        }
       
   801     		    line->SetExtent( TPoint( formRect.iTl.iX, topY ), lineSize );
       
   802     			AknsUtils::RegisterControlPosition( line );
       
   803     			AknsUtils::RegisterControlPosition( line->iCaption );
       
   804     			AknsUtils::RegisterControlPosition( line->iControl );
       
   805     			AknsUtils::RegisterControlPosition( line->iTrailer );
       
   806     			AknsUtils::RegisterControlPosition( line->iBitmap );
       
   807     			reservedHeight += lineSize.iHeight;
       
   808     			/** 
       
   809     			* The control at a window edge is considered as partially-visible.
       
   810     			* Its subcontrols must be checked for visibility individually.
       
   811     			*/
       
   812     			if( reservedHeight > rectHeight )
       
   813     			    {
       
   814     			    TInt visibleSubctrls = HideLines( line, aRect );    // Check how many subcontrols stayed visible
       
   815     			    insideWindow = EFalse;
       
   816     			    /**
       
   817     			    * For the bottom-up placement:
       
   818     			    * if the window contains only an empty "partially-visible" control and a
       
   819     			    * a selected popup field, make the popup to hang at the top alone.
       
   820     			    */
       
   821     			    if( !topDefined && index < count - 1 ) // bottom-up and not last
       
   822     			        {
       
   823         			    CEikCaptionedControl* lineBelow = (*this)[index+1];
       
   824         			    if( visibleSubctrls == 0 && ii == 1 &&
       
   825         			        IsPopupField( lineBelow ) && lineBelow == selectedLine )
       
   826         			        {
       
   827             		        TRect popupRect( lineBelow->Rect() );
       
   828             		        TInt diff = aRect.iTl.iY - popupRect.iTl.iY; // negative
       
   829             		        popupRect.Move( 0, diff );
       
   830             		        lineBelow->SetRect( popupRect );
       
   831         			        }
       
   832     			        }
       
   833     			    }
       
   834 		        }
       
   835 		    else
       
   836 		        {
       
   837 	            line->SetPosition( invisPoint );
       
   838 		        }
       
   839 		    topDefined? index++ : index--;
       
   840 			}
       
   841 		}
       
   842 	else    // Dialogs other than forms:
       
   843 		{
       
   844     	TRect rect=aRect;
       
   845     	const TInt fullWidth=rect.iBr.iX-rect.iTl.iX;
       
   846     	const TInt count=Count();
       
   847     	const TInt topMargin=iDensePacking ? KAknNoTopMargin : KAknTopMargin;
       
   848     	const TInt verticalSpacing=iDensePacking ? KVerticalSpacingSquash : KVerticalSpacing;
       
   849     	rect.iTl.iY+=topMargin;
       
   850     	TInt deltaHeight=0;
       
   851     	for (TInt ii=0;ii<count;++ii)
       
   852     		{
       
   853     		CEikCaptionedControl* line=(*this)[ii];
       
   854     	    TSize thisSize=line->MinimumSize();
       
   855     		TInt thisDeltaHeight=thisSize.iHeight+verticalSpacing;
       
   856     		if (deltaHeight<thisDeltaHeight)
       
   857     			deltaHeight=thisDeltaHeight;
       
   858     		if (!(line->iCaptionWidth))
       
   859     			thisSize.iWidth=fullWidth;
       
   860     		else
       
   861     			{
       
   862     			CEikCapCArrayExtension *ext = ExtensionOrNull();
       
   863     			TInt deltaWidth = 0;
       
   864     			if (ext) 
       
   865     				deltaWidth = ext->iCaptionWidth-line->iCaptionWidth;
       
   866     			thisSize.iWidth+=deltaWidth;
       
   867     			if (ext)
       
   868     				line->iCaptionWidth=ext->iCaptionWidth;
       
   869     			else
       
   870     				line->iCaptionWidth = 0;
       
   871     			line->iMinSize.iWidth+=deltaWidth;
       
   872     			}
       
   873     		line->iFullWidth=fullWidth;
       
   874     	    line->SetExtent(rect.iTl,thisSize);
       
   875     		if (!(line->LatentGroupLineFollows()))
       
   876     			{
       
   877     			rect.iTl.iY+=deltaHeight;
       
   878     			deltaHeight=0;
       
   879     			}
       
   880     		}
       
   881 		}
       
   882 	}
       
   883 
       
   884 TInt CEikCapCArray::YPosToLine(const TRect &aRect, 
       
   885 							   TInt aTop, TInt aMiddle, TInt aBottom, 
       
   886 							   TInt aYCoord)
       
   887 	{
       
   888 	TInt top = aTop;
       
   889 	TInt middle = aMiddle;
       
   890 	TInt bottom = aBottom;
       
   891 	CalcItemIndexes(top, middle, bottom, aRect.Size());
       
   892 	
       
   893 	for(int i = top ; i < top+middle; i++)
       
   894 		{
       
   895 		CEikCaptionedControl *fst = (*this)[i];
       
   896 		if (aYCoord < fst->Rect().iTl.iY)
       
   897 			{
       
   898 			if (i > 0)
       
   899 				return i-1;
       
   900 			else
       
   901 				return KErrNotFound;
       
   902 			}
       
   903 		}
       
   904 	if (Count() == 0) return -1;
       
   905 	TInt ii = top+middle-1;
       
   906 	CEikCaptionedControl *last = (*this)[ii];
       
   907 	if ( aYCoord < last->Rect().iBr.iY )
       
   908 		{
       
   909 		return ii;
       
   910 		}
       
   911 	else
       
   912 		{
       
   913 		if ( ii+1 < Count() )
       
   914 		    {
       
   915 		    return ii+1;
       
   916 		    }
       
   917 		else if ( aYCoord > last->Rect().iBr.iY )
       
   918 		    {
       
   919 		    return KErrNotFound;
       
   920 		    }
       
   921 		else
       
   922 		    {
       
   923 		    return ii;
       
   924 		    }
       
   925 		}
       
   926 	}
       
   927 	
       
   928 EXPORT_C void CEikCapCArray::ResetMinimumSizes()
       
   929 	{
       
   930 	const TInt count=Count();
       
   931 	for (TInt ii=0;ii<count;++ii)
       
   932 		(*this)[ii]->ResetMinimumSizes();
       
   933 	}
       
   934 
       
   935 EXPORT_C TInt CEikCapCArray::LineIndexFromId(TInt aControlId) const
       
   936 	{
       
   937     const TInt count=Count();
       
   938     TInt ii=0;
       
   939     FOREVER
       
   940         {
       
   941         if (ii==count)
       
   942             return(KErrNotFound);
       
   943         if ((*this)[ii]->iId==aControlId)
       
   944             break;
       
   945 		ii++;
       
   946         }
       
   947     return(ii);
       
   948 	}
       
   949 
       
   950 EXPORT_C void CEikCapCArray::AdjustAllIds(TInt aControlIdDelta)
       
   951 	{
       
   952     const TInt count=Count();
       
   953 	for (TInt ii=0; ii<count; ii++)
       
   954 		(*this)[ii]->iId+=aControlIdDelta;
       
   955 	}
       
   956 
       
   957 EXPORT_C TInt CEikCapCArray::FindLineIndex(const CCoeControl* aControl) const
       
   958 	{
       
   959     const TInt count=Count();
       
   960     TInt ii=0;
       
   961 	while (ii<count)
       
   962 		{
       
   963 		CEikCaptionedControl* line=(*this)[ii];
       
   964 		if (line==aControl || line->iControl==aControl)
       
   965 			return(ii);
       
   966 		ii++;
       
   967 		}
       
   968 	return(KErrNotFound);
       
   969 	}
       
   970 
       
   971 // ---------------------------------------------------------------------------
       
   972 // CEikCapCArray::ScrollByPixels
       
   973 // ---------------------------------------------------------------------------
       
   974 //
       
   975 TInt CEikCapCArray::ScrollByPixels( TInt aDelta )
       
   976     {
       
   977     TInt count = Count();
       
   978     
       
   979     // Top and bottom of lines
       
   980     TInt topY = (*this)[0]->Rect().iTl.iY;
       
   981     TInt bottomY = (*this)[count - 1]->Rect().iBr.iY;
       
   982 
       
   983     TRect formRect( Rect() );
       
   984 
       
   985     if ( aDelta )
       
   986         {
       
   987         for( TInt i = 0; i < count; ++i )
       
   988             {
       
   989             CEikCaptionedControl* line = (*this)[i];
       
   990             TBool onDisplay = line->Rect().Intersects( formRect );
       
   991             TPoint position( line->Position() );
       
   992             position.iY += aDelta;
       
   993             
       
   994             line->SetPosition( position );
       
   995             
       
   996             onDisplay = onDisplay || line->Rect().Intersects( formRect );
       
   997             
       
   998             // Line is or was on display
       
   999             if ( ETrue /*onDisplay*/ )
       
  1000                 // Some controls, eg. slider and edwin don't handle
       
  1001                 // SetPosition properly. Workaround is to use SetRect,
       
  1002                 // which is slow as it does a whole layout for the control.
       
  1003                 // If form panning is ever speed optimized, captioned
       
  1004                 // control should me made to support SetPosition() correctly.
       
  1005                 {
       
  1006                 if ( line->ControlIsAPopfield( line->iControlType ) )
       
  1007                     {
       
  1008                     // Have to layout whole captioned control, otherwise
       
  1009                     // text doesn't move. Fix later popup field to move
       
  1010                     // properly.
       
  1011                     line->SetRect( line->Rect() );
       
  1012                     }
       
  1013                 else
       
  1014                     {
       
  1015                     line->iControl->SetRect( line->iControl->Rect() );
       
  1016                     }
       
  1017                 line->DrawDeferred();
       
  1018                 //line->DrawNow();
       
  1019                 }
       
  1020             }
       
  1021         }
       
  1022 
       
  1023     return aDelta;
       
  1024     }
       
  1025 
       
  1026 // ---------------------------------------------------------------------------
       
  1027 // CEikCapCArray::SetRealRect
       
  1028 // ---------------------------------------------------------------------------
       
  1029 //
       
  1030 void CEikCapCArray::SetRealRect( 
       
  1031 		const TRect& /*aRect*/, TInt /*aTop*/, TInt /*aBottom*/ )
       
  1032     {
       
  1033     TInt count = Count();
       
  1034     const TPoint virtualTl( 1000, 0 );
       
  1035     TPoint skinLocation( 0, 0 );
       
  1036     CEikCaptionedControl* currentLine = (*this)[0]->DialogPage()->CurrentLine();
       
  1037     
       
  1038     for ( TInt i = 0; i < count; ++i )
       
  1039         {
       
  1040         CEikCaptionedControl* line = (*this)[i];
       
  1041         
       
  1042         if ( line != currentLine )
       
  1043             {
       
  1044             line->SetExtent( virtualTl, line->Size() );
       
  1045             }
       
  1046         else
       
  1047             {
       
  1048         	line->SetExtent( line->Position(), line->Size() ); 
       
  1049             }
       
  1050         
       
  1051         skinLocation.iY += line->Size().iHeight;
       
  1052         
       
  1053         AknsUtils::RegisterControlPosition( line, skinLocation );
       
  1054         AknsUtils::RegisterControlPosition( line->iCaption, skinLocation );
       
  1055         AknsUtils::RegisterControlPosition( line->iControl, skinLocation );
       
  1056         AknsUtils::RegisterControlPosition( line->iTrailer, skinLocation );
       
  1057         AknsUtils::RegisterControlPosition( line->iBitmap, skinLocation );
       
  1058         }
       
  1059     }
       
  1060 
       
  1061 
       
  1062 // ---------------------------------------------------------------------------
       
  1063 // CEikCapCArray::YPositionToLineIndex
       
  1064 // ---------------------------------------------------------------------------
       
  1065 //
       
  1066 TInt CEikCapCArray::YPositionToLineIndex( TInt aYPos ) const
       
  1067     {
       
  1068     TInt count = Count();
       
  1069     TInt topY = 0;
       
  1070     TInt bottomY = 0;
       
  1071     
       
  1072     for ( TInt i = 0; i < count; ++i )
       
  1073         {
       
  1074         topY = bottomY;           
       
  1075         bottomY = topY + (*this)[i]->Size().iHeight;
       
  1076         
       
  1077         if ( aYPos >= topY && aYPos < bottomY )
       
  1078             {
       
  1079             return i;
       
  1080             }
       
  1081         }
       
  1082 
       
  1083     return KErrNotFound;
       
  1084     }
       
  1085 
       
  1086 
       
  1087 // ---------------------------------------------------------------------------
       
  1088 // CEikCapCArray::LineIndexToYPosition
       
  1089 // ---------------------------------------------------------------------------
       
  1090 //
       
  1091 TInt CEikCapCArray::LineIndexToYPosition( TInt aLine, TInt aTopY ) const
       
  1092     {
       
  1093     TInt topY = 0;
       
  1094     TInt bottomY = 0;
       
  1095     
       
  1096     for ( TInt i = 0; i <= aLine; ++i )
       
  1097         {
       
  1098         topY = bottomY;
       
  1099         bottomY = topY + (*this)[i]->Size().iHeight;
       
  1100         }
       
  1101 
       
  1102     return topY - aTopY;
       
  1103     }
       
  1104 
       
  1105 
       
  1106 // ---------------------------------------------------------------------------
       
  1107 // CEikCapCArray::MoveLineToScreen
       
  1108 // ---------------------------------------------------------------------------
       
  1109 //
       
  1110 void CEikCapCArray::MoveLineToScreen( TInt aLine, TInt aTopY, TBool aVisible )
       
  1111     {
       
  1112     if ( aLine != -1 && aLine < Count() )
       
  1113         {
       
  1114         CEikCaptionedControl* line = (*this)[aLine];
       
  1115         TPoint topLeft( 1000, 0 );
       
  1116         
       
  1117         if ( aVisible )
       
  1118             {
       
  1119             topLeft.SetXY( Rect().iTl.iX, LineIndexToYPosition( aLine, aTopY ) );
       
  1120             }
       
  1121         
       
  1122         line->SetRect( TRect( topLeft, line->Size() ) );
       
  1123         }
       
  1124     }
       
  1125 
       
  1126 
       
  1127 // ---------------------------------------------------------------------------
       
  1128 // CEikCapCArray::FocusableLine
       
  1129 // ---------------------------------------------------------------------------
       
  1130 //
       
  1131 TInt CEikCapCArray::FocusableLine( TInt aCurrentLine, TInt aTopY )
       
  1132     {
       
  1133     TInt focusableLine = KErrNotFound;
       
  1134     
       
  1135     if ( aCurrentLine >= 0 && aCurrentLine < Count() )
       
  1136         {
       
  1137         TInt y = LineIndexToYPosition( aCurrentLine, aTopY );
       
  1138 
       
  1139         // if current line is visible on the screen the focus that
       
  1140         if ( y >= 0 && y <= Rect().Height() )
       
  1141             {
       
  1142             focusableLine = aCurrentLine;
       
  1143             }
       
  1144         else // otherwise return the topmost totally visible line
       
  1145             {
       
  1146             TInt topLine = YPositionToLineIndex( aTopY );
       
  1147             
       
  1148             if ( topLine != KErrNotFound && 
       
  1149                     (*this)[topLine]->Position().iY < aTopY )
       
  1150                 {
       
  1151                 if ( ( topLine + 1 ) < Count() )
       
  1152                     {
       
  1153                     ++topLine;
       
  1154                     }
       
  1155                 
       
  1156                 focusableLine = topLine;
       
  1157                 }
       
  1158             }
       
  1159         }
       
  1160     
       
  1161     return focusableLine;
       
  1162     }
       
  1163