import { KGraphData, SKGraphElement } from '@kieler/klighd-interactive/lib/constraint-classes';
import { VNode } from 'snabbdom';
import { ActionHandlerRegistry, IActionHandler, IActionHandlerInitializer, ICommand, SModelRootImpl } from 'sprotty';
import { Action, Bounds, Dimension, Point, Viewport } from 'sprotty-protocol';
import { SKEdge, SKLabel, SKNode, SKPort } from '../skgraph-models';
/** Suffix of a proxy's ID. */
export declare const PROXY_SUFFIX = "$proxy";
/**
 * Contains all attributes used in defining a VNode's transform attribute.
 * @example (x, y, width, height, scale, rotation)
 */
export interface TransformAttributes extends Bounds {
    readonly scale?: number;
    readonly rotation?: number;
    readonly rotationPoint?: Point;
}
/**
 * Contains all canvas-related attributes.
 * CRF - Canvas Reference Frame.
 * The canvas reference frames is the coordinate system defined by the viewport bounds.
 * The position (0,0) is in the top left corner of the viewport on the canvas. This means
 * that scroll and zoom are already accounted for.
 * GRF - Global Reference Frame.
 * The global reference frame is the coordinate system defined by the svg bounds. The
 * position (0,0) is the top left corner of the svg. All coordinates are absolute
 * positions in the svg.
 * @example (x, y, width, height, scroll, zoom)
 */
