uifw/EikStd/dlgsrc/EIKCAPCA.CPP
branchRCL_3
changeset 19 aecbbf00d063
parent 17 a1caeb42b3a3
child 20 d48ab3b357f1
--- a/uifw/EikStd/dlgsrc/EIKCAPCA.CPP	Thu Aug 19 10:11:06 2010 +0300
+++ b/uifw/EikStd/dlgsrc/EIKCAPCA.CPP	Tue Aug 31 15:28:30 2010 +0300
@@ -24,7 +24,6 @@
 #include <AknsUtils.h>
 #include <eikedwin.h>
 #include "AknPanic.h"
-#include "akntrace.h"
 
 const TInt KVerticalSpacing=-2;  // Avkon form controls overlap by two pixels!
 const TInt KVerticalSpacingSquash=0;
@@ -97,14 +96,105 @@
 	return iExtension;
 }
 
+TInt CEikCapCArray::NumberOfTextLines() const
+{
+	CEikCaptionedControl *firstCapCC = Count() > 0 ? (*this)[0] : NULL;
+	const CEikDialogPage *dialogPage = firstCapCC ? firstCapCC->DialogPage() : NULL;
+    CEikDialogPage::TFormLayoutSelection ret = CEikDialogPage::ESingle;
+	if ( dialogPage )
+		ret = dialogPage->FormLayout();
 
+	TInt lines = 0;
+	for(TInt i = 0; i<Count(); i++)
+		{
+			TInt num_of_lines = 0;
+			CEikCaptionedControl *line = (*this)[i];
+			if (ret == CEikDialogPage::ESingle)
+					{
+					//line->MinimumSize(); // ensures NumberOfLines() is valid.
+					TInt h = line->NumberOfLinesForScrollBar();
+					num_of_lines = h;
+					}
+			else if (ret == CEikDialogPage::EDouble)
+					{
+					//line->MinimumSize(); // ensures NumberOfLines() is valid.
+					TInt h = line->NumberOfLinesForScrollBar();
+					num_of_lines = h; // one for title
+					}	
+		lines += num_of_lines;
+	}
+	return lines;
+}
+
+TInt CEikCapCArray::NumberOfTextLinesBeforeLine(TInt aLine) const
+{
+	CEikCaptionedControl *firstCapCC = Count() > 0 ? (*this)[0] : NULL;
+	const CEikDialogPage *dialogPage = firstCapCC ? firstCapCC->DialogPage() : NULL;
+    CEikDialogPage::TFormLayoutSelection ret = CEikDialogPage::ESingle;
+	if ( dialogPage )
+		ret = dialogPage->FormLayout();
+
+	TInt lines = 0;
+	for(TInt i = 0; i<aLine; i++)
+		{
+			TInt num_of_lines = 0;
+			CEikCaptionedControl *line = (*this)[i];
+			if (ret == CEikDialogPage::ESingle)
+					{
+					//line->MinimumSize(); // ensures NumberOfLines() is valid.
+					TInt h = line->NumberOfLinesForScrollBar();
+					num_of_lines = h;
+					}
+			else if (ret == CEikDialogPage::EDouble)
+					{
+					//line->MinimumSize(); // ensures NumberOfLines() is valid.
+					TInt h = line->NumberOfLinesForScrollBar();
+					num_of_lines = h; // one for title
+					}	
+		lines += num_of_lines;
+	}
+	return lines;
+
+}
+
+TInt CEikCapCArray::FindItemFromTextLine(TInt aTextLine) const
+	{
+	CEikCaptionedControl *firstCapCC = Count() > 0 ? (*this)[0] : NULL;
+	const CEikDialogPage *dialogPage = firstCapCC ? firstCapCC->DialogPage() : NULL;
+    CEikDialogPage::TFormLayoutSelection ret = CEikDialogPage::ESingle;
+	if ( dialogPage )
+		ret = dialogPage->FormLayout();
+
+	TInt lines = 0;
+	TInt i = 0;
+	for(i = 0; i<Count(); i++)
+		{
+			TInt num_of_lines = 0;
+			CEikCaptionedControl *line = (*this)[i];
+			if (ret == CEikDialogPage::ESingle)
+					{
+					//line->MinimumSize(); // ensures NumberOfLines() is valid.
+					TInt h = line->NumberOfLinesForScrollBar();
+					num_of_lines = h;
+					}
+			else if (ret == CEikDialogPage::EDouble)
+					{
+					//line->MinimumSize(); // ensures NumberOfLines() is valid.
+					TInt h = line->NumberOfLinesForScrollBar();
+					num_of_lines = h; // one for title
+					}	
+		lines += num_of_lines;
+		if (lines > aTextLine)
+			break;
+	}
+	return i;
+	}
 /**
  *  Calculate the size of all the component controls stacked vertically.
  *  For Avkon Forms the controls overlap by 2 pixels (hard coded)
  */
 EXPORT_C TSize CEikCapCArray::MinimumSize()
 	{
-	_AKNTRACE_FUNC_ENTER;
 	TSize size(0,0);
 
 	CEikCaptionedControl *firstCapCC = Count() > 0 ? (*this)[0] : NULL;
@@ -114,65 +204,78 @@
 		// TP HACK START (made because MinimumSize() is not good name for situations where content dimensions are desired)
 		TInt height = 0;
 		TInt width = 0;
+		TRect parentRect = Rect();
 		TSize lineSize; // absolute size, minimumSize = maximumSize = LAF size
 		for(TInt i=0;i<Count();i++)
 			{
+			TInt gap = 0; // not possible to get this from LAF. (should be 0.5u or something)
 			CEikCaptionedControl *line = (*this)[i];
-            lineSize = line->MinimumSize(); // ensures NumberOfLines() is valid.
-			height += lineSize.iHeight;
+				TAknWindowLineLayout layout;
+			const CEikDialogPage *dialogPage = firstCapCC->DialogPage();
+		    CEikDialogPage::TFormLayoutSelection ret = CEikDialogPage::ESingle;
+			if ( dialogPage )
+				ret = dialogPage->FormLayout();
+			if (ret == CEikDialogPage::ESingle)
+					{
+					lineSize = line->MinimumSize(); // ensures NumberOfLines() is valid.
+					}
+			else if (ret == CEikDialogPage::EDouble)
+					{
+					lineSize = line->MinimumSize(); // ensures NumberOfLines() is valid.
+					}	
+			height += lineSize.iHeight + gap;
 			width = lineSize.iWidth;
 			}
-		size.SetSize(width,height);
+		size = TSize(width,height);
 		}
 	else
 		{
-        TInt wholeWidth=0;
-        const TInt count=Count();
-        const TInt topMargin=iDensePacking ? KAknNoTopMargin : KAknTopMargin;
-        const TInt bottomMargin = iDensePacking ? KAknNoTopMargin : KAknTopMargin ;
-        const TInt verticalSpacing=iDensePacking ? KVerticalSpacingSquash : KVerticalSpacing;
-        TInt deltaHeight=0;
-        CEikCapCArrayExtension *extension = ExtensionOrNull();
-        if (!extension) return TSize(30,30); // OOM
-        for (TInt ii=0;ii<count;++ii)
-            {
-            CEikCaptionedControl* line=(*this)[ii];
-            TSize thisSize=line->MinimumSize();
-            TInt thisDeltaHeight=thisSize.iHeight+verticalSpacing;
-            if (deltaHeight<thisDeltaHeight)
-                deltaHeight=thisDeltaHeight;
-            const TInt thisCaptionWidth=line->iCaptionWidth;
-            if (!(line->LatentGroupLineFollows()))
-                {
-                size.iHeight+=deltaHeight;
-                deltaHeight=0;
-                }
-            if (!thisCaptionWidth)
-                {
-                if (wholeWidth<thisSize.iWidth)
-                    wholeWidth=thisSize.iWidth;
-                }
-            else
-                {
-                thisSize.iWidth-=thisCaptionWidth;
-                if (extension->iCaptionWidth<thisCaptionWidth)
-                    extension->iCaptionWidth=thisCaptionWidth;
-                if (size.iWidth<thisSize.iWidth)
-                    size.iWidth=thisSize.iWidth;
-                }
-            }
-        size.iWidth+=extension->iCaptionWidth;
-        if (size.iWidth<wholeWidth)
-            size.iWidth=wholeWidth;
-        // If the total height is zero don't bother adding a top margin
-        if ( size.iHeight > 0 )
-            {
-            size.iHeight+=( topMargin + bottomMargin ) ;
-            size.iHeight+=2 ;  // (we have included one too many '-2's)
-            }
-        }
-    _AKNTRACE( "The Size : ( %d, %d ) ", size.iHeight, size.iWidth );
-	_AKNTRACE_FUNC_EXIT;
+
+	TInt wholeWidth=0;
+	const TInt count=Count();
+	const TInt topMargin=iDensePacking ? KAknNoTopMargin : KAknTopMargin;
+	const TInt bottomMargin = iDensePacking ? KAknNoTopMargin : KAknTopMargin ;
+	const TInt verticalSpacing=iDensePacking ? KVerticalSpacingSquash : KVerticalSpacing;
+	TInt deltaHeight=0;
+	CEikCapCArrayExtension *extension = ExtensionOrNull();
+	if (!extension) return TSize(30,30); // OOM
+	for (TInt ii=0;ii<count;++ii)
+		{
+		CEikCaptionedControl* line=(*this)[ii];
+		TSize thisSize=line->MinimumSize();
+		TInt thisDeltaHeight=thisSize.iHeight+verticalSpacing;
+		if (deltaHeight<thisDeltaHeight)
+			deltaHeight=thisDeltaHeight;
+		const TInt thisCaptionWidth=line->iCaptionWidth;
+		if (!(line->LatentGroupLineFollows()))
+			{
+			size.iHeight+=deltaHeight;
+			deltaHeight=0;
+			}
+		if (!thisCaptionWidth)
+			{
+			if (wholeWidth<thisSize.iWidth)
+				wholeWidth=thisSize.iWidth;
+			}
+		else
+			{
+			thisSize.iWidth-=thisCaptionWidth;
+			if (extension->iCaptionWidth<thisCaptionWidth)
+				extension->iCaptionWidth=thisCaptionWidth;
+			if (size.iWidth<thisSize.iWidth)
+				size.iWidth=thisSize.iWidth;
+			}
+		}
+	size.iWidth+=extension->iCaptionWidth;
+	if (size.iWidth<wholeWidth)
+		size.iWidth=wholeWidth;
+	// If the total height is zero don't bother adding a top margin
+	if ( size.iHeight > 0 )
+		{
+		size.iHeight+=( topMargin + bottomMargin ) ;
+		size.iHeight+=2 ;  // (we have included one too many '-2's)
+		}
+	}
 	return size;
 	}
 
