/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ /** * A position in a grid. This interface is suitable for serialization. */ export interface IGridPosition { /** * line number (starts at 1) */ readonly row: number; /** * column */ readonly column: number; } /** * A position in a grid. */ export class GridPosition { /** * row (starts at 1) */ public readonly row: number; /** * column */ public readonly column: number; constructor(row: number, column: number) { this.row = row; this.column = column; } /** * Create a new postion from this position. * * @param newRow new row * @param newColumn new column */ with(newRow: number = this.row, newColumn: number = this.column): GridPosition { if (newRow === this.row && newColumn === this.column) { return this; } else { return new GridPosition(newRow, newColumn); } } /** * Derive a new grid position from this grid position. * * @param deltaRow row delta * @param deltaColumn column delta */ delta(deltaRow: number = 0, deltaColumn: number = 0): GridPosition { return this.with(this.row + deltaRow, this.column + deltaColumn); } /** * Test if this grid position equals other grid position */ public equals(other: IGridPosition): boolean { return GridPosition.equals(this, other); } /** * Test if grid position `a` equals grid position `b` */ public static equals(a: IGridPosition | null, b: IGridPosition | null): boolean { if (!a && !b) { return true; } return ( !!a && !!b && a.row === b.row && a.column === b.column ); } /** * Test if this grid position is before other grid position. * If the two grid positions are equal, the result will be false. */ public isBefore(other: IGridPosition): boolean { return GridPosition.isBefore(this, other); } /** * Test if grid position `a` is before grid position `b`. * If the two grid positions are equal, the result will be false. */ public static isBefore(a: IGridPosition, b: IGridPosition): boolean { if (a.row < b.row) { return true; } if (b.row < a.row) { return false; } return a.column < b.column; } /** * Test if this grid position is before other grid position. * If the two grid positions are equal, the result will be true. */ public isBeforeOrEqual(other: IGridPosition): boolean { return GridPosition.isBeforeOrEqual(this, other); } /** * Test if grid position `a` is before grid position `b`. * If the two grid positions are equal, the result will be true. */ public static isBeforeOrEqual(a: IGridPosition, b: IGridPosition): boolean { if (a.row < b.row) { return true; } if (b.row < a.row) { return false; } return a.column <= b.column; } /** * A function that compares grid positions, useful for sorting */ public static compare(a: IGridPosition, b: IGridPosition): number { let aRow = a.row | 0; let bRow = b.row | 0; if (aRow === bRow) { let aColumn = a.column | 0; let bColumn = b.column | 0; return aColumn - bColumn; } return aRow - bRow; } /** * Clone this grid position. */ public clone(): GridPosition { return new GridPosition(this.row, this.column); } /** * Convert to a human-readable representation. */ public toString(): string { return '(' + this.row + ',' + this.column + ')'; } // --- /** * Create a `GridPosition` from an `IGridPosition`. */ public static lift(pos: IGridPosition): GridPosition { return new GridPosition(pos.row, pos.column); } /** * Test if `obj` is an `IGridPosition`. */ public static isIGridPosition(obj: any): obj is IGridPosition { return ( obj && (typeof obj.row === 'number') && (typeof obj.column === 'number') ); } }