 
 package flex.layout
 {
+import flash.display.DisplayObject;
+import flash.geom.Point;
 import flash.geom.Rectangle;
-import flash.display.DisplayObject;
 import flash.events.Event;
 import flash.events.EventDispatcher;
 

            return 1.0;

        // index is first (r0) or last (r1) visible row
        var y0:Number = vp.verticalScrollPosition;
        var y1:Number = y0 + vp.height;
        var iy0:Number = li.actualPosition.y;
        var iy1:Number = iy0 + li.actualSize.y;
        if (iy0 >= iy1)  // item has 0 or negative height

            return (iy1 - y0) / (iy1 - iy0);
        else 
            return (y1 - iy0) / (iy1 - iy0);
	}
	
	/**
	 *  Binary search for the first layout item that contains y.  
	 * 
	 *  This function considers both the item's actual bounds and 
	 *  the gap that follows it to be part of the item.  The search 
	 *  covers index i0 through i1 (inclusive).
	 *  
	 *  This function is intended for variable height items.
	 * 
	 *  Returns the index of the item that contains y, or -1.
	 * 
	 *  Implementation note: currently the inclusion test is slightly
	 *  incorrect, since we're comparing y with the _closed_ interval
	 *  from p.y to p.y + s.y + gap.  This is to accomodate checking the
	 *  "bottom" of the scrollRect, see the computation of i1 in
	 *  scrollPositionChanged.  One alternative that would restore
	 *  the more correct open ended interval, would be to check
	 *  the bottom of the scrollRect less some infintesimally small
	 *  amount.
	 *   
	 * @private 
	 */
	private static function findIndexAt(y:Number, gap:int, g:GroupBase, i0:int, i1:int):int
	{
	    var index:int = (i0 + i1) / 2;
        var item:ILayoutItem = g.getLayoutItemAt(index);	    
	    var p:Point = item.actualPosition;
        var s:Point = item.actualSize;
        // TBD: deal with null item, includeInLayout false.
        if ((y >= p.y) && (y <= p.y + s.y + gap))
            return index;
        else if (i0 == i1)
            return -1;
        else if (y < p.y)
            return findIndexAt(y, gap, g, i0, Math.max(i0, index-1));
        else 
            return findIndexAt(y, gap, g, Math.min(index+1, i1), i1);
	}   

   /**
    *  Updates the first,lastIndexInView properties per the new
    *  scroll position.
    *  
    *  @see setIndexInView
    */
    override protected function scrollPositionChanged():void
    {
        super.scrollPositionChanged();
        
        var g:GroupBase = target;
        if (!g)
            return;     

        var r:Rectangle = g.scrollRect;
        if (!r)
        {
            // TBD: find first/last non-null includeInLayout items
        }
        // TBD: special case for variableRowHeight false
        else 
        {
	        var n:int = Math.max(g.numLayoutItems - 1, 0);
	        var i0:int = findIndexAt(r.y + gap, gap, g, 0, n);
	        var i1:int = findIndexAt(r.bottom, gap, g, 0, n);
	        setIndexInView(i0, i1);
        }
    }
    
    private function variableRowHeightMeasure(layoutTarget:GroupBase):void
    {
        var minWidth:Number = 0;