@@ -260,7 +363,7 @@
 			{
 			// should Panic() here 
 			}
-		TRect rect(aAreaSize);
+		TRect rect = TRect(TPoint(0,0), aAreaSize);
 		TAknLayoutRect layoutRect;
 		layoutRect.LayoutRect(rect, layout);
 		TInt height2 = layoutRect.Rect().Height();
@@ -271,6 +374,7 @@
 			break;
 			}
 
+
 		newMiddle = i + 1;
 		if (aTopItemIndex == -1)
 			{
@@ -362,6 +466,149 @@
 	SetRect(aRect, 0, -1, -1);
 }
 
+/**
+ * If aControl is an edwin, set its clipping rect to empty. This
+ * will disable the text hiding.
+ */
+static void ResetHides(CEikCaptionedControl *aControl)
+	{
+	aControl->SetPartiallyVisible( EFalse );
+	if (aControl->ControlIsAnEdwin(aControl->iControlType))
+		{
+		CEikEdwin *edwin = (CEikEdwin*)aControl->iControl;
+		edwin->SetTextLinesRect(TRect());
+		}
+	}
+
+/**
+ * Sets a clipping rectangle for hiding the whole or a part of edwin's text.
+ *
+ * The reason for using this function is the multiline edwins. The text inside
+ * an edwin can be broken to two or more lines, which must be hidden or shown 
+ * independently from each other. That is why it is not enough just to move
+ * the whole edwin out of the screen.
+ *
+ * @param aClipRect The clipping rect for edwin's text. An empty rect disables 
+ *   hiding.
+ *
+ * @return How many subcontrols were hidden
+ */
+static TInt HideLines_Edwin(CEikEdwin *aEdwin, TRect aClipRect)
+	{
+	aEdwin->SetTextLinesRect(aClipRect);
+    
+    // Create rects of the first and last edwin lines
+    TPoint edwinTl( aEdwin->Rect().iTl );
+    TPoint edwinBr( aEdwin->Rect().iBr );
+    TRect textFirstLine;
+    aEdwin->TextLayout()->GetLineRect(edwinTl.iY, textFirstLine);
+    textFirstLine.Move( edwinTl.iX, edwinTl.iY + aEdwin->Margins().iTop );
+    TRect textLastLine;
+    aEdwin->TextLayout()->GetLineRect(edwinBr.iY, textLastLine);
+    textLastLine.Move( edwinBr.iX, edwinBr.iY - aEdwin->Margins().iTop - textLastLine.Height() );
+
+    // Check if at least one line fits to the clipping rect
+	if( aClipRect.Contains(textFirstLine.iTl) &&
+	    aClipRect.iBr.iY >= textFirstLine.iBr.iY )   // The first line fits
+	    return 0;
+	if( aClipRect.Contains(textLastLine.iTl) &&
+	    aClipRect.iBr.iY >= textLastLine.iBr.iY )   // The last line fits
+	    return 0;
+	return 1;
+	}
+
+/**
+ * Tries to hide the specified control. The control will be hidden, if it doesn't
+ * fit to the specified clipping rectangle. Checks if the control exists.
+ *
+ * @return How many subcontrols were hidden
+ */
+static TInt HideLines_Ctrl(CCoeControl *aControl, TRect aClipRect)
+	{
+	if ( !aControl )
+	    return 1;   // It doesn't exist and hence not visible
+	TRect rect( aControl->Rect() );
+	if ( !aClipRect.Contains(rect.iTl) || aClipRect.iBr.iY <= rect.iBr.iY )
+	    // Never use TRect::Contains() for checking the bottom right corner, see documentation
+		{
+		// hide it
+		aControl->SetPosition( TPoint(-666,-666) );
+		return 1;
+		}
+    else
+        return 0;
+	}
+
+/**
+ * Get vertically minimal rectangle of the two given.
+ *
+ * Vertically reduces aRect1 by aRect2's dangling part, if aRect2
+ * doesn't fit to aRect1.
+ *
+ * Sets aRect1 to the resulting minimal rectangle.
+ */	
+static void GetVertMinRect( TRect& aRect1, const TRect aRect2 )
+    {
+    // If aRect2's top doesn't fit, lower aRect1's top
+    if( aRect2.iTl.iY < aRect1.iTl.iY )
+        aRect1.iTl.iY = Max( aRect1.iTl.iY, aRect2.iBr.iY );
+    // If aRect2's bottom doesn't fit, raise aRect1's bottom
+    if( aRect2.iBr.iY > aRect1.iBr.iY )
+        aRect1.iBr.iY = Min( aRect1.iBr.iY, aRect2.iTl.iY );
+    }
+
+/**
+ * Hides the specified form line, if it does not fit to the specified clipping rectangle.
+ * The function never hides focused editable lines. If the form layout is single, the whole
+ * captioned control is hidden.
+ * 
+ * @param aControl The form line to be hidden
+ * @param aClipRect The clipping rectangle
+ *
+ * @return How many subcontrols remained visible
+ */	
+static TInt HideLines(CEikCaptionedControl *aControl, TRect aClipRect)
+	{
+	TInt visibleCtrls = 3; // Visible subcontrols after hiding
+	CEikCaptionedControl *currentdLine = aControl->DialogPage()->CurrentLine();
+	if( ( aControl == currentdLine ) && aControl->iIsEditable )
+	    {
+	    return visibleCtrls;
+	    }
+	
+	TBool isEdwin = aControl->ControlIsAnEdwin(aControl->iControlType);    
+	CEikEdwin* edwin( NULL );
+	if( isEdwin )
+	    edwin = (CEikEdwin*)aControl->iControl;
+	TRect ctrlRect( aControl->iControl->Rect() );
+		
+	if( isEdwin )
+	    {
+	    // Adjust rectangle only to the first line (with edwin's top margin)
+	    TRect textFirstLine;
+	    edwin->TextLayout()->GetLineRect(ctrlRect.iTl.iY, textFirstLine);
+	    ctrlRect.iBr.iY = ctrlRect.iTl.iY + edwin->Margins().iTop + textFirstLine.Height();
+	    }	    
+	
+	// Find the minimal clipping rectangle
+	if( aControl->iBitmap )
+	    GetVertMinRect( aClipRect, aControl->iBitmap->Rect() );
+	if( aControl->iCaption )
+	    GetVertMinRect( aClipRect, aControl->iCaption->Rect() );
+	GetVertMinRect( aClipRect, ctrlRect );
+	
+	
+	
+	// Try to hide all controls on the current line
+	aControl->SetPartiallyVisible( ETrue );
+	visibleCtrls -= HideLines_Ctrl( aControl->iBitmap, aClipRect );
+	visibleCtrls -= HideLines_Ctrl( aControl->iCaption, aClipRect );
+	if( isEdwin )
+		visibleCtrls -= HideLines_Edwin( edwin, aClipRect );
+	else
+		visibleCtrls -= HideLines_Ctrl( aControl->iControl, aClipRect );
+    return visibleCtrls;
+	}
 
 /**
 * Places the dialog items according to the current visible window position.
@@ -389,19 +636,14 @@
 */
 void CEikCapCArray::SetRect(const TRect& aRect, TInt aTop, TInt /*aMiddle*/, TInt aBottom)
 	{
-	_AKNTRACE_FUNC_ENTER;
     TAknLayoutRect formtLayoutRect;
     formtLayoutRect.LayoutRect(aRect, AknLayoutScalable_Avkon::listscroll_form_pane().LayoutLine());
     formtLayoutRect.LayoutRect(formtLayoutRect.Rect(), AknLayoutScalable_Avkon::list_form_gen_pane().LayoutLine());
-    TRect formRect( formtLayoutRect.Rect() );
+    TRect formRect = formtLayoutRect.Rect();
 	
 	CEikCapCArrayExtension *extension_or_null = ExtensionOrNull();
-	
-	TBool rectChanged = ETrue;
-	
 	if (extension_or_null)
 		{
-        rectChanged = ( extension_or_null->iRect != formRect );
 		extension_or_null->iRect = formRect;
 		}
 
@@ -412,56 +654,275 @@
         
         if ( control->DialogPage()->IsForm() )
             {
-            if ( rectChanged )
-                {
-                SetRealRect( aRect, aTop, aBottom );
-                }
-
-            _AKNTRACE_FUNC_EXIT;
+            SetRealRect( aRect, aTop, aBottom );
             return;
             }
         }
         
