license import { MatGridTile } from './grid-tile' ; docs-private export class TileCoordinator { /** Tracking array (see class description). */ tracker : number [ ] ; /** Index at which the search for the next gap will start. */ columnIndex : number = 0 ; /** The current row index. */ rowIndex : number = 0 ; /** Gets the total number of rows occupied by tiles */ get rowCount ( ) : number { return this . rowIndex + 1 ; } /**
     * Gets the total span of rows occupied by tiles.
     * Ex: A list with 1 row that contains a tile with rowspan 2 will have a total rowspan of 2.
     */ get rowspan ( ) { const lastRowMax = Math . max ( ... this . tracker ) ; return lastRowMax > 1 ? this . rowCount + lastRowMax - 1 : this . rowCount ; } /** The computed (row, col) position of each tile (the output). */ positions : TilePosition [ ] ; param numColumns update ( numColumns , tiles ) { this . columnIndex = 0 ; this . rowIndex = 0 ; this . tracker = new Array ( numColumns ) ; this . tracker . fill ( 0 , 0 , this . tracker . length ) ; this . positions = tiles . map ( tile => this . _trackTile ( tile ) ) ; } /** Calculates the row and col position of a tile. */ private _trackTile ( tile ) { const gapStartIndex = this . _findMatchingGap ( tile . colspan ) ; this . _markTilePosition ( gapStartIndex , tile ) ; this . columnIndex = gapStartIndex + tile . colspan ; return new TilePosition ( this . rowIndex , gapStartIndex ) ; } /** Finds the next available space large enough to fit the tile. */ private _findMatchingGap ( tileCols ) { if ( tileCols > this . tracker . length ) { throw Error ( `mat-grid-list: tile with colspan ${ tileCols } is wider than ` + `grid with cols="${ this . tracker . length }".` ) ; } let gapStartIndex = - 1 ; let gapEndIndex = - 1 ; do { if ( this . columnIndex + tileCols > this . tracker . length ) { this . _nextRow ( ) ; gapStartIndex = this . tracker . indexOf ( 0 , this . columnIndex ) ; gapEndIndex = this . _findGapEndIndex ( gapStartIndex ) ; continue ; } gapStartIndex = this . tracker . indexOf ( 0 , this . columnIndex ) ; if ( gapStartIndex == - 1 ) { this . _nextRow ( ) ; gapStartIndex = this . tracker . indexOf ( 0 , this . columnIndex ) ; gapEndIndex = this . _findGapEndIndex ( gapStartIndex ) ; continue ; } gapEndIndex = this . _findGapEndIndex ( gapStartIndex ) ; this . columnIndex = gapStartIndex + 1 ; } while ( ( gapEndIndex - gapStartIndex < tileCols ) || ( gapEndIndex == 0 ) ) ; return Math . max ( gapStartIndex , 0 ) ; } /** Move "down" to the next row. */ private _nextRow ( ) { this . columnIndex = 0 ; this . rowIndex ++ ; for ( let i = 0 ; i < this . tracker . length ; i ++ ) { this . tracker [ i ] = Math . max ( 0 , this . tracker [ i ] - 1 ) ; } } /**
     * Finds the end index (exclusive) of a gap given the index from which to start looking.
     * The gap ends when a non-zero value is found.
     */ private _findGapEndIndex ( gapStartIndex ) { for ( let i = gapStartIndex + 1 ; i < this . tracker . length ; i ++ ) { if ( this . tracker [ i ] != 0 ) { return i ; } } return this . tracker . length ; } /** Update the tile tracker to account for the given tile in the given space. */ private _markTilePosition ( start , tile ) { for ( let i = 0 ; i < tile . colspan ; i ++ ) { this . tracker [ start + i ] = tile . rowspan ; } } } docs-private export class TilePosition { constructor ( public row , public col ) { } }