     	var layoutTarget:GroupBase = target;
         if (!layoutTarget)
             return;
-        if (variableRowHeight) 
+        if (virtualLayout)
+            virtualRowHeightMeasure(layoutTarget);
+        else if (variableRowHeight) 
             variableRowHeightMeasure(layoutTarget);
         else 
             fixedRowHeightMeasure(layoutTarget);
 
     }
     
-    
+    //  - virtual layout only - 
+    private function calculateElementX(elt:ILayoutElement, eltWidth:Number, contentWidth:Number):Number
+    {
+       switch(horizontalAlign)
+       {
+           case HorizontalAlign.CENTER: 
+               return (contentWidth - eltWidth) * 0.5;
+           case HorizontalAlign.RIGHT: 
+               return contentWidth - eltWidth;
+       }
+       return 0;
+    }
+
+    //  - virtual layout only - 
+    private function calculateElementWidth(elt:ILayoutElement, targetWidth:Number, contentWidth:Number):Number
+    {
+       // If percentWidth is specified then the element's width is the percentage
+       // of targetWidth clipped to min/maxWidth and to (upper limit) targetWidth.
+       var percentWidth:Number = elt.percentWidth;
+       if (!isNaN(percentWidth))
+       {
+          var width:Number = percentWidth * 0.01 * targetWidth;
+          return Math.min(targetWidth, Math.min(elt.getMaxWidth(), Math.max(elt.getMinWidth(), width)));
+       }
+       switch(horizontalAlign)
+       {
+           case HorizontalAlign.JUSTIFY: 
+               return targetWidth;
+           case HorizontalAlign.CONTENT_JUSTIFY: 
+               return contentWidth;
+       }
+       return elt.getPreferredWidth();
+    }
+    
+    /**
+     *  @private
+     *  Update the layout of the virtualized elements that are within 
+     *  the scrollRect's vertical extent.
+     *
+     *  The height of each layout element will be its preferred height, and its
+     *  y will be the bottom of the previous item, plus the gap.
+     * 
+     *  No support for percentHeight, includeInLayout=false, or null layoutElements,
+     * 
+     *  The width of each layout element will be set to its preferred width, unless
+     *  one of the following is true:
+     * 
+     *  - If percentWidth is specified for this element, then its width will be the
+     *  specified percentage of the target's actual (unscaled) width, clipped 
+     *  the layout element's minimum and maximum width.
+     * 
+     *  - If horizontalAlign is "justify", then the element's width will
+     *  be set to the target's actual (unscaled) width.
+     * 
+     *  - If horizontalAlign is "contentJustify", then the element's width
+     *  will be set to the target's content width.
+     * 
+     *  The X coordinate of each layout element will be set to 0 unless one of the
+     *  following is true:
+     * 
+     *  - If horizontalAlign is "center" then x is set so that the element's preferred
+     *  width is centered within the contentWidth:
+     *      x = (contentWidth - layoutElementWidth) * 0.5
+     * 
+     *  - If horizontalAlign is "right" the x is set so that the element's right
+     *  edge is aligned with the the right edge of the content:
+     *      x = (contentWidth - layoutElementWidth)
+     * 
+     *  Implementation note: unless horizontalAlign is either "justify" or 
+     *  "left", the layout elements' x or width depends on the contentWidth.
+     *  The contentWidth is a maximum and although it may be updated to 
+     *  different value after all (viewable) elements have been laid out, it
+     *  often does not change.  For that reason we use the current contentWidth
+     *  for the initial layout and then, if it has changed, we loop through 
+     *  the layout items again and fix up the x/width values.
+     */
+    private function updateDisplayListInView(startIndex:int = -1):void
+    {
+        var layoutTarget:GroupBase = target; 
+        var eltCount:int = layoutTarget.numLayoutElements;
+        var targetWidth:Number = layoutTarget.width;
+        var minVisibleY:Number = layoutTarget.verticalScrollPosition;
+        var maxVisibleY:Number = minVisibleY + layoutTarget.height;
+        
+        // TBD: don't assume typicalLayoutElement is set, use 1st row...
+        var typicalWidth:Number = typicalLayoutElement.getPreferredWidth();
+        var typicalHeight:Number = typicalLayoutElement.getPreferredHeight();
+        llv.length = layoutTarget.numLayoutElements;        
+        llv.minorSize = Math.max(llv.minorSize, typicalWidth);
+        llv.defaultMajorSize = typicalHeight;
+        if (startIndex < 0)            
+            startIndex = llv.indexOf(minVisibleY);           
+         
+        layoutTarget.beginVirtualLayout(startIndex);
+        var contentWidth:Number = llv.minorSize;
+        var y:Number = llv.start(startIndex);
+        var index:int = startIndex;
+        
+        // First pass: compute element x,y,width,height based on 
+        // current contentWidth; cache computed widths/heights in llv.
+        for (; (y < maxVisibleY) && (index < eltCount); index++)
+        {
+            var elt:ILayoutElement = layoutTarget.getLayoutElementAt(index);
+            var h:Number = elt.getPreferredHeight();
+            var w:Number = calculateElementWidth(elt, targetWidth, contentWidth);
+            var x:Number = calculateElementX(elt, w, contentWidth);
+            elt.setLayoutPosition(x, y);
+            elt.setLayoutSize(w, elt.getPreferredHeight());            
+            llv.cacheDimensions(index, elt);
+            y += h + gap;
+        }
+
+        // Second pass: if neccessary, fix up x and width values based
+        // on the updated contentWidth
+        var endIndex:int = index - 1;
+        var finalContentWidth:Number = llv.minorSize;
+        if ((finalContentWidth != contentWidth) &&
+            (horizontalAlign != HorizontalAlign.LEFT) &&
+            (horizontalAlign != HorizontalAlign.JUSTIFY))
+        {
+            contentWidth = finalContentWidth;
+            for (index = startIndex; index < eltCount; index++)
+            {
+                elt = layoutTarget.getLayoutElementAt(index);
+                w = calculateElementWidth(elt, targetWidth, contentWidth);
+                x = calculateElementX(elt, w, contentWidth);
+                elt.setLayoutPosition(x, elt.getLayoutPositionY());
+                elt.setLayoutSize(w, elt.getLayoutHeight());         
+            }
+        }
+        setRowCount(index - startIndex);
+        setIndexInView(startIndex, endIndex);
+        layoutTarget.setContentSize(contentWidth, llv.end(llv.length - 1));
+        layoutTarget.endVirtualLayout(startIndex, endIndex);
+    }
+    
+
     override public function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
     {
         super.updateDisplayList(unscaledWidth, unscaledHeight);

    }
    
    
    override public function measure():void
    {
        super.measure();

                    i1 = index1;
            }
        }   
        if (virtualLayout)
            updateDisplayListInView(i0);  // TBD returns i1
                
        setIndexInView(i0, i1);
    }