-	// rest of the function is executed for dialogs and empty forms only
-    TRect rect(aRect);
-    const TInt fullWidth=rect.iBr.iX-rect.iTl.iX;
-    const TInt count=Count();
-    const TInt topMargin=iDensePacking ? KAknNoTopMargin : KAknTopMargin;
-    const TInt verticalSpacing=iDensePacking ? KVerticalSpacingSquash : KVerticalSpacing;
-    rect.iTl.iY+=topMargin;
-    TInt deltaHeight=0;
-    for (TInt ii=0;ii<count;++ii)
-        {
-        CEikCaptionedControl* line=(*this)[ii];
-        TSize thisSize=line->MinimumSize();
-        TInt thisDeltaHeight=thisSize.iHeight+verticalSpacing;
-        if (deltaHeight<thisDeltaHeight)
-            deltaHeight=thisDeltaHeight;
-        if (!(line->iCaptionWidth))
-            thisSize.iWidth=fullWidth;
-        else
-            {
-            CEikCapCArrayExtension *ext = ExtensionOrNull();
-            TInt deltaWidth = 0;
+	TBool topDefined = EFalse;   // top or bottom number defined?
+	if( aTop > -1 )
+	    {
+	    topDefined = ETrue;
+	    }
+	else if( aBottom > -1 )
+	    {
+	    topDefined = EFalse;
+	    }
+	else    // aBottom == aTop == -1
+	    {
+	    User::Panic( _L("CEikCapCArray::SetRect(): Neither top nor bottom items number defined"), EAknPanicInvalidValue );
+	    }
+	const TInt count = Count();
+	const TInt rectHeight = aRect.Height();
+	/**
+	* Special invisible points are used for placing the items that are
+	* outside the window. CCoeControl's invisible flag cannot be used,
+	* as it is controlled by third-party applications.
+	*/
+	const TPoint topInvisPoint( -10000, -10000 );
+	const TPoint bottomInvisPoint( 10000, 10000 );
+	
+	CEikCaptionedControl *firstCapCC = count > 0 ? (*this)[0] : NULL;
+	if( firstCapCC && firstCapCC->iIsFormControl )  // Forms
+		{
+		CEikCaptionedControl *selectedLine( NULL );
+		if( firstCapCC->DialogPage())
+	        selectedLine = firstCapCC->DialogPage()->CurrentLine();
+		
+		// Check height of items and the input parameters aTop and aBottom.
+		TInt rest = 0;  // number of the rest items without aTop or aBottom
+		TInt index = 0;
+    	if( topDefined )
+    	    {
+    	    rest = count - aTop;
+    	    index = aTop;
+    	    }
+    	else
+    	    {
+    	    rest = count - aBottom;
+    	    index = rest - 1;
+    	    }
+		TInt height = 0;
+		for( TInt ii = 0; ii < rest; ii++ )
+			{
+    		CEikCaptionedControl* line = (*this)[index];
+		    height += line->MinimumSize().iHeight;  // Use MinimumSize() here as a protection from dynamic layout change
+		    if( height >= rectHeight )
+                break;  // Input params are OK
+		    topDefined? index++ : index--;
+		    }
+		/** 
+		* If the window contains too few items inside and there are still items outside,
+		* correct the input parameters @a aTop and @a aBottom to fill up the window.
+		*/
+		if( height < rectHeight )
+		    {
+		    if( topDefined && aTop > 0 )    // For top-down placement and there are items above the window
+    		    {
+    		    // Calculate height of controls above the window also
+		        for( TInt ii = 0; ii < aTop; ii++ )
+		            {
+    		        CEikCaptionedControl* line = (*this)[ii];
+		            height += line->MinimumSize().iHeight;
+        		    if( height >= rectHeight )  // All items don't fit to the window anyway
+    		            {
+        		        topDefined = EFalse;   // Reverse direction to bottom-up
+        		        aBottom = 0;
+                        break;
+        		        }
+		            }
+		        if( height < rectHeight )  // All items fit to the window
+    		        {
+    		        aTop = 0; // Just place them from the first item
+    		        }
+    		    }
+    	    else if( !topDefined )  // For bottom-up placement
+    	        {
+    		    topDefined = ETrue;   // Reverse direction to top-down
+    		    aTop = 0;
+    	        }
+    	    }
+		
+		// Hiding items that are explicitly defined to be outside the window
+		TInt start;
+		TInt end;
+	    TPoint invisPoint;    // current invisible point, depends on placement direction
+    	if( topDefined )
+    	    {
+    	    start = 0;
+    	    end = aTop;
+    	    invisPoint = topInvisPoint;
+    	    }
+    	else
+    	    {
+    	    start = count - aBottom;
+    	    end = count;
+    	    invisPoint = bottomInvisPoint;
+    	    }
+		for( TInt ii = start; ii < end; ii++ )
+			{
+			CEikCaptionedControl* line = (*this)[ii];
+			line->SetPosition( invisPoint );
+			}
+		
+		// Setting rects for the rest of the items
+    	if( topDefined )
+    	    {
+    	    rest = count - aTop;
+    	    invisPoint = bottomInvisPoint;
+    	    index = aTop;
+    	    }
+    	else
+    	    {
+    	    rest = count - aBottom;
+    	    invisPoint = topInvisPoint;
+    	    index = rest - 1;
+    	    }
+		TInt reservedHeight = 0; // in pixels
+		TBool insideWindow = ETrue; // The current item is still inside the window
+        TInt topY = 0;
+        
+		
+		for( TInt ii = 0; ii < rest; ii++ )
+			{
+    		CEikCaptionedControl* line = (*this)[index];
+    		TSize lineSize( line->Size() );
+		    if( insideWindow )
+		        {
+			    ResetHides( line );
+    		    if( topDefined )
+    		        {   // Top-down placement
+    		        topY = aRect.iTl.iY + reservedHeight;   
+    		        }
+    		    else
+    		        {   // Bottom-up placement
+    		        topY = aRect.iBr.iY - reservedHeight - lineSize.iHeight;
+    		        }
+    		    line->SetExtent( TPoint( formRect.iTl.iX, topY ), lineSize );
+    			AknsUtils::RegisterControlPosition( line );
+    			AknsUtils::RegisterControlPosition( line->iCaption );
+    			AknsUtils::RegisterControlPosition( line->iControl );
+    			AknsUtils::RegisterControlPosition( line->iTrailer );
+    			AknsUtils::RegisterControlPosition( line->iBitmap );
+    			reservedHeight += lineSize.iHeight;
+    			/** 
+    			* The control at a window edge is considered as partially-visible.
+    			* Its subcontrols must be checked for visibility individually.
+    			*/
+    			if( reservedHeight > rectHeight )
+    			    {
+    			    TInt visibleSubctrls = HideLines( line, aRect );    // Check how many subcontrols stayed visible
+    			    insideWindow = EFalse;
+    			    /**
+    			    * For the bottom-up placement:
+    			    * if the window contains only an empty "partially-visible" control and a
+    			    * a selected popup field, make the popup to hang at the top alone.
+    			    */
+    			    if( !topDefined && index < count - 1 ) // bottom-up and not last
+    			        {
+        			    CEikCaptionedControl* lineBelow = (*this)[index+1];
+        			    if( visibleSubctrls == 0 && ii == 1 &&
+        			        IsPopupField( lineBelow ) && lineBelow == selectedLine )
+        			        {
+            		        TRect popupRect( lineBelow->Rect() );
+            		        TInt diff = aRect.iTl.iY - popupRect.iTl.iY; // negative
+            		        popupRect.Move( 0, diff );
+            		        lineBelow->SetRect( popupRect );
+        			        }
+    			        }
+    			    }
+		        }
+		    else
+		        {
+	            line->SetPosition( invisPoint );
+		        }
+		    topDefined? index++ : index--;
+			}
+		}
+	else    // Dialogs other than forms:
+		{
+    	TRect rect=aRect;
+    	const TInt fullWidth=rect.iBr.iX-rect.iTl.iX;
+    	const TInt count=Count();
+    	const TInt topMargin=iDensePacking ? KAknNoTopMargin : KAknTopMargin;
+    	const TInt verticalSpacing=iDensePacking ? KVerticalSpacingSquash : KVerticalSpacing;
+    	rect.iTl.iY+=topMargin;
+    	TInt deltaHeight=0;
+    	for (TInt ii=0;ii<count;++ii)
+    		{
+    		CEikCaptionedControl* line=(*this)[ii];
+    	    TSize thisSize=line->MinimumSize();
+    		TInt thisDeltaHeight=thisSize.iHeight+verticalSpacing;
+    		if (deltaHeight<thisDeltaHeight)
+    			deltaHeight=thisDeltaHeight;
+    		if (!(line->iCaptionWidth))
+    			thisSize.iWidth=fullWidth;
+    		else
+    			{
+    			CEikCapCArrayExtension *ext = ExtensionOrNull();
+    			TInt deltaWidth = 0;
+    			if (ext) 
+    				deltaWidth = ext->iCaptionWidth-line->iCaptionWidth;
+    			thisSize.iWidth+=deltaWidth;
+    			if (ext)
+    				line->iCaptionWidth=ext->iCaptionWidth;
+    			else
+    				line->iCaptionWidth = 0;
+    			line->iMinSize.iWidth+=deltaWidth;
+    			}
+    		line->iFullWidth=fullWidth;
+    	    line->SetExtent(rect.iTl,thisSize);
+    		if (!(line->LatentGroupLineFollows()))
+    			{
+    			rect.iTl.iY+=deltaHeight;
+    			deltaHeight=0;
+    			}
+    		}
+		}
+	}
 
-            if (ext) 
-                deltaWidth = ext->iCaptionWidth-line->iCaptionWidth;
-            thisSize.iWidth+=deltaWidth;
-            if (ext)
-                line->iCaptionWidth=ext->iCaptionWidth;
-            else
-                line->iCaptionWidth = 0;
-            }
-        line->iFullWidth=fullWidth;
-        line->SetExtent(rect.iTl,thisSize);
-        if (!(line->LatentGroupLineFollows()))
-            {
-            rect.iTl.iY+=deltaHeight;
-            deltaHeight=0;
-            }
-        }
-
-    _AKNTRACE_FUNC_EXIT;
+TInt CEikCapCArray::YPosToLine(const TRect &aRect, 
+							   TInt aTop, TInt aMiddle, TInt aBottom, 
+							   TInt aYCoord)
+	{
+	TInt top = aTop;
+	TInt middle = aMiddle;
+	TInt bottom = aBottom;
+	CalcItemIndexes(top, middle, bottom, aRect.Size());
+	
+	for(int i = top ; i < top+middle; i++)
+		{
+		CEikCaptionedControl *fst = (*this)[i];
+		if (aYCoord < fst->Rect().iTl.iY)
+			{
+			if (i > 0)
+				return i-1;
+			else
+				return KErrNotFound;
+			}
+		}
+	if (Count() == 0) return -1;
+	TInt ii = top+middle-1;
+	CEikCaptionedControl *last = (*this)[ii];
+	if ( aYCoord < last->Rect().iBr.iY )
+		{
+		return ii;
+		}
+	else
+		{
+		if ( ii+1 < Count() )
+		    {
+		    return ii+1;
+		    }
+		else if ( aYCoord > last->Rect().iBr.iY )
+		    {
+		    return KErrNotFound;
+		    }
+		else
+		    {
+		    return ii;
+		    }
+		}
 	}
 	
 EXPORT_C void CEikCapCArray::ResetMinimumSizes()
