UNPKG

@eclipse-glsp/protocol

Version:

The protocol definition for client-server communication in GLSP

368 lines (301 loc) 13.9 kB
/******************************************************************************** * Copyright (c) 2024 EclipseSource and others. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0 which is available at * http://www.eclipse.org/legal/epl-2.0. * * This Source Code may also be made available under the following Secondary * Licenses when the conditions for such availability set forth in the Eclipse * Public License v. 2.0 are satisfied: GNU General Public License, version 2 * with the GNU Classpath Exception which is available at * https://www.gnu.org/software/classpath/license.html. * * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 ********************************************************************************/ /* eslint-disable @typescript-eslint/no-shadow */ import { Bounds } from 'sprotty-protocol/lib/utils/geometry'; import { Dimension } from './sprotty-geometry-dimension'; import { Point } from './sprotty-geometry-point'; import { AnyObject, hasNumberProp } from './utils/type-util'; declare module 'sprotty-protocol/lib/utils/geometry' { namespace Bounds { /** * The empty bounds with valid dimensions. It has x, y, width, and height set to 0. */ const ZERO: Bounds; /** * Type guard to check if the given object is a bound. * @param bounds the object to be checked */ function is(bounds: any): bounds is Bounds; /** * Type guard to check if a bound is valid. For a bound to be valid it needs to be defined and have valid * coordinates and dimensions. * * @param bounds the bounds to be checked for validity */ function isValid(bounds?: Bounds): bounds is Bounds; /** * Checks whether the inner bounds are compeletely encompassed by the outer bounds. * * @param outer outer bounds * @param inner inner bounds * @returns true if the outer bounds completely encompass the inner bounds */ function encompasses(outer: Bounds, inner: Bounds): boolean; /** * Checks whether the two bounds overlap. * * @param left left bounds * @param right right bounds * @param touch if true the bounds are considered to overlap if they touch each other * @returns true if the two bounds overlap */ function overlap(left: Bounds, right: Bounds, touch?: boolean): boolean; /** * Checks whether the two bounds are equal. * @param left left bounds * @param right right bounds * @param eps the epsilon for the comparison * @returns true if the two bounds are equal */ function equals(left: Bounds, right: Bounds, eps?: number): boolean; /** * Returns the x-coordinate of the left edge of the bounds. * @param bounds the bounds * @returns the x-coordinate of the left edge */ function left(bounds: Bounds): number; /** * Returns the x-coordinate of the center of the bounds. * @param bounds the bounds * @returns the x-coordinate of the center */ function centerX(bounds: Bounds): number; /** * Returns the x-coordinate of the right edge of the bounds. * @param bounds the bounds * @returns the x-coordinate of the right edge */ function right(bounds: Bounds): number; /** * Returns the y-coordinate of the top edge of the bounds. * @param bounds the bounds * @returns the y-coordinate of the top edge */ function top(bounds: Bounds): number; /** * Returns the y-coordinate of the middle of the bounds. * @param bounds the bounds * @returns the y-coordinate of the middle */ function middle(bounds: Bounds): number; /** * Returns the y-coordinate of the center of the bounds. * @param bounds the bounds * @returns the y-coordinate of the center */ function centerY(bounds: Bounds): number; /** * Returns the y-coordinate of the bottom edge of the bounds. * @param bounds the bounds * @returns the y-coordinate of the bottom edge */ function bottom(bounds: Bounds): number; /** * Returns the top left corner of the bounds. * @param bounds the bounds * @returns the top left corner */ function topLeft(bounds: Bounds): Point; /** * Returns the top center point of the bounds. * @param bounds the bounds * @returns the top center point */ function topCenter(bounds: Bounds): Point; /** * Returns the top right corner of the bounds. * @param bounds the bounds * @returns the top right corner */ function topRight(bounds: Bounds): Point; /** * Returns the middle left point of the bounds. * @param bounds the bounds * @returns the middle left point */ function middleLeft(bounds: Bounds): Point; /** * Returns the middle center point of the bounds. * @param bounds the bounds * @returns the middle center point */ function middleCenter(bounds: Bounds): Point; /** * Returns the middle right point of the bounds. * @param bounds the bounds * @returns the middle right point */ function middleRight(bounds: Bounds): Point; /** * Returns the bottom left corner of the bounds. * @param bounds the bounds * @returns the bottom left corner */ function bottomLeft(bounds: Bounds): Point; /** * Returns the bottom center point of the bounds. * @param bounds the bounds * @returns the bottom center point */ function bottomCenter(bounds: Bounds): Point; /** * Returns the bottom right corner of the bounds. * @param bounds the bounds * @returns the bottom right corner */ function bottomRight(bounds: Bounds): Point; /** * Checks if the left bounds are above the right bounds, i.e., the top edge of the left bounds is * above the top edge of the right bounds. * @param leftBounds the left bounds * @param rightBounds the right bounds * @returns true if the left bounds are above the right bounds */ function isAbove(leftBounds: Bounds, rightBounds: Bounds): boolean; /** * Checks if the left bounds are below the right bounds, i.e., the top edge of the left bounds is * below the top edge of the right bounds. * @param leftBounds the left bounds * @param rightBounds the right bounds * @returns true if the left bounds are below the right bounds */ function isBelow(leftBounds: Bounds, rightBounds: Bounds): boolean; /** * Checks if the left bounds are before the right bounds, i.e., the left edge of the left bounds is * before the left edge of the right bounds. * @param leftBounds the left bounds * @param rightBounds the right bounds * @returns true if the left bounds are before the right bounds */ function isBefore(leftBounds: Bounds, rightBounds: Bounds): boolean; /** * Checks if the left bounds are after the right bounds, i.e., the left edge of the left bounds is * after the left edge of the right bounds. * @param leftBounds the left bounds * @param rightBounds the right bounds * @returns true if the left bounds are after the right bounds */ function isAfter(leftBounds: Bounds, rightBounds: Bounds): boolean; /** * Creates a bounds from the given top left and bottom right points. * @param topLeft top left point * @param bottomRight bottom right point * @returns the bounds */ function from(topLeft: Point, bottomRight: Point): Bounds; /** * Creates a new point from the given bounds by removing the `width` and `height` of the bounds. * This is the same as the top-left point but this method may carry more semantics. * @param bounds the bounds * @returns new point */ function position(bounds: Bounds): Point; /** * Creates a new dimension from the given bounds by removing the `x` and `y` of the bounds. * @param bounds the bounds * @returns new dimension */ function dimension(bounds: Bounds): Dimension; /** * Sorts the given bounds by the given rank function. * @param rankFunc the rank function * @param bounds the bounds to sort * @returns the sorted bounds */ function sortBy<T>(rankFunc: (elem: T) => number, ...bounds: T[]): T[]; /** * Moves the bounds by the given delta. * @param bounds the bounds to move * @param delta the delta to move the bounds by * @returns the moved bounds */ function move(bounds: Bounds, delta: Point): Bounds; /** * Resizes the bounds by the given delta. * @param bounds the bounds to resize * @param delta the delta to resize the bounds by * @returns the resized bounds */ function resize(bounds: Bounds, delta: Dimension): Bounds; } } (Bounds as any).ZERO = Object.freeze({ x: 0, y: 0, width: 0, height: 0 }); Bounds.is = (bounds: any): bounds is Bounds => AnyObject.is(bounds) && hasNumberProp(bounds, 'x') && hasNumberProp(bounds, 'y') && hasNumberProp(bounds, 'width') && hasNumberProp(bounds, 'height'); Bounds.isValid = (bounds?: Bounds): bounds is Bounds => bounds !== undefined && Dimension.isValid(bounds) && Point.isValid(bounds); Bounds.encompasses = (outer: Bounds, inner: Bounds): boolean => Bounds.includes(outer, Bounds.topLeft(inner)) && Bounds.includes(outer, Bounds.bottomRight(inner)); Bounds.overlap = (one: Bounds, other: Bounds, touch?: boolean): boolean => { const oneTopLeft: Point = Bounds.topLeft(one); const oneBottomRight = Bounds.bottomRight(one); const otherTopLeft: Point = Bounds.topLeft(other); const otherBottomRight = Bounds.bottomRight(other); return touch ? oneTopLeft.x <= otherBottomRight.x && otherTopLeft.x <= oneBottomRight.x && oneBottomRight.y >= otherTopLeft.y && otherBottomRight.y >= oneTopLeft.y : oneTopLeft.x < otherBottomRight.x && otherTopLeft.x < oneBottomRight.x && oneBottomRight.y > otherTopLeft.y && otherBottomRight.y > oneTopLeft.y; }; Bounds.equals = (left: Bounds, right: Bounds, eps?: number): boolean => Point.equals(left, right, eps) && Dimension.equals(left, right, eps); Bounds.left = (bounds: Bounds): number => bounds.x; Bounds.centerX = (bounds: Bounds): number => bounds.x + (bounds.width >= 0 ? bounds.width * 0.5 : 0); Bounds.right = (bounds: Bounds): number => bounds.x + bounds.width; Bounds.top = (bounds: Bounds): number => bounds.y; Bounds.middle = (bounds: Bounds): number => bounds.y + (bounds.height >= 0 ? bounds.height * 0.5 : 0); Bounds.centerY = Bounds.middle; Bounds.bottom = (bounds: Bounds): number => bounds.y + bounds.height; Bounds.topLeft = (bounds: Bounds): Point => ({ x: Bounds.left(bounds), y: Bounds.top(bounds) }); Bounds.topCenter = (bounds: Bounds): Point => ({ x: Bounds.centerX(bounds), y: Bounds.top(bounds) }); Bounds.topRight = (bounds: Bounds): Point => ({ x: Bounds.right(bounds), y: Bounds.top(bounds) }); Bounds.middleLeft = (bounds: Bounds): Point => ({ x: Bounds.left(bounds), y: Bounds.middle(bounds) }); Bounds.middleCenter = (bounds: Bounds): Point => ({ x: Bounds.centerX(bounds), y: Bounds.middle(bounds) }); Bounds.middleRight = (bounds: Bounds): Point => ({ x: Bounds.right(bounds), y: Bounds.middle(bounds) }); Bounds.bottomLeft = (bounds: Bounds): Point => ({ x: Bounds.left(bounds), y: Bounds.bottom(bounds) }); Bounds.bottomCenter = (bounds: Bounds): Point => ({ x: Bounds.centerX(bounds), y: Bounds.bottom(bounds) }); Bounds.bottomRight = (bounds: Bounds): Point => ({ x: Bounds.right(bounds), y: Bounds.bottom(bounds) }); Bounds.isAbove = (leftBounds: Bounds, rightBounds: Bounds): boolean => Bounds.top(leftBounds) <= Bounds.top(rightBounds); Bounds.isBelow = (leftBounds: Bounds, rightBounds: Bounds): boolean => Bounds.top(leftBounds) >= Bounds.top(rightBounds); Bounds.isBefore = (leftBounds: Bounds, rightBounds: Bounds): boolean => Bounds.left(leftBounds) < Bounds.left(rightBounds); Bounds.isAfter = (leftBounds: Bounds, rightBounds: Bounds): boolean => Bounds.left(leftBounds) >= Bounds.left(rightBounds); Bounds.sortBy = <T>(rankFunc: (elem: T) => number, ...bounds: T[]): T[] => bounds.sort((left, right) => rankFunc(left) - rankFunc(right)); Bounds.from = (topLeft: Point, bottomRight: Point): Bounds => ({ ...topLeft, width: bottomRight.x - topLeft.x, height: bottomRight.y - topLeft.y }); Bounds.position = Bounds.topLeft; Bounds.dimension = (bounds: Bounds): Dimension => ({ width: bounds.width, height: bounds.height }); Bounds.move = Bounds.translate; Bounds.resize = (bounds: Bounds, delta: Dimension): Bounds => ({ ...bounds, width: bounds.width + delta.width, height: bounds.height + delta.height }); export { Bounds };