export interface Canvas extends Viewport, Bounds {
    /**
     * Whether the canvas is in GRF, i.e. not in CRF.
     * Usually doesn't need to be set explicitly - handled by translation methods.
     * When the canvas hasn't been translated yet, this should be `undefined` or `false`,
     * as the canvas should be in the CRF.
     */
    isInGRF?: boolean;
}
export declare namespace Canvas {
    /**
     * Creates a canvas in CRF.
     * @param boundsOrRoot The canvas' bounds or the root element.
     * @param viewport The viewport.
     * @returns The canvas.
     */
    function of(boundsOrRoot: Bounds | SModelRootImpl, viewport: Viewport): Canvas;
    /**
     * Returns the bounds translated from the GRF to the CRF.
     * E.g. calculates its position & width/height according to scroll and zoom.
     * Inverse to {@link translateToGRF()}.
     * @param originalBounds The bounds/point/dimension in the GRF.
     * @param canvas The canvas.
     * @returns The bounds translated to the CRF.
     */
    function translateToCRF(originalBounds: Bounds | Point | Dimension, canvas: Canvas): Bounds;
    /**
     * Returns the bounds translated from the CRF to the GRF.
     * Inverse to {@link translateToCRF()}.
     * @param originalBounds The bounds/point/dimension in the CRF.
     * @param canvas The canvas.
     * @returns The bounds translated to the GRF.
     */
    function translateToGRF(originalBounds: Bounds | Point | Dimension, canvas: Canvas): Bounds;
    /**
     * Adds `p1` and `p2` and translates the result to the CRF.
     * @param p1 The first point.
     * @param p2 The second point.
     * @param canvas The canvas.
     */
    function translateToCRFAdd(p1: Point, p2: Point, canvas: Canvas): Point;
    /**
     * Translates the canvas from the GRF to the CRF, if not already in CRF.
     * Inverse to {@link translateCanvasToGRF()}.
     * @param canvas The canvas.
     * @returns The canvas translated to the CRF.
     */
    function translateCanvasToCRF(canvas: Canvas): Canvas;
    /**
     * Translates the canvas from the CRF to the GRF, if not already in GRF.
     * Inverse to {@link translateCanvasToCRF()}.
     * @param canvas The canvas.
     * @returns The canvas translated to the GRF.
     */
    function translateCanvasToGRF(canvas: Canvas): Canvas;
    /**
     * Checks if `bounds` is (partially) on-screen.
     * Note that `bounds` and `canvas` need to be in the same Reference Frame.
     * @param bounds The bounds to check.
     * @returns `true` if `b` is (partially) on-screen.
     */
    function isOnScreen(bounds: Bounds, canvas: Canvas): boolean;
    /**
     * Returns the distance between the bounds and the canvas.
     * @see {@link distanceBetweenBounds()} for an explanation on how the distance is calculated.
     * Note that `bounds` and `canvas` need to be in the same Reference Frame.
     *
     * @param bounds The bounds/point to calculate the distance to the canvas for.
     * @param canvas The canvas.
     * @returns The distance between the bounds and the canvas.
     */
    function distance(bounds: Bounds | Point, canvas: Canvas): number;
    /**
     * Performs along-border-routing from `from` to `to`, both of which need to be at their respective border already.
     * Note that `from` and `to` are not part of the returned path.
     * @param from The bounds/point to route along the border from.
     * @param fromBorder The border for `from`.
     * @param to The bounds/point to route along the border to.
     * @param toBorder The border for `to`.
     * @param preferLeft Whether routing left should be preferred when `from` and `to` are vertically opposite of each other.
     * @param preferTop Whether routing top should be preferred when `from` and `to` are horizontally opposite of each other.
     * @returns A path along the border from `from` to `to`. Exclusive, e.g. (from, to).
     */
    function routeAlongBorder(from: Bounds | Point, fromBorder: Bounds, to: Bounds | Point, toBorder: Bounds, preferLeft?: boolean, preferTop?: boolean): Point[];
    /**
     * Offsets the canvas by the given values.
     * @param canvas The canvas.
     * @param offset The offset. Values `>0` reduce the canvas size.
     * @returns An offset canvas.
     */
    function offsetCanvas(canvas: Canvas, offset: number | Rect): Canvas;
    /**
     * Returns the given bounds capped to the canvas border w.r.t. the sidebar if enabled.
     * Note that `bounds` and `canvas` need to be in CRF.
     * Also, `bounds` has to contain the absolute position (not relative to parent).
     * @param bounds The bounds/point to cap to the canvas border, absolute.
     * @param canvas The canvas.
     * @param capToSidebar Whether the bounds should also be capped to the sidebar.
     * @returns The given bounds capped to the canvas border w.r.t. the sidebar if enabled.
     */
    function capToCanvas(bounds: Bounds | Point, canvas: Bounds, capToSidebar?: boolean): Bounds;
}
/** Like {@link Bounds} but contains coordinates instead of width and height. */
export interface Rect {
    readonly left: number;
    readonly right: number;
    readonly top: number;
    readonly bottom: number;
}
export declare namespace Rect {
    /** A Rect with all coordinates as zeros. */
    const EMPTY: Rect;
    /**
     * Returns `bounds` as a Rect.
     * @param bounds The Bounds/Dimension to transform into a Rect.
     * @returns The Rect corresponding to `bounds`.
     */
    function fromBounds(bounds: Bounds | Dimension): Rect;
    /**
     * Returns `rect` as Bounds.
     * @param rect The Rect to transform into Bounds.
     * @returns The Bounds corresponding to `rect`.
     */
    function toBounds(rect: Rect): Bounds;
}
/** A VNode containing some additional information to be used only by the {@link ProxyView}. */
export interface ProxyVNode extends VNode {
    /** Whether this vnode is selected. */
    selected?: boolean;
    /** Indicates that this vnode is for a proxy. */
    proxy?: boolean;
}
/** KGraphData containing some additional information to be used only by the {@link ProxyView}. */
export interface ProxyKGraphData extends KGraphData {
    /** The proxy's scale. */
    proxyScale: number;
    /** Whether title scaling should be used if smart zoom is enabled. */
    useTitleScaling: boolean;
}
/**
 * Checks if this vnode is for a proxy.
 * @param vnode The vnode to check this property for.
 * @returns If the vnode is for a proxy.
 */