@@ -507,6 +968,60 @@
 	return(KErrNotFound);
 	}
 
+// ---------------------------------------------------------------------------
+// CEikCapCArray::ScrollByPixels
+// ---------------------------------------------------------------------------
+//
+TInt CEikCapCArray::ScrollByPixels( TInt aDelta )
+    {
+    TInt count = Count();
+    
+    // Top and bottom of lines
+    TInt topY = (*this)[0]->Rect().iTl.iY;
+    TInt bottomY = (*this)[count - 1]->Rect().iBr.iY;
+
+    TRect formRect( Rect() );
+
+    if ( aDelta )
+        {
+        for( TInt i = 0; i < count; ++i )
+            {
+            CEikCaptionedControl* line = (*this)[i];
+            TBool onDisplay = line->Rect().Intersects( formRect );
+            TPoint position( line->Position() );
+            position.iY += aDelta;
+            
+            line->SetPosition( position );
+            
+            onDisplay = onDisplay || line->Rect().Intersects( formRect );
+            
+            // Line is or was on display
+            if ( ETrue /*onDisplay*/ )
+                // Some controls, eg. slider and edwin don't handle
+                // SetPosition properly. Workaround is to use SetRect,
+                // which is slow as it does a whole layout for the control.
+                // If form panning is ever speed optimized, captioned
+                // control should me made to support SetPosition() correctly.
+                {
+                if ( line->ControlIsAPopfield( line->iControlType ) )
+                    {
+                    // Have to layout whole captioned control, otherwise
+                    // text doesn't move. Fix later popup field to move
+                    // properly.
+                    line->SetRect( line->Rect() );
+                    }
+                else
+                    {
+                    line->iControl->SetRect( line->iControl->Rect() );
+                    }
+                line->DrawDeferred();
+                //line->DrawNow();
+                }
+            }
+        }
+
+    return aDelta;
+    }
 
 // ---------------------------------------------------------------------------
 // CEikCapCArray::SetRealRect
