| package spark.components.gridClasses { |
| import flash.events.Event; |
| import flash.events.EventDispatcher; |
| |
| import flash.geom.Matrix; |
| import flash.geom.Point; |
| import flash.geom.Rectangle; |
| |
| import mx.collections.ArrayCollection; |
| |
| import org.flexunit.assertThat; |
| |
| import org.flexunit.asserts.assertEquals; |
| import org.flexunit.asserts.assertTrue; |
| import org.flexunit.async.Async; |
| import org.flexunit.runners.Parameterized; |
| import org.fluint.uiImpersonation.UIImpersonator; |
| |
| import spark.components.DataGrid; |
| import spark.components.GridColumnHeaderGroup; |
| |
| /* |
| Example for two-column table (with no horizontal scroll): |
| |
| [pt]: GridColumnHeaderGroup padding top |
| [pl]: GridColumnHeaderGroup padding left |
| [lch]: still part of last column header, but beyond last column width |
| |
| b0: top-left corner of the data grid. Also, first column starts at this x-coordinate |
| b1: first column ends at this x-coordinate (but the first header usually doesn't, due to [pl]) |
| b2: second column ends at this x-coordinate (but the second header usually doesn't, due to [pl]) |
| ... |
| bx: last column ends at this x-coordinate |
| |
| c0: first column header starts at this x-coordinate |
| c1: first column header ends at this x-coordinate, separator starts at this x-coordinate, and |
| second column header (if it exists) starts at this x-coordinate + separator.width |
| c1: second column header ends at this x-coordinate, next separator (if it exists) starts at |
| this x-coordinate, and third column header (if it exists) starts at this x-coordinate + separator.width |
| ... |
| cx: last column header ends at this x-coordinate; last column separator starts at this x-coordinate |
| |
| d: table ends at this x-axis coordinate |
| e: top-left corner of header. If [pt] and [pl] are 0, this coincides with b0 |
| f: b0ttom-left corner of header. If [pb] and [pl] are 0, this coincides with g0 |
| |
| g0: header ends and grid starts at this y-coordinate |
| g1: first column ends at this x-coordinate and second column (if it exists) begins at this x-coordinate |
| g2: second column ends at this x-coordinate and third column (if it exists) begins at this x-coordinate |
| ... |
| gx: last column ends at this x-coordinate |
| |
| i: bottom-right point of last column header and x-coordinate at end of data grid |
| |
| And for each point we generate the 8 adjacent points: |
| (x+1, y), (x+1, y+1), (x+1, y-1), |
| (x-1, y), (x-1, y+1), (x-1, y-1), |
| (x, y-1), (x, y-1). For easier comprehension we mark them |
| using cardinal points: N, NE, E, SE, S, SW, W, NW. |
| ...and we check various boundaries against all of them |
| |
| a (0, 0) |
| ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ |
| ░░░░░b0═══c0══════b1═══c1════════════════════════════b2══c2═════════d░░░░░░░ |
| ░░░░░║ [pt] ║░░░░░░░ |
| ░░░░░║ e▓▓▓▓▓▓▓▓▓▓▓▓║▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓║▓▓▓▓▓▓▓▓▓▓║░░░░░░░ |
| ░░░░░║[pl]║▓▓▓INDEX▓▓▓▓║▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓NAME▓▓▓▓▓▓▓▓▓▓▓▓▓║▓▓▓[lch]▓▓║░░░░░░░ |
| ░░░░░║ f▓▓▓▓▓▓▓▓▓▓▓▓║▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓║▓▓▓▓▓▓▓▓▓▓║░░░░░░░ |
| ░░░░░║ [pb] ║░░░░░░░ |
| ░░░░░g0═══════════g1═════════════════════════════════g2═════════════i░░░░░░░ |
| ░░░░░║ 01 ║ John ║ ║░░░░░░░ |
| ░░░░░║ 02 ║ Jane ║ ║░░░░░░░ |
| ░░░░░║ 03 ║ Judy ║ ║░░░░░░░ |
| ░░░░░║ 04 ║ James ║ ║░░░░░░░ |
| ░░░░░╚════════════╩══════════════════════════════════╩══════════════╝░░░░░░░ |
| ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ |
| ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ |
| */ |
| |
| [RunWith("org.flexunit.runners.Parameterized")] |
| public class GridHeaderViewLayout_FLEX_35260_Tests |
| { |
| private static var foo:Parameterized; |
| private static const N:Matrix = new Matrix(1, 0, 0, 1, 0, -1); |
| private static const NE:Matrix = new Matrix(1, 0, 0, 1, 1, -1); |
| private static const E:Matrix = new Matrix(1, 0, 0, 1, 1, 0); |
| private static const SE:Matrix = new Matrix(1, 0, 0, 1, 1, 1); |
| private static const S:Matrix = new Matrix(1, 0, 0, 1, 0, 1); |
| private static const SW:Matrix = new Matrix(1, 0, 0, 1, -1, 1); |
| private static const W:Matrix = new Matrix(1, 0, 0, 1, -1, 0); |
| private static const NW:Matrix = new Matrix(1, 0, 0, 1, -1, -1); |
| private static const ITSELF:Matrix = new Matrix(1, 0, 0, 1, 0, 0); //the point, unmodified |
| private static const directions:Array = [ITSELF, N, NE, E, SE, S, SW, W, NW]; |
| |
| private static const ENTIRE_HEADER_RECTANGLE:String = "visibleHeaderRectangle"; //includes padding |
| private static const FIXED_HEADER_VIEW_RECTANGLE:String = "fixedHeaderViewRectangle"; |
| |
| private static const NO_ENTER_FRAMES_TO_ALLOW:int = 2; |
| |
| private static var _dataGrid:DataGrid; |
| private static const _finishNotifier:EventDispatcher = new EventDispatcher(); |
| |
| private var _keyRectangles:Array; |
| private var _keyPoints:Array; |
| private var _dimensions:Array; |
| private var _noEnterFramesRemaining:int = NaN; |
| |
| //@TODO add cases with fixed columns |
| //@TODO can the grid itself have padding? |
| //@TODO test with a columnGap as well |
| public static var allDimensions:Array = [ |
| /*x, y, width, header padding left, header padding top, header padding bottom, [column widths] */ |
| [[/*x=*/ 0, /*y=*/ 0, /*width=*/ 300, /*paddingLeft=*/ 5, /*paddingTop=*/ 0, /*paddingBottom=*/ 0, /*columnWidths=*/[25, 150]]], |
| [[/*x=*/ 10, /*y=*/ 0, /*width=*/ 300, /*paddingLeft=*/ 5, /*paddingTop=*/ 0, /*paddingBottom=*/ 5, /*columnWidths=*/[25, 150]]], |
| [[/*x=*/ 0, /*y=*/ 0, /*width=*/ 200, /*paddingLeft=*/ 5, /*paddingTop=*/ 0, /*paddingBottom=*/ 0, /*columnWidths=*/[80, 150]]], //horizontal scroll |
| [[/*x=*/ 0, /*y=*/ 0, /*width=*/ 100, /*paddingLeft=*/ 0, /*paddingTop=*/ 0, /*paddingBottom=*/ 0, /*columnWidths=*/[10, 110, 15]]], //horizontal scroll |
| [[/*x=*/ -5, /*y=*/-100, /*width=*/ 200, /*paddingLeft=*/ 25, /*paddingTop=*/ 12, /*paddingBottom=*/ 5, /*columnWidths=*/[100, 150]]] //horizontal scroll |
| ]; |
| |
| |
| [BeforeClass] |
| public static function setUpBeforeClass():void |
| { |
| _dataGrid = new DataGrid(); |
| _dataGrid.setStyle("borderVisible", false); //to not deal with the complications of Scroller.minViewportInset |
| UIImpersonator.addChild(_dataGrid); |
| } |
| |
| [AfterClass] |
| public static function tearDownAfterClass():void |
| { |
| UIImpersonator.removeAllChildren(); |
| |
| _dataGrid = null; |
| } |
| |
| [Before] |
| public function setUp():void |
| { |
| |
| } |
| |
| [After] |
| public function tearDown():void |
| { |
| _keyRectangles = null; |
| _keyPoints = null; |
| _dimensions = null; |
| } |
| |
| |
| [Test(dataProvider="allDimensions", async, timeout=3000)] |
| public function test_ltr(dimensions:Array):void |
| { |
| //given |
| _dataGrid.width = getWidth(dimensions); |
| _dataGrid.x = getX(dimensions); |
| _dataGrid.y = getY(dimensions); |
| |
| _dataGrid.columnHeaderGroup.setStyle("paddingLeft", getHeaderPaddingLeft(dimensions)); |
| _dataGrid.columnHeaderGroup.setStyle("paddingTop", getHeaderPaddingTop(dimensions)); |
| _dataGrid.columnHeaderGroup.setStyle("paddingBottom", getHeaderPaddingBottom(dimensions)); |
| |
| var gridColumns:Array = []; |
| for (var i:int = 0; i < getColumnWidths(dimensions).length; i++) |
| { |
| var column:GridColumn = new GridColumn(); |
| column.width = getColumnWidth(dimensions, i); |
| gridColumns.push(column); |
| } |
| _dataGrid.columns = new ArrayCollection(gridColumns); |
| |
| _dataGrid.columnHeaderGroup.invalidateDisplayList(); |
| _dataGrid.columnHeaderGroup.validateNow(); |
| _dataGrid.grid.validateNow(); |
| _dataGrid.validateNow(); |
| |
| _dimensions = dimensions; |
| _keyPoints = generateKeyPoints(_dataGrid); |
| _keyRectangles = generateKeyRectangles(); |
| |
| _noEnterFramesRemaining = NO_ENTER_FRAMES_TO_ALLOW; |
| UIImpersonator.testDisplay.addEventListener(Event.ENTER_FRAME, onEnterFrame); |
| Async.handleEvent(this, _finishNotifier, Event.COMPLETE, doTests, 3000); |
| } |
| |
| private function doTests(event:Event, passThroughData:Object):void |
| { |
| //then |
| //first, make sure that the dataGrid was rendered correctly |
| assertThat("The dataGrid has not yet been correctly rendered on stage", getActualHeaderHeight(_dataGrid) > 0); |
| |
| //test the assumption about the center column header view location |
| var centerGridViewLocation:Point = GridHeaderLayout(_dataGrid.columnHeaderGroup.layout).centerGridColumnHeaderView.localToGlobal(new Point(0, 0)); |
| assertTrue("The location of the centerGridColumnHeaderView does not reflect the columnHeaderGroup's padding rules! It's located at the global coordinates " + |
| centerGridViewLocation + ", but it should be at " + _keyPoints["e"], |
| centerGridViewLocation.equals(_keyPoints["e"])); |
| |
| forEachPointAndScrollLocation(assertAssumptionsAboutPoint); |
| } |
| |
| private function forEachPointAndScrollLocation(assertThat_:Function):void |
| { |
| _dataGrid.columnHeaderGroup.invalidateDisplayList(); |
| _dataGrid.columnHeaderGroup.validateNow(); |
| _dataGrid.grid.validateNow(); |
| _dataGrid.validateNow(); |
| |
| var maxScroll:Number = Math.max(1, getTotalColumnWidths(_dimensions) - getWidth(_dimensions) - getHeaderPaddingLeft(_dimensions)); |
| for (var i:int = 0; i < maxScroll; i++) |
| { |
| _dataGrid.grid.horizontalScrollPosition = i; |
| _dataGrid.columnHeaderGroup.invalidateDisplayList(); |
| _dataGrid.columnHeaderGroup.validateNow(); |
| _dataGrid.grid.validateNow(); |
| _dataGrid.validateNow(); |
| |
| for (var pointName:String in _keyPoints) |
| { |
| for (var j:int = 0; j < directions.length; j++) |
| { |
| assertThat_(getAdjacentPoint(_keyPoints[pointName], directions[j]), pointName, directions[j]); |
| _dataGrid.columnHeaderGroup.invalidateDisplayList(); |
| _dataGrid.columnHeaderGroup.validateNow(); |
| _dataGrid.grid.validateNow(); |
| _dataGrid.validateNow(); |
| } |
| } |
| } |
| } |
| |
| private function assertAssumptionsAboutPoint(point:Point, pointName:String, currentTransformation:Matrix):void |
| { |
| assertThatHeaderContainsPointOrNot(point, pointName, currentTransformation); |
| assertThatCoordinatesOverHeaderViewOrNot(point, pointName, currentTransformation); |
| assertThatHeaderIndexIsCorrect(point, pointName, currentTransformation); |
| assertThatColumnIndexIsCorrect(point, pointName, currentTransformation); |
| } |
| |
| private function assertThatHeaderContainsPointOrNot(point:Point, pointName:String, currentTransformation:Matrix):void |
| { |
| //when |
| var headerShouldContainThisPoint:Boolean = getHeaderShouldContainPointAssumption(point); |
| var doesHeaderContainThisPoint:Boolean = _sut.containsGlobalCoordinates(point); |
| const errorMessageHeaderContainsPoint:String = getHeaderContainsPointErrorMessage(pointName, currentTransformation, point, headerShouldContainThisPoint, doesHeaderContainThisPoint); |
| |
| //then |
| assertEquals(errorMessageHeaderContainsPoint, headerShouldContainThisPoint, doesHeaderContainThisPoint); |
| } |
| |
| private function assertThatCoordinatesOverHeaderViewOrNot(point:Point, pointName:String, currentTransformation:Matrix):void |
| { |
| //when |
| const visibleHeaderViewRectangle:Rectangle = getVisibleHeaderViewRectangle(getCurrentHScrollPosition()); |
| var shouldBeContainedInMainHeaderView:Boolean = getMainHeaderViewContainsPointAssumption(visibleHeaderViewRectangle, point); |
| var shouldBeContainedInFixedHeaderView:Boolean = getFixedHeaderViewContainsPointAssumption(point); |
| const shouldBeContainedInAHeaderView:Boolean = shouldBeContainedInMainHeaderView || shouldBeContainedInFixedHeaderView; |
| var actuallyContainedInAHeaderView:Boolean = _sut.areCoordinatesOverAHeaderView(point); |
| const errorMessageHeaderViewContainsPoint:String = getHeaderViewContainsPointErrorMessage(pointName, currentTransformation, point, shouldBeContainedInAHeaderView, actuallyContainedInAHeaderView, visibleHeaderViewRectangle); |
| |
| //then |
| assertEquals(errorMessageHeaderViewContainsPoint, shouldBeContainedInAHeaderView, actuallyContainedInAHeaderView); |
| } |
| |
| private function assertThatHeaderIndexIsCorrect(point:Point, pointName:String, currentTransformation:Matrix):void |
| { |
| //when |
| const visibleColumnHeaderRectangles:Array = getVisibleColumnHeaderRectangles(getCurrentHScrollPosition()); |
| var expectedHeaderIndex:int = getHeaderIndexAssumption(point, visibleColumnHeaderRectangles); |
| var actualHeaderIndex:int = getHeaderIndexAtGlobalPoint(point); |
| const errorMessageHeaderIndex:String = getHeaderIndexErrorMessage(pointName, currentTransformation, point, expectedHeaderIndex, actualHeaderIndex, visibleColumnHeaderRectangles); |
| |
| //then |
| assertEquals(errorMessageHeaderIndex, expectedHeaderIndex, actualHeaderIndex); |
| } |
| |
| private function assertThatColumnIndexIsCorrect(point:Point, pointName:String, currentTransformation:Matrix):void |
| { |
| //when |
| const visibleColumnRectangles:Array = getAllColumnRectangles(getCurrentHScrollPosition()); |
| var expectedColumnIndex:int = getColumnIndexAssumption(visibleColumnRectangles, point); |
| var actualColumnIndex:int = getColumnIndexAtGlobalPoint(point); |
| const errorMessageColumnIndex:String = getColumnIndexErrorMessage(pointName, currentTransformation, point, expectedColumnIndex, actualColumnIndex, visibleColumnRectangles); |
| |
| //then |
| assertEquals(errorMessageColumnIndex, expectedColumnIndex, actualColumnIndex); |
| } |
| |
| private function getHeaderIndexErrorMessage(pointName:String, direction:Matrix, transformedPoint:Point, expectedColumnHeaderIndex:int, actualColumnHeaderIndex:int, visibleColumnHeaderRectangles:Array):String |
| { |
| return "The point " + pointName + " transformed with Matrix " + direction + " (resulting in " + transformedPoint + ") should be " |
| + (expectedColumnHeaderIndex == -1 ? "outside any column header bounds" : "inside the column header with index " + expectedColumnHeaderIndex) |
| + " but was mistakenly found to be " |
| + (actualColumnHeaderIndex == -1 ? "outside any column header bounds" : "inside the column header with index " + actualColumnHeaderIndex) |
| + " given a horizontalScrollPosition of " + getCurrentHScrollPosition() |
| + "\n DEBUG INFO: visibleColumnHeaderRectangles=" + visibleColumnHeaderRectangles; |
| } |
| |
| private function getColumnIndexErrorMessage(pointName:String, direction:Matrix, transformedPoint:Point, expectedColumnHeaderIndex:int, actualColumnHeaderIndex:int, visibleColumnRectangles:Array):String |
| { |
| return "The point " + pointName + " transformed with Matrix " + direction + " (resulting in " + transformedPoint + ") should have its x value " |
| + (expectedColumnHeaderIndex == -1 ? "outside any column bounds" : "inside the column with index " + expectedColumnHeaderIndex) |
| + " but was mistakenly found to be " |
| + (actualColumnHeaderIndex == -1 ? "outside any column bounds" : "inside the column with index " + actualColumnHeaderIndex) |
| + " given a horizontalScrollPosition of " + getCurrentHScrollPosition() |
| + "\n DEBUG INFO: columnRectangles=" + visibleColumnRectangles; |
| } |
| |
| private function getHeaderContainsPointErrorMessage(pointName:String, direction:Matrix, transformedPoint:Point, shouldBeContainedInHeader:Boolean, isActuallyContainedInHeader:Boolean):String |
| { |
| return "The point " + pointName + " transformed with Matrix " + direction + " (resulting in " + transformedPoint + ") should be " |
| + (shouldBeContainedInHeader ? "within " : "outside ") + "the header bounds" |
| + " but was mistakenly found to be " |
| + (isActuallyContainedInHeader ? "within" : "outside") |
| + " given a horizontalScrollPosition of " + getCurrentHScrollPosition() |
| + "\n DEBUG INFO: header rectangle=" + entireHeaderRectangle; |
| } |
| |
| private function getHeaderViewContainsPointErrorMessage(pointName:String, direction:Matrix, transformedPoint:Point, shouldBeContainedInAHeaderView:Boolean, isActuallyContainedByAHeaderView:Boolean, visibleHeaderViewRectangle:Rectangle):String |
| { |
| return "The point " + pointName + " transformed with Matrix " + direction + " (resulting in " + transformedPoint + ") should be " |
| + (shouldBeContainedInAHeaderView ? "within " : "outside ") + "a header view" |
| + " but was mistakenly found to be " |
| + (isActuallyContainedByAHeaderView ? "within" : "outside") |
| + " given a horizontalScrollPosition of " + getCurrentHScrollPosition() |
| + "\n DEBUG INFO: rectangles of visible header views = " + fixedHeaderViewRectangle + "; " + visibleHeaderViewRectangle; |
| } |
| |
| private function getHeaderIndexAtGlobalPoint(globalPoint:Point):int |
| { |
| var localPoint:Point = _sut.globalToLocal(globalPoint); |
| return _sut.getHeaderIndexAt(localPoint.x, localPoint.y); |
| } |
| |
| private function getColumnIndexAtGlobalPoint(globalPoint:Point):int |
| { |
| var localPoint:Point = _dataGrid.grid.globalToLocal(globalPoint); |
| return _dataGrid.grid.getColumnIndexAt(localPoint.x, localPoint.y); |
| } |
| |
| private function getHeaderShouldContainPointAssumption(point:Point):Boolean |
| { |
| return rectangleContainsPoint(entireHeaderRectangle, point); |
| } |
| |
| private function getFixedHeaderViewContainsPointAssumption(point:Point):Boolean |
| { |
| return rectangleContainsPoint(fixedHeaderViewRectangle, point); |
| } |
| |
| private function getMainHeaderViewContainsPointAssumption(visibleHeaderViewRectangle:Rectangle, point:Point):Boolean |
| { |
| return rectangleContainsPoint(visibleHeaderViewRectangle, point); |
| } |
| |
| private function getHeaderIndexAssumption(point:Point, visibleColumnHeaderRectangles:Array):int |
| { |
| return getIndexOfRectangleWhichContainsPoint(point, visibleColumnHeaderRectangles); |
| } |
| |
| private function getColumnIndexAssumption(visibleColumnRectangles:Array, point:Point):int |
| { |
| return getIndexOfRectangleWhichContainsPoint(point, visibleColumnRectangles); |
| } |
| |
| private function getIndexOfRectangleWhichContainsPoint(point:Point, rectangles:Array):int |
| { |
| for (var i:int = 0; i < rectangles.length; i++) |
| { |
| if(rectangleContainsPoint(rectangles[i], point)) |
| return i; |
| } |
| |
| return -1; |
| } |
| |
| private function rectangleContainsPoint(rectangle:Rectangle, point:Point):Boolean |
| { |
| return rectangle.containsPoint(point); |
| } |
| |
| private function getAdjacentPoint(point:Point, direction:Matrix):Point |
| { |
| return direction.transformPoint(point); |
| } |
| |
| private function generateKeyPoints(grid:DataGrid):Array |
| { |
| var keyPoints:Array = []; |
| |
| keyPoints["a"] = new Point(0, 0); |
| keyPoints["b0"] = new Point(getX(_dimensions), getY(_dimensions)); |
| generateColumnIntermediates(keyPoints, _dimensions, "b0"); |
| keyPoints["c0"] = new Point(getX(_dimensions) + getHeaderPaddingLeft(_dimensions), getY(_dimensions)); |
| generateColumnIntermediates(keyPoints, _dimensions, "c0"); |
| keyPoints["d"] = new Point(getX(_dimensions) + getWidth(_dimensions), getY(_dimensions)); |
| keyPoints["e"] = new Point(Point(keyPoints["c0"]).x, getY(_dimensions) + getHeaderPaddingTop(_dimensions)); |
| keyPoints["f"] = new Point(Point(keyPoints["c0"]).x, getY(_dimensions) + getActualHeaderHeight(grid) - getHeaderPaddingBottom(_dimensions)); |
| keyPoints["g0"] = new Point(getX(_dimensions), getY(_dimensions) + getActualHeaderHeight(grid)); |
| generateColumnIntermediates(keyPoints, _dimensions, "g0"); |
| keyPoints["i"] = new Point(getX(_dimensions) + getWidth(_dimensions), Point(keyPoints["g0"]).y); |
| return keyPoints; |
| } |
| |
| private function generateColumnIntermediates(keyPoints:Array, dimensions:Array, initialPointName:String):void |
| { |
| const initialPoint:Point = keyPoints[initialPointName]; |
| const y:Number = initialPoint.y; |
| var currentX:Number = initialPoint.x; |
| const initialPointFirstCharacter:String = initialPointName.charAt(0); |
| for (var i:int = 0; i < getColumnWidths(dimensions).length; i++) |
| { |
| currentX += getColumnWidth(dimensions, i); |
| keyPoints[initialPointFirstCharacter + (i+1)] = new Point(currentX, y); |
| } |
| } |
| |
| private function generateKeyRectangles():Array |
| { |
| var keyRectangles:Array = []; |
| |
| keyRectangles[ENTIRE_HEADER_RECTANGLE] = generateVisibleHeaderRectangle(); |
| keyRectangles[FIXED_HEADER_VIEW_RECTANGLE] = generateFixedHeaderViewRectangle(); |
| |
| return keyRectangles; |
| } |
| |
| private function generateFixedHeaderViewRectangle():Rectangle |
| { |
| //this is the GridColumnHeaderGroup.centerGridColumnHeaderView, which is holds the non-fixed columns; padding excluded |
| const topLeftCorner:Point = _keyPoints["e"]; |
| return new Rectangle(topLeftCorner.x, topLeftCorner.y, 0, 0); |
| } |
| |
| private function generateVisibleHeaderRectangle():Rectangle |
| { |
| const topLeftCorner:Point = _keyPoints["b0"]; |
| const bottomRightCorner:Point = _keyPoints["i"]; |
| return new Rectangle(topLeftCorner.x, topLeftCorner.y, bottomRightCorner.x - topLeftCorner.x, bottomRightCorner.y - topLeftCorner.y); |
| } |
| |
| |
| private function getActualHeaderHeight(grid:DataGrid):Number |
| { |
| //Note that we're assuming the grid is on stage and validated by this point! |
| return grid.columnHeaderGroup.height; |
| } |
| |
| private function getCurrentHScrollPosition():Number |
| { |
| return _dataGrid.grid.horizontalScrollPosition; |
| } |
| |
| |
| private function getVisibleHeaderViewRectangle(hScrollPosition:Number = 0):Rectangle |
| { |
| //this is the GridColumnHeaderGroup.centerGridColumnHeaderView, which holds the non-fixed columns; padding excluded |
| const topLeftCorner:Point = _keyPoints["e"]; |
| return new Rectangle(topLeftCorner.x, topLeftCorner.y, |
| getHeaderWidthFromKeyPoints(_keyPoints) - getHeaderPaddingLeft(_dimensions), |
| getHeaderHeightFromKeyPoints(_keyPoints) - getHeaderPaddingTop(_dimensions) - getHeaderPaddingBottom(_dimensions)); |
| } |
| |
| private function getVisibleColumnHeaderRectangles(hScrollPosition:Number = 0):Array |
| { |
| var headerRectangles:Array = []; |
| |
| const headerPaddingTop:Number = getHeaderPaddingTop(_dimensions); |
| const headerPaddingBottom:Number = getHeaderPaddingBottom(_dimensions); |
| const headerHeight:Number = getHeaderHeightFromKeyPoints(_keyPoints) - headerPaddingTop - headerPaddingBottom; |
| const numColumns:uint = getColumnWidths(_dimensions).length; |
| const headerPaddingLeft:Number = getHeaderPaddingLeft(_dimensions); |
| const headerWidth:Number = getWidth(_dimensions) - headerPaddingLeft; |
| const e:Point = _keyPoints["e"]; |
| const visibleRectangle:Rectangle = new Rectangle(e.x, e.y, headerWidth, 100); |
| var totalColumnWidths:Number = getTotalColumnWidths(_dimensions); |
| var columnHeaderY:Number = NaN; |
| |
| //create the header rectangles from the first visible point on the left until the end |
| for (var i:int = 0; i < numColumns; i++) |
| { |
| var topLeft:Point = _keyPoints["c" + i]; |
| var topRight:Point = _keyPoints["c" + (i+1)]; |
| var topLeftX:Number = topLeft.x - hScrollPosition; |
| var topRightX:Number = topRight.x - hScrollPosition; |
| |
| if(isNaN(columnHeaderY)) |
| columnHeaderY = topLeft.y + headerPaddingTop; |
| |
| var endsBeforeVisibleRectangle:Boolean = topRightX < visibleRectangle.x; |
| var startsAfterVisibleRectangle:Boolean = topLeftX >= visibleRectangle.x + visibleRectangle.width; |
| |
| if(!(endsBeforeVisibleRectangle || startsAfterVisibleRectangle)) |
| { |
| const startingX:Number = Math.max(topLeftX, visibleRectangle.x); |
| const rightEdge:Number = Math.min(topRightX, visibleRectangle.x + visibleRectangle.width); |
| const width:Number = rightEdge - startingX; |
| headerRectangles.push(new Rectangle(startingX, columnHeaderY, width, headerHeight)); |
| } |
| } |
| |
| assertThat("no example has 0 columns, so we expect this Array to have at least one item.", headerRectangles.length > 0); |
| |
| //correct last header rectangle to extend to grid boundaries if the total width of all the columns is smaller |
| //than the grid's width. It is one of the issues which prompted this unit test in the first place. |
| if(totalColumnWidths <= headerWidth) |
| { |
| var lastHeaderRectangle:Rectangle = headerRectangles[headerRectangles.length - 1]; |
| lastHeaderRectangle.width = Point(_keyPoints["d"]).x - lastHeaderRectangle.x; |
| } |
| |
| return headerRectangles; |
| } |
| |
| |
| //Note that the height and y of the rectangles needs to be all-encompassing until FLEX-35280 is fixed |
| private function getAllColumnRectangles(hScrollPosition:Number = 0):Array |
| { |
| var columnRectangles:Array = []; |
| const numColumns:uint = getColumnWidths(_dimensions).length; |
| |
| for (var i:int = 0; i < numColumns; i++) |
| { |
| var topLeft:Point = _keyPoints["g" + i]; |
| var topRight:Point = _keyPoints["g" + (i+1)]; |
| |
| columnRectangles.push(new Rectangle(topLeft.x, -10000, topRight.x - topLeft.x, Number.MAX_VALUE)); |
| } |
| |
| return columnRectangles; |
| } |
| |
| /* key rectangles getters */ |
| |
| private function get entireHeaderRectangle():Rectangle //includes padding |
| { |
| return _keyRectangles[ENTIRE_HEADER_RECTANGLE] as Rectangle; |
| } |
| |
| private function get fixedHeaderViewRectangle():Rectangle |
| { |
| return _keyRectangles[FIXED_HEADER_VIEW_RECTANGLE] as Rectangle; |
| } |
| |
| /* key points getters */ |
| |
| private function getColumnWidthFromKeyPoints(keyPoints:Array, columnIndex:int):Number |
| { |
| //we're assuming columnIndex has a valid value |
| return Point(keyPoints["c" + (columnIndex + 1)]).x - Point(keyPoints["c" + columnIndex]).x; |
| } |
| |
| private function getHeaderHeightFromKeyPoints(keyPoints:Array):Number |
| { |
| return Point(keyPoints["i"]).y - Point(keyPoints["d"]).y; |
| } |
| |
| private function getHeaderWidthFromKeyPoints(keyPoints:Array):Number |
| { |
| return Point(keyPoints["d"]).x - Point(keyPoints["b0"]).x; |
| } |
| |
| /* dimensions getters */ |
| |
| private function getX(dimensions:Array):Number |
| { |
| return dimensions[0]; |
| } |
| |
| private function getY(dimensions:Array):Number |
| { |
| return dimensions[1]; |
| } |
| |
| private function getWidth(dimensions:Array):Number |
| { |
| return dimensions[2]; |
| } |
| |
| private function getHeaderPaddingLeft(dimensions:Array):Number |
| { |
| return dimensions[3]; |
| } |
| |
| private function getHeaderPaddingTop(dimensions:Array):Number |
| { |
| return dimensions[4]; |
| } |
| |
| private function getHeaderPaddingBottom(dimensions:Array):Number |
| { |
| return dimensions[5]; |
| } |
| |
| private function getColumnWidths(dimensions:Array):Array |
| { |
| return dimensions[6]; |
| } |
| |
| private function getColumnWidth(dimensions:Array, columnIndex:int):Number |
| { |
| return getColumnWidths(dimensions)[columnIndex]; |
| } |
| |
| private function getTotalColumnWidths(dimensions:Array):Number |
| { |
| var sum:Number = 0; |
| getColumnWidths(dimensions).forEach(function (item:*, index:int, arr:Array):void {sum += item;}); |
| return sum; |
| } |
| |
| |
| private function onEnterFrame(event:Event):void |
| { |
| if(!--_noEnterFramesRemaining) |
| { |
| UIImpersonator.testDisplay.removeEventListener(Event.ENTER_FRAME, onEnterFrame); |
| _finishNotifier.dispatchEvent(new Event(Event.COMPLETE)); |
| } |
| } |
| |
| private function get _sut():GridColumnHeaderGroup |
| { |
| return _dataGrid.columnHeaderGroup; |
| } |
| } |
| } |