export declare function isProxy(vnode: VNode): vnode is ProxyVNode;
/**
 * Determines if the SVG element is a proxy rendering for the given node ID.
 * @param element The SVG element to check.
 * @param nodeId The ID of the node to check.
 * @returns if the SVG element is a proxy rendering for the given node ID.
 */
export declare function isProxyRendering(element: SVGElement, nodeId: string): boolean;
/** Appends {@link PROXY_SUFFIX} to the given id if the given id isn't already a proxy's id. */
export declare function getProxyId(id: string): string;
/** Removes {@link PROXY_SUFFIX} from the given id if the given id is a proxy's id. */
export declare function getNodeId(id: string): string;
/**
 * Checks if `b1` is (partially) in `b2`.
 * @returns `true` if `b1` is (partially) in `b2`.
 */
export declare function isInBounds(b1: Bounds, b2: Bounds): boolean;
/**
 * Checks if the given bounds overlap.
 * @returns `true` if there is overlap.
 */
export declare function checkOverlap(b1: Bounds, b2: Bounds): boolean;
/**
 * Returns `bpd` if given bounds, otherwise fills the empty attributes with zeros.
 * @param bpd The bounds/point/dimension.
 */
export declare function asBounds(bpd: Bounds | Point | Dimension): Bounds;
/**
 * Returns `n` capped to the range given by `rangeExtreme1` and `rangeExtreme2`
 * (inclusive), e.g. `n` in `[rangeExtreme1, rangeExtreme2]`.
 * @param n The number to cap.
 * @param rangeExtreme1 The lower bound of the range.
 * @param rangeExtreme2 The upper bound of the range.
 * @returns `n` capped to the given range. If `rangeExtreme1 > rangeExtreme2`,
 * the two are swapped.
 */
export declare function capNumber(n: number, rangeExtreme1: number, rangeExtreme2: number): number;
/**
 * Returns the distance between two bounds. If given two points, this
 * basically just calculates the euclidean distance between the two.
 * Explanation on how the distance is calculated:
 *
 * Partition the plane into 9 segments (as in tic-tac-toe):
 *
 * 1 | 2 | 3
 *
 * --+---+--
 *
 * 4 | 5 | 6
 *
 * --+---+--
 *
 * 7 | 8 | 9
 *
 * Now 5 correlates to b2.
 *
 * Using the other segments we can figure out the distance from b1 to b2:
 *
 * 1,3,7,9: calculate euclidean distance to nearest corner of 5
 *
 * 2,8: only take y-coordinate into consideration for calculating the distance
 *
 * 4,6: only take x-coordinate into consideration for calculating the distance
 *
 * @param bounds1 The first bounds/point to calculate the distance for.
 * @param bounds2 The second bounds/point to calculate the distance for.
 * @returns The distance between the two bounds.
 */
export declare function distanceBetweenBounds(bounds1: Bounds | Point, bounds2: Bounds | Point): number;
/**
 * Returns the intersection between the line spanning from `p1` to `p2` and `bounds`.
 * @param p1 The start of the line.
 * @param p2 The end of the line.
 * @param bounds The bounds.
 * @returns The intersection between the line and bounds or `undefined` if there is none.
 */
export declare function getIntersection(p1: Point, p2: Point, bounds: Bounds): Point | undefined;
/**
 * Updates a VNode's transform attribute.
 * @param vnode The VNode.
 * @param transform The TransformAttributes.
 * @param baseDiv The base div ID of the root node, from the viewerOptions.
 */
export declare function updateTransform(vnode: VNode, transform: TransformAttributes, baseDiv: string): void;
/**
 * Updates a VNode's opacity.
 * @param vnode The VNode.
 * @param opacity The new opacity.
 * @param baseDiv The base div ID of the root node, from the viewerOptions.
 */
export declare function updateOpacity(vnode: VNode, opacity: number, baseDiv: string): void;
/**
 * Updates a VNode's pointer-events to make it click-through.
 * @param vnode The VNode.
 * @param clickThrough Whether the VNode should be click-through.
 * @param baseDiv The base div ID of the root node, from the viewerOptions.
 */
export declare function updateClickThrough(vnode: VNode, clickThrough: boolean, baseDiv: string): void;
/**
 * Checks if `item` is contained in any (nested) group, e.g. if `item` is contained in a flattened version of `groups`.
 * @returns `true` if `item` is contained in any (nested) group.
 * @example anyContains([[0, 1], [1, 2]], 2) === true
 */
export declare function anyContains<T>(groups: T[][], item: T): boolean;
/**
 * Join groups containing at least 1 same element. Transitive joining applies:
 * @example joinTransitiveGroups([[0, 1], [1, 2], [2, 3]]) === [[0, 1, 2, 3]]
 */
export declare function joinTransitiveGroups<T>(groups: T[][]): T[][];
/**
 * Checks if `node` has an incoming edge to at least one of the other given `nodes`.
 * @returns `true` if `node` has an incoming edge to at least one of the other given `nodes`.
 */
export declare function isIncomingToAny(node: SKNode, nodes: SKNode[]): boolean;
/**
 * Checks if `node` has an outgoing edge to at least one of the other given `nodes`.
 * @returns `true` if `node` has an outgoing edge to at least one of the other given `nodes`.
 */
export declare function isOutgoingToAny(node: SKNode, nodes: SKNode[]): boolean;
/**
 * Checks if `node` is connected to at least one of the other given `nodes`.
 * @returns `true` if `node` is connected to at least one of the other given `nodes`.
 */
export declare function isConnectedToAny(node: SKNode, nodes: SKNode[]): boolean;
/** Checks if `node` is selected or connected to any selected element. */
export declare function isSelectedOrConnectedToSelected(node: SKNode): boolean;
/** Util class for easily accessing the currently selected elements. */
export declare class SelectedElementsUtil {
    /** The model index for looking up elements. */
    private static index?;
    /** The currently selected elements. */
    private static selectedElements;
    /** Cache of {@link selectedElements} containing only selected nodes. */
    private static nodeCache?;
    /** Cache of {@link selectedElements} containing only selected edges. */
    private static edgeCache?;
    /** Cache of {@link selectedElements} containing only selected labels. */
    private static labelCache?;
    /** Cache of {@link selectedElements} containing only selected ports. */
    private static portCache?;
    /**
     * Clears all caches for stored element types.
     */
    private static clearCaches;
    /**
     * Recalculates the selected elements.
     */
    static recalculateSelection(): void;
    /** Checks if the current index is reset. */
    static isReset(): boolean;
    /** Resets the current index elements. */
    static resetModel(): void;
    /** Sets the current root. */
    static setRoot(root: SModelRootImpl): void;
    /** Returns the currently selected elements. */
    static getSelectedElements(): SKGraphElement[];
    /** Returns whether there are any currently selected elements. */
    static areElementsSelected(): boolean;
    /** Returns the currently selected nodes. */
    static getSelectedNodes(): SKNode[];
    /** Returns whether there are any currently selected nodes. */
    static areNodesSelected(): boolean;
    /** Returns the currently selected edges. */
    static getSelectedEdges(): SKEdge[];
    /** Returns whether there are any currently selected edges. */
    static areEdgesSelected(): boolean;
    /** Returns the currently selected labels. */
    static getSelectedLabels(): SKLabel[];
    /** Returns whether there are any currently selected labels. */
    static areLabelsSelected(): boolean;
    /** Returns the currently selected ports. */
    static getSelectedPorts(): SKPort[];
    /** Returns whether there are any currently selected ports. */
    static arePortsSelected(): boolean;
}
/** Handles all actions regarding the {@link SelectedElementsUtil}. */
export declare class SelectedElementsUtilActionHandler implements IActionHandler, IActionHandlerInitializer {
    handle(action: Action): void | Action | ICommand;
    initialize(registry: ActionHandlerRegistry): void;
}
//# sourceMappingURL=proxy-view-util.d.ts.map