@@ -515,7 +1030,6 @@
 void CEikCapCArray::SetRealRect( 
 		const TRect& /*aRect*/, TInt /*aTop*/, TInt /*aBottom*/ )
     {
-	_AKNTRACE_FUNC_ENTER;
     TInt count = Count();
     const TPoint virtualTl( 1000, 0 );
     TPoint skinLocation( 0, 0 );
@@ -542,7 +1056,6 @@
         AknsUtils::RegisterControlPosition( line->iTrailer, skinLocation );
         AknsUtils::RegisterControlPosition( line->iBitmap, skinLocation );
         }
-    _AKNTRACE_FUNC_EXIT;
     }
 
 
@@ -596,8 +1109,6 @@
 //
 void CEikCapCArray::MoveLineToScreen( TInt aLine, TInt aTopY, TBool aVisible )
     {
-	_AKNTRACE_FUNC_ENTER;
-	_AKNTRACE( "aLine: [%d], aTopY: [%d], aVisible: [%d]", aLine, aTopY, aVisible );
     if ( aLine != -1 && aLine < Count() )
         {
         CEikCaptionedControl* line = (*this)[aLine];
@@ -608,14 +1119,8 @@
             topLeft.SetXY( Rect().iTl.iX, LineIndexToYPosition( aLine, aTopY ) );
             }
         
-        TRect newRect( topLeft, line->Size() );
-        
-        if ( newRect != line->Rect() )
-            {
-            line->SetRect( TRect( topLeft, line->Size() ) );
-            }
+        line->SetRect( TRect( topLeft, line->Size() ) );
         }
-    _AKNTRACE_FUNC_EXIT;
     }
 
 
@@ -625,15 +1130,13 @@
 //
 TInt CEikCapCArray::FocusableLine( TInt aCurrentLine, TInt aTopY )
     {
-	_AKNTRACE_FUNC_ENTER;
-	_AKNTRACE( "aCurrentLine: [%d]", aCurrentLine );
     TInt focusableLine = KErrNotFound;
     
     if ( aCurrentLine >= 0 && aCurrentLine < Count() )
         {
         TInt y = LineIndexToYPosition( aCurrentLine, aTopY );
 
-        // if current line is visible on the screen then focus that
+        // if current line is visible on the screen the focus that
         if ( y >= 0 && y <= Rect().Height() )
             {
             focusableLine = aCurrentLine;
@@ -654,7 +1157,7 @@
                 }
             }
         }
-    _AKNTRACE_FUNC_EXIT;
+    
     return focusableLine;